@ykdz/template 0.0.33 → 0.0.36
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/dist/application.d.ts +2 -1
- package/dist/application.js +64 -75
- package/dist/main.js +6 -2
- package/node_modules/@ykdz/template-builtin-presets/dist/src/foundation.d.ts +50 -36
- package/node_modules/@ykdz/template-builtin-presets/dist/src/foundation.js +970 -365
- package/node_modules/@ykdz/template-builtin-presets/dist/src/generation-record.d.ts +24 -0
- package/node_modules/@ykdz/template-builtin-presets/dist/src/generation-record.js +154 -0
- package/node_modules/@ykdz/template-builtin-presets/dist/src/index.d.ts +2 -2
- package/node_modules/@ykdz/template-builtin-presets/dist/src/index.js +1 -1
- package/node_modules/@ykdz/template-builtin-presets/dist/src/rust-bin/definition.d.ts +31 -2
- package/node_modules/@ykdz/template-builtin-presets/dist/src/rust-bin/definition.js +29 -33
- package/node_modules/@ykdz/template-builtin-presets/dist/src/shared/development-container.d.ts +1 -0
- package/node_modules/@ykdz/template-builtin-presets/dist/src/shared/development-container.js +17 -0
- package/node_modules/@ykdz/template-builtin-presets/dist/src/shared/typescript.d.ts +4 -3
- package/node_modules/@ykdz/template-builtin-presets/dist/src/shared/typescript.js +9 -5
- package/node_modules/@ykdz/template-builtin-presets/dist/src/shared/vue.d.ts +1 -1
- package/node_modules/@ykdz/template-builtin-presets/dist/src/shared/vue.js +1 -2
- package/node_modules/@ykdz/template-builtin-presets/dist/src/ts-cli/definition.d.ts +31 -2
- package/node_modules/@ykdz/template-builtin-presets/dist/src/ts-cli/definition.js +79 -58
- package/node_modules/@ykdz/template-builtin-presets/dist/src/ts-lib/definition.d.ts +31 -2
- package/node_modules/@ykdz/template-builtin-presets/dist/src/ts-lib/definition.js +31 -23
- package/node_modules/@ykdz/template-builtin-presets/dist/src/vike-app/definition.d.ts +22 -2
- package/node_modules/@ykdz/template-builtin-presets/dist/src/vike-app/definition.js +61 -35
- package/node_modules/@ykdz/template-builtin-presets/dist/src/vue-app/definition.d.ts +26 -2
- package/node_modules/@ykdz/template-builtin-presets/dist/src/vue-app/definition.js +19 -8
- package/node_modules/@ykdz/template-builtin-presets/dist/src/vue-hono-app/definition.d.ts +22 -2
- package/node_modules/@ykdz/template-builtin-presets/dist/src/vue-hono-app/definition.js +31 -21
- package/node_modules/@ykdz/template-builtin-presets/package.json +12 -11
- package/node_modules/@ykdz/template-builtin-presets/templates/foundation/.github/workflows/check-deployment-diagnostics.yml +1 -1
- package/node_modules/@ykdz/template-builtin-presets/templates/foundation/.github/workflows/check-deployment.yml +1 -1
- package/node_modules/@ykdz/template-builtin-presets/templates/foundation/.pnpmfile.mjs +19 -0
- package/node_modules/@ykdz/template-builtin-presets/templates/foundation/gitignore +1 -0
- package/node_modules/@ykdz/template-builtin-presets/templates/foundation/tsconfig.packing-hook.json +8 -0
- package/node_modules/@ykdz/template-builtin-presets/templates/shared/devcontainer/github-cli.Dockerfile +9 -0
- package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/CHANGELOG.md.template +17 -0
- package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/RELEASING.md +17 -0
- package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/artifact.ts +1271 -0
- package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/changelog.ts +283 -0
- package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/check-artifact.ts +99 -0
- package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/check-readiness.ts +66 -0
- package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/cli-command-identity.ts +4 -0
- package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/handoff.ts +450 -0
- package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/publish.ts +483 -0
- package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/readiness.ts +1125 -0
- package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/release.ts +819 -0
- package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/release.yml +119 -0
- package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/root-tsconfig.json +13 -0
- package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/tsconfig.json +4 -0
- package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/turbo.json +6 -0
- package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication-setup/README.md +48 -0
- package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication-setup/assets/CHANGELOG.md.template +17 -0
- package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication-setup/assets/LICENSE-APACHE-2.0.txt +202 -0
- package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication-setup/assets/LICENSE-MIT.txt +21 -0
- package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication-setup/assets/README.md.template +5 -0
- package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication-setup/bridge.ts +3336 -0
- package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication-setup/setup.sh +221 -0
- package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/src/cli-command-identity.ts +133 -0
- package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/src/cli.ts +4 -3
- package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/src/main.ts +5 -4
- package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/test/integration/command.test.ts +14 -13
- package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/test/unit/cli-command-identity.test.ts +76 -0
- package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/tsconfig.build.json +2 -0
- package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/db/src/readiness.ts +1 -1
- package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/db/test/global-setup.ts +21 -0
- package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/db/tsconfig.json +6 -1
- package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/db/vitest.config.ts +7 -0
- package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/db-migrations/drizzle.config.ts +5 -1
- package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/web/playwright.config.ts +102 -22
- package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/web/test/playwright-teardown.ts +12 -0
- package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/web/vite.config.ts +39 -1
- package/node_modules/@ykdz/template-builtin-presets/templates/vue-app/playwright.config.ts +48 -7
- package/node_modules/@ykdz/template-builtin-presets/templates/vue-hono-app/web/playwright.config.ts +59 -8
- package/node_modules/@ykdz/template-core/dist/module-graph.d.ts +15 -53
- package/node_modules/@ykdz/template-core/dist/module-graph.js +134 -101
- package/node_modules/@ykdz/template-core/dist/package-contribution.d.ts +13 -1
- package/node_modules/@ykdz/template-core/dist/package-contribution.js +92 -0
- package/node_modules/@ykdz/template-core/dist/pnpm-workspace.yaml +14 -10
- package/node_modules/@ykdz/template-core/dist/preset-definition.d.ts +71 -13
- package/node_modules/@ykdz/template-core/dist/preset-definition.js +16 -1
- package/node_modules/@ykdz/template-core/dist/project-blueprint.d.ts +56 -0
- package/node_modules/@ykdz/template-core/dist/project-blueprint.js +271 -0
- package/node_modules/@ykdz/template-core/dist/project-linking-v2.d.ts +2 -2
- package/node_modules/@ykdz/template-core/dist/project-linking-v2.js +2 -2
- package/node_modules/@ykdz/template-core/dist/project-projection.d.ts +2 -1
- package/node_modules/@ykdz/template-core/dist/project-projection.js +107 -20
- package/node_modules/@ykdz/template-core/dist/renderer.d.ts +0 -2
- package/node_modules/@ykdz/template-core/dist/renderer.js +17 -38
- package/node_modules/@ykdz/template-core/dist/template-boundary-check.d.ts +2 -2
- package/node_modules/@ykdz/template-core/dist/template-boundary-check.js +6 -0
- package/node_modules/@ykdz/template-core/dist/toolchain-resolution.d.ts +2 -0
- package/node_modules/@ykdz/template-core/dist/toolchain-resolution.js +9 -3
- package/package.json +3 -3
- package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/db-migrations/scripts/prepare-database.ts +0 -45
- package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/web/scripts/run-playwright.ts +0 -151
- package/node_modules/@ykdz/template-builtin-presets/templates/vue-app/scripts/run-playwright.ts +0 -62
- package/node_modules/@ykdz/template-builtin-presets/templates/vue-hono-app/web/scripts/run-playwright.ts +0 -103
- package/node_modules/@ykdz/template-core/dist/project-blueprint-v2.d.ts +0 -33
- package/node_modules/@ykdz/template-core/dist/project-blueprint-v2.js +0 -182
|
@@ -1,74 +1,156 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
function isRecord(value) {
|
|
2
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3
|
+
}
|
|
4
|
+
function assertExactKeys(value, allowedKeys, context) {
|
|
5
|
+
for (const key of Object.keys(value)) {
|
|
6
|
+
if (!allowedKeys.includes(key)) {
|
|
7
|
+
throw new Error(`${context} contains unknown field: ${key}`);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
function parseComponentOwner(value, context) {
|
|
12
|
+
if (!isRecord(value)) {
|
|
13
|
+
throw new Error(`${context} must be a Component Owner`);
|
|
14
|
+
}
|
|
15
|
+
assertExactKeys(value, ["kind", "path"], context);
|
|
16
|
+
if (value.kind === "workspace-orchestration" && value.path === ".") {
|
|
17
|
+
return { kind: value.kind, path: value.path };
|
|
18
|
+
}
|
|
19
|
+
if (value.kind === "package-boundary" &&
|
|
20
|
+
typeof value.path === "string" &&
|
|
21
|
+
value.path.length > 0) {
|
|
22
|
+
return { kind: value.kind, path: value.path };
|
|
23
|
+
}
|
|
24
|
+
throw new Error(`${context} is not a supported Component Owner`);
|
|
25
|
+
}
|
|
26
|
+
function parseCheckEnvironmentNeed(value, context) {
|
|
27
|
+
if (!isRecord(value)) {
|
|
28
|
+
throw new Error(`${context} must be a Check Environment Need`);
|
|
29
|
+
}
|
|
30
|
+
switch (value.kind) {
|
|
31
|
+
case "playwright-browser-assets": {
|
|
32
|
+
assertExactKeys(value, ["kind", "browser", "owner"], context);
|
|
33
|
+
if (value.browser !== "chromium") {
|
|
34
|
+
throw new Error(`${context}.browser must be chromium`);
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
kind: value.kind,
|
|
38
|
+
browser: value.browser,
|
|
39
|
+
owner: parseComponentOwner(value.owner, `${context}.owner`),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
5
42
|
case "shellcheck-command":
|
|
6
|
-
|
|
7
|
-
|
|
43
|
+
assertExactKeys(value, ["kind", "owner"], context);
|
|
44
|
+
return {
|
|
45
|
+
kind: value.kind,
|
|
46
|
+
owner: parseComponentOwner(value.owner, `${context}.owner`),
|
|
47
|
+
};
|
|
48
|
+
case "rust-toolchain": {
|
|
49
|
+
assertExactKeys(value, ["kind", "owner", "toolchain"], context);
|
|
50
|
+
if (value.toolchain !== "stable") {
|
|
51
|
+
throw new Error(`${context}.toolchain must be stable`);
|
|
52
|
+
}
|
|
8
53
|
return {
|
|
9
|
-
kind:
|
|
10
|
-
owner:
|
|
11
|
-
toolchain:
|
|
54
|
+
kind: value.kind,
|
|
55
|
+
owner: parseComponentOwner(value.owner, `${context}.owner`),
|
|
56
|
+
toolchain: value.toolchain,
|
|
12
57
|
};
|
|
58
|
+
}
|
|
59
|
+
default:
|
|
60
|
+
throw new Error(`${context} has unsupported kind: ${String(value.kind)}`);
|
|
13
61
|
}
|
|
14
62
|
}
|
|
15
|
-
|
|
16
|
-
|
|
63
|
+
function parseDeploymentEnvironmentNeed(value, context) {
|
|
64
|
+
if (!isRecord(value)) {
|
|
65
|
+
throw new Error(`${context} must be a Deployment Environment Need`);
|
|
66
|
+
}
|
|
67
|
+
assertExactKeys(value, ["kind"], context);
|
|
68
|
+
if (value.kind !== "docker-engine") {
|
|
69
|
+
throw new Error(`${context} has unsupported kind: ${String(value.kind)}`);
|
|
70
|
+
}
|
|
71
|
+
return { kind: value.kind };
|
|
72
|
+
}
|
|
73
|
+
function componentOwnerIdentity(owner) {
|
|
74
|
+
return `${owner.kind}:${owner.path}`;
|
|
75
|
+
}
|
|
76
|
+
function checkEnvironmentNeedConflictKey(need) {
|
|
77
|
+
return `${need.kind}:${componentOwnerIdentity(need.owner)}`;
|
|
78
|
+
}
|
|
79
|
+
function checkEnvironmentNeedIdentity(need) {
|
|
80
|
+
switch (need.kind) {
|
|
17
81
|
case "playwright-browser-assets":
|
|
18
|
-
return
|
|
19
|
-
browser: fact.browser,
|
|
20
|
-
owner: fact.owner,
|
|
21
|
-
});
|
|
82
|
+
return `${checkEnvironmentNeedConflictKey(need)}:browser=${need.browser}`;
|
|
22
83
|
case "shellcheck-command":
|
|
23
|
-
return
|
|
84
|
+
return checkEnvironmentNeedConflictKey(need);
|
|
24
85
|
case "rust-toolchain":
|
|
25
|
-
return
|
|
86
|
+
return `${checkEnvironmentNeedConflictKey(need)}:toolchain=${need.toolchain}`;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function normalizeCheckEnvironmentNeeds(needs) {
|
|
90
|
+
const byIdentity = new Map();
|
|
91
|
+
const identityByConflictKey = new Map();
|
|
92
|
+
for (const [index, input] of needs.entries()) {
|
|
93
|
+
const need = parseCheckEnvironmentNeed(input, `check[${index}]`);
|
|
94
|
+
const identity = checkEnvironmentNeedIdentity(need);
|
|
95
|
+
const conflictKey = checkEnvironmentNeedConflictKey(need);
|
|
96
|
+
const previousIdentity = identityByConflictKey.get(conflictKey);
|
|
97
|
+
if (previousIdentity !== undefined && previousIdentity !== identity) {
|
|
98
|
+
throw new Error(`Check Environment Need ${conflictKey} has conflicting semantic parameters`);
|
|
99
|
+
}
|
|
100
|
+
identityByConflictKey.set(conflictKey, identity);
|
|
101
|
+
byIdentity.set(identity, need);
|
|
102
|
+
}
|
|
103
|
+
return [...byIdentity]
|
|
104
|
+
.toSorted(([left], [right]) => left.localeCompare(right))
|
|
105
|
+
.map(([, need]) => need);
|
|
106
|
+
}
|
|
107
|
+
function normalizeDeploymentEnvironmentNeeds(needs) {
|
|
108
|
+
const byIdentity = new Map();
|
|
109
|
+
for (const [index, input] of needs.entries()) {
|
|
110
|
+
const need = parseDeploymentEnvironmentNeed(input, `deployment[${index}]`);
|
|
111
|
+
byIdentity.set(need.kind, need);
|
|
26
112
|
}
|
|
113
|
+
return [...byIdentity]
|
|
114
|
+
.toSorted(([left], [right]) => left.localeCompare(right))
|
|
115
|
+
.map(([, need]) => need);
|
|
27
116
|
}
|
|
28
|
-
|
|
29
|
-
|
|
117
|
+
/** Validates, deduplicates, and canonically orders durable Environment Needs. */
|
|
118
|
+
export function normalizeEnvironmentNeeds(options) {
|
|
119
|
+
return {
|
|
120
|
+
schemaVersion: 1,
|
|
121
|
+
check: normalizeCheckEnvironmentNeeds(options.check),
|
|
122
|
+
deployment: normalizeDeploymentEnvironmentNeeds(options.deployment),
|
|
123
|
+
};
|
|
30
124
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
125
|
+
/** Strict codec for Local Template Metadata consumed by Package Addition. */
|
|
126
|
+
export function parseEnvironmentNeedsMetadata(value) {
|
|
127
|
+
if (!isRecord(value)) {
|
|
128
|
+
throw new Error("Environment Need metadata must be an object");
|
|
129
|
+
}
|
|
130
|
+
assertExactKeys(value, ["schemaVersion", "check", "deployment"], "$");
|
|
131
|
+
if (value.schemaVersion !== 1) {
|
|
132
|
+
throw new Error(`Unsupported Environment Need metadata schema version ${String(value.schemaVersion)}; expected 1`);
|
|
133
|
+
}
|
|
134
|
+
if (!Array.isArray(value.check)) {
|
|
135
|
+
throw new Error("$.check must be an array");
|
|
136
|
+
}
|
|
137
|
+
if (!Array.isArray(value.deployment)) {
|
|
138
|
+
throw new Error("$.deployment must be an array");
|
|
34
139
|
}
|
|
35
|
-
return
|
|
140
|
+
return normalizeEnvironmentNeeds({
|
|
141
|
+
check: value.check,
|
|
142
|
+
deployment: value.deployment,
|
|
143
|
+
});
|
|
36
144
|
}
|
|
37
145
|
export function rustToolchainEnvironmentNeed(owner) {
|
|
38
146
|
return {
|
|
39
147
|
kind: "rust-toolchain",
|
|
40
148
|
owner,
|
|
41
149
|
toolchain: "stable",
|
|
42
|
-
nextStep: {
|
|
43
|
-
id: "install-rust-toolchain",
|
|
44
|
-
label: "Install Rust toolchain",
|
|
45
|
-
command: "rustup",
|
|
46
|
-
args: [
|
|
47
|
-
"toolchain",
|
|
48
|
-
"install",
|
|
49
|
-
"stable",
|
|
50
|
-
"--component",
|
|
51
|
-
"rustfmt",
|
|
52
|
-
"--component",
|
|
53
|
-
"clippy",
|
|
54
|
-
],
|
|
55
|
-
display: "rustup toolchain install stable --component rustfmt --component clippy",
|
|
56
|
-
machineVerifiable: false,
|
|
57
|
-
},
|
|
58
150
|
};
|
|
59
151
|
}
|
|
60
152
|
export function dockerEngineEnvironmentNeed() {
|
|
61
|
-
return {
|
|
62
|
-
kind: "docker-engine",
|
|
63
|
-
preparation: {
|
|
64
|
-
id: "verify-docker-engine",
|
|
65
|
-
label: "Verify Docker engine",
|
|
66
|
-
command: "docker",
|
|
67
|
-
args: ["version", "--format", "{{.Server.Version}}"],
|
|
68
|
-
display: "docker version --format {{.Server.Version}}",
|
|
69
|
-
machineVerifiable: true,
|
|
70
|
-
},
|
|
71
|
-
};
|
|
153
|
+
return { kind: "docker-engine" };
|
|
72
154
|
}
|
|
73
155
|
export const qualityTaskVocabulary = [
|
|
74
156
|
"boundaries",
|
|
@@ -92,8 +174,8 @@ export function renderTurboRunCommand(taskNames, args = [], options = {}) {
|
|
|
92
174
|
...(options.taskPrefix ? ["--log-prefix=task"] : []),
|
|
93
175
|
].join(" ");
|
|
94
176
|
}
|
|
95
|
-
export function renderRootCheckCommand() {
|
|
96
|
-
return renderTurboRunCommand(qualityTaskVocabulary, [], {
|
|
177
|
+
export function renderRootCheckCommand(additionalTasks = []) {
|
|
178
|
+
return renderTurboRunCommand([...qualityTaskVocabulary, ...additionalTasks], [], {
|
|
97
179
|
continueAfterFailure: true,
|
|
98
180
|
taskPrefix: true,
|
|
99
181
|
});
|
|
@@ -108,65 +190,16 @@ export function renderFixCommand() {
|
|
|
108
190
|
taskPrefix: true,
|
|
109
191
|
});
|
|
110
192
|
}
|
|
111
|
-
function playwrightBrowserInstallArgs(need, options = {}) {
|
|
112
|
-
const installArgs = [
|
|
113
|
-
"exec",
|
|
114
|
-
"playwright",
|
|
115
|
-
"install",
|
|
116
|
-
...(options.withDeps ? ["--with-deps"] : []),
|
|
117
|
-
need.browser,
|
|
118
|
-
];
|
|
119
|
-
if (need.owner.kind === "package-boundary" && need.owner.path !== ".") {
|
|
120
|
-
return ["--filter", `./${need.owner.path}`, ...installArgs];
|
|
121
|
-
}
|
|
122
|
-
return installArgs;
|
|
123
|
-
}
|
|
124
|
-
export function renderPlaywrightBrowserInstallCommand(need, options = {}) {
|
|
125
|
-
if (need.kind !== "playwright-browser-assets") {
|
|
126
|
-
throw new Error("Playwright install requires browser assets.");
|
|
127
|
-
}
|
|
128
|
-
return ["pnpm", ...playwrightBrowserInstallArgs(need, options)].join(" ");
|
|
129
|
-
}
|
|
130
|
-
export function playwrightBrowserAssetsNextStepDescriptor(owner) {
|
|
131
|
-
if (owner.kind === "package-boundary" && owner.path !== ".") {
|
|
132
|
-
return {
|
|
133
|
-
id: `install-${owner.path.replaceAll("/", "-")}-playwright-browsers`,
|
|
134
|
-
label: `Install Playwright browser assets for ${owner.path} package`,
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
return {
|
|
138
|
-
id: "install-workspace-playwright-browsers",
|
|
139
|
-
label: "Install Playwright browser assets for workspace",
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
193
|
export function playwrightBrowserAssetsEnvironmentNeed(options) {
|
|
143
|
-
const args = playwrightBrowserInstallArgs(options);
|
|
144
|
-
const descriptor = playwrightBrowserAssetsNextStepDescriptor(options.owner);
|
|
145
194
|
return {
|
|
146
195
|
kind: "playwright-browser-assets",
|
|
147
196
|
browser: options.browser,
|
|
148
197
|
owner: options.owner,
|
|
149
|
-
nextStep: {
|
|
150
|
-
id: options.id ?? descriptor.id,
|
|
151
|
-
label: options.label ?? descriptor.label,
|
|
152
|
-
command: "pnpm",
|
|
153
|
-
args,
|
|
154
|
-
display: ["pnpm", ...args].join(" "),
|
|
155
|
-
machineVerifiable: options.machineVerifiable ?? true,
|
|
156
|
-
},
|
|
157
198
|
};
|
|
158
199
|
}
|
|
159
200
|
export function shellCheckEnvironmentNeed(owner) {
|
|
160
201
|
return {
|
|
161
202
|
kind: "shellcheck-command",
|
|
162
203
|
owner,
|
|
163
|
-
nextStep: {
|
|
164
|
-
id: "install-shellcheck",
|
|
165
|
-
label: "Install ShellCheck",
|
|
166
|
-
command: "sudo",
|
|
167
|
-
args: ["sh", "-c", "apt-get update && apt-get install -y shellcheck"],
|
|
168
|
-
display: "sudo apt-get update && sudo apt-get install -y shellcheck",
|
|
169
|
-
machineVerifiable: false,
|
|
170
|
-
},
|
|
171
204
|
};
|
|
172
205
|
}
|
|
@@ -2,10 +2,14 @@ import { type CiDiagnosticArtifactDeclaration } from "./ci-diagnostic-artifact.t
|
|
|
2
2
|
import type { DevelopmentContainerToolLayer } from "./development-container-tool-layer.ts";
|
|
3
3
|
import type { EditorCustomizationCapability } from "./editor-customization.ts";
|
|
4
4
|
import type { CheckEnvironmentNeed, DeploymentEnvironmentNeed } from "./module-graph.ts";
|
|
5
|
-
import type { PackageDefinition } from "./project-blueprint
|
|
5
|
+
import type { PackageDefinition } from "./project-blueprint.ts";
|
|
6
6
|
import type { DependencyMaintenancePolicy } from "./project-github.ts";
|
|
7
7
|
import type { RenderOperation, TemplateSourceHandle } from "./renderer.ts";
|
|
8
8
|
export type FoundationContribution = {
|
|
9
|
+
/** Closed publication capability consumed only by coordinated root policy. */
|
|
10
|
+
readonly npmPublication?: {
|
|
11
|
+
readonly kind: "public-cli-candidate";
|
|
12
|
+
};
|
|
9
13
|
/** Toolchains the Foundation must install and project into coordinated root files. */
|
|
10
14
|
readonly toolchains: {
|
|
11
15
|
readonly rust?: {
|
|
@@ -17,6 +21,10 @@ export type FoundationContribution = {
|
|
|
17
21
|
readonly editorCapabilities: readonly EditorCustomizationCapability[];
|
|
18
22
|
/** Ecosystems and paths whose maintenance belongs in the coordinated root policy. */
|
|
19
23
|
readonly dependencyMaintenance: DependencyMaintenancePolicy;
|
|
24
|
+
/** Explicit dependency on the Foundation-owned TypeScript policy Package. */
|
|
25
|
+
readonly typescriptConfigurationPackage?: {
|
|
26
|
+
readonly dependency: "required";
|
|
27
|
+
};
|
|
20
28
|
/** Workspace membership patterns contributed by package boundaries. */
|
|
21
29
|
readonly workspacePackageGlobs?: readonly string[];
|
|
22
30
|
/** Dependency Catalog entries required by package-owned manifests. */
|
|
@@ -49,6 +57,10 @@ export type PackageContribution = {
|
|
|
49
57
|
/** Requirements prepared only by a focused deployment entrypoint. */
|
|
50
58
|
readonly deploymentEnvironmentNeeds?: readonly DeploymentEnvironmentNeed[];
|
|
51
59
|
};
|
|
60
|
+
/** Validates the portable executable name promised by a CLI Package Boundary. */
|
|
61
|
+
export declare function validateCliCommandName(commandName: string, occupiedCommandNames?: readonly string[]): string;
|
|
62
|
+
/** Validates command portability and uniqueness across one complete plan. */
|
|
63
|
+
export declare function assertPackageContributionCommandNames(contributions: readonly PackageContribution[]): readonly PackageContribution[];
|
|
52
64
|
export declare function assertPackageContribution(contribution: PackageContribution, provenance?: {
|
|
53
65
|
readonly definitionName?: string;
|
|
54
66
|
readonly planner?: string;
|
|
@@ -6,6 +6,98 @@ const operationPath = (operation) => {
|
|
|
6
6
|
return operation.path;
|
|
7
7
|
return "";
|
|
8
8
|
};
|
|
9
|
+
const reservedSystemToolNames = new Set([
|
|
10
|
+
"aux",
|
|
11
|
+
"bash",
|
|
12
|
+
"bun",
|
|
13
|
+
"cmd",
|
|
14
|
+
"com1",
|
|
15
|
+
"com2",
|
|
16
|
+
"com3",
|
|
17
|
+
"com4",
|
|
18
|
+
"com5",
|
|
19
|
+
"com6",
|
|
20
|
+
"com7",
|
|
21
|
+
"com8",
|
|
22
|
+
"com9",
|
|
23
|
+
"con",
|
|
24
|
+
"corepack",
|
|
25
|
+
"deno",
|
|
26
|
+
"git",
|
|
27
|
+
"lpt1",
|
|
28
|
+
"lpt2",
|
|
29
|
+
"lpt3",
|
|
30
|
+
"lpt4",
|
|
31
|
+
"lpt5",
|
|
32
|
+
"lpt6",
|
|
33
|
+
"lpt7",
|
|
34
|
+
"lpt8",
|
|
35
|
+
"lpt9",
|
|
36
|
+
"node",
|
|
37
|
+
"nul",
|
|
38
|
+
"npm",
|
|
39
|
+
"npx",
|
|
40
|
+
"pnpm",
|
|
41
|
+
"powershell",
|
|
42
|
+
"prn",
|
|
43
|
+
"pwsh",
|
|
44
|
+
"sh",
|
|
45
|
+
"yarn",
|
|
46
|
+
"zsh",
|
|
47
|
+
]);
|
|
48
|
+
/** Validates the portable executable name promised by a CLI Package Boundary. */
|
|
49
|
+
export function validateCliCommandName(commandName, occupiedCommandNames = []) {
|
|
50
|
+
if (/[/\\]/u.test(commandName)) {
|
|
51
|
+
throw new Error(`CLI command name must not be a path; received ${JSON.stringify(commandName)}`);
|
|
52
|
+
}
|
|
53
|
+
if (/\p{White_Space}/u.test(commandName)) {
|
|
54
|
+
throw new Error(`CLI command name must not contain whitespace; received ${JSON.stringify(commandName)}`);
|
|
55
|
+
}
|
|
56
|
+
if (/\p{Control}/u.test(commandName)) {
|
|
57
|
+
throw new Error(`CLI command name must not contain a control character; received ${JSON.stringify(commandName)}`);
|
|
58
|
+
}
|
|
59
|
+
if (commandName.startsWith("-")) {
|
|
60
|
+
throw new Error(`CLI command name must not have a leading hyphen; received ${JSON.stringify(commandName)}`);
|
|
61
|
+
}
|
|
62
|
+
if (!/^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/u.test(commandName)) {
|
|
63
|
+
throw new Error(`CLI command name must use lowercase ASCII letters, digits, and single hyphens; received ${JSON.stringify(commandName)}`);
|
|
64
|
+
}
|
|
65
|
+
if (reservedSystemToolNames.has(commandName)) {
|
|
66
|
+
throw new Error(`CLI command name is a reserved system tool; received ${JSON.stringify(commandName)}`);
|
|
67
|
+
}
|
|
68
|
+
if (occupiedCommandNames.includes(commandName)) {
|
|
69
|
+
throw new Error(`CLI command name is already used by another workspace package; received ${JSON.stringify(commandName)}`);
|
|
70
|
+
}
|
|
71
|
+
return commandName;
|
|
72
|
+
}
|
|
73
|
+
function manifestBinEntries(contribution) {
|
|
74
|
+
const bin = contribution.manifest.bin;
|
|
75
|
+
if (typeof bin !== "object" || bin === null || Array.isArray(bin)) {
|
|
76
|
+
return [];
|
|
77
|
+
}
|
|
78
|
+
return Object.entries(bin);
|
|
79
|
+
}
|
|
80
|
+
/** Validates command portability and uniqueness across one complete plan. */
|
|
81
|
+
export function assertPackageContributionCommandNames(contributions) {
|
|
82
|
+
const commandOwner = new Map();
|
|
83
|
+
for (const contribution of contributions) {
|
|
84
|
+
const entries = manifestBinEntries(contribution);
|
|
85
|
+
for (const [commandName] of entries) {
|
|
86
|
+
const existingOwner = commandOwner.get(commandName);
|
|
87
|
+
try {
|
|
88
|
+
validateCliCommandName(commandName, [...commandOwner.keys()]);
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
if (existingOwner !== undefined) {
|
|
92
|
+
throw new Error(`CLI command name ${JSON.stringify(commandName)} from ${contribution.definition.name} is already used by ${existingOwner}`);
|
|
93
|
+
}
|
|
94
|
+
throw error;
|
|
95
|
+
}
|
|
96
|
+
commandOwner.set(commandName, contribution.definition.name);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return contributions;
|
|
100
|
+
}
|
|
9
101
|
export function assertPackageContribution(contribution, provenance = {}) {
|
|
10
102
|
if (contribution.definition.name !== contribution.manifest.name) {
|
|
11
103
|
throw new Error("Package Contribution manifest name must match its Package Definition");
|
|
@@ -23,7 +23,7 @@ overrides:
|
|
|
23
23
|
catalog:
|
|
24
24
|
"@devcontainers/cli": 0.88.0
|
|
25
25
|
"@hono/node-server": ^2.0.12
|
|
26
|
-
"@playwright/test": ^1.
|
|
26
|
+
"@playwright/test": ^1.62.1
|
|
27
27
|
"@tailwindcss/vite": ^4.3.3
|
|
28
28
|
"@types/node": ^24.13.3
|
|
29
29
|
"@types/web-bluetooth": ^0.0.21
|
|
@@ -34,28 +34,32 @@ catalog:
|
|
|
34
34
|
commander: ^15.0.0
|
|
35
35
|
drizzle-kit: 1.0.0-rc.4
|
|
36
36
|
drizzle-orm: 1.0.0-rc.4
|
|
37
|
-
execa: ^10.0.
|
|
38
|
-
hono: ^4.
|
|
37
|
+
execa: ^10.0.1
|
|
38
|
+
hono: ^4.13.3
|
|
39
39
|
node-diff3: ^3.2.1
|
|
40
|
+
npm: 11.19.1
|
|
40
41
|
oxfmt: ^0.58.0
|
|
41
|
-
oxlint: ^1.
|
|
42
|
+
oxlint: ^1.77.0
|
|
42
43
|
oxlint-tsgolint: ^7.0.2001
|
|
43
44
|
semver: ^7.8.5
|
|
44
45
|
"@types/semver": ^7.7.1
|
|
46
|
+
spdx-expression-parse: ^5.0.0
|
|
47
|
+
"@types/spdx-expression-parse": ^4.0.0
|
|
45
48
|
pinia: ^4.0.2
|
|
46
|
-
srvx: ^0.12.
|
|
47
|
-
tailwindcss: ^4.3.
|
|
49
|
+
srvx: ^0.12.5
|
|
50
|
+
tailwindcss: ^4.3.3
|
|
51
|
+
tar: ^7.5.22
|
|
48
52
|
telefunc: ^0.2.22
|
|
49
|
-
turbo: 2.10.
|
|
53
|
+
turbo: 2.10.11
|
|
50
54
|
typescript: npm:@typescript/typescript6@^6.0.2
|
|
51
55
|
typescript-7: npm:typescript@^7.0.2
|
|
52
56
|
valibot: ^1.4.2
|
|
53
|
-
vite: ^8.
|
|
57
|
+
vite: ^8.2.0
|
|
54
58
|
vike: ^0.4.260
|
|
55
59
|
vike-vue: ^0.9.12
|
|
56
60
|
vitest: ^4.1.10
|
|
57
|
-
vue: ^3.5.
|
|
58
|
-
vue-tsc: ^3.3.
|
|
61
|
+
vue: ^3.5.40
|
|
62
|
+
vue-tsc: ^3.3.9
|
|
59
63
|
yaml: ^2.9.0
|
|
60
64
|
|
|
61
65
|
catalogs:
|
|
@@ -1,18 +1,65 @@
|
|
|
1
1
|
import type { PackageContribution } from "./package-contribution.ts";
|
|
2
|
-
import type {
|
|
2
|
+
import type { PackageDefinition, PackageRole, ProjectBlueprintDraft } from "./project-blueprint.ts";
|
|
3
3
|
import type { TemplateSourceHandle } from "./renderer.ts";
|
|
4
4
|
/** Stable, preset-agnostic input supplied after toolchain resolution. */
|
|
5
5
|
export type GenerationContext = {
|
|
6
6
|
readonly targetDir: string;
|
|
7
|
-
readonly
|
|
8
|
-
readonly
|
|
7
|
+
readonly repositoryName: string;
|
|
8
|
+
readonly defaultPackageScope: string;
|
|
9
|
+
readonly foundationPackages: {
|
|
10
|
+
readonly typescriptConfiguration: {
|
|
11
|
+
readonly name: string;
|
|
12
|
+
};
|
|
13
|
+
};
|
|
9
14
|
readonly toolchain: {
|
|
10
15
|
readonly nodeLtsMajor: string;
|
|
11
16
|
readonly packageManagerPin: string;
|
|
12
17
|
};
|
|
13
18
|
};
|
|
14
|
-
/**
|
|
15
|
-
export type
|
|
19
|
+
/** An in-memory plan tagged with the stable adapter that can replay it. */
|
|
20
|
+
export type PlannedPackageContribution = PackageContribution & {
|
|
21
|
+
readonly planningIdentity: string;
|
|
22
|
+
};
|
|
23
|
+
/** Narrow access to initial sibling packages, keyed by stable adapter identity. */
|
|
24
|
+
export type InitialPackageDefinitionLookup = {
|
|
25
|
+
require(identity: string): PackageDefinition;
|
|
26
|
+
};
|
|
27
|
+
export type PackageContributionReplayAdapter = {
|
|
28
|
+
readonly identity: string;
|
|
29
|
+
identify(contribution: PackageContribution): PlannedPackageContribution;
|
|
30
|
+
replay(options: {
|
|
31
|
+
readonly context: GenerationContext;
|
|
32
|
+
readonly planningContribution: "foundationPlan" | "planInitialization" | "planPackageAddition";
|
|
33
|
+
readonly packageDefinition: PackageDefinition;
|
|
34
|
+
readonly packageLeafName: string;
|
|
35
|
+
readonly initialPackages: InitialPackageDefinitionLookup;
|
|
36
|
+
}): PackageContribution;
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Declares one stable replay semantic. Persisted provenance selection and
|
|
40
|
+
* diagnostics stay with the Foundation instead of leaking into Presets.
|
|
41
|
+
*/
|
|
42
|
+
export declare function definePackageContributionReplayAdapter(options: {
|
|
43
|
+
readonly identity: string;
|
|
44
|
+
readonly replay: PackageContributionReplayAdapter["replay"];
|
|
45
|
+
}): PackageContributionReplayAdapter;
|
|
46
|
+
export type ResolvedPrimaryPackageIdentity = {
|
|
47
|
+
readonly leafName: string;
|
|
48
|
+
readonly definition: PackageDefinition;
|
|
49
|
+
};
|
|
50
|
+
/** Optional behavior owned only by Presets with a configurable initial package. */
|
|
51
|
+
export type InitialPrimaryPackageCapability = {
|
|
52
|
+
readonly defaultLeafName: string;
|
|
53
|
+
readonly role: PackageRole;
|
|
54
|
+
defaultPackagePath(options: {
|
|
55
|
+
readonly packageLeafName: string;
|
|
56
|
+
}): string;
|
|
57
|
+
planInitialContribution(options: {
|
|
58
|
+
readonly context: GenerationContext;
|
|
59
|
+
readonly resolvedPackageIdentity: ResolvedPrimaryPackageIdentity;
|
|
60
|
+
}): PlannedPackageContribution;
|
|
61
|
+
};
|
|
62
|
+
type BuiltInPresetDefinitionBase = {
|
|
16
63
|
readonly metadata: {
|
|
17
64
|
readonly name: string;
|
|
18
65
|
readonly title: string;
|
|
@@ -22,13 +69,8 @@ export type BuiltInPresetDefinition = {
|
|
|
22
69
|
readonly source: TemplateSourceHandle;
|
|
23
70
|
/** The owned planner source inspected by the Template Boundary Check. */
|
|
24
71
|
readonly plannerSourceFile: string;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Multi-package Definitions expose their complete owned topology directly,
|
|
29
|
-
* while single-package Definitions keep the compact tracer interface.
|
|
30
|
-
*/
|
|
31
|
-
planInitializationContributions?(context: GenerationContext): readonly PackageContribution[];
|
|
72
|
+
/** Stable semantics used to replay persisted Package Definitions. */
|
|
73
|
+
readonly packageContributionReplayAdapters: readonly PackageContributionReplayAdapter[];
|
|
32
74
|
/** Package layout is Preset-owned even when callers omit --path. */
|
|
33
75
|
defaultPackagePath?(options: {
|
|
34
76
|
readonly context: GenerationContext;
|
|
@@ -38,5 +80,21 @@ export type BuiltInPresetDefinition = {
|
|
|
38
80
|
readonly context: GenerationContext;
|
|
39
81
|
readonly packageLeafName: string;
|
|
40
82
|
readonly packagePath: string;
|
|
41
|
-
}):
|
|
83
|
+
}): PlannedPackageContribution;
|
|
84
|
+
};
|
|
85
|
+
type ConfigurablePrimaryPackagePresetDefinition = BuiltInPresetDefinitionBase & {
|
|
86
|
+
readonly initialPrimaryPackage: InitialPrimaryPackageCapability;
|
|
87
|
+
readonly blueprint?: never;
|
|
88
|
+
readonly planInitialization?: never;
|
|
89
|
+
readonly planInitializationContributions?: never;
|
|
42
90
|
};
|
|
91
|
+
type FixedTopologyPresetDefinition = BuiltInPresetDefinitionBase & {
|
|
92
|
+
readonly initialPrimaryPackage?: never;
|
|
93
|
+
blueprint(context: GenerationContext): ProjectBlueprintDraft;
|
|
94
|
+
planInitialization(context: GenerationContext): PlannedPackageContribution;
|
|
95
|
+
/** Multi-package Definitions expose their complete owned topology directly. */
|
|
96
|
+
planInitializationContributions?(context: GenerationContext): readonly PlannedPackageContribution[];
|
|
97
|
+
};
|
|
98
|
+
/** A side-effect-free Built-in Preset planner. */
|
|
99
|
+
export type BuiltInPresetDefinition = ConfigurablePrimaryPackagePresetDefinition | FixedTopologyPresetDefinition;
|
|
100
|
+
export {};
|
|
@@ -1 +1,16 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Declares one stable replay semantic. Persisted provenance selection and
|
|
3
|
+
* diagnostics stay with the Foundation instead of leaking into Presets.
|
|
4
|
+
*/
|
|
5
|
+
export function definePackageContributionReplayAdapter(options) {
|
|
6
|
+
if (options.identity.length === 0) {
|
|
7
|
+
throw new Error("Package Contribution replay adapter identity is required");
|
|
8
|
+
}
|
|
9
|
+
return {
|
|
10
|
+
identity: options.identity,
|
|
11
|
+
identify(contribution) {
|
|
12
|
+
return { ...contribution, planningIdentity: options.identity };
|
|
13
|
+
},
|
|
14
|
+
replay: options.replay,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The durable, preset-agnostic topology used by local template follow-up
|
|
3
|
+
* operations. Preset provenance deliberately belongs in Generation Record.
|
|
4
|
+
*/
|
|
5
|
+
declare const packageRoles: readonly ["cli-tool", "runtime-service", "shared-library", "native-package"];
|
|
6
|
+
export type PackageRole = (typeof packageRoles)[number];
|
|
7
|
+
export type PackageDefinition = {
|
|
8
|
+
readonly name: string;
|
|
9
|
+
readonly path: string;
|
|
10
|
+
readonly role: PackageRole;
|
|
11
|
+
};
|
|
12
|
+
/** Opaque durable identity assigned once when a Package Definition is created. */
|
|
13
|
+
export type PackageDefinitionId = `package-${string}`;
|
|
14
|
+
export type PersistedPackageDefinition = PackageDefinition & {
|
|
15
|
+
readonly packageDefinitionId: PackageDefinitionId;
|
|
16
|
+
};
|
|
17
|
+
export type PackageLinkIntent = {
|
|
18
|
+
readonly consumerPackagePath: string;
|
|
19
|
+
readonly providerPackagePath: string;
|
|
20
|
+
};
|
|
21
|
+
export type ProjectBlueprint = {
|
|
22
|
+
readonly schemaVersion: 3;
|
|
23
|
+
readonly packages: readonly PersistedPackageDefinition[];
|
|
24
|
+
readonly packageLinkIntents?: readonly PackageLinkIntent[];
|
|
25
|
+
};
|
|
26
|
+
/** Preset-owned topology before Foundation assigns durable package identities. */
|
|
27
|
+
export type ProjectBlueprintDraft = {
|
|
28
|
+
readonly schemaVersion: 3;
|
|
29
|
+
readonly packages: readonly PackageDefinition[];
|
|
30
|
+
readonly packageLinkIntents?: readonly PackageLinkIntent[];
|
|
31
|
+
};
|
|
32
|
+
export type BlueprintValidationIssue = {
|
|
33
|
+
readonly path: string;
|
|
34
|
+
readonly message: string;
|
|
35
|
+
};
|
|
36
|
+
export type BlueprintValidationResult = {
|
|
37
|
+
readonly ok: true;
|
|
38
|
+
readonly value: ProjectBlueprint;
|
|
39
|
+
} | {
|
|
40
|
+
readonly ok: false;
|
|
41
|
+
readonly issues: readonly BlueprintValidationIssue[];
|
|
42
|
+
};
|
|
43
|
+
/** Canonical npm package-name predicate shared by Blueprint and input preparation. */
|
|
44
|
+
export declare function isValidNewNpmPackageName(value: string): boolean;
|
|
45
|
+
export type NewPackagePathValidation = {
|
|
46
|
+
readonly hasValidShape: boolean;
|
|
47
|
+
readonly reservedWorkspaceCollection?: string;
|
|
48
|
+
};
|
|
49
|
+
/** Canonical Package Path facts shared by Blueprint and input preparation. */
|
|
50
|
+
export declare function validateNewPackagePath(value: string): NewPackagePathValidation;
|
|
51
|
+
/** Validates persisted metadata before it is used to plan or render changes. */
|
|
52
|
+
export declare function validateProjectBlueprint(value: unknown): BlueprintValidationResult;
|
|
53
|
+
/** Validates preset-owned topology before any persisted identity is assigned. */
|
|
54
|
+
export declare function assertProjectBlueprintDraft(value: ProjectBlueprintDraft): ProjectBlueprintDraft;
|
|
55
|
+
export declare function assertProjectBlueprint(value: unknown): ProjectBlueprint;
|
|
56
|
+
export {};
|