@ykdz/template 0.0.35 → 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.
Files changed (80) hide show
  1. package/dist/application.d.ts +2 -1
  2. package/dist/application.js +64 -75
  3. package/dist/main.js +6 -2
  4. package/node_modules/@ykdz/template-builtin-presets/dist/src/foundation.d.ts +50 -36
  5. package/node_modules/@ykdz/template-builtin-presets/dist/src/foundation.js +968 -364
  6. package/node_modules/@ykdz/template-builtin-presets/dist/src/generation-record.d.ts +24 -0
  7. package/node_modules/@ykdz/template-builtin-presets/dist/src/generation-record.js +154 -0
  8. package/node_modules/@ykdz/template-builtin-presets/dist/src/index.d.ts +2 -2
  9. package/node_modules/@ykdz/template-builtin-presets/dist/src/index.js +1 -1
  10. package/node_modules/@ykdz/template-builtin-presets/dist/src/rust-bin/definition.d.ts +31 -2
  11. package/node_modules/@ykdz/template-builtin-presets/dist/src/rust-bin/definition.js +29 -33
  12. package/node_modules/@ykdz/template-builtin-presets/dist/src/shared/typescript.d.ts +4 -3
  13. package/node_modules/@ykdz/template-builtin-presets/dist/src/shared/typescript.js +9 -5
  14. package/node_modules/@ykdz/template-builtin-presets/dist/src/shared/vue.d.ts +1 -1
  15. package/node_modules/@ykdz/template-builtin-presets/dist/src/shared/vue.js +0 -1
  16. package/node_modules/@ykdz/template-builtin-presets/dist/src/ts-cli/definition.d.ts +31 -2
  17. package/node_modules/@ykdz/template-builtin-presets/dist/src/ts-cli/definition.js +79 -58
  18. package/node_modules/@ykdz/template-builtin-presets/dist/src/ts-lib/definition.d.ts +31 -2
  19. package/node_modules/@ykdz/template-builtin-presets/dist/src/ts-lib/definition.js +31 -23
  20. package/node_modules/@ykdz/template-builtin-presets/dist/src/vike-app/definition.d.ts +22 -2
  21. package/node_modules/@ykdz/template-builtin-presets/dist/src/vike-app/definition.js +53 -25
  22. package/node_modules/@ykdz/template-builtin-presets/dist/src/vue-app/definition.d.ts +26 -2
  23. package/node_modules/@ykdz/template-builtin-presets/dist/src/vue-app/definition.js +19 -7
  24. package/node_modules/@ykdz/template-builtin-presets/dist/src/vue-hono-app/definition.d.ts +22 -2
  25. package/node_modules/@ykdz/template-builtin-presets/dist/src/vue-hono-app/definition.js +31 -20
  26. package/node_modules/@ykdz/template-builtin-presets/package.json +12 -11
  27. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/.github/workflows/check-deployment-diagnostics.yml +1 -1
  28. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/.github/workflows/check-deployment.yml +1 -1
  29. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/.pnpmfile.mjs +19 -0
  30. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/tsconfig.packing-hook.json +8 -0
  31. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/CHANGELOG.md.template +17 -0
  32. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/RELEASING.md +17 -0
  33. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/artifact.ts +1271 -0
  34. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/changelog.ts +283 -0
  35. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/check-artifact.ts +99 -0
  36. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/check-readiness.ts +66 -0
  37. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/cli-command-identity.ts +4 -0
  38. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/handoff.ts +450 -0
  39. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/publish.ts +483 -0
  40. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/readiness.ts +1125 -0
  41. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/release.ts +819 -0
  42. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/release.yml +119 -0
  43. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/root-tsconfig.json +13 -0
  44. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/tsconfig.json +4 -0
  45. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/turbo.json +6 -0
  46. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication-setup/README.md +48 -0
  47. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication-setup/assets/CHANGELOG.md.template +17 -0
  48. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication-setup/assets/LICENSE-APACHE-2.0.txt +202 -0
  49. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication-setup/assets/LICENSE-MIT.txt +21 -0
  50. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication-setup/assets/README.md.template +5 -0
  51. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication-setup/bridge.ts +3336 -0
  52. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication-setup/setup.sh +221 -0
  53. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/src/cli-command-identity.ts +133 -0
  54. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/src/cli.ts +4 -3
  55. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/src/main.ts +5 -4
  56. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/test/integration/command.test.ts +14 -13
  57. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/test/unit/cli-command-identity.test.ts +76 -0
  58. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/tsconfig.build.json +2 -0
  59. package/node_modules/@ykdz/template-core/dist/module-graph.d.ts +15 -53
  60. package/node_modules/@ykdz/template-core/dist/module-graph.js +134 -101
  61. package/node_modules/@ykdz/template-core/dist/package-contribution.d.ts +13 -1
  62. package/node_modules/@ykdz/template-core/dist/package-contribution.js +92 -0
  63. package/node_modules/@ykdz/template-core/dist/pnpm-workspace.yaml +14 -10
  64. package/node_modules/@ykdz/template-core/dist/preset-definition.d.ts +71 -13
  65. package/node_modules/@ykdz/template-core/dist/preset-definition.js +16 -1
  66. package/node_modules/@ykdz/template-core/dist/project-blueprint.d.ts +56 -0
  67. package/node_modules/@ykdz/template-core/dist/project-blueprint.js +271 -0
  68. package/node_modules/@ykdz/template-core/dist/project-linking-v2.d.ts +2 -2
  69. package/node_modules/@ykdz/template-core/dist/project-linking-v2.js +2 -2
  70. package/node_modules/@ykdz/template-core/dist/project-projection.d.ts +2 -1
  71. package/node_modules/@ykdz/template-core/dist/project-projection.js +107 -20
  72. package/node_modules/@ykdz/template-core/dist/renderer.d.ts +0 -2
  73. package/node_modules/@ykdz/template-core/dist/renderer.js +17 -38
  74. package/node_modules/@ykdz/template-core/dist/template-boundary-check.d.ts +2 -2
  75. package/node_modules/@ykdz/template-core/dist/template-boundary-check.js +6 -0
  76. package/node_modules/@ykdz/template-core/dist/toolchain-resolution.d.ts +2 -0
  77. package/node_modules/@ykdz/template-core/dist/toolchain-resolution.js +9 -3
  78. package/package.json +5 -5
  79. package/node_modules/@ykdz/template-core/dist/project-blueprint-v2.d.ts +0 -33
  80. package/node_modules/@ykdz/template-core/dist/project-blueprint-v2.js +0 -182
@@ -11,70 +11,39 @@ export type PlaywrightBrowserAssetsEnvironmentNeed = {
11
11
  readonly kind: "playwright-browser-assets";
12
12
  readonly browser: "chromium";
13
13
  readonly owner: ComponentOwner;
14
- readonly nextStep: {
15
- readonly id: string;
16
- readonly label: string;
17
- readonly command: string;
18
- readonly args: readonly string[];
19
- readonly display: string;
20
- readonly machineVerifiable: boolean;
21
- };
22
14
  };
23
15
  export type ShellCheckEnvironmentNeed = {
24
16
  readonly kind: "shellcheck-command";
25
17
  readonly owner: ComponentOwner;
26
- readonly nextStep: {
27
- readonly id: "install-shellcheck";
28
- readonly label: "Install ShellCheck";
29
- readonly command: "sudo";
30
- readonly args: readonly string[];
31
- readonly display: "sudo apt-get update && sudo apt-get install -y shellcheck";
32
- readonly machineVerifiable: false;
33
- };
34
18
  };
35
19
  /** Rust task leaves require the maintained toolchain in local and CI plans. */
36
20
  export type RustToolchainEnvironmentNeed = {
37
21
  readonly kind: "rust-toolchain";
38
22
  readonly owner: ComponentOwner;
39
23
  readonly toolchain: "stable";
40
- readonly nextStep: {
41
- readonly id: "install-rust-toolchain";
42
- readonly label: "Install Rust toolchain";
43
- readonly command: "rustup";
44
- readonly args: readonly string[];
45
- readonly display: "rustup toolchain install stable --component rustfmt --component clippy";
46
- readonly machineVerifiable: boolean;
47
- };
48
24
  };
49
25
  /**
50
26
  * Docker is needed only by the focused deployment mode. It is deliberately
51
- * outside ordinary Check Environment Needs, whose preparation and next steps
52
- * apply to every generated-check scenario.
27
+ * outside ordinary Check Environment Needs, which apply to every
28
+ * generated-check scenario.
53
29
  */
54
30
  export type DockerEngineEnvironmentNeed = {
55
31
  readonly kind: "docker-engine";
56
- readonly preparation: {
57
- readonly id: "verify-docker-engine";
58
- readonly label: "Verify Docker engine";
59
- readonly command: "docker";
60
- readonly args: readonly ["version", "--format", "{{.Server.Version}}"];
61
- readonly display: "docker version --format {{.Server.Version}}";
62
- readonly machineVerifiable: true;
63
- };
64
32
  };
65
33
  export type CheckEnvironmentNeed = PlaywrightBrowserAssetsEnvironmentNeed | ShellCheckEnvironmentNeed | RustToolchainEnvironmentNeed;
66
34
  export type DeploymentEnvironmentNeed = DockerEngineEnvironmentNeed;
67
- /**
68
- * The durable form of a Check Environment Need. It deliberately retains only
69
- * the explicit preparation fact, never a task name or package execution list.
70
- */
71
- export type CheckEnvironmentNeedFact = Pick<PlaywrightBrowserAssetsEnvironmentNeed, "kind" | "browser" | "owner"> | Pick<ShellCheckEnvironmentNeed, "kind" | "owner"> | Pick<RustToolchainEnvironmentNeed, "kind" | "owner" | "toolchain">;
72
- /** Deployment preparation is likewise durable without selecting an executing package. */
73
- export type DeploymentEnvironmentNeedFact = Pick<DockerEngineEnvironmentNeed, "kind">;
74
- export declare function checkEnvironmentNeedFact(need: CheckEnvironmentNeed): CheckEnvironmentNeedFact;
75
- export declare function checkEnvironmentNeedFromFact(fact: CheckEnvironmentNeedFact): CheckEnvironmentNeed;
76
- export declare function deploymentEnvironmentNeedFact(need: DeploymentEnvironmentNeed): DeploymentEnvironmentNeedFact;
77
- export declare function deploymentEnvironmentNeedFromFact(fact: DeploymentEnvironmentNeedFact): DeploymentEnvironmentNeed;
35
+ export type EnvironmentNeedsMetadata = {
36
+ readonly schemaVersion: 1;
37
+ readonly check: readonly CheckEnvironmentNeed[];
38
+ readonly deployment: readonly DeploymentEnvironmentNeed[];
39
+ };
40
+ /** Validates, deduplicates, and canonically orders durable Environment Needs. */
41
+ export declare function normalizeEnvironmentNeeds(options: {
42
+ readonly check: readonly CheckEnvironmentNeed[];
43
+ readonly deployment: readonly DeploymentEnvironmentNeed[];
44
+ }): EnvironmentNeedsMetadata;
45
+ /** Strict codec for Local Template Metadata consumed by Package Addition. */
46
+ export declare function parseEnvironmentNeedsMetadata(value: unknown): EnvironmentNeedsMetadata;
78
47
  export declare function rustToolchainEnvironmentNeed(owner: ComponentOwner): RustToolchainEnvironmentNeed;
79
48
  export declare function dockerEngineEnvironmentNeed(): DockerEngineEnvironmentNeed;
80
49
  export declare const qualityTaskVocabulary: readonly ["boundaries", "format:check", "lint", "typecheck", "build", "test", "test:e2e"];
@@ -83,18 +52,11 @@ export declare function renderTurboRunCommand(taskNames: readonly string[], args
83
52
  readonly continueAfterFailure?: boolean;
84
53
  readonly taskPrefix?: boolean;
85
54
  }): string;
86
- export declare function renderRootCheckCommand(): string;
55
+ export declare function renderRootCheckCommand(additionalTasks?: readonly string[]): string;
87
56
  export declare function renderDeploymentCheckCommand(): string;
88
57
  export declare function renderFixCommand(): string;
89
- export declare function renderPlaywrightBrowserInstallCommand(need: CheckEnvironmentNeed, options?: {
90
- readonly withDeps?: boolean;
91
- }): string;
92
- export declare function playwrightBrowserAssetsNextStepDescriptor(owner: ComponentOwner): Pick<CheckEnvironmentNeed["nextStep"], "id" | "label">;
93
58
  export declare function playwrightBrowserAssetsEnvironmentNeed(options: {
94
59
  readonly browser: "chromium";
95
60
  readonly owner: ComponentOwner;
96
- readonly id?: string;
97
- readonly label?: string;
98
- readonly machineVerifiable?: boolean;
99
61
  }): PlaywrightBrowserAssetsEnvironmentNeed;
100
62
  export declare function shellCheckEnvironmentNeed(owner: ComponentOwner): ShellCheckEnvironmentNeed;
@@ -1,74 +1,156 @@
1
- export function checkEnvironmentNeedFact(need) {
2
- switch (need.kind) {
3
- case "playwright-browser-assets":
4
- return { kind: need.kind, browser: need.browser, owner: need.owner };
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
- return { kind: need.kind, owner: need.owner };
7
- case "rust-toolchain":
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: need.kind,
10
- owner: need.owner,
11
- toolchain: need.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
- export function checkEnvironmentNeedFromFact(fact) {
16
- switch (fact.kind) {
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 playwrightBrowserAssetsEnvironmentNeed({
19
- browser: fact.browser,
20
- owner: fact.owner,
21
- });
82
+ return `${checkEnvironmentNeedConflictKey(need)}:browser=${need.browser}`;
22
83
  case "shellcheck-command":
23
- return shellCheckEnvironmentNeed(fact.owner);
84
+ return checkEnvironmentNeedConflictKey(need);
24
85
  case "rust-toolchain":
25
- return rustToolchainEnvironmentNeed(fact.owner);
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
- export function deploymentEnvironmentNeedFact(need) {
29
- return { kind: need.kind };
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
- export function deploymentEnvironmentNeedFromFact(fact) {
32
- if (fact.kind !== "docker-engine") {
33
- throw new Error("Unsupported Deployment Environment Need fact.");
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 dockerEngineEnvironmentNeed();
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-v2.ts";
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.61.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.0
38
- hono: ^4.12.31
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.73.0
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.1
47
- tailwindcss: ^4.3.2
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.5
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.1.5
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.39
58
- vue-tsc: ^3.3.6
61
+ vue: ^3.5.40
62
+ vue-tsc: ^3.3.9
59
63
  yaml: ^2.9.0
60
64
 
61
65
  catalogs: