@ykdz/template 0.0.24 → 0.0.26

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 (51) hide show
  1. package/node_modules/@ykdz/template-builtin-presets/dist/src/foundation.d.ts +3 -5
  2. package/node_modules/@ykdz/template-builtin-presets/dist/src/foundation.js +172 -165
  3. package/node_modules/@ykdz/template-builtin-presets/dist/src/rust-bin/definition.js +4 -24
  4. package/node_modules/@ykdz/template-builtin-presets/dist/src/shared/vue.d.ts +0 -3
  5. package/node_modules/@ykdz/template-builtin-presets/dist/src/shared/vue.js +8 -26
  6. package/node_modules/@ykdz/template-builtin-presets/dist/src/ts-lib/definition.js +5 -29
  7. package/node_modules/@ykdz/template-builtin-presets/dist/src/vike-app/definition.js +24 -50
  8. package/node_modules/@ykdz/template-builtin-presets/dist/src/vue-app/definition.js +2 -4
  9. package/node_modules/@ykdz/template-builtin-presets/dist/src/vue-hono-app/definition.js +9 -26
  10. package/node_modules/@ykdz/template-builtin-presets/package.json +2 -1
  11. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/.github/workflows/check-playwright.yml +1 -1
  12. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/.github/workflows/check-rust.yml +1 -1
  13. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/.github/workflows/check.dynamic.template +1 -1
  14. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/.github/workflows/check.yml +1 -1
  15. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/pnpm-workspace.dynamic.txt +1 -5
  16. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/pnpm-workspace.yaml +2 -3
  17. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/scripts/check-boundaries.ts +12 -0
  18. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/scripts/run-root-owned-task.ts +69 -0
  19. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/tsconfig.json +6 -1
  20. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/turbo.json +15 -8
  21. package/node_modules/@ykdz/template-builtin-presets/templates/rust-bin/.github/workflows/check.yml +1 -1
  22. package/node_modules/@ykdz/template-builtin-presets/templates/rust-bin/Cargo.lock +2 -2
  23. package/node_modules/@ykdz/template-builtin-presets/templates/rust-bin/Cargo.toml +1 -1
  24. package/node_modules/@ykdz/template-builtin-presets/templates/shared/devcontainer/node-pnpm.Dockerfile +5 -2
  25. package/node_modules/@ykdz/template-builtin-presets/templates/ts-lib/.github/workflows/check.yml +1 -1
  26. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/db/turbo.json +1 -1
  27. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/db-migrations/turbo.json +2 -2
  28. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/web/Dockerfile +5 -6
  29. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/web/scripts/check-standalone-deployment.ts +1 -1
  30. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/web/tsconfig.json +1 -1
  31. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/web/turbo.json +3 -3
  32. package/node_modules/@ykdz/template-builtin-presets/templates/vue-app/.github/workflows/check.yml +1 -1
  33. package/node_modules/@ykdz/template-builtin-presets/templates/vue-app/turbo.json +3 -3
  34. package/node_modules/@ykdz/template-builtin-presets/templates/vue-hono-app/api/turbo.json +1 -1
  35. package/node_modules/@ykdz/template-builtin-presets/templates/vue-hono-app/web/playwright.config.ts +1 -1
  36. package/node_modules/@ykdz/template-builtin-presets/templates/vue-hono-app/web/turbo.json +2 -2
  37. package/node_modules/@ykdz/template-core/dist/Cargo.lock +2 -2
  38. package/node_modules/@ykdz/template-core/dist/Cargo.toml +1 -1
  39. package/node_modules/@ykdz/template-core/dist/dependency-catalog.d.ts +0 -1
  40. package/node_modules/@ykdz/template-core/dist/dependency-catalog.js +2 -8
  41. package/node_modules/@ykdz/template-core/dist/module-graph.d.ts +39 -37
  42. package/node_modules/@ykdz/template-core/dist/module-graph.js +84 -142
  43. package/node_modules/@ykdz/template-core/dist/package-contribution.d.ts +3 -5
  44. package/node_modules/@ykdz/template-core/dist/package-contribution.js +7 -7
  45. package/node_modules/@ykdz/template-core/dist/pnpm-workspace.yaml +5 -7
  46. package/node_modules/@ykdz/template-core/dist/project-github.d.ts +11 -3
  47. package/node_modules/@ykdz/template-core/dist/project-github.js +31 -36
  48. package/node_modules/@ykdz/template-core/dist/project-linking-v2.d.ts +1 -1
  49. package/node_modules/@ykdz/template-core/dist/renderer.js +38 -21
  50. package/package.json +1 -1
  51. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/.pnpmfile.cts +0 -14
@@ -1,4 +1,4 @@
1
- import type { CheckComponent, CheckEnvironmentNeed, DeploymentCheckComponent, FixComponent } from "@ykdz/template-core/module-graph";
1
+ import type { CheckEnvironmentNeed, DeploymentEnvironmentNeed } from "@ykdz/template-core/module-graph";
2
2
  import { type PackageContribution } from "@ykdz/template-core/package-contribution";
3
3
  import type { BuiltInPresetDefinition, GenerationContext } from "@ykdz/template-core/preset-definition";
4
4
  import { type ProjectBlueprintV2 } from "@ykdz/template-core/project-blueprint-v2";
@@ -23,10 +23,8 @@ export type GeneratedRepositoryPlan = {
23
23
  readonly toolchain: BuiltInGenerationContext["toolchain"];
24
24
  };
25
25
  readonly operations: readonly RenderOperation[];
26
- readonly checks: readonly CheckComponent[];
27
- readonly fixes: readonly FixComponent[];
28
26
  readonly environmentNeeds: readonly CheckEnvironmentNeed[];
29
- readonly deploymentChecks: readonly DeploymentCheckComponent[];
27
+ readonly deploymentEnvironmentNeeds: readonly DeploymentEnvironmentNeed[];
30
28
  /** Structured manifests used to derive the generated Dependency Catalog. */
31
29
  readonly manifests: readonly Readonly<Record<string, unknown>>[];
32
30
  readonly dependencyCatalog: Readonly<Record<string, string>>;
@@ -42,7 +40,7 @@ export type BuiltInPresetTemplateSourceCheckContext = {
42
40
  /**
43
41
  * The Foundation persists the non-rendering half of every Package
44
42
  * Contribution with the Generated Repository. Package Addition cannot infer
45
- * check, fix, deployment, or maintenance semantics from a package name (or
43
+ * fix, deployment, or maintenance semantics from a package name (or
46
44
  * from a lossy subset of scripts), so this is the durable topology it reads.
47
45
  */
48
46
  /** Resolve an owned source handle for diagnostics and source checks. */
@@ -4,7 +4,7 @@ import { fileURLToPath } from "node:url";
4
4
  import { collectGeneratedManifestCatalogReferences, selectTemplateDependencyCatalogEntries, } from "@ykdz/template-core/dependency-catalog";
5
5
  import { browserTestToolLayer } from "@ykdz/template-core/devcontainer";
6
6
  import { editorCustomizationForCapabilities, loadEditorCustomizationDeclarations, } from "@ykdz/template-core/editor-customization";
7
- import { checkComponentTaskName, fixComponentTaskName, playwrightBrowserAssetsEnvironmentNeed, renderTurboRunCommand, rustToolchainEnvironmentNeed, shellCheckEnvironmentNeed, } from "@ykdz/template-core/module-graph";
7
+ import { checkEnvironmentNeedFact, checkEnvironmentNeedFromFact, deploymentEnvironmentNeedFact, deploymentEnvironmentNeedFromFact, renderDeploymentCheckCommand, renderFixCommand, renderRootCheckCommand, } from "@ykdz/template-core/module-graph";
8
8
  import { assertPackageContribution, } from "@ykdz/template-core/package-contribution";
9
9
  import { assertProjectBlueprintV2, validateProjectBlueprintV2 as validateCoreProjectBlueprintV2, } from "@ykdz/template-core/project-blueprint-v2";
10
10
  import { projectCheckWorkflowTemplateReplacements, projectDependabotTemplateReplacements, } from "@ykdz/template-core/project-github";
@@ -17,10 +17,11 @@ import { tsLibDefinition } from "./ts-lib/definition.js";
17
17
  import { vikeAppDefinition } from "./vike-app/definition.js";
18
18
  import { vueAppDefinition } from "./vue-app/definition.js";
19
19
  import { vueHonoAppDefinition } from "./vue-hono-app/definition.js";
20
+ const environmentNeedsPath = ".template/environment-needs.json";
20
21
  /**
21
22
  * The Foundation persists the non-rendering half of every Package
22
23
  * Contribution with the Generated Repository. Package Addition cannot infer
23
- * check, fix, deployment, or maintenance semantics from a package name (or
24
+ * fix, deployment, or maintenance semantics from a package name (or
24
25
  * from a lossy subset of scripts), so this is the durable topology it reads.
25
26
  */
26
27
  /** Resolve an owned source handle for diagnostics and source checks. */
@@ -110,10 +111,85 @@ export function createGenerationContext(options) {
110
111
  toolchain: options.toolchain,
111
112
  };
112
113
  }
114
+ function isRecord(value) {
115
+ return typeof value === "object" && value !== null && !Array.isArray(value);
116
+ }
117
+ function environmentNeedOwner(value) {
118
+ if (!isRecord(value))
119
+ return undefined;
120
+ if (value.kind === "workspace-orchestration" && value.path === ".") {
121
+ return { kind: "workspace-orchestration", path: "." };
122
+ }
123
+ if (value.kind === "package-boundary" && typeof value.path === "string") {
124
+ return { kind: "package-boundary", path: value.path };
125
+ }
126
+ return undefined;
127
+ }
128
+ function persistedCheckEnvironmentNeedFact(value) {
129
+ if (!isRecord(value))
130
+ return undefined;
131
+ const owner = environmentNeedOwner(value.owner);
132
+ if (owner === undefined)
133
+ return undefined;
134
+ switch (value.kind) {
135
+ case "playwright-browser-assets":
136
+ return value.browser === "chromium"
137
+ ? { kind: value.kind, browser: value.browser, owner }
138
+ : undefined;
139
+ case "shellcheck-command":
140
+ return { kind: value.kind, owner };
141
+ case "rust-toolchain":
142
+ return value.toolchain === "stable"
143
+ ? { kind: value.kind, toolchain: value.toolchain, owner }
144
+ : undefined;
145
+ default:
146
+ return undefined;
147
+ }
148
+ }
149
+ function readPersistedEnvironmentNeeds(targetDir) {
150
+ const filePath = path.join(targetDir, environmentNeedsPath);
151
+ if (!existsSync(filePath)) {
152
+ throw new Error(`Package Addition requires explicit Check Environment Need facts: ${environmentNeedsPath} is missing`);
153
+ }
154
+ let value;
155
+ try {
156
+ value = JSON.parse(readFileSync(filePath, "utf8"));
157
+ }
158
+ catch (error) {
159
+ throw new Error(`Package Addition requires valid Check Environment Need facts: ${error instanceof Error ? error.message : String(error)}`);
160
+ }
161
+ if (!isRecord(value) ||
162
+ value.schemaVersion !== 1 ||
163
+ !Array.isArray(value.check) ||
164
+ !Array.isArray(value.deployment)) {
165
+ throw new Error(`Package Addition requires valid Check Environment Need facts in ${environmentNeedsPath}`);
166
+ }
167
+ const check = value.check.map(persistedCheckEnvironmentNeedFact);
168
+ if (check.some((fact) => fact === undefined)) {
169
+ throw new Error(`Package Addition requires supported Check Environment Need facts in ${environmentNeedsPath}`);
170
+ }
171
+ if (value.deployment.some((fact) => !isRecord(fact) || fact.kind !== "docker-engine")) {
172
+ throw new Error(`Package Addition requires supported deployment Environment Need facts in ${environmentNeedsPath}`);
173
+ }
174
+ return {
175
+ check: check.map(checkEnvironmentNeedFromFact),
176
+ deployment: value.deployment.map((fact) => deploymentEnvironmentNeedFromFact(fact)),
177
+ };
178
+ }
179
+ function uniqueEnvironmentNeeds(needs) {
180
+ const seen = new Set();
181
+ return needs.filter((need) => {
182
+ const key = JSON.stringify(need);
183
+ if (seen.has(key))
184
+ return false;
185
+ seen.add(key);
186
+ return true;
187
+ });
188
+ }
113
189
  /**
114
- * Package Addition reconstructs generic current facts from the Blueprint
115
- * topology and each package's real manifest/configuration. A second durable
116
- * Contribution database would drift from the generated repository.
190
+ * Package Addition reconstructs generic current facts from the Blueprint,
191
+ * manifest truth, and explicit persisted Environment Need facts. Environment
192
+ * preparation is never derived from task script text.
117
193
  */
118
194
  function existingPackageContribution(options) {
119
195
  const packageRoot = path.join(options.context.targetDir, options.definition.path);
@@ -129,15 +205,10 @@ function existingPackageContribution(options) {
129
205
  throw new Error(`Package Addition requires manifest truth for ${options.definition.path}: expected name ${options.definition.name}`);
130
206
  }
131
207
  const record = manifest;
132
- const scripts = typeof record.scripts === "object" && record.scripts !== null
133
- ? record.scripts
134
- : {};
135
- const owner = {
136
- kind: "package-boundary",
137
- path: options.definition.path,
138
- };
139
208
  const dependencyMaintenance = existingDependencyMaintenancePolicy(options.context.targetDir);
140
- const rust = existsSync(path.join(packageRoot, "Cargo.toml"));
209
+ const environmentNeeds = options.environmentNeeds.filter((need) => need.owner.kind === "package-boundary" &&
210
+ need.owner.path === options.definition.path);
211
+ const rust = environmentNeeds.some((need) => need.kind === "rust-toolchain");
141
212
  const editorRecommendationsPath = path.join(options.context.targetDir, ".vscode/extensions.json");
142
213
  const editorRecommendations = existsSync(editorRecommendationsPath)
143
214
  ? JSON.parse(readFileSync(editorRecommendationsPath, "utf8")).recommendations
@@ -157,32 +228,6 @@ function existingPackageContribution(options) {
157
228
  ? ["vitest"]
158
229
  : []),
159
230
  ];
160
- const checks = rust
161
- ? [
162
- { kind: "rustfmt-check", owner },
163
- { kind: "cargo-clippy", owner },
164
- { kind: "cargo-test", owner },
165
- ]
166
- : [
167
- ...(scripts["typecheck:run"] === undefined
168
- ? []
169
- : [{ kind: "typescript-typecheck", owner }]),
170
- ...(scripts["lint:run"] === undefined
171
- ? []
172
- : [{ kind: "oxc-lint", owner }]),
173
- ...(scripts["format:check:run"] === undefined
174
- ? []
175
- : [{ kind: "oxc-format-check", owner }]),
176
- ...(scripts["build:run"] === undefined
177
- ? []
178
- : [{ kind: "build", owner }]),
179
- ...(scripts["test:run"] === undefined
180
- ? []
181
- : [{ kind: "unit-test", owner }]),
182
- ...(scripts["test:e2e:run"] === undefined
183
- ? []
184
- : [{ kind: "e2e-test", owner }]),
185
- ];
186
231
  return {
187
232
  definition: options.definition,
188
233
  manifest: record,
@@ -195,34 +240,7 @@ function existingPackageContribution(options) {
195
240
  : {},
196
241
  },
197
242
  operations: [],
198
- checks,
199
- fixes: rust
200
- ? [{ kind: "rustfmt-write", owner }]
201
- : [
202
- ...(scripts["format:write:run"] === undefined
203
- ? []
204
- : [{ kind: "oxc-format-write", owner }]),
205
- ...(scripts["lint:fix:run"] === undefined
206
- ? []
207
- : [{ kind: "oxc-lint-fix", owner }]),
208
- ],
209
- environmentNeeds: [
210
- ...(rust ? [rustToolchainEnvironmentNeed(owner)] : []),
211
- ...(scripts["test:e2e:run"] === undefined
212
- ? []
213
- : [
214
- playwrightBrowserAssetsEnvironmentNeed({
215
- browser: "chromium",
216
- owner,
217
- }),
218
- ]),
219
- ...(Object.values(scripts).some((script) => typeof script === "string" && script.includes("shellcheck"))
220
- ? [shellCheckEnvironmentNeed(owner)]
221
- : []),
222
- ],
223
- ...(scripts["check:deployment"] === undefined
224
- ? {}
225
- : { deploymentChecks: [{ kind: "deployment-image", owner }] }),
243
+ environmentNeeds,
226
244
  foundation: {
227
245
  toolchains: rust
228
246
  ? { rust: { toolchain: "stable", components: ["rustfmt", "clippy"] } }
@@ -287,38 +305,6 @@ function existingDependencyMaintenancePolicy(targetDir) {
287
305
  interval: "weekly",
288
306
  };
289
307
  }
290
- function unique(values) {
291
- return [...new Set(values)];
292
- }
293
- function rootCheckCommand(checks) {
294
- const rootTasks = unique(checks
295
- .filter((check) => check.owner.kind === "workspace-orchestration")
296
- .map(checkComponentTaskName));
297
- const packageChecks = checks.filter((check) => check.owner.kind === "package-boundary");
298
- const packageTasks = unique(packageChecks.map(checkComponentTaskName));
299
- const packageFilters = unique(packageChecks.map((check) => `--filter './${check.owner.path}'`));
300
- return [
301
- "pnpm run check:boundaries",
302
- ...rootTasks.map((task) => `pnpm run ${task}`),
303
- ...(packageTasks.length === 0
304
- ? []
305
- : [renderTurboRunCommand(packageTasks, packageFilters)]),
306
- ].join(" && ");
307
- }
308
- function rootFixCommand(fixes) {
309
- const rootTasks = unique(fixes
310
- .filter((fix) => fix.owner.kind === "workspace-orchestration")
311
- .map(fixComponentTaskName));
312
- const packageFixes = fixes.filter((fix) => fix.owner.kind === "package-boundary");
313
- const packageTasks = unique(packageFixes.map(fixComponentTaskName));
314
- const packageFilters = unique(packageFixes.map((fix) => `--filter './${fix.owner.path}'`));
315
- return [
316
- ...rootTasks.map((task) => `pnpm run ${task}`),
317
- ...(packageTasks.length === 0
318
- ? []
319
- : [renderTurboRunCommand(packageTasks, packageFilters)]),
320
- ].join(" && ");
321
- }
322
308
  function devcontainerDockerfileOperations(options) {
323
309
  const hasBrowserTests = options.environmentNeeds.some((need) => need.kind === "playwright-browser-assets");
324
310
  const hasShellChecks = options.environmentNeeds.some((need) => need.kind === "shellcheck-command");
@@ -366,40 +352,22 @@ function devcontainerDockerfileOperations(options) {
366
352
  }
367
353
  function foundationPlan(options) {
368
354
  assertProjectBlueprintV2(options.blueprint);
369
- const foundationChecks = [
370
- {
371
- kind: "oxc-format-check",
372
- owner: { kind: "workspace-orchestration", path: "." },
373
- },
374
- {
375
- kind: "oxc-lint",
376
- owner: { kind: "workspace-orchestration", path: "." },
377
- },
378
- {
379
- kind: "typescript-typecheck",
380
- owner: { kind: "workspace-orchestration", path: "." },
381
- },
382
- ];
383
- const foundationFixes = [
384
- {
385
- kind: "oxc-format-write",
386
- owner: { kind: "workspace-orchestration", path: "." },
387
- },
388
- {
389
- kind: "oxc-lint-fix",
390
- owner: { kind: "workspace-orchestration", path: "." },
391
- },
392
- ];
393
- const checks = [
394
- ...foundationChecks,
395
- ...options.contributions.flatMap((item) => item.checks),
396
- ];
397
- const fixes = [
398
- ...foundationFixes,
399
- ...options.contributions.flatMap((item) => item.fixes),
400
- ];
401
- const environmentNeeds = options.contributions.flatMap((item) => item.environmentNeeds);
402
- const deploymentChecks = options.contributions.flatMap((item) => item.deploymentChecks ?? []);
355
+ const environmentNeeds = uniqueEnvironmentNeeds(options.contributions.flatMap((item) => item.environmentNeeds));
356
+ const deploymentEnvironmentNeeds = uniqueEnvironmentNeeds([
357
+ ...(options.existingDeploymentEnvironmentNeeds ?? []),
358
+ ...options.contributions.flatMap((item) => item.deploymentEnvironmentNeeds ?? []),
359
+ ]);
360
+ const persistedEnvironmentNeeds = {
361
+ schemaVersion: 1,
362
+ check: environmentNeeds.map(checkEnvironmentNeedFact),
363
+ deployment: deploymentEnvironmentNeeds.map(deploymentEnvironmentNeedFact),
364
+ };
365
+ const hasDeploymentTask = options.contributions.some((contribution) => {
366
+ const scripts = contribution.manifest.scripts;
367
+ return (typeof scripts === "object" &&
368
+ scripts !== null &&
369
+ typeof scripts.deployment === "string");
370
+ });
403
371
  const packagePaths = options.contributions.map((contribution) => contribution.definition.path);
404
372
  if (new Set(packagePaths).size !== packagePaths.length)
405
373
  throw new Error("Package Contributions must have unique Package Paths");
@@ -414,9 +382,15 @@ function foundationPlan(options) {
414
382
  throw new Error("Foundation requires one coordinated Rust toolchain");
415
383
  }
416
384
  const workspacePackageGlobs = [
385
+ "apps/*",
386
+ "packages/*",
417
387
  ...new Set([
418
- ...options.blueprint.packages.map((definition) => `${definition.path.split("/")[0]}/*`),
419
- ...options.contributions.flatMap((contribution) => contribution.foundation.workspacePackageGlobs ?? []),
388
+ ...options.blueprint.packages
389
+ .map((definition) => `${definition.path.split("/")[0]}/*`)
390
+ .filter((glob) => glob !== "apps/*" && glob !== "packages/*"),
391
+ ...options.contributions
392
+ .flatMap((contribution) => contribution.foundation.workspacePackageGlobs ?? [])
393
+ .filter((glob) => glob !== "apps/*" && glob !== "packages/*"),
420
394
  ]),
421
395
  ];
422
396
  const editorCustomization = editorCustomizationForCapabilities(options.contributions.flatMap((contribution) => contribution.foundation.editorCapabilities), loadEditorCustomizationDeclarations(resolveTemplateSource(templateSources.editorCustomization, "capabilities.json")));
@@ -434,22 +408,17 @@ function foundationPlan(options) {
434
408
  private: true,
435
409
  type: "module",
436
410
  scripts: {
437
- check: rootCheckCommand(checks),
438
- "check:boundaries": "turbo boundaries --no-color",
439
- ...(deploymentChecks.length === 0
440
- ? {}
441
- : {
442
- "check:deployment": deploymentChecks
443
- .map((check) => `pnpm --filter './${check.owner.path}' run check:deployment`)
444
- .join(" && "),
445
- }),
446
- fix: rootFixCommand(fixes),
447
- "format:check:run": "oxfmt --list-different --config oxfmt.config.ts .",
448
- "format:write:run": "oxfmt --write --config oxfmt.config.ts .",
449
- "lint:run": "oxlint --quiet --format=unix --config oxlint.config.ts .",
450
- "lint:fix:run": "oxlint --format=unix --config oxlint.config.ts . --fix",
451
- typecheck: "pnpm run typecheck:run",
452
- "typecheck:run": "tsc -p tsconfig.json --noEmit --pretty false",
411
+ check: renderRootCheckCommand(),
412
+ boundaries: "node scripts/check-boundaries.ts",
413
+ ...(hasDeploymentTask
414
+ ? { "check:deployment": renderDeploymentCheckCommand() }
415
+ : {}),
416
+ fix: renderFixCommand(),
417
+ "format:check": "node scripts/run-root-owned-task.ts format:check",
418
+ "format:write": "node scripts/run-root-owned-task.ts format:write",
419
+ lint: "node scripts/run-root-owned-task.ts lint",
420
+ "lint:fix": "node scripts/run-root-owned-task.ts lint:fix",
421
+ typecheck: "tsc -p tsconfig.json --noEmit --pretty false",
453
422
  },
454
423
  devDependencies: {
455
424
  "@types/node": "catalog:",
@@ -467,7 +436,6 @@ function foundationPlan(options) {
467
436
  rootManifest,
468
437
  ]));
469
438
  const dependencyOverrides = {
470
- "valibot>typescript": "-",
471
439
  ...(Object.hasOwn(dependencyCatalog, "vue") ||
472
440
  Object.hasOwn(dependencyCatalog, "pinia")
473
441
  ? vuePnpmDependencyOverrides
@@ -488,10 +456,16 @@ function foundationPlan(options) {
488
456
  .toSorted(([left], [right]) => left.localeCompare(right))
489
457
  .map(([name, version]) => ` ${JSON.stringify(name)}: ${String(version)}`)
490
458
  .join("\n"),
491
- DEPENDENCY_OVERRIDES: Object.entries(dependencyOverrides)
492
- .toSorted(([left], [right]) => left.localeCompare(right))
493
- .map(([dependency, version]) => ` ${JSON.stringify(dependency)}: ${JSON.stringify(version)}`)
494
- .join("\n"),
459
+ DEPENDENCY_OVERRIDES_SECTION: Object.keys(dependencyOverrides).length === 0
460
+ ? ""
461
+ : [
462
+ "",
463
+ "overrides:",
464
+ ...Object.entries(dependencyOverrides)
465
+ .toSorted(([left], [right]) => left.localeCompare(right))
466
+ .map(([dependency, version]) => ` ${JSON.stringify(dependency)}: ${JSON.stringify(version)}`),
467
+ "",
468
+ ].join("\n"),
495
469
  },
496
470
  ...(options.mode === "addition" ? { overwrite: true } : {}),
497
471
  }
@@ -507,7 +481,9 @@ function foundationPlan(options) {
507
481
  from: ".github/workflows/check.dynamic.template",
508
482
  to: ".github/workflows/check.yml",
509
483
  replacements: projectCheckWorkflowTemplateReplacements({
510
- checkPlan: { components: checks, environmentNeeds, deploymentChecks },
484
+ environment: { needs: environmentNeeds },
485
+ deploymentEnvironmentNeeds,
486
+ hasDeploymentTask,
511
487
  }),
512
488
  ...(options.mode === "addition" ? { overwrite: true } : {}),
513
489
  };
@@ -538,14 +514,20 @@ function foundationPlan(options) {
538
514
  {
539
515
  kind: "copyFile",
540
516
  source: templateSources.foundation,
541
- from: ".pnpmfile.cts",
542
- to: ".pnpmfile.cts",
517
+ from: "turbo.json",
518
+ to: "turbo.json",
543
519
  },
544
520
  {
545
521
  kind: "copyFile",
546
522
  source: templateSources.foundation,
547
- from: "turbo.json",
548
- to: "turbo.json",
523
+ from: "scripts/check-boundaries.ts",
524
+ to: "scripts/check-boundaries.ts",
525
+ },
526
+ {
527
+ kind: "copyFile",
528
+ source: templateSources.foundation,
529
+ from: "scripts/run-root-owned-task.ts",
530
+ to: "scripts/run-root-owned-task.ts",
549
531
  },
550
532
  {
551
533
  kind: "copyFile",
@@ -623,6 +605,22 @@ function foundationPlan(options) {
623
605
  source: templateSources.foundation,
624
606
  from: "rust/devcontainer/rust.Dockerfile",
625
607
  },
608
+ ...(environmentNeeds.some((need) => need.kind === "playwright-browser-assets")
609
+ ? [
610
+ {
611
+ source: templateSources.sharedDevcontainer,
612
+ from: "browser-test.Dockerfile",
613
+ },
614
+ ]
615
+ : []),
616
+ ...(environmentNeeds.some((need) => need.kind === "shellcheck-command")
617
+ ? [
618
+ {
619
+ source: templateSources.sharedDevcontainer,
620
+ from: "shellcheck.Dockerfile",
621
+ },
622
+ ]
623
+ : []),
626
624
  ],
627
625
  },
628
626
  ]),
@@ -632,6 +630,11 @@ function foundationPlan(options) {
632
630
  to: ".template/blueprint.json",
633
631
  value: options.blueprint,
634
632
  },
633
+ {
634
+ kind: "writeJson",
635
+ to: environmentNeedsPath,
636
+ value: persistedEnvironmentNeeds,
637
+ },
635
638
  {
636
639
  kind: "writeJson",
637
640
  to: ".template/generation.json",
@@ -714,10 +717,8 @@ function foundationPlan(options) {
714
717
  toolchain: options.context.toolchain,
715
718
  },
716
719
  operations,
717
- checks,
718
- fixes,
719
720
  environmentNeeds,
720
- deploymentChecks,
721
+ deploymentEnvironmentNeeds,
721
722
  manifests: [
722
723
  ...options.contributions.map((item) => item.manifest),
723
724
  rootManifest,
@@ -780,7 +781,12 @@ export function planGeneratedRepositoryPackageAddition(options) {
780
781
  : {}),
781
782
  };
782
783
  assertProjectBlueprintV2(blueprint);
783
- const existingContributions = options.blueprint.packages.map((definition) => existingPackageContribution({ context: options.context, definition }));
784
+ const persistedEnvironmentNeeds = readPersistedEnvironmentNeeds(options.context.targetDir);
785
+ const existingContributions = options.blueprint.packages.map((definition) => existingPackageContribution({
786
+ context: options.context,
787
+ definition,
788
+ environmentNeeds: persistedEnvironmentNeeds.check,
789
+ }));
784
790
  if (existingContributions.length !== options.blueprint.packages.length ||
785
791
  existingContributions.some((existing) => !options.blueprint.packages.some((definition) => definition.path === existing.definition.path &&
786
792
  definition.name === existing.definition.name))) {
@@ -792,6 +798,7 @@ export function planGeneratedRepositoryPackageAddition(options) {
792
798
  blueprint,
793
799
  contributions: [...existingContributions, contribution],
794
800
  renderContributions: [contribution],
801
+ existingDeploymentEnvironmentNeeds: persistedEnvironmentNeeds.deployment,
795
802
  mode: "addition",
796
803
  });
797
804
  }
@@ -12,10 +12,10 @@ function cargoPackageName(projectName) {
12
12
  }
13
13
  function packageScripts() {
14
14
  return {
15
- "format:check:run": "cargo fmt --all -- --check",
16
- "format:write:run": "cargo fmt --all",
17
- "lint:run": "cargo clippy --workspace --all-targets -- -D warnings",
18
- "test:run": "cargo test --workspace",
15
+ "format:check": "cargo fmt --all -- --check",
16
+ "format:write": "cargo fmt --all",
17
+ lint: "cargo clippy --workspace --all-targets -- -D warnings",
18
+ test: "cargo test --workspace",
19
19
  };
20
20
  }
21
21
  function rustContribution(context) {
@@ -71,26 +71,6 @@ function rustContribution(context) {
71
71
  engines: { node: context.toolchain.nodeLtsMajor },
72
72
  },
73
73
  operations,
74
- checks: [
75
- {
76
- kind: "rustfmt-check",
77
- owner: { kind: "package-boundary", path: definition.path },
78
- },
79
- {
80
- kind: "cargo-clippy",
81
- owner: { kind: "package-boundary", path: definition.path },
82
- },
83
- {
84
- kind: "cargo-test",
85
- owner: { kind: "package-boundary", path: definition.path },
86
- },
87
- ],
88
- fixes: [
89
- {
90
- kind: "rustfmt-write",
91
- owner: { kind: "package-boundary", path: definition.path },
92
- },
93
- ],
94
74
  environmentNeeds: [
95
75
  rustToolchainEnvironmentNeed({
96
76
  kind: "package-boundary",
@@ -1,4 +1,3 @@
1
- import { type CheckComponent, type FixComponent } from "@ykdz/template-core/module-graph";
2
1
  import type { PackageContribution } from "@ykdz/template-core/package-contribution";
3
2
  import type { GenerationContext } from "@ykdz/template-core/preset-definition";
4
3
  import type { PackageDefinition } from "@ykdz/template-core/project-blueprint-v2";
@@ -26,8 +25,6 @@ export declare function vueApplicationScripts(): Record<string, string>;
26
25
  export declare function sharedVueSourceOperations(packagePath: string): readonly RenderOperation[];
27
26
  /** Vike shares Vue's compiler runner, but owns its distinct Vike source tree. */
28
27
  export declare function vueTypecheckRunnerSourceOperation(packagePath: string): RenderOperation;
29
- export declare function vueApplicationChecks(packagePath: string): readonly CheckComponent[];
30
- export declare function vueApplicationFixes(packagePath: string): readonly FixComponent[];
31
28
  export declare function vueApplicationEnvironmentNeeds(packagePath: string): import("@ykdz/template-core/module-graph").PlaywrightBrowserAssetsEnvironmentNeed[];
32
29
  export declare function vueApplicationManifest(options: {
33
30
  readonly context: GenerationContext;
@@ -1,4 +1,4 @@
1
- import { playwrightBrowserAssetsEnvironmentNeed, } from "@ykdz/template-core/module-graph";
1
+ import { playwrightBrowserAssetsEnvironmentNeed } from "@ykdz/template-core/module-graph";
2
2
  import { templateSources } from "../template-sources.js";
3
3
  /** Vue's tooling peers need these repository policy overrides, never Core defaults. */
4
4
  export const vuePnpmDependencyOverrides = {
@@ -22,15 +22,15 @@ const sharedVueSourceFiles = [
22
22
  ];
23
23
  export function vueApplicationScripts() {
24
24
  return {
25
- "build:run": "vite build",
25
+ build: "vite build",
26
26
  dev: "vite",
27
- "format:check:run": "oxfmt --list-different --config ../../oxfmt.config.ts .",
28
- "format:write:run": "oxfmt --write --config ../../oxfmt.config.ts .",
29
- "lint:run": "oxlint --quiet --format=unix --config ../../oxlint.config.ts .",
30
- "lint:fix:run": "oxlint --format=unix --config ../../oxlint.config.ts . --fix",
27
+ "format:check": "oxfmt --list-different --config ../../oxfmt.config.ts .",
28
+ "format:write": "oxfmt --write --config ../../oxfmt.config.ts .",
29
+ lint: "oxlint --quiet --format=unix --config ../../oxlint.config.ts .",
30
+ "lint:fix": "oxlint --format=unix --config ../../oxlint.config.ts . --fix",
31
31
  preview: "vite preview",
32
- "test:run": "vitest run --reporter=agent --silent=passed-only",
33
- "test:e2e:run": "node scripts/run-playwright.ts",
32
+ test: "vitest run --reporter=agent --silent=passed-only",
33
+ "test:e2e": "node scripts/run-playwright.ts",
34
34
  };
35
35
  }
36
36
  export function sharedVueSourceOperations(packagePath) {
@@ -50,24 +50,6 @@ export function vueTypecheckRunnerSourceOperation(packagePath) {
50
50
  to: `${packagePath}/scripts/run-vue-tsc.ts`,
51
51
  };
52
52
  }
53
- export function vueApplicationChecks(packagePath) {
54
- const owner = { kind: "package-boundary", path: packagePath };
55
- return [
56
- { kind: "typescript-typecheck", owner },
57
- { kind: "oxc-lint", owner },
58
- { kind: "oxc-format-check", owner },
59
- { kind: "build", owner },
60
- { kind: "unit-test", owner },
61
- { kind: "e2e-test", owner },
62
- ];
63
- }
64
- export function vueApplicationFixes(packagePath) {
65
- const owner = { kind: "package-boundary", path: packagePath };
66
- return [
67
- { kind: "oxc-format-write", owner },
68
- { kind: "oxc-lint-fix", owner },
69
- ];
70
- }
71
53
  export function vueApplicationEnvironmentNeeds(packagePath) {
72
54
  return [
73
55
  playwrightBrowserAssetsEnvironmentNeed({
@@ -2,11 +2,11 @@ import { fileURLToPath } from "node:url";
2
2
  import { templateSources } from "../template-sources.js";
3
3
  function packageScripts() {
4
4
  return {
5
- "format:check:run": "oxfmt --list-different --config ../../oxfmt.config.ts .",
6
- "format:write:run": "oxfmt --write --config ../../oxfmt.config.ts .",
7
- "lint:run": "oxlint --quiet --format=unix --config ../../oxlint.config.ts --ignore-pattern node_modules .",
8
- "lint:fix:run": "oxlint --format=unix --config ../../oxlint.config.ts . --fix",
9
- "typecheck:run": "tsc -p tsconfig.json --noEmit --pretty false",
5
+ "format:check": "oxfmt --list-different --config ../../oxfmt.config.ts .",
6
+ "format:write": "oxfmt --write --config ../../oxfmt.config.ts .",
7
+ lint: "oxlint --quiet --format=unix --config ../../oxlint.config.ts --ignore-pattern node_modules .",
8
+ "lint:fix": "oxlint --format=unix --config ../../oxlint.config.ts . --fix",
9
+ typecheck: "tsc -p tsconfig.json --noEmit --pretty false",
10
10
  };
11
11
  }
12
12
  function libraryContribution(options) {
@@ -67,30 +67,6 @@ function libraryContribution(options) {
67
67
  scripts: packageScripts(),
68
68
  },
69
69
  operations,
70
- checks: [
71
- {
72
- kind: "typescript-typecheck",
73
- owner: { kind: "package-boundary", path: definition.path },
74
- },
75
- {
76
- kind: "oxc-lint",
77
- owner: { kind: "package-boundary", path: definition.path },
78
- },
79
- {
80
- kind: "oxc-format-check",
81
- owner: { kind: "package-boundary", path: definition.path },
82
- },
83
- ],
84
- fixes: [
85
- {
86
- kind: "oxc-format-write",
87
- owner: { kind: "package-boundary", path: definition.path },
88
- },
89
- {
90
- kind: "oxc-lint-fix",
91
- owner: { kind: "package-boundary", path: definition.path },
92
- },
93
- ],
94
70
  environmentNeeds: [],
95
71
  foundation: {
96
72
  toolchains: {},