zudojs-cli 2.1.1 → 2.1.3
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 +1 -1
- package/dist/src/bin/zudojs.js +1 -1
- package/dist/src/commands/generate.command.js +11 -16
- package/dist/src/constants/index.js +5 -1
- package/dist/src/constants/zudojsVersions.generated.js +37 -37
- package/dist/src/generators/command/command.generator.d.ts +7 -1
- package/dist/src/generators/command/command.generator.js +18 -44
- package/dist/src/generators/command/command.template.d.ts +24 -0
- package/dist/src/generators/command/command.template.js +78 -0
- package/dist/src/generators/command/index.d.ts +6 -0
- package/dist/src/generators/command/index.js +6 -0
- package/dist/src/generators/index.d.ts +0 -1
- package/dist/src/generators/index.js +0 -1
- package/dist/src/generators/infrastructure/infrastructure.generator.js +1 -1
- package/dist/src/generators/middleware/index.d.ts +2 -1
- package/dist/src/generators/middleware/index.js +2 -1
- package/dist/src/generators/middleware/middleware.generator.d.ts +28 -1
- package/dist/src/generators/middleware/middleware.generator.js +60 -15
- package/dist/src/generators/middleware/middleware.template.d.ts +21 -0
- package/dist/src/generators/middleware/middleware.template.js +35 -0
- package/dist/src/generators/query/index.d.ts +6 -0
- package/dist/src/generators/query/index.js +6 -0
- package/dist/src/generators/query/query.generator.d.ts +7 -1
- package/dist/src/generators/query/query.generator.js +19 -44
- package/dist/src/generators/query/query.template.d.ts +14 -0
- package/dist/src/generators/query/query.template.js +72 -0
- package/dist/src/generators/resource/resource.plan.d.ts +8 -2
- package/dist/src/generators/resource/resource.plan.js +10 -1
- package/dist/src/recipes/docker/docker.recipe.js +1 -1
- package/dist/src/recipes/docker/docker.refresh.js +1 -1
- package/dist/src/templates/resource/layers/resourceData.template.d.ts +1 -1
- package/dist/src/templates/resource/layers/resourceData.template.js +2 -1
- package/dist/src/templates/resource/layers/resourceRoutes.template.d.ts +1 -1
- package/dist/src/templates/resource/layers/resourceRoutes.template.js +6 -5
- package/dist/src/templates/resource/resource.names.d.ts +6 -0
- package/dist/src/templates/resource/resource.names.js +15 -0
- package/dist/src/templates/shared/dockerfile/dockerfile.install.d.ts +35 -0
- package/dist/src/templates/shared/dockerfile/dockerfile.install.js +89 -0
- package/dist/src/templates/shared/{dockerfile.template.d.ts → dockerfile/dockerfile.template.d.ts} +4 -2
- package/dist/src/templates/shared/{dockerfile.template.js → dockerfile/dockerfile.template.js} +17 -30
- package/dist/src/templates/shared/dockerfile/index.d.ts +6 -0
- package/dist/src/templates/shared/dockerfile/index.js +6 -0
- package/dist/src/templates/shared/index.d.ts +1 -1
- package/dist/src/templates/shared/index.js +1 -1
- package/dist/src/templates/shared/server.template.d.ts +7 -0
- package/dist/src/templates/shared/server.template.js +15 -3
- package/package.json +6 -6
- package/dist/src/generators/service/service.generator.d.ts +0 -12
- package/dist/src/generators/service/service.generator.js +0 -41
package/dist/src/templates/shared/{dockerfile.template.js → dockerfile/dockerfile.template.js}
RENAMED
|
@@ -8,30 +8,7 @@
|
|
|
8
8
|
* unprivileged `node` user and declares a /health HEALTHCHECK. The images
|
|
9
9
|
* used to run as root and ship the whole dev toolchain.
|
|
10
10
|
*/
|
|
11
|
-
|
|
12
|
-
export function dockerInstallCommand(packageManager) {
|
|
13
|
-
// No lockfile is generated, so never `npm ci`; bare node images need
|
|
14
|
-
// corepack for pnpm/yarn; bun is not available there, so npm is used.
|
|
15
|
-
switch (packageManager) {
|
|
16
|
-
case "pnpm":
|
|
17
|
-
return "corepack enable && pnpm install";
|
|
18
|
-
case "yarn":
|
|
19
|
-
return "corepack enable && yarn install";
|
|
20
|
-
default:
|
|
21
|
-
return "npm install";
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
/** Removes dev dependencies after the build (scripts off: prisma is a dev tool). */
|
|
25
|
-
function dockerPruneCommand(packageManager) {
|
|
26
|
-
switch (packageManager) {
|
|
27
|
-
case "pnpm":
|
|
28
|
-
return "pnpm prune --prod --ignore-scripts";
|
|
29
|
-
case "yarn":
|
|
30
|
-
return undefined;
|
|
31
|
-
default:
|
|
32
|
-
return "npm prune --omit=dev --ignore-scripts";
|
|
33
|
-
}
|
|
34
|
-
}
|
|
11
|
+
import { lockedInstallSteps, workspaceMemberInstallSteps, } from "./dockerfile.install.js";
|
|
35
12
|
function runnerFor(packageManager) {
|
|
36
13
|
return packageManager === "npm" || packageManager === "bun" ? "npm" : packageManager;
|
|
37
14
|
}
|
|
@@ -54,24 +31,31 @@ CMD ["node", "${dist}/server.js"]
|
|
|
54
31
|
* project root; `appPath` is the app's directory (`.` for a single-app
|
|
55
32
|
* project). pnpm's `pnpm-workspace.yaml` is copied for its build-script
|
|
56
33
|
* allow-list, without which pnpm 11 refuses to install.
|
|
34
|
+
*
|
|
35
|
+
* An app at the project root copies its lockfile and installs frozen (see
|
|
36
|
+
* `dockerfile.install.ts`); an app inside a workspace cannot use the
|
|
37
|
+
* workspace lockfile on its own, and its Dockerfile says so.
|
|
57
38
|
*/
|
|
58
39
|
export function renderAppPackageDockerfile(options) {
|
|
59
40
|
const app = options.appPath.replace(/^\.\/?/, "").replace(/\/$/, "");
|
|
60
41
|
const at = (file) => (app === "" ? file : `${app}/${file}`);
|
|
61
42
|
const pm = options.packageManager;
|
|
62
|
-
const
|
|
43
|
+
const steps = app === "" ? lockedInstallSteps(pm) : workspaceMemberInstallSteps(pm);
|
|
44
|
+
const manifests = app === ""
|
|
45
|
+
? [`COPY ${["package.json", ...steps.files].join(" ")} ./`]
|
|
46
|
+
: [`COPY ${at("package.json")} ./`, ...steps.files.map((file) => `COPY ${file} ./`)];
|
|
63
47
|
const lines = [
|
|
64
48
|
"# syntax=docker/dockerfile:1",
|
|
65
49
|
"FROM node:24-alpine AS build",
|
|
66
50
|
"WORKDIR /app",
|
|
67
|
-
|
|
68
|
-
...
|
|
51
|
+
...steps.comment,
|
|
52
|
+
...manifests,
|
|
69
53
|
...(options.prisma ? [`COPY ${at("prisma.config.ts")} ./`, `COPY ${at("prisma")} ./prisma`] : []),
|
|
70
|
-
`RUN ${
|
|
54
|
+
`RUN ${steps.install}`,
|
|
71
55
|
`COPY ${at("tsconfig.json")} ./`,
|
|
72
56
|
`COPY ${at("src")} ./src`,
|
|
73
57
|
`RUN ${runnerFor(pm)} run build`,
|
|
74
|
-
...(prune === undefined ? [] : [`RUN ${prune}`]),
|
|
58
|
+
...(steps.prune === undefined ? [] : [`RUN ${steps.prune}`]),
|
|
75
59
|
"",
|
|
76
60
|
];
|
|
77
61
|
return `${lines.join("\n")}\n${runtimeStage(options.port, "dist", "/app")}`;
|
|
@@ -86,13 +70,16 @@ export function renderWorkspaceAppDockerfile(options) {
|
|
|
86
70
|
const runner = runnerFor(options.packageManager);
|
|
87
71
|
const build = dir === "" ? `${runner} run build` : `cd ${dir} && ${runner} run build`;
|
|
88
72
|
const dist = dir === "" ? "dist" : `${dir}/dist`;
|
|
73
|
+
// The whole workspace is copied, lockfile included, so it installs frozen.
|
|
74
|
+
const steps = lockedInstallSteps(options.packageManager);
|
|
89
75
|
// pnpm links workspace dependencies through the root node_modules, so
|
|
90
76
|
// the runtime stage takes the whole built workspace.
|
|
91
77
|
return `# syntax=docker/dockerfile:1
|
|
92
78
|
FROM node:24-alpine AS build
|
|
93
79
|
WORKDIR /app
|
|
80
|
+
${steps.comment.join("\n")}
|
|
94
81
|
COPY . .
|
|
95
|
-
RUN ${
|
|
82
|
+
RUN ${steps.install}
|
|
96
83
|
RUN ${build}
|
|
97
84
|
|
|
98
85
|
FROM node:24-alpine AS runtime
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export * from "./appRuntime.template.js";
|
|
5
5
|
export * from "./capability.template.js";
|
|
6
|
-
export * from "./dockerfile.
|
|
6
|
+
export * from "./dockerfile/index.js";
|
|
7
7
|
export * from "./pnpm.template.js";
|
|
8
8
|
export * from "./server.template.js";
|
|
9
9
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export * from "./appRuntime.template.js";
|
|
5
5
|
export * from "./capability.template.js";
|
|
6
|
-
export * from "./dockerfile.
|
|
6
|
+
export * from "./dockerfile/index.js";
|
|
7
7
|
export * from "./pnpm.template.js";
|
|
8
8
|
export * from "./server.template.js";
|
|
9
9
|
//# sourceMappingURL=index.js.map
|
|
@@ -14,6 +14,13 @@
|
|
|
14
14
|
* 500. On SIGINT/SIGTERM integrations drain, HTTP stops, then the runtime
|
|
15
15
|
* stops. `tests/generatedProject.typecheck.test.ts` type-checks the output
|
|
16
16
|
* against the current `@zudojs/*` sources.
|
|
17
|
+
*
|
|
18
|
+
* The signal listeners stay registered (`process.on`, not `once`) for the
|
|
19
|
+
* whole shutdown. Under `tsx watch`, Ctrl+C delivers SIGINT twice (from the
|
|
20
|
+
* terminal and forwarded by the watcher); with `once` the second signal
|
|
21
|
+
* found no listener and Node's default action killed the process before
|
|
22
|
+
* the runtime had stopped or logged anything. "Listening on" is logged once
|
|
23
|
+
* the listeners are in place, so a signal sent after it is always handled.
|
|
17
24
|
*/
|
|
18
25
|
/** Options for {@link renderServerFile}. */
|
|
19
26
|
export interface ServerFileOptions {
|
|
@@ -14,6 +14,13 @@
|
|
|
14
14
|
* 500. On SIGINT/SIGTERM integrations drain, HTTP stops, then the runtime
|
|
15
15
|
* stops. `tests/generatedProject.typecheck.test.ts` type-checks the output
|
|
16
16
|
* against the current `@zudojs/*` sources.
|
|
17
|
+
*
|
|
18
|
+
* The signal listeners stay registered (`process.on`, not `once`) for the
|
|
19
|
+
* whole shutdown. Under `tsx watch`, Ctrl+C delivers SIGINT twice (from the
|
|
20
|
+
* terminal and forwarded by the watcher); with `once` the second signal
|
|
21
|
+
* found no listener and Node's default action killed the process before
|
|
22
|
+
* the runtime had stopped or logged anything. "Listening on" is logged once
|
|
23
|
+
* the listeners are in place, so a signal sent after it is always handled.
|
|
17
24
|
*/
|
|
18
25
|
import { MARKERS, renderMarkerBlock } from "../../wiring/index.js";
|
|
19
26
|
/** Emits a string as a TypeScript string literal that cannot break out. */
|
|
@@ -98,13 +105,16 @@ const server = createHttpServer({
|
|
|
98
105
|
});
|
|
99
106
|
|
|
100
107
|
await server.start();
|
|
101
|
-
console.log(\`Listening on http://\${config.host}:\${server.address?.port ?? config.port}\`);
|
|
102
108
|
|
|
103
109
|
let stopping = false;
|
|
104
110
|
for (const signal of ["SIGINT", "SIGTERM"] as const) {
|
|
105
|
-
process.
|
|
106
|
-
if (stopping)
|
|
111
|
+
process.on(signal, () => {
|
|
112
|
+
if (stopping) {
|
|
113
|
+
console.log(\`Received \${signal} again: already shutting down.\`);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
107
116
|
stopping = true;
|
|
117
|
+
console.log(\`Received \${signal}: shutting down.\`);
|
|
108
118
|
void drainIntegrations(integrations)
|
|
109
119
|
.then(() => server.stop())
|
|
110
120
|
.then(() => runtime.stop())
|
|
@@ -117,6 +127,8 @@ for (const signal of ["SIGINT", "SIGTERM"] as const) {
|
|
|
117
127
|
});
|
|
118
128
|
});
|
|
119
129
|
}
|
|
130
|
+
|
|
131
|
+
console.log(\`Listening on http://\${config.host}:\${server.address?.port ?? config.port}\`);
|
|
120
132
|
`;
|
|
121
133
|
}
|
|
122
134
|
//# sourceMappingURL=server.template.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zudojs-cli",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.3",
|
|
4
4
|
"description": "Command-line interface for scaffolding, generating, and managing Zudojs framework projects.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
@@ -32,14 +32,14 @@
|
|
|
32
32
|
],
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"@clack/prompts": "^1.8.1",
|
|
35
|
-
"@zudojs/config": "1.3.
|
|
36
|
-
"@zudojs/core": "1.2.
|
|
37
|
-
"@zudojs/errors": "1.3.
|
|
38
|
-
"@zudojs/logger": "1.4.
|
|
35
|
+
"@zudojs/config": "1.3.3",
|
|
36
|
+
"@zudojs/core": "1.2.4",
|
|
37
|
+
"@zudojs/errors": "1.3.2",
|
|
38
|
+
"@zudojs/logger": "1.4.3"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@types/node": "^26.6.2",
|
|
42
|
-
"@zudojs/constants": "1.1.
|
|
42
|
+
"@zudojs/constants": "1.1.4",
|
|
43
43
|
"tsx": "^4.23.15",
|
|
44
44
|
"typescript": "7.0.2",
|
|
45
45
|
"vitest": "^5.0.1"
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* zudojs-cli — Service Generator
|
|
3
|
-
*
|
|
4
|
-
* Generates a new service with CQRS structure.
|
|
5
|
-
*/
|
|
6
|
-
export interface GenerateServiceOptions {
|
|
7
|
-
readonly name: string;
|
|
8
|
-
readonly basePath?: string;
|
|
9
|
-
readonly dryRun?: boolean;
|
|
10
|
-
}
|
|
11
|
-
export declare function generateService(options: GenerateServiceOptions, cwd: string): Promise<string[]>;
|
|
12
|
-
//# sourceMappingURL=service.generator.d.ts.map
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* zudojs-cli — Service Generator
|
|
3
|
-
*
|
|
4
|
-
* Generates a new service with CQRS structure.
|
|
5
|
-
*/
|
|
6
|
-
import { writeFileTree, mergeBarrelExport, } from "../../utils/utils.fileSystem.js";
|
|
7
|
-
import { CLIGenerationError } from "../../errors/index.js";
|
|
8
|
-
import { assertGeneratableName, toPascalCase } from "../../utils/utils.name.js";
|
|
9
|
-
export async function generateService(options, cwd) {
|
|
10
|
-
const basePath = options.basePath ?? "services";
|
|
11
|
-
const name = assertGeneratableName(options.name, "service name");
|
|
12
|
-
const namePascal = toPascalCase(name);
|
|
13
|
-
const files = {
|
|
14
|
-
[`${basePath}/${name}/${name}.service.ts`]: `import { createLogger } from "@zudojs/logger";
|
|
15
|
-
|
|
16
|
-
export class ${namePascal}Service {
|
|
17
|
-
private readonly logger = createLogger({ name: "${name}-service" });
|
|
18
|
-
|
|
19
|
-
async initialize(): Promise<void> {
|
|
20
|
-
this.logger.info("${name} service initialized");
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
`,
|
|
24
|
-
// Merge with any existing barrel content instead of overwriting it.
|
|
25
|
-
[`${basePath}/${name}/index.ts`]: mergeBarrelExport(cwd, `${basePath}/${name}/index.ts`, `export { ${namePascal}Service } from "./${name}.service.js";`),
|
|
26
|
-
// Preserve any existing content in the CQRS barrels.
|
|
27
|
-
[`${basePath}/${name}/commands/index.ts`]: mergeBarrelExport(cwd, `${basePath}/${name}/commands/index.ts`, ""),
|
|
28
|
-
[`${basePath}/${name}/queries/index.ts`]: mergeBarrelExport(cwd, `${basePath}/${name}/queries/index.ts`, ""),
|
|
29
|
-
};
|
|
30
|
-
if (options.dryRun) {
|
|
31
|
-
return Object.keys(files);
|
|
32
|
-
}
|
|
33
|
-
try {
|
|
34
|
-
await writeFileTree(cwd, files);
|
|
35
|
-
return Object.keys(files);
|
|
36
|
-
}
|
|
37
|
-
catch (error) {
|
|
38
|
-
throw new CLIGenerationError(`Failed to generate service: ${name}`, error);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
//# sourceMappingURL=service.generator.js.map
|