zudojs-cli 1.2.0 → 2.0.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 +35 -1
- package/dist/src/adapters/frontend/flutter.adapter.d.ts +9 -0
- package/dist/src/adapters/frontend/flutter.adapter.js +16 -1
- package/dist/src/bin/zudojs.js +16 -5
- package/dist/src/cliApplication/cliApplication.builtins.d.ts +4 -0
- package/dist/src/cliApplication/cliApplication.builtins.js +28 -9
- package/dist/src/cliApplication/cliApplication.core.d.ts +8 -0
- package/dist/src/cliApplication/cliApplication.core.js +45 -5
- package/dist/src/cliApplication/cliApplication.help.d.ts +17 -0
- package/dist/src/cliApplication/cliApplication.help.js +94 -0
- package/dist/src/cliApplication/cliApplication.logger.js +4 -4
- package/dist/src/cliCommand/cliCommand.validator.js +22 -0
- package/dist/src/cliConstant/cliConstant.value.d.ts +18 -12
- package/dist/src/cliConstant/cliConstant.value.js +25 -19
- package/dist/src/cliError/cliError.argument.js +2 -2
- package/dist/src/cliError/cliError.base.js +28 -5
- package/dist/src/cliError/cliError.command.js +5 -2
- package/dist/src/cliError/cliError.execution.js +3 -3
- package/dist/src/cliParser/cliParser.core.js +15 -6
- package/dist/src/cliParser/cliParser.helper.d.ts +11 -0
- package/dist/src/cliParser/cliParser.helper.js +19 -0
- package/dist/src/cliParser/cliParser.longOption.js +4 -4
- package/dist/src/cliParser/cliParser.shortOption.js +7 -4
- package/dist/src/cliVersion/cliVersion.update.js +5 -3
- package/dist/src/commands/add.command.js +17 -2
- package/dist/src/commands/commandError.helper.d.ts +15 -0
- package/dist/src/commands/commandError.helper.js +28 -0
- package/dist/src/commands/create.command.js +284 -46
- package/dist/src/commands/doctor.command.d.ts +8 -0
- package/dist/src/commands/doctor.command.js +38 -5
- package/dist/src/commands/generate.command.js +71 -32
- package/dist/src/constants/index.d.ts +40 -68
- package/dist/src/constants/index.js +73 -23
- package/dist/src/generators/frontend/frontendPipeline.js +16 -4
- package/dist/src/generators/integration/integrationGenerator.core.js +10 -6
- package/dist/src/generators/project/project.generator.js +5 -1
- package/dist/src/index.d.ts +4 -4
- package/dist/src/index.js +3 -3
- package/dist/src/manifest/index.d.ts +1 -0
- package/dist/src/manifest/index.js +1 -0
- package/dist/src/manifest/manifestFile.helper.d.ts +42 -0
- package/dist/src/manifest/manifestFile.helper.js +141 -0
- package/dist/src/manifest/manifestManager.core.d.ts +16 -0
- package/dist/src/manifest/manifestManager.core.js +65 -35
- package/dist/src/prompts/backend/api-style.prompt.js +2 -5
- package/dist/src/prompts/backend/backend-architecture.prompt.js +5 -22
- package/dist/src/prompts/backend/database.prompt.js +5 -23
- package/dist/src/prompts/backend/services.prompt.js +12 -10
- package/dist/src/prompts/cancel.prompt.d.ts +18 -0
- package/dist/src/prompts/cancel.prompt.js +26 -0
- package/dist/src/prompts/capabilities/capabilities.prompt.js +2 -5
- package/dist/src/prompts/frontend/framework.prompt.js +2 -5
- package/dist/src/prompts/frontend/frontend-architecture.prompt.js +2 -5
- package/dist/src/prompts/index.d.ts +1 -0
- package/dist/src/prompts/index.js +1 -0
- package/dist/src/prompts/project/confirmation.prompt.js +2 -5
- package/dist/src/prompts/project/project-name.prompt.js +6 -7
- package/dist/src/prompts/project/project-type.prompt.js +2 -5
- package/dist/src/prompts/workspace/package-manager.prompt.js +5 -12
- package/dist/src/registries/adapter/frontendAdapterRegistry.core.d.ts +6 -0
- package/dist/src/registries/adapter/frontendAdapterRegistry.core.js +12 -0
- package/dist/src/registries/adapter/packageManagerRegistry.core.d.ts +5 -0
- package/dist/src/registries/adapter/packageManagerRegistry.core.js +11 -0
- package/dist/src/registries/dependency/dependencyRegistry.core.d.ts +9 -0
- package/dist/src/registries/dependency/dependencyRegistry.core.js +16 -0
- package/dist/src/registries/generator/generatorRegistry.core.d.ts +8 -0
- package/dist/src/registries/generator/generatorRegistry.core.js +14 -0
- package/dist/src/resolvers/capability/capabilityResolver.core.d.ts +1 -1
- package/dist/src/resolvers/capability/capabilityResolver.core.js +0 -2
- package/dist/src/resolvers/layout/projectLayout.core.js +1 -6
- package/dist/src/resolvers/project.resolver.d.ts +9 -3
- package/dist/src/resolvers/project.resolver.js +11 -7
- package/dist/src/rollback/index.d.ts +1 -1
- package/dist/src/rollback/index.js +1 -1
- package/dist/src/rollback/rollbackManager.core.d.ts +19 -1
- package/dist/src/rollback/rollbackManager.core.js +21 -2
- package/dist/src/runners/package-manager/index.d.ts +1 -1
- package/dist/src/runners/package-manager/index.js +1 -1
- package/dist/src/runners/package-manager/packageManagerRunner.core.d.ts +13 -1
- package/dist/src/runners/package-manager/packageManagerRunner.core.js +19 -1
- package/dist/src/runners/process/processRunner.core.d.ts +11 -0
- package/dist/src/runners/process/processRunner.core.js +41 -6
- package/dist/src/runners/task/index.d.ts +1 -1
- package/dist/src/runners/task/taskRunner.core.d.ts +22 -1
- package/dist/src/runners/task/taskRunner.core.js +35 -6
- package/dist/src/scaffolders/framework.scaffolder.js +3 -0
- package/dist/src/scaffolders/scaffolder.helper.d.ts +10 -0
- package/dist/src/scaffolders/scaffolder.helper.js +25 -2
- package/dist/src/templates/microservice/index.d.ts +1 -1
- package/dist/src/templates/microservice/index.js +1 -1
- package/dist/src/templates/microservice/microservice.template.d.ts +8 -4
- package/dist/src/templates/microservice/microservice.template.js +30 -19
- package/dist/src/templates/modular-monolith/modularMonolith.template.js +27 -8
- package/dist/src/templates/monolith/monolith.template.js +11 -17
- package/dist/src/templates/shared/capability.template.d.ts +25 -0
- package/dist/src/templates/shared/capability.template.js +46 -0
- package/dist/src/templates/shared/index.d.ts +1 -0
- package/dist/src/templates/shared/index.js +1 -0
- package/dist/src/utils/utils.exec.d.ts +22 -0
- package/dist/src/utils/utils.exec.js +51 -4
- package/dist/src/utils/utils.fileSystem.js +46 -2
- package/dist/src/utils/utils.name.d.ts +9 -0
- package/dist/src/utils/utils.name.js +29 -3
- package/dist/src/validators/environment/environmentValidator.core.d.ts +11 -1
- package/dist/src/validators/environment/environmentValidator.core.js +40 -73
- package/dist/src/validators/project/index.d.ts +1 -1
- package/dist/src/validators/project/projectValidator.core.d.ts +11 -1
- package/dist/src/validators/project/projectValidator.core.js +20 -4
- package/package.json +6 -6
|
@@ -11,20 +11,31 @@ import { CLI_VERSION } from "./cliVersion.js";
|
|
|
11
11
|
export const CLI_NAME = "zudojs";
|
|
12
12
|
/** Default application configuration. */
|
|
13
13
|
export const CLI_DEFAULTS = {
|
|
14
|
-
NAME:
|
|
14
|
+
NAME: CLI_NAME,
|
|
15
15
|
VERSION: CLI_VERSION,
|
|
16
16
|
DESCRIPTION: "Command-line interface for the Zudojs framework.",
|
|
17
|
-
COMMAND_PREFIX:
|
|
17
|
+
COMMAND_PREFIX: CLI_NAME,
|
|
18
18
|
DEFAULT_CWD: process.cwd(),
|
|
19
19
|
EXIT_CODE: 0,
|
|
20
20
|
};
|
|
21
21
|
/* -------------------------------------------------------------------------- */
|
|
22
|
+
/* Symbolic Names */
|
|
23
|
+
/* -------------------------------------------------------------------------- */
|
|
24
|
+
/** Internal symbolic names for CLI elements. */
|
|
25
|
+
export const CLI_SYMBOLS = {
|
|
26
|
+
COMMAND: "command",
|
|
27
|
+
OPTION: "option",
|
|
28
|
+
ARGUMENT: "argument",
|
|
29
|
+
HELP: "help",
|
|
30
|
+
VERSION: "version",
|
|
31
|
+
};
|
|
32
|
+
/* -------------------------------------------------------------------------- */
|
|
22
33
|
/* Built-in Commands */
|
|
23
34
|
/* -------------------------------------------------------------------------- */
|
|
24
35
|
/** Built-in command names. */
|
|
25
36
|
export const CLI_COMMANDS = {
|
|
26
|
-
HELP:
|
|
27
|
-
VERSION:
|
|
37
|
+
HELP: CLI_SYMBOLS.HELP,
|
|
38
|
+
VERSION: CLI_SYMBOLS.VERSION,
|
|
28
39
|
};
|
|
29
40
|
/** Built-in command aliases. */
|
|
30
41
|
export const CLI_ALIASES = {
|
|
@@ -41,17 +52,6 @@ export const CLI_OPTION_PREFIXES = {
|
|
|
41
52
|
VALUE_SEPARATOR: "=",
|
|
42
53
|
};
|
|
43
54
|
/* -------------------------------------------------------------------------- */
|
|
44
|
-
/* Symbolic Names */
|
|
45
|
-
/* -------------------------------------------------------------------------- */
|
|
46
|
-
/** Internal symbolic names for CLI elements. */
|
|
47
|
-
export const CLI_SYMBOLS = {
|
|
48
|
-
COMMAND: "command",
|
|
49
|
-
OPTION: "option",
|
|
50
|
-
ARGUMENT: "argument",
|
|
51
|
-
HELP: "help",
|
|
52
|
-
VERSION: "version",
|
|
53
|
-
};
|
|
54
|
-
/* -------------------------------------------------------------------------- */
|
|
55
55
|
/* User-Facing Messages */
|
|
56
56
|
/* -------------------------------------------------------------------------- */
|
|
57
57
|
/** Standard CLI messages. */
|
|
@@ -61,7 +61,7 @@ export const CLI_MESSAGES = {
|
|
|
61
61
|
PERMISSION_DENIED: "Permission denied.",
|
|
62
62
|
INTERRUPTED: "Process interrupted.",
|
|
63
63
|
UNKNOWN_ERROR: "An unexpected error occurred.",
|
|
64
|
-
MISSING_COMMAND: "
|
|
64
|
+
MISSING_COMMAND: "No command given.",
|
|
65
65
|
};
|
|
66
66
|
/* -------------------------------------------------------------------------- */
|
|
67
67
|
/* Help Labels */
|
|
@@ -79,11 +79,17 @@ export const CLI_HELP = {
|
|
|
79
79
|
/* -------------------------------------------------------------------------- */
|
|
80
80
|
/* Environment */
|
|
81
81
|
/* -------------------------------------------------------------------------- */
|
|
82
|
-
/**
|
|
82
|
+
/**
|
|
83
|
+
* Environment variable names the CLI reads.
|
|
84
|
+
*
|
|
85
|
+
* Every entry has a single reader: `DEBUG` turns on verbose logging,
|
|
86
|
+
* `CI` and `NO_UPDATE_CHECK`/`NPM_OFFLINE` suppress the update check.
|
|
87
|
+
*/
|
|
83
88
|
export const CLI_ENVIRONMENT = {
|
|
84
|
-
|
|
85
|
-
DEBUG: "DEBUG",
|
|
89
|
+
DEBUG: "ZUDOJS_DEBUG",
|
|
86
90
|
CI: "CI",
|
|
91
|
+
NO_UPDATE_CHECK: "ZUDOJS_NO_UPDATE_CHECK",
|
|
92
|
+
NPM_OFFLINE: "npm_config_offline",
|
|
87
93
|
};
|
|
88
94
|
/* -------------------------------------------------------------------------- */
|
|
89
95
|
/* Formatting */
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Error classes for argument validation failures.
|
|
5
5
|
*/
|
|
6
6
|
import { CLIError } from "./cliError.base.js";
|
|
7
|
-
import { CLI_ERROR_CODES, CLI_EXIT_CODES, } from "../cliConstant/cliConstant.value.js";
|
|
7
|
+
import { CLI_ERROR_CODES, CLI_EXIT_CODES, CLI_MESSAGES, } from "../cliConstant/cliConstant.value.js";
|
|
8
8
|
/* -------------------------------------------------------------------------- */
|
|
9
9
|
/* Invalid Arguments */
|
|
10
10
|
/* -------------------------------------------------------------------------- */
|
|
@@ -12,7 +12,7 @@ import { CLI_ERROR_CODES, CLI_EXIT_CODES, } from "../cliConstant/cliConstant.val
|
|
|
12
12
|
* Thrown when command arguments fail validation.
|
|
13
13
|
*/
|
|
14
14
|
export class InvalidArgumentsError extends CLIError {
|
|
15
|
-
constructor(message =
|
|
15
|
+
constructor(message = CLI_MESSAGES.INVALID_ARGUMENTS, options = {}) {
|
|
16
16
|
super(message, {
|
|
17
17
|
...options,
|
|
18
18
|
code: CLI_ERROR_CODES.INVALID_ARGUMENTS,
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* command, option, argument).
|
|
7
7
|
*/
|
|
8
8
|
import { ApplicationError } from "@zudojs/errors";
|
|
9
|
-
import { CLI_ERROR_CODES, CLI_EXIT_CODES, } from "../cliConstant/cliConstant.value.js";
|
|
9
|
+
import { CLI_ERROR_CODES, CLI_EXIT_CODES, CLI_MESSAGES, } from "../cliConstant/cliConstant.value.js";
|
|
10
10
|
/**
|
|
11
11
|
* Base error for all CLI subsystem failures.
|
|
12
12
|
*
|
|
@@ -54,21 +54,44 @@ export class CLIError extends ApplicationError {
|
|
|
54
54
|
export function isCLIError(error) {
|
|
55
55
|
return error instanceof CLIError;
|
|
56
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* Reads a process exit code carried by an arbitrary error.
|
|
59
|
+
*
|
|
60
|
+
* Only `CLIError` extends this base class; `CommandNotFoundError`,
|
|
61
|
+
* `CLIPermissionError` and the other errors built on `@zudojs/errors`
|
|
62
|
+
* declare their own `exitCode` field. Without this, every one of them was
|
|
63
|
+
* re-wrapped as `GENERAL_ERROR` and the declared `COMMAND_NOT_FOUND` (3),
|
|
64
|
+
* `PERMISSION_DENIED` (4) and `INTERRUPTED` (130) codes never reached the
|
|
65
|
+
* shell.
|
|
66
|
+
*/
|
|
67
|
+
function readExitCode(error) {
|
|
68
|
+
if (typeof error !== "object" || error === null)
|
|
69
|
+
return undefined;
|
|
70
|
+
const candidate = error.exitCode;
|
|
71
|
+
if (typeof candidate !== "number" ||
|
|
72
|
+
!Number.isInteger(candidate) ||
|
|
73
|
+
candidate < 0 ||
|
|
74
|
+
candidate > 255) {
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
return candidate;
|
|
78
|
+
}
|
|
57
79
|
/** Normalizes any error into a CLIError. */
|
|
58
|
-
export function normalizeCLIError(error, fallbackMessage =
|
|
80
|
+
export function normalizeCLIError(error, fallbackMessage = CLI_MESSAGES.UNKNOWN_ERROR) {
|
|
59
81
|
if (error instanceof CLIError) {
|
|
60
82
|
return error;
|
|
61
83
|
}
|
|
84
|
+
const exitCode = readExitCode(error) ?? CLI_EXIT_CODES.GENERAL_ERROR;
|
|
62
85
|
if (error instanceof Error) {
|
|
63
86
|
return new CLIError(error.message || fallbackMessage, {
|
|
64
87
|
code: CLI_ERROR_CODES.UNKNOWN_ERROR,
|
|
65
|
-
exitCode
|
|
88
|
+
exitCode,
|
|
66
89
|
cause: error,
|
|
67
90
|
});
|
|
68
91
|
}
|
|
69
92
|
return new CLIError(fallbackMessage, {
|
|
70
93
|
code: CLI_ERROR_CODES.UNKNOWN_ERROR,
|
|
71
|
-
exitCode
|
|
94
|
+
exitCode,
|
|
72
95
|
cause: error,
|
|
73
96
|
});
|
|
74
97
|
}
|
|
@@ -77,7 +100,7 @@ export function getCLIExitCode(error) {
|
|
|
77
100
|
if (isCLIError(error)) {
|
|
78
101
|
return error.exitCode;
|
|
79
102
|
}
|
|
80
|
-
return CLI_EXIT_CODES.GENERAL_ERROR;
|
|
103
|
+
return readExitCode(error) ?? CLI_EXIT_CODES.GENERAL_ERROR;
|
|
81
104
|
}
|
|
82
105
|
/** Extracts the error code from an error. */
|
|
83
106
|
export function getCLIErrorCode(error) {
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Extends base errors from `@zudojs/errors` where possible.
|
|
6
6
|
*/
|
|
7
7
|
import { NotFoundError, ConflictError } from "@zudojs/errors";
|
|
8
|
-
import { CLI_ERROR_CODES, CLI_EXIT_CODES, } from "../cliConstant/cliConstant.value.js";
|
|
8
|
+
import { CLI_ERROR_CODES, CLI_EXIT_CODES, CLI_MESSAGES, } from "../cliConstant/cliConstant.value.js";
|
|
9
9
|
/* -------------------------------------------------------------------------- */
|
|
10
10
|
/* Command Not Found */
|
|
11
11
|
/* -------------------------------------------------------------------------- */
|
|
@@ -16,7 +16,10 @@ import { CLI_ERROR_CODES, CLI_EXIT_CODES, } from "../cliConstant/cliConstant.val
|
|
|
16
16
|
export class CommandNotFoundError extends NotFoundError {
|
|
17
17
|
exitCode;
|
|
18
18
|
constructor(command) {
|
|
19
|
-
|
|
19
|
+
const message = command
|
|
20
|
+
? `Command "${command}" was not found.`
|
|
21
|
+
: CLI_MESSAGES.COMMAND_NOT_FOUND;
|
|
22
|
+
super(message, {
|
|
20
23
|
code: CLI_ERROR_CODES.COMMAND_NOT_FOUND,
|
|
21
24
|
statusCode: 404,
|
|
22
25
|
expose: true,
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { AuthorizationError, ConfigurationError } from "@zudojs/errors";
|
|
7
7
|
import { CLIError } from "./cliError.base.js";
|
|
8
|
-
import { CLI_ERROR_CODES, CLI_EXIT_CODES, } from "../cliConstant/cliConstant.value.js";
|
|
8
|
+
import { CLI_ERROR_CODES, CLI_EXIT_CODES, CLI_MESSAGES, } from "../cliConstant/cliConstant.value.js";
|
|
9
9
|
/* -------------------------------------------------------------------------- */
|
|
10
10
|
/* Execution Error */
|
|
11
11
|
/* -------------------------------------------------------------------------- */
|
|
@@ -32,7 +32,7 @@ export class CLIExecutionError extends CLIError {
|
|
|
32
32
|
*/
|
|
33
33
|
export class CLIPermissionError extends AuthorizationError {
|
|
34
34
|
exitCode;
|
|
35
|
-
constructor(message =
|
|
35
|
+
constructor(message = CLI_MESSAGES.PERMISSION_DENIED, options = {}) {
|
|
36
36
|
super(message, {
|
|
37
37
|
...options,
|
|
38
38
|
code: CLI_ERROR_CODES.PERMISSION_DENIED,
|
|
@@ -56,7 +56,7 @@ export class CLIPermissionError extends AuthorizationError {
|
|
|
56
56
|
* Thrown when the CLI process is interrupted (e.g. SIGINT).
|
|
57
57
|
*/
|
|
58
58
|
export class CLIInterruptedError extends CLIError {
|
|
59
|
-
constructor(message =
|
|
59
|
+
constructor(message = CLI_MESSAGES.INTERRUPTED, options = {}) {
|
|
60
60
|
super(message, {
|
|
61
61
|
...options,
|
|
62
62
|
code: CLI_ERROR_CODES.INTERRUPTED,
|
|
@@ -32,9 +32,13 @@ export class CLIParser {
|
|
|
32
32
|
const definitions = command?.options ?? [];
|
|
33
33
|
const argumentsDefinitions = command?.arguments ?? [];
|
|
34
34
|
let index = 0;
|
|
35
|
+
// Where the `--` pass-through began, if it did: everything after it is
|
|
36
|
+
// deliberately opaque and is never measured against the declarations.
|
|
37
|
+
let escapedAt;
|
|
35
38
|
while (index < tokens.length) {
|
|
36
39
|
const token = tokens[index];
|
|
37
40
|
if (token === "--") {
|
|
41
|
+
escapedAt = positional.length;
|
|
38
42
|
positional.push(...tokens.slice(index + 1));
|
|
39
43
|
break;
|
|
40
44
|
}
|
|
@@ -64,8 +68,13 @@ export class CLIParser {
|
|
|
64
68
|
options[definition.name] = definition.defaultValue;
|
|
65
69
|
}
|
|
66
70
|
}
|
|
67
|
-
|
|
68
|
-
|
|
71
|
+
// Surplus positionals are only an error once a command is known: with no
|
|
72
|
+
// command there is no declaration to measure them against.
|
|
73
|
+
const parsedArguments = this.parseArguments(positional, argumentsDefinitions, command === undefined ? null : (escapedAt ?? positional.length));
|
|
74
|
+
// `stopAtFirstArgument` is checked here too: without it the fallback undid
|
|
75
|
+
// the flag, putting the first positional in both `commands` and `args`.
|
|
76
|
+
if (!this.stopAtFirstArgument &&
|
|
77
|
+
!this.allowUnknownCommands &&
|
|
69
78
|
!command &&
|
|
70
79
|
commands.length === 0 &&
|
|
71
80
|
tokens.length > 0) {
|
|
@@ -82,10 +91,8 @@ export class CLIParser {
|
|
|
82
91
|
};
|
|
83
92
|
}
|
|
84
93
|
/* ---- Arguments ---- */
|
|
85
|
-
parseArguments(values, definitions) {
|
|
94
|
+
parseArguments(values, definitions, strictUpTo) {
|
|
86
95
|
const result = {};
|
|
87
|
-
if (definitions.length === 0)
|
|
88
|
-
return result;
|
|
89
96
|
let valueIndex = 0;
|
|
90
97
|
for (const definition of definitions) {
|
|
91
98
|
if (definition.variadic) {
|
|
@@ -110,7 +117,9 @@ export class CLIParser {
|
|
|
110
117
|
result[definition.name] = value;
|
|
111
118
|
valueIndex++;
|
|
112
119
|
}
|
|
113
|
-
|
|
120
|
+
// Commands that declare no arguments used to return before this check,
|
|
121
|
+
// so `zudojs doctor my-proj` discarded `my-proj` without a word.
|
|
122
|
+
if (strictUpTo !== null && valueIndex < strictUpTo) {
|
|
114
123
|
throw new InvalidArgumentsError(`Unexpected argument "${values[valueIndex]}".`);
|
|
115
124
|
}
|
|
116
125
|
return result;
|
|
@@ -15,6 +15,17 @@ export declare function parseBoolean(value: string, option?: string): boolean;
|
|
|
15
15
|
export declare function isOption(token: string): boolean;
|
|
16
16
|
/** Returns whether a token is a long option (e.g. `--verbose`). */
|
|
17
17
|
export declare function isLongOption(token: string): boolean;
|
|
18
|
+
/** Returns whether a token looks like a negative number (e.g. `-1`, `-2.5`). */
|
|
19
|
+
export declare function isNegativeNumber(token: string): boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Returns whether the token following an option can be taken as its value.
|
|
22
|
+
*
|
|
23
|
+
* A flag-looking token is refused so that `--type --frontend react` reports
|
|
24
|
+
* the missing value for `--type` instead of setting it to `"--frontend"`.
|
|
25
|
+
* Negative numbers stay usable for numeric options: `--port -1` and
|
|
26
|
+
* `--port=-1` both keep working.
|
|
27
|
+
*/
|
|
28
|
+
export declare function isOptionValueToken(definition: CLIOption, token: string | undefined): token is string;
|
|
18
29
|
/** Returns whether a token is a short option (e.g. `-v`). */
|
|
19
30
|
export declare function isShortOption(token: string): boolean;
|
|
20
31
|
/** Resolves a command name to a CLICommand. */
|
|
@@ -54,6 +54,25 @@ export function isLongOption(token) {
|
|
|
54
54
|
return (token.startsWith(CLI_OPTION_PREFIXES.LONG) &&
|
|
55
55
|
token.length > CLI_OPTION_PREFIXES.LONG.length);
|
|
56
56
|
}
|
|
57
|
+
/** Returns whether a token looks like a negative number (e.g. `-1`, `-2.5`). */
|
|
58
|
+
export function isNegativeNumber(token) {
|
|
59
|
+
return /^-(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?$/.test(token);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Returns whether the token following an option can be taken as its value.
|
|
63
|
+
*
|
|
64
|
+
* A flag-looking token is refused so that `--type --frontend react` reports
|
|
65
|
+
* the missing value for `--type` instead of setting it to `"--frontend"`.
|
|
66
|
+
* Negative numbers stay usable for numeric options: `--port -1` and
|
|
67
|
+
* `--port=-1` both keep working.
|
|
68
|
+
*/
|
|
69
|
+
export function isOptionValueToken(definition, token) {
|
|
70
|
+
if (token === undefined || token === "--")
|
|
71
|
+
return false;
|
|
72
|
+
if (!isOption(token))
|
|
73
|
+
return true;
|
|
74
|
+
return definition.type === "number" && isNegativeNumber(token);
|
|
75
|
+
}
|
|
57
76
|
/** Returns whether a token is a short option (e.g. `-v`). */
|
|
58
77
|
export function isShortOption(token) {
|
|
59
78
|
return (token.startsWith(CLI_OPTION_PREFIXES.SHORT) &&
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { CLI_OPTION_PREFIXES } from "../cliConstant/cliConstant.value.js";
|
|
7
7
|
import { InvalidOptionError, MissingOptionValueError, } from "../cliError/cliError.option.js";
|
|
8
|
-
import { isOption, parseBoolean, parseOptionValue, } from "./cliParser.helper.js";
|
|
8
|
+
import { isOption, isOptionValueToken, parseBoolean, parseOptionValue, } from "./cliParser.helper.js";
|
|
9
9
|
/** Parses a long option token from the token stream. */
|
|
10
10
|
export function parseLongOption(tokens, index, definitions, values, allowUnknownOptions) {
|
|
11
11
|
const token = tokens[index];
|
|
@@ -50,11 +50,11 @@ export function parseLongOption(tokens, index, definitions, values, allowUnknown
|
|
|
50
50
|
return index + 1;
|
|
51
51
|
}
|
|
52
52
|
if (value === undefined) {
|
|
53
|
-
|
|
53
|
+
const next = tokens[index + 1];
|
|
54
|
+
if (!isOptionValueToken(definition, next)) {
|
|
54
55
|
throw new MissingOptionValueError(token);
|
|
55
56
|
}
|
|
56
|
-
|
|
57
|
-
assignOptionValue(definition, value, values);
|
|
57
|
+
assignOptionValue(definition, next, values);
|
|
58
58
|
return index + 2;
|
|
59
59
|
}
|
|
60
60
|
assignOptionValue(definition, value, values);
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { CLI_OPTION_PREFIXES } from "../cliConstant/cliConstant.value.js";
|
|
7
7
|
import { InvalidOptionError, MissingOptionValueError, } from "../cliError/cliError.option.js";
|
|
8
|
+
import { isOptionValueToken } from "./cliParser.helper.js";
|
|
8
9
|
import { assignOptionValue } from "./cliParser.longOption.js";
|
|
9
10
|
/** Parses a short option token from the token stream. */
|
|
10
11
|
export function parseShortOption(tokens, index, definitions, values, allowUnknownOptions) {
|
|
@@ -44,10 +45,11 @@ export function parseShortOption(tokens, index, definitions, values, allowUnknow
|
|
|
44
45
|
assignOptionValue(definition, attachedValue, values);
|
|
45
46
|
return index + 1;
|
|
46
47
|
}
|
|
47
|
-
|
|
48
|
+
const next = tokens[index + 1];
|
|
49
|
+
if (!isOptionValueToken(definition, next)) {
|
|
48
50
|
throw new MissingOptionValueError(`-${short}`);
|
|
49
51
|
}
|
|
50
|
-
assignOptionValue(definition,
|
|
52
|
+
assignOptionValue(definition, next, values);
|
|
51
53
|
return index + 2;
|
|
52
54
|
}
|
|
53
55
|
values[definition.name] = true;
|
|
@@ -66,10 +68,11 @@ export function parseShortOption(tokens, index, definitions, values, allowUnknow
|
|
|
66
68
|
values[definition.name] = true;
|
|
67
69
|
return index + 1;
|
|
68
70
|
}
|
|
69
|
-
|
|
71
|
+
const next = tokens[index + 1];
|
|
72
|
+
if (!isOptionValueToken(definition, next)) {
|
|
70
73
|
throw new MissingOptionValueError(token);
|
|
71
74
|
}
|
|
72
|
-
assignOptionValue(definition,
|
|
75
|
+
assignOptionValue(definition, next, values);
|
|
73
76
|
return index + 2;
|
|
74
77
|
}
|
|
75
78
|
/** Finds an option by its short flag. */
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
*
|
|
12
12
|
* @module cliVersion/update
|
|
13
13
|
*/
|
|
14
|
+
import { CLI_ENVIRONMENT } from "../cliConstant/cliConstant.value.js";
|
|
14
15
|
import { compareVersions, isValidVersion } from "./cliVersion.core.js";
|
|
15
16
|
/**
|
|
16
17
|
* Whether the update check is turned off for this environment.
|
|
@@ -19,12 +20,13 @@ import { compareVersions, isValidVersion } from "./cliVersion.core.js";
|
|
|
19
20
|
* mode disable it implicitly.
|
|
20
21
|
*/
|
|
21
22
|
export function isUpdateCheckDisabled(env = process.env) {
|
|
22
|
-
const flag = env[
|
|
23
|
+
const flag = env[CLI_ENVIRONMENT.NO_UPDATE_CHECK];
|
|
23
24
|
if (flag !== undefined && flag !== "" && flag !== "0")
|
|
24
25
|
return true;
|
|
25
|
-
|
|
26
|
+
const ci = env[CLI_ENVIRONMENT.CI];
|
|
27
|
+
if (ci !== undefined && ci !== "" && ci !== "false")
|
|
26
28
|
return true;
|
|
27
|
-
if (env[
|
|
29
|
+
if (env[CLI_ENVIRONMENT.NPM_OFFLINE] === "true")
|
|
28
30
|
return true;
|
|
29
31
|
return false;
|
|
30
32
|
}
|
|
@@ -88,6 +88,14 @@ export async function runAddCommand(context) {
|
|
|
88
88
|
}
|
|
89
89
|
context.logger.info(`Adding feature: ${feature}`);
|
|
90
90
|
context.logger.info(`Packages: ${packages.join(", ")}`);
|
|
91
|
+
// The manifest is read and validated before anything is written: an
|
|
92
|
+
// unusable manifest used to be discovered after every package.json had
|
|
93
|
+
// already been rewritten, leaving the project half-updated.
|
|
94
|
+
const manifest = new ManifestManager(layout.root);
|
|
95
|
+
const manifestState = await manifest.readResult();
|
|
96
|
+
if (manifestState.status === "invalid") {
|
|
97
|
+
throw new CLIGenerationError(`The project manifest at ${manifest.path} is unusable: ${manifestState.reason ?? "unknown reason"}. Fix or delete it, then re-run; nothing has been changed.`);
|
|
98
|
+
}
|
|
91
99
|
try {
|
|
92
100
|
for (const pkgPath of targets) {
|
|
93
101
|
if (!existsSync(pkgPath)) {
|
|
@@ -111,8 +119,15 @@ export async function runAddCommand(context) {
|
|
|
111
119
|
writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
|
|
112
120
|
context.logger.info(`Updated ${relative(context.cwd, pkgPath) || "package.json"}`);
|
|
113
121
|
}
|
|
114
|
-
// The manifest records capabilities for the whole project.
|
|
115
|
-
|
|
122
|
+
// The manifest records capabilities for the whole project. A project
|
|
123
|
+
// described by a legacy zudojs.config.ts or a package.json block has
|
|
124
|
+
// none; that is said out loud rather than passed over in silence.
|
|
125
|
+
if (manifestState.status === "ok") {
|
|
126
|
+
await manifest.addCapability(feature);
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
context.logger.warn(`No .zudojs/manifest.json in ${layout.root}; "${feature}" was recorded in package.json only.`);
|
|
130
|
+
}
|
|
116
131
|
if (context.values["skip-install"] !== true) {
|
|
117
132
|
const [file, ...args] = getInstallCommand(layout.packageManager);
|
|
118
133
|
context.logger.info(`Installing dependencies with ${file}...`);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* zudojs-cli — Command Error Helpers
|
|
3
|
+
*
|
|
4
|
+
* Rendering for errors a command reports to the user.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Renders an error together with everything it was caused by.
|
|
8
|
+
*
|
|
9
|
+
* Generators wrap failures in a CLIGenerationError whose own message says
|
|
10
|
+
* only what was being attempted — "Failed to write project files:",
|
|
11
|
+
* "Failed to generate service: billing" — and the cause carried the reason
|
|
12
|
+
* (ENOTDIR, EACCES) without anything ever printing it.
|
|
13
|
+
*/
|
|
14
|
+
export declare function describeError(error: unknown): string;
|
|
15
|
+
//# sourceMappingURL=commandError.helper.d.ts.map
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* zudojs-cli — Command Error Helpers
|
|
3
|
+
*
|
|
4
|
+
* Rendering for errors a command reports to the user.
|
|
5
|
+
*/
|
|
6
|
+
/** How many `cause` links are followed before the chain is cut off. */
|
|
7
|
+
const MAX_CAUSE_DEPTH = 5;
|
|
8
|
+
/**
|
|
9
|
+
* Renders an error together with everything it was caused by.
|
|
10
|
+
*
|
|
11
|
+
* Generators wrap failures in a CLIGenerationError whose own message says
|
|
12
|
+
* only what was being attempted — "Failed to write project files:",
|
|
13
|
+
* "Failed to generate service: billing" — and the cause carried the reason
|
|
14
|
+
* (ENOTDIR, EACCES) without anything ever printing it.
|
|
15
|
+
*/
|
|
16
|
+
export function describeError(error) {
|
|
17
|
+
const parts = [];
|
|
18
|
+
let current = error;
|
|
19
|
+
for (let depth = 0; depth < MAX_CAUSE_DEPTH && current instanceof Error; depth += 1) {
|
|
20
|
+
const message = current.message.replace(/[:\s]+$/, "");
|
|
21
|
+
if (message.length > 0 && !parts.includes(message)) {
|
|
22
|
+
parts.push(message);
|
|
23
|
+
}
|
|
24
|
+
current = current.cause;
|
|
25
|
+
}
|
|
26
|
+
return parts.length > 0 ? parts.join(": ") : String(error);
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=commandError.helper.js.map
|