zudojs-cli 2.0.0 → 2.1.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 +69 -9
- package/dist/src/adapters/frontend/angular.adapter.d.ts +0 -1
- package/dist/src/adapters/frontend/angular.adapter.js +14 -97
- package/dist/src/adapters/frontend/astro.adapter.d.ts +0 -1
- package/dist/src/adapters/frontend/astro.adapter.js +4 -64
- package/dist/src/adapters/frontend/fallback/fallback.helper.d.ts +41 -0
- package/dist/src/adapters/frontend/fallback/fallback.helper.js +57 -0
- package/dist/src/adapters/frontend/fallback/framework/angular/angular.fallback.d.ts +18 -0
- package/dist/src/adapters/frontend/fallback/framework/angular/angular.fallback.js +107 -0
- package/dist/src/adapters/frontend/fallback/framework/angular/angularWorkspace.fallback.d.ts +23 -0
- package/dist/src/adapters/frontend/fallback/framework/angular/angularWorkspace.fallback.js +125 -0
- package/dist/src/adapters/frontend/fallback/framework/angular/index.d.ts +8 -0
- package/dist/src/adapters/frontend/fallback/framework/angular/index.js +8 -0
- package/dist/src/adapters/frontend/fallback/framework/astro.fallback.d.ts +14 -0
- package/dist/src/adapters/frontend/fallback/framework/astro.fallback.js +76 -0
- package/dist/src/adapters/frontend/fallback/framework/index.d.ts +13 -0
- package/dist/src/adapters/frontend/fallback/framework/index.js +13 -0
- package/dist/src/adapters/frontend/fallback/framework/next.fallback.d.ts +13 -0
- package/dist/src/adapters/frontend/fallback/framework/next.fallback.js +105 -0
- package/dist/src/adapters/frontend/fallback/framework/nuxt.fallback.d.ts +14 -0
- package/dist/src/adapters/frontend/fallback/framework/nuxt.fallback.js +56 -0
- package/dist/src/adapters/frontend/fallback/framework/sveltekit.fallback.d.ts +15 -0
- package/dist/src/adapters/frontend/fallback/framework/sveltekit.fallback.js +94 -0
- package/dist/src/adapters/frontend/fallback/index.d.ts +12 -0
- package/dist/src/adapters/frontend/fallback/index.js +12 -0
- package/dist/src/adapters/frontend/fallback/vite/index.d.ts +11 -0
- package/dist/src/adapters/frontend/fallback/vite/index.js +11 -0
- package/dist/src/adapters/frontend/fallback/vite/react.fallback.d.ts +13 -0
- package/dist/src/adapters/frontend/fallback/vite/react.fallback.js +77 -0
- package/dist/src/adapters/frontend/fallback/vite/svelte.fallback.d.ts +14 -0
- package/dist/src/adapters/frontend/fallback/vite/svelte.fallback.js +95 -0
- package/dist/src/adapters/frontend/fallback/vite/vanilla.fallback.d.ts +13 -0
- package/dist/src/adapters/frontend/fallback/vite/vanilla.fallback.js +71 -0
- package/dist/src/adapters/frontend/fallback/vite/vue.fallback.d.ts +14 -0
- package/dist/src/adapters/frontend/fallback/vite/vue.fallback.js +78 -0
- package/dist/src/adapters/frontend/next.adapter.d.ts +0 -1
- package/dist/src/adapters/frontend/next.adapter.js +16 -95
- package/dist/src/adapters/frontend/nuxt.adapter.d.ts +1 -2
- package/dist/src/adapters/frontend/nuxt.adapter.js +32 -43
- package/dist/src/adapters/frontend/react-native.adapter.js +1 -1
- package/dist/src/adapters/frontend/react.adapter.d.ts +0 -1
- package/dist/src/adapters/frontend/react.adapter.js +7 -89
- package/dist/src/adapters/frontend/svelte.adapter.d.ts +0 -1
- package/dist/src/adapters/frontend/svelte.adapter.js +4 -86
- package/dist/src/adapters/frontend/sveltekit.adapter.d.ts +0 -1
- package/dist/src/adapters/frontend/sveltekit.adapter.js +4 -57
- package/dist/src/adapters/frontend/vanilla.adapter.d.ts +0 -1
- package/dist/src/adapters/frontend/vanilla.adapter.js +4 -47
- package/dist/src/adapters/frontend/vue.adapter.d.ts +0 -1
- package/dist/src/adapters/frontend/vue.adapter.js +4 -76
- package/dist/src/bin/bin.menu.d.ts +22 -0
- package/dist/src/bin/bin.menu.js +40 -0
- package/dist/src/bin/bin.runner.d.ts +38 -0
- package/dist/src/bin/bin.runner.js +51 -0
- package/dist/src/bin/index.d.ts +9 -0
- package/dist/src/bin/index.js +9 -0
- package/dist/src/bin/zudojs.js +15 -4
- package/dist/src/cliApplication/cliApplication.core.d.ts +4 -2
- package/dist/src/cliApplication/cliApplication.core.js +48 -36
- package/dist/src/cliApplication/cliApplication.logger.d.ts +5 -0
- package/dist/src/cliApplication/cliApplication.logger.js +5 -3
- package/dist/src/cliApplication/invocation/index.d.ts +12 -0
- package/dist/src/cliApplication/invocation/index.js +12 -0
- package/dist/src/cliApplication/invocation/invocation.hint.d.ts +30 -0
- package/dist/src/cliApplication/invocation/invocation.hint.js +74 -0
- package/dist/src/cliApplication/invocation/invocation.locate.d.ts +34 -0
- package/dist/src/cliApplication/invocation/invocation.locate.js +53 -0
- package/dist/src/cliApplication/invocation/invocation.name.d.ts +37 -0
- package/dist/src/cliApplication/invocation/invocation.name.js +69 -0
- package/dist/src/cliApplication/invocation/invocation.sanitize.d.ts +19 -0
- package/dist/src/cliApplication/invocation/invocation.sanitize.js +32 -0
- package/dist/src/cliParser/cliParser.core.js +3 -1
- package/dist/src/cliParser/cliParser.helper.d.ts +7 -0
- package/dist/src/cliParser/cliParser.helper.js +19 -2
- package/dist/src/cliParser/cliParser.longOption.js +2 -2
- package/dist/src/commands/add.command.d.ts +7 -3
- package/dist/src/commands/add.command.js +96 -57
- package/dist/src/commands/create.command.js +29 -42
- package/dist/src/commands/doctor.command.d.ts +2 -1
- package/dist/src/commands/doctor.command.js +52 -4
- package/dist/src/commands/generate.command.js +31 -16
- package/dist/src/commands/info.command.js +11 -1
- package/dist/src/constants/index.d.ts +21 -3
- package/dist/src/constants/index.js +40 -5
- package/dist/src/constants/zudojsVersions.generated.d.ts +9 -0
- package/dist/src/constants/zudojsVersions.generated.js +48 -0
- package/dist/src/constants/zudojsVersions.helper.d.ts +21 -0
- package/dist/src/constants/zudojsVersions.helper.js +29 -0
- package/dist/src/generators/frontend/frontendGenerator.core.js +9 -10
- package/dist/src/generators/frontend/frontendPipeline.d.ts +6 -1
- package/dist/src/generators/frontend/frontendPipeline.js +9 -1
- package/dist/src/generators/fullstack/fullstackComposer.core.js +7 -1
- package/dist/src/generators/index.d.ts +1 -2
- package/dist/src/generators/index.js +1 -2
- package/dist/src/generators/infrastructure/infrastructure.generator.js +13 -5
- package/dist/src/generators/integration/integrationGenerator.core.d.ts +2 -0
- package/dist/src/generators/integration/integrationGenerator.core.js +31 -2
- package/dist/src/generators/module/module.generator.js +36 -4
- package/dist/src/generators/resource/index.d.ts +8 -0
- package/dist/src/generators/resource/index.js +8 -0
- package/dist/src/generators/resource/resource.generator.d.ts +27 -0
- package/dist/src/generators/resource/resource.generator.js +87 -0
- package/dist/src/generators/resource/resource.layout.d.ts +26 -0
- package/dist/src/generators/resource/resource.layout.js +46 -0
- package/dist/src/generators/resource/resource.plan.d.ts +27 -0
- package/dist/src/generators/resource/resource.plan.js +46 -0
- package/dist/src/generators/resource/resource.run.d.ts +25 -0
- package/dist/src/generators/resource/resource.run.js +52 -0
- package/dist/src/prompts/cancel.prompt.d.ts +5 -1
- package/dist/src/prompts/cancel.prompt.js +4 -0
- package/dist/src/prompts/menu/index.d.ts +13 -0
- package/dist/src/prompts/menu/index.js +13 -0
- package/dist/src/prompts/menu/menu.adapter.d.ts +16 -0
- package/dist/src/prompts/menu/menu.adapter.js +56 -0
- package/dist/src/prompts/menu/menu.constant.d.ts +20 -0
- package/dist/src/prompts/menu/menu.constant.js +29 -0
- package/dist/src/prompts/menu/menu.flow.d.ts +18 -0
- package/dist/src/prompts/menu/menu.flow.js +82 -0
- package/dist/src/prompts/menu/menu.select.d.ts +26 -0
- package/dist/src/prompts/menu/menu.select.js +118 -0
- package/dist/src/prompts/menu/menu.type.d.ts +66 -0
- package/dist/src/prompts/menu/menu.type.js +8 -0
- package/dist/src/recipes/apply/index.d.ts +9 -0
- package/dist/src/recipes/apply/index.js +9 -0
- package/dist/src/recipes/apply/recipeApply.app.d.ts +20 -0
- package/dist/src/recipes/apply/recipeApply.app.js +79 -0
- package/dist/src/recipes/apply/recipeApply.context.d.ts +14 -0
- package/dist/src/recipes/apply/recipeApply.context.js +76 -0
- package/dist/src/recipes/apply/recipeApply.files.d.ts +39 -0
- package/dist/src/recipes/apply/recipeApply.files.js +84 -0
- package/dist/src/recipes/apply/recipeApply.project.d.ts +11 -0
- package/dist/src/recipes/apply/recipeApply.project.js +50 -0
- package/dist/src/recipes/apply/recipeApply.report.d.ts +20 -0
- package/dist/src/recipes/apply/recipeApply.report.js +51 -0
- package/dist/src/recipes/catalog/database/database.files.d.ts +15 -0
- package/dist/src/recipes/catalog/database/database.files.js +98 -0
- package/dist/src/recipes/catalog/database/database.recipe.d.ts +9 -0
- package/dist/src/recipes/catalog/database/database.recipe.js +50 -0
- package/dist/src/recipes/catalog/database/index.d.ts +6 -0
- package/dist/src/recipes/catalog/database/index.js +6 -0
- package/dist/src/recipes/catalog/email.recipe.d.ts +9 -0
- package/dist/src/recipes/catalog/email.recipe.js +122 -0
- package/dist/src/recipes/catalog/index.d.ts +11 -0
- package/dist/src/recipes/catalog/index.js +11 -0
- package/dist/src/recipes/catalog/openapi.recipe.d.ts +8 -0
- package/dist/src/recipes/catalog/openapi.recipe.js +25 -0
- package/dist/src/recipes/catalog/platform/cache.recipe.d.ts +7 -0
- package/dist/src/recipes/catalog/platform/cache.recipe.js +55 -0
- package/dist/src/recipes/catalog/platform/index.d.ts +9 -0
- package/dist/src/recipes/catalog/platform/index.js +9 -0
- package/dist/src/recipes/catalog/platform/messaging.recipe.d.ts +7 -0
- package/dist/src/recipes/catalog/platform/messaging.recipe.js +46 -0
- package/dist/src/recipes/catalog/platform/observability.recipe.d.ts +8 -0
- package/dist/src/recipes/catalog/platform/observability.recipe.js +49 -0
- package/dist/src/recipes/catalog/platform/queue.recipe.d.ts +7 -0
- package/dist/src/recipes/catalog/platform/queue.recipe.js +61 -0
- package/dist/src/recipes/catalog/platform/scheduler.recipe.d.ts +7 -0
- package/dist/src/recipes/catalog/platform/scheduler.recipe.js +56 -0
- package/dist/src/recipes/catalog/redis.recipe.d.ts +8 -0
- package/dist/src/recipes/catalog/redis.recipe.js +79 -0
- package/dist/src/recipes/catalog/storage.recipe.d.ts +7 -0
- package/dist/src/recipes/catalog/storage.recipe.js +49 -0
- package/dist/src/recipes/catalog/websockets.recipe.d.ts +10 -0
- package/dist/src/recipes/catalog/websockets.recipe.js +84 -0
- package/dist/src/recipes/docker/docker.compose.d.ts +19 -0
- package/dist/src/recipes/docker/docker.compose.js +90 -0
- package/dist/src/recipes/docker/docker.recipe.d.ts +10 -0
- package/dist/src/recipes/docker/docker.recipe.js +51 -0
- package/dist/src/recipes/docker/docker.refresh.d.ts +13 -0
- package/dist/src/recipes/docker/docker.refresh.js +37 -0
- package/dist/src/recipes/docker/index.d.ts +7 -0
- package/dist/src/recipes/docker/index.js +7 -0
- package/dist/src/recipes/index.d.ts +8 -0
- package/dist/src/recipes/index.js +8 -0
- package/dist/src/recipes/recipe.registry.d.ts +17 -0
- package/dist/src/recipes/recipe.registry.js +46 -0
- package/dist/src/recipes/recipe.type.d.ts +93 -0
- package/dist/src/recipes/recipe.type.js +12 -0
- package/dist/src/resolvers/dependency/dependencyVersions.constant.d.ts +100 -5
- package/dist/src/resolvers/dependency/dependencyVersions.constant.js +103 -34
- package/dist/src/resolvers/dependency/index.d.ts +1 -1
- package/dist/src/resolvers/dependency/index.js +1 -1
- package/dist/src/resolvers/project.resolver.d.ts +14 -1
- package/dist/src/resolvers/project.resolver.js +11 -3
- package/dist/src/scaffolders/scaffolder.helper.js +12 -1
- package/dist/src/templates/backendApp/backendApp.core.d.ts +45 -0
- package/dist/src/templates/backendApp/backendApp.core.js +66 -0
- package/dist/src/templates/backendApp/backendApp.modules.d.ts +26 -0
- package/dist/src/templates/backendApp/backendApp.modules.js +25 -0
- package/dist/src/templates/backendApp/backendApp.project.d.ts +26 -0
- package/dist/src/templates/backendApp/backendApp.project.js +87 -0
- package/dist/src/templates/backendApp/index.d.ts +8 -0
- package/dist/src/templates/backendApp/index.js +8 -0
- package/dist/src/templates/backendApp/parts/config.template.d.ts +28 -0
- package/dist/src/templates/backendApp/parts/config.template.js +118 -0
- package/dist/src/templates/backendApp/parts/httpUtils.template.d.ts +10 -0
- package/dist/src/templates/backendApp/parts/httpUtils.template.js +103 -0
- package/dist/src/templates/backendApp/parts/index.d.ts +9 -0
- package/dist/src/templates/backendApp/parts/index.js +9 -0
- package/dist/src/templates/backendApp/parts/integrations.template.d.ts +16 -0
- package/dist/src/templates/backendApp/parts/integrations.template.js +115 -0
- package/dist/src/templates/backendApp/parts/wiring.template.d.ts +26 -0
- package/dist/src/templates/backendApp/parts/wiring.template.js +111 -0
- package/dist/src/templates/microservice/microservice.template.d.ts +4 -1
- package/dist/src/templates/microservice/microservice.template.js +74 -90
- package/dist/src/templates/modular-monolith/modularMonolith.template.js +25 -77
- package/dist/src/templates/monolith/monolith.template.d.ts +11 -26
- package/dist/src/templates/monolith/monolith.template.js +49 -146
- package/dist/src/templates/resource/index.d.ts +9 -0
- package/dist/src/templates/resource/index.js +9 -0
- package/dist/src/templates/resource/layers/index.d.ts +9 -0
- package/dist/src/templates/resource/layers/index.js +9 -0
- package/dist/src/templates/resource/layers/resourceData.template.d.ts +9 -0
- package/dist/src/templates/resource/layers/resourceData.template.js +108 -0
- package/dist/src/templates/resource/layers/resourcePrisma.template.d.ts +15 -0
- package/dist/src/templates/resource/layers/resourcePrisma.template.js +89 -0
- package/dist/src/templates/resource/layers/resourceRoutes.template.d.ts +13 -0
- package/dist/src/templates/resource/layers/resourceRoutes.template.js +128 -0
- package/dist/src/templates/resource/layers/resourceService.template.d.ts +13 -0
- package/dist/src/templates/resource/layers/resourceService.template.js +95 -0
- package/dist/src/templates/resource/resource.files.d.ts +33 -0
- package/dist/src/templates/resource/resource.files.js +99 -0
- package/dist/src/templates/resource/resource.names.d.ts +38 -0
- package/dist/src/templates/resource/resource.names.js +60 -0
- package/dist/src/templates/resource/resource.type.d.ts +19 -0
- package/dist/src/templates/resource/resource.type.js +15 -0
- package/dist/src/templates/shared/appRuntime.template.js +28 -11
- package/dist/src/templates/shared/capability.template.d.ts +13 -4
- package/dist/src/templates/shared/capability.template.js +21 -5
- package/dist/src/templates/shared/dockerfile.template.d.ts +12 -4
- package/dist/src/templates/shared/dockerfile.template.js +68 -29
- package/dist/src/templates/shared/pnpm.template.d.ts +8 -2
- package/dist/src/templates/shared/pnpm.template.js +9 -1
- package/dist/src/templates/shared/server.template.d.ts +23 -22
- package/dist/src/templates/shared/server.template.js +79 -53
- package/dist/src/types/scaffold.type.d.ts +6 -0
- package/dist/src/types/scaffold.type.js +2 -1
- package/dist/src/utils/utils.name.js +6 -0
- package/dist/src/utils/utils.writeGuard.d.ts +5 -0
- package/dist/src/utils/utils.writeGuard.js +23 -0
- package/dist/src/wiring/index.d.ts +10 -0
- package/dist/src/wiring/index.js +10 -0
- package/dist/src/wiring/wiring.dependencies.d.ts +29 -0
- package/dist/src/wiring/wiring.dependencies.js +83 -0
- package/dist/src/wiring/wiring.edits.d.ts +51 -0
- package/dist/src/wiring/wiring.edits.js +90 -0
- package/dist/src/wiring/wiring.markers.d.ts +53 -0
- package/dist/src/wiring/wiring.markers.js +87 -0
- package/package.json +20 -15
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* zudojs-cli — Terminal-Safe Text
|
|
3
|
+
*
|
|
4
|
+
* Neutralises control characters in text that echoes user input back to
|
|
5
|
+
* the terminal.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Replaces terminal control characters with a visible escape.
|
|
9
|
+
*
|
|
10
|
+
* Error messages quote what the user passed (`Command "…" was not found.`,
|
|
11
|
+
* `Unknown or invalid option "…"`). An argument carrying ESC sequences —
|
|
12
|
+
* from a script that forwards untrusted input — could otherwise recolour
|
|
13
|
+
* the terminal, rewrite its title, hide text or emit OSC 8 links. The
|
|
14
|
+
* escaped form (`\x1b`) still shows the user what was received.
|
|
15
|
+
*
|
|
16
|
+
* @param text - Text about to be written to the terminal.
|
|
17
|
+
*/
|
|
18
|
+
export declare function escapeControlCharacters(text: string): string;
|
|
19
|
+
//# sourceMappingURL=invocation.sanitize.d.ts.map
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* zudojs-cli — Terminal-Safe Text
|
|
3
|
+
*
|
|
4
|
+
* Neutralises control characters in text that echoes user input back to
|
|
5
|
+
* the terminal.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* C0 and C1 control characters other than tab and newline, plus the Unicode
|
|
9
|
+
* bidirectional overrides that can make a line read differently from what
|
|
10
|
+
* it contains.
|
|
11
|
+
*/
|
|
12
|
+
const UNSAFE_CHARACTERS = /[\u0000-\u0008\u000B-\u001F\u007F-\u009F--]/g;
|
|
13
|
+
/**
|
|
14
|
+
* Replaces terminal control characters with a visible escape.
|
|
15
|
+
*
|
|
16
|
+
* Error messages quote what the user passed (`Command "…" was not found.`,
|
|
17
|
+
* `Unknown or invalid option "…"`). An argument carrying ESC sequences —
|
|
18
|
+
* from a script that forwards untrusted input — could otherwise recolour
|
|
19
|
+
* the terminal, rewrite its title, hide text or emit OSC 8 links. The
|
|
20
|
+
* escaped form (`\x1b`) still shows the user what was received.
|
|
21
|
+
*
|
|
22
|
+
* @param text - Text about to be written to the terminal.
|
|
23
|
+
*/
|
|
24
|
+
export function escapeControlCharacters(text) {
|
|
25
|
+
return text.replace(UNSAFE_CHARACTERS, (character) => {
|
|
26
|
+
const code = character.codePointAt(0);
|
|
27
|
+
return code <= 0xff
|
|
28
|
+
? `\\x${code.toString(16).padStart(2, "0")}`
|
|
29
|
+
: `\\u${code.toString(16).padStart(4, "0")}`;
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=invocation.sanitize.js.map
|
|
@@ -28,7 +28,9 @@ export class CLIParser {
|
|
|
28
28
|
const tokens = Array.from(args);
|
|
29
29
|
const commands = [];
|
|
30
30
|
const positional = [];
|
|
31
|
-
|
|
31
|
+
// No prototype: an undeclared `--constructor` (allowUnknownOptions) must
|
|
32
|
+
// not read or shadow Object.prototype members.
|
|
33
|
+
const options = Object.create(null);
|
|
32
34
|
const definitions = command?.options ?? [];
|
|
33
35
|
const argumentsDefinitions = command?.arguments ?? [];
|
|
34
36
|
let index = 0;
|
|
@@ -11,6 +11,13 @@ export declare function parseCLIArguments(args: CLIArguments, command?: CLIComma
|
|
|
11
11
|
export declare function parseOptionValue(definition: CLIOption, value: string): CLIValue;
|
|
12
12
|
/** Parses a string into a boolean. */
|
|
13
13
|
export declare function parseBoolean(value: string, option?: string): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Returns whether an option name would touch an object's prototype chain.
|
|
16
|
+
*
|
|
17
|
+
* Only reachable when `allowUnknownOptions` is on: undeclared names are then
|
|
18
|
+
* written to the values object as typed, so `--__proto__` must be refused.
|
|
19
|
+
*/
|
|
20
|
+
export declare function isReservedOptionKey(name: string): boolean;
|
|
14
21
|
/** Returns whether a token is any option (short or long). */
|
|
15
22
|
export declare function isOption(token: string): boolean;
|
|
16
23
|
/** Returns whether a token is a long option (e.g. `--verbose`). */
|
|
@@ -19,8 +19,10 @@ export function parseOptionValue(definition, value) {
|
|
|
19
19
|
case "boolean":
|
|
20
20
|
return parseBoolean(value, definition.name);
|
|
21
21
|
case "number": {
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
// `Number("")` is 0 and `Number("Infinity")` is Infinity, so
|
|
23
|
+
// `--port=` used to start the server with PORT=0 instead of failing.
|
|
24
|
+
const parsed = value.trim() === "" ? Number.NaN : Number(value);
|
|
25
|
+
if (!Number.isFinite(parsed)) {
|
|
24
26
|
throw new InvalidArgumentsError(`Option "${definition.name}" expects a number, received "${value}".`);
|
|
25
27
|
}
|
|
26
28
|
return parsed;
|
|
@@ -42,6 +44,21 @@ export function parseBoolean(value, option = "option") {
|
|
|
42
44
|
/* -------------------------------------------------------------------------- */
|
|
43
45
|
/* Token Classification */
|
|
44
46
|
/* -------------------------------------------------------------------------- */
|
|
47
|
+
/** Keys that must never be written from the command line. */
|
|
48
|
+
const RESERVED_OPTION_KEYS = new Set([
|
|
49
|
+
"__proto__",
|
|
50
|
+
"constructor",
|
|
51
|
+
"prototype",
|
|
52
|
+
]);
|
|
53
|
+
/**
|
|
54
|
+
* Returns whether an option name would touch an object's prototype chain.
|
|
55
|
+
*
|
|
56
|
+
* Only reachable when `allowUnknownOptions` is on: undeclared names are then
|
|
57
|
+
* written to the values object as typed, so `--__proto__` must be refused.
|
|
58
|
+
*/
|
|
59
|
+
export function isReservedOptionKey(name) {
|
|
60
|
+
return RESERVED_OPTION_KEYS.has(name);
|
|
61
|
+
}
|
|
45
62
|
/** Returns whether a token is any option (short or long). */
|
|
46
63
|
export function isOption(token) {
|
|
47
64
|
return ((token.startsWith(CLI_OPTION_PREFIXES.LONG) && token !== "--") ||
|
|
@@ -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, isOptionValueToken, parseBoolean, parseOptionValue, } from "./cliParser.helper.js";
|
|
8
|
+
import { isOption, isOptionValueToken, isReservedOptionKey, 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];
|
|
@@ -26,7 +26,7 @@ export function parseLongOption(tokens, index, definitions, values, allowUnknown
|
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
const definition = findOption(name, definitions);
|
|
29
|
-
if (!definition && !allowUnknownOptions) {
|
|
29
|
+
if (!definition && (!allowUnknownOptions || isReservedOptionKey(name))) {
|
|
30
30
|
throw new InvalidOptionError(token);
|
|
31
31
|
}
|
|
32
32
|
if (!definition) {
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* zudojs-cli — Add Command
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* `zudojs add <feature>` writes a working recipe for the feature (see
|
|
5
|
+
* `src/recipes/`): the integration code, its registration, config, env
|
|
6
|
+
* variables and dependencies — or, for `docker`, the project's container
|
|
7
|
+
* files — then records the feature and installs.
|
|
5
8
|
*/
|
|
6
9
|
import type { CLIContext } from "../cliType/cliType.type.js";
|
|
7
10
|
import { type ProjectLayout } from "../resolvers/layout/projectLayout.core.js";
|
|
@@ -29,9 +32,10 @@ export declare function selectAddTargets(layout: ProjectLayout, service: string
|
|
|
29
32
|
* them contains the framework packages, so the next install failed with
|
|
30
33
|
* "not found in workspace". The protocol is now used only when the target
|
|
31
34
|
* already links a framework package that way — i.e. inside the Zudojs
|
|
32
|
-
* monorepo itself.
|
|
35
|
+
* monorepo itself. Otherwise the package gets a caret range on the version
|
|
36
|
+
* this CLI build targets.
|
|
33
37
|
*/
|
|
34
|
-
export declare function versionForNewDependency(pkg: PackageJsonShape): string;
|
|
38
|
+
export declare function versionForNewDependency(pkg: PackageJsonShape, name?: string): string;
|
|
35
39
|
export declare function runAddCommand(context: CLIContext): Promise<void>;
|
|
36
40
|
export {};
|
|
37
41
|
//# sourceMappingURL=add.command.d.ts.map
|
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* zudojs-cli — Add Command
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* `zudojs add <feature>` writes a working recipe for the feature (see
|
|
5
|
+
* `src/recipes/`): the integration code, its registration, config, env
|
|
6
|
+
* variables and dependencies — or, for `docker`, the project's container
|
|
7
|
+
* files — then records the feature and installs.
|
|
5
8
|
*/
|
|
6
|
-
import { join
|
|
7
|
-
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
9
|
+
import { join } from "node:path";
|
|
8
10
|
import { runStreaming } from "../utils/utils.exec.js";
|
|
9
11
|
import { assertSafePathSegment } from "../utils/utils.name.js";
|
|
10
12
|
import { CLIValidationError, CLIGenerationError } from "../errors/index.js";
|
|
11
13
|
import { ManifestManager } from "../manifest/manifestManager.core.js";
|
|
12
14
|
import { getInstallCommand } from "../installers/dependency.installer.js";
|
|
13
|
-
import {
|
|
15
|
+
import { FEATURE_NAMES, zudojsVersionRange } from "../constants/index.js";
|
|
14
16
|
import { resolveProjectLayout, } from "../resolvers/layout/projectLayout.core.js";
|
|
17
|
+
import { applyAppRecipe, applyProjectRecipe, applyProjectSettings, projectRecipeContext, recipeContextFor, recordFeature, recordProjectFeature, refreshGeneratedDockerfiles, reportOutcomes, resolveFeatureRecipe, } from "../recipes/index.js";
|
|
18
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
19
|
+
import { findProjectRoot } from "../resolvers/project.resolver.js";
|
|
15
20
|
/**
|
|
16
21
|
* Picks the `package.json` files a feature is added to.
|
|
17
22
|
*
|
|
@@ -48,34 +53,39 @@ export function selectAddTargets(layout, service) {
|
|
|
48
53
|
* them contains the framework packages, so the next install failed with
|
|
49
54
|
* "not found in workspace". The protocol is now used only when the target
|
|
50
55
|
* already links a framework package that way — i.e. inside the Zudojs
|
|
51
|
-
* monorepo itself.
|
|
56
|
+
* monorepo itself. Otherwise the package gets a caret range on the version
|
|
57
|
+
* this CLI build targets.
|
|
52
58
|
*/
|
|
53
|
-
export function versionForNewDependency(pkg) {
|
|
59
|
+
export function versionForNewDependency(pkg, name = "@zudojs/core") {
|
|
54
60
|
const linksFramework = Object.entries({
|
|
55
61
|
...pkg.dependencies,
|
|
56
62
|
...pkg.devDependencies,
|
|
57
|
-
}).some(([
|
|
58
|
-
return linksFramework ? "workspace:*" :
|
|
63
|
+
}).some(([dep, version]) => dep.startsWith("@zudojs/") && version.startsWith("workspace:"));
|
|
64
|
+
return linksFramework ? "workspace:*" : zudojsVersionRange(name);
|
|
65
|
+
}
|
|
66
|
+
/** A recipe with its `@zudojs/*` ranges swapped for `workspace:*` when the app links the framework. */
|
|
67
|
+
function forApp(recipe, pkg) {
|
|
68
|
+
const dependencies = Object.fromEntries(Object.entries(recipe.dependencies).map(([name, range]) => [
|
|
69
|
+
name,
|
|
70
|
+
name.startsWith("@zudojs/") ? versionForNewDependency(pkg, name) : range,
|
|
71
|
+
]));
|
|
72
|
+
return { ...recipe, dependencies };
|
|
59
73
|
}
|
|
60
74
|
export async function runAddCommand(context) {
|
|
61
|
-
const
|
|
75
|
+
const requested = context.values.feature;
|
|
62
76
|
const service = context.values.service;
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
throw new CLIValidationError(`Feature name is required. Available: ${available}`);
|
|
66
|
-
}
|
|
67
|
-
// Own keys only: `constructor` or `__proto__` resolved to Object.prototype
|
|
68
|
-
// members and crashed with "packages.join is not a function".
|
|
69
|
-
const packages = Object.hasOwn(FEATURE_PACKAGES, feature)
|
|
70
|
-
? FEATURE_PACKAGES[feature]
|
|
71
|
-
: undefined;
|
|
72
|
-
if (!packages) {
|
|
73
|
-
throw new CLIValidationError(`Unknown feature: "${feature}". Available: ${available}`);
|
|
77
|
+
if (!requested) {
|
|
78
|
+
throw new CLIValidationError(`Feature name is required. Available: ${FEATURE_NAMES.join(", ")}`);
|
|
74
79
|
}
|
|
80
|
+
const recipe = resolveFeatureRecipe(requested);
|
|
81
|
+
const feature = recipe.feature;
|
|
75
82
|
if (service !== undefined) {
|
|
76
83
|
assertSafePathSegment(service, "--service");
|
|
77
84
|
}
|
|
78
|
-
|
|
85
|
+
// Walks up, so `add` works from any directory inside the project; an app
|
|
86
|
+
// of a workspace resolves to the workspace, whose manifest is updated.
|
|
87
|
+
const root = findProjectRoot(context.cwd, { workspace: true });
|
|
88
|
+
const layout = root === null ? null : resolveProjectLayout(root);
|
|
79
89
|
if (!layout) {
|
|
80
90
|
throw new CLIValidationError("No Zudojs project found in this directory. Run `zudojs create` first.");
|
|
81
91
|
}
|
|
@@ -86,8 +96,6 @@ export async function runAddCommand(context) {
|
|
|
86
96
|
if (targets.length === 0) {
|
|
87
97
|
throw new CLIValidationError("No backend app with a package.json was found in this project.");
|
|
88
98
|
}
|
|
89
|
-
context.logger.info(`Adding feature: ${feature}`);
|
|
90
|
-
context.logger.info(`Packages: ${packages.join(", ")}`);
|
|
91
99
|
// The manifest is read and validated before anything is written: an
|
|
92
100
|
// unusable manifest used to be discovered after every package.json had
|
|
93
101
|
// already been rewritten, leaving the project half-updated.
|
|
@@ -96,45 +104,48 @@ export async function runAddCommand(context) {
|
|
|
96
104
|
if (manifestState.status === "invalid") {
|
|
97
105
|
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
106
|
}
|
|
107
|
+
for (const pkgPath of targets) {
|
|
108
|
+
if (!existsSync(pkgPath)) {
|
|
109
|
+
throw new CLIGenerationError(`Could not find ${pkgPath}`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
context.logger.info(`Adding feature: ${feature} — ${recipe.summary}`);
|
|
113
|
+
const outcomes = [];
|
|
114
|
+
const nextSteps = [];
|
|
99
115
|
try {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
116
|
+
if (recipe.scope === "app") {
|
|
117
|
+
const apps = targets.map((pkgPath) => join(pkgPath, ".."));
|
|
118
|
+
// Validate every app before touching any of them.
|
|
119
|
+
for (const dir of apps)
|
|
120
|
+
recipe.validate?.(recipeContextFor(layout.root, dir));
|
|
121
|
+
const gitignore = new Set();
|
|
122
|
+
for (const dir of apps) {
|
|
123
|
+
const recipeContext = recipeContextFor(layout.root, dir);
|
|
124
|
+
const pkg = JSON.parse(readFileSync(join(dir, "package.json"), "utf-8"));
|
|
125
|
+
outcomes.push(await applyAppRecipe(forApp(recipe, pkg), recipeContext, layout.root));
|
|
126
|
+
for (const line of recipe.gitignore?.(recipeContext) ?? [])
|
|
127
|
+
gitignore.add(line);
|
|
128
|
+
nextSteps.push(...(recipe.nextSteps?.(recipeContext) ?? []));
|
|
103
129
|
}
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
const block = pkg.zudojs;
|
|
109
|
-
const features = new Set(Array.isArray(block.features)
|
|
110
|
-
? block.features.filter((f) => typeof f === "string")
|
|
111
|
-
: []);
|
|
112
|
-
features.add(feature);
|
|
113
|
-
block.features = [...features];
|
|
114
|
-
for (const name of packages) {
|
|
115
|
-
if (!(name in pkg.dependencies)) {
|
|
116
|
-
pkg.dependencies[name] = version;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
|
|
120
|
-
context.logger.info(`Updated ${relative(context.cwd, pkgPath) || "package.json"}`);
|
|
121
|
-
}
|
|
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);
|
|
130
|
+
const settings = await applyProjectSettings(layout.root, [...gitignore], recipe.allowBuilds ?? []);
|
|
131
|
+
// A Dockerfile written before Prisma was added cannot build the app.
|
|
132
|
+
const dockerfiles = await refreshGeneratedDockerfiles(projectRecipeContext(layout, feature, []));
|
|
133
|
+
outcomes.push({ written: [], kept: [], edited: [...settings, ...dockerfiles], manualSteps: [] });
|
|
127
134
|
}
|
|
128
135
|
else {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
|
|
136
|
+
const capabilities = manifestState.manifest?.capabilities ?? [];
|
|
137
|
+
const projectContext = projectRecipeContext(layout, feature, capabilities);
|
|
138
|
+
const refreshed = await refreshGeneratedDockerfiles(projectContext);
|
|
139
|
+
const outcome = await applyProjectRecipe(recipe, projectContext);
|
|
140
|
+
outcomes.push({
|
|
141
|
+
...outcome,
|
|
142
|
+
edited: [...outcome.edited, ...refreshed],
|
|
143
|
+
kept: outcome.kept.filter((path) => !refreshed.includes(path)),
|
|
144
|
+
});
|
|
145
|
+
for (const pkgPath of targets)
|
|
146
|
+
recordFeature(pkgPath, feature);
|
|
147
|
+
nextSteps.push(...(recipe.nextSteps?.(projectContext) ?? []));
|
|
135
148
|
}
|
|
136
|
-
context.logger.info(`Feature "${feature}" added successfully.`);
|
|
137
|
-
context.logger.info(`Import from ${packages.map((p) => `"${p}"`).join(", ")} in your modules.`);
|
|
138
149
|
}
|
|
139
150
|
catch (error) {
|
|
140
151
|
if (error instanceof CLIValidationError) {
|
|
@@ -143,5 +154,33 @@ export async function runAddCommand(context) {
|
|
|
143
154
|
const message = error instanceof Error ? error.message : String(error);
|
|
144
155
|
throw new CLIGenerationError(`Failed to add feature "${feature}": ${message}`, error);
|
|
145
156
|
}
|
|
157
|
+
// The manifest (and a microservice root's package.json) record
|
|
158
|
+
// capabilities for the whole project, under the same name the apps got.
|
|
159
|
+
// A project described by a legacy zudojs.config.ts or a package.json
|
|
160
|
+
// block has no manifest; that is said out loud rather than passed over.
|
|
161
|
+
if (recordProjectFeature(layout.root, feature, targets)) {
|
|
162
|
+
outcomes.push({ written: [], kept: [], edited: ["package.json"], manualSteps: [] });
|
|
163
|
+
}
|
|
164
|
+
if (manifestState.status === "ok") {
|
|
165
|
+
await manifest.addCapability(feature);
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
context.logger.warn(`No .zudojs/manifest.json in ${layout.root}; "${feature}" was recorded in package.json only.`);
|
|
169
|
+
}
|
|
170
|
+
reportOutcomes(context.logger, context.cwd, layout.root, outcomes);
|
|
171
|
+
if (context.values["skip-install"] !== true) {
|
|
172
|
+
const [file, ...args] = getInstallCommand(layout.packageManager);
|
|
173
|
+
context.logger.info(`Installing dependencies with ${file}...`);
|
|
174
|
+
try {
|
|
175
|
+
await runStreaming(file, args, layout.root);
|
|
176
|
+
}
|
|
177
|
+
catch (error) {
|
|
178
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
179
|
+
throw new CLIGenerationError(`Feature "${feature}" was added, but installing dependencies failed: ${message}. Run "${file} ${args.join(" ")}" to retry.`, error);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
context.logger.info(`Feature "${feature}" added successfully.`);
|
|
183
|
+
for (const step of new Set(nextSteps))
|
|
184
|
+
context.logger.info(`Next: ${step}`);
|
|
146
185
|
}
|
|
147
186
|
//# sourceMappingURL=add.command.js.map
|
|
@@ -21,12 +21,14 @@ import { promptFramework, promptFrontendArchitecture, } from "../prompts/fronten
|
|
|
21
21
|
import { promptPackageManager } from "../prompts/workspace/index.js";
|
|
22
22
|
import { promptCapabilities } from "../prompts/capabilities/index.js";
|
|
23
23
|
import { CLIValidationError, CLIGenerationError } from "../errors/index.js";
|
|
24
|
+
import { InvalidArgumentsError } from "../cliError/cliError.argument.js";
|
|
24
25
|
import { execCommand, runStreaming } from "../utils/utils.exec.js";
|
|
25
26
|
import { writeFileTree } from "../utils/utils.fileSystem.js";
|
|
26
27
|
import { normalizeName } from "../utils/utils.name.js";
|
|
27
28
|
import { resolveMicroserviceServices } from "../templates/microservice/index.js";
|
|
29
|
+
import { capabilityPackages, resolveProjectCapabilities, } from "../templates/shared/index.js";
|
|
28
30
|
import { ManifestManager } from "../manifest/manifestManager.core.js";
|
|
29
|
-
import { CLI_VERSION,
|
|
31
|
+
import { CLI_VERSION, PACKAGE_MANAGERS, zudojsVersionRange, } from "../constants/index.js";
|
|
30
32
|
import { registerCLIInterruptHandler } from "../cliApplication/cliApplication.writer.js";
|
|
31
33
|
import { resolveProjectLayout } from "../resolvers/layout/projectLayout.core.js";
|
|
32
34
|
import { CapabilityResolver } from "../resolvers/capability/capabilityResolver.core.js";
|
|
@@ -253,7 +255,6 @@ export async function runCreateCommand(context) {
|
|
|
253
255
|
}
|
|
254
256
|
const isInteractive = process.stdin.isTTY;
|
|
255
257
|
let answers;
|
|
256
|
-
let selectedCapabilities;
|
|
257
258
|
if (isInteractive) {
|
|
258
259
|
p.intro("Zudojs");
|
|
259
260
|
const name = (await promptProjectName(projectName ?? undefined));
|
|
@@ -285,7 +286,6 @@ export async function runCreateCommand(context) {
|
|
|
285
286
|
// `--capabilities` seeds the prompt so both branches start from the
|
|
286
287
|
// same selection.
|
|
287
288
|
const capabilities = await promptCapabilities(capabilitiesExplicit ? requestedCapabilities : []);
|
|
288
|
-
selectedCapabilities = capabilities;
|
|
289
289
|
const flags = capabilityFlags(capabilities);
|
|
290
290
|
const enableDocker = arch === "microservice";
|
|
291
291
|
const confirmed = await promptConfirmation(`Create project "${name}"?`, true);
|
|
@@ -307,6 +307,7 @@ export async function runCreateCommand(context) {
|
|
|
307
307
|
"typescript"),
|
|
308
308
|
services: interactiveServices,
|
|
309
309
|
...flags,
|
|
310
|
+
capabilities,
|
|
310
311
|
enableDocker,
|
|
311
312
|
installDeps: !noInstall,
|
|
312
313
|
initGit: !noGit,
|
|
@@ -315,7 +316,7 @@ export async function runCreateCommand(context) {
|
|
|
315
316
|
else {
|
|
316
317
|
// Without --capabilities this is the set the branch has always
|
|
317
318
|
// hard-coded; with it, the same project the prompts would produce.
|
|
318
|
-
selectedCapabilities = capabilitiesExplicit
|
|
319
|
+
const selectedCapabilities = capabilitiesExplicit
|
|
319
320
|
? requestedCapabilities
|
|
320
321
|
: DEFAULT_CAPABILITIES;
|
|
321
322
|
answers = {
|
|
@@ -333,6 +334,7 @@ export async function runCreateCommand(context) {
|
|
|
333
334
|
language: languageValue,
|
|
334
335
|
services,
|
|
335
336
|
...capabilityFlags(selectedCapabilities),
|
|
337
|
+
capabilities: selectedCapabilities,
|
|
336
338
|
// Match the interactive branch, which enables Docker for microservices.
|
|
337
339
|
enableDocker: architectureValue === "microservice",
|
|
338
340
|
installDeps: !noInstall,
|
|
@@ -340,7 +342,9 @@ export async function runCreateCommand(context) {
|
|
|
340
342
|
};
|
|
341
343
|
}
|
|
342
344
|
if (!answers.projectName) {
|
|
343
|
-
|
|
345
|
+
// A usage error (exit 2), like any other missing positional; `zudojs
|
|
346
|
+
// new` is the same command, so the example names the canonical form.
|
|
347
|
+
throw new InvalidArgumentsError('Missing required argument "project-name". Pass one (zudojs create my-api) or run in an interactive terminal to be prompted.');
|
|
344
348
|
}
|
|
345
349
|
// Backend templates only emit TypeScript. `--language javascript` used to
|
|
346
350
|
// be accepted and ignored (tooling/CLI-09); in a fullstack project it
|
|
@@ -361,8 +365,11 @@ export async function runCreateCommand(context) {
|
|
|
361
365
|
answers.projectType === "backend") {
|
|
362
366
|
throw new CLIValidationError(`--frontend ${frontendValue} applies to --type frontend or --type fullstack; a backend project has no frontend. Use --type fullstack to get one.`);
|
|
363
367
|
}
|
|
368
|
+
if (capabilitiesExplicit && answers.projectType === "frontend") {
|
|
369
|
+
context.logger.warn("--capabilities applies to backend apps; a frontend project records none.");
|
|
370
|
+
}
|
|
364
371
|
assertCompatibleOptions(answers, context);
|
|
365
|
-
await createProject(answers, context
|
|
372
|
+
await createProject(answers, context);
|
|
366
373
|
}
|
|
367
374
|
/**
|
|
368
375
|
* Refuses option combinations the generators cannot honour, and reports the
|
|
@@ -393,8 +400,10 @@ function assertCompatibleOptions(options, context) {
|
|
|
393
400
|
.join("\n")}`);
|
|
394
401
|
}
|
|
395
402
|
}
|
|
396
|
-
async function createProject(options, context
|
|
403
|
+
async function createProject(options, context) {
|
|
397
404
|
const { projectName, packageManager } = options;
|
|
405
|
+
// One list for the manifest and every backend package.json.
|
|
406
|
+
const capabilities = resolveProjectCapabilities(options);
|
|
398
407
|
const targetPath = join(context.cwd, projectName);
|
|
399
408
|
if (existsSync(targetPath)) {
|
|
400
409
|
throw new CLIValidationError(`Directory "${projectName}" already exists in ${context.cwd}`);
|
|
@@ -534,12 +543,16 @@ function installCommandFor(packageManager) {
|
|
|
534
543
|
}
|
|
535
544
|
}
|
|
536
545
|
/**
|
|
537
|
-
*
|
|
538
|
-
*
|
|
546
|
+
* Makes every backend app declare `capabilities` in `zudojs.features` and
|
|
547
|
+
* depend on the packages behind them — the list the manifest records.
|
|
539
548
|
*
|
|
540
549
|
* The capability prompt offers `events` and `security`, but only six of its
|
|
541
550
|
* eight options reached ScaffoldOptions, so ticking **Security** produced
|
|
542
|
-
* no dependency, no manifest capability and no message.
|
|
551
|
+
* no dependency, no manifest capability and no message. Later this function
|
|
552
|
+
* returned early when no capability had an entry in FEATURE_PACKAGES, so
|
|
553
|
+
* `--capabilities events,cqrs` put `events` in the manifest but not in
|
|
554
|
+
* package.json; and it mapped packages differently from `zudojs doctor`, so
|
|
555
|
+
* a microservice gateway declared `cqrs` without `@zudojs/cqrs`.
|
|
543
556
|
*/
|
|
544
557
|
async function applyCapabilityPackages(targetPath, capabilities, context) {
|
|
545
558
|
if (capabilities.length === 0)
|
|
@@ -547,14 +560,7 @@ async function applyCapabilityPackages(targetPath, capabilities, context) {
|
|
|
547
560
|
const layout = resolveProjectLayout(targetPath);
|
|
548
561
|
if (!layout || layout.backendDirs.length === 0)
|
|
549
562
|
return;
|
|
550
|
-
const required =
|
|
551
|
-
for (const capability of capabilities) {
|
|
552
|
-
for (const name of FEATURE_PACKAGES[capability] ?? []) {
|
|
553
|
-
required.add(name);
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
|
-
if (required.size === 0)
|
|
557
|
-
return;
|
|
563
|
+
const required = capabilityPackages(capabilities);
|
|
558
564
|
const added = new Set();
|
|
559
565
|
for (const pkgPath of selectAddTargets(layout, undefined)) {
|
|
560
566
|
if (!existsSync(pkgPath))
|
|
@@ -564,7 +570,7 @@ async function applyCapabilityPackages(targetPath, capabilities, context) {
|
|
|
564
570
|
let changed = false;
|
|
565
571
|
for (const name of required) {
|
|
566
572
|
if (!(name in pkg.dependencies)) {
|
|
567
|
-
pkg.dependencies[name] =
|
|
573
|
+
pkg.dependencies[name] = zudojsVersionRange(name);
|
|
568
574
|
added.add(name);
|
|
569
575
|
changed = true;
|
|
570
576
|
}
|
|
@@ -614,26 +620,7 @@ async function collectProjectProblems(targetPath, options, installed) {
|
|
|
614
620
|
* Writes the machine-managed .zudojs/manifest.json so follow-up commands
|
|
615
621
|
* (`zudojs dev`, `generate`, `add`) recognize the project immediately.
|
|
616
622
|
*/
|
|
617
|
-
async function writeProjectManifest(options, targetPath,
|
|
618
|
-
const capabilities = [];
|
|
619
|
-
if (options.enableCQRS)
|
|
620
|
-
capabilities.push("cqrs");
|
|
621
|
-
if (options.enableMessaging)
|
|
622
|
-
capabilities.push("messaging");
|
|
623
|
-
if (options.enableObservability)
|
|
624
|
-
capabilities.push("observability");
|
|
625
|
-
if (options.enableOpenAPI)
|
|
626
|
-
capabilities.push("openapi");
|
|
627
|
-
if (options.enableDatabase)
|
|
628
|
-
capabilities.push("database");
|
|
629
|
-
if (options.enableQueue)
|
|
630
|
-
capabilities.push("queue");
|
|
631
|
-
// Capabilities with no ScaffoldOptions flag of their own (events,
|
|
632
|
-
// security) were selected and then dropped on the floor.
|
|
633
|
-
for (const capability of selected) {
|
|
634
|
-
if (!capabilities.includes(capability))
|
|
635
|
-
capabilities.push(capability);
|
|
636
|
-
}
|
|
623
|
+
async function writeProjectManifest(options, targetPath, capabilities) {
|
|
637
624
|
// Record the services actually generated, not the raw request: the
|
|
638
625
|
// microservice template drops reserved names (gateway) and duplicates, and
|
|
639
626
|
// the modular-monolith template normalizes each name into a directory
|
|
@@ -670,7 +657,7 @@ async function writeProjectManifest(options, targetPath, selected = []) {
|
|
|
670
657
|
: {}),
|
|
671
658
|
...(options.database ? { database: { provider: options.database } } : {}),
|
|
672
659
|
workspace: { packageManager: options.packageManager },
|
|
673
|
-
capabilities,
|
|
660
|
+
capabilities: [...capabilities],
|
|
674
661
|
...(services ? { services: [...services] } : {}),
|
|
675
662
|
});
|
|
676
663
|
}
|
|
@@ -695,7 +682,7 @@ async function generateFullstackProject(options, projectPath, rollback) {
|
|
|
695
682
|
workspace: {
|
|
696
683
|
packageManager: options.packageManager,
|
|
697
684
|
},
|
|
698
|
-
features: options
|
|
685
|
+
features: resolveProjectCapabilities(options),
|
|
699
686
|
},
|
|
700
687
|
projectPath,
|
|
701
688
|
installDeps: options.installDeps,
|
|
@@ -730,7 +717,7 @@ async function generateFullstackProject(options, projectPath, rollback) {
|
|
|
730
717
|
workspace: {
|
|
731
718
|
packageManager: options.packageManager,
|
|
732
719
|
},
|
|
733
|
-
features: options
|
|
720
|
+
features: resolveProjectCapabilities(options),
|
|
734
721
|
},
|
|
735
722
|
projectPath,
|
|
736
723
|
backendPort: 3000,
|
|
@@ -16,7 +16,8 @@ export interface DoctorCheck {
|
|
|
16
16
|
readonly severity: "error" | "warning";
|
|
17
17
|
}
|
|
18
18
|
/**
|
|
19
|
-
* Runs every diagnostic for the project
|
|
19
|
+
* Runs every diagnostic for the project containing `cwd` (any directory
|
|
20
|
+
* inside it: the root is found by walking up, as `generate` does).
|
|
20
21
|
*
|
|
21
22
|
* Exported so the checks can be run against a scaffolded directory in tests
|
|
22
23
|
* without going through the logger.
|