diff --git a/cli/README.md b/cli/README.md index 0e39db20e..db3d3b72b 100644 --- a/cli/README.md +++ b/cli/README.md @@ -1,13 +1,13 @@ -# @dhis2/cli-app +# @dhis2/cli-app-scripts Single-dependency build, start, and test scripts for the DHIS2 App Platform See [platform.dhis2.nu](https://platform.dhis2.nu) for complete documentation. ```sh -> yarn add --dev @dhis2/cli-app +> yarn add --dev @dhis2/cli-app-scripts # OR -> npm install --save-dev @dhis2/cli-app +> npm install --save-dev @dhis2/cli-app-scripts ``` diff --git a/cli/bin/d2-app b/cli/bin/d2-app-scripts similarity index 100% rename from cli/bin/d2-app rename to cli/bin/d2-app-scripts diff --git a/cli/config/d2.config.app.js b/cli/config/d2.config.app.js new file mode 100644 index 000000000..4806d1280 --- /dev/null +++ b/cli/config/d2.config.app.js @@ -0,0 +1,9 @@ +const config = { + type: 'app', + + entryPoints: { + app: './src/App', + }, +} + +module.exports = config diff --git a/cli/config/d2.config.js b/cli/config/d2.config.js deleted file mode 100644 index fb38b6118..000000000 --- a/cli/config/d2.config.js +++ /dev/null @@ -1,15 +0,0 @@ -const defaultD2Config = { - type: 'app', - - entryPoints: { - // (UNIMPLEMENTED) - // app: { - // source: './src/App', - // }, - // plugin: { - // source: './src/Plugin' - // } - }, -} - -module.exports = defaultD2Config diff --git a/cli/config/d2.config.lib.js b/cli/config/d2.config.lib.js new file mode 100644 index 000000000..1412b0279 --- /dev/null +++ b/cli/config/d2.config.lib.js @@ -0,0 +1,9 @@ +const config = { + type: 'lib', + + entryPoints: { + lib: './src/index', + }, +} + +module.exports = config diff --git a/cli/config/init.package.json b/cli/config/init.package.json new file mode 100644 index 000000000..dcd6ced6c --- /dev/null +++ b/cli/config/init.package.json @@ -0,0 +1,7 @@ +{ + "name": "", + "version": "1.0.0", + "description": "", + "license": "BSD-3-Clause", + "private": true +} diff --git a/cli/package.json b/cli/package.json index 19397b836..234621799 100644 --- a/cli/package.json +++ b/cli/package.json @@ -1,5 +1,5 @@ { - "name": "@dhis2/cli-app", + "name": "@dhis2/cli-app-scripts", "version": "0.9.1", "main": "src/index.js", "repository": "https://github.com/amcgee/dhis2-app-platform", @@ -35,7 +35,7 @@ "styled-jsx": "^3.2.1" }, "bin": { - "d2-app": "./bin/d2-app" + "d2-app-scripts": "./bin/d2-app-scripts" }, "scripts": { "copy:shell": "mkdir -p assets && rm -rf assets/shell && cp -rf ../shell assets/shell && rm -rf assets/shell/node_modules", diff --git a/cli/src/commands/init.js b/cli/src/commands/init.js new file mode 100644 index 000000000..6ac42988a --- /dev/null +++ b/cli/src/commands/init.js @@ -0,0 +1,174 @@ +const { reporter, exec } = require('@dhis2/cli-helpers-engine') +const path = require('path') +const fs = require('fs-extra') +const chalk = require('chalk') + +const makePaths = require('../lib/paths') + +const handler = async ({ force, name, title, cwd, lib }) => { + const paths = makePaths(cwd) + + if (fs.existsSync(paths.config) && !force) { + reporter.warn( + 'A config file already exists, use --force to overwrite it' + ) + } else { + reporter.info('Importing d2.config.js defaults') + fs.copyFileSync( + lib ? paths.configDefaultsLib : paths.configDefaultsApp, + paths.config + ) + } + + if (!fs.existsSync(paths.package)) { + reporter.info('No package.json found, creating one...') + // await exec({ + // cmd: 'yarn', + // args: [ + // 'init' + // ], + // cwd: target || cwd, + // stdio: 'inherit', + // pipe: true + // }) + + const pkg = require(path.join( + __dirname, + '../../config/init.package.json' + )) + pkg.name = name + fs.writeJSONSync(paths.package, pkg, { + spaces: 2, + }) + + // await exec({ + // cmd: 'yarn', + // args: [ + // 'install', + // '--pnp' // Let's be FANCY! + // ], + // cwd: paths.base + // }) + } + + reporter.info('Creating package scripts...') + const pkg = require(paths.package) + if (pkg.scripts && pkg.scripts.build && !force) { + reporter.warn( + 'A script called "build" already exists, use --force to overwrite it' + ) + } else { + pkg.scripts = pkg.scripts || {} + pkg.scripts.build = 'yarn run d2-app-scripts build' + } + + if (pkg.scripts && pkg.scripts.start && !force) { + reporter.warn( + 'A script called "start" already exists, use --force to overwrite it' + ) + } else { + pkg.scripts = pkg.scripts || {} + pkg.scripts.start = 'yarn run d2-app-scripts start' + } + + if (pkg.scripts && pkg.scripts.test && !force) { + reporter.warn( + 'A script called "test" already exists, use --force to overwrite it' + ) + } else { + pkg.scripts = pkg.scripts || {} + pkg.scripts.test = 'yarn run d2-app-scripts test' + } + + fs.writeJSONSync(paths.package, pkg, { + spaces: 2, + }) + + if ( + !force && + ((pkg.devDependencies && + Object.keys(pkg.devDependencies).includes( + '@dhis2/cli-app-scripts' + )) || + (pkg.dependencies && + Object.keys(pkg.dependencies).includes( + '@dhis2/cli-app-scripts' + ))) + ) { + reporter.warn( + 'A version of `@dhis2/cli-app-scripts` is already listed as a dependency, use --force to overwrite it' + ) + } else { + reporter.info('Installing @dhis2/cli-app-scripts...') + await exec({ + cmd: 'yarn', + args: ['add', '--dev', '@dhis2/cli-app-scripts'], + cwd: paths.base, + }) + } + + if ( + !force && + ((pkg.dependencies && + Object.keys(pkg.dependencies).includes('@dhis2/app-runtime')) || + (pkg.peerDependencies && + Object.keys(pkg.peerDependencies).includes( + '@dhis2/app-runtime' + ))) + ) { + reporter.warn( + 'A version of `@dhis2/app-runtime` is already listed as a dependency, use --force to overwrite it' + ) + } else { + reporter.info('Installing @dhis2/app-runtime...') + await exec({ + cmd: 'yarn', + args: ['add', '@dhis2/app-runtime'], + cwd: paths.base, + }) + } + + const entrypoint = lib ? 'src/index.js' : 'src/App.js' + + if (!force && fs.existsSync(path.join(paths.base, entrypoint))) { + reporter.warn( + `An entrypoint file at ${entrypoint} already exists, use --force to overwrite it` + ) + } else { + reporter.info(`Creating entrypoint ${chalk.bold(entrypoint)}`) + fs.mkdirpSync(path.join(paths.base, 'src')) + fs.writeFileSync( + path.join(paths.base, entrypoint), + "export default () => 'Welcome to DHIS2!'" + ) + } + + reporter.print('') + reporter.info('SUCCESS!') + reporter.print('Run `yarn start` to launch your new DHIS2 application') +} + +const command = { + command: 'init ', + desc: 'Setup an app ', + builder: { + force: { + description: 'Overwrite existing files and configurations', + type: 'boolean', + default: false, + }, + lib: { + description: 'Create a library', + type: 'boolean', + default: false, + }, + title: { + description: + 'The human-readable title of the application or library', + type: 'string', + }, + }, + handler, +} + +module.exports = command diff --git a/cli/src/index.js b/cli/src/index.js index e3a18ca8f..ec4024996 100644 --- a/cli/src/index.js +++ b/cli/src/index.js @@ -1,6 +1,6 @@ const { namespace } = require('@dhis2/cli-helpers-engine') -module.exports = namespace('app', { +module.exports = namespace('scripts', { desc: 'Scripts for development of DHIS2 applications', builder: yargs => { yargs.option('cwd', { diff --git a/cli/src/lib/parseConfig.js b/cli/src/lib/parseConfig.js index f53e5b77d..7a6114d1a 100644 --- a/cli/src/lib/parseConfig.js +++ b/cli/src/lib/parseConfig.js @@ -1,9 +1,8 @@ const { reporter } = require('@dhis2/cli-helpers-engine') const { defaultsDeep, has } = require('lodash') +const fs = require('fs-extra') const chalk = require('chalk') -const defaultConfig = require('../../config/d2.config') - const requiredConfigFields = { app: ['name', 'title', 'entryPoints.app'], lib: ['name', 'entryPoints.lib'], @@ -32,10 +31,29 @@ const validateConfig = config => { const parseConfig = paths => { try { - reporter.debug('Load d2 config at', paths.config) + let config = {} + // if (!fs.existsSync(paths.config)) { + // reporter.error('Config file d2.config.js not found - use the init command to create one!') + // process.exit(1) + // } + + if (fs.existsSync(paths.config)) { + reporter.debug('Loading d2 config at', paths.config) + config = require(paths.config) + reporter.debug('loaded', config) + } - let config = require(paths.config) - config = defaultsDeep(config, defaultConfig) + const type = config.type || 'app' + reporter.debug(`Type identified : ${chalk.bold(type)}`) + + const defaults = + type === 'lib' ? paths.configDefaultsLib : paths.configDefaultsApp + config = defaultsDeep(config, require(defaults)) + + if (fs.existsSync(paths.package)) { + config.name = config.name || require(paths.package).name + } + config.title = config.title || config.name validateConfig(config) diff --git a/cli/src/lib/paths.js b/cli/src/lib/paths.js index 0d3a4e6db..1002eb1bb 100644 --- a/cli/src/lib/paths.js +++ b/cli/src/lib/paths.js @@ -7,6 +7,14 @@ module.exports = makePaths = (cwd = process.cwd()) => { const base = path.resolve(cwd) const paths = { babelConfig: path.join(__dirname, '../../config/babel.config.js'), + configDefaultsApp: path.join( + __dirname, + '../../config/d2.config.app.js' + ), + configDefaultsLib: path.join( + __dirname, + '../../config/d2.config.lib.js' + ), shellSource: path.join(__dirname, '../../assets/shell'), diff --git a/examples/simple-app/package.json b/examples/simple-app/package.json index 55d2ccbd7..9aa5c0e45 100644 --- a/examples/simple-app/package.json +++ b/examples/simple-app/package.json @@ -8,12 +8,12 @@ "private": true, "dependencies": {}, "devDependencies": { - "@dhis2/cli-app": "file:../../cli" + "@dhis2/cli-app-scripts": "file:../../cli" }, "scripts": { - "start": "d2-app start", - "build": "d2-app build", - "test": "d2-app test --no-cypress" + "start": "d2-app-scripts start", + "build": "d2-app-scripts build", + "test": "d2-app-scripts test --no-cypress" }, "peerDependencies": { "@dhis2/app-runtime": "*", diff --git a/examples/simple-app/yarn.lock b/examples/simple-app/yarn.lock index 6ef1ddf98..06804452f 100644 --- a/examples/simple-app/yarn.lock +++ b/examples/simple-app/yarn.lock @@ -726,7 +726,7 @@ lodash "^4.17.11" to-fast-properties "^2.0.0" -"@dhis2/cli-app@file:../../cli": +"@dhis2/cli-app-scripts@file:../../cli": version "0.9.1" dependencies: "@babel/core" "^7.3.3" @@ -737,7 +737,7 @@ "@babel/preset-typescript" "^7.3.3" "@dhis2/cli-helpers-engine" "^1.4.0" chalk "^2.4.2" - fs-extra "^7.0.1" + fs-extra "^8.1.0" gaze "^1.1.3" handlebars "^4.1.2" i18next-conv "^9" @@ -1489,16 +1489,7 @@ form-data@~2.3.2: combined-stream "^1.0.6" mime-types "^2.1.12" -fs-extra@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" - integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== - dependencies: - graceful-fs "^4.1.2" - jsonfile "^4.0.0" - universalify "^0.1.0" - -fs-extra@^8.0.1: +fs-extra@^8.0.1, fs-extra@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==