zudojs-cli 2.0.1 → 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 +59 -7
- 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.js +61 -87
- 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
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* @module generators/integration
|
|
5
5
|
*/
|
|
6
|
-
import { existsSync } from "node:fs";
|
|
6
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
7
7
|
import { join } from "node:path";
|
|
8
8
|
import { mergeBarrelExport, writeFileTree, } from "../../utils/utils.fileSystem.js";
|
|
9
9
|
import { renderDatabaseEnv } from "../../adapters/databases/databaseAdapter.resolver.js";
|
|
@@ -33,6 +33,18 @@ export class IntegrationGenerator {
|
|
|
33
33
|
const configDir = `${this.getBackendPath(context)}src/configs`;
|
|
34
34
|
files[`${configDir}/cors.ts`] = this.generateCorsConfig(context);
|
|
35
35
|
files[`${configDir}/index.ts`] = mergeBarrelExport(context.projectPath, `${configDir}/index.ts`, `export { corsConfig } from "./cors.js";`);
|
|
36
|
+
// The generated server enforces CORS_ORIGINS (empty: no browser
|
|
37
|
+
// origin allowed), so the frontend's dev origin must be listed there or
|
|
38
|
+
// every cross-origin call from it is refused.
|
|
39
|
+
const backendEnv = `${this.getBackendPath(context)}.env.example`;
|
|
40
|
+
const backendEnvPath = join(context.projectPath, backendEnv);
|
|
41
|
+
if (existsSync(backendEnvPath)) {
|
|
42
|
+
const origins = this.frontendOrigins(context).join(",");
|
|
43
|
+
const current = readFileSync(backendEnvPath, "utf-8");
|
|
44
|
+
if (/^CORS_ORIGINS=$/m.test(current)) {
|
|
45
|
+
files[backendEnv] = current.replace(/^CORS_ORIGINS=$/m, `CORS_ORIGINS=${origins}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
36
48
|
// Development proxy configuration (belongs to the frontend app). The
|
|
37
49
|
// frontend adapter has already written a vite.config.ts carrying the
|
|
38
50
|
// framework plugin and path aliases; overwriting it with this minimal
|
|
@@ -59,10 +71,22 @@ export class IntegrationGenerator {
|
|
|
59
71
|
// written anywhere, so nothing downstream could agree with the CORS
|
|
60
72
|
// origins generated from the same value.
|
|
61
73
|
`FRONTEND_PORT=${frontendPort}`,
|
|
74
|
+
`CORS_ORIGINS=${this.frontendOrigins(context).join(",")}`,
|
|
62
75
|
`VITE_API_URL=http://localhost:${backendPort}`,
|
|
63
76
|
"",
|
|
64
77
|
"# Database",
|
|
65
|
-
|
|
78
|
+
// The database docker-compose.yml creates (it was "mydb").
|
|
79
|
+
renderDatabaseEnv(context.project.backend?.database, context.project.name),
|
|
80
|
+
// Empty, never a placeholder such as "change-me": docker-compose.yml
|
|
81
|
+
// refuses to start until it is set. Hex keeps it valid in a URL.
|
|
82
|
+
...(context.project.backend?.database === "sqlite"
|
|
83
|
+
? []
|
|
84
|
+
: [
|
|
85
|
+
"# Password for the docker-compose.yml database; generate with: openssl rand -hex 32",
|
|
86
|
+
context.project.backend?.database === "mysql"
|
|
87
|
+
? "MYSQL_ROOT_PASSWORD="
|
|
88
|
+
: "POSTGRES_PASSWORD=",
|
|
89
|
+
]),
|
|
66
90
|
"",
|
|
67
91
|
];
|
|
68
92
|
if (context.project.frontend?.framework === "next") {
|
|
@@ -167,6 +191,11 @@ export const api = {
|
|
|
167
191
|
}
|
|
168
192
|
return "apps/web/src/services/api-client.ts";
|
|
169
193
|
}
|
|
194
|
+
/** Origins the frontend dev server is reached on. */
|
|
195
|
+
frontendOrigins(context) {
|
|
196
|
+
const port = context.frontendPort ?? 5173;
|
|
197
|
+
return [`http://localhost:${port}`, `http://127.0.0.1:${port}`];
|
|
198
|
+
}
|
|
170
199
|
generateCorsConfig(context) {
|
|
171
200
|
const frontendPort = context.frontendPort ?? 5173;
|
|
172
201
|
return `/**
|
|
@@ -7,10 +7,14 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { basename, dirname } from "node:path";
|
|
9
9
|
import { mergeBarrelExport, writeFileTree } from "../../utils/utils.fileSystem.js";
|
|
10
|
-
import { CLIGenerationError } from "../../errors/index.js";
|
|
10
|
+
import { CLIGenerationError, CLIValidationError } from "../../errors/index.js";
|
|
11
11
|
import { assertGeneratableName, toPascalCase } from "../../utils/utils.name.js";
|
|
12
12
|
import { moduleSpec, renderModuleFile } from "../../templates/shared/appRuntime.template.js";
|
|
13
13
|
import { registerModuleInApp } from "./module.registration.js";
|
|
14
|
+
import { moduleRoutesWiring, renderModuleRoutesIndex, } from "../../templates/backendApp/index.js";
|
|
15
|
+
import { MARKERS, applyMarkerEdits, conflictingImport } from "../../wiring/index.js";
|
|
16
|
+
import { existsSync } from "node:fs";
|
|
17
|
+
import { join } from "node:path";
|
|
14
18
|
export async function generateModule(options, cwd) {
|
|
15
19
|
const basePath = options.basePath ?? "modules";
|
|
16
20
|
const name = assertGeneratableName(options.name, "module name");
|
|
@@ -34,8 +38,21 @@ export class ${namePascal}Feature {
|
|
|
34
38
|
files[`${basePath}/${name}/features/index.ts`] = `export { ${namePascal}Feature } from "./${featureName}.js";
|
|
35
39
|
`;
|
|
36
40
|
}
|
|
41
|
+
// A module gets its own routes index, registered with the app's
|
|
42
|
+
// src/routes/index.ts, when the app has one (every app `create` writes).
|
|
43
|
+
const appSrc = dirname(basePath);
|
|
44
|
+
const appRoutes = `${appSrc}/routes/index.ts`;
|
|
45
|
+
const routes = moduleRoutesWiring(name);
|
|
46
|
+
const hasAppRoutes = existsSync(join(cwd, appRoutes));
|
|
47
|
+
const clash = hasAppRoutes ? conflictingImport(cwd, appRoutes, routes.importLine) : undefined;
|
|
48
|
+
if (clash !== undefined) {
|
|
49
|
+
throw new CLIValidationError(`${appRoutes} already imports ${routes.functionName} (${clash.trim()}), so module "${name}" cannot register its routes. Choose another name.`);
|
|
50
|
+
}
|
|
51
|
+
if (hasAppRoutes) {
|
|
52
|
+
files[`${basePath}/${name}/routes/index.ts`] = renderModuleRoutesIndex(routes.functionName, "../../../container.js");
|
|
53
|
+
}
|
|
37
54
|
if (options.dryRun) {
|
|
38
|
-
return Object.keys(files);
|
|
55
|
+
return hasAppRoutes ? [...Object.keys(files), appRoutes] : Object.keys(files);
|
|
39
56
|
}
|
|
40
57
|
try {
|
|
41
58
|
await writeFileTree(cwd, files);
|
|
@@ -43,9 +60,24 @@ export class ${namePascal}Feature {
|
|
|
43
60
|
catch (error) {
|
|
44
61
|
throw new CLIGenerationError(`Failed to generate module: ${name}`, error);
|
|
45
62
|
}
|
|
63
|
+
const routeEdits = hasAppRoutes
|
|
64
|
+
? await applyMarkerEdits(cwd, [
|
|
65
|
+
{ file: appRoutes, marker: MARKERS.routeImports, line: routes.importLine },
|
|
66
|
+
{ file: appRoutes, marker: MARKERS.routes, line: routes.entryLine },
|
|
67
|
+
])
|
|
68
|
+
: undefined;
|
|
46
69
|
const appPath = `${dirname(basePath)}/app.ts`;
|
|
47
70
|
const registration = registerModuleInApp(cwd, appPath, spec.className, `./${basename(basePath)}/index.js`);
|
|
48
|
-
options.onRegistered?.(
|
|
49
|
-
|
|
71
|
+
options.onRegistered?.(routeEdits && routeEdits.manualSteps.length > 0
|
|
72
|
+
? {
|
|
73
|
+
registered: registration.registered,
|
|
74
|
+
manualSteps: [...registration.manualSteps, ...routeEdits.manualSteps],
|
|
75
|
+
}
|
|
76
|
+
: registration);
|
|
77
|
+
return [
|
|
78
|
+
...Object.keys(files),
|
|
79
|
+
...(registration.registered ? [appPath] : []),
|
|
80
|
+
...(routeEdits?.edited ?? []),
|
|
81
|
+
];
|
|
50
82
|
}
|
|
51
83
|
//# sourceMappingURL=module.generator.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* zudojs-cli — Resource generator: `generate resource|route|controller|repository|dto`.
|
|
3
|
+
*/
|
|
4
|
+
export * from "./resource.plan.js";
|
|
5
|
+
export * from "./resource.generator.js";
|
|
6
|
+
export * from "./resource.layout.js";
|
|
7
|
+
export * from "./resource.run.js";
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* zudojs-cli — Resource generator: `generate resource|route|controller|repository|dto`.
|
|
3
|
+
*/
|
|
4
|
+
export * from "./resource.plan.js";
|
|
5
|
+
export * from "./resource.generator.js";
|
|
6
|
+
export * from "./resource.layout.js";
|
|
7
|
+
export * from "./resource.run.js";
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* zudojs-cli — Resource generator.
|
|
3
|
+
*
|
|
4
|
+
* Writes the files of a resource-family schematic (see `resource.plan.ts`)
|
|
5
|
+
* and wires them: the routes are registered between the markers of the
|
|
6
|
+
* nearest `routes/index.ts`, and the controller is constructed once, in the
|
|
7
|
+
* app's `src/container.ts`. Running it twice for the same name fails with
|
|
8
|
+
* the files that already exist; it never duplicates a registration.
|
|
9
|
+
*/
|
|
10
|
+
import { type ResourceLayout } from "../../templates/resource/index.js";
|
|
11
|
+
import { type ResourceSchematic } from "./resource.plan.js";
|
|
12
|
+
/** Options for {@link generateResource}. */
|
|
13
|
+
export interface GenerateResourceOptions {
|
|
14
|
+
readonly name: string;
|
|
15
|
+
readonly schematic: ResourceSchematic;
|
|
16
|
+
readonly layout: ResourceLayout;
|
|
17
|
+
readonly dryRun?: boolean;
|
|
18
|
+
/** Overwrite the schematic's own files when they exist. */
|
|
19
|
+
readonly force?: boolean;
|
|
20
|
+
}
|
|
21
|
+
/** What {@link generateResource} wrote and what is left to do by hand. */
|
|
22
|
+
export interface ResourceGenerationResult {
|
|
23
|
+
readonly files: readonly string[];
|
|
24
|
+
readonly manualSteps: readonly string[];
|
|
25
|
+
}
|
|
26
|
+
export declare function generateResource(options: GenerateResourceOptions, cwd: string): Promise<ResourceGenerationResult>;
|
|
27
|
+
//# sourceMappingURL=resource.generator.d.ts.map
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* zudojs-cli — Resource generator.
|
|
3
|
+
*
|
|
4
|
+
* Writes the files of a resource-family schematic (see `resource.plan.ts`)
|
|
5
|
+
* and wires them: the routes are registered between the markers of the
|
|
6
|
+
* nearest `routes/index.ts`, and the controller is constructed once, in the
|
|
7
|
+
* app's `src/container.ts`. Running it twice for the same name fails with
|
|
8
|
+
* the files that already exist; it never duplicates a registration.
|
|
9
|
+
*/
|
|
10
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
11
|
+
import { join } from "node:path";
|
|
12
|
+
import { CLIValidationError } from "../../errors/index.js";
|
|
13
|
+
import { renderHttpUtils } from "../../templates/backendApp/index.js";
|
|
14
|
+
import { hasPrismaModel, joinPath, renderPrismaModel, renderResourceLayers, resourceLayerPaths, resourceNames, resourceWiring, } from "../../templates/resource/index.js";
|
|
15
|
+
import { writeFileTree } from "../../utils/utils.fileSystem.js";
|
|
16
|
+
import { MARKERS, applyMarkerEdits, conflictingImport, } from "../../wiring/index.js";
|
|
17
|
+
import { planResource } from "./resource.plan.js";
|
|
18
|
+
export async function generateResource(options, cwd) {
|
|
19
|
+
const names = resourceNames(options.name);
|
|
20
|
+
const { layout } = options;
|
|
21
|
+
const plan = planResource(options.schematic);
|
|
22
|
+
const exists = (path) => existsSync(join(cwd, path));
|
|
23
|
+
const primaryPaths = plan.primary.flatMap((layer) => resourceLayerPaths(names, layout, layer));
|
|
24
|
+
const taken = primaryPaths.filter(exists);
|
|
25
|
+
if (taken.length > 0 && options.force !== true) {
|
|
26
|
+
throw new CLIValidationError(`${options.schematic} "${names.slug}" already exists:\n${taken
|
|
27
|
+
.map((path) => ` - ${path}`)
|
|
28
|
+
.join("\n")}\nChoose another name, or re-run with --force to regenerate these files.`);
|
|
29
|
+
}
|
|
30
|
+
const wiring = resourceWiring(names, layout);
|
|
31
|
+
if (plan.register && exists(wiring.container)) {
|
|
32
|
+
const container = readFileSync(join(cwd, wiring.container), "utf-8");
|
|
33
|
+
if (container.includes(`${wiring.containerKey}:`) && taken.length === 0) {
|
|
34
|
+
throw new CLIValidationError(`${wiring.container} already constructs "${wiring.containerKey}" (a resource named "${names.slug}" exists elsewhere in this app). Choose another name.`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const clash = plan.register
|
|
38
|
+
? conflictingImport(cwd, wiring.routesIndex, wiring.routeImport)
|
|
39
|
+
: undefined;
|
|
40
|
+
if (clash !== undefined) {
|
|
41
|
+
throw new CLIValidationError(`${wiring.routesIndex} already imports the routes function ${options.schematic} "${names.slug}" would register (${clash.trim()}). Choose another name.`);
|
|
42
|
+
}
|
|
43
|
+
const missingRequired = plan.required.filter((layer) => resourceLayerPaths(names, layout, layer).some((path) => !exists(path)));
|
|
44
|
+
const files = renderResourceLayers(names, layout, [
|
|
45
|
+
...missingRequired,
|
|
46
|
+
...plan.primary,
|
|
47
|
+
]);
|
|
48
|
+
// Older projects have no src/utils/http.ts, which controllers import.
|
|
49
|
+
const httpUtils = joinPath(layout.appSrc, "utils", "http.ts");
|
|
50
|
+
if ((plan.primary.includes("controller") || missingRequired.includes("controller")) &&
|
|
51
|
+
!exists(httpUtils)) {
|
|
52
|
+
files[httpUtils] = renderHttpUtils();
|
|
53
|
+
}
|
|
54
|
+
const writesRepository = plan.primary.includes("repository") || missingRequired.includes("repository");
|
|
55
|
+
const schemaPath = joinPath(layout.appRoot, "prisma", "schema.prisma");
|
|
56
|
+
if (layout.prisma && writesRepository && exists(schemaPath)) {
|
|
57
|
+
const schema = readFileSync(join(cwd, schemaPath), "utf-8");
|
|
58
|
+
if (!hasPrismaModel(schema, names.entity)) {
|
|
59
|
+
files[schemaPath] = `${schema.replace(/\n*$/, "\n")}${renderPrismaModel(names)}`;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
const edits = plan.register
|
|
63
|
+
? [
|
|
64
|
+
{ file: wiring.routesIndex, marker: MARKERS.routeImports, line: wiring.routeImport },
|
|
65
|
+
{ file: wiring.routesIndex, marker: MARKERS.routes, line: wiring.routeEntry },
|
|
66
|
+
...wiring.containerImports.map((line) => ({
|
|
67
|
+
file: wiring.container,
|
|
68
|
+
marker: MARKERS.containerImports,
|
|
69
|
+
line,
|
|
70
|
+
})),
|
|
71
|
+
{ file: wiring.container, marker: MARKERS.container, line: wiring.containerEntry },
|
|
72
|
+
]
|
|
73
|
+
: [];
|
|
74
|
+
if (!options.dryRun) {
|
|
75
|
+
await writeFileTree(cwd, files);
|
|
76
|
+
}
|
|
77
|
+
const outcome = await applyMarkerEdits(cwd, edits, options.dryRun === true);
|
|
78
|
+
const manualSteps = [...outcome.manualSteps];
|
|
79
|
+
if (layout.prisma && writesRepository) {
|
|
80
|
+
manualSteps.push(`Run "prisma migrate dev --name add-${names.slug}" (the ${names.entity} model was added to ${schemaPath}).`);
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
files: [...Object.keys(files), ...outcome.edited],
|
|
84
|
+
manualSteps,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=resource.generator.js.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* zudojs-cli — Where `generate` puts a resource in each architecture.
|
|
3
|
+
*
|
|
4
|
+
* - monolith / modular monolith: the app is the project root (`apps/api`
|
|
5
|
+
* in a fullstack workspace); `--module <name>` places the resource in
|
|
6
|
+
* `src/modules/<name>/` and registers it in that module's routes index.
|
|
7
|
+
* - microservice: the gateway app, or `apps/services/<name>` with
|
|
8
|
+
* `--service <name>`; `--module` works inside that app the same way.
|
|
9
|
+
*/
|
|
10
|
+
import { type ResourceLayout } from "../../templates/resource/index.js";
|
|
11
|
+
/** Inputs of {@link resolveResourceLayout}. */
|
|
12
|
+
export interface ResourceLayoutInput {
|
|
13
|
+
readonly cwd: string;
|
|
14
|
+
readonly architecture: string | undefined;
|
|
15
|
+
/** `""` or `"apps/api"`: where a non-microservice backend lives. */
|
|
16
|
+
readonly backendRoot: string;
|
|
17
|
+
readonly service?: string;
|
|
18
|
+
readonly module?: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Resolves the {@link ResourceLayout} for a generate call.
|
|
22
|
+
*
|
|
23
|
+
* @throws {CLIValidationError} When the selected service or module does not exist.
|
|
24
|
+
*/
|
|
25
|
+
export declare function resolveResourceLayout(input: ResourceLayoutInput): ResourceLayout;
|
|
26
|
+
//# sourceMappingURL=resource.layout.d.ts.map
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* zudojs-cli — Where `generate` puts a resource in each architecture.
|
|
3
|
+
*
|
|
4
|
+
* - monolith / modular monolith: the app is the project root (`apps/api`
|
|
5
|
+
* in a fullstack workspace); `--module <name>` places the resource in
|
|
6
|
+
* `src/modules/<name>/` and registers it in that module's routes index.
|
|
7
|
+
* - microservice: the gateway app, or `apps/services/<name>` with
|
|
8
|
+
* `--service <name>`; `--module` works inside that app the same way.
|
|
9
|
+
*/
|
|
10
|
+
import { existsSync } from "node:fs";
|
|
11
|
+
import { join } from "node:path";
|
|
12
|
+
import { CLIValidationError } from "../../errors/index.js";
|
|
13
|
+
import { joinPath } from "../../templates/resource/index.js";
|
|
14
|
+
/**
|
|
15
|
+
* Resolves the {@link ResourceLayout} for a generate call.
|
|
16
|
+
*
|
|
17
|
+
* @throws {CLIValidationError} When the selected service or module does not exist.
|
|
18
|
+
*/
|
|
19
|
+
export function resolveResourceLayout(input) {
|
|
20
|
+
const { cwd } = input;
|
|
21
|
+
let appRoot = input.backendRoot;
|
|
22
|
+
if (input.architecture === "microservice") {
|
|
23
|
+
appRoot =
|
|
24
|
+
input.service === undefined || input.service === "gateway"
|
|
25
|
+
? "apps/gateway"
|
|
26
|
+
: `apps/services/${input.service}`;
|
|
27
|
+
if (!existsSync(join(cwd, appRoot, "package.json"))) {
|
|
28
|
+
throw new CLIValidationError(`No app at ${appRoot}. Pass --service with an existing service (or omit it for the gateway).`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
const appSrc = joinPath(appRoot, "src");
|
|
32
|
+
let base = appSrc;
|
|
33
|
+
if (input.module !== undefined) {
|
|
34
|
+
base = joinPath(appSrc, "modules", input.module);
|
|
35
|
+
if (!existsSync(join(cwd, base))) {
|
|
36
|
+
throw new CLIValidationError(`Module "${input.module}" does not exist at ${base}. Create it first: zudojs generate module ${input.module}`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
base,
|
|
41
|
+
appSrc,
|
|
42
|
+
appRoot,
|
|
43
|
+
prisma: existsSync(join(cwd, appRoot, "prisma", "schema.prisma")),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=resource.layout.js.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* zudojs-cli — Which files a resource-family schematic writes.
|
|
3
|
+
*
|
|
4
|
+
* `resource`, `route`, `controller`, `repository` and `dto` all write part
|
|
5
|
+
* of the same DTO → repository → service → controller → routes chain. Each
|
|
6
|
+
* writes its own layer ("primary") and any lower layer that does not exist
|
|
7
|
+
* yet ("required"), so whatever it writes compiles on its own:
|
|
8
|
+
* `generate controller users` also writes the users service, repository
|
|
9
|
+
* and DTO when they are missing, and never touches them when they exist.
|
|
10
|
+
*/
|
|
11
|
+
import type { ResourceLayer } from "../../templates/resource/index.js";
|
|
12
|
+
/** Schematics served by the resource generator. */
|
|
13
|
+
export declare const RESOURCE_SCHEMATICS: readonly ["resource", "route", "controller", "repository", "dto"];
|
|
14
|
+
/** A schematic served by the resource generator. */
|
|
15
|
+
export type ResourceSchematic = (typeof RESOURCE_SCHEMATICS)[number];
|
|
16
|
+
/** Whether `schematic` is served by the resource generator. */
|
|
17
|
+
export declare function isResourceSchematic(schematic: string): schematic is ResourceSchematic;
|
|
18
|
+
/** The layers a schematic owns, and the ones it needs underneath. */
|
|
19
|
+
export interface ResourcePlan {
|
|
20
|
+
readonly primary: readonly ResourceLayer[];
|
|
21
|
+
readonly required: readonly ResourceLayer[];
|
|
22
|
+
/** Whether the routes are registered and the controller constructed. */
|
|
23
|
+
readonly register: boolean;
|
|
24
|
+
}
|
|
25
|
+
/** The {@link ResourcePlan} of each schematic. */
|
|
26
|
+
export declare function planResource(schematic: ResourceSchematic): ResourcePlan;
|
|
27
|
+
//# sourceMappingURL=resource.plan.d.ts.map
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* zudojs-cli — Which files a resource-family schematic writes.
|
|
3
|
+
*
|
|
4
|
+
* `resource`, `route`, `controller`, `repository` and `dto` all write part
|
|
5
|
+
* of the same DTO → repository → service → controller → routes chain. Each
|
|
6
|
+
* writes its own layer ("primary") and any lower layer that does not exist
|
|
7
|
+
* yet ("required"), so whatever it writes compiles on its own:
|
|
8
|
+
* `generate controller users` also writes the users service, repository
|
|
9
|
+
* and DTO when they are missing, and never touches them when they exist.
|
|
10
|
+
*/
|
|
11
|
+
/** Schematics served by the resource generator. */
|
|
12
|
+
export const RESOURCE_SCHEMATICS = [
|
|
13
|
+
"resource",
|
|
14
|
+
"route",
|
|
15
|
+
"controller",
|
|
16
|
+
"repository",
|
|
17
|
+
"dto",
|
|
18
|
+
];
|
|
19
|
+
/** Whether `schematic` is served by the resource generator. */
|
|
20
|
+
export function isResourceSchematic(schematic) {
|
|
21
|
+
return RESOURCE_SCHEMATICS.includes(schematic);
|
|
22
|
+
}
|
|
23
|
+
/** The {@link ResourcePlan} of each schematic. */
|
|
24
|
+
export function planResource(schematic) {
|
|
25
|
+
switch (schematic) {
|
|
26
|
+
case "resource":
|
|
27
|
+
return {
|
|
28
|
+
primary: ["dto", "repository", "service", "controller", "routes", "test"],
|
|
29
|
+
required: [],
|
|
30
|
+
register: true,
|
|
31
|
+
};
|
|
32
|
+
case "route":
|
|
33
|
+
return {
|
|
34
|
+
primary: ["routes"],
|
|
35
|
+
required: ["dto", "repository", "service", "controller"],
|
|
36
|
+
register: true,
|
|
37
|
+
};
|
|
38
|
+
case "controller":
|
|
39
|
+
return { primary: ["controller"], required: ["dto", "repository", "service"], register: false };
|
|
40
|
+
case "repository":
|
|
41
|
+
return { primary: ["repository"], required: ["dto"], register: false };
|
|
42
|
+
case "dto":
|
|
43
|
+
return { primary: ["dto"], required: [], register: false };
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=resource.plan.js.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* zudojs-cli — Running a resource-family schematic for `zudojs generate`.
|
|
3
|
+
*/
|
|
4
|
+
import type { CLIContext } from "../../cliType/cliType.type.js";
|
|
5
|
+
import type { ResourceSchematic } from "./resource.plan.js";
|
|
6
|
+
/** Inputs of {@link runResourceSchematic}. */
|
|
7
|
+
export interface ResourceSchematicRun {
|
|
8
|
+
readonly schematic: ResourceSchematic;
|
|
9
|
+
readonly name: string;
|
|
10
|
+
readonly cwd: string;
|
|
11
|
+
/** `""` or `"apps/api"` (fullstack). */
|
|
12
|
+
readonly backendRoot: string;
|
|
13
|
+
readonly architecture: string | undefined;
|
|
14
|
+
readonly service?: string;
|
|
15
|
+
readonly moduleName?: string;
|
|
16
|
+
readonly dryRun: boolean;
|
|
17
|
+
readonly force: boolean;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Runs a resource-family schematic: writes the DTO → repository → service
|
|
21
|
+
* → controller → routes chain it needs and registers the routes and the
|
|
22
|
+
* controller between the project's markers.
|
|
23
|
+
*/
|
|
24
|
+
export declare function runResourceSchematic(context: CLIContext, run: ResourceSchematicRun): Promise<void>;
|
|
25
|
+
//# sourceMappingURL=resource.run.d.ts.map
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* zudojs-cli — Running a resource-family schematic for `zudojs generate`.
|
|
3
|
+
*/
|
|
4
|
+
import { describeError } from "../../commands/commandError.helper.js";
|
|
5
|
+
import { CLIGenerationError, CLIValidationError } from "../../errors/index.js";
|
|
6
|
+
import { generateResource } from "./resource.generator.js";
|
|
7
|
+
import { resolveResourceLayout } from "./resource.layout.js";
|
|
8
|
+
import { describeAddedDependencies, ensureZudojsDependencies, fileCount, } from "../../wiring/index.js";
|
|
9
|
+
/**
|
|
10
|
+
* Runs a resource-family schematic: writes the DTO → repository → service
|
|
11
|
+
* → controller → routes chain it needs and registers the routes and the
|
|
12
|
+
* controller between the project's markers.
|
|
13
|
+
*/
|
|
14
|
+
export async function runResourceSchematic(context, run) {
|
|
15
|
+
const layout = resolveResourceLayout({
|
|
16
|
+
cwd: run.cwd,
|
|
17
|
+
architecture: run.architecture,
|
|
18
|
+
backendRoot: run.backendRoot,
|
|
19
|
+
...(run.service !== undefined ? { service: run.service } : {}),
|
|
20
|
+
...(run.moduleName !== undefined ? { module: run.moduleName } : {}),
|
|
21
|
+
});
|
|
22
|
+
let result;
|
|
23
|
+
try {
|
|
24
|
+
result = await generateResource({
|
|
25
|
+
name: run.name,
|
|
26
|
+
schematic: run.schematic,
|
|
27
|
+
layout,
|
|
28
|
+
dryRun: run.dryRun,
|
|
29
|
+
force: run.force,
|
|
30
|
+
}, run.cwd);
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
if (error instanceof CLIValidationError)
|
|
34
|
+
throw error;
|
|
35
|
+
throw new CLIGenerationError(`Failed to generate ${run.schematic} "${run.name}": ${describeError(error)}`, error);
|
|
36
|
+
}
|
|
37
|
+
context.logger.info(run.dryRun
|
|
38
|
+
? `Dry run: ${fileCount(result.files.length)} would be written or updated (nothing written):`
|
|
39
|
+
: `Generated ${fileCount(result.files.length)}:`);
|
|
40
|
+
for (const file of result.files) {
|
|
41
|
+
context.logger.info(` - ${file}`);
|
|
42
|
+
}
|
|
43
|
+
if (!run.dryRun) {
|
|
44
|
+
for (const line of describeAddedDependencies(ensureZudojsDependencies(run.cwd, result.files))) {
|
|
45
|
+
context.logger.warn(line);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (result.manualSteps.length > 0) {
|
|
49
|
+
context.logger.warn(`Finish by hand:\n${result.manualSteps.map((step) => ` - ${step}`).join("\n")}`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=resource.run.js.map
|
|
@@ -11,8 +11,12 @@
|
|
|
11
11
|
* an abort was indistinguishable from a success. The exit status is now 130,
|
|
12
12
|
* the conventional "terminated by SIGINT" value.
|
|
13
13
|
*
|
|
14
|
+
* The return type strips `symbol` from the argument's type rather than
|
|
15
|
+
* inferring `T` from `T | symbol`: TypeScript 7 infers the clack cancel
|
|
16
|
+
* symbol into `T` from that pattern, which broke every call site.
|
|
17
|
+
*
|
|
14
18
|
* @param value - The value a `@clack/prompts` call resolved with.
|
|
15
19
|
* @returns The answer, once it is known not to be the cancel symbol.
|
|
16
20
|
*/
|
|
17
|
-
export declare function cancelled<T>(value: T
|
|
21
|
+
export declare function cancelled<T>(value: T): Exclude<T, symbol>;
|
|
18
22
|
//# sourceMappingURL=cancel.prompt.d.ts.map
|
|
@@ -13,6 +13,10 @@ import { CLI_EXIT_CODES } from "../cliConstant/cliConstant.value.js";
|
|
|
13
13
|
* an abort was indistinguishable from a success. The exit status is now 130,
|
|
14
14
|
* the conventional "terminated by SIGINT" value.
|
|
15
15
|
*
|
|
16
|
+
* The return type strips `symbol` from the argument's type rather than
|
|
17
|
+
* inferring `T` from `T | symbol`: TypeScript 7 infers the clack cancel
|
|
18
|
+
* symbol into `T` from that pattern, which broke every call site.
|
|
19
|
+
*
|
|
16
20
|
* @param value - The value a `@clack/prompts` call resolved with.
|
|
17
21
|
* @returns The answer, once it is known not to be the cancel symbol.
|
|
18
22
|
*/
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* zudojs-cli — Interactive Menu
|
|
3
|
+
*
|
|
4
|
+
* The numbered menu a bare `zudojs` / `zudo` opens on an interactive
|
|
5
|
+
* terminal: entries, the digit-or-arrow select prompt, the flow that turns
|
|
6
|
+
* a choice into a command line, and the terminal prompter.
|
|
7
|
+
*/
|
|
8
|
+
export { MENU_CANCEL, type MenuCancel, type MenuFlowOptions, type MenuItem, type MenuItemId, type MenuOutcome, type MenuProjectScope, type MenuPrompter, } from "./menu.type.js";
|
|
9
|
+
export { MENU_CANCELLED, MENU_ITEMS, MENU_MESSAGE, MENU_NAME_PATTERN, } from "./menu.constant.js";
|
|
10
|
+
export { numberedSelect, type NumberedSelectIO } from "./menu.select.js";
|
|
11
|
+
export { notInProjectMessage, runMenuFlow } from "./menu.flow.js";
|
|
12
|
+
export { createTerminalMenuPrompter } from "./menu.adapter.js";
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* zudojs-cli — Interactive Menu
|
|
3
|
+
*
|
|
4
|
+
* The numbered menu a bare `zudojs` / `zudo` opens on an interactive
|
|
5
|
+
* terminal: entries, the digit-or-arrow select prompt, the flow that turns
|
|
6
|
+
* a choice into a command line, and the terminal prompter.
|
|
7
|
+
*/
|
|
8
|
+
export { MENU_CANCEL, } from "./menu.type.js";
|
|
9
|
+
export { MENU_CANCELLED, MENU_ITEMS, MENU_MESSAGE, MENU_NAME_PATTERN, } from "./menu.constant.js";
|
|
10
|
+
export { numberedSelect } from "./menu.select.js";
|
|
11
|
+
export { notInProjectMessage, runMenuFlow } from "./menu.flow.js";
|
|
12
|
+
export { createTerminalMenuPrompter } from "./menu.adapter.js";
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* zudojs-cli — Menu Prompter
|
|
3
|
+
*
|
|
4
|
+
* The terminal implementation of `MenuPrompter`: the numbered select for
|
|
5
|
+
* the menu itself and `@clack/prompts` for the follow-up questions.
|
|
6
|
+
*/
|
|
7
|
+
import { type NumberedSelectIO } from "./menu.select.js";
|
|
8
|
+
import { type MenuPrompter } from "./menu.type.js";
|
|
9
|
+
/**
|
|
10
|
+
* Creates the prompter the binary uses.
|
|
11
|
+
*
|
|
12
|
+
* @param io - Streams to read keys from and draw on; defaults to the
|
|
13
|
+
* process's stdin and stdout.
|
|
14
|
+
*/
|
|
15
|
+
export declare function createTerminalMenuPrompter(io?: NumberedSelectIO): MenuPrompter;
|
|
16
|
+
//# sourceMappingURL=menu.adapter.d.ts.map
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* zudojs-cli — Menu Prompter
|
|
3
|
+
*
|
|
4
|
+
* The terminal implementation of `MenuPrompter`: the numbered select for
|
|
5
|
+
* the menu itself and `@clack/prompts` for the follow-up questions.
|
|
6
|
+
*/
|
|
7
|
+
import * as p from "@clack/prompts";
|
|
8
|
+
import { numberedSelect } from "./menu.select.js";
|
|
9
|
+
import { MENU_CANCEL, } from "./menu.type.js";
|
|
10
|
+
/**
|
|
11
|
+
* Maps clack's cancel symbol onto the menu's own sentinel.
|
|
12
|
+
*
|
|
13
|
+
* Both follow-up prompts answer with a string, so anything else is the
|
|
14
|
+
* cancel symbol; narrowing on `string` avoids TypeScript 7 inferring the
|
|
15
|
+
* clack symbol into a generic parameter (see `cancelled`).
|
|
16
|
+
*/
|
|
17
|
+
function orCancel(value) {
|
|
18
|
+
return typeof value === "string" && !p.isCancel(value) ? value : MENU_CANCEL;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Creates the prompter the binary uses.
|
|
22
|
+
*
|
|
23
|
+
* @param io - Streams to read keys from and draw on; defaults to the
|
|
24
|
+
* process's stdin and stdout.
|
|
25
|
+
*/
|
|
26
|
+
export function createTerminalMenuPrompter(io = { input: process.stdin, output: process.stdout }) {
|
|
27
|
+
return {
|
|
28
|
+
choose: (items) => numberedSelect(items, io),
|
|
29
|
+
async select(message, choices) {
|
|
30
|
+
const value = await p.select({
|
|
31
|
+
message,
|
|
32
|
+
options: choices.map((choice) => ({
|
|
33
|
+
value: choice.value,
|
|
34
|
+
label: choice.label,
|
|
35
|
+
...(choice.hint ? { hint: choice.hint } : {}),
|
|
36
|
+
})),
|
|
37
|
+
});
|
|
38
|
+
return orCancel(value);
|
|
39
|
+
},
|
|
40
|
+
async text(message, placeholder, validate) {
|
|
41
|
+
const value = await p.text({
|
|
42
|
+
message,
|
|
43
|
+
placeholder,
|
|
44
|
+
validate: (input) => validate(input ?? ""),
|
|
45
|
+
});
|
|
46
|
+
return orCancel(value);
|
|
47
|
+
},
|
|
48
|
+
warn(message) {
|
|
49
|
+
p.log.warn(message);
|
|
50
|
+
},
|
|
51
|
+
cancel(message) {
|
|
52
|
+
p.cancel(message);
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=menu.adapter.js.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* zudojs-cli — Menu Entries
|
|
3
|
+
*
|
|
4
|
+
* The numbered entries of the interactive menu, in display order.
|
|
5
|
+
*/
|
|
6
|
+
import type { MenuItem } from "./menu.type.js";
|
|
7
|
+
/** Menu entries; `key` is the digit that selects each one. */
|
|
8
|
+
export declare const MENU_ITEMS: readonly MenuItem[];
|
|
9
|
+
/** The question the menu asks. */
|
|
10
|
+
export declare const MENU_MESSAGE = "What would you like to do?";
|
|
11
|
+
/** Printed when the menu is left with Esc or Ctrl+C. */
|
|
12
|
+
export declare const MENU_CANCELLED = "Operation cancelled.";
|
|
13
|
+
/**
|
|
14
|
+
* Names accepted by the "Generate code" follow-up.
|
|
15
|
+
*
|
|
16
|
+
* The same shape the project-name prompt allows: a leading "-" would be
|
|
17
|
+
* parsed as an option once the name is handed to `generate`.
|
|
18
|
+
*/
|
|
19
|
+
export declare const MENU_NAME_PATTERN: RegExp;
|
|
20
|
+
//# sourceMappingURL=menu.constant.d.ts.map
|