@magic/cli 0.0.45 → 0.0.47
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 +18 -7
- package/package.json +17 -12
- package/src/exec.js +38 -0
- package/src/{execFile.mjs → execFile.js} +8 -1
- package/src/help/{argToHelp.mjs → argToHelp.js} +11 -1
- package/src/help/{envToHelp.mjs → envToHelp.js} +13 -1
- package/src/help/findLongestString.js +19 -0
- package/src/help/index.js +100 -0
- package/src/{index.mjs → index.js} +12 -7
- package/src/parse/argv.js +125 -0
- package/src/parse/{clean.mjs → clean.js} +14 -1
- package/src/parse/{commands.mjs → commands.js} +14 -2
- package/src/parse/env.js +37 -0
- package/src/parse/index.js +60 -0
- package/src/parse/required.js +56 -0
- package/src/{prompt.mjs → prompt.js} +11 -2
- package/src/spawn.js +20 -0
- package/types/exec.d.ts +6 -0
- package/types/execFile.d.ts +5 -0
- package/types/help/argToHelp.d.ts +5 -0
- package/types/help/envToHelp.d.ts +1 -0
- package/types/help/findLongestString.d.ts +1 -0
- package/types/help/index.d.ts +67 -0
- package/types/index.d.ts +36 -0
- package/types/parse/argv.d.ts +35 -0
- package/types/parse/clean.d.ts +14 -0
- package/types/parse/commands.d.ts +11 -0
- package/types/parse/env.d.ts +15 -0
- package/types/parse/index.d.ts +22 -0
- package/types/parse/required.d.ts +16 -0
- package/types/prompt.d.ts +8 -0
- package/types/spawn.d.ts +5 -0
- package/src/exec.mjs +0 -24
- package/src/help/findLongestString.mjs +0 -15
- package/src/help/index.mjs +0 -64
- package/src/parse/argv.mjs +0 -118
- package/src/parse/env.mjs +0 -22
- package/src/parse/index.mjs +0 -29
- package/src/parse/required.mjs +0 -32
- package/src/spawn.mjs +0 -12
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import is from '@magic/types'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @typedef {object} ParsedCLI
|
|
5
|
+
* @property {Record<string, string>} env
|
|
6
|
+
* @property {Record<string, any>} argv
|
|
7
|
+
* @property {Record<string, any>} args
|
|
8
|
+
* @property {Record<string, boolean>} commands
|
|
9
|
+
* @property {Array<string|string[]>} errors
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @typedef {object} ParseRequiredArgs
|
|
14
|
+
* @property {ParsedCLI} [parsed]
|
|
15
|
+
* @property {object} [props]
|
|
16
|
+
* @property {Array<string|string[]> | string} [props.required]
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Validates that required CLI arguments exist.
|
|
21
|
+
*
|
|
22
|
+
* @param {ParseRequiredArgs} args
|
|
23
|
+
* @returns {Array<string|string[]>} - List of missing required arguments.
|
|
24
|
+
*/
|
|
25
|
+
export const parseRequired = (args = {}) => {
|
|
26
|
+
const { parsed, props } = args
|
|
27
|
+
|
|
28
|
+
if (is.empty(props?.required)) {
|
|
29
|
+
return []
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** @type {string[]} */
|
|
33
|
+
const errors = []
|
|
34
|
+
|
|
35
|
+
if (is.string(props?.required)) {
|
|
36
|
+
props.required = [props.required]
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
props?.required?.forEach(req => {
|
|
40
|
+
if (is.array(req)) {
|
|
41
|
+
const some = req.some(a => parsed?.argv[a])
|
|
42
|
+
|
|
43
|
+
if (!some) {
|
|
44
|
+
errors.push(...req)
|
|
45
|
+
}
|
|
46
|
+
} else {
|
|
47
|
+
const opt = parsed?.argv[req]
|
|
48
|
+
|
|
49
|
+
if (is.empty(opt)) {
|
|
50
|
+
errors.push(req)
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
return errors
|
|
56
|
+
}
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import is from '@magic/types'
|
|
2
2
|
import readline from 'readline'
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Prompts the user for input or confirmation.
|
|
5
|
+
* @param {string|string[]} [msg=''] - Message to display in the prompt.
|
|
6
|
+
* @param {object} [options={}] - Prompt options.
|
|
7
|
+
* @param {boolean} [options.yesNo=false] - Whether to treat the input as a yes/no confirmation.
|
|
8
|
+
* @param {boolean} [options.yesDefault=false] - If true, defaults to "yes" on empty input.
|
|
9
|
+
* @param {NodeJS.Process} [options.std=process] - Standard input/output streams.
|
|
10
|
+
* @returns {Promise<string|boolean>} Resolves with the user input (string) or boolean for yes/no prompts.
|
|
11
|
+
*/
|
|
4
12
|
export const prompt = (msg = '', options = {}) =>
|
|
5
13
|
new Promise((resolve, reject) => {
|
|
6
14
|
const { yesNo = false, std = process, yesDefault = false } = options
|
|
@@ -36,7 +44,8 @@ export const prompt = (msg = '', options = {}) =>
|
|
|
36
44
|
rl.on('line', line => {
|
|
37
45
|
if (yesNo) {
|
|
38
46
|
const trimmed = line.trim().toLowerCase()
|
|
39
|
-
|
|
47
|
+
resolve(trimmed === 'y' || trimmed === 'yes' || yesDefault)
|
|
48
|
+
return
|
|
40
49
|
}
|
|
41
50
|
|
|
42
51
|
resolve(line)
|
package/src/spawn.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import child_process from 'child_process'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Spawns a new process.
|
|
5
|
+
* @param {string} cmd - Command to run.
|
|
6
|
+
* @param {string[]} [args=[]] - Arguments for the command.
|
|
7
|
+
* @param {import('child_process').SpawnOptions} [opt={}] - Spawn options.
|
|
8
|
+
* @returns {import('child_process').ChildProcess} The spawned process.
|
|
9
|
+
*/
|
|
10
|
+
export const spawn = (cmd, args = [], opt = {}) => {
|
|
11
|
+
/** @type {import('child_process').SpawnOptions} */
|
|
12
|
+
const opts = {
|
|
13
|
+
cwd: process.cwd(),
|
|
14
|
+
env: process.env,
|
|
15
|
+
stdio: 'inherit',
|
|
16
|
+
...opt,
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return child_process.spawn(cmd, args, opts)
|
|
20
|
+
}
|
package/types/exec.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function envToHelp(env: Array<[string[], string, string]>): string
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function findLongestString(arr: Array<string | string[]>): string
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
export function maybeHelp(args: CLIArgs): string | false
|
|
2
|
+
export type ParsedCLI = {
|
|
3
|
+
/**
|
|
4
|
+
* - Parsed CLI flags or arguments.
|
|
5
|
+
*/
|
|
6
|
+
args?: Record<string, any> | undefined
|
|
7
|
+
/**
|
|
8
|
+
* - Parsed subcommands.
|
|
9
|
+
*/
|
|
10
|
+
commands?: Record<string, any> | undefined
|
|
11
|
+
/**
|
|
12
|
+
* - Validation errors or missing required args.
|
|
13
|
+
*/
|
|
14
|
+
errors?: (string | string[])[] | undefined
|
|
15
|
+
}
|
|
16
|
+
export type CLIHelpMeta = {
|
|
17
|
+
/**
|
|
18
|
+
* - CLI name shown in the help header.
|
|
19
|
+
*/
|
|
20
|
+
name?: string | undefined
|
|
21
|
+
/**
|
|
22
|
+
* - General help text or description.
|
|
23
|
+
*/
|
|
24
|
+
text?: string | undefined
|
|
25
|
+
/**
|
|
26
|
+
* - Example usage text or lines.
|
|
27
|
+
*/
|
|
28
|
+
example?: string | string[] | undefined
|
|
29
|
+
/**
|
|
30
|
+
* - Help text for commands.
|
|
31
|
+
*/
|
|
32
|
+
commands?: Record<string, string> | undefined
|
|
33
|
+
/**
|
|
34
|
+
* - Help text for options/flags.
|
|
35
|
+
*/
|
|
36
|
+
options?: Record<string, string> | undefined
|
|
37
|
+
/**
|
|
38
|
+
* - Help text for environment variables.
|
|
39
|
+
*/
|
|
40
|
+
env?: Record<string, string> | undefined
|
|
41
|
+
}
|
|
42
|
+
export type CLIArgs = {
|
|
43
|
+
/**
|
|
44
|
+
* - Parsed CLI data (from argument parser).
|
|
45
|
+
*/
|
|
46
|
+
parsed?: ParsedCLI | undefined
|
|
47
|
+
/**
|
|
48
|
+
* - CLI commands or argument definitions.
|
|
49
|
+
*/
|
|
50
|
+
commands?: (string | string[])[] | undefined
|
|
51
|
+
/**
|
|
52
|
+
* - CLI option/flag definitions.
|
|
53
|
+
*/
|
|
54
|
+
options?: (string | string[])[] | undefined
|
|
55
|
+
/**
|
|
56
|
+
* - Environment variable mappings.
|
|
57
|
+
*/
|
|
58
|
+
env?: [string[], string, string][] | undefined
|
|
59
|
+
/**
|
|
60
|
+
* - Default values for options or flags.
|
|
61
|
+
*/
|
|
62
|
+
default?: Record<string, any> | undefined
|
|
63
|
+
/**
|
|
64
|
+
* - Help configuration or raw string help text.
|
|
65
|
+
*/
|
|
66
|
+
help?: CLIHelpMeta | undefined
|
|
67
|
+
}
|
package/types/index.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export function cli(args?: { options?: (string | string[])[] | undefined }): object
|
|
2
|
+
export namespace cli {
|
|
3
|
+
export { spawner as spawn }
|
|
4
|
+
export { execute as exec }
|
|
5
|
+
export { promptUser as prompt }
|
|
6
|
+
export { executeFile as execFile }
|
|
7
|
+
}
|
|
8
|
+
export const spawn: (
|
|
9
|
+
cmd: string,
|
|
10
|
+
args?: string[],
|
|
11
|
+
opt?: import('child_process').SpawnOptions,
|
|
12
|
+
) => import('child_process').ChildProcess
|
|
13
|
+
export const exec: (
|
|
14
|
+
cmd: string,
|
|
15
|
+
options?: {
|
|
16
|
+
stderrToStdout?: boolean | undefined
|
|
17
|
+
},
|
|
18
|
+
) => Promise<string>
|
|
19
|
+
export const prompt: (
|
|
20
|
+
msg?: string | string[],
|
|
21
|
+
options?: {
|
|
22
|
+
yesNo?: boolean | undefined
|
|
23
|
+
yesDefault?: boolean | undefined
|
|
24
|
+
std?: NodeJS.Process | undefined
|
|
25
|
+
},
|
|
26
|
+
) => Promise<string | boolean>
|
|
27
|
+
export const execFile: (
|
|
28
|
+
p: string,
|
|
29
|
+
args?: string[],
|
|
30
|
+
opts?: import('child_process').ExecFileOptions,
|
|
31
|
+
) => Promise<string | Buffer>
|
|
32
|
+
export default cli
|
|
33
|
+
import { spawn as spawner } from './spawn.js'
|
|
34
|
+
import { exec as execute } from './exec.js'
|
|
35
|
+
import { prompt as promptUser } from './prompt.js'
|
|
36
|
+
import { execFile as executeFile } from './execFile.js'
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export function parseArgv(props?: ParseArgvProps): ParseArgvResult
|
|
2
|
+
export type Option = string | string[]
|
|
3
|
+
export type ArgMap = Record<string, string | string[]>
|
|
4
|
+
export type ParseArgvProps = {
|
|
5
|
+
/**
|
|
6
|
+
* - CLI option names or aliases.
|
|
7
|
+
*/
|
|
8
|
+
options?: Option[] | undefined
|
|
9
|
+
/**
|
|
10
|
+
* - Arguments to prepend to process.argv.
|
|
11
|
+
*/
|
|
12
|
+
prepend?: string[] | ArgMap | undefined
|
|
13
|
+
/**
|
|
14
|
+
* - Arguments to append to process.argv.
|
|
15
|
+
*/
|
|
16
|
+
append?: string[] | ArgMap | undefined
|
|
17
|
+
/**
|
|
18
|
+
* - Default values for options.
|
|
19
|
+
*/
|
|
20
|
+
default?: ArgMap | undefined
|
|
21
|
+
/**
|
|
22
|
+
* - If true, do not modify process.argv.
|
|
23
|
+
*/
|
|
24
|
+
pure?: boolean | undefined
|
|
25
|
+
}
|
|
26
|
+
export type ParseArgvResult = {
|
|
27
|
+
/**
|
|
28
|
+
* - Raw argument key/value map.
|
|
29
|
+
*/
|
|
30
|
+
argv: Record<string, string[]>
|
|
31
|
+
/**
|
|
32
|
+
* - Camel-cased argument key/value map.
|
|
33
|
+
*/
|
|
34
|
+
args: Record<string, string[]>
|
|
35
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export function clean(
|
|
2
|
+
cli: import('./index.js').ParsedCLI,
|
|
3
|
+
props?: CleanProps,
|
|
4
|
+
): import('./index.js').ParsedCLI
|
|
5
|
+
export type CleanProps = {
|
|
6
|
+
/**
|
|
7
|
+
* - List of single-value argument keys to clean.
|
|
8
|
+
*/
|
|
9
|
+
single?: string[] | undefined
|
|
10
|
+
/**
|
|
11
|
+
* - Default values for arguments.
|
|
12
|
+
*/
|
|
13
|
+
default?: Record<string, any> | undefined
|
|
14
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export function parseCommands(props?: ParseCommandsProps): Record<string, boolean>
|
|
2
|
+
export type ParseCommandsProps = {
|
|
3
|
+
/**
|
|
4
|
+
* - Commands or alias arrays to check.
|
|
5
|
+
*/
|
|
6
|
+
commands?: (string | string[])[] | undefined
|
|
7
|
+
/**
|
|
8
|
+
* - If true, do not modify process.argv.
|
|
9
|
+
*/
|
|
10
|
+
pure?: boolean | undefined
|
|
11
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export function parseEnv({ env, pure }: ParseEnvProps): Record<string, string>
|
|
2
|
+
/**
|
|
3
|
+
* Tuple of: [CLI switches], environment variable name, value].
|
|
4
|
+
*/
|
|
5
|
+
export type EnvTuple = [string | string[], string, string]
|
|
6
|
+
export type ParseEnvProps = {
|
|
7
|
+
/**
|
|
8
|
+
* - Environment variables to parse.
|
|
9
|
+
*/
|
|
10
|
+
env: EnvTuple[]
|
|
11
|
+
/**
|
|
12
|
+
* - If true, do not modify process.env.
|
|
13
|
+
*/
|
|
14
|
+
pure?: boolean | undefined
|
|
15
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export function parse(props: ParseProps): ParsedCLI
|
|
2
|
+
export type ParseProps = {
|
|
3
|
+
options?: (string | string[])[] | undefined
|
|
4
|
+
prepend?: any[] | Record<string, any> | undefined
|
|
5
|
+
append?: any[] | Record<string, any> | undefined
|
|
6
|
+
default?: Record<string, any> | undefined
|
|
7
|
+
pure?: boolean | undefined
|
|
8
|
+
pureEnv?: boolean | undefined
|
|
9
|
+
pureArgv?: boolean | undefined
|
|
10
|
+
pureCommands?: boolean | undefined
|
|
11
|
+
commands?: (string | string[])[] | undefined
|
|
12
|
+
env?: [string[], string, string][] | undefined
|
|
13
|
+
required?: (string | string[])[] | undefined
|
|
14
|
+
help?: object | undefined
|
|
15
|
+
}
|
|
16
|
+
export type ParsedCLI = {
|
|
17
|
+
env: Record<string, string>
|
|
18
|
+
argv: Record<string, any>
|
|
19
|
+
args: Record<string, any>
|
|
20
|
+
commands: Record<string, boolean>
|
|
21
|
+
errors: Array<string | string[]>
|
|
22
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export function parseRequired(args?: ParseRequiredArgs): Array<string | string[]>
|
|
2
|
+
export type ParsedCLI = {
|
|
3
|
+
env: Record<string, string>
|
|
4
|
+
argv: Record<string, any>
|
|
5
|
+
args: Record<string, any>
|
|
6
|
+
commands: Record<string, boolean>
|
|
7
|
+
errors: Array<string | string[]>
|
|
8
|
+
}
|
|
9
|
+
export type ParseRequiredArgs = {
|
|
10
|
+
parsed?: ParsedCLI | undefined
|
|
11
|
+
props?:
|
|
12
|
+
| {
|
|
13
|
+
required?: string | (string | string[])[] | undefined
|
|
14
|
+
}
|
|
15
|
+
| undefined
|
|
16
|
+
}
|
package/types/spawn.d.ts
ADDED
package/src/exec.mjs
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import child_process from 'child_process'
|
|
2
|
-
|
|
3
|
-
import error from '@magic/error'
|
|
4
|
-
|
|
5
|
-
const libName = '@magic/cli.exec'
|
|
6
|
-
|
|
7
|
-
export const exec = (cmd, options = {}) =>
|
|
8
|
-
new Promise((resolve, reject) => {
|
|
9
|
-
child_process.exec(cmd, options, (err, stdout, stderr) => {
|
|
10
|
-
if (err) {
|
|
11
|
-
const e = error(err, 'E_EXEC_ERR')
|
|
12
|
-
reject(e)
|
|
13
|
-
return
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
if (stderr) {
|
|
17
|
-
const e = error(new Error(`${libName}: ${cmd} error: ${stderr}`), 'E_EXEC_STDERR')
|
|
18
|
-
reject(e)
|
|
19
|
-
return
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
resolve(stdout)
|
|
23
|
-
})
|
|
24
|
-
})
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import deep from '@magic/deep'
|
|
2
|
-
|
|
3
|
-
export const findLongestString = arr => {
|
|
4
|
-
arr = deep.flatten(arr)
|
|
5
|
-
|
|
6
|
-
const sorted = arr.sort((a, b) => {
|
|
7
|
-
if (a.length !== b.length) {
|
|
8
|
-
return b.length - a.length
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
return a > b ? 1 : -1
|
|
12
|
-
})
|
|
13
|
-
|
|
14
|
-
return sorted[0]
|
|
15
|
-
}
|
package/src/help/index.mjs
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import log from '@magic/log'
|
|
2
|
-
import is from '@magic/types'
|
|
3
|
-
|
|
4
|
-
import { envToHelp } from './envToHelp.mjs'
|
|
5
|
-
import { argToHelp } from './argToHelp.mjs'
|
|
6
|
-
|
|
7
|
-
export const maybeHelp = args => {
|
|
8
|
-
const { parsed } = args
|
|
9
|
-
const hasCommands = args.commands && Object.entries(args.commands).length > 0
|
|
10
|
-
const showCommandHelp = hasCommands && Object.keys(parsed.commands).length === 0
|
|
11
|
-
|
|
12
|
-
const helpRequested = parsed.args.help
|
|
13
|
-
|
|
14
|
-
const showHelp = showCommandHelp || helpRequested || !is.empty(parsed.errors)
|
|
15
|
-
|
|
16
|
-
if (!showHelp) {
|
|
17
|
-
return false
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
// add help text inspection here
|
|
21
|
-
const { commands = [], default: defaults = [], options = [], env = [], help = '' } = args
|
|
22
|
-
|
|
23
|
-
const commandHelp = argToHelp(commands, help.commands)
|
|
24
|
-
const optionHelp = argToHelp(options, help.options, defaults)
|
|
25
|
-
const envHelp = envToHelp(env, help.env)
|
|
26
|
-
|
|
27
|
-
const name = help.name || '@magic/cli wrapped cli.'
|
|
28
|
-
const header = is.string(help) ? help : help.text
|
|
29
|
-
|
|
30
|
-
const exampleArray = is.string(help.example) ? help.example.split('\n') : help.example
|
|
31
|
-
|
|
32
|
-
const exampleText = exampleArray
|
|
33
|
-
.map(a => {
|
|
34
|
-
if (a.trim().startsWith('#')) {
|
|
35
|
-
return log.color('green', a)
|
|
36
|
-
} else {
|
|
37
|
-
return a.trim()
|
|
38
|
-
}
|
|
39
|
-
})
|
|
40
|
-
.join('\n')
|
|
41
|
-
|
|
42
|
-
const helpArray = [
|
|
43
|
-
log.paint('green', name),
|
|
44
|
-
'\n',
|
|
45
|
-
header && `\n${log.paint('grey', header)}\n\n`,
|
|
46
|
-
commands.length && `${log.paint('grey', 'commands')}:\n${commandHelp}\n\n`,
|
|
47
|
-
options.length && `${log.paint('grey', 'flags')}:\n${optionHelp}\n\n`,
|
|
48
|
-
env.length && `${log.paint('grey', 'environment switches')}:\n${envHelp}\n\n`,
|
|
49
|
-
'examples:\n',
|
|
50
|
-
exampleText,
|
|
51
|
-
]
|
|
52
|
-
|
|
53
|
-
const errors = parsed.errors
|
|
54
|
-
.map(e => `${log.paint('red', 'Error:')} ${is.arr(e) ? e.join(' or ') : e} is required`)
|
|
55
|
-
.filter(a => a)
|
|
56
|
-
.join('\n')
|
|
57
|
-
|
|
58
|
-
const errorMsg = `\n${errors}`
|
|
59
|
-
if (errors.length) {
|
|
60
|
-
helpArray.push(errorMsg)
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
return helpArray.filter(a => a).join('')
|
|
64
|
-
}
|
package/src/parse/argv.mjs
DELETED
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
import is from '@magic/types'
|
|
2
|
-
import cases from '@magic/cases'
|
|
3
|
-
|
|
4
|
-
export const parseArgv = ({
|
|
5
|
-
options = [],
|
|
6
|
-
prepend = {},
|
|
7
|
-
append = {},
|
|
8
|
-
default: def = {},
|
|
9
|
-
pure = false,
|
|
10
|
-
}) => {
|
|
11
|
-
let lastArg
|
|
12
|
-
const argv = {}
|
|
13
|
-
// map over argv, find arguments and values.
|
|
14
|
-
// arguments are all strings starting with a -,
|
|
15
|
-
// values are all strings between strings starting with a -.
|
|
16
|
-
process.argv.forEach((arg, i) => {
|
|
17
|
-
if (i <= 1) {
|
|
18
|
-
return arg
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
if (arg.startsWith('-')) {
|
|
22
|
-
// this is a key
|
|
23
|
-
let argvArg
|
|
24
|
-
options.forEach(option => {
|
|
25
|
-
if (is.array(option)) {
|
|
26
|
-
if (option.some(opt => opt === arg)) {
|
|
27
|
-
argvArg = option[0]
|
|
28
|
-
}
|
|
29
|
-
} else if (option === arg) {
|
|
30
|
-
argvArg = option
|
|
31
|
-
}
|
|
32
|
-
})
|
|
33
|
-
if (argvArg) {
|
|
34
|
-
lastArg = argvArg
|
|
35
|
-
argv[lastArg] = []
|
|
36
|
-
if (!pure) {
|
|
37
|
-
process.argv[i] = lastArg
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
} else {
|
|
41
|
-
// this is a value
|
|
42
|
-
if (lastArg) {
|
|
43
|
-
argv[lastArg].push(arg)
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
})
|
|
47
|
-
|
|
48
|
-
const [argv1, argv2, ...argvRest] = process.argv
|
|
49
|
-
|
|
50
|
-
const entries = Object.entries(def)
|
|
51
|
-
|
|
52
|
-
if (entries.length) {
|
|
53
|
-
entries.forEach(([k, v]) => {
|
|
54
|
-
if (is.empty(argv[k])) {
|
|
55
|
-
argv[k] = v
|
|
56
|
-
|
|
57
|
-
argvRest.push(k)
|
|
58
|
-
if (!is.array(v)) {
|
|
59
|
-
v = [v]
|
|
60
|
-
}
|
|
61
|
-
v.forEach(vv => argvRest.push(vv))
|
|
62
|
-
}
|
|
63
|
-
})
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
let argvPrepend = []
|
|
67
|
-
if (!is.array(prepend)) {
|
|
68
|
-
argvPrepend.push(prepend)
|
|
69
|
-
} else if (prepend.length) {
|
|
70
|
-
Object.entries(prepend).forEach(([k, v]) => {
|
|
71
|
-
argv[k] = v
|
|
72
|
-
|
|
73
|
-
argvPrepend.push(k)
|
|
74
|
-
if (!is.array(v)) {
|
|
75
|
-
argvPrepend.push(v)
|
|
76
|
-
} else {
|
|
77
|
-
argvPrepend = [...argvPrepend, ...v]
|
|
78
|
-
}
|
|
79
|
-
})
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
let argvAppend = []
|
|
83
|
-
if (!is.array(append)) {
|
|
84
|
-
argvAppend.push(append)
|
|
85
|
-
} else if (append.length) {
|
|
86
|
-
Object.entries(append)
|
|
87
|
-
.forEach(([k, v]) => {
|
|
88
|
-
argv[k] = v
|
|
89
|
-
|
|
90
|
-
argvAppend.push(k)
|
|
91
|
-
if (!is.array(v)) {
|
|
92
|
-
argvAppend.push(v)
|
|
93
|
-
} else {
|
|
94
|
-
argvAppend = [...argvAppend, ...v]
|
|
95
|
-
}
|
|
96
|
-
})
|
|
97
|
-
.filter(a => a)
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
if (!pure) {
|
|
101
|
-
const argvArgs = [argv1, argv2, ...argvAppend, ...argvRest, ...argvPrepend].filter(
|
|
102
|
-
a => a && a.length > 0,
|
|
103
|
-
)
|
|
104
|
-
|
|
105
|
-
process.argv = argvArgs
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
const args = {}
|
|
109
|
-
|
|
110
|
-
Object.entries(argv).map(([k, v]) => {
|
|
111
|
-
args[cases.camel(k)] = v
|
|
112
|
-
})
|
|
113
|
-
|
|
114
|
-
return {
|
|
115
|
-
argv,
|
|
116
|
-
args,
|
|
117
|
-
}
|
|
118
|
-
}
|
package/src/parse/env.mjs
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import is from '@magic/types'
|
|
2
|
-
|
|
3
|
-
export const parseEnv = ({ env = [], pure = false }) => {
|
|
4
|
-
const environment = []
|
|
5
|
-
|
|
6
|
-
// set env depending on env switches
|
|
7
|
-
env
|
|
8
|
-
.filter(([argv]) => {
|
|
9
|
-
if (!is.array(argv)) {
|
|
10
|
-
argv = [argv]
|
|
11
|
-
}
|
|
12
|
-
return argv.some(a => process.argv.includes(a))
|
|
13
|
-
})
|
|
14
|
-
.map(([_, key, val]) => {
|
|
15
|
-
environment[key] = val
|
|
16
|
-
if (!pure) {
|
|
17
|
-
process.env[key] = val
|
|
18
|
-
}
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
return environment
|
|
22
|
-
}
|
package/src/parse/index.mjs
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { parseEnv } from './env.mjs'
|
|
2
|
-
import { parseArgv } from './argv.mjs'
|
|
3
|
-
import { parseCommands } from './commands.mjs'
|
|
4
|
-
import { parseRequired } from './required.mjs'
|
|
5
|
-
import { clean } from './clean.mjs'
|
|
6
|
-
|
|
7
|
-
export const parse = props => {
|
|
8
|
-
const { pure = false } = props
|
|
9
|
-
|
|
10
|
-
const { pureEnv = pure, pureArgv = pure, pureCommands = pure } = props
|
|
11
|
-
|
|
12
|
-
const env = parseEnv({ ...props, pure: pureEnv })
|
|
13
|
-
const { argv, args } = parseArgv({ ...props, pure: pureArgv })
|
|
14
|
-
const commands = parseCommands({ ...props, pure: pureCommands })
|
|
15
|
-
|
|
16
|
-
const cli = {
|
|
17
|
-
env,
|
|
18
|
-
argv,
|
|
19
|
-
args,
|
|
20
|
-
commands,
|
|
21
|
-
errors: [],
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const parsed = clean(cli, props)
|
|
25
|
-
|
|
26
|
-
parsed.errors = parseRequired({ props, parsed })
|
|
27
|
-
|
|
28
|
-
return parsed
|
|
29
|
-
}
|
package/src/parse/required.mjs
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import is from '@magic/types'
|
|
2
|
-
|
|
3
|
-
export const parseRequired = (args = {}) => {
|
|
4
|
-
const {
|
|
5
|
-
parsed,
|
|
6
|
-
props: { required },
|
|
7
|
-
} = args
|
|
8
|
-
|
|
9
|
-
if (is.empty(required)) {
|
|
10
|
-
return []
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const errors = []
|
|
14
|
-
|
|
15
|
-
required.forEach(req => {
|
|
16
|
-
if (is.array(req)) {
|
|
17
|
-
const some = req.some(a => parsed.argv[a])
|
|
18
|
-
|
|
19
|
-
if (!some) {
|
|
20
|
-
errors.push(req)
|
|
21
|
-
}
|
|
22
|
-
} else {
|
|
23
|
-
const opt = parsed.argv[req]
|
|
24
|
-
|
|
25
|
-
if (is.empty(opt)) {
|
|
26
|
-
errors.push(req)
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
return errors
|
|
32
|
-
}
|