diff --git a/.eslintrc b/.eslintrc index 370fb68..7c05da9 100644 --- a/.eslintrc +++ b/.eslintrc @@ -3,17 +3,5 @@ "parserOptions": { "project": "./tsconfig.json", "createDefaultProgram": true - }, - "rules": { - "prefer-spread": "off", - "no-return-assign": "off", - "no-case-declarations": "off", - "prefer-const": "off", - "no-regex-spaces": "off", - "no-return-await": "off", - "@typescript-eslint/no-unused-vars": "off", - "@typescript-eslint/no-use-before-define": "off", - "@typescript-eslint/no-empty-function": "off", - "@typescript-eslint/no-var-requires": "off" } } diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..7185109 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,19 @@ +name: Release +on: + # 合并后自动发布 + # push: + # branches: [ master, main, next, beta, '*.x' ] + + # 手动发布 + workflow_dispatch: {} + +jobs: + release: + name: Node.js + uses: artusjs/github-actions/.github/workflows/node-release.yml@v1 + secrets: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + GIT_TOKEN: ${{ secrets.GIT_TOKEN }} + # with: + # checkTest: false + # dryRun: true \ No newline at end of file diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..9cf9495 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +package-lock=false \ No newline at end of file diff --git a/README.md b/README.md index e6706ef..d2621f9 100644 --- a/README.md +++ b/README.md @@ -1,40 +1,36 @@ -# artus-cli/template +# @artus-cli/plugin-help -template repository for artus-cli +Built-in plugin for showing help information in artus-cli - +[![NPM version](https://img.shields.io/npm/v/@artus-cli/plugin-help.svg?style=flat-square)](https://npmjs.org/package/@artus-cli/plugin-help) +[![NPM quality](https://img.shields.io/npms-io/final-score/@artus-cli/plugin-help.svg?style=flat-square)](https://npmjs.org/package/@artus-cli/plugin-help) +[![NPM download](https://img.shields.io/npm/dm/@artus-cli/plugin-help.svg?style=flat-square)](https://npmjs.org/package/@artus-cli/plugin-help) +[![Continuous Integration](https://github.com/artus-cli/plugin-help/actions/workflows/ci.yml/badge.svg)](https://github.com/artus-cli/plugin-help/actions/workflows/ci.yml) +[![Test coverage](https://img.shields.io/codecov/c/github/artus-cli/plugin-help.svg?style=flat-square)](https://codecov.io/gh/artus-cli/plugin-help) +[![Oss Insight Analytics](https://img.shields.io/badge/OssInsight-artus--cli%2Fartus--cli-blue.svg?style=flat-square)](https://ossinsight.io/analyze/artus-cli/plugin-help) -[![NPM version](https://img.shields.io/npm/v/@artus-cli/artus-cli.svg?style=flat-square)](https://npmjs.org/package/@artus-cli/artus-cli) -[![NPM quality](https://img.shields.io/npms-io/final-score/@artus-cli/artus-cli.svg?style=flat-square)](https://npmjs.org/package/@artus-cli/artus-cli) -[![NPM download](https://img.shields.io/npm/dm/@artus-cli/artus-cli.svg?style=flat-square)](https://npmjs.org/package/@artus-cli/artus-cli) -[![Continuous Integration](https://github.com/artus-cli/artus-cli/actions/workflows/ci.yml/badge.svg)](https://github.com/artus-cli/artus-cli/actions/workflows/ci.yml) -[![Test coverage](https://img.shields.io/codecov/c/github/artus-cli/artus-cli.svg?style=flat-square)](https://codecov.io/gh/artus-cli/artus-cli) -[![Oss Insight Analytics](https://img.shields.io/badge/OssInsight-artus--cli%2Fartus--cli-blue.svg?style=flat-square)](https://ossinsight.io/analyze/artus-cli/artus-cli) - - -## Usage +## Install ```sh -# print help -$ my-bin --help - -# run dev -$ my-bin dev --port=8080 +$ npm i @artus-cli/plugin-help ``` -## Commands - -### dev - +## Usage -### debug +```ts +// plugin.ts +export default { + help: { + enable: true, + package: '@artus-cli/plugin-help', + }, +}; +``` ## Contributing ```sh $ npm test $ npm run cov - -$ npx ts-node src/bin/cli.ts dev --port=8080 ``` diff --git a/package.json b/package.json index 9aa962b..37321f9 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { - "name": "@artus-cli/template", - "version": "0.0.0", - "description": "artus-cli template", + "name": "@artus-cli/plugin-help", + "version": "0.0.1-beta.1", + "description": "show help information for @artus-cli", "homepage": "", "author": "", "main": "dist/index.js", @@ -25,7 +25,7 @@ "prepack": "npm run tsc" }, "dependencies": { - "@artus-cli/artus-cli": "beta" + "tslib": "^2.4.0" }, "devDependencies": { "@artus/eslint-config-artus": "^0.0.1", @@ -38,13 +38,13 @@ "mocha": "^10.0.0", "ts-mocha": "^10.0.0", "ts-node": "^10.9.1", + "@artus-cli/artus-cli": "latest", "tsconfig-paths": "^4.1.1", - "tslib": "^2.4.0", "typescript": "^4.8.2" }, "repository": { "type": "git", - "url": "" + "url": "https://github.com/artus-cli/plugin-help" }, "files": [ "dist" @@ -55,6 +55,7 @@ "keywords": [ "artus", "artus-cli", + "artus-cli-plugin", "command-line-app", "cli", "commander" diff --git a/src/cmd/main.ts b/src/cmd/main.ts deleted file mode 100644 index ca24424..0000000 --- a/src/cmd/main.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { DefineCommand, Command, Option, DefineOption } from '@artus-cli/artus-cli'; - -interface MainOption extends Option { - params?: string[]; -} - -@DefineCommand({ - command: '$0 [params...]', -}) -export class MainCommand extends Command { - @DefineOption() - args: MainOption; - - async run() { - console.info('main', this.args.params.join(',')); - } -} diff --git a/src/config/plugin.ts b/src/config/plugin.ts deleted file mode 100644 index 832e840..0000000 --- a/src/config/plugin.ts +++ /dev/null @@ -1,6 +0,0 @@ -export default { - // checkUpdate: { - // enable: true, - // package: 'plugin-check-update', - // }, -}; diff --git a/src/help.ts b/src/help.ts new file mode 100644 index 0000000..abf89e8 --- /dev/null +++ b/src/help.ts @@ -0,0 +1,79 @@ +import { Option, DefineCommand, Command, DefineOption, Inject, CommandContext, Program } from '@artus-cli/artus-cli'; +import commandLineUsage from 'command-line-usage'; + +interface HelpOption extends Option { + command: string; +} + +@DefineCommand({ + command: 'help [command]', + description: 'show help infomation for command', + alias: 'h', +}) +export class HelpCommand extends Command { + @Inject() + ctx: CommandContext; + + @Inject() + program: Program; + + @DefineOption() + option: HelpOption; + + async run() { + const ctx = this.ctx; + const { binName: bin } = this.program; + const command = this.option.command || bin; + const commandUid = command.startsWith(bin) ? command : `${bin} ${command}`; + const helpCommand = ctx.commands.get(commandUid) || ctx.rootCommand; + + // display help informations + const displayTexts: string[] = []; + const commandLineUsageList: any[] = []; + const optionKeys = helpCommand.options ? Object.keys(helpCommand.options) : []; + + // usage info in first line + displayTexts.push(`Usage: ${helpCommand.command.startsWith(bin) ? '' : `${bin} `}${helpCommand.command}`); + if (helpCommand.description) { + displayTexts.push('', helpCommand.description); + } + + // available commands, display all subcommands if match the root command + const availableCommands = ( + helpCommand.isRoot + ? Array.from(new Set(ctx.commands.values())) + : [ helpCommand ].concat(helpCommand.childs || []) + ).filter(c => !c.isRoot && c.isRunable); + + if (availableCommands.length) { + commandLineUsageList.push({ + header: 'Available Commands', + content: availableCommands.map(command => ({ + name: command.command, + summary: command.description, + })), + }); + } + + // options list, like -h, --help / -v, --version ... + commandLineUsageList.push({ + header: 'Options', + optionList: optionKeys + .map(flag => { + const option = helpCommand.options[flag]; + const showFlag = flag[0].toLowerCase() + flag.substring(1).replace(/[A-Z]/g, '-$&').toLowerCase(); + return { + name: showFlag, + type: { name: option.type }, + description: option.description, + alias: option.alias, + defaultValue: option.default, + }; + }), + }); + + // use command-line-usage to format help informations. + displayTexts.push(commandLineUsage(commandLineUsageList)); + console.info(displayTexts.join('\n')); + } +} diff --git a/src/index.ts b/src/index.ts index c0cc167..b658848 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,2 +1 @@ -export * from './cmd/dev'; -export * from './cmd/debug'; +export * from './help'; diff --git a/src/lifecycle.ts b/src/lifecycle.ts new file mode 100644 index 0000000..8ad7b4e --- /dev/null +++ b/src/lifecycle.ts @@ -0,0 +1,37 @@ +import { Inject, ApplicationLifecycle, LifecycleHook, LifecycleHookUnit, Program, CommandContext, Utils } from '@artus-cli/artus-cli'; + +@LifecycleHookUnit() +export default class UsageLifecycle implements ApplicationLifecycle { + @Inject() + private readonly program: Program; + + @LifecycleHook() + async configDidLoad() { + // add global options + this.program.option({ + help: { + type: 'boolean', + description: 'Show Help', + alias: 'h', + }, + }); + + this.program.use(async (ctx: CommandContext, next) => { + const { binName: bin } = this.program; + const { fuzzyMatched, matched, args, raw } = ctx; + if (!fuzzyMatched || !args.help) { + if (!matched) { + // can not match any command + console.error(`\n Command not found: '${bin} ${raw.join(' ')}', try '${fuzzyMatched?.cmds.join(' ') || bin} --help' for more information.\n`); + process.exit(1); + } + + return next(); + } + + // redirect to help command + const utils = ctx.container.get(Utils); + await utils.redirect([ 'help', fuzzyMatched.uid ]); + }); + } +} diff --git a/src/meta.json b/src/meta.json new file mode 100644 index 0000000..084a60b --- /dev/null +++ b/src/meta.json @@ -0,0 +1,3 @@ +{ + "name": "help" +} diff --git a/test/cmd/debug.test.ts b/test/cmd/debug.test.ts deleted file mode 100644 index a684221..0000000 --- a/test/cmd/debug.test.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { run } from '../test-utils'; - -describe('test/debug.test.ts', () => { - it('debug', async () => { - await run('debug --port=80 --flags=1') - // .debug() - .expect('stdout', /inspect true/) - .expect('stdout', /port 80/) - .expect('stdout', /flags 1 number/) - .end(); - }); - - it('inspect alias', async () => { - await run('inspect') - // .debug() - .expect('stdout', /inspect true/) - .expect('stdout', /flags 0 number/) - .end(); - }); -}); diff --git a/test/cmd/dev.test.ts b/test/cmd/dev.test.ts deleted file mode 100644 index 72193a7..0000000 --- a/test/cmd/dev.test.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { run } from '../test-utils'; - -describe('test/dev.test.ts', () => { - it('dev', async () => { - await run('dev --port=80 --nodeFlags=--experimental-vm-modules') - // .debug() - .expect('stdout', /port 80/) - .expect('stdout', /inspect false boolean/) - .expect('stdout', /nodeFlags --experimental-vm-module/) - .end(); - }); - - it('dev with baseDir', async () => { - await run('dev ./src -p=80') - // .debug() - .expect('stdout', /port 80/) - .expect('stdout', /baseDir .\/src/) - .end(); - }); -}); diff --git a/test/cmd/main.test.ts b/test/cmd/main.test.ts deleted file mode 100644 index 3a17ac2..0000000 --- a/test/cmd/main.test.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { run } from '../test-utils'; - -describe('test/main.test.ts', () => { - it('should fallback', async () => { - await run('a b c') - // .debug() - .expect('stdout', /main a,b,c/) - .end(); - }); -}); diff --git a/test/fixtures/README.md b/test/fixtures/README.md deleted file mode 100644 index e69de29..0000000 diff --git a/src/bin/cli.ts b/test/fixtures/my-bin/bin/cli.ts similarity index 98% rename from src/bin/cli.ts rename to test/fixtures/my-bin/bin/cli.ts index 8b89046..f72d41b 100644 --- a/src/bin/cli.ts +++ b/test/fixtures/my-bin/bin/cli.ts @@ -1,5 +1,4 @@ #!/usr/bin/env node import { start } from '@artus-cli/artus-cli'; - start(); diff --git a/test/fixtures/my-bin/cmd/cov.ts b/test/fixtures/my-bin/cmd/cov.ts new file mode 100644 index 0000000..b1e14b4 --- /dev/null +++ b/test/fixtures/my-bin/cmd/cov.ts @@ -0,0 +1,24 @@ +import { DefineCommand, DefineOption } from '@artus-cli/artus-cli'; +import { TestCommand, TestOption } from './test'; + +interface CovOption extends TestOption { + c8?: boolean; +} + +@DefineCommand({ + command: 'cov [file...]', + description: 'Run the coverage', +}) +export class CovCommand extends TestCommand { + @DefineOption({ + c8: { + type: 'boolean', + default: true, + }, + }) + args: CovOption; + + async run() { + // nothing + } +} diff --git a/src/cmd/debug.ts b/test/fixtures/my-bin/cmd/debug.ts similarity index 54% rename from src/cmd/debug.ts rename to test/fixtures/my-bin/cmd/debug.ts index 2c88342..bd9739b 100644 --- a/src/cmd/debug.ts +++ b/test/fixtures/my-bin/cmd/debug.ts @@ -7,16 +7,10 @@ interface DebugOption extends DevOption { @DefineCommand({ command: 'debug [baseDir]', - alias: [ 'inspect' ], description: 'Run the development server at debug mode', }) export class DebugCommand extends DevCommand { @DefineOption({ - inspect: { - type: 'boolean', - default: true, - description: 'Debug with node-inspector', - }, flags: { type: 'number', alias: 'f', @@ -26,13 +20,6 @@ export class DebugCommand extends DevCommand { args: DebugOption; async run() { - console.info('port', this.args.port); - console.info('inspect', this.args.inspect); - console.info('flags', this.args.flags, typeof this.args.flags); - console.info('baseDir', this.args.baseDir); - return { - command: 'debug', - args: this.args, - }; + // nothing } } diff --git a/src/cmd/dev.ts b/test/fixtures/my-bin/cmd/dev.ts similarity index 71% rename from src/cmd/dev.ts rename to test/fixtures/my-bin/cmd/dev.ts index 0d764fd..bfaa9cc 100644 --- a/src/cmd/dev.ts +++ b/test/fixtures/my-bin/cmd/dev.ts @@ -10,6 +10,7 @@ export interface DevOption extends Option { @DefineCommand({ command: 'dev [baseDir]', description: 'Run the development server', + alias: [ 'd' ], }) export class DevCommand extends Command { @DefineOption({ @@ -33,13 +34,6 @@ export class DevCommand extends Command { args: DevOption; async run() { - console.info('port', this.args.port); - console.info('inspect', this.args.inspect, typeof this.args.inspect); - console.info('nodeFlags', this.args.nodeFlags); - console.info('baseDir', this.args.baseDir); - return { - command: 'dev', - args: this.args, - }; + // nothing } } diff --git a/test/fixtures/my-bin/cmd/main.ts b/test/fixtures/my-bin/cmd/main.ts new file mode 100644 index 0000000..561d892 --- /dev/null +++ b/test/fixtures/my-bin/cmd/main.ts @@ -0,0 +1,8 @@ +import { DefineCommand, Command } from '@artus-cli/artus-cli'; + +@DefineCommand() +export class MainCommand extends Command { + async run() { + console.info('main'); + } +} diff --git a/test/fixtures/my-bin/cmd/test.ts b/test/fixtures/my-bin/cmd/test.ts new file mode 100644 index 0000000..963b091 --- /dev/null +++ b/test/fixtures/my-bin/cmd/test.ts @@ -0,0 +1,21 @@ +import { DefineCommand, DefineOption, Command, Option } from '@artus-cli/artus-cli'; + +export interface TestOption extends Option { + baseDir: string; + file: string[] +} + +@DefineCommand({ + command: 'test [file...]', + description: 'Run the unitest', + alias: [ 't' ], +}) +export class TestCommand extends Command { + @DefineOption() + options: TestOption; + + async run() { + console.info('test baseDir', this.options.baseDir); + console.info('test files', this.options.file); + } +} diff --git a/src/config/framework.ts b/test/fixtures/my-bin/config/framework.ts similarity index 100% rename from src/config/framework.ts rename to test/fixtures/my-bin/config/framework.ts diff --git a/test/fixtures/my-bin/config/plugin.ts b/test/fixtures/my-bin/config/plugin.ts new file mode 100644 index 0000000..3bef3ce --- /dev/null +++ b/test/fixtures/my-bin/config/plugin.ts @@ -0,0 +1,8 @@ +import path from 'node:path'; + +export default { + help: { + enable: true, + path: path.resolve(__dirname, '../../../../src'), + }, +}; diff --git a/test/fixtures/my-bin/package.json b/test/fixtures/my-bin/package.json new file mode 100644 index 0000000..aab8077 --- /dev/null +++ b/test/fixtures/my-bin/package.json @@ -0,0 +1,6 @@ +{ + "name": "my-bin", + "version": "1.0.0", + "type": "commonjs", + "bin": "./bin/cli.js" +} diff --git a/test/fixtures/other-bin/bin/cli.ts b/test/fixtures/other-bin/bin/cli.ts new file mode 100644 index 0000000..f72d41b --- /dev/null +++ b/test/fixtures/other-bin/bin/cli.ts @@ -0,0 +1,4 @@ +#!/usr/bin/env node + +import { start } from '@artus-cli/artus-cli'; +start(); diff --git a/test/fixtures/other-bin/config/framework.ts b/test/fixtures/other-bin/config/framework.ts new file mode 100644 index 0000000..2e2085e --- /dev/null +++ b/test/fixtures/other-bin/config/framework.ts @@ -0,0 +1,5 @@ +import path from 'path'; + +export default { + path: path.resolve(__dirname, '../../my-bin'), +}; diff --git a/test/fixtures/other-bin/package.json b/test/fixtures/other-bin/package.json new file mode 100644 index 0000000..d7efc66 --- /dev/null +++ b/test/fixtures/other-bin/package.json @@ -0,0 +1,6 @@ +{ + "name": "other-bin", + "version": "1.0.0", + "type": "commonjs", + "bin": "./bin/cli.js" +} diff --git a/test/index.test.ts b/test/index.test.ts index 63f658e..604a639 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -2,9 +2,88 @@ import { run } from './test-utils'; describe('test/index.test.ts', () => { it('should --help', async () => { - await run('--help') + await run('my-bin', '--help') // .debug() + .expect('stdout', /Usage: my-bin/) .expect('stdout', /Available Commands/) + .expect('stdout', /help \[command\]\s+show help infomation for command/) + .expect('stdout', /test \ \[file\.\.\.\]\s+Run the unitest/) + .expect('stdout', /cov \ \[file\.\.\.\]\s+Run the coverage/) + .expect('stdout', /dev \[baseDir\]\s+Run the development server/) + .expect('stdout', /debug \[baseDir\]\s+Run the development server at debug mode/) + .expect('stdout', /Options/) + .expect('stdout', /-h, --help\s+Show Help/) + .end(); + }); + + it('should subcommand --help', async () => { + await run('my-bin', 'dev -h') + .debug() + .expect('stdout', /Available Commands/) + .notExpect('stdout', /help \[command\]\s+show help infomation for command/) + .notExpect('stdout', /test \ \[file\.\.\.\]\s+Run the unitest/) + .notExpect('stdout', /cov \ \[file\.\.\.\]\s+Run the coverage/) + .expect('stdout', /dev \[baseDir\]\s+Run the development server/) + .expect('stdout', /Options/) + .expect('stdout', /--inspect\s+Debug with node-inspector/) + .expect('stdout', /--node-flags string/) + .expect('stdout', /-h, --help\s+Show Help/) + .end(); + }); + + it('should use help command', async () => { + await run('my-bin', 'help') + // .debug() + .expect('stdout', /Available Commands/) + .expect('stdout', /help \[command\]\s+show help infomation for command/) + .expect('stdout', /test \ \[file\.\.\.\]\s+Run the unitest/) + .expect('stdout', /cov \ \[file\.\.\.\]\s+Run the coverage/) + .expect('stdout', /dev \[baseDir\]\s+Run the development server/) + .expect('stdout', /debug \[baseDir\]\s+Run the development server at debug mode/) + .expect('stdout', /Options/) + .expect('stdout', /-h, --help\s+Show Help/) + .end(); + + await run('my-bin', 'help dev') + // .debug() + .expect('stdout', /Available Commands/) + .notExpect('stdout', /help \[command\]\s+show help infomation for command/) + .notExpect('stdout', /test \ \[file\.\.\.\]\s+Run the unitest/) + .notExpect('stdout', /cov \ \[file\.\.\.\]\s+Run the coverage/) + .expect('stdout', /dev \[baseDir\]\s+Run the development server/) + .expect('stdout', /Options/) + .expect('stdout', /--inspect\s+Debug with node-inspector/) + .expect('stdout', /--node-flags string/) + .expect('stdout', /-h, --help\s+Show Help/) + .end(); + }); + + it('should show command not found', async () => { + await run('my-bin', 'notexistscommand -h') + // .debug() + .expect('stderr', /Command not found: 'my-bin notexistscommand -h'/) + .expect('stderr', /try 'my-bin --help' for more information/) + .end(); + + await run('my-bin', 'dev abc bbc') + // .debug() + .expect('stderr', /Command not found: 'my-bin dev abc bbc'/) + .expect('stderr', /try 'my-bin dev --help' for more information/) + .end(); + }); + + it('should show help in extends command without error', async () => { + await run('other-bin', '-h') + // .debug() + .expect('stdout', /Usage: other-bin/) + .expect('stdout', /Available Commands/) + .expect('stdout', /help \[command\]\s+show help infomation for command/) + .expect('stdout', /test \ \[file\.\.\.\]\s+Run the unitest/) + .expect('stdout', /cov \ \[file\.\.\.\]\s+Run the coverage/) + .expect('stdout', /dev \[baseDir\]\s+Run the development server/) + .expect('stdout', /debug \[baseDir\]\s+Run the development server at debug mode/) + .expect('stdout', /Options/) + .expect('stdout', /-h, --help\s+Show Help/) .end(); }); }); diff --git a/test/test-utils.ts b/test/test-utils.ts index 8b2c377..eba3c1d 100644 --- a/test/test-utils.ts +++ b/test/test-utils.ts @@ -2,12 +2,10 @@ import path from 'path'; import coffee from 'coffee'; import { ForkOptions } from 'child_process'; -export function run(args: string | string[], options: ForkOptions = {}) { - const bin = path.join(__dirname, '../src/bin/cli.ts'); - const cwd = path.join(__dirname, 'fixtures'); +export function run(binName: string, args: string | string[], options: ForkOptions = {}) { + const bin = path.resolve(__dirname, './fixtures', binName, 'bin/cli.ts'); if (typeof args === 'string') args = args.split(' '); return coffee.fork(bin, args, { - cwd, execArgv: [ '-r', 'ts-node/register' ].concat(options.execArgv || []), ...options, }); diff --git a/test/tsconfig.json b/test/tsconfig.json new file mode 100644 index 0000000..4d08d15 --- /dev/null +++ b/test/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends": "../tsconfig", + "include": [ + "**/*.ts" + ] +} diff --git a/tsconfig.json b/tsconfig.json index aab23a6..e400a73 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,8 +2,6 @@ "extends": "@artus/tsconfig", "compilerOptions": { "baseUrl": ".", - "noUnusedParameters": false, - "noUnusedLocals":false, "resolveJsonModule": true, "outDir": "dist" },