juisy 2.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +211 -0
- package/bin/cli/cli.js +23 -0
- package/bin/cli/cmds/changelog.js +41 -0
- package/bin/cli/cmds/docs/generate-api.js +22 -0
- package/bin/cli/cmds/docs/generate-cli.js +11 -0
- package/bin/cli/cmds/docs/generate-readme.js +11 -0
- package/bin/cli/cmds/docs/index.js +22 -0
- package/bin/cli/cmds/docs/lint.js +42 -0
- package/bin/cli/cmds/eject.js +28 -0
- package/bin/cli/cmds/git-hooks/index.js +20 -0
- package/bin/cli/cmds/git-hooks/reset.js +48 -0
- package/bin/cli/cmds/git-hooks/sync.js +19 -0
- package/bin/cli/cmds/index.js +15 -0
- package/bin/cli/cmds/print-globals.js +28 -0
- package/bin/cli/cmds/release.js +231 -0
- package/bin/cli/cmds/squeeze.js +269 -0
- package/bin/cli/cmds/test.js +33 -0
- package/bin/cli/index.js +9 -0
- package/bin/cli/lib/docs/generate-api-doc.js +78 -0
- package/bin/cli/lib/version/update-version.js +52 -0
- package/bin/scripts/commit-msg.js +32 -0
- package/bin/scripts/pre-commit.js +24 -0
- package/dist/DataExporter.d.ts +67 -0
- package/dist/cli/CLIFactory.d.ts +19 -0
- package/dist/cli/Command.d.ts +44 -0
- package/dist/cli/InterfaceUtils.d.ts +53 -0
- package/dist/cli/OutputUtils.d.ts +123 -0
- package/dist/cli/command-visitors/command-handler-injections.d.ts +10 -0
- package/dist/cli/command-visitors/get-command-meta.d.ts +10 -0
- package/dist/cli/command-visitors/index.d.ts +9 -0
- package/dist/cli/command-visitors/private-command.d.ts +16 -0
- package/dist/cli/create-engine.d.ts +7 -0
- package/dist/cli/extract-usage.d.ts +72 -0
- package/dist/cli/index.d.ts +20 -0
- package/dist/cli/index.js +559 -0
- package/dist/cli/types.d.ts +112 -0
- package/dist/cli/utils.d.ts +19 -0
- package/dist/eject.d.ts +22 -0
- package/dist/get-package-info.d.ts +6 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +244 -0
- package/dist/project-globals.d.ts +63 -0
- package/dist/templater/Templater.d.ts +23 -0
- package/dist/templater/index.d.ts +6 -0
- package/dist/templater/index.js +330 -0
- package/dist/templater/markdown-templater/ReadmeTemplater.d.ts +154 -0
- package/dist/templater/markdown-templater/index.d.ts +25 -0
- package/dist/templater/types.d.ts +10 -0
- package/dist/utils/misc.d.ts +21 -0
- package/package.json +179 -0
- package/src/index.js +507 -0
- package/template/CHANGELOG.md +0 -0
- package/template/bin/cli/cli.js +27 -0
- package/template/bin/cli/cmds/changelog.js +71 -0
- package/template/bin/cli/cmds/docs.js +30 -0
- package/template/bin/cli/cmds/docs_cmds/generate-api.js +75 -0
- package/template/bin/cli/cmds/docs_cmds/generate-readme.js +51 -0
- package/template/bin/cli/cmds/git-hooks.js +30 -0
- package/template/bin/cli/cmds/git_hooks_cmds/reset.js +76 -0
- package/template/bin/cli/cmds/git_hooks_cmds/sync.js +44 -0
- package/template/bin/cli/cmds/release.js +219 -0
- package/template/bin/cli/index.js +7 -0
- package/template/bin/cli/lib/docs/generate-api-doc.js +33 -0
- package/template/bin/cli/lib/release/generate-release-note.js +3 -0
- package/template/bin/cli/lib/version/update-version.js +51 -0
- package/template/bin/scripts/commit-msg.js +42 -0
- package/template/bin/scripts/pre-commit.js +32 -0
- package/template/docs/api/docs.config.js +10 -0
- package/template/docs/readme/config.js +22 -0
- package/template/docs/readme/readme.js +70 -0
- package/template/docs/readme/template.md +53 -0
package/package.json
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "juisy",
|
|
3
|
+
"version": "2.0.0-beta.0",
|
|
4
|
+
"description": "Make your JavaScript (and/or TypeScript) project juicy!",
|
|
5
|
+
"main": "src/index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"files": [
|
|
8
|
+
"bin",
|
|
9
|
+
"dist",
|
|
10
|
+
"template"
|
|
11
|
+
],
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"import": "./dist/index.js"
|
|
16
|
+
},
|
|
17
|
+
"./cli": {
|
|
18
|
+
"types": "./dist/cli/index.d.ts",
|
|
19
|
+
"import": "./dist/cli/index.js"
|
|
20
|
+
},
|
|
21
|
+
"./templater": {
|
|
22
|
+
"types": "./dist/templater/index.d.ts",
|
|
23
|
+
"import": "./dist/templater/index.js"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"imports": {
|
|
27
|
+
"#juisy": {
|
|
28
|
+
"types": "./dist/index.d.ts",
|
|
29
|
+
"import": "./dist/index.js"
|
|
30
|
+
},
|
|
31
|
+
"#juisy/cli": {
|
|
32
|
+
"types": "./dist/cli/index.d.ts",
|
|
33
|
+
"import": "./dist/cli/index.js"
|
|
34
|
+
},
|
|
35
|
+
"#juisy/templater": {
|
|
36
|
+
"types": "./dist/templater/index.d.ts",
|
|
37
|
+
"import": "./dist/templater/index.js"
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"publishConfig": {
|
|
41
|
+
"access": "public"
|
|
42
|
+
},
|
|
43
|
+
"scripts": {
|
|
44
|
+
"build": "vite build",
|
|
45
|
+
"audit": "ncu && npm audit",
|
|
46
|
+
"audit:fix": "ncu --interactive",
|
|
47
|
+
"docs:api": "npx cross-env CLI_ENV=private node ./bin/cli docs generate:api",
|
|
48
|
+
"docs:readme": "npx cross-env CLI_ENV=private node ./bin/cli docs generate:readme",
|
|
49
|
+
"docs:cli": "npx cross-env CLI_ENV=private node ./bin/cli docs generate:cli",
|
|
50
|
+
"docs:lint": "npx cross-env CLI_ENV=private node ./bin/cli docs lint -c ./docs/.markdownlint-cli2.cjs",
|
|
51
|
+
"docs:lint:fix": "npm run docs:lint -- --fix",
|
|
52
|
+
"docs": "npm run docs:readme && npm run docs:cli && npm run docs:api && npm run docs:lint",
|
|
53
|
+
"lint": "eslint .",
|
|
54
|
+
"lint:fix": "npm run lint -- --fix",
|
|
55
|
+
"lint:markdown": "npm run docs:lint",
|
|
56
|
+
"lint:markdown:fix": "npm run docs:lint:fix",
|
|
57
|
+
"release": "npx cross-env CLI_ENV=private NODE_ENV=development node ./bin/cli release",
|
|
58
|
+
"changelog": "npx cross-env CLI_ENV=private NODE_ENV=development node ./bin/cli changelog",
|
|
59
|
+
"example:reset": "git checkout --no-overlay -- example && cd example && git clean -fdX",
|
|
60
|
+
"example:test": "npm run example:reset && cd example && npm install -D @hperchec/juisy@file:../ && npx juisy squeeze && npm run docs:readme",
|
|
61
|
+
"git-hooks:reset": "npx cross-env CLI_ENV=private NODE_ENV=development node ./bin/cli git-hooks reset",
|
|
62
|
+
"git-hooks:sync": "npx cross-env CLI_ENV=private NODE_ENV=development node ./bin/cli git-hooks sync",
|
|
63
|
+
"print:globals": "node --no-warnings ./bin/cli print:globals",
|
|
64
|
+
"test": "npx cross-env CLI_ENV=private node ./bin/cli test",
|
|
65
|
+
"test:dev": "npm test -- --watch",
|
|
66
|
+
"test:ui": "npm test -- --ui",
|
|
67
|
+
"__prepare": "npm run git-hooks:sync"
|
|
68
|
+
},
|
|
69
|
+
"repository": {
|
|
70
|
+
"type": "git",
|
|
71
|
+
"url": "git+https://gitlab.com/hperchec/juisy.git"
|
|
72
|
+
},
|
|
73
|
+
"keywords": [
|
|
74
|
+
"js",
|
|
75
|
+
"build",
|
|
76
|
+
"release",
|
|
77
|
+
"changelog",
|
|
78
|
+
"bin",
|
|
79
|
+
"cmd",
|
|
80
|
+
"easy"
|
|
81
|
+
],
|
|
82
|
+
"author": {
|
|
83
|
+
"name": "Hervé Perchec",
|
|
84
|
+
"email": "contact@herve-perchec.com",
|
|
85
|
+
"url": "https://gitlab.com/herveperchec"
|
|
86
|
+
},
|
|
87
|
+
"license": "ISC",
|
|
88
|
+
"bugs": {
|
|
89
|
+
"url": "https://gitlab.com/hperchec/juisy/issues"
|
|
90
|
+
},
|
|
91
|
+
"homepage": "https://gitlab.com/hperchec/juisy#readme",
|
|
92
|
+
"bin": {
|
|
93
|
+
"juisy": "./bin/cli/index.js"
|
|
94
|
+
},
|
|
95
|
+
"simple-git-hooks": {
|
|
96
|
+
"pre-commit": "node ./bin/scripts/pre-commit.js",
|
|
97
|
+
"commit-msg": "node ./bin/scripts/commit-msg.js ${1}"
|
|
98
|
+
},
|
|
99
|
+
"lint-staged": {
|
|
100
|
+
"*.{js,cjs,ts}": [
|
|
101
|
+
"eslint --fix",
|
|
102
|
+
"git add"
|
|
103
|
+
]
|
|
104
|
+
},
|
|
105
|
+
"peerDependencies": {
|
|
106
|
+
"@commitlint/cli": "^17.7.2",
|
|
107
|
+
"@commitlint/config-conventional": "^17.7.0",
|
|
108
|
+
"@github/markdownlint-github": "^0.6.0",
|
|
109
|
+
"@hperchec/readme-generator": "^3.0.0",
|
|
110
|
+
"@stylistic/eslint-plugin": "^2",
|
|
111
|
+
"@typescript-eslint/eslint-plugin": "^8",
|
|
112
|
+
"chalk": "^4.1.2",
|
|
113
|
+
"conventional-changelog-cli": "^4.1.0",
|
|
114
|
+
"eslint": "^9",
|
|
115
|
+
"execa": "^5.1.1",
|
|
116
|
+
"lint-staged": "^14.0.1",
|
|
117
|
+
"markdownlint-cli2": "^0.12.1",
|
|
118
|
+
"markdownlint-cli2-formatter-pretty": "^0.0.6",
|
|
119
|
+
"prompts": "^2.4.2",
|
|
120
|
+
"simple-git-hooks": "^2.9.0",
|
|
121
|
+
"yargs": "^17.7.2"
|
|
122
|
+
},
|
|
123
|
+
"devDependencies": {
|
|
124
|
+
"@commitlint/cli": "^19.6.1",
|
|
125
|
+
"@commitlint/config-conventional": "^19.6.0",
|
|
126
|
+
"@github/markdownlint-github": "^0.6.3",
|
|
127
|
+
"@rollup/plugin-typescript": "^12.1.2",
|
|
128
|
+
"@stylistic/eslint-plugin": "^2.12.1",
|
|
129
|
+
"@types/ejs": "^3.1.5",
|
|
130
|
+
"@types/fs-extra": "^11.0.4",
|
|
131
|
+
"@types/lodash.merge": "^4.6.9",
|
|
132
|
+
"@types/prompts": "^2.4.9",
|
|
133
|
+
"@types/yargs": "^17.0.33",
|
|
134
|
+
"@typescript-eslint/eslint-plugin": "^8.18.1",
|
|
135
|
+
"@vitest/coverage-v8": "^2.1.8",
|
|
136
|
+
"@vitest/ui": "^2.1.8",
|
|
137
|
+
"conventional-changelog-cli": "^5.0.0",
|
|
138
|
+
"eslint": "^9.17.0",
|
|
139
|
+
"happy-dom": "^15.11.7",
|
|
140
|
+
"lint-staged": "^14.0.1",
|
|
141
|
+
"markdown-table": "^3.0.4",
|
|
142
|
+
"markdownlint-cli2": "^0.16.0",
|
|
143
|
+
"markdownlint-cli2-formatter-pretty": "^0.0.7",
|
|
144
|
+
"npm-check-updates": "^17.1.12",
|
|
145
|
+
"typescript": "^5.7.2",
|
|
146
|
+
"vite": "^5.4.11",
|
|
147
|
+
"vite-plugin-dts": "^4.3.0",
|
|
148
|
+
"vitest": "^2.1.8"
|
|
149
|
+
},
|
|
150
|
+
"dependencies": {
|
|
151
|
+
"@dotenvx/dotenvx": "^1.31.0",
|
|
152
|
+
"ascii-tree": "^0.3.0",
|
|
153
|
+
"chalk": "^4.1.2",
|
|
154
|
+
"deepmerge": "^4.3.1",
|
|
155
|
+
"ejs": "^3.1.10",
|
|
156
|
+
"execa": "^5.1.1",
|
|
157
|
+
"find-up": "^7.0.0",
|
|
158
|
+
"fs-extra": "^11.2.0",
|
|
159
|
+
"github-slugger": "^2.0.0",
|
|
160
|
+
"glob": "^11.0.0",
|
|
161
|
+
"indent-string": "^5.0.0",
|
|
162
|
+
"json-2-csv": "^5.5.7",
|
|
163
|
+
"jstoxml": "^5.0.2",
|
|
164
|
+
"lodash.merge": "^4.6.2",
|
|
165
|
+
"loglevel": "^1.9.2",
|
|
166
|
+
"markdown-toc": "^1.2.0",
|
|
167
|
+
"markdown-utils": "^1.0.0",
|
|
168
|
+
"package-json-type": "^1.0.3",
|
|
169
|
+
"pkg-dir": "^8.0.0",
|
|
170
|
+
"prompts": "^2.4.2",
|
|
171
|
+
"remark": "^15.0.1",
|
|
172
|
+
"remark-frontmatter": "^5.0.0",
|
|
173
|
+
"remark-toc": "^9.0.0",
|
|
174
|
+
"simple-git-hooks": "^2.9.0",
|
|
175
|
+
"strip-ansi": "^7.1.0",
|
|
176
|
+
"yaml": "^2.6.1",
|
|
177
|
+
"yargs": "^17.7.2"
|
|
178
|
+
}
|
|
179
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,507 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Entry point
|
|
3
|
+
* @description @hperchec/juisy [/src/index.js]
|
|
4
|
+
* @author Hervé Perchec
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @module juisy
|
|
9
|
+
* @type {object}
|
|
10
|
+
* @typicalname juisy
|
|
11
|
+
* @description
|
|
12
|
+
* From: @hperchec/juisy@{{{{VERSION}}}}
|
|
13
|
+
* @example
|
|
14
|
+
* const juisy = require('@hperchec/juisy')
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const getCallerFile = require('get-caller-file')
|
|
18
|
+
const Yargs = require('yargs/yargs')
|
|
19
|
+
const utils = require('./utils')
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @param {Function} builder - The CLI builder function
|
|
23
|
+
* @returns {Function} A function that takes optional argv as first parameter and returns {@link CLI CLI}
|
|
24
|
+
* @description
|
|
25
|
+
* Creates a CLI (yargs instance) factory
|
|
26
|
+
* @example
|
|
27
|
+
* const { createCli } = require('@hperchec/juisy')
|
|
28
|
+
*
|
|
29
|
+
* const cli = createCli(cli => cli
|
|
30
|
+
* .scriptName('my-juicy-cli')
|
|
31
|
+
* .usage('Usage: $0 <command> [<options>]')
|
|
32
|
+
* )
|
|
33
|
+
*
|
|
34
|
+
* const argv = process.argv.slice(2)
|
|
35
|
+
*
|
|
36
|
+
* // Parse argv
|
|
37
|
+
* cli().parse(argv)
|
|
38
|
+
*/
|
|
39
|
+
exports.createCli = function (builder) {
|
|
40
|
+
return function (argv) {
|
|
41
|
+
const cli = initYargs(Yargs(argv))
|
|
42
|
+
return builder(cli)
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @typedef {object} CommandDoclet
|
|
48
|
+
* @category types
|
|
49
|
+
* @description
|
|
50
|
+
* Command documentation object returned by {@link module:juisy.cliTools.extractUsage extractUsage} tool.
|
|
51
|
+
* @property {string} command - The command
|
|
52
|
+
* @property {string[]} args - The command args
|
|
53
|
+
* @property {object} aliases - The yargs instance `aliasMap` reference
|
|
54
|
+
* @property {object} deprecated - If command is deprecated
|
|
55
|
+
* @property {module:juisy~ExtractedUsage} extractedUsage - The extracted usage object from yargs usage instance
|
|
56
|
+
* @property {string} rawUsage - The usage output as string (as if `--help` option passed)
|
|
57
|
+
* @property {?object} [children] - The child commands
|
|
58
|
+
*/
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* @typedef {object} ExtractedUsage
|
|
62
|
+
* @category types
|
|
63
|
+
* @description
|
|
64
|
+
* Type of {@link module:juisy~CommandDoclet CommandDoclet} `extractedUsage` property
|
|
65
|
+
* @property {object} demandedCommands - Same as yargs instance `getDemandedCommands` method
|
|
66
|
+
* @property {object} demandedOptions - Same as yargs instance `getDemandedOptions` method
|
|
67
|
+
* @property {object} deprecatedOptions - Same as yargs instance `getDeprecatedOptions` method
|
|
68
|
+
* @property {object} groups - Same as yargs instance `getGroups` method
|
|
69
|
+
* @property {object} options - Same as yargs instance `getOptions` method
|
|
70
|
+
* @property {string[]} usages - Same as yargs usage instance `getUsage` method
|
|
71
|
+
* @property {object} commands - The result of yargs usage instance `getCommands` method as object.
|
|
72
|
+
* While the UsageInstance commands items are defined as follow: `[cmd, description, isDefault, aliases, deprecated]`,
|
|
73
|
+
* we cast it to an object like: `{cmd, description, isDefault, aliases, deprecated}`.
|
|
74
|
+
*/
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* @alias module:juisy.cliTools
|
|
78
|
+
* @type {object}
|
|
79
|
+
* @description
|
|
80
|
+
* CLI tools
|
|
81
|
+
*/
|
|
82
|
+
const cliTools = exports.cliTools = {
|
|
83
|
+
/**
|
|
84
|
+
* @async
|
|
85
|
+
* @param {Function} cliFactory - The cli factory function returned by createCli method
|
|
86
|
+
* @param {boolean} [recursive = false] - Recursive mode (parse child commands)
|
|
87
|
+
* @param {string[]} [args = [""]] - The base args to pass as parseAsync first parameter
|
|
88
|
+
* @param {string} [locale = en] - The locale
|
|
89
|
+
* @returns {Promise<module:juisy~CommandDoclet>} The extracted command doclet
|
|
90
|
+
* @fulfil {module:juisy~CommandDoclet}
|
|
91
|
+
* @description
|
|
92
|
+
* Extract usage object from CLI (Yargs) instance factory
|
|
93
|
+
* @example
|
|
94
|
+
* **Note**: don't call `cli()`, pass the factory.
|
|
95
|
+
*
|
|
96
|
+
* ```js
|
|
97
|
+
* const { createCli, cliTools } = require('@hperchec/juisy')
|
|
98
|
+
*
|
|
99
|
+
* const cli = createCli(cli => cli
|
|
100
|
+
* // ...
|
|
101
|
+
* )
|
|
102
|
+
*
|
|
103
|
+
* cliTools.extractUsage(cli)
|
|
104
|
+
* ```
|
|
105
|
+
*
|
|
106
|
+
* Recursively extract usage:
|
|
107
|
+
*
|
|
108
|
+
* ```js
|
|
109
|
+
* await cliTools.extractUsage(cli, true)
|
|
110
|
+
* ```
|
|
111
|
+
* With base args:
|
|
112
|
+
*
|
|
113
|
+
* ```js
|
|
114
|
+
* await cliTools.extractUsage(cli, false, [ 'my-command' ])
|
|
115
|
+
* ```
|
|
116
|
+
*
|
|
117
|
+
* Change locale:
|
|
118
|
+
*
|
|
119
|
+
* ```js
|
|
120
|
+
* await cliTools.extractUsage(cli, undefined, undefined, 'fr')
|
|
121
|
+
* ```
|
|
122
|
+
*/
|
|
123
|
+
async extractUsage (cliFactory, recursive = false, args = [ '' ], locale = 'en') {
|
|
124
|
+
const innerYargs = cliFactory([ '' ]) // empty argv
|
|
125
|
+
// Set locale
|
|
126
|
+
innerYargs.locale(locale)
|
|
127
|
+
|
|
128
|
+
// Init doclet object extracted usage object
|
|
129
|
+
const doclet = {
|
|
130
|
+
command: undefined,
|
|
131
|
+
args: undefined,
|
|
132
|
+
aliases: undefined,
|
|
133
|
+
// deprecated: false,
|
|
134
|
+
extractedUsage: undefined,
|
|
135
|
+
rawUsage: undefined,
|
|
136
|
+
children: recursive ? {} : undefined
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const parseCallback = function (err, argv, output) {
|
|
140
|
+
if (err) throw err
|
|
141
|
+
// this is the yargs instance with temporary parse state
|
|
142
|
+
const self = this
|
|
143
|
+
// Set doclet args
|
|
144
|
+
doclet.args = argv._
|
|
145
|
+
// Set doclet command
|
|
146
|
+
doclet.command = argv._[argv._.length - 1] // is there a better way?
|
|
147
|
+
// Set rawUsage
|
|
148
|
+
doclet.rawUsage = output
|
|
149
|
+
// Extracted usage
|
|
150
|
+
const extractedUsage = doclet.extractedUsage = {}
|
|
151
|
+
|
|
152
|
+
extractedUsage.demandedCommands = self.getDemandedCommands()
|
|
153
|
+
extractedUsage.demandedOptions = self.getDemandedOptions()
|
|
154
|
+
extractedUsage.deprecatedOptions = self.getDeprecatedOptions()
|
|
155
|
+
extractedUsage.groups = self.getGroups()
|
|
156
|
+
extractedUsage.options = self.getOptions()
|
|
157
|
+
// extractedUsage.examples = examples // @todo: No API for UsageInstance examples?
|
|
158
|
+
|
|
159
|
+
const internalMethods = self.getInternalMethods()
|
|
160
|
+
const usageInstance = internalMethods.getUsageInstance()
|
|
161
|
+
|
|
162
|
+
extractedUsage.usages = usageInstance.getUsage()
|
|
163
|
+
|
|
164
|
+
const commandInstance = internalMethods.getCommandInstance()
|
|
165
|
+
|
|
166
|
+
// Set doclet aliases
|
|
167
|
+
doclet.aliases = commandInstance.aliasMap
|
|
168
|
+
|
|
169
|
+
const childCommandsFromHandlers = commandInstance.handlers
|
|
170
|
+
const childCommandsFromUsage = usageInstance.getCommands()
|
|
171
|
+
|
|
172
|
+
extractedUsage.commands = Object.keys(childCommandsFromHandlers).reduce((accumulator, handlerKey) => {
|
|
173
|
+
// the UsageInstance commands item is like: [cmd, description, isDefault, aliases, deprecated]
|
|
174
|
+
const [ cmd, description, isDefault, aliases, deprecated ] = childCommandsFromUsage.find((command) => {
|
|
175
|
+
return command[0] === childCommandsFromHandlers[handlerKey].original
|
|
176
|
+
})
|
|
177
|
+
accumulator[handlerKey] = { cmd, description, isDefault, aliases, deprecated }
|
|
178
|
+
return accumulator
|
|
179
|
+
}, {})
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Parse async command
|
|
183
|
+
const parsed = await innerYargs.parseAsync(args, { help: true }, parseCallback) // eslint-disable-line no-unused-vars
|
|
184
|
+
|
|
185
|
+
// If recursive, loop on child commands
|
|
186
|
+
if (recursive) {
|
|
187
|
+
for (const childCommand in doclet.extractedUsage.commands) {
|
|
188
|
+
// Recursively call extractUsage method
|
|
189
|
+
doclet.children[childCommand] = await cliTools.extractUsage(
|
|
190
|
+
cliFactory,
|
|
191
|
+
true,
|
|
192
|
+
[ ...(args.filter(a => a !== '')), childCommand ],
|
|
193
|
+
locale
|
|
194
|
+
)
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return doclet
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* @type {object}
|
|
204
|
+
* @description
|
|
205
|
+
* Juisy utils. See [utils](./utils.md) documentation.
|
|
206
|
+
*/
|
|
207
|
+
exports.utils = utils
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* @ignore
|
|
211
|
+
* @param {Yargs} yargs - The yargs instance
|
|
212
|
+
* @returns {CLI} The initialized yargs as CLI
|
|
213
|
+
*/
|
|
214
|
+
function initYargs (yargs) {
|
|
215
|
+
// Private properties
|
|
216
|
+
yargs._isPrivate = false
|
|
217
|
+
yargs._globalCommandVisitors = {}
|
|
218
|
+
yargs._globalCommandVisitorsEnabled = new Set([])
|
|
219
|
+
yargs._meta = {}
|
|
220
|
+
|
|
221
|
+
// Methods
|
|
222
|
+
const originalCommandDirMethod = yargs.commandDir
|
|
223
|
+
yargs.originalCommandDir = originalCommandDirMethod
|
|
224
|
+
yargs.commandDir = commandDir
|
|
225
|
+
yargs.globalCommandVisitor = globalCommandVisitor
|
|
226
|
+
yargs.globalCommandVisitorOptions = globalCommandVisitorOptions
|
|
227
|
+
yargs.hasGlobalCommandVisitor = hasGlobalCommandVisitor
|
|
228
|
+
yargs.disableGlobalCommandVisitors = disableGlobalCommandVisitors
|
|
229
|
+
yargs.enableGlobalCommandVisitors = enableGlobalCommandVisitors
|
|
230
|
+
yargs.isPrivate = isPrivate
|
|
231
|
+
yargs.getMeta = getMeta
|
|
232
|
+
|
|
233
|
+
return yargs
|
|
234
|
+
.globalCommandVisitor('private-command-visitor', privateCommandVisitor, privateCommandVisitor.options)
|
|
235
|
+
.globalCommandVisitor('get-meta-command-visitor', getMetaCommandVisitor, getMetaCommandVisitor.options)
|
|
236
|
+
.strict() // disallow unknow command
|
|
237
|
+
.help() // Enable help
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* @typedef {Yargs} CLI
|
|
242
|
+
* @typicalname cli
|
|
243
|
+
* @category types
|
|
244
|
+
* @description
|
|
245
|
+
* CLI object returned by cli factory from {@link module:juisy.createCli createCli} method.
|
|
246
|
+
*
|
|
247
|
+
* It has all inherited properties and methods from [yargs](https://github.com/yargs/yargs) instance plus the following:
|
|
248
|
+
*/
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* @alias module:juisy~CLI#commandDir
|
|
252
|
+
* @param {string} dir - Same as yargs `commandDir` argument
|
|
253
|
+
* @param {object} [options] - Same as yargs `commandDir` options
|
|
254
|
+
* @returns {CLI} Returns the CLI (yargs) instance
|
|
255
|
+
* @description
|
|
256
|
+
* See [yargs.commandDir](https://yargs.js.org/docs/#api-reference-commanddirdirectory-opts) documentation.
|
|
257
|
+
*/
|
|
258
|
+
function commandDir (dir, options = {}) {
|
|
259
|
+
const self = this // this is yargs instance
|
|
260
|
+
// Is options.visit set?
|
|
261
|
+
const visitor = options.visit || (cmdObj => cmdObj)
|
|
262
|
+
|
|
263
|
+
// Add directory with wrapped visit option
|
|
264
|
+
self.getInternalMethods().getCommandInstance().addDirectory(dir, require, getCallerFile(), {
|
|
265
|
+
...options,
|
|
266
|
+
visit: function (commandObject, pathToFile, filename) {
|
|
267
|
+
let failOnFalsyReturn
|
|
268
|
+
// Loop on enabled global command visitors
|
|
269
|
+
for (const name of self._globalCommandVisitorsEnabled) {
|
|
270
|
+
const globalVisitor = self._globalCommandVisitors[name]
|
|
271
|
+
// Call global visitor: fail on falsy returned value
|
|
272
|
+
if (!globalVisitor(commandObject, pathToFile, filename, self, globalVisitor.options)) {
|
|
273
|
+
failOnFalsyReturn = true
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Then custom visitor
|
|
278
|
+
const customVisitorResult = visitor(commandObject, pathToFile, filename, self)
|
|
279
|
+
|
|
280
|
+
return failOnFalsyReturn ? false : customVisitorResult
|
|
281
|
+
}
|
|
282
|
+
})
|
|
283
|
+
return self
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* @callback module:juisy~CLI~globalCommandVisitorCallback
|
|
288
|
+
* @category callback
|
|
289
|
+
* @param {object} commandObject - The command object
|
|
290
|
+
* @param {string} pathToFile - The path to file
|
|
291
|
+
* @param {string} filename - The filename
|
|
292
|
+
* @param {CLI} yargs - The current CLI instance
|
|
293
|
+
* @param {object} options - The default options to set
|
|
294
|
+
* @description
|
|
295
|
+
* Custom global command visitor callback.
|
|
296
|
+
*
|
|
297
|
+
* Takes same parameters as original yargs commandDir "visit" option, plus yargs itself and visitor options.
|
|
298
|
+
*/
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* @alias module:juisy~CLI#globalCommandVisitor
|
|
302
|
+
* @param {string} name - The visitor unique name
|
|
303
|
+
* @param {module:juisy~CLI~globalCommandVisitorCallback} visitor - The visitor function
|
|
304
|
+
* @param {object} defaultOptions - The default visitor options object
|
|
305
|
+
* @returns {CLI} Returns the CLI (yargs) instance
|
|
306
|
+
* @description
|
|
307
|
+
* Set a global command visitor function
|
|
308
|
+
* @example
|
|
309
|
+
* const visitor = function (commandObject, pathToFile, filename, yargs, options) {
|
|
310
|
+
* const { foo } = options
|
|
311
|
+
* console.log('The "foo" option : ', foo)
|
|
312
|
+
* return commandObject
|
|
313
|
+
* }
|
|
314
|
+
*
|
|
315
|
+
* cli.globalCommandVisitor('my-custom-visitor', visitor, { foo: 'bar' })
|
|
316
|
+
* .commandDir('cmds_dir')
|
|
317
|
+
* // => will console log foo option for each command visited
|
|
318
|
+
*/
|
|
319
|
+
function globalCommandVisitor (name, visitor, defaultOptions = {}) {
|
|
320
|
+
this._globalCommandVisitors[name] = visitor
|
|
321
|
+
return this.enableGlobalCommandVisitors([ name ])
|
|
322
|
+
.globalCommandVisitorOptions(name, defaultOptions)
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* @alias module:juisy~CLI#globalCommandVisitorOptions
|
|
327
|
+
* @param {string} name - The visitor unique name
|
|
328
|
+
* @param {object} options - The visitor options object
|
|
329
|
+
* @returns {CLI} Returns the CLI (yargs) instance
|
|
330
|
+
* @description
|
|
331
|
+
* Set global command visitor options
|
|
332
|
+
* @example
|
|
333
|
+
* // Overrides default options for 'my-custom-visitor'
|
|
334
|
+
* // defined via globalCommandVisitor method
|
|
335
|
+
* cli.globalCommandVisitorOptions('my-custom-visitor', { foo: 'baz' })
|
|
336
|
+
*/
|
|
337
|
+
function globalCommandVisitorOptions (name, options) {
|
|
338
|
+
this._globalCommandVisitors[name].options = {
|
|
339
|
+
...this._globalCommandVisitors[name].options,
|
|
340
|
+
...options
|
|
341
|
+
}
|
|
342
|
+
return this
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* @alias module:juisy~CLI#hasGlobalCommandVisitor
|
|
347
|
+
* @param {string} name - The visitor name
|
|
348
|
+
* @returns {boolean} True if global command visitor is defined
|
|
349
|
+
* @description
|
|
350
|
+
* Check if global command visitor is defined
|
|
351
|
+
* @example
|
|
352
|
+
* cli.hasGlobalCommandVisitor('my-custom-visitor')
|
|
353
|
+
*/
|
|
354
|
+
function hasGlobalCommandVisitor (name) {
|
|
355
|
+
return Object.keys(this._globalCommandVisitors).includes(name)
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* @alias module:juisy~CLI#disableGlobalCommandVisitors
|
|
360
|
+
* @param {string[]} visitors - The visitor names
|
|
361
|
+
* @returns {CLI} Returns the CLI (yargs) instance
|
|
362
|
+
* @description
|
|
363
|
+
* Disables global command visitors
|
|
364
|
+
* @example
|
|
365
|
+
* // Disables the "my-disabled-visitor" global command visitor
|
|
366
|
+
* cli.disableGlobalCommandVisitors(['my-disabled-visitor'])
|
|
367
|
+
*/
|
|
368
|
+
function disableGlobalCommandVisitors (visitors = []) {
|
|
369
|
+
for (const name of visitors) {
|
|
370
|
+
// If visitor exists
|
|
371
|
+
if (this.hasGlobalCommandVisitor(name)) {
|
|
372
|
+
// Enable
|
|
373
|
+
this._globalCommandVisitorsEnabled.delete(name)
|
|
374
|
+
} else {
|
|
375
|
+
throw new Error('Global command visitor: "' + name + '" not defined.')
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
return this
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* @alias module:juisy~CLI#enableGlobalCommandVisitors
|
|
383
|
+
* @param {string[]} visitors - The visitor names
|
|
384
|
+
* @returns {CLI} Returns the CLI (yargs) instance
|
|
385
|
+
* @description
|
|
386
|
+
* Enables global command visitors
|
|
387
|
+
* @example
|
|
388
|
+
* // Enables the "my-custom-visitor" and "my-awesome-visitor"
|
|
389
|
+
* // global command visitors
|
|
390
|
+
* cli.enableGlobalCommandVisitors(['my-custom-visitor', 'my-awesome-visitor'])
|
|
391
|
+
*/
|
|
392
|
+
function enableGlobalCommandVisitors (visitors = []) {
|
|
393
|
+
for (const name of visitors) {
|
|
394
|
+
// If visitor exists
|
|
395
|
+
if (this.hasGlobalCommandVisitor(name)) {
|
|
396
|
+
// Enable
|
|
397
|
+
this._globalCommandVisitorsEnabled.add(name)
|
|
398
|
+
} else {
|
|
399
|
+
throw new Error('Global command visitor: "' + name + '" not defined.')
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
return this
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* @alias module:juisy~CLI#isPrivate
|
|
407
|
+
* @returns {boolean} True if command is private
|
|
408
|
+
* @description
|
|
409
|
+
* Get command private status
|
|
410
|
+
*/
|
|
411
|
+
function isPrivate () {
|
|
412
|
+
return this._isPrivate
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* @alias module:juisy~CLI#getMeta
|
|
417
|
+
* @returns {object} The command meta
|
|
418
|
+
* @description
|
|
419
|
+
* Get the CLI instance meta
|
|
420
|
+
* @example
|
|
421
|
+
* cli.getMeta()
|
|
422
|
+
*/
|
|
423
|
+
function getMeta () {
|
|
424
|
+
return this._meta
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* @ignore
|
|
429
|
+
* @param {?Function} target - The target builder
|
|
430
|
+
* @param {Function} builder - The wrap
|
|
431
|
+
* @description
|
|
432
|
+
* Wrap command builder (target) with builder passed as second parameter
|
|
433
|
+
* that will be called before target. Target can be undefined
|
|
434
|
+
*/
|
|
435
|
+
function wrapBuilder (target, builder) {
|
|
436
|
+
// Is target set?
|
|
437
|
+
const _target = target || (yargs => yargs)
|
|
438
|
+
// Return wrapped builder
|
|
439
|
+
return function (yargs) {
|
|
440
|
+
return _target(builder(yargs))
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* @ignore
|
|
446
|
+
* @param {object} commandObject - Same as yargs.commandDir "visit" option
|
|
447
|
+
* @param {string} pathToFile - Same as yargs.commandDir "visit" option
|
|
448
|
+
* @param {string} filename - Same as yargs.commandDir "visit" option
|
|
449
|
+
* @param {CLI} cli - The CLI (yargs) instance
|
|
450
|
+
* @param {object} options - The global command visitor defined options
|
|
451
|
+
* @returns {object|boolean} False if command is private and env key is set to "private".
|
|
452
|
+
* Otherwise, returns the commandObject with wrapped builder to tag CLI instance as private.
|
|
453
|
+
* @description
|
|
454
|
+
* Global command visitor to auto-set command private status
|
|
455
|
+
*/
|
|
456
|
+
function privateCommandVisitor (commandObject, pathToFile, filename, cli, options) {
|
|
457
|
+
const { cmdObjectProp, envKey } = options
|
|
458
|
+
if (commandObject[cmdObjectProp]) {
|
|
459
|
+
// Check if env key is set to 'private'
|
|
460
|
+
if (process.env[envKey] === 'private') {
|
|
461
|
+
// Wrap builder
|
|
462
|
+
commandObject.builder = wrapBuilder(commandObject.builder, function (yargs) {
|
|
463
|
+
yargs._isPrivate = true
|
|
464
|
+
return yargs
|
|
465
|
+
})
|
|
466
|
+
} else {
|
|
467
|
+
// Else, don't return command object
|
|
468
|
+
return false
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
return commandObject
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
privateCommandVisitor.options = {
|
|
475
|
+
cmdObjectProp: 'private',
|
|
476
|
+
envKey: 'CLI_ENV'
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
/**
|
|
480
|
+
* @ignore
|
|
481
|
+
* @param {object} commandObject - Same as yargs.commandDir "visit" option
|
|
482
|
+
* @param {string} pathToFile - Same as yargs.commandDir "visit" option
|
|
483
|
+
* @param {string} filename - Same as yargs.commandDir "visit" option
|
|
484
|
+
* @param {CLI} cli - The CLI (yargs) instance
|
|
485
|
+
* @param {object} options - The global command visitor defined options
|
|
486
|
+
* @returns {object} The commandObject with wrapped builder to inject CLI instance meta.
|
|
487
|
+
* @description
|
|
488
|
+
* Global command visitor to auto-set command meta
|
|
489
|
+
*/
|
|
490
|
+
function getMetaCommandVisitor (commandObject, pathToFile, filename, cli, options) {
|
|
491
|
+
const { cmdObjectProp } = options
|
|
492
|
+
// if prop is defined (default: "meta")
|
|
493
|
+
if (commandObject[cmdObjectProp]) {
|
|
494
|
+
const commandMeta = commandObject[cmdObjectProp]
|
|
495
|
+
// Wrap builder
|
|
496
|
+
commandObject.builder = wrapBuilder(commandObject.builder, function (yargs) {
|
|
497
|
+
// Deep merge the meta objects with parent
|
|
498
|
+
yargs._meta = utils.merge(yargs._meta, commandMeta)
|
|
499
|
+
return yargs
|
|
500
|
+
})
|
|
501
|
+
}
|
|
502
|
+
return commandObject
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
getMetaCommandVisitor.options = {
|
|
506
|
+
cmdObjectProp: 'meta'
|
|
507
|
+
}
|
|
File without changes
|