From b5de1aeb54533c4991f4ba094fd3489e5a0f7ca5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?w=C7=92=5Fis=E7=A5=9E=E4=BB=99?= Date: Thu, 30 Aug 2018 23:03:26 +0800 Subject: [PATCH] feat: Remove biz-app logic and add subapp config in package.json (#9) * feat: Update config * feat: Remove biz-app logic * feat: Change `apfe init` to `apfe create` * feat: Remove `apfe pack init` and `apfe pack build` * feat: Adjust offline-package config into package.json ` "subapp": { "id": "hello-world", "includes": [ "./dist/**/*" ], "ignores": [ "./dist/**/*.md", "./dist/**/*.map" ] }, ` * feat: Cleanup `84` in dir path --- .eslintrc.js | 5 - .npmignore | 3 + LICENSE | 2 +- README.md | 6 +- package.json | 105 +++-- src/bin/apfe-bizapp-compose.js | 99 ----- src/bin/apfe-bizapp-create.js | 69 ---- src/bin/apfe-bizapp.js | 11 - src/bin/{apfe-init.js => apfe-create.js} | 28 +- src/bin/apfe-pack-build.js | 321 --------------- src/bin/apfe-pack-init.js | 108 ----- src/bin/apfe-pack-pack.js | 266 ++++++------- src/bin/apfe-pack.js | 6 +- src/bin/apfe-update.js | 16 +- src/bin/apfe.js | 34 +- src/index.js | 7 - src/lib/ask.js | 18 +- src/lib/check-version.js | 2 +- src/lib/compose-apps/index.js | 32 -- src/lib/compose-apps/plugin-factory.js | 93 ----- src/lib/compose-apps/plugins/assets.js | 222 ----------- src/lib/compose-apps/plugins/i18n.js | 125 ------ src/lib/compose-apps/plugins/router.js | 326 --------------- src/lib/compose-apps/plugins/spm.js | 56 --- src/lib/compose-apps/plugins/store.js | 113 ------ src/lib/compose-apps/plugins/styles.js | 125 ------ src/lib/compose-apps/read-src.js | 82 ---- src/lib/compose-apps/utils.js | 376 ------------------ src/lib/exists.js | 14 + src/lib/generate.js | 62 +-- src/lib/sign.js | 7 +- src/lib/util.js | 29 +- src/vendor/hook.js | 13 +- .../build/config/compose-biz-apps.js | 8 - .../build/scripts/.gitkeep | 0 .../build/util/.gitkeep | 0 .../build/webpack/.gitkeep | 0 .../src/assets/icons/AlipayPlus_Logo.svg | 29 -- .../src/assets/icons/account.svg | 1 - .../biz-apps/autodebit/assets/icons/aplus.svg | 1 - .../src/biz-apps/autodebit/constants/apis.js | 5 - .../autodebit/constants/mutation-types.js | 1 - .../src/biz-apps/autodebit/constants/pages.js | 3 - .../biz-apps/autodebit/i18n/locales/en_US.js | 8 - .../biz-apps/autodebit/i18n/locales/zh_CN.js | 8 - .../src/biz-apps/autodebit/libs/index.js | 0 .../src/biz-apps/autodebit/router/index.js | 27 -- .../src/biz-apps/autodebit/store/index.js | 19 - .../src/biz-apps/autodebit/styles/index.less | 21 - .../src/biz-apps/autodebit/views/detail.vue | 50 --- .../src/biz-apps/autodebit/views/index.vue | 78 ---- .../src/biz-apps/autodebit/views/list.vue | 50 --- .../cashier/assets/icons/creditcard.svg | 1 - .../src/biz-apps/cashier/constants/apis.js | 2 - .../cashier/constants/mutation-types.js | 1 - .../src/biz-apps/cashier/constants/pages.js | 1 - .../biz-apps/cashier/i18n/locales/en_US.js | 5 - .../biz-apps/cashier/i18n/locales/zh_CN.js | 5 - .../src/biz-apps/cashier/libs/index.js | 0 .../src/biz-apps/cashier/router/index.js | 12 - .../src/biz-apps/cashier/store/index.js | 19 - .../src/biz-apps/cashier/styles/index.less | 10 - .../src/biz-apps/cashier/views/index.vue | 32 -- .../src/components/icon.vue | 40 -- .../src/components/index.js | 5 - .../src/components/typer.vue | 86 ---- .../src/constants/apis.js | 1 - .../src/constants/errors.js | 7 - .../src/constants/index.js | 5 - .../src/constants/mutation-types.js | 8 - .../src/constants/pages.js | 3 - .../src/ejs-templates/.gitkeep | 0 .../src/entry/index.js | 18 - .../A-Plus-standard-project/src/i18n/index.js | 31 -- .../src/i18n/locales/en_US.js | 7 - .../src/i18n/locales/zh_CN.js | 7 - .../src/libs/vue-init.js | 38 -- .../src/router/index.js | 46 --- .../src/store/index.js | 11 - .../src/styles/components/typer.less | 27 -- .../src/styles/index.less | 22 - .../src/utils/load-icons.js | 7 - .../src/views/index.vue | 14 - test/scripts/test-bizapp-compose.js | 92 ----- 84 files changed, 278 insertions(+), 3375 deletions(-) delete mode 100755 src/bin/apfe-bizapp-compose.js delete mode 100755 src/bin/apfe-bizapp-create.js delete mode 100755 src/bin/apfe-bizapp.js rename src/bin/{apfe-init.js => apfe-create.js} (81%) delete mode 100755 src/bin/apfe-pack-build.js delete mode 100755 src/bin/apfe-pack-init.js delete mode 100644 src/index.js delete mode 100644 src/lib/compose-apps/index.js delete mode 100644 src/lib/compose-apps/plugin-factory.js delete mode 100644 src/lib/compose-apps/plugins/assets.js delete mode 100644 src/lib/compose-apps/plugins/i18n.js delete mode 100644 src/lib/compose-apps/plugins/router.js delete mode 100644 src/lib/compose-apps/plugins/spm.js delete mode 100644 src/lib/compose-apps/plugins/store.js delete mode 100644 src/lib/compose-apps/plugins/styles.js delete mode 100644 src/lib/compose-apps/read-src.js delete mode 100644 src/lib/compose-apps/utils.js create mode 100644 src/lib/exists.js delete mode 100644 test/fixtures/A-Plus-standard-project/build/config/compose-biz-apps.js delete mode 100644 test/fixtures/A-Plus-standard-project/build/scripts/.gitkeep delete mode 100644 test/fixtures/A-Plus-standard-project/build/util/.gitkeep delete mode 100644 test/fixtures/A-Plus-standard-project/build/webpack/.gitkeep delete mode 100644 test/fixtures/A-Plus-standard-project/src/assets/icons/AlipayPlus_Logo.svg delete mode 100644 test/fixtures/A-Plus-standard-project/src/assets/icons/account.svg delete mode 100644 test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/assets/icons/aplus.svg delete mode 100644 test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/constants/apis.js delete mode 100644 test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/constants/mutation-types.js delete mode 100644 test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/constants/pages.js delete mode 100644 test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/i18n/locales/en_US.js delete mode 100644 test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/i18n/locales/zh_CN.js delete mode 100644 test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/libs/index.js delete mode 100644 test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/router/index.js delete mode 100644 test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/store/index.js delete mode 100644 test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/styles/index.less delete mode 100644 test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/views/detail.vue delete mode 100644 test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/views/index.vue delete mode 100644 test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/views/list.vue delete mode 100644 test/fixtures/A-Plus-standard-project/src/biz-apps/cashier/assets/icons/creditcard.svg delete mode 100644 test/fixtures/A-Plus-standard-project/src/biz-apps/cashier/constants/apis.js delete mode 100644 test/fixtures/A-Plus-standard-project/src/biz-apps/cashier/constants/mutation-types.js delete mode 100644 test/fixtures/A-Plus-standard-project/src/biz-apps/cashier/constants/pages.js delete mode 100644 test/fixtures/A-Plus-standard-project/src/biz-apps/cashier/i18n/locales/en_US.js delete mode 100644 test/fixtures/A-Plus-standard-project/src/biz-apps/cashier/i18n/locales/zh_CN.js delete mode 100644 test/fixtures/A-Plus-standard-project/src/biz-apps/cashier/libs/index.js delete mode 100644 test/fixtures/A-Plus-standard-project/src/biz-apps/cashier/router/index.js delete mode 100644 test/fixtures/A-Plus-standard-project/src/biz-apps/cashier/store/index.js delete mode 100644 test/fixtures/A-Plus-standard-project/src/biz-apps/cashier/styles/index.less delete mode 100644 test/fixtures/A-Plus-standard-project/src/biz-apps/cashier/views/index.vue delete mode 100644 test/fixtures/A-Plus-standard-project/src/components/icon.vue delete mode 100644 test/fixtures/A-Plus-standard-project/src/components/index.js delete mode 100644 test/fixtures/A-Plus-standard-project/src/components/typer.vue delete mode 100644 test/fixtures/A-Plus-standard-project/src/constants/apis.js delete mode 100644 test/fixtures/A-Plus-standard-project/src/constants/errors.js delete mode 100644 test/fixtures/A-Plus-standard-project/src/constants/index.js delete mode 100644 test/fixtures/A-Plus-standard-project/src/constants/mutation-types.js delete mode 100644 test/fixtures/A-Plus-standard-project/src/constants/pages.js delete mode 100644 test/fixtures/A-Plus-standard-project/src/ejs-templates/.gitkeep delete mode 100644 test/fixtures/A-Plus-standard-project/src/entry/index.js delete mode 100644 test/fixtures/A-Plus-standard-project/src/i18n/index.js delete mode 100644 test/fixtures/A-Plus-standard-project/src/i18n/locales/en_US.js delete mode 100644 test/fixtures/A-Plus-standard-project/src/i18n/locales/zh_CN.js delete mode 100644 test/fixtures/A-Plus-standard-project/src/libs/vue-init.js delete mode 100644 test/fixtures/A-Plus-standard-project/src/router/index.js delete mode 100644 test/fixtures/A-Plus-standard-project/src/store/index.js delete mode 100644 test/fixtures/A-Plus-standard-project/src/styles/components/typer.less delete mode 100644 test/fixtures/A-Plus-standard-project/src/styles/index.less delete mode 100644 test/fixtures/A-Plus-standard-project/src/utils/load-icons.js delete mode 100644 test/fixtures/A-Plus-standard-project/src/views/index.vue delete mode 100644 test/scripts/test-bizapp-compose.js diff --git a/.eslintrc.js b/.eslintrc.js index 02f2aa1..c10e310 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,13 +1,8 @@ -'use strict' - module.exports = { extends: 'eslint-config-antife', env: { node: true, es6: true, mocha: true - }, - rules: { - 'max-len': 0 } } diff --git a/.npmignore b/.npmignore index 7807993..e97b893 100644 --- a/.npmignore +++ b/.npmignore @@ -5,6 +5,9 @@ coverage/ .babelrc .eslintrc.js .eslintignore +.travis.yml +entrypoint.sh +Dockerfile .idea .code *.sw* diff --git a/LICENSE b/LICENSE index 3eddbd6..3b24011 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT LICENSE -Copyright (c) 2017 Alibaba Group Holding Limited and other contributors. +Copyright (c) 2018 Alibaba Group Holding Limited and other contributors. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/README.md b/README.md index 7349277..72df86c 100644 --- a/README.md +++ b/README.md @@ -34,11 +34,11 @@ $ apfe -h ## Contributors -|[
xiekw2010](https://github.com/xiekw2010)
|[
xudafeng](https://github.com/xudafeng)
|[
elrrrrrrr](https://github.com/elrrrrrrr)
-| :---: | :---: | :---: | +|[
xudafeng](https://github.com/xudafeng)
|[
xiekw2010](https://github.com/xiekw2010)
|[
elrrrrrrr](https://github.com/elrrrrrrr)
|[
jsw0528](https://github.com/jsw0528)
+| :---: | :---: | :---: | :---: | -This project follows the git-contributor [spec](https://github.com/xudafeng/git-contributor), auto upated at `Thu Apr 26 2018 15:27:57 GMT+0800`. +This project follows the git-contributor [spec](https://github.com/xudafeng/git-contributor), auto upated at `Thu Aug 30 2018 20:28:11 GMT+0800`. diff --git a/package.json b/package.json index 0d1548e..f1c5f93 100644 --- a/package.json +++ b/package.json @@ -1,18 +1,12 @@ { "name": "apfe-cli", "version": "1.1.1", - "description": "Alipay+ Sub-app ToolKit", + "description": "Alipay+ Subapp ToolKit", "keywords": [ - "Alipay+", "ToolKit", "CLI", "FrontEnd" ], - "contributors": [ - "xiekw2010 ", - "brucejcw ", - "elrrrrrrr " - ], "repository": { "type": "git", "url": "https://github.com/ant-ife/apfe-cli.git" @@ -24,75 +18,80 @@ "bin": { "apfe": "dist/bin/apfe.js" }, + "scripts": { + "babel": "babel ./src --out-dir ./dist", + "babel:dev": "babel ./src -w --out-dir ./dist", + "lint": "eslint ./src --ext .js --fix", + "lint:dev": "esw ./src -w", + "dev": "npm run lint:dev & npm run babel:dev", + "build": "npm run lint && rm -rf ./dist && npm run babel", + "pub": "npm run build && npm publish", + "build:docker": "docker build . -t=apfe/apfe-build-docker", + "ci": "npm run lint", + "contributor": "git-contributor" + }, + "husky": { + "hooks": { + "pre-commit": "npm run lint" + } + }, "dependencies": { "babel-code-frame": "^6.26.0", - "babel-core": "^6.26.0", - "babel-plugin-transform-object-rest-spread": "^6.23.0", + "babel-core": "^6.26.3", + "babel-plugin-transform-object-rest-spread": "^6.26.0", "babel-plugin-transform-regenerator": "^6.26.0", "babel-plugin-transform-runtime": "^6.23.0", "babel-preset-es2015": "^6.24.1", "babel-runtime": "^6.26.0", - "camelcase": "^4.1.0", - "commander": "^2.11.0", - "consolidate": "^0.14.5", + "camelcase": "^5.0.0", + "commander": "^2.17.1", + "consolidate": "^0.15.1", "debug": "^3.1.0", - "deepmerge": "^1.5.2", - "fs-extra": "^4.0.2", - "git-branch": "^1.0.0", + "deepmerge": "^2.1.1", + "fs-extra": "^7.0.0", + "git-branch": "^2.0.1", "git-clone": "^0.1.0", - "globby": "^6.1.0", - "gulp": "^3.8.1", - "gulp-tar": "~1.0.0", - "gulp-zip": "^0.4.0", - "handlebars": "^4.0.5", - "inquirer": "^0.12.0", + "globby": "^8.0.1", + "gulp": "^3.9.1", + "gulp-tar": "~2.1.0", + "gulp-zip": "^4.2.0", + "handlebars": "^4.0.11", + "inquirer": "^6.2.0", "ios-simulator": "^1.0.15", "map-stream": "^0.1.0", - "metalsmith": "^2.1.0", - "minimatch": "^3.0.0", + "metalsmith": "^2.3.0", + "minimatch": "^3.0.4", "multimatch": "^2.1.0", - "node-forge": "^0.7.1", - "ora": "^0.2.1", + "node-forge": "^0.7.6", + "ora": "^3.0.0", "ramda": "^0.25.0", "ramda-fantasy": "^0.8.0", "read-metadata": "^1.0.0", - "request": "^2.67.0", + "request": "^2.88.0", "rimraf": "^2.6.2", - "semver": "^5.4.1", - "shelljs": "^0.7.8", + "semver": "^5.5.1", + "shelljs": "^0.8.2", "user-home": "^2.0.0", - "validate-npm-package-name": "^2.2.2", - "win-spawn": "^2.0.0", - "xutil": "^1.0.11" + "validate-npm-package-name": "^3.0.0", + "win-spawn": "^2.0.0" }, "devDependencies": { - "babel-cli": "^6.24.1", - "babel-eslint": "^7.1.1", - "chai": "^3.5.0", + "babel-cli": "^6.26.0", + "babel-eslint": "^9.0.0", + "chai": "^4.1.2", "chai-fs": "^2.0.0", - "chalk": "^2.3.0", - "eslint": "^4.14.0", - "eslint-config-antife": "^1.0.0", - "eslint-plugin-babel": "^4.1.1", - "eslint-watch": "^3.1.2", + "chalk": "^2.4.1", + "eslint": "^5.4.0", + "eslint-config-antife": "^1.0.3", + "eslint-plugin-babel": "^5.1.0", + "eslint-watch": "^4.0.2", + "git-contributor": "^1.0.8", + "husky": "^1.0.0-rc.13", "istanbul": "^0.4.5", - "mocha": "^4.0.1" + "mocha": "^5.2.0" }, "engines": { "node": ">=8.0.0" }, - "scripts": { - "babel": "babel ./src --out-dir ./dist", - "babel:dev": "babel ./src -w --out-dir ./dist", - "lint": "eslint ./src --ext .js --fix", - "lint:dev": "esw ./src -w", - "dev": "npm run lint:dev & npm run babel:dev", - "build": "rm -rf ./dist && npm run babel", - "mocha": "istanbul cover `npm bin`/_mocha test/scripts/test-bizapp-compose.js --slow 1000", - "test": "npm run build && npm run mocha", - "pub": "npm run build && npm publish", - "build:docker": "docker build . -t=apfe/apfe-build-docker", - "ci": "npm run lint && npm run test" - }, "license": "MIT" } diff --git a/src/bin/apfe-bizapp-compose.js b/src/bin/apfe-bizapp-compose.js deleted file mode 100755 index 0017aaa..0000000 --- a/src/bin/apfe-bizapp-compose.js +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/env node - -import { Command } from 'commander' -import { remoteDoc } from '../lib/defaults' -import { composeApps, defaultOptions } from '../lib/compose-apps/index' -import { resolve, join } from 'path' -import globby from 'globby' -import { warn, log, error } from '../lib/logger' -import { existsFile } from '../lib/compose-apps/read-src' -import checkVersion from '../lib/check-version' -import chalk from 'chalk' - -const program = new Command('apfe bizapp compose') - -/** - * Help. - */ - -program.on('--help', function () { - console.log(` - ${chalk.gray('# For biz-apps architecture reference please check this doc:')} - ${remoteDoc}/project-structure/biz-apps-arch.html - - `) -}) - -/** - * Usage. - */ -program - .option('-c, --config path/to/config.js', 'default is {pwd}/build/config/compose-biz-apps.js') - .parse(process.argv) - -run().catch(error) - -/** - * 1. get config from option - * 2. if not exist, then get from default - * 3. if not exist, then compose all the biz-apps using default options - * @returns {Promise.<*>} - */ -async function run () { - try { - await checkVersion() - } catch (err) { - } - - validCwd() - - let config = {} - if (program.config) { - config = resolve(program.config) - if (!existsFile(config)) { - error(`config file ${config} is not exist, compose failed.`) - return program.help() - } - config = require(config) - } - - const cwd = process.cwd() - if (!Object.keys(config).length) { - const DEFAULT_CONFIG_PATH = 'build/config/compose-biz-apps.js' - config = await globby(DEFAULT_CONFIG_PATH) - if (config && config.length) { - config = config[0] - config = require(join(cwd, config)) - } else { - warn(`${DEFAULT_CONFIG_PATH} is not exist, default will compose all biz-apps under src`) - } - } - - let options = config.options || {} - let bizapps = config['biz-apps'] || [] - - if (!bizapps.length) { - bizapps = await globby('*', { cwd: join(cwd, 'src/biz-apps/') }) - } - - log(`composing biz-apps: ${bizapps.join(', ')}`) - options = { ...defaultOptions, ...options } - await composeApps(resolve(cwd, './src'), options, ...bizapps) -} - -function validCwd () { - const cwd = process.cwd() - const validationPaths = [ - 'build/config/index.js', - 'src/router/index.js', - 'src/store/index.js', - ] - - for (const file of validationPaths) { - const jf = join(cwd, file) - if (!existsFile(jf)) { - error("It's not a valid A+ project, composing failed...") - return program.help() - } - } -} diff --git a/src/bin/apfe-bizapp-create.js b/src/bin/apfe-bizapp-create.js deleted file mode 100755 index 124e982..0000000 --- a/src/bin/apfe-bizapp-create.js +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/env node - -import { Command } from 'commander' -import { remoteDoc, remoteGit } from '../lib/defaults' -import { join } from 'path' -import { error } from '../lib/logger' -import { generateBizApp } from '../lib/generate' -import { confirm, normalizeTemplate } from '../lib/util' -import { existsSync as exists } from 'fs' -import chalk from 'chalk' - -const program = new Command('apfe bizapp create') - -/** - * Help. - */ - -program.on('--help', function () { - console.log(` - Examples: - - ${chalk.gray('# create a top-up bizapp')} - $ apfe bizapp create top-up - - ${chalk.gray('# For biz-apps architecture reference please check this doc:')} - ${remoteDoc}/project-structure/biz-apps-arch.html - `) -}) - -/** - * Usage. - */ -program - .usage('[YOUR-BIZ-APP-NAME]') - .option('-t, --template [value]', 'using a template for creating the biz-app') - .parse(process.argv) - -const args = program.args -if (args.length !== 1) { - program.help() -} else { - run().catch(error) -} - -/** - * 1. get config from option - * 2. if not exist, then get from default - * 3. if not exist, then compose all the biz-apps using default options - * @returns {Promise.<*>} - */ -async function run () { - const cwd = process.cwd() - const name = program.args[0] - // eslint-disable-next-line - if (!/^[^\\/?%*:|"<>\.]+$/.test(name)) { - throw new Error(`${name} isn't a valid biz-app name, it suggested to be like topup, mobilecharge, cashier, etc.`) - } - const source = program.template || remoteGit - const template = await normalizeTemplate(source) - const dest = join(cwd, `/src/biz-apps/${name}`) - const next = () => generateBizApp(name, `${template}/biz-app-template`, dest).catch(error) - confirm(`Are you sure to create biz-app at ${dest}`, () => { - if (exists(dest)) { - confirm(`${dest} has already exist, are you sure to overwrite?`, next) - } else { - next() - } - }) -} diff --git a/src/bin/apfe-bizapp.js b/src/bin/apfe-bizapp.js deleted file mode 100755 index ceeca33..0000000 --- a/src/bin/apfe-bizapp.js +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env node - -import { Command } from 'commander' - -const program = new Command('apfe bizapp') - -program - .usage(' [options]') - .command('compose', 'compose the biz-apps') - .command('create [app-name]', 'create a new biz-app') - .parse(process.argv) diff --git a/src/bin/apfe-init.js b/src/bin/apfe-create.js similarity index 81% rename from src/bin/apfe-init.js rename to src/bin/apfe-create.js index ad49871..a936625 100755 --- a/src/bin/apfe-init.js +++ b/src/bin/apfe-create.js @@ -13,7 +13,7 @@ import { isLocalPath } from '../lib/local-path' import { remoteGit } from '../lib/defaults' import { normalizeTemplate } from '../lib/util' -const program = new Command('apfe init') +const program = new Command('apfe create') /** * Help. @@ -24,13 +24,13 @@ program.on('--help', function () { Examples: ${chalk.gray('# create a new project with an default template')} - $ apfe init path/to/my-project + $ apfe create path/to/my-project ${chalk.gray('# create a new project with an local path template')} - $ apfe init path/to/local-template path/to/my-project + $ apfe create path/to/local-template path/to/my-project ${chalk.gray('# create a new project straight from a git template')} - $ apfe init ${remoteGit} path/to/my-project + $ apfe create ${remoteGit} path/to/my-project `) }) @@ -82,16 +82,16 @@ process.on('exit', function () { }) if (exists(to)) { - inquirer.prompt([{ - type: 'confirm', - message: inPlace - ? 'Generate project in current directory?' - : 'Target directory exists. Continue?', - name: 'ok', - }], function (answers) { - if (answers.ok) { - run() - } + inquirer.prompt([ + { + type: 'confirm', + message: inPlace + ? 'Generate project in current directory?' + : 'Target directory exists. Continue?', + name: 'ok', + }, + ]).then(answers => { + answers.ok && run() }) } else { run() diff --git a/src/bin/apfe-pack-build.js b/src/bin/apfe-pack-build.js deleted file mode 100755 index a185d63..0000000 --- a/src/bin/apfe-pack-build.js +++ /dev/null @@ -1,321 +0,0 @@ -#!/usr/bin/env node - -import chalk from 'chalk' -import fs from 'fs-extra' -import path from 'path' -import gulp from 'gulp' -import tar from 'gulp-tar' -import zip from 'gulp-zip' -import map from 'map-stream' -import sign from '../lib/sign' -import home from 'user-home' -import globby from 'globby' -import { Command } from 'commander' - -const ROOT_PATH = process.cwd() -const PACKAGE_DIR = './_package' -const DIST_DIR = './_dist' -const DIST_PATH = path.join(ROOT_PATH, DIST_DIR) - -const HOOK_PATH = path.join(ROOT_PATH, './hook.js') - - -const program = new Command('apfe pack build') - -program - .usage('') - .parse(process.argv) - -const CONFIG_ENTRY = program.args[0] - -/** - * archiving - * archiving the offline-package - * 1. empty ./_dist - * 2. parse config-file include and ignore configuration - * 3. invoke gulp task - * - * @name archiving - * @function - * @access public - * @param {Object} packer config-file - */ -function archiving (packer, cb) { - console.log(chalk.yellow('# start apfe pack...')) - // empty dist path - if (fs.pathExistsSync(DIST_PATH)) { - fs.removeSync(DIST_PATH) - } - - let distSrc = [] - const files84 = [] - - // parse packer include files - if (packer.build && packer.build.include) { - distSrc = distSrc.concat(packer.build.include) - } - - // ignore builder files - distSrc.push( - '!' + PACKAGE_DIR, - '!' + '!' + PACKAGE_DIR + '/**' - ) - - // ignore packer.ignore configuration - if (packer.build && packer.build.ignore) { - packer.build.ignore.forEach((v) => { - distSrc.push('!' + v) - }) - } - - // define gulp entry task - gulp.task('tar', () => { - return gulp - .src(DIST_DIR + '/84/_tar/**/*') - .pipe(tar(packer.appid + '.tar')) - .pipe(gulp.dest(DIST_DIR + '/84')) - }) - - gulp.task('cert84', ['tar'], () => { - const _tarPath = DIST_PATH + '/84/_tar' - if (fs.existsSync(_tarPath)) { - fs.removeSync(_tarPath) - } - - const rtv = gulp.src(DIST_DIR + '/84/**/*') - function scanPipe (files) { - function fn (file, cb) { - !file.isDirectory() && files.push(file.relative) - } - return map(fn) - } - rtv.pipe(scanPipe(files84)) - rtv.on('end', () => { - signTar(DIST_PATH + '/84', files84, () => { - const _options = { - tar: true, - } - gulpPkg(_options, packer, cb) - }) - }) - return rtv - }) - - gulp.task('dist84', () => { - const src = gulp.src(distSrc).on('end', () => { - // build Manifest.xml - buildManifestSync(packer, DIST_PATH, true) - - setTimeout(() => { - gulp.start('cert84') - }, 500) - }) - - src.pipe( - gulp.dest((file) => { - let distDir = DIST_DIR + '/84/_tar' - if (file.base.indexOf(ROOT_PATH) > -1) { - distDir += file.base.replace(ROOT_PATH, '') - } - return distDir - }), - ) - - fs.copySync(`./${CONFIG_ENTRY}`, path.join(DIST_DIR + `/84/_tar/${CONFIG_ENTRY}`)) - }) - - gulp.start('dist84') -} - -/** - * entry - * 1. preCheck config-file exist - * 2. render build config - * 3. invoke singlePack @see singlePack - * @name entry - * @function - * @access public - */ -function entry () { - if (!fs.pathExistsSync(CONFIG_ENTRY)) { - console.log(chalk.red("Fail: Can't find config-file !\r\n")) - return - } - try { - const config = fs.readJSONSync(CONFIG_ENTRY) - singlePack(config) - } catch (e) { - console.error(e) - console.log(chalk.red('failed to pack .')) - } -} - -/** - * singlePack - * - * 1. copy src - * 2. link node_modules - * 3. compose bizapps - * 4. build assets - * 5. load hook - * 6. execute pack - * @name singlePack - * @function - * @access public - * @param {Object} config pack config - */ -function singlePack (config) { - (async () => { - try { - // 1. loading hook - let beforePack, afterPack - if (fs.pathExistsSync(HOOK_PATH)) { - const hook = require(HOOK_PATH) - afterPack = hook.afterPack - beforePack = hook.beforePack - } - - console.log(chalk.yellow('# starting beforePack')) - beforePack && beforePack({ - fse: fs, - globby, - }) - - // 2. execute pack - await new Promise(res => { - archiving(config, res) - }) - - console.log(chalk.yellow('# starting afterPack')) - afterPack && afterPack({ - fse: fs, - globby, - }) - } catch (e) { - console.error(chalk.red('# error', e)) - } - })() -} - -/** - * buildManifestSync - * generate Manifest.xml - * - * @name buildManifestSync - * @function - * @access public - * @param {Object} packer config-file config - * @param {String} manifestDir output path - */ -function buildManifestSync (packer, manifestDir) { - try { - const out = [] - out.push('') - out.push('') - out.push(' ' + packer.appid + '') - out.push(' ' + packer.name + '') - out.push(' ' + packer.version + '') - out.push('') - const outStr = out.join('\n') - fs.outputFileSync(manifestDir + '/84/Manifest.xml', outStr) - } catch (e) { - console.error(chalk.red('# write Manifest.xml error:')) - } -} - -/** - * signTar - * generate cert.json by invoking remote server - * contains 2 signatures - * 1. Manifest.xml - * 2. tar package - * - * @name signTar - * @function - * @access public - * @param {String} distPath dist path - * @param {Array} files file list - * @param {Function} cb callback - */ -function signTar (distPath, files, cb) { - const CERT_JSON = {} - const queue = files.slice(0) - let working = 0 - const threads = 2 - next() - - function next () { - const fileDir = queue.shift() - if (!fileDir) { - if (working <= 0) { - fs.writeFileSync(DIST_DIR + '/84/CERT.json', JSON.stringify(CERT_JSON, null, 2)) - cb && cb() - } - return - } - const filePath = path.join(distPath, fileDir) - - sign.doSign(filePath, (res) => { - CERT_JSON[fileDir] = res - working -= 1 - next() - }) - - if (++working < threads) { - next() - } - } -} - -/** - * gulpPkg - * build the target zip type package - * 1. zip the _dist path - * 2. generate the *.amr in ./_package - * - * @name gulpPkg - * @function - * @access public - * @param {Object} options options - * @param {Object} packer config-file - * @param {Function} cb callback - */ -function gulpPkg (options, packer, cb) { - const amrFilename = `${packer.appid}_${packer.version}.amr` - - const packageDir = PACKAGE_DIR + '/' + packer.version - const amrPath = path.join(ROOT_PATH, packageDir + '/' + amrFilename) - const srcPath = DIST_DIR + '/84/**/*' - - gulp.task('zip', () => { - return gulp - .src(srcPath) - .pipe(zip(amrFilename)) - .pipe(gulp.dest(packageDir)) - }) - gulp.task('pack', ['zip'], () => { - console.log('# packed at ' + chalk.green(amrPath)) - const pkgInfo = { - file: packageDir + '/' + amrFilename, - packer: packer, - } - cb && cb(options.all, pkgInfo) - }) - gulp.start('pack') -} - -function preCheck () { - if (!fs.existsSync(path.join(home, '.apfe/rsa-key/private.pem'))) { - console.log(` - Run the 'apfe pack setkey /path/to/private.pem'. - - If not having the private-key. - - Run the 'apfe pack genkey'. - `) - return - } - entry() -} - -preCheck() diff --git a/src/bin/apfe-pack-init.js b/src/bin/apfe-pack-init.js deleted file mode 100755 index 7e275ec..0000000 --- a/src/bin/apfe-pack-init.js +++ /dev/null @@ -1,108 +0,0 @@ -#!/usr/bin/env node - -import globby from 'globby' -import fs from 'fs-extra' -import uuid from 'uuid/v4' -import path from 'path' -import {success, error} from '../lib/logger' -import inquirer from 'inquirer' -import { Command } from 'commander' - -const program = new Command('apfe pack init') -program - .usage(' ') - .parse(process.argv) - -const CWD = process.cwd() -const BIZ_APPS_PATH = path.join(CWD, '../src/biz-apps') - -let bizApps - -const packerConfig = { - name: 'cashier', - version: '0.0.0.1', - appId: uuid(), - author: '', - description: '', - build: { - include: [ - './**/*', - ], - ignore: [ - './**/*.md', - './**/*.map', - ], - }, - 'biz-apps': [], -} - -const inputMap = { - name: 'input the offline-package name', - author: 'input the package author', - description: 'input the description', -} - -entry() - -function preCheck () { - // 1. in offline-package folder - if (!/offline-package$/.test(CWD)) { - error('please execute in the offline-package folder') - return Promise.reject() - } - - // 2. has bizApps - return globby(['*'], { - cwd: BIZ_APPS_PATH, - }).then(res => { - if (res.length) { - bizApps = res - } else { - error(`failed to find the bizApps , path ${BIZ_APPS_PATH}`) - return Promise.reject() - } - }) -} - -function _mapInputMessage (map) { - const res = Object.keys(map) - .map(name => ({ - name, - type: 'input', - message: map[name], - })) - return res.concat([{ - type: 'checkbox', - message: 'select bizApps, check/uncheck with spacebar', - name: 'biz-apps', - choices: bizApps.map(name => ({name})), - }]) -} - -function generateFile (packerConfig) { - // 1. write packer.json - const PACKER_PATH = path.join(CWD, packerConfig.name) - fs.ensureDirSync(PACKER_PATH) - fs.writeJSONSync(path.join(PACKER_PATH, 'packer.json'), packerConfig, { - spaces: 2, - }) - - // 2. copy hook.js - fs.copySync(path.join(__dirname, '../vendor/hook.js'), path.join(PACKER_PATH, 'hook.js')) -} - -async function entry () { - try { - await preCheck() - } catch (e) { return } - inquirer - .prompt(_mapInputMessage(inputMap), (res) => { - if (!packerConfig.name) { - error('invalid offline-package name') - return - } - Object.assign(packerConfig, res) - generateFile(packerConfig) - success('init offline-package success') - }) -} diff --git a/src/bin/apfe-pack-pack.js b/src/bin/apfe-pack-pack.js index a95b896..e45ed89 100755 --- a/src/bin/apfe-pack-pack.js +++ b/src/bin/apfe-pack-pack.js @@ -9,21 +9,14 @@ import zip from 'gulp-zip' import map from 'map-stream' import sign from '../lib/sign' import home from 'user-home' -import globby from 'globby' -import {execSync} from 'child_process' +// import globby from 'globby' import { Command } from 'commander' -import {composeApps} from '../lib/compose-apps' const ROOT_PATH = process.cwd() -const PACKAGE_DIR = './_package' -const DIST_DIR = './_dist' -const DIST_PATH = path.join(ROOT_PATH, DIST_DIR) -const TEMP_PATH = path.join(ROOT_PATH, '_temp') - -const PROJECT_PATH = path.join(ROOT_PATH, '../../') -// const PRE_PACK_PATH = path.join(ROOT_PATH, './prepack.js') -const HOOK_PATH = path.join(ROOT_PATH, './hook.js') - +const PACKAGE_DIR = './_packages' +const TEMP_DIR = './._temp' +const TEMP_PATH = path.join(ROOT_PATH, TEMP_DIR) +// const HOOK_PATH = path.join(ROOT_PATH, './.hook.js') const program = new Command('apfe pack') program @@ -34,206 +27,185 @@ program * archiving * archiving the offline-package * 1. empty ./_dist - * 2. parse packer.json include and ignore configuration + * 2. parse include and ignore configuration * 3. invoke gulp task * * @name archiving * @function * @access public - * @param {Object} packer packer.json + * @param {Object} subapp package.json */ -function archiving (packer, cb) { - console.log(chalk.yellow('# start apfe pack...')) +function archiving (subapp, cb) { + console.log(chalk.yellow('# packing offline-package with config below...')) + console.log(subapp) // output pkg.subapp config + // empty dist path - if (fs.pathExistsSync(DIST_PATH)) { - fs.removeSync(DIST_PATH) + if (fs.pathExistsSync(TEMP_PATH)) { + fs.removeSync(TEMP_PATH) } - let distSrc = [] - const files84 = [] + let distSrc = ['./dist/**/*'] // Defaults include all filse in dist dir + const tarFiles = [] - // parse packer include files - if (packer.build && packer.build.include) { - distSrc = distSrc.concat(packer.build.include) + // parse include files + if (Array.isArray(subapp.includes) && subapp.includes.length > 0) { + distSrc = subapp.includes } // ignore builder files - distSrc.push( - '!' + PACKAGE_DIR, - '!' + '!' + PACKAGE_DIR + '/**' - ) - - // ignore packer.ignore configuration - if (packer.build && packer.build.ignore) { - packer.build.ignore.forEach((v) => { + // distSrc.push( + // '!' + PACKAGE_DIR, + // '!' + '!' + PACKAGE_DIR + '/**' + // ) + + // ignore subapp.ignores configuration + if (Array.isArray(subapp.ignores)) { + subapp.ignores.forEach((v) => { distSrc.push('!' + v) }) } - // define gulp entry task + // define gulp tasks gulp.task('tar', () => { + // console.log('Start gulp task: tar') + return gulp - .src(DIST_DIR + '/84/_tar/**/*') - .pipe(tar(packer.name + '.tar')) - .pipe(gulp.dest(DIST_DIR + '/84')) + .src(TEMP_DIR + '/_tar/dist/**/*') + .pipe(tar(subapp.id + '.tar')) + .pipe(gulp.dest(TEMP_DIR)) }) - gulp.task('cert84', ['tar'], () => { - const _tarPath = DIST_PATH + '/84/_tar' + gulp.task('cert', ['tar'], () => { + // console.log('Start gulp task: cert') + + const _tarPath = TEMP_PATH + '/_tar' if (fs.existsSync(_tarPath)) { fs.removeSync(_tarPath) } - const rtv = gulp.src(DIST_DIR + '/84/**/*') + const rtv = gulp.src(TEMP_DIR + '/**/*') function scanPipe (files) { function fn (file, cb) { !file.isDirectory() && files.push(file.relative) } return map(fn) } - rtv.pipe(scanPipe(files84)) + rtv.pipe(scanPipe(tarFiles)) rtv.on('end', () => { - signTar(DIST_PATH + '/84', files84, () => { + signTar(TEMP_PATH, tarFiles, () => { const _options = { tar: true, } - gulpPkg(_options, packer, cb) + gulpPkg(_options, subapp, cb) }) }) return rtv }) - gulp.task('dist84', () => { + gulp.task('dist', () => { + // console.log('Start gulp task: dist') + const src = gulp.src(distSrc).on('end', () => { // build Manifest.xml - buildManifestSync(packer, DIST_PATH, true) + // buildManifestSync(subapp, TEMP_PATH, true) setTimeout(() => { - gulp.start('cert84') + gulp.start('cert') }, 500) }) src.pipe( gulp.dest((file) => { - let distDir = DIST_DIR + '/84/_tar' + let distDir = TEMP_DIR + '/_tar' if (file.base.indexOf(ROOT_PATH) > -1) { - distDir += file.base.replace(path.join(TEMP_PATH, 'dist'), '') + distDir += file.base.replace(ROOT_PATH, '') } return distDir }), ) - - fs.copySync('./packer.json', path.join(DIST_DIR + '/84/_tar/packer.json')) }) - gulp.start('dist84') + gulp.start('dist') } /** * entry - * 1. preCheck packer.json exist + * 1. preCheck package.json exist * 2. render build config - * 3. invoke bizAppPack @see bizAppPack + * 3. invoke packSubapp @see packSubapp * @name entry * @function * @access public */ function entry () { - if (!fs.pathExistsSync('packer.json')) { - console.log(chalk.red("Fail: Can't find packer.json !\r\n")) + if (!fs.pathExistsSync('package.json')) { + console.log(chalk.red('\r\nMissing package.json')) return } + try { - const config = fs.readJSONSync('packer.json') - const build = config.build; + const pkg = fs.readJSONSync('package.json') + const version = pkg.version + const config = Object.assign({ version }, pkg.subapp) - // render inclue, ignore config - ['include', 'ignore'].forEach(k => { - build[k] = build[k].map(_ => path.join(TEMP_PATH, 'dist', _)) - }) - bizAppPack(config) + if (!('subapp' in pkg)) { + console.log(chalk.red('\r\nMissing `subapp` config in package.json')) + return + } + + if (!config.id) { + console.log(chalk.red('\r\nMissing `subapp.id` config in package.json')) + return + } + + packSubapp(config) } catch (e) { console.error(e) - console.log(chalk.red('failed to pack .')) + console.log(chalk.red('Pack offline-package failed.')) } } -function removeTemp () { - console.log(chalk.yellow('# removing temp folder')) - fs.removeSync(path.join(ROOT_PATH, '_temp')) -} - /** - * bizAppPack + * packSubapp * - * 1. copy src - * 2. link node_modules - * 3. compose bizapps - * 4. build assets - * 5. load hook - * 6. execute pack - * @name bizAppPack + * 1. load hook + * 2. execute pack + * @name packSubapp * @function * @access public * @param {Object} config pack config */ -function bizAppPack (config) { - const bizApps = config['biz-apps']; - +function packSubapp (config) { (async () => { try { - const paths = await globby(['*', '!{node_modules,offline-package,dist,offline_package}'], { - cwd: '../../', - }) - - console.log(chalk.yellow('# staring copy file src to _temp')) - paths.forEach(f => { - fs.copySync(path.join(PROJECT_PATH, f), path.join(TEMP_PATH, f)) - }) - - // 2. link node_modules - console.log(chalk.yellow('# staring link node_modules')) - fs.ensureSymlinkSync(path.join(PROJECT_PATH, 'node_modules'), path.join(TEMP_PATH, 'node_modules')) - - // 3. compose bizapps - console.log(chalk.yellow('# staring compose biz apps', bizApps)) - await composeApps(path.join(TEMP_PATH, './src'), {}, ...bizApps) - - // 4. build assets - console.log(chalk.yellow('# staring building assets')) - execSync('npm run build', { - cwd: TEMP_PATH, - }) - - // 5. loading hook - let beforePack, afterPack - if (fs.pathExistsSync(HOOK_PATH)) { - const hook = require(HOOK_PATH) - afterPack = hook.afterPack - beforePack = hook.beforePack - } - - console.log(chalk.yellow('# starting beforePack')) - beforePack && beforePack({ - fse: fs, - globby, - }) - - // 6. execute pack + // // 1. loading hook + // if (!fs.pathExistsSync(HOOK_PATH)) { + // fs.copySync(path.join(__dirname, '../vendor/hook.js'), HOOK_PATH) + // } + + // const hook = require(HOOK_PATH) + // const afterPack = hook.afterPack + // const beforePack = hook.beforePack + + // console.log(chalk.yellow('# starting beforePack')) + // beforePack && beforePack({ + // fse: fs, + // globby, + // }) + + // 2. execute pack await new Promise(res => { archiving(config, res) }) - console.log(chalk.yellow('# starting afterPack')) - afterPack && afterPack({ - fse: fs, - globby, - }) - } catch (e) { - console.error(chalk.red('# error', e)) + // console.log(chalk.yellow('# starting afterPack')) + // afterPack && afterPack({ + // fse: fs, + // globby, + // }) + } catch (ex) { + console.error(ex) } - - removeTemp() })() } @@ -244,23 +216,23 @@ function bizAppPack (config) { * @name buildManifestSync * @function * @access public - * @param {Object} packer packer.json config + * @param {Object} subapp package.json config * @param {String} manifestDir output path */ -function buildManifestSync (packer, manifestDir) { - try { - const out = [] - out.push('') - out.push('') - out.push(' ' + packer.name + '') - out.push(' ' + packer.version + '') - out.push('') - const outStr = out.join('\n') - fs.outputFileSync(manifestDir + '/84/Manifest.xml', outStr) - } catch (e) { - console.error(chalk.red('# write Manifest.xml error:')) - } -} +// function buildManifestSync (subapp, manifestDir) { +// try { +// const out = [] +// out.push('') +// out.push('') +// out.push(' ' + subapp.id + '') +// out.push(' ' + subapp.version + '') +// out.push('') +// const outStr = out.join('\n') +// fs.outputFileSync(manifestDir + '/Manifest.xml', outStr) +// } catch (e) { +// console.error(chalk.red('# write Manifest.xml error:')) +// } +// } /** * signTar @@ -287,7 +259,7 @@ function signTar (distPath, files, cb) { const fileDir = queue.shift() if (!fileDir) { if (working <= 0) { - fs.writeJSON(DIST_DIR + '/84/CERT.json', CERT_JSON) + fs.writeJSON(TEMP_DIR + '/CERT.json', CERT_JSON) cb && cb() } return @@ -316,15 +288,15 @@ function signTar (distPath, files, cb) { * @function * @access public * @param {Object} options options - * @param {Object} packer packer.json + * @param {Object} subapp package.json * @param {Function} cb callback */ -function gulpPkg (options, packer, cb) { - const amrFilename = `${packer.appid}_${packer.version}.amr` +function gulpPkg (options, subapp, cb) { + const amrFilename = `${subapp.id}_${subapp.version}.amr` - const packageDir = PACKAGE_DIR + '/' + packer.version + const packageDir = PACKAGE_DIR + '/' + subapp.version const amrPath = path.join(ROOT_PATH, packageDir + '/' + amrFilename) - const srcPath = DIST_DIR + '/84/**/*' + const srcPath = TEMP_DIR + '/**/*' gulp.task('zip', () => { return gulp @@ -333,10 +305,10 @@ function gulpPkg (options, packer, cb) { .pipe(gulp.dest(packageDir)) }) gulp.task('pack', ['zip'], () => { - console.log('# packed at ' + chalk.green(amrPath)) + console.log(chalk.yellow('# packed successfully at'), chalk.green(amrPath.replace(home, '~'))) const pkgInfo = { file: packageDir + '/' + amrFilename, - packer: packer, + config: subapp, } cb && cb(options.all, pkgInfo) }) diff --git a/src/bin/apfe-pack.js b/src/bin/apfe-pack.js index 7813309..72035dd 100755 --- a/src/bin/apfe-pack.js +++ b/src/bin/apfe-pack.js @@ -8,9 +8,5 @@ program .command('setkey ', 'set the privtekey to sign the offline package') .command('genkey', 'generate the RSA key pairs') .command('exportkey', 'export the RSA key pairs') - .command('init', 'init offline package') - .command('build', 'only build offline package without biz-apps') - .command('pack', 'pack offline package', { - isDefault: true, - }) + .command('pack', 'pack offline package', { isDefault: true }) .parse(process.argv) diff --git a/src/bin/apfe-update.js b/src/bin/apfe-update.js index bfc755b..d0f7524 100755 --- a/src/bin/apfe-update.js +++ b/src/bin/apfe-update.js @@ -57,14 +57,14 @@ function help () { if (args.length < 1) { return apfeUpdateDefaultHandle() } else { - inquirer.prompt([{ - type: 'confirm', - message: `confirm to update ${args.join(', ')}`, - name: 'ok', - }], function (answers) { - if (answers.ok) { - run() - } + inquirer.prompt([ + { + type: 'confirm', + message: `confirm to update ${args.join(', ')}`, + name: 'ok', + }, + ]).then(answers => { + answers.ok && run() }) } } diff --git a/src/bin/apfe.js b/src/bin/apfe.js index a2000c0..a5bfdac 100755 --- a/src/bin/apfe.js +++ b/src/bin/apfe.js @@ -1,23 +1,20 @@ #!/usr/bin/env node -import checkUpdate from '../lib/check-version' +import checkSelfVersion from '../lib/check-version' import spawn from 'win-spawn' import path from 'path' import chalk from 'chalk' -import _ from 'xutil' - -const packageCommands = { - init: 'generate a new project step-by-step, or by a template', - update: 'update project\'s basic-settings, includes babel, eslint, webpack, etc.', - pack: 'pack the web app for offline use', - sim: 'debug web app in iOS simulator', - bizapp: 'bizapp operations, includes create and compose', +import { existsFile } from '../lib/exists' + +const _commands = { + create: 'create a new project', + update: 'update configs (babel, eslint, webpack...)', + pack: 'pack offline package', + sim: 'debug in iOS simulator', } if (Math.random() < 0.2) { - checkUpdate() - .then(exec) - .catch(exec) + checkSelfVersion().then(exec).catch(exec) } else { exec() } @@ -28,11 +25,10 @@ function exec () { program .version(require('../../package').version, '-v, --version') .usage(' [options]') - .command('init', packageCommands.init) - .command('update', packageCommands.update) - .command('pack', packageCommands.pack) - .command('sim', packageCommands.sim) - .command('bizapp', packageCommands.bizapp) + .command('create', _commands.create) + .command('update', _commands.update) + .command('pack', _commands.pack) + .command('sim', _commands.sim) .parse(process.argv) const subcmd = program.args[0] @@ -70,11 +66,11 @@ function executable (subcmd) { const local = path.join(__dirname, bin) - if (_.isExistedFile(local)) { + if (existsFile(local)) { return } - let commands = Object.keys(packageCommands) + let commands = Object.keys(_commands) function printSimilar () { // guess commands diff --git a/src/index.js b/src/index.js deleted file mode 100644 index bb7b282..0000000 --- a/src/index.js +++ /dev/null @@ -1,7 +0,0 @@ -import { composeApps } from './lib/compose-apps/index' -import * as factory from './lib/compose-apps/plugin-factory' - -module.exports = { - composeApps, - ...factory, -} diff --git a/src/lib/ask.js b/src/lib/ask.js index 1904db6..4ed5bae 100644 --- a/src/lib/ask.js +++ b/src/lib/ask.js @@ -44,14 +44,16 @@ function prompt (data, key, prompt, done) { } } - inquirer.prompt([{ - type: promptMapping[prompt.type] || prompt.type, - name: key, - message: prompt.message || prompt.label || key, - default: promptDefault, - choices: prompt.choices || [], - validate: prompt.validate || function () { return true }, - }], function (answers) { + inquirer.prompt([ + { + type: promptMapping[prompt.type] || prompt.type, + name: key, + message: prompt.message || prompt.label || key, + default: promptDefault, + choices: prompt.choices || [], + validate: prompt.validate || function () { return true }, + }, + ]).then(answers => { if (Array.isArray(answers[key])) { data[key] = {} answers[key].forEach(function (multiChoiceAnswer) { diff --git a/src/lib/check-version.js b/src/lib/check-version.js index 6b98bc3..9aad30e 100644 --- a/src/lib/check-version.js +++ b/src/lib/check-version.js @@ -10,7 +10,7 @@ export default function () { // Ensure minimum supported node version is used if (!semver.satisfies(process.version, packageConfig.engines.node)) { return console.log(chalk.red( - ' You must upgrade node to >=' + packageConfig.engines.node + '.x to use apfe-cli' + ' You must upgrade Node.js to >=' + packageConfig.engines.node + '.x to use apfe-cli' )) } diff --git a/src/lib/compose-apps/index.js b/src/lib/compose-apps/index.js deleted file mode 100644 index de67148..0000000 --- a/src/lib/compose-apps/index.js +++ /dev/null @@ -1,32 +0,0 @@ -import Ware from '../ware' -import assets from './plugins/assets' -import router from './plugins/router' -import store from './plugins/store' -import i18n from './plugins/i18n' -import spm from './plugins/spm' -import styles from './plugins/styles' -import readSrc from './read-src' - -export const defaultOptions = { - webpackImportAlias: '~', -} - -export const composeApps = async (src, config, ...apps) => { - config = { ...defaultOptions, ...config } - const ware = new Ware() - ware - .use(assets) - .use(router) - .use(store) - .use(i18n) - .use(spm) - .use(styles) - - if (Array.isArray(config.plugins)) { - ware.use(config.plugins) - } - - const distinctApps = new Set(apps) - const project = readSrc(src, ...distinctApps) - return await ware.run(project, config) -} diff --git a/src/lib/compose-apps/plugin-factory.js b/src/lib/compose-apps/plugin-factory.js deleted file mode 100644 index 533fa41..0000000 --- a/src/lib/compose-apps/plugin-factory.js +++ /dev/null @@ -1,93 +0,0 @@ -import globby from 'globby' -import { warn, success } from '../logger' -import { - duplicateArrayChecker, - loggerPrefix, - getExportConstValues, - getExportDefaultObjectKeys, - getExportDefaultObjectValues, -} from './utils' -import { join, basename } from 'path' -import chalk from 'chalk' - -export const duplicateChecker = getValueFunc => filePath => async (project, config, next) => { - const filename = basename(filePath) - const logPrefix = `***[static checking ${filename}]***` - success(`${logPrefix} starting check ${filename} duplicate values...`) - const { container, bizapps } = project - const checkerObject = log => app => globby(filePath, { cwd: app.path }) - .then(res => { - if (res.length !== 1) { - log && log(app) - return null - } - - return { - name: `${app.name}/${filePath}`, - array: getValueFunc(join(app.path, res[0])), - } - }) - .catch(_ => warn(`${logPrefix} transform ${app.path} failed`)) - - const containerChecker = await checkerObject(_ => warn(`${logPrefix} requires container app has the ${filePath}`))(container) - if (!containerChecker) { - success(`${logPrefix} stopping check ${filename}...`) - next && await next() - return - } - - let bizappCheckers = await Promise.all(bizapps.map( - checkerObject(app => - warn(`Could not find ${app.path}/${filePath}.js, skip to next one`)) - ) - ) - bizappCheckers = bizappCheckers.filter(Boolean) - - duplicateArrayChecker( - containerChecker, - (container, app, obj) => warn(`${logPrefix} ${chalk.red(container)} && ${chalk.red(app)} encounter duplicate ${obj.length > 1 ? 'values' : 'value'} with ${chalk.red(obj.join(', '))}`), - ...bizappCheckers, - ) - - success(`${logPrefix} stopping check ${filename} duplicate values...`) - next && await next() -} - -export const duplicateExportConstValuesChecker = duplicateChecker(getExportConstValues) -export const duplicateExportConstKeysChecker = duplicateChecker(getExportDefaultObjectKeys) - -export const duplicateExportDefaultObjectValuesChecker = duplicateChecker(getExportDefaultObjectValues) -/** - * - * @param name pluginName - * @param globPattern globPattern for scripts to transform - * @param transform (scripts, project, config, logPrefix) - */ -export const composePlugin = (name, globPattern, transform) => async (project, config, next) => { - const filename = name || basename(globPattern) - const logPrefix = loggerPrefix(filename) - success(`${logPrefix} starting compose ${filename}...`) - - const { container } = project - const scripts = await globby(globPattern, { cwd: container.path }) - if (!scripts.length) { - warn(`${logPrefix} requires container app has the ${globPattern}`) - success(`${logPrefix} stopping compose ${filename}...`) - await next() - return - } - - if (transform) { - success(`${logPrefix} starting transform ${globPattern}...`) - await transform( - scripts.map(s => join(container.path, s)), - project, - config, - logPrefix - ) - success(`${logPrefix} stopping transform ${globPattern}...`) - } - - success(`${logPrefix} stopping compose ${filename}...`) - await next() -} diff --git a/src/lib/compose-apps/plugins/assets.js b/src/lib/compose-apps/plugins/assets.js deleted file mode 100644 index ddf83e8..0000000 --- a/src/lib/compose-apps/plugins/assets.js +++ /dev/null @@ -1,222 +0,0 @@ -import globby from 'globby' -import { warn, success } from '../../logger' -import { - babelTransform, - duplicateArrayChecker, - babelAppsFactory, -} from '../utils' -import chalk from 'chalk' -import { composePlugin } from '../plugin-factory' -import { join } from 'path' - -// 1. change the container app's utils/load-icons methods, add the multiple sources, if the source exist, then not add -/* -FROM: -const allIcons = require.context('assets/icons', true, /\.(svg|png)$/) -function importAll (r) { - r.keys().forEach(r) -} -importAll(allIcons) - -TO: -const allIcons = require.context('assets/icons', true, /\.(svg|png)$/) -const all${app}Icons = require.context('${biz-apps}/assets/icons', true, /\.(svg|png)$/) -function importAll (r) { - r.keys().forEach(r) -} -importAll(allIcons) -importAll(all${app}Icons) - -SUPPORT OPERATIONS: -ADD -REMOVE -UPDATE -*/ - - -export default composePlugin( - 'assets', - 'utils/load-icons.js', - async (scripts, project, config, logPrefix) => { - const { bizapps, container } = project - const globbyIcons = name => app => { - return globby(['*.svg', '*.png'], { cwd: join(app.path, 'assets/icons') }) - .then(array => { - return { - name: name || app.name, - array, - } - }) - } - - const containerIcons = await globbyIcons('container')(container) - const bizappIcons = await Promise.all(bizapps.map(globbyIcons())) - - success(`${logPrefix} starting check duplicate assets/icons/*.svg|*.png`) - duplicateArrayChecker( - containerIcons, - (container, app, obj) => warn(`${logPrefix} ${chalk.red(container)} && ${chalk.red(app)} assets encounter duplicate ${obj.length > 1 ? 'files' : 'file'} with ${chalk.red(obj.join(', '))}`), - ...bizappIcons, - ) - success(`${logPrefix} stopping check duplicate assets/icons/*.svg|*.png`) - - await babelTransform( - scripts[0], - { plugins: assetsPlugin(bizapps, config) } - ) - }) - - -// TestCases: -// 1. get the variable by require.context({bizApp}/assets) -// if not exist, then init it and call it. -// if existed, check if called, if not called, then call. -// 2. if the unnecessary require.context('assets/${app}) variable exist, then remove it both in declaration and callExpression -function assetsPlugin (bizapps, config) { - const alias = config.webpackImportAlias - const container = { - name: 'container', - required: false, - called: false, - variableName: 'allIcons', - } - const apps = bizapps.map(babelAppsFactory(config.assets)) - - const unusedRequireContextVarNames = new Set() - - return function ({ types: t }) { - return { - visitor: { - VariableDeclaration (path) { - const { node } = path - if (node.declarations.length) { - const declarator = node.declarations[0] - const varName = declarator.id.name - - if (declarator.init && - declarator.init.arguments.length && - declarator.init.arguments[0]) { - if (unusedRequireContextVarNames.has(varName)) { - path.remove() - return - } - } - - const idName = declarator.id.name - if (idName === container.variableName) { - for (const app of apps) { - if (!app.required) { - path.insertAfter( - t.variableDeclaration( - 'const', - [t.variableDeclarator( - t.identifier(`${app.variableName}`), - t.callExpression( - t.memberExpression(t.identifier('require'), - t.identifier('context')), - [t.stringLiteral(`${alias}biz-apps/${app.name}/assets/icons`), - t.booleanLiteral(true), - // eslint-disable-next-line - t.regExpLiteral('\.(svg|png)$')]))] - ) - ) - } - } - } - } - }, - - CallExpression (path) { - const { node } = path - const arg1 = node.arguments && node.arguments[0] - if (!arg1 || !arg1.name || - !(node.callee && node.callee.name === 'importAll')) return - - if (arg1.name === container.variableName) { - for (const app of apps) { - if (!app.called) { - path.insertAfter( - t.callExpression(t.identifier('importAll'), - [t.identifier(app.variableName)]) - ) - } - } - } - - if (unusedRequireContextVarNames.has(arg1.name)) { - path.remove() - } - }, - - Program ({ node }) { - const { body } = node - const declarations = body - .filter(node => { - const vType = node.type === 'VariableDeclaration' - if (!vType) return false - - let declarations = node.declarations - if (!declarations.length) return false - - declarations = declarations[0] - if (!declarations.init) return false - - declarations = declarations.init - if (!declarations.callee) return false - - declarations = declarations.callee - if (!declarations.object || !declarations.property) return false - - return declarations.object.name === 'require' && - declarations.property.name === 'context' - }) - - for (const declaration of declarations) { - const declarator = declaration.declarations[0] - const varName = declarator.id.name - const requirePath = declarator.init.arguments[0].value - for (const app of apps) { - const reg = new RegExp(`^${alias}biz-apps/${app.name}/assets/icons`) - if (reg.test(requirePath)) { - app.required = true - app.variableName = varName - } else if ((new RegExp(`^${alias}assets/icons`).test(requirePath))) { - container.required = true - container.variableName = varName - } else { - unusedRequireContextVarNames.add(varName) - } - } - } - - // filter the real unused variable - for (const app of apps) { - if (unusedRequireContextVarNames.has(app.variableName)) { - unusedRequireContextVarNames.delete(app.variableName) - } - } - - const expressions = body - .filter(node => { - const expressType = node.type === 'ExpressionStatement' - const callType = node.expression && - node.expression.type === 'CallExpression' - return expressType && callType - }) - - for (const expression of expressions) { - const callExp = expression.expression - const args = callExp.arguments || [{ value: void 0 }] - for (const app of apps) { - if (app.variableName === args[0].name) { - app.called = true - } else if (app.variableName === container.variableName) { - container.called = true - } - } - } - }, - }, - } - } -} diff --git a/src/lib/compose-apps/plugins/i18n.js b/src/lib/compose-apps/plugins/i18n.js deleted file mode 100644 index 8e9edb6..0000000 --- a/src/lib/compose-apps/plugins/i18n.js +++ /dev/null @@ -1,125 +0,0 @@ -import glob from 'glob' -import { warn, success } from '../../logger' -import { - babelTransform, - duplicateImportPlugin, - babelAppsFactory, - duplicateArrayChecker, - getExportDefaultObjectKeys, - spreadLocalePlugin, -} from '../utils' -import { basename } from 'path' -import chalk from 'chalk' -import { composePlugin } from '../plugin-factory' - -// 1. change the container app's i18n/locale/*.js files, add and use the biz-apps i18n/locale/*.js -/* -FROM: i18n/locale/en_US.js -export default { - 'index.title': 'A-Plus Front-End Scaffold', - 'modal.button.ok': 'OK', - 'modal.button.cancel': 'Cancel', - 'error.system': 'System error', - 'common.success': 'Success', - 'common.failed': 'Failed', - - // Common Keywords - 'keyword.accountName': 'Account Name', - 'keyword.vaExpireDate': 'Valid Until', - 'keyword.register': 'Register', - 'keyword.login': 'Login', - 'keyword.refresh': 'Refresh', - 'keyword.change': 'Change', - 'keyword.to': 'to', -} - -TO: -import autodebit from 'biz-apps/autodebit/i18n/locales/en_US' - -export default Object.assign({}, autodebit, { - 'index.title': 'A-Plus Front-End Scaffold', - 'modal.button.ok': 'OK', - 'modal.button.cancel': 'Cancel', - 'error.system': 'System error', - 'common.success': 'Success', - 'common.failed': 'Failed', - - // Common Keywords - 'keyword.accountName': 'Account Name', - 'keyword.vaExpireDate': 'Valid Until', - 'keyword.register': 'Register', - 'keyword.login': 'Login', - 'keyword.refresh': 'Refresh', - 'keyword.change': 'Change', - 'keyword.to': 'to', -} - -SUPPORT OPERATIONS: CRUD -*/ - -const IMPORT_PATH = 'i18n/locales' - -export default composePlugin( - 'i18n', - `${IMPORT_PATH}/*.js`, - async (scripts, project, config, logPrefix) => { - const babelTransformers = scripts.map(filePath => { - return babelTransform(filePath, { - plugins: i18nBabelPlugins(filePath, project, config, logPrefix), - }) - }) - - await Promise.all(babelTransformers) - } -) - -function i18nBabelPlugins (filePath, project, config, logPrefix) { - const { bizapps, container } = project - const filename = basename(filePath, '.js') - const apps = bizapps - .filter(app => { - const matchFiles = glob.sync( - `${app.path}/${IMPORT_PATH}/${filename}.js`, - { cwd: container.path } - ) - if (matchFiles.length !== 1) { - warn(`Could not find ${app.path}/${IMPORT_PATH}/${filename}.js, skip to next one`) - } - return matchFiles.length === 1 - }) - .map(babelAppsFactory(config.i18n)) - - - success(`${logPrefix} starting check ${IMPORT_PATH}/${filename}.js duplicate keys...`) - const notValidExportLogger = filePath => warn(`${logPrefix} ${filePath} export not a valid object, expect Object or Object.assign() Object`) - const containerApp = { - name: `src/${IMPORT_PATH}/${filename}.js`, - array: getExportDefaultObjectKeys(filePath, notValidExportLogger), - } - const duplicateCheckerApps = apps.map(app => { - return { - name: `${app.name}/${IMPORT_PATH}/${filename}.js`, - array: getExportDefaultObjectKeys( - `${app.path}/${IMPORT_PATH}/${filename}.js`, - notValidExportLogger - ), - } - }) - - duplicateArrayChecker( - containerApp, - (container, app, obj) => warn(`${logPrefix} ${chalk.red(container)} && ${chalk.red(app)} exports encounter duplicate ${obj.length > 1 ? 'keys' : 'key'} with ${chalk.red(obj.join(', '))}`), - ...duplicateCheckerApps, - ) - success(`${logPrefix} stopping check ${IMPORT_PATH}/${filename}.js duplicate keys...`) - - const ctx = { - apps, - unusedImportVars: new Set(), - } - - return [ - duplicateImportPlugin(ctx, config, IMPORT_PATH, filename), - spreadLocalePlugin(ctx), - ] -} diff --git a/src/lib/compose-apps/plugins/router.js b/src/lib/compose-apps/plugins/router.js deleted file mode 100644 index 542a2fd..0000000 --- a/src/lib/compose-apps/plugins/router.js +++ /dev/null @@ -1,326 +0,0 @@ -import { warn, success } from '../../logger' -import { - babelTransform, - duplicateImportPlugin, - babelAppsFactory, - duplicateArrayChecker, - getExportDefaultDeclaration, - parseAstWrapper, -} from '../utils' -import { composePlugin } from '../plugin-factory' -import chalk from 'chalk' -import * as R from 'ramda' - -// 1. change the container app's router/index.js methods, add the multiple sources -/* -FROM: -import { gettext } from 'utils/gettext' - -Vue.use(Router) - -const routes = [ - { - meta: { - aspm: '', - bgGray: true, - }, - name: pages.ERROR, - path: '/error', - component: r => require.ensure([], () => r(require('views/error')), 'error'), - }, -] - -TO: -import { gettext } from 'utils/gettext' -import autoDebitRoutes from 'biz-apps/autodebit/router/index' - -Vue.use(Router) - -const routes = [ - { - meta: { - aspm: '', - bgGray: true, - }, - name: pages.ERROR, - path: '/error', - component: r => require.ensure([], () => r(require('views/error')), 'error'), - }, -].concat(autoDebitRoutes) - -SUPPORT OPERATIONS: CRUD -*/ - -export default composePlugin( - 'router', - 'router/index.js', - async (scripts, project, config, logPrefix) => { - const { container, bizapps } = project - // check duplicate export's Array's path - success(`${logPrefix} starting check duplicate route path...`) - const containerApp = { - name: 'src/router/index.js', - array: getContainerRoutesPathsArray( - `${container.path}/router/index.js`, - filePath => warn(`${logPrefix} ${filePath} doesn't init vue-router's routes with an array expression`) - ), - } - - duplicateArrayChecker( - containerApp, - (container, app, obj) => warn(`${logPrefix} ${chalk.red(container)} && ${chalk.red(app)} encounter duplicate route ${obj.length > 1 ? 'paths' : 'path'} with ${chalk.red(obj.join(', '))}`), - ...bizapps.map(app => { - return { - name: app.name, - array: getRoutesPathsArray( - `${app.path}/router/index.js`, - filePath => warn(`${logPrefix} ${filePath} needs to export an Array of Routes`) - ), - } - }) - ) - success(`${logPrefix} stopping check duplicate route path...`) - await babelTransform( - scripts[0], - { plugins: routesPlugins(project, config) } - ) - } -) - -// 1. check import variable name -// 2. check routes callee -function routesPlugins (project, config) { - const { bizapps } = project - const ctx = { - apps: bizapps.map(babelAppsFactory(config.router)), - unusedImportVars: new Set(), - } - - const routerInitPlugin = function (ctx) { - const { apps, unusedImportVars } = ctx - return function ({ types: t }) { - return { - visitor: { - MemberExpression (path) { - const isValid = R.allPass([ - R.pathEq(['node', 'object', 'type'], 'ArrayExpression'), - R.pathEq(['node', 'property', 'name'], 'concat'), - x => { - const containerArgs = R.path(['container', 'arguments'], path) - if (!notEmptyArray(containerArgs)) { - return false - } - - const properties = R.path(['node', 'object', 'elements', 0, 'properties'], x) - if (notEmptyArray(properties)) { - return isValidRoutesProperties(properties) - } - - return false - }, - ]) - - if (isValid(path)) { - const args = R.pipe( - R.path(['container', 'arguments']), - R.filter(arg => !unusedImportVars.has(arg.name)), - )(path) - - const filterSet = new Set(R.map(R.prop('name'), args)) - const identifiers = R.pipe( - R.filter(app => !app.called && !filterSet.has(app.variableName)), - R.map(app => t.identifier(app.variableName)), - )(apps) - - path.container.arguments = args.concat(identifiers) - } - }, - }, - } - } - } - - return [ - duplicateImportPlugin(ctx, config, 'router'), - routerInitPlugin(ctx), - ] -} - -const getArrayElementsPaths = R.pipe( - R.prop('properties'), - R.find(R.pathEq(['key', 'name'], 'path')), - R.path(['value', 'value']) -) - -const isValidRoutesProperties = p => !R.isEmpty(R.intersection( - R.map(R.path(['key', 'name']), p), - ['meta', 'path', 'name'], -)) - -const isExist = R.complement(R.isNil) -const notEmptyArray = R.both(isExist, R.complement(R.isEmpty)) - -// Get this expression's routes.map(r => r.path) -/* -const router = new Router({ - mode: 'history', - base: basePath, - routes: [{ - meta: { - aspm: '', - bgGray: true - }, - name: ERROR, - path: '/error', - component: r => require.ensure([], () => r(require('views/error')), 'error') - }].concat(cashier, autodebit), - */ -function getContainerRoutesPathsArray (filePath, log) { - const ast = parseAstWrapper(filePath) - const body = ast.program.body - let res = [] - const firstDeclaration = R.path(['declarations', 0]) - const getRoutesElements = R.path(['init', 'callee', 'object', 'elements']) - const isTypeDeclaration = R.propEq('type', 'VariableDeclaration') - - // two possible situations - /* 1. within the new Route Expression - const router = new Router({ - mode: 'history', - base: basePath, - routes: [...].concat(...), - }) - */ - const finder1 = R.allPass( - [ - isTypeDeclaration, - R.pipe(firstDeclaration, isExist), - R.pipe(firstDeclaration, R.allPass( - [ - R.pathEq(['init', 'type'], 'NewExpression'), - R.pathEq(['init', 'callee', 'name'], 'Router'), - R.pathEq(['init', 'arguments', 0, 'type'], 'ObjectExpression'), - firstD => { - const properties = R.path(['init', 'arguments', 0, 'properties'], firstD) - if (!properties || !properties.length) return false - return R.any(p => { - const key = R.path(['key', 'name'], p) - const value = R.path(['value', 'type'], p) - return key === 'routes' && value === 'CallExpression' - }, properties) - }, - ], - )), - ] - ) - const mapper1 = R.pipe( - R.path(['declarations', 0, 'init', 'arguments', 0, 'properties']), - R.find(R.pathEq(['key', 'name'], 'routes')), - R.view(R.lensPath(['value', 'callee', 'object', 'elements'])), - R.map(getArrayElementsPaths) - ) - - /* 2. outside the new Route Expression - const routes = [...].concat(...) - const router = new Router(routes, ...) - */ - const finder2 = R.allPass( - [ - isTypeDeclaration, - R.pipe(firstDeclaration, isExist), - R.pipe( - firstDeclaration, - R.allPass( - [ - R.pathEq(['init', 'callee', 'object', 'type'], 'ArrayExpression'), - R.pipe(getRoutesElements, R.all( - R.allPass( - [ - R.propEq('type', 'ObjectExpression'), - R.propSatisfies(p => { - if (!p.length) return false - return !R.isEmpty(R.intersection( - R.map(R.path(['key', 'name']), p), - ['meta', 'path', 'name'] - )) - }, 'properties'), - ] - ) - )), - ] - ) - ), - ] - ) - const mapper2 = R.pipe( - R.path(['declarations', 0, 'init', 'callee', 'object', 'elements']), - R.map(getArrayElementsPaths), - ) - - const lookups = [ - R.pipe(R.find(finder2), mapper2), - R.pipe(R.find(finder1), mapper1), - ] - - for (let i = 0; i < lookups.length; i++) { - const f = lookups[i] - let r - try { - r = f(body) - } catch (err) { - - } - - if (r && r.length) { - res = r - break - } - } - - if (!res || !res.length) { - log && log(filePath) - } - - return res -} - -// Get this expression's export.default.map(r => r.path) -/* -export default [ - { - meta: { - titleKey: 'auto.debit.title', - bgGray: true, - }, - name: pages.AUTO_DEBIT_DETAIL, - path: '/autodebit', - component: r => require.ensure([], () => r(require('../views/detail')), 'autodebit')}, - { - meta: { - titleKey: 'auto.debit.title', - bgGray: true, - }, - name: pages.AUTO_DEBIT_LIST, - path: '/autodebit/list', - component: r => require.ensure([], () => r(require('../views/list')), 'autodebit'), - }, - */ -function getRoutesPathsArray (filePath, log) { - let res = [] - try { - const ast = parseAstWrapper(filePath) - const exportDefaultDeclaration = getExportDefaultDeclaration(ast.program) - if (exportDefaultDeclaration) { - const { declaration } = exportDefaultDeclaration - if (declaration.type === 'ArrayExpression') { - res = declaration.elements.map(getArrayElementsPaths) - } - } - } catch (err) {} - - if (!res || !res.length) { - log && log(filePath) - } - - return res -} diff --git a/src/lib/compose-apps/plugins/spm.js b/src/lib/compose-apps/plugins/spm.js deleted file mode 100644 index c5de7bb..0000000 --- a/src/lib/compose-apps/plugins/spm.js +++ /dev/null @@ -1,56 +0,0 @@ -import { - babelTransform, - duplicateImportPlugin, - babelAppsFactory, - spreadLocalePlugin, -} from '../utils' -import { - composePlugin, -} from '../plugin-factory' - -// 1. change the container app's constants/spm.js files, import and use the biz-apps constants/spm.js -/* -FROM: constants/spm.js -import cashier from '~biz-apps/cashier/constants/spm' - -export default Object.assign({}, cashier, { - [PAGE.ERROR]: { - $: '', - }, -}) - -TO: -import * as PAGE from './pages' - -import cashier from '~biz-apps/cashier/constants/spm' -import autoDebit from '~biz-apps/auto-debit/constants/spm' -import paymentResult from '~biz-apps/payment-result/constants/spm' -import topup from '~biz-apps/topup/constants/spm' - -export default Object.assign({}, cashier, autoDebit, paymentResult, topup, { - [PAGE.ERROR]: { - $: '', - }, -}) - -SUPPORT OPERATIONS: CRUD -*/ - -const IMPORT_PATH = 'constants/spm' - -export default composePlugin('spm', `${IMPORT_PATH}.js`, async (scripts, project, config) => { - const { bizapps } = project - const ctx = { - apps: bizapps.map(babelAppsFactory(config.spm)), - unusedImportVars: new Set(), - } - await babelTransform( - scripts[0], - { - plugins: [ - duplicateImportPlugin(ctx, config, IMPORT_PATH), - spreadLocalePlugin(ctx), - ], - } - ) -}) diff --git a/src/lib/compose-apps/plugins/store.js b/src/lib/compose-apps/plugins/store.js deleted file mode 100644 index 979236c..0000000 --- a/src/lib/compose-apps/plugins/store.js +++ /dev/null @@ -1,113 +0,0 @@ -import { - babelTransform, - duplicateImportPlugin, - babelAppsFactory, -} from '../utils' -import { composePlugin } from '../plugin-factory' - -// 1. change the container app's store/index.js methods, add the multiple sources -/* -FROM: -import Vue from 'vue' -import Vuex from 'vuex' -import wallet from './modules/wallet' -import lastSecurityContext from './modules/lastSecurityContext' -import getPaymentGuide from './modules/getPaymentGuide' - -Vue.use(Vuex) - -export default new Vuex.Store({ - modules: { - checkout, - lastSecurityContext, - getPaymentGuide, - }, -}) - -TO: -import Vue from 'vue' -import Vuex from 'vuex' -import autoDebit from 'biz-apps/autodebit/store' -import checkout from 'biz-apps/cashier/store' -import wallet from './modules/wallet' -import lastSecurityContext from './modules/lastSecurityContext' -import getPaymentGuide from './modules/getPaymentGuide' - -Vue.use(Vuex) - -export default new Vuex.Store({ - modules: { - autoDebit, - wallet, - checkout, - lastSecurityContext, - getPaymentGuide, - }, -}) - -SUPPORT OPERATIONS: -ADD -REMOVE -UPDATE -*/ - -export default composePlugin( - 'store', - 'store/index.js', - async (scripts, project, config) => { - await babelTransform(scripts[0], { plugins: storePlugins(project, config) }) - } -) - -// 1. check import variable name -// 2. check routes callee -function storePlugins (project, config) { - const { bizapps } = project - const ctx = { - apps: bizapps.map(babelAppsFactory(config.vuexStoreModulesNames)), - unusedImportVars: new Set(), - } - - // insert the variable in the `new Vuex.store({})` function - const vuexInsertPlugin = function (ctx) { - const { apps, unusedImportVars } = ctx - return function ({ types: t }) { - return { - visitor: { - NewExpression (path) { - const { node } = path - if (node.callee.type === 'MemberExpression') { - const memberExpression = node.callee - if (memberExpression.object.name === 'Vuex' && - memberExpression.property.name === 'Store') { - const objectExpression = node.arguments[0] - const properties = objectExpression.properties - if (properties.length) { - let moduleProperty = properties - .filter(p => p.key.name === 'modules') - if (moduleProperty.length) moduleProperty = moduleProperty[0] - - const valueExpression = moduleProperty.value - const modules = valueExpression.properties - .filter(arg => !unusedImportVars.has(arg.key.name)) - const filterSet = new Set(modules.map(arg => arg.key.name)) - const identifiers = apps - .filter(app => !app.called && - !filterSet.has(app.variableName) - ) - .map(app => t.identifier(app.variableName)) - valueExpression.properties = modules.concat(identifiers) - } - } - } - }, - }, - } - } - } - - return [ - duplicateImportPlugin(ctx, config, 'store'), - vuexInsertPlugin(ctx), - ] -} diff --git a/src/lib/compose-apps/plugins/styles.js b/src/lib/compose-apps/plugins/styles.js deleted file mode 100644 index 27a57ce..0000000 --- a/src/lib/compose-apps/plugins/styles.js +++ /dev/null @@ -1,125 +0,0 @@ -import glob from 'glob' -import { warn, success } from '../../logger' -import { readFile, writeFile } from 'fs-extra' -import { composePlugin } from '../plugin-factory' -import * as R from 'ramda' -import Debug from 'debug' - -const logStyles = Debug('compose-style-plugin') - -/* -// Core -@import './core/variables.less'; -@import './core/mixins.less'; -@import './core/normalize.less'; -@import './core/scaffolding.less'; -@import './core/utilities.less'; -@import './core/transitions.less'; - -// Components -@import './components/button.less'; -@import './components/digital-password.less'; -@import './components/row.less'; -@import './components/icon.less'; -@import './components/modal.less'; - - -TO: -// Core -@import './core/variables.less'; -@import './core/mixins.less'; -@import './core/normalize.less'; -@import './core/scaffolding.less'; -@import './core/utilities.less'; -@import './core/transitions.less'; - -// Components -@import './components/button.less'; -@import './components/digital-password.less'; -@import './components/row.less'; -@import './components/icon.less'; -@import './components/modal.less'; - -// Pages -@import '../biz-apps/autodebit/styles/index.less'; -@import '../biz-apps/cashier/styles/index.less'; - -SUPPORT OPERATIONS: -ADD -REMOVE -UPDATE -*/ - -// TODO: using less AST to write the plugin -export default composePlugin( - 'styles', - 'styles/index.less', - async (scripts, project, config, logPrefix) => { - const { container, bizapps } = project - - const apps = bizapps - .filter(app => { - const lessPath = `${app.path}/styles/index.less` - const matchFiles = glob.sync( - lessPath, - { cwd: container.path } - ) - if (matchFiles.length !== 1) { - warn(`${logPrefix} Could not find ${lessPath}, skip to next one`) - } - return matchFiles.length === 1 - }) - .map(app => { - return { - module: `@import '../biz-apps/${app.name}/styles/index.less'`, - name: app.name, - required: false, - } - }) - - const sourceFilePath = `${container.path}/styles/index.less` - let fileContent = await readFile(sourceFilePath, 'utf-8') - // eslint-disable-next-line - let currentApps = fileContent.match(new RegExp('[^\/\/+]@import.*', 'ig')) - if (currentApps && currentApps.length) { - const unusedApps = new Set() - currentApps.forEach(p => { - const reg = new RegExp('../biz-apps/([A-Za-z0-9_-]+)/styles/index.less') - const name = reg.exec(p) - if (name && name.length === 2) { - for (const app of apps) { - if (app.name === name[1]) { - app.required = true - } else { - unusedApps.add(name[1]) - } - } - } - }) - - for (const app of apps) { - unusedApps.delete(app.name) - } - - for (const unusedApp of unusedApps) { - const importPath = `../biz-apps/${unusedApp}/styles/index.less` - fileContent = fileContent.replace(new RegExp(`@import\\s+['"]${importPath}['"];\n*`), '') - } - logStyles('file content before is', fileContent) - - for (const app of apps) { - if (!app.required) { - let split = '' - if (R.last(fileContent) !== '\n') { - split = '\n' - } - fileContent = `${fileContent}${split}${app.module};` - logStyles('file content is', fileContent) - } - } - } - - await writeFile(sourceFilePath, fileContent) - success(`${logPrefix} stopping compose styles...`) - } -) diff --git a/src/lib/compose-apps/read-src.js b/src/lib/compose-apps/read-src.js deleted file mode 100644 index 20013a0..0000000 --- a/src/lib/compose-apps/read-src.js +++ /dev/null @@ -1,82 +0,0 @@ -import { resolve, join, basename } from 'path' -import fs from 'fs' - -const LOGGER_PREFIX = '***[compose biz-apps read-src]***' - -function App (path) { - this.path = path - this.name = basename(path) - const subAppsPath = join(path, 'biz-apps') - if (existsDir(subAppsPath)) { - this.subApps = fs.readdirSync(subAppsPath) - .map(p => new App(join(path, p))) - } -} - -export default function readSrc (src, ...apps) { - if (!apps.length) { - throw new Error(`${LOGGER_PREFIX} requires at least one app`) - } - - for (const app of apps) { - if (!app) throw new Error(`${LOGGER_PREFIX} ${app} of biz-app args is not a valid biz-app`) - } - - const container = isValidContainerApp(resolve(src)) - let bizapps = apps.map(app => resolve(join(src, `biz-apps/${app}`))) - bizapps = bizapps.filter(isValidBizApp) - - return { - bizapps: bizapps.map(app => new App(app)), - container: new App(container), - } -} - -function isValidContainerApp (container) { - const validAppFileRequires = [ - 'libs/vue-init.js', - 'store/index.js', - 'router/index.js', - 'entry/index.js', - ] - - validAppFileRequires.forEach(file => { - const jf = join(container, file) - if (!existsFile(jf)) { - throw new Error(`${LOGGER_PREFIX} ${file} is not exist! It's not Alipay+ project.\n Maybe you need to init that by 'apfe init your-project'`) - } - }) - - return container -} - -function isValidBizApp (app) { - if (!existsDir(app)) { - throw new Error(`${LOGGER_PREFIX} ${app} is not exist, it's not a valid biz-app`) - } - - const validAppFileRequires = ['store/index.js', 'router/index.js'] - validAppFileRequires.forEach(file => { - const jf = join(app, file) - if (!existsFile(jf)) { - throw new Error(`${LOGGER_PREFIX} ${app} ${file} is not exist! Maybe it's not need to be a biz app`) - } - }) - - return app -} - -const exists = type => fileOrDir => { - try { - const status = fs.statSync(fileOrDir) - const func = type === 'file' ? status.isFile : status.isDirectory - if (func.call(status)) { - return true - } - } catch (e) { - return false - } -} - -export const existsFile = exists('file') -export const existsDir = exists('dir') diff --git a/src/lib/compose-apps/utils.js b/src/lib/compose-apps/utils.js deleted file mode 100644 index 4d2ae85..0000000 --- a/src/lib/compose-apps/utils.js +++ /dev/null @@ -1,376 +0,0 @@ -import * as babel from 'babel-core' -import codeFrame from 'babel-code-frame' -import { readFileSync, writeFileSync } from 'fs' -import { execSync } from 'child_process' -import glob from 'glob' -import { resolve } from 'path' -import * as babylon from 'babylon' -import camelcase from 'camelcase' -import { warn } from '../logger' -import Debug from 'debug' - -const debug = Debug('babel:util') - -export const loggerPrefix = prefix => `***[compose ${prefix}]***` - -// babel-handbook: https://github.com/thejameskyle/babel-handbook/blob/master/translations/en/plugin-handbook.md -export function babelTransform (file, options) { - return new Promise((resolve, reject) => { - babel.transformFile(file, { - ...options, - babelrc: false, // Keep the file origin smell - }, function (err, result) { - if (err) { - if (err.loc) { - console.log(`${file} syntax error:`) - console.log(codeFrame(readFileSync(file, 'utf8'), err.loc.line, err.loc.column)) - } - reject(err) - return - } - writeFileSync(file, result.code) - try { - beautifulFile(file) - } catch (err) { - warn('format file failed', err) - } - resolve(result) - }) - }) -} - -export const getExportDefaultDeclaration = program => { - const exp = program.body - .filter(node => node.type === 'ExportDefaultDeclaration') - if (exp.length === 1) { - return exp[0] - } - return null -} - -const getStringProperties = ObjectExpression => { - const props = ObjectExpression.properties || [] - return props.some(node => node.key.type === 'StringLiteral') -} - -// Get all the keys or values of such two expressions -/* Will Get ['index.title', 'modal.button.ok', 'modal.button.cancel'] -export default Object.assign({}, autodebit, cashier, { - 'index.title': 'A-Plus Front-End Scaffold', - 'modal.button.ok': 'OK', - 'modal.button.cancel': 'Cancel', -}) - */ - -/* Will get ['index1', 'index2'] -export default { - 'index1': 'A+前端工程模板', - 'index2': '确认', -} - */ -const getExportDefaultObject = (filePath, filter, mapper, log) => { - const ast = parseAstWrapper(filePath) - const exportDefaultDeclaration = getExportDefaultDeclaration(ast.program) - if (exportDefaultDeclaration) { - const { declaration } = exportDefaultDeclaration - if (declaration.type === 'CallExpression' && - declaration.callee.type === 'MemberExpression') { - const objectExps = declaration.arguments.filter(getStringProperties) - if (objectExps.length) { - return objectExps[0].properties - .filter(filter) - .map(mapper) - } - } else if (declaration.type === 'ObjectExpression') { - return declaration.properties - .filter(filter) - .map(mapper) - } else { - log && log(filePath) - } - } - return [] -} - -export const getExportDefaultObjectKeys = (filePath, log) => { - return getExportDefaultObject( - filePath, - node => node.key.type === 'StringLiteral' || node.key.type === 'Identifier', - node => { - if (node.key.type === 'StringLiteral') { - return node.key.value - } else if (node.key.type === 'Identifier') { - return node.key.name - } - }, - log - ) -} - -// Get all the values of such two expressions -export const getExportDefaultObjectValues = (filePath, log) => { - return getExportDefaultObject( - filePath, - node => node.value.type === 'StringLiteral', - node => node.value.value, - log - ) -} - -export function parseAstWrapper (filePath) { - const fileContent = readFileSync(filePath, 'utf8') - let ast - try { - ast = babylon.parse(fileContent, { sourceType: 'module' }) - } catch (err) { - if (err.loc) { - console.log(`${filePath} syntax error:`) - console.log(codeFrame(fileContent, err.loc.line, err.loc.column)) - } - throw err - } - - return ast -} - -// Get all const values from export or export const syntax -// `export const AA = 'something_aa'` -// `export const BB = 'something_bb'` -// Will Get ['something_aa', 'something_bb'] -export function getExportConstValues (filePath) { - const ast = parseAstWrapper(filePath) - const { body } = ast.program - let res = [] - try { - res = body - .filter(node => { - if (node.type !== 'ExportNamedDeclaration') return false - const { declaration } = node - if (!declaration || - declaration.type !== 'VariableDeclaration' || - declaration.kind !== 'const') { - return false - } - const dcl = declaration.declarations && declaration.declarations[0] - return dcl && - dcl.type === 'VariableDeclarator' && - dcl.init.type === 'StringLiteral' - }) - .map(node => { - const { declaration } = node - const dcl = declaration.declarations && declaration.declarations[0] - return dcl.init.value - }) - } catch (err) { - warn(`try to getExportConstValues while parsing ${filePath} failed.`) - } - - return res -} - -export function duplicateArrayChecker (container, log, ...bizapps) { - function compareApps (app1, app2) { - const conflictFiles = app1.array.filter(_ => app2.array.includes(_)) - if (conflictFiles.length > 0) { - log(app1.name, app2.name, conflictFiles) - } - } - - function compareAnyTowApps (arrs, cb) { - doMatch(arrs) - - function doMatch (arrs) { - const app = arrs.shift() - arrs.forEach(_ => cb(app, _)) - if (arrs.length > 0) { - doMatch(arrs) - } - } - } - - compareAnyTowApps([container, ...bizapps], compareApps) -} - -function searchNodeModules (dir) { - let deps = 10 - while (!(glob.sync('node_modules', { cwd: dir })).length && deps > 0) { - dir = resolve(dir, '..') - --deps - } - - if (!(glob.sync('node_modules', { cwd: dir })).length) { - throw new Error('Could not find node_modules file') - } else { - return dir - } -} - - -export function beautifulFile (file, cwd) { - const dftCwd = cwd || searchNodeModules(file) - execSync(`./node_modules/.bin/eslint --fix --format ./node_modules/eslint-friendly-formatter ${file}`, { cwd: dftCwd }) -} - -export const babelAppsFactory = middlewareConfig => app => { - let variableName = camelcase(app.name) - if (middlewareConfig && middlewareConfig[app.name]) { - variableName = middlewareConfig[app.name] - } - return { - ...app, - required: false, - called: false, - variableName, - } -} - -/** - * This plugin is to import biz-app's variable or delete the unused variable - * @param ctx - * @param config - * @param importPath - * @param filename - * @returns {Function} - */ -export function duplicateImportPlugin (ctx, config, importPath, filename) { - const alias = config.webpackImportAlias || '' - const { apps, unusedImportVars } = ctx - return function ({ types: t }) { - return { - visitor: { - Program (path) { - const { node } = path - let { body } = node - - // filter the possible variables - const declarations = body - .filter(node => { - const vType = node.type === 'ImportDeclaration' - if (!vType) return false - - if (!node || - !node.specifiers || - !node.specifiers.length) return false - - const source = node.specifiers[0] - if (source.type !== 'ImportDefaultSpecifier') return false - - const localName = source.local && source.local.name - if (!localName) return false - - const reg = new RegExp(`${alias}biz-apps/[A-Za-z0-9_-]+/${importPath}/?.*`) - return reg.test(node.source.value) - }) - - for (const declaration of declarations) { - const requirePath = declaration.source.value - for (const app of apps) { - const localName = declaration.specifiers[0].local.name - const reg = new RegExp(`^${alias}biz-apps/${app.name}/${importPath}/?.*`) - if (reg.test(requirePath)) { - app.required = true - app.variableName = localName - } else { - unusedImportVars.add(localName) - } - } - } - - // delete the unused variable according to current apps - for (const app of apps) { - unusedImportVars.delete(app.variableName) - } - - // filter the needed node, do not use the unusedImportVars node - body = body.filter(exp => { - if (exp.type === 'ImportDeclaration') { - if (exp.specifiers && exp.specifiers.length) { - const source = exp.specifiers[0] - if (source.type === 'ImportDefaultSpecifier') { - const localName = source.local && source.local.name - if (unusedImportVars.has(localName)) { - return false - } - } - } - } - return true - }) - - // transform the apps into AST - const importIdentiers = apps - .filter(app => !app.required) - .map(app => t.importDeclaration( - [t.ImportDefaultSpecifier(t.Identifier(app.variableName))], - t.stringLiteral(`${alias}biz-apps/${app.name}/${importPath}${filename ? ('/' + filename) : ''}`) - )) - - // insert the needed imports under the lastImport node - debug(`body is ${body}`) - body.splice(0, 0, ...importIdentiers) - - path.node.body = body - }, - }, - } - } -} - -// Case:1 Try to make -// `export default { origin }` into -// `export default Object.assign({}, app1, app2..., { origin })` -// Case2: Try to make -// `export default Object.assign({}, app1, { origin })` into -// `export default Object.assign({}, app1, app2..., { origin })` -export function spreadLocalePlugin (ctx) { - return function ({ types: t }) { - return { - visitor: { - ObjectExpression (path) { - if (path.container && path.container.type === 'ExportDefaultDeclaration') { - const { apps } = ctx - const identifiers = apps - .filter(app => !app.called) - .map(app => t.identifier(app.variableName)) - path.replaceWith( - t.callExpression( - t.memberExpression(t.identifier('Object'), t.identifier('assign')), - [t.objectExpression([]), ...identifiers, path.node] - ), - ) - } - }, - - CallExpression (path) { - const { node } = path - if (path.container && - path.container.type === 'ExportDefaultDeclaration' && - node.callee && - node.callee.type === 'MemberExpression' && - node.callee.object.name === 'Object' && - node.callee.property.name === 'assign') { - const { apps, unusedImportVars } = ctx - const objectArgs = node.arguments - - // TODO: here only match the pattern object.assign({}, ...apps, {origin}) - const origin = objectArgs.slice(0, 1).concat(objectArgs.slice(-1)) - const properties = objectArgs.slice(1, -1) - const appVars = properties - .filter(arg => { - const isIdentifier = arg.type === 'identifier' - if (!isIdentifier) return false - return !unusedImportVars.has(arg.name) - }) - const filterSet = new Set(appVars.map(arg => arg.name)) - const identifiers = apps - .filter(app => !app.called && !filterSet.has(app.variableName)) - .map(app => t.identifier(app.variableName)) - - origin.splice(1, 0, ...identifiers) - node.arguments = origin - } - }, - }, - } - } -} diff --git a/src/lib/exists.js b/src/lib/exists.js new file mode 100644 index 0000000..231c1fd --- /dev/null +++ b/src/lib/exists.js @@ -0,0 +1,14 @@ +import fs from 'fs' + +const exists = type => target => { + try { + const status = fs.statSync(target) + const func = type === 'file' ? status.isFile : status.isDirectory + return !!func.call(status) + } catch (ex) { + return false + } +} + +export const existsFile = exists('file') +export const existsDir = exists('dir') diff --git a/src/lib/generate.js b/src/lib/generate.js index 3ec0e92..1ca9e79 100644 --- a/src/lib/generate.js +++ b/src/lib/generate.js @@ -11,17 +11,18 @@ import ask from './ask' import filter from './filter' import uuid from 'uuid/v4' import { readJsonSync } from 'fs-extra' -import { existsFile } from './compose-apps/read-src' +import { existsFile } from './exists' const render = handlebars.render const defaultMeta = (modules = [], dest) => { const result = {} modules.forEach(module => { - if (module === 'offline-package') { - result['offline'] = true - } else { - result[module] = true - } + // if (module === 'offline-package') { + // result['offline'] = true + // } else { + // result[module] = true + // } + result[module] = true }) return Object.assign(result, { destDirName: modules.join('-'), @@ -49,45 +50,6 @@ Handlebars.registerHelper('toUpperCase', function (str) { Handlebars.registerHelper('uuid', uuid) -export function generateBizApp (name, src, dest) { - return new Promise((resolve, reject) => { - const opts = getOptions(name, src) - const metalsmith = Metalsmith(path.join(src, 'template')) - const data = Object.assign(metalsmith.metadata(), { name }) - opts.helpers && Object.keys(opts.helpers).map(function (key) { - Handlebars.registerHelper(key, opts.helpers[key]) - }) - - const helpers = { chalk, logger } - - metalsmith - .use(renderTemplateFiles(opts.skipInterpolation)) - - if (typeof opts.metalsmith === 'function') { - opts.metalsmith(metalsmith, opts, helpers) - } else if (opts.metalsmith && typeof opts.metalsmith.after === 'function') { - opts.metalsmith.after(metalsmith, opts, helpers) - } - - metalsmith - .clean(false) - .source('.') - .destination(dest) - .build(function (err, files) { - if (err) reject(err) - if (typeof opts.complete === 'function') { - const helpers = { chalk, logger, files } - opts.complete(data, dest, helpers) - } - - if (typeof opts.completeMessage === 'string') { - logMessage(opts.completeMessage, data) - } - resolve() - }) - }) -} - /** * Generate a template given a `src` and `dest`. * @@ -131,7 +93,7 @@ export function generate (name, src, dest, done) { metalsmith.clean(false) .source('.') // start from template root instead of `./src` which is Metalsmith's default for `source` .destination(dest) - .build(function (err, files) { + .build((err, files) => { done(err) if (typeof opts.complete === 'function') { const helpers = { chalk, logger, files } @@ -210,7 +172,7 @@ function originMeta (dir) { const origin = { flow: false, test: false, - offline: false, + // offline: false, } if (existsFile(path.join(dir, 'flow-typed/modules.js')) && @@ -222,9 +184,9 @@ function originMeta (dir) { origin.test = true } - if (existsFile(path.join(dir, 'offline-package'))) { - origin.offline = true - } + // if (existsFile(path.join(dir, 'offline-package'))) { + // origin.offline = true + // } return Object.assign({ name: oriJson.name, diff --git a/src/lib/sign.js b/src/lib/sign.js index 547cf49..3b99fe6 100644 --- a/src/lib/sign.js +++ b/src/lib/sign.js @@ -2,13 +2,14 @@ import crypto from 'crypto' import fs from 'fs' import path from 'path' +import chalk from 'chalk' import home from 'user-home' function doSign (file, cb) { - const privateKeyFile = path.join(home, '.apfe/rsa-key/private.pem') - console.log(`using the private.pem: ${privateKeyFile}`) - const privateKey = fs.readFileSync(privateKeyFile).toString() + const privateKeyFile = '.apfe/rsa-key/private.pem' + console.log(chalk.yellow('# using the private.pem:'), chalk.green(`~/${privateKeyFile}`)) + const privateKey = fs.readFileSync(path.join(home, privateKeyFile)).toString() const f = fs.ReadStream(file) const sign = crypto.createSign('RSA-SHA1') diff --git a/src/lib/util.js b/src/lib/util.js index bd32d55..59ffc03 100644 --- a/src/lib/util.js +++ b/src/lib/util.js @@ -24,23 +24,24 @@ export async function normalizeTemplate (gitOrLocal) { } export function choose (opts) { - return new Promise((resolve) => { - inquirer.prompt( - [opts], - resolve - ) - }) + return inquirer.prompt([opts]).then(resolve => resolve()) + // return new Promise((resolve) => { + // inquirer.prompt( + // [opts], + // resolve + // ) + // }) } export function confirm (message, cb) { - inquirer.prompt([{ - type: 'confirm', - message: message, - name: 'confirm', - }], function (answers) { - if (answers.confirm) { - cb() - } + inquirer.prompt([ + { + type: 'confirm', + message: message, + name: 'confirm', + }, + ]).then(answers => { + answers.confirm && cb() }) } diff --git a/src/vendor/hook.js b/src/vendor/hook.js index 0d90fa4..609b276 100644 --- a/src/vendor/hook.js +++ b/src/vendor/hook.js @@ -1,7 +1,7 @@ const path = require('path') const ROOT_PATH = process.cwd() -const TEMP_PATH = path.join(ROOT_PATH, '_temp') -const config = require(path.join(TEMP_PATH, 'build/config')) +const DIST_PATH = path.join(ROOT_PATH, 'dist') +const config = require(path.join(ROOT_PATH, 'build/config')) /** * Run before pack, doing the stuff synchronized @@ -11,21 +11,20 @@ const config = require(path.join(TEMP_PATH, 'build/config')) */ exports.beforePack = function (utils) { const fse = utils.fse - const walletPath = path.join(TEMP_PATH, '/dist') - if (walletPath === path.join(config.build.assetsRoot)) { + if (DIST_PATH === path.join(config.build.assetsRoot)) { return } try { - fse.emptyDirSync(walletPath) + fse.emptyDirSync(DIST_PATH) } catch (err) { console.log('failed to empty resoure files') } try { - fse.copySync(path.join(config.build.assetsRoot), walletPath) - fse.copySync(config.build.index, path.join(walletPath, '/index.html')) + fse.copySync(path.join(config.build.assetsRoot), DIST_PATH) + fse.copySync(config.build.index, path.join(DIST_PATH, 'index.html')) } catch (err) { console.log('failed to copy resoure files') } diff --git a/test/fixtures/A-Plus-standard-project/build/config/compose-biz-apps.js b/test/fixtures/A-Plus-standard-project/build/config/compose-biz-apps.js deleted file mode 100644 index 38f8b28..0000000 --- a/test/fixtures/A-Plus-standard-project/build/config/compose-biz-apps.js +++ /dev/null @@ -1,8 +0,0 @@ -module.exports = { - // For you build: - // compose the biz-app name 'directory name' under src/biz-apps - // default empty means all the biz-apps - 'biz-apps': [], -} - - diff --git a/test/fixtures/A-Plus-standard-project/build/scripts/.gitkeep b/test/fixtures/A-Plus-standard-project/build/scripts/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/test/fixtures/A-Plus-standard-project/build/util/.gitkeep b/test/fixtures/A-Plus-standard-project/build/util/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/test/fixtures/A-Plus-standard-project/build/webpack/.gitkeep b/test/fixtures/A-Plus-standard-project/build/webpack/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/test/fixtures/A-Plus-standard-project/src/assets/icons/AlipayPlus_Logo.svg b/test/fixtures/A-Plus-standard-project/src/assets/icons/AlipayPlus_Logo.svg deleted file mode 100644 index 5797d94..0000000 --- a/test/fixtures/A-Plus-standard-project/src/assets/icons/AlipayPlus_Logo.svg +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - diff --git a/test/fixtures/A-Plus-standard-project/src/assets/icons/account.svg b/test/fixtures/A-Plus-standard-project/src/assets/icons/account.svg deleted file mode 100644 index a0e66dc..0000000 --- a/test/fixtures/A-Plus-standard-project/src/assets/icons/account.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/assets/icons/aplus.svg b/test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/assets/icons/aplus.svg deleted file mode 100644 index c3e521e..0000000 --- a/test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/assets/icons/aplus.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/constants/apis.js b/test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/constants/apis.js deleted file mode 100644 index bdc75ac..0000000 --- a/test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/constants/apis.js +++ /dev/null @@ -1,5 +0,0 @@ -// auto debit -export const AUTODEBIT_API1 = 'alipayplus.bizapp.autodebit.api1' -export const AUTODEBIT_API2 = 'alipayplus.bizapp.autodebit.api2' -export const AUTODEBIT_API3 = 'alipayplus.bizapp.autodebit.api3' -export const AUTODEBIT_API4 = 'alipayplus.bizapp.autodebit.api4' diff --git a/test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/constants/mutation-types.js b/test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/constants/mutation-types.js deleted file mode 100644 index 9c45008..0000000 --- a/test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/constants/mutation-types.js +++ /dev/null @@ -1 +0,0 @@ -export const UPDATE_SIGNING_INFO = 'UPDATE_SIGNING_INFO' diff --git a/test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/constants/pages.js b/test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/constants/pages.js deleted file mode 100644 index 1f98dfa..0000000 --- a/test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/constants/pages.js +++ /dev/null @@ -1,3 +0,0 @@ -export const AUTO_DEBIT_INDEX = 'AUTO_DEBIT_INDEX' -export const AUTO_DEBIT_LIST = 'AUTO_DEBIT_LIST' -export const AUTO_DEBIT_DETAIL = 'AUTO_DEBIT_DETAIL' diff --git a/test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/i18n/locales/en_US.js b/test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/i18n/locales/en_US.js deleted file mode 100644 index c186c55..0000000 --- a/test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/i18n/locales/en_US.js +++ /dev/null @@ -1,8 +0,0 @@ -/* eslint-disable */ - -export default { - // Auto Debit - 'auto.debit.title': 'Auto Debit', - 'bizapp.autodebit.title': 'Autodebit title', - 'autodebit.sign.times': 'autodebit vuex store signTimes: {{ times }}' -} diff --git a/test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/i18n/locales/zh_CN.js b/test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/i18n/locales/zh_CN.js deleted file mode 100644 index b968e2b..0000000 --- a/test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/i18n/locales/zh_CN.js +++ /dev/null @@ -1,8 +0,0 @@ -/* eslint-disable */ - -export default { - // Auto Debit - 'auto.debit.title': 'Auto Debit', - 'bizapp.autodebit.title': 'bizapp 的 autodebit', - 'autodebit.sign.times': 'autodebit vuex store 记录 signTimes: {{ times }}', -} diff --git a/test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/libs/index.js b/test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/libs/index.js deleted file mode 100644 index e69de29..0000000 diff --git a/test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/router/index.js b/test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/router/index.js deleted file mode 100644 index ecfaaad..0000000 --- a/test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/router/index.js +++ /dev/null @@ -1,27 +0,0 @@ -import * as pages from '../constants/pages' - -export default [ - { - meta: { - titleKey: 'auto.debit.title', - }, - name: pages.AUTO_DEBIT_INDEX, - path: '/autodebit', - component: r => require.ensure([], () => r(require('../views/index')), 'autodebit')}, - { - meta: { - titleKey: 'auto.debit.title', - }, - name: pages.AUTO_DEBIT_LIST, - path: '/autodebit/list', - component: r => require.ensure([], () => r(require('../views/list')), 'autodebit'), - }, - { - meta: { - titleKey: 'auto.debit.title', - }, - name: pages.AUTO_DEBIT_DETAIL, - path: '/autodebit/detail', - component: r => require.ensure([], () => r(require('../views/detail')), 'autodebit'), - }, -] diff --git a/test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/store/index.js b/test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/store/index.js deleted file mode 100644 index b948e86..0000000 --- a/test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/store/index.js +++ /dev/null @@ -1,19 +0,0 @@ -import { UPDATE_SIGNING_INFO } from '../constants/mutation-types' - -export default { - state: { - signTimes: 0, - }, - - mutations: { - [UPDATE_SIGNING_INFO] (state) { - state.signTimes ++ - }, - }, - - actions: { - }, - - getters: { - }, -} diff --git a/test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/styles/index.less b/test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/styles/index.less deleted file mode 100644 index 3b9d687..0000000 --- a/test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/styles/index.less +++ /dev/null @@ -1,21 +0,0 @@ -.autodebit { - header { - margin-top: .5rem; - text-align: center; - } - section { - text-align: center; - } - - p { - font-size: .3rem; - - &.title { - font-size: .4rem; - } - } - - div { - font-size: .3rem; - } -} diff --git a/test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/views/detail.vue b/test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/views/detail.vue deleted file mode 100644 index 368767c..0000000 --- a/test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/views/detail.vue +++ /dev/null @@ -1,50 +0,0 @@ - - diff --git a/test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/views/index.vue b/test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/views/index.vue deleted file mode 100644 index e4b2d95..0000000 --- a/test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/views/index.vue +++ /dev/null @@ -1,78 +0,0 @@ - - diff --git a/test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/views/list.vue b/test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/views/list.vue deleted file mode 100644 index 3b76d5d..0000000 --- a/test/fixtures/A-Plus-standard-project/src/biz-apps/autodebit/views/list.vue +++ /dev/null @@ -1,50 +0,0 @@ - - diff --git a/test/fixtures/A-Plus-standard-project/src/biz-apps/cashier/assets/icons/creditcard.svg b/test/fixtures/A-Plus-standard-project/src/biz-apps/cashier/assets/icons/creditcard.svg deleted file mode 100644 index 73f4efc..0000000 --- a/test/fixtures/A-Plus-standard-project/src/biz-apps/cashier/assets/icons/creditcard.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/test/fixtures/A-Plus-standard-project/src/biz-apps/cashier/constants/apis.js b/test/fixtures/A-Plus-standard-project/src/biz-apps/cashier/constants/apis.js deleted file mode 100644 index 6dc32f5..0000000 --- a/test/fixtures/A-Plus-standard-project/src/biz-apps/cashier/constants/apis.js +++ /dev/null @@ -1,2 +0,0 @@ -// cashier -export const CASHIER_API1 = 'alipayplus.bizapp.cashier.api1' \ No newline at end of file diff --git a/test/fixtures/A-Plus-standard-project/src/biz-apps/cashier/constants/mutation-types.js b/test/fixtures/A-Plus-standard-project/src/biz-apps/cashier/constants/mutation-types.js deleted file mode 100644 index 0285803..0000000 --- a/test/fixtures/A-Plus-standard-project/src/biz-apps/cashier/constants/mutation-types.js +++ /dev/null @@ -1 +0,0 @@ -export const ADD_CREDIT_CARD = 'ADD_CREDIT_CARD' diff --git a/test/fixtures/A-Plus-standard-project/src/biz-apps/cashier/constants/pages.js b/test/fixtures/A-Plus-standard-project/src/biz-apps/cashier/constants/pages.js deleted file mode 100644 index 6e0dc12..0000000 --- a/test/fixtures/A-Plus-standard-project/src/biz-apps/cashier/constants/pages.js +++ /dev/null @@ -1 +0,0 @@ -export const CASHIER_INDEX = 'CASHIER_INDEX' diff --git a/test/fixtures/A-Plus-standard-project/src/biz-apps/cashier/i18n/locales/en_US.js b/test/fixtures/A-Plus-standard-project/src/biz-apps/cashier/i18n/locales/en_US.js deleted file mode 100644 index 14d82f2..0000000 --- a/test/fixtures/A-Plus-standard-project/src/biz-apps/cashier/i18n/locales/en_US.js +++ /dev/null @@ -1,5 +0,0 @@ -export default { - 'cashier.title': 'cashier', - 'bizapp.cashier.title': 'Cashier title', - 'cashier.creditcards': 'cashier vuex store creditcards: {{ cards }}', -} diff --git a/test/fixtures/A-Plus-standard-project/src/biz-apps/cashier/i18n/locales/zh_CN.js b/test/fixtures/A-Plus-standard-project/src/biz-apps/cashier/i18n/locales/zh_CN.js deleted file mode 100644 index 0fe0694..0000000 --- a/test/fixtures/A-Plus-standard-project/src/biz-apps/cashier/i18n/locales/zh_CN.js +++ /dev/null @@ -1,5 +0,0 @@ -export default { - 'cashier.title': '收银台', - 'bizapp.cashier.title': 'bizapp 的 cashier', - 'cashier.creditcards': 'cashier vuex store creditcards: {{ cards }} 卡数', -} diff --git a/test/fixtures/A-Plus-standard-project/src/biz-apps/cashier/libs/index.js b/test/fixtures/A-Plus-standard-project/src/biz-apps/cashier/libs/index.js deleted file mode 100644 index e69de29..0000000 diff --git a/test/fixtures/A-Plus-standard-project/src/biz-apps/cashier/router/index.js b/test/fixtures/A-Plus-standard-project/src/biz-apps/cashier/router/index.js deleted file mode 100644 index b42de35..0000000 --- a/test/fixtures/A-Plus-standard-project/src/biz-apps/cashier/router/index.js +++ /dev/null @@ -1,12 +0,0 @@ -import * as pages from '../constants/pages' - -export default [ - { - meta: { - titleKey: 'cashier.title', - }, - name: pages.CASHIER_INDEX, - path: '/cashier', - component: r => require.ensure([], () => r(require('../views/index')), 'cashier'), - }, -] diff --git a/test/fixtures/A-Plus-standard-project/src/biz-apps/cashier/store/index.js b/test/fixtures/A-Plus-standard-project/src/biz-apps/cashier/store/index.js deleted file mode 100644 index d8e02af..0000000 --- a/test/fixtures/A-Plus-standard-project/src/biz-apps/cashier/store/index.js +++ /dev/null @@ -1,19 +0,0 @@ -import { ADD_CREDIT_CARD } from '../constants/mutation-types' - -export default { - state: { - creditCards: 1, - }, - - mutations: { - [ADD_CREDIT_CARD] (state) { - state.creditCards = state.creditCards * 2 - }, - }, - - actions: { - }, - - getters: { - }, -} diff --git a/test/fixtures/A-Plus-standard-project/src/biz-apps/cashier/styles/index.less b/test/fixtures/A-Plus-standard-project/src/biz-apps/cashier/styles/index.less deleted file mode 100644 index 5a921fe..0000000 --- a/test/fixtures/A-Plus-standard-project/src/biz-apps/cashier/styles/index.less +++ /dev/null @@ -1,10 +0,0 @@ -.cashier { - padding: 1rem; - header { - margin-top: .5rem; - text-align: center; - } - section { - text-align: center; - } -} diff --git a/test/fixtures/A-Plus-standard-project/src/biz-apps/cashier/views/index.vue b/test/fixtures/A-Plus-standard-project/src/biz-apps/cashier/views/index.vue deleted file mode 100644 index 8a4dc76..0000000 --- a/test/fixtures/A-Plus-standard-project/src/biz-apps/cashier/views/index.vue +++ /dev/null @@ -1,32 +0,0 @@ - - diff --git a/test/fixtures/A-Plus-standard-project/src/components/icon.vue b/test/fixtures/A-Plus-standard-project/src/components/icon.vue deleted file mode 100644 index d236470..0000000 --- a/test/fixtures/A-Plus-standard-project/src/components/icon.vue +++ /dev/null @@ -1,40 +0,0 @@ - - - diff --git a/test/fixtures/A-Plus-standard-project/src/components/index.js b/test/fixtures/A-Plus-standard-project/src/components/index.js deleted file mode 100644 index cfdbcbd..0000000 --- a/test/fixtures/A-Plus-standard-project/src/components/index.js +++ /dev/null @@ -1,5 +0,0 @@ -import icon from '~components/icon.vue' - -export default { - icon, -} diff --git a/test/fixtures/A-Plus-standard-project/src/components/typer.vue b/test/fixtures/A-Plus-standard-project/src/components/typer.vue deleted file mode 100644 index 5bf3dd0..0000000 --- a/test/fixtures/A-Plus-standard-project/src/components/typer.vue +++ /dev/null @@ -1,86 +0,0 @@ - - - diff --git a/test/fixtures/A-Plus-standard-project/src/constants/apis.js b/test/fixtures/A-Plus-standard-project/src/constants/apis.js deleted file mode 100644 index 884f7f4..0000000 --- a/test/fixtures/A-Plus-standard-project/src/constants/apis.js +++ /dev/null @@ -1 +0,0 @@ -export const API_INIT = 'test.rpc.or.http' diff --git a/test/fixtures/A-Plus-standard-project/src/constants/errors.js b/test/fixtures/A-Plus-standard-project/src/constants/errors.js deleted file mode 100644 index b1298e3..0000000 --- a/test/fixtures/A-Plus-standard-project/src/constants/errors.js +++ /dev/null @@ -1,7 +0,0 @@ -export const TIMEOUT_ERROR = 'timeout' -export const NETWORK_ERROR = 'network' -export const SYSTEM_ERROR = 'system' -export const LOGIN_ERROR = 'login' - -// RPC error -export const GATEWAY_ERROR = 'gateway' diff --git a/test/fixtures/A-Plus-standard-project/src/constants/index.js b/test/fixtures/A-Plus-standard-project/src/constants/index.js deleted file mode 100644 index 7556a6a..0000000 --- a/test/fixtures/A-Plus-standard-project/src/constants/index.js +++ /dev/null @@ -1,5 +0,0 @@ -/** - * This file is for container app constants - */ -export const basePath = '/' - diff --git a/test/fixtures/A-Plus-standard-project/src/constants/mutation-types.js b/test/fixtures/A-Plus-standard-project/src/constants/mutation-types.js deleted file mode 100644 index 26a84e7..0000000 --- a/test/fixtures/A-Plus-standard-project/src/constants/mutation-types.js +++ /dev/null @@ -1,8 +0,0 @@ -/** - * This file is for common vuex constants - */ -export const SET_ERROR_MSG = 'SET_ERROR_MSG' - -export const SET_SECURITY_CONTEXT = 'SET_SECURITY_CONTEXT' - -export const SET_CACHED_PAYMENT_GUIDE = 'SET_CACHED_PAYMENT_GUIDE' diff --git a/test/fixtures/A-Plus-standard-project/src/constants/pages.js b/test/fixtures/A-Plus-standard-project/src/constants/pages.js deleted file mode 100644 index 0e2bd49..0000000 --- a/test/fixtures/A-Plus-standard-project/src/constants/pages.js +++ /dev/null @@ -1,3 +0,0 @@ -export const ERROR = 'error' -export const HOME = 'home' -export const NOT_FOUND = 'not found' diff --git a/test/fixtures/A-Plus-standard-project/src/ejs-templates/.gitkeep b/test/fixtures/A-Plus-standard-project/src/ejs-templates/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/test/fixtures/A-Plus-standard-project/src/entry/index.js b/test/fixtures/A-Plus-standard-project/src/entry/index.js deleted file mode 100644 index 30d88d3..0000000 --- a/test/fixtures/A-Plus-standard-project/src/entry/index.js +++ /dev/null @@ -1,18 +0,0 @@ - -import Vue from '~libs/vue-init' -import App from '~views/index' -import router from '~router/index' -import store from '~store/index' -import { language, langPkgs } from '~i18n/index' -import '~styles/index.less' - -langPkgs[language]((i18n) => { - window.i18n = i18n.default - const app = new Vue({ - ...App, - router, - store, - }) - app.$mount('#app') -}) - diff --git a/test/fixtures/A-Plus-standard-project/src/i18n/index.js b/test/fixtures/A-Plus-standard-project/src/i18n/index.js deleted file mode 100644 index aa5b54c..0000000 --- a/test/fixtures/A-Plus-standard-project/src/i18n/index.js +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Default language - */ -const _default = 'en_US' - -/** - * detected language - */ -const _lang = getLang() || _default - -export const langPkgs = { - 'en_US': r => require.ensure([], () => r(require('./locales/en_US')), 'en_US'), - 'zh_CN': r => require.ensure([], () => r(require('./locales/zh_CN')), 'zh_CN'), -} - -export const language = langPkgs.hasOwnProperty(_lang) ? _lang : _default - -function getLang () { - const localeMatches = navigator.userAgent.match(/Language\/([\w-]+)/) - const locale = localeMatches ? localeMatches[1] : navigator.language - - if (/zh[_-](cn|hans)/i.test(locale)) { - return 'zh_CN' - } else if (/zh[_-](hk|tw|hant)/i.test(locale)) { - return 'zh_HK' - } else if (/en/i.test(locale)) { - return 'en_US' - } - - return '' -} diff --git a/test/fixtures/A-Plus-standard-project/src/i18n/locales/en_US.js b/test/fixtures/A-Plus-standard-project/src/i18n/locales/en_US.js deleted file mode 100644 index a1664d9..0000000 --- a/test/fixtures/A-Plus-standard-project/src/i18n/locales/en_US.js +++ /dev/null @@ -1,7 +0,0 @@ -import autodebit from '~biz-apps/autodebit/i18n/locales/en_US' - -export default Object.assign({}, autodebit, { - 'index.title': 'Alipay Plus Front-End Scaffold', - 'index.bizapp': 'Here are the biz-apps', - 'index.msg': 'Built with vue, webpack', -}) diff --git a/test/fixtures/A-Plus-standard-project/src/i18n/locales/zh_CN.js b/test/fixtures/A-Plus-standard-project/src/i18n/locales/zh_CN.js deleted file mode 100644 index b43400a..0000000 --- a/test/fixtures/A-Plus-standard-project/src/i18n/locales/zh_CN.js +++ /dev/null @@ -1,7 +0,0 @@ -import autodebit from '~biz-apps/autodebit/i18n/locales/zh_CN' - -export default Object.assign({}, autodebit, { - 'index.title': 'A+前端工程模板', - 'index.bizapp': '采用 biz-apps 的架构', - 'index.msg': '基于 vue, webpack', -}) diff --git a/test/fixtures/A-Plus-standard-project/src/libs/vue-init.js b/test/fixtures/A-Plus-standard-project/src/libs/vue-init.js deleted file mode 100644 index a8db555..0000000 --- a/test/fixtures/A-Plus-standard-project/src/libs/vue-init.js +++ /dev/null @@ -1,38 +0,0 @@ -import 'es6-promise/auto' -import FastClick from 'fastclick' -import Vue from 'vue' -import * as filters from '~utils/filters' -import * as directives from '~utils/directives' -import gettext from '~utils/gettext' -import components from '~components/index' - -/** - * install gettext - */ -Vue.use(gettext) - -// Init FastClick -FastClick.attach(document.body) - -/** - * Register global filter for all views - */ -for (let key in filters) { - Vue.filter(key, filters[key]) -} - -/** - * Register global directive for all views - */ -for (let key in directives) { - Vue.directive(key, directives[key]) -} - -/** - * Register global component for all views - */ -for (let key in components) { - Vue.component(key, components[key]) -} - -export default Vue diff --git a/test/fixtures/A-Plus-standard-project/src/router/index.js b/test/fixtures/A-Plus-standard-project/src/router/index.js deleted file mode 100644 index 1d7b304..0000000 --- a/test/fixtures/A-Plus-standard-project/src/router/index.js +++ /dev/null @@ -1,46 +0,0 @@ -import Vue from 'vue' -import Router from 'vue-router' -import { basePath } from '~constants/index' -import { HOME, ERROR, NOT_FOUND } from '~constants/pages' -import autodebit from '~biz-apps/autodebit/router/index' -import home from '~views/home' -import { gettext } from '~utils/gettext' -import jsbridge from '~utils/jsbridge' - -Vue.use(Router) - -const routes = [ - { - meta: { - titleKey: 'index.title', - }, - name: HOME, - path: '/', - component: home, - }, - { - name: ERROR, - path: '/error', - component: r => - require.ensure([], () => r(require('~views/error')), 'error'), - }, - { - name: NOT_FOUND, - path: '*', - component: r => require.ensure([], () => r(require('~views/404')), '404'), - }, -].concat(autodebit) - -const router = new Router({ - mode: 'history', - base: basePath, - routes, -}) - -router.afterEach(route => { - const meta = route.meta || {} - const title = gettext(meta.titleKey || 'index.title') - jsbridge.setTitle(title) -}) - -export default router diff --git a/test/fixtures/A-Plus-standard-project/src/store/index.js b/test/fixtures/A-Plus-standard-project/src/store/index.js deleted file mode 100644 index 63d0050..0000000 --- a/test/fixtures/A-Plus-standard-project/src/store/index.js +++ /dev/null @@ -1,11 +0,0 @@ -import Vue from 'vue' -import Vuex from 'vuex' -import autodebit from '~biz-apps/autodebit/store' - -Vue.use(Vuex) - -export default new Vuex.Store({ - modules: { - autodebit, - }, -}) diff --git a/test/fixtures/A-Plus-standard-project/src/styles/components/typer.less b/test/fixtures/A-Plus-standard-project/src/styles/components/typer.less deleted file mode 100644 index 6a941db..0000000 --- a/test/fixtures/A-Plus-standard-project/src/styles/components/typer.less +++ /dev/null @@ -1,27 +0,0 @@ -.slogan { - padding: .4rem; - font-family: "Raleway", sans-serif; - font-size: .36rem; - font-weight: 500; - line-height: .44rem; - letter-spacing: .03rem; - color: #999; - text-align: center; - - .typed-cursor { - opacity: 1; - animation: blink 0.7s infinite; - } -} - -@keyframes blink { - 0% { - opacity: 1; - } - 50% { - opacity: 0; - } - 100% { - opacity: 1; - } -} diff --git a/test/fixtures/A-Plus-standard-project/src/styles/index.less b/test/fixtures/A-Plus-standard-project/src/styles/index.less deleted file mode 100644 index 1cc9bc0..0000000 --- a/test/fixtures/A-Plus-standard-project/src/styles/index.less +++ /dev/null @@ -1,22 +0,0 @@ -// This is used by scaffold project, you could delete this and the file -@import './components/typer.less'; -@import '../biz-apps/autodebit/styles/index.less'; - -.home { - header, - section { - text-align: center; - } - - p { - font-size: .3rem; - - &.title { - font-size: .4rem; - } - } - - div { - font-size: .3rem; - } -} diff --git a/test/fixtures/A-Plus-standard-project/src/utils/load-icons.js b/test/fixtures/A-Plus-standard-project/src/utils/load-icons.js deleted file mode 100644 index 124a827..0000000 --- a/test/fixtures/A-Plus-standard-project/src/utils/load-icons.js +++ /dev/null @@ -1,7 +0,0 @@ -const allIcons = require.context('~assets/icons', true, /\.(svg|png)$/) -const autodebitIcons = require.context('~biz-apps/autodebit/assets/icons', true, /\.(svg|png)$/) -function importAll (r) { - r.keys().forEach(r) -} -importAll(allIcons) -importAll(autodebitIcons) diff --git a/test/fixtures/A-Plus-standard-project/src/views/index.vue b/test/fixtures/A-Plus-standard-project/src/views/index.vue deleted file mode 100644 index ba44166..0000000 --- a/test/fixtures/A-Plus-standard-project/src/views/index.vue +++ /dev/null @@ -1,14 +0,0 @@ - - - diff --git a/test/scripts/test-bizapp-compose.js b/test/scripts/test-bizapp-compose.js deleted file mode 100644 index e7f5276..0000000 --- a/test/scripts/test-bizapp-compose.js +++ /dev/null @@ -1,92 +0,0 @@ -const chai = require('chai') -const { resolve, join } = require('path') -const { tmpdir } = require('os') -const fse = require('fs-extra') -const { - composeApps, -} = require('../../dist') - -chai.use(require('chai-fs')) - -const assert = chai.assert -const tmpDir = join(tmpdir(), './A-Plus-standard-project') -const source = resolve(__dirname, '../fixtures/A-Plus-standard-project') -const allApps = fse.readdirSync(join(source, './src')) - -describe('apfe-bizapp-compose', function () { - before(function () { - fse.copySync(source, tmpDir) - }) - - it('compose biz-app all, it should change the files', function (done) { - const ctx = this - const apps = ['autodebit', 'cashier'] - composeApps(resolve(tmpDir, './src'), {}, ...apps) - .then(function () { - ctx.routerContent = assertImports('router', apps) - ctx.storeContent = assertImports('store', apps) - done() - }) - .catch(done) - }) - - it('compose biz-app all again, it should not change the files', function (done) { - const apps = ['autodebit', 'cashier'] - const ctx = this - composeApps(resolve(tmpDir, './src'), {}, ...apps) - .then(function () { - assertSameContent('router', ctx.routerContent) - assertSameContent('store', ctx.storeContent) - done() - }) - .catch(done) - }) - - it('compose biz-app only cashier, it should only contains the cashier logic', function (done) { - const apps = ['cashier'] - const ctx = this - composeApps(resolve(tmpDir, './src'), {}, ...apps) - .then(function () { - ctx.routerContent = assertImports('router', apps) - ctx.storeContent = assertImports('store', apps) - done() - }) - .catch(done) - }) - - after(function () { - fse.removeSync(tmpDir) - }) -}) - -const getImportContentReg = (importPath, app) => { - return new RegExp(`.*import ${app} from '~biz-apps/${app}/${importPath}.*'.*`) -} - -const unusedApps = apps => { - const usedSet = new Set(apps) - return allApps.filter(app => usedSet.has(app)) -} - -const assertImports = (importPath, apps) => { - const filePath = join(tmpDir, `./src/${importPath}/index.js`) - const assertMatch = ifMatch => app => { - const fn = ifMatch ? assert.fileContentMatch : assert.notFileContentMatch - return fn.call( - null, - filePath, - getImportContentReg(importPath, app) - ) - } - - apps.forEach(assertMatch(true)) - unusedApps(apps).forEach(assertMatch(false)) - - return fse.readFileSync(filePath, 'utf8') -} - -const assertSameContent = (importPath, origin) => { - const filePath = join(tmpDir, `./src/${importPath}/index.js`) - assert.fileContent(filePath, origin) -} -