diff --git a/create-block.js b/create-block.js index 6586c60..55a9163 100644 --- a/create-block.js +++ b/create-block.js @@ -2,53 +2,59 @@ import {Command} from 'commander'; import path from 'path'; import fetch from "node-fetch"; import fs from "fs"; -import http from "https"; +import http from "http"; +import https from "https"; import unzipper from "unzipper"; import {createTechnicalFiles, defaultGitRepo} from "./generators/block/index.js"; import {fileURLToPath} from 'url'; +import config from 'config'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); +const isDev = process.env.NODE_ENV === 'development' || (config.has('isDev') && config.get('isDev')); // Check README file in case you get "missing files" error. +const blocksRegistry = isDev ? 'http://localhost:3020' : 'https://'; +const blocksDirectory = isDev ? 'blocks/' : ''; -init(); +const blockName = await init(); +console.log(`🎉 Done! \n\nCheck the "${blocksDirectory}${blockName}" directory. \n`); -function init() { +async function init() { const program = new Command(); program .name('create-block') .description('AXE-WEB Platform Blocks'); - program.command('pull') - .argument('', 'Provide a full name of required block, for example: @axe-web/hero-block') - .action(async (blockName, options) => { - console.log('Block to download:', blockName) + const promise = new Promise(resolve => { + program.command('pull') + .argument('', 'Provide a full name of required block, for example: @axe-web/hero-block') + .action(async (blockName, options) => { + console.log('📦 Block to download:', blockName) - await getBlockSourceFiles(blockName); - - - }); + await getBlockSourceFiles(blockName); + resolve(blockName); + }); + }); program.parse(); + return promise; } async function getBlockSourceFiles(blockName) { - const blocksRegistry = 'http://localhost:3020'; - const queryString = new URLSearchParams(); queryString.append('blockName', blockName); + queryString.append('includeDevConfig', 'true'); const response = await fetch(`${blocksRegistry}?${queryString.toString()}`); const responseData = await response.json(); - if (!responseData) { + if (!responseData || !responseData.name) { return; } - const zipFile = await downloadFile(responseData.downloadUrl, responseData.name); - - const file = await fs.createReadStream(zipFile) - .pipe(unzipper.Extract({path: `blocks/${responseData.name}/src`})) + const zipFile = await downloadFile(responseData.downloadUrl, responseData.name + '.zip'); + await fs.createReadStream(zipFile) + .pipe(unzipper.Extract({path: `${blocksDirectory}${responseData.name}/src`})) .promise(); // Remove downloaded file. @@ -59,24 +65,100 @@ async function getBlockSourceFiles(blockName) { console.log(e) } + if (responseData.statusCode && responseData.statusCode !== 200) { + console.log(responseData); + console.log("⚠️ [ERROR]", responseData.message || "Server side error."); + return; + } + await createTechnicalFiles({ + title: responseData.title, name: responseData.name, blockFilename: responseData.name, - devToolSource: defaultGitRepo + blockGroupName: responseData.project, + version: responseData.version, + devToolSource: defaultGitRepo, }, __dirname); + + if (responseData.config.design_files) { + await downloadDesignFiles(responseData.name, responseData.config.design_files); + } + + await createDataFiles(responseData.name, responseData.config.data_sources); + + await createConfigFile(responseData.name, responseData.config); +} + +async function createConfigFile(blockName, config = {}) { + const obj = { + blockName, + baseView: config.baseView, + remToPx: config.remToPx, + }; + + const cssAssets = config.assets.filter(item => item.type === 'css').map(item => item.url); + if (cssAssets.length) { + obj.cssUrl = cssAssets; + } + + const jsAssets = config.assets.filter(item => item.type === 'js').map(item => item.url); + if (jsAssets.length) { + obj.jsUrl = jsAssets; + } + + await setupPath(`${blocksDirectory}${blockName}/config`); + await fs.promises.writeFile(`${blocksDirectory}${blockName}/config/default.json`, JSON.stringify(obj, null, 2)); } -async function downloadFile(url, blockName) { - const file = fs.createWriteStream(blockName + '.zip'); +async function downloadDesignFiles(blockName = '', files) { + for (let url of files) { + const fileName = url.split('/').pop(); + await setupPath(`${blocksDirectory}${blockName}/design`); + await downloadFile(url, `${blocksDirectory}${blockName}/design/${fileName}`) + } +} + +async function createDataFiles(blockName, dataSources = []) { + for (let source of dataSources) { + await setupPath(`${blocksDirectory}${blockName}/data`); + + await fs.promises.writeFile(`${blocksDirectory}${blockName}/data/${source.name}.json`, JSON.stringify(source.data, null, 2)); + + if (typeof source.preview_images !== 'undefined' && source.preview_images.length) { + for (let preview_image of source.preview_images) { + await downloadFile(preview_image.url, `${blocksDirectory}${blockName}/design/${source.name}-${preview_image.width}.${preview_image.extension}`) + } + } + } +} + +// +// Helpers +// + +async function setupPath(path) { + if (!fs.existsSync(path)) { + await fs.promises.mkdir(path); + } +} + +async function downloadFile(url, fileName) { + const file = fs.createWriteStream(fileName); return new Promise((resolve, reject) => { - const request = http.get(url, function (response) { + const protocol = url.startsWith('https://') ? https : http; + protocol.get(url, function (response) { response.pipe(file); + // Loading Indicator. + const loadingInterval = setInterval(() => console.log('🕐 Download in progress...'), 3000); + // after download completed close filestream file.on("finish", () => { + clearInterval(loadingInterval); + file.close(); - resolve(`./${blockName}.zip`); + resolve(fileName); }); }); }) diff --git a/generators/block/index.js b/generators/block/index.js index 3695f85..556d7df 100644 --- a/generators/block/index.js +++ b/generators/block/index.js @@ -71,6 +71,7 @@ export default class extends Generator { const group = capitalize(this.data.group); const data = Object.assign(this.data, { title, + version: '1.0.0', blockFilename: title.toLowerCase().replace(/ /ig, '-'), blockGroupName: group.toLowerCase().replace(/ /ig, '-'), blockClassName: title.toLowerCase().replace(/ /ig, '_'), @@ -78,12 +79,6 @@ export default class extends Generator { const pathDist = path.join(baseDir, 'blocks', data.blockFilename); - this.fs.copyTpl( - this.templatePath('block.json'), - this.destinationPath(path.join(pathDist, 'block.json')), - data - ); - this.fs.copyTpl( this.templatePath('config/default.cjs'), this.destinationPath(path.join(pathDist, 'config', 'default.cjs')), @@ -144,7 +139,7 @@ export async function createTechnicalFiles(data, baseDir) { const store = memFs.create(); const filesystem = editor.create(store); - const files = ['package.json', 'README.md', '.editorconfig', '.gitignore']; + const files = ['package.json', 'README.md', '.editorconfig', '.gitignore', 'block.json']; for (let file of files) { await filesystem.copyTplAsync( diff --git a/generators/block/templates/block.json b/generators/block/templates/block.json index 5adaaad..9f2eed1 100644 --- a/generators/block/templates/block.json +++ b/generators/block/templates/block.json @@ -1,6 +1,6 @@ { "name": "<%= blockGroupName %>/<%= blockFilename %>", - "version": "1.0.0", + "version": "<%= version %>", "title": "<%= title %>", "categories": [], "icon": "shortcode", diff --git a/layouts/partials/head.hbs b/layouts/partials/head.hbs index 9382c94..8f2e892 100644 --- a/layouts/partials/head.hbs +++ b/layouts/partials/head.hbs @@ -3,9 +3,10 @@ {{#if config.cssUrl }} - - {{/if}} - {{# if config.blockName}} + {{#each config.cssUrl }} + + {{/each}} + {{/if}}{{# if config.blockName}} {{/if}} diff --git a/layouts/partials/scripts.hbs b/layouts/partials/scripts.hbs index 7991cb1..5349648 100644 --- a/layouts/partials/scripts.hbs +++ b/layouts/partials/scripts.hbs @@ -1,4 +1,8 @@ {{#if config.jsUrl }} -{{/if}}{{#if config.blockName }} -{{/if}} +{{#each config.jsUrl }} +{{/each}} +{{/if}} +{{#if config.blockName }} + +{{/if}} diff --git a/server.js b/server.js index 7a0cb6e..436895b 100755 --- a/server.js +++ b/server.js @@ -25,6 +25,7 @@ import archiver from 'archiver'; */ const isDev = process.env.NODE_ENV === 'development' || (config.has('isDev') && config.get('isDev')); // Check README file in case you get "missing files" error. +const blocksRegistry = isDev ? 'http://localhost:3020' : ''; const modulePath = isDev ? '' : 'node_modules/create-block-dev-tool/'; const projectDir = modulePath; @@ -95,8 +96,6 @@ app.get('/view/:baseView', async (req, res) => { }); app.get('/publish', async (req, res) => { - - const blocksRegistry = 'http://localhost:3020'; const data = await readJSONFile('./block.json'); const response = await fetch(`${blocksRegistry}`, { @@ -108,10 +107,10 @@ app.get('/publish', async (req, res) => { const responseData = await response.json(); if (responseData.statusCode !== 200) { + console.log(responseData); res.json({success: false, message: 'Error on registry level.'}); return; } - console.log(responseData) if (responseData.uploadUrl) { await zipProject(); @@ -124,6 +123,8 @@ app.get('/publish', async (req, res) => { } res.json({success: true}); + + await fs.unlink('./dist.zip'); }); app.use(express.static('src')); @@ -227,7 +228,7 @@ async function readJSONFile(jsonFile) { } async function getBlockConfigs(jsonFileName = 'default') { - let data = readJSONFile(`./data/${jsonFileName}.json`); + let data = await readJSONFile(`./data/${jsonFileName}.json`); if (data.error) { return data; } @@ -243,6 +244,8 @@ async function getBlockConfigs(jsonFileName = 'default') { }) }); + console.log(data) + return data; } @@ -255,7 +258,7 @@ function getErrorHtml(message = '', errorMessage = '') { async function zipProject() { // create a file to stream archive data to. - const output = await fsExtra.createWriteStream(projectDir + 'dist.zip'); + const output = await fsExtra.createWriteStream('dist.zip'); const archive = archiver('zip', {}); // listen for all archive data to be written