@ykdz/template 0.0.40 → 0.0.42

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 (87) hide show
  1. package/node_modules/@ykdz/template-builtin-presets/dist/src/foundation.js +144 -101
  2. package/node_modules/@ykdz/template-builtin-presets/dist/src/rust-bin/definition.js +29 -4
  3. package/node_modules/@ykdz/template-builtin-presets/dist/src/shared/vue.js +11 -2
  4. package/node_modules/@ykdz/template-builtin-presets/dist/src/ts-cli/definition.js +14 -4
  5. package/node_modules/@ykdz/template-builtin-presets/dist/src/ts-lib/definition.js +13 -0
  6. package/node_modules/@ykdz/template-builtin-presets/dist/src/vike-app/definition.js +44 -10
  7. package/node_modules/@ykdz/template-builtin-presets/dist/src/vue-app/definition.js +4 -1
  8. package/node_modules/@ykdz/template-builtin-presets/dist/src/vue-hono-app/definition.js +19 -8
  9. package/node_modules/@ykdz/template-builtin-presets/package.json +23 -10
  10. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/.github/workflows/check-deployment-diagnostics.yml +30 -29
  11. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/.github/workflows/check-deployment.yml +8 -21
  12. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/.github/workflows/check-diagnostics.yml +21 -5
  13. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/.github/workflows/check.yml +4 -2
  14. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/AGENTS.md.template +9 -1
  15. package/node_modules/@ykdz/template-builtin-presets/templates/{shared/devcontainer/node-pnpm.Dockerfile → foundation/devcontainer/base.Dockerfile} +14 -1
  16. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/gitignore +1 -0
  17. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/pnpm-workspace.yaml +3 -0
  18. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/scripts/node-test-count-reporter.ts +31 -0
  19. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/scripts/run-rust-tests.ts +100 -0
  20. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/scripts/run-turbo-boundaries.ts +74 -0
  21. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/scripts/task-gates.ts +589 -0
  22. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/turbo-projections/database-preparation.json +17 -0
  23. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/turbo-projections/deployment.json +13 -0
  24. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/turbo-projections/rust-toolchain.json +5 -0
  25. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/turbo-projections/vue-hono-joint-e2e.json +13 -0
  26. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/turbo.json +14 -15
  27. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/typescript-config/turbo.json +30 -1
  28. package/node_modules/@ykdz/template-builtin-presets/templates/rust-bin/devcontainer/rust.Dockerfile +1 -5
  29. package/node_modules/@ykdz/template-builtin-presets/templates/rust-bin/tsconfig.scripts.json +12 -0
  30. package/node_modules/@ykdz/template-builtin-presets/templates/rust-bin/turbo.json +19 -4
  31. package/node_modules/@ykdz/template-builtin-presets/templates/shared/devcontainer/github-cli.Dockerfile +1 -3
  32. package/node_modules/@ykdz/template-builtin-presets/templates/shared/vue/TESTING.md +7 -0
  33. package/node_modules/@ykdz/template-builtin-presets/templates/shared/vue/src/components/CounterButton.vue +18 -0
  34. package/node_modules/@ykdz/template-builtin-presets/templates/shared/vue/test/counter.browser.test.ts +16 -0
  35. package/node_modules/@ykdz/template-builtin-presets/templates/shared/vue/test/{app.test.ts → counter.node.test.ts} +1 -0
  36. package/node_modules/@ykdz/template-builtin-presets/templates/shared/vue/tsconfig.test.json +1 -1
  37. package/node_modules/@ykdz/template-builtin-presets/templates/shared/vue/vitest.config.ts +50 -0
  38. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/check-artifact.ts +16 -5
  39. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/release.yml +5 -2
  40. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/turbo.json +5 -2
  41. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication-setup/bridge.ts +1 -1
  42. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/src/cli-command-identity.ts +0 -45
  43. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/test/e2e/run-journeys.test.ts +11 -0
  44. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/test/integration/command.test.ts +43 -39
  45. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/test/unit/cli-command-identity.test.ts +52 -52
  46. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/tsconfig.json +1 -1
  47. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/turbo.json +58 -3
  48. package/node_modules/@ykdz/template-builtin-presets/templates/ts-lib/test/greet.test.ts +20 -0
  49. package/node_modules/@ykdz/template-builtin-presets/templates/ts-lib/tsconfig.json +1 -1
  50. package/node_modules/@ykdz/template-builtin-presets/templates/ts-lib/turbo.json +44 -1
  51. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/db/test/todos.test.ts +8 -11
  52. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/db/turbo.json +38 -1
  53. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/db-migrations/turbo.json +44 -1
  54. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/web/playwright.config.ts +18 -2
  55. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/web/test/counter.browser.test.ts +14 -0
  56. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/web/tsconfig.test.json +8 -2
  57. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/web/turbo.json +61 -1
  58. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/web/vitest.config.ts +29 -2
  59. package/node_modules/@ykdz/template-builtin-presets/templates/vue-app/src/App.vue +2 -12
  60. package/node_modules/@ykdz/template-builtin-presets/templates/vue-app/turbo.json +60 -2
  61. package/node_modules/@ykdz/template-builtin-presets/templates/vue-hono-app/api/test/app.test.ts +7 -6
  62. package/node_modules/@ykdz/template-builtin-presets/templates/vue-hono-app/api/tsconfig.json +2 -7
  63. package/node_modules/@ykdz/template-builtin-presets/templates/vue-hono-app/api/turbo.json +46 -1
  64. package/node_modules/@ykdz/template-builtin-presets/templates/vue-hono-app/web/src/App.vue +2 -11
  65. package/node_modules/@ykdz/template-builtin-presets/templates/vue-hono-app/web/turbo.json +57 -1
  66. package/node_modules/@ykdz/template-core/dist/ci-diagnostic-artifact.d.ts +1 -1
  67. package/node_modules/@ykdz/template-core/dist/ci-diagnostic-artifact.js +6 -3
  68. package/node_modules/@ykdz/template-core/dist/dependency-catalog.d.ts +0 -1
  69. package/node_modules/@ykdz/template-core/dist/dependency-catalog.js +0 -19
  70. package/node_modules/@ykdz/template-core/dist/module-graph.d.ts +0 -9
  71. package/node_modules/@ykdz/template-core/dist/module-graph.js +0 -40
  72. package/node_modules/@ykdz/template-core/dist/package-contribution.d.ts +2 -2
  73. package/node_modules/@ykdz/template-core/dist/package-contribution.js +2 -44
  74. package/node_modules/@ykdz/template-core/dist/pnpm-workspace.yaml +4 -1
  75. package/node_modules/@ykdz/template-core/dist/project-github.d.ts +0 -59
  76. package/node_modules/@ykdz/template-core/dist/project-github.js +7 -70
  77. package/node_modules/@ykdz/template-core/dist/renderer.d.ts +1 -0
  78. package/node_modules/@ykdz/template-core/dist/renderer.js +39 -1
  79. package/node_modules/@ykdz/template-core/dist/template-boundary-check.js +34 -16
  80. package/node_modules/@ykdz/template-core/package.json +0 -5
  81. package/package.json +4 -10
  82. package/node_modules/@ykdz/template-builtin-presets/templates/rust-bin/.github/workflows/check.yml +0 -23
  83. package/node_modules/@ykdz/template-builtin-presets/templates/ts-lib/.github/workflows/check.yml +0 -19
  84. package/node_modules/@ykdz/template-builtin-presets/templates/vue-app/.github/workflows/check.yml +0 -20
  85. package/node_modules/@ykdz/template-builtin-presets/templates/vue-app/vitest.config.ts +0 -8
  86. package/node_modules/@ykdz/template-builtin-presets/templates/vue-hono-app/api/vitest.config.ts +0 -15
  87. package/node_modules/@ykdz/template-builtin-presets/templates/vue-hono-app/web/vitest.config.ts +0 -10
@@ -7,7 +7,7 @@ import { composeCiDiagnosticArtifacts } from "@ykdz/template-core/ci-diagnostic-
7
7
  import { collectGeneratedManifestCatalogReferences, selectTemplateDependencyCatalogEntries, } from "@ykdz/template-core/dependency-catalog";
8
8
  import { planDevelopmentContainerToolLayersSync, } from "@ykdz/template-core/development-container-tool-layer";
9
9
  import { editorCustomizationForCapabilities, loadEditorCustomizationDeclarations, } from "@ykdz/template-core/editor-customization";
10
- import { normalizeEnvironmentNeeds, parseEnvironmentNeedsMetadata, playwrightBrowserAssetsEnvironmentNeed, renderDeploymentCheckCommand, renderFixCommand, renderRootCheckCommand, renderTurboRunCommand, shellCheckEnvironmentNeed, } from "@ykdz/template-core/module-graph";
10
+ import { normalizeEnvironmentNeeds, parseEnvironmentNeedsMetadata, playwrightBrowserAssetsEnvironmentNeed, shellCheckEnvironmentNeed, } from "@ykdz/template-core/module-graph";
11
11
  import { assertPackageContribution, assertPackageContributionCommandNames, } from "@ykdz/template-core/package-contribution";
12
12
  import { assertProjectBlueprint, assertProjectBlueprintDraft, isValidNewNpmPackageName, validateNewPackagePath, validateProjectBlueprint as validateCoreProjectBlueprint, } from "@ykdz/template-core/project-blueprint";
13
13
  import { projectCheckWorkflowTemplateSource, projectCheckWorkflowTemplateReplacements, projectDependabotTemplateReplacements, } from "@ykdz/template-core/project-github";
@@ -688,8 +688,8 @@ function contributedDevcontainerComposition(options) {
688
688
  baseLayer: {
689
689
  identity: "node-pnpm",
690
690
  dockerfile: {
691
- source: templateSources.sharedDevcontainer,
692
- from: "node-pnpm.Dockerfile",
691
+ source: templateSources.foundation,
692
+ from: "devcontainer/base.Dockerfile",
693
693
  },
694
694
  buildArguments: [
695
695
  {
@@ -701,6 +701,37 @@ function contributedDevcontainerComposition(options) {
701
701
  probes: [
702
702
  { identity: "procps", command: "ps", args: ["--version"] },
703
703
  { identity: "bubblewrap", command: "bwrap", args: ["--version"] },
704
+ {
705
+ identity: "awk",
706
+ command: "awk",
707
+ args: ["BEGIN { exit (6 * 7 != 42) }"],
708
+ },
709
+ { identity: "ripgrep", command: "rg", args: ["--version"] },
710
+ {
711
+ identity: "jq",
712
+ command: "jq",
713
+ args: ["--exit-status", "--null-input", "{ ready: true } | .ready"],
714
+ },
715
+ {
716
+ identity: "python3",
717
+ command: "python3",
718
+ args: [
719
+ "-c",
720
+ 'import json, pathlib, sqlite3, urllib.request; assert json.loads("true") is True',
721
+ ],
722
+ },
723
+ {
724
+ identity: "python",
725
+ command: "python",
726
+ args: [
727
+ "-c",
728
+ 'import os, shutil, sys; assert sys.version_info.major == 3; assert os.path.samefile(sys.executable, shutil.which("python3"))',
729
+ ],
730
+ },
731
+ { identity: "openssh-client", command: "ssh", args: ["-V"] },
732
+ { identity: "unzip", command: "unzip", args: ["-v"] },
733
+ { identity: "file", command: "file", args: ["--version"] },
734
+ { identity: "iproute2", command: "ss", args: ["--version"] },
704
735
  ],
705
736
  mounts: [
706
737
  {
@@ -853,32 +884,19 @@ function databasePreparationCommands(preparation) {
853
884
  dev: `pnpm run database:prepare:dev && turbo watch dev --filter=${preparation.consumers["application-dev"]}`,
854
885
  };
855
886
  }
856
- function databasePreparationTurboTasks(preparation) {
887
+ function databasePreparationRootTurboTasks() {
857
888
  return {
858
- "//#database:prepare:dev": { cache: false },
859
- "//#database:prepare:test": { cache: false },
860
- "//#database:prepare:e2e": { cache: false },
861
- [`${preparation.databasePackageName}#test`]: {
862
- dependsOn: ["//#database:prepare:test"],
863
- },
864
- [`${preparation.migrationPackageName}#typecheck`]: {
865
- dependsOn: [`${preparation.databasePackageName}#build`],
866
- },
867
- [`${preparation.consumers["application-dev"]}#typecheck`]: {
868
- dependsOn: [`${preparation.databasePackageName}#build`],
889
+ "//#database:prepare:dev": {
890
+ cache: false,
891
+ tags: ["work:preparation"],
869
892
  },
870
- [`${preparation.consumers["application-dev"]}#dev`]: {
871
- dependsOn: [`${preparation.databasePackageName}#build`],
893
+ "//#database:prepare:test": {
872
894
  cache: false,
873
- persistent: true,
895
+ tags: ["work:preparation"],
874
896
  },
875
- [`${preparation.consumers["application-e2e"]}#test:e2e`]: {
876
- dependsOn: [
877
- "//#database:prepare:e2e",
878
- `${preparation.databasePackageName}#build`,
879
- "build",
880
- ],
897
+ "//#database:prepare:e2e": {
881
898
  cache: false,
899
+ tags: ["work:preparation"],
882
900
  },
883
901
  };
884
902
  }
@@ -891,14 +909,20 @@ function deploymentTurboTasks(deploymentCheck) {
891
909
  `${deploymentCheck.migrationPackageName}#build`,
892
910
  ],
893
911
  cache: false,
912
+ tags: ["quality:heavy"],
894
913
  },
895
914
  };
896
915
  }
897
916
  function vueHonoJointE2eTurboTasks(e2e) {
898
917
  return {
899
918
  "//#test:e2e": {
900
- dependsOn: [`${e2e.apiPackageName}#build`, `${e2e.webPackageName}#build`],
919
+ dependsOn: [
920
+ `${e2e.apiPackageName}#build`,
921
+ `${e2e.webPackageName}#build`,
922
+ `${e2e.webPackageName}#browser:prepare`,
923
+ ],
901
924
  cache: false,
925
+ tags: ["quality:heavy"],
902
926
  },
903
927
  };
904
928
  }
@@ -1170,7 +1194,6 @@ function assertRootCapabilityManifestTruth(options) {
1170
1194
  ? {}
1171
1195
  : {
1172
1196
  deployment: "node --conditions=source scripts/check-standalone-deployment.ts",
1173
- "check:deployment": renderDeploymentCheckCommand(),
1174
1197
  }),
1175
1198
  ...(options.vueHonoJointE2e === undefined
1176
1199
  ? {}
@@ -1212,13 +1235,7 @@ function assertCapabilityPackageTurboInheritanceTruth(options) {
1212
1235
  throw new Error(`${options.label} requires exact Turbo extends truth`);
1213
1236
  }
1214
1237
  }
1215
- function effectiveCapabilityTaskDependencies(options) {
1216
- if (options.localTask === undefined) {
1217
- if (!isRecord(options.inheritedTask)) {
1218
- throw new Error(`${options.label} requires Turbo task ${options.taskName}`);
1219
- }
1220
- return options.inheritedTask.dependsOn;
1221
- }
1238
+ function localCapabilityTaskDependencies(options) {
1222
1239
  if (!isRecord(options.localTask)) {
1223
1240
  throw new Error(`${options.label} requires Turbo task ${options.taskName}`);
1224
1241
  }
@@ -1226,24 +1243,11 @@ function effectiveCapabilityTaskDependencies(options) {
1226
1243
  if (extendsValue !== undefined && typeof extendsValue !== "boolean") {
1227
1244
  throw new Error(`${options.label} requires Turbo task ${options.taskName} extends truth`);
1228
1245
  }
1229
- if (extendsValue === false || options.localTask.dependsOn !== undefined) {
1230
- return options.localTask.dependsOn;
1231
- }
1232
- if (!isRecord(options.inheritedTask)) {
1233
- throw new Error(`${options.label} requires Turbo task ${options.taskName}`);
1234
- }
1235
- return options.inheritedTask.dependsOn;
1246
+ return options.localTask.dependsOn;
1236
1247
  }
1237
1248
  function assertCapabilityConsumerTurboTruth(options) {
1238
1249
  const turboByPackagePath = new Map();
1239
- for (const [qualifiedTaskName, expectedTask] of Object.entries(options.expectedTasks)) {
1240
- if (expectedTask.dependsOn === undefined)
1241
- continue;
1242
- const separator = qualifiedTaskName.lastIndexOf("#");
1243
- if (separator <= 0)
1244
- continue;
1245
- const packageName = qualifiedTaskName.slice(0, separator);
1246
- const taskName = qualifiedTaskName.slice(separator + 1);
1250
+ const assertPackageTaskTruth = (packageName, taskName, expectedTask) => {
1247
1251
  const contribution = requireContributionByName(options.packageByName, packageName, "Database Preparation");
1248
1252
  const packageTurbo = turboByPackagePath.get(contribution.definition.path) ??
1249
1253
  readRepositoryJsonRecord({
@@ -1260,17 +1264,46 @@ function assertCapabilityConsumerTurboTruth(options) {
1260
1264
  label: `Package Addition ${contribution.definition.name} Turbo Truth`,
1261
1265
  });
1262
1266
  const localTask = packageTurbo.tasks[taskName];
1263
- const localDependencies = effectiveCapabilityTaskDependencies({
1267
+ localCapabilityTaskDependencies({
1264
1268
  localTask,
1265
- inheritedTask: expectedTask,
1266
1269
  label: `Package Addition ${contribution.definition.name} Turbo Truth`,
1267
1270
  taskName,
1268
1271
  });
1269
- if (!Array.isArray(localDependencies) ||
1270
- expectedTask.dependsOn.some((expectedDependency) => !localDependencies.includes(expectedDependency))) {
1271
- throw new Error(`Package Addition ${contribution.definition.name} Turbo Truth requires Turbo task ${taskName} dependsOn`);
1272
- }
1273
- }
1272
+ assertTurboTaskTruth({
1273
+ config: packageTurbo,
1274
+ expectedTasks: { [taskName]: expectedTask },
1275
+ label: `Package Addition ${contribution.definition.name} Turbo Truth`,
1276
+ });
1277
+ };
1278
+ const preparation = options.preparation;
1279
+ assertPackageTaskTruth(preparation.databasePackageName, "test", {
1280
+ dependsOn: ["//#database:prepare:test"],
1281
+ tags: ["quality:light"],
1282
+ });
1283
+ assertPackageTaskTruth(preparation.migrationPackageName, "typecheck", {
1284
+ dependsOn: [`${preparation.databasePackageName}#build`],
1285
+ tags: ["quality:light"],
1286
+ });
1287
+ assertPackageTaskTruth(preparation.consumers["application-dev"], "typecheck", {
1288
+ dependsOn: [`${preparation.databasePackageName}#build`],
1289
+ tags: ["quality:light"],
1290
+ });
1291
+ assertPackageTaskTruth(preparation.consumers["application-dev"], "dev", {
1292
+ dependsOn: [`${preparation.databasePackageName}#build`],
1293
+ cache: false,
1294
+ persistent: true,
1295
+ tags: ["work:development"],
1296
+ });
1297
+ assertPackageTaskTruth(preparation.consumers["application-e2e"], "test:e2e", {
1298
+ dependsOn: [
1299
+ "//#database:prepare:e2e",
1300
+ `${preparation.databasePackageName}#build`,
1301
+ "build",
1302
+ "browser:prepare",
1303
+ ],
1304
+ cache: false,
1305
+ tags: ["quality:heavy"],
1306
+ });
1274
1307
  for (const packageName of options.buildConsumerPackageNames) {
1275
1308
  const contribution = requireContributionByName(options.packageByName, packageName, "Database Preparation");
1276
1309
  const packageTurbo = turboByPackagePath.get(contribution.definition.path) ??
@@ -1288,21 +1321,14 @@ function assertCapabilityConsumerTurboTruth(options) {
1288
1321
  label: `Package Addition ${contribution.definition.name} Turbo Truth`,
1289
1322
  });
1290
1323
  const localBuild = packageTurbo.tasks.build;
1291
- const qualifiedBuild = isRecord(options.rootTurbo.tasks)
1292
- ? options.rootTurbo.tasks[`${packageName}#build`]
1293
- : undefined;
1294
- const genericBuild = isRecord(options.rootTurbo.tasks)
1295
- ? options.rootTurbo.tasks.build
1296
- : undefined;
1297
- const dependencies = effectiveCapabilityTaskDependencies({
1324
+ const dependencies = localCapabilityTaskDependencies({
1298
1325
  localTask: localBuild,
1299
- inheritedTask: qualifiedBuild === undefined ? genericBuild : qualifiedBuild,
1300
1326
  label: `Package Addition ${contribution.definition.name} Turbo Truth`,
1301
1327
  taskName: "build",
1302
1328
  });
1303
1329
  if (!Array.isArray(dependencies) ||
1304
1330
  !dependencies.some((dependency) => dependency === "^build" ||
1305
- dependency === `${options.databasePackageName}#build`)) {
1331
+ dependency === `${options.preparation.databasePackageName}#build`)) {
1306
1332
  throw new Error(`Package Addition ${contribution.definition.name} Turbo Truth requires Turbo task build dependsOn`);
1307
1333
  }
1308
1334
  }
@@ -1323,7 +1349,7 @@ function assertCapabilityTurboTruth(options) {
1323
1349
  expectedTasks: {
1324
1350
  ...(options.databasePreparation === undefined
1325
1351
  ? {}
1326
- : databasePreparationTurboTasks(options.databasePreparation)),
1352
+ : databasePreparationRootTurboTasks()),
1327
1353
  ...(options.deploymentCheck === undefined
1328
1354
  ? {}
1329
1355
  : deploymentTurboTasks(options.deploymentCheck)),
@@ -1348,13 +1374,11 @@ function assertCapabilityTurboTruth(options) {
1348
1374
  });
1349
1375
  assertCapabilityConsumerTurboTruth({
1350
1376
  repositoryRoot: options.repositoryRoot,
1351
- rootTurbo,
1352
- expectedTasks: databasePreparationTurboTasks(options.databasePreparation),
1377
+ preparation: options.databasePreparation,
1353
1378
  buildConsumerPackageNames: [
1354
1379
  options.databasePreparation.migrationPackageName,
1355
1380
  ...new Set(Object.values(options.databasePreparation.consumers)),
1356
1381
  ],
1357
- databasePackageName: options.databasePreparation.databasePackageName,
1358
1382
  packageByName: options.packageByName,
1359
1383
  });
1360
1384
  }
@@ -1745,17 +1769,6 @@ function publicCliCandidate(contributions) {
1745
1769
  }
1746
1770
  return candidate;
1747
1771
  }
1748
- function renderPublicationRootCheckCommand(candidatePackagePath) {
1749
- return [
1750
- "pnpm run boundaries",
1751
- renderTurboRunCommand(["format:check", "lint", "typecheck", "test"], [], {
1752
- continueAfterFailure: true,
1753
- taskPrefix: true,
1754
- }),
1755
- renderTurboRunCommand(["build", "test:e2e"], [`--filter=!./${candidatePackagePath}`], { continueAfterFailure: true, taskPrefix: true }),
1756
- "pnpm run publication:artifact",
1757
- ].join(" && ");
1758
- }
1759
1772
  /**
1760
1773
  * 票 26 清单单源:把 plan 声明的镜像槽位集合投影成生成检查器携带的清单文本。
1761
1774
  * 转义 `$` 是必要的:清单文本注入模板字面量,未转义的 `$` 会被当成 TypeScript 插值。
@@ -2011,14 +2024,14 @@ function foundationPlan(options) {
2011
2024
  },
2012
2025
  }),
2013
2026
  scripts: {
2014
- check: publicationCandidate === undefined
2015
- ? renderRootCheckCommand()
2016
- : renderPublicationRootCheckCommand(publicationCandidate.definition.path),
2027
+ check: "node --conditions=source scripts/task-gates.ts check",
2028
+ "check:heavy": "node --conditions=source scripts/task-gates.ts check:heavy",
2029
+ "check:full": "node --conditions=source scripts/task-gates.ts check:full",
2017
2030
  // Cargo 会在首次代理调用时按根 rust-toolchain.toml 安装版本与组件;先经唯一根任务完成解析,再并行运行各 Rust 包的 Cargo 检查。
2018
2031
  ...(rustToolchain === undefined
2019
2032
  ? {}
2020
2033
  : { "toolchain:prepare": "cargo --version" }),
2021
- boundaries: "turbo boundaries --no-color && node --conditions=source scripts/check-toolchain-versions.ts",
2034
+ boundaries: "node --conditions=source scripts/run-turbo-boundaries.ts && node --conditions=source scripts/check-toolchain-versions.ts",
2022
2035
  ...(databasePreparation === undefined
2023
2036
  ? {}
2024
2037
  : databasePreparationCommands(databasePreparation)),
@@ -2032,10 +2045,9 @@ function foundationPlan(options) {
2032
2045
  ? {}
2033
2046
  : {
2034
2047
  deployment: "node --conditions=source scripts/check-standalone-deployment.ts",
2035
- "check:deployment": renderDeploymentCheckCommand(),
2036
2048
  }),
2037
2049
  ...(rootOwnedE2e ? { "test:e2e": "playwright test" } : {}),
2038
- fix: renderFixCommand(),
2050
+ fix: "node --conditions=source scripts/task-gates.ts fix",
2039
2051
  "format:check": `oxfmt --list-different --no-error-on-unmatched-pattern package.json pnpm-workspace.yaml pnpm-lock.yaml turbo.json tsconfig.json tsconfig.config.json *.config.ts .pnpmfile.mjs .gitignore .dockerignore Dockerfile TODO.md rust-toolchain.toml .vscode .github .devcontainer ${rootAutomationPaths}`,
2040
2052
  "format:write": `oxfmt --write --no-error-on-unmatched-pattern package.json pnpm-workspace.yaml pnpm-lock.yaml turbo.json tsconfig.json tsconfig.config.json *.config.ts .pnpmfile.mjs .gitignore .dockerignore Dockerfile TODO.md rust-toolchain.toml .vscode .github .devcontainer ${rootAutomationPaths}`,
2041
2053
  lint: deploymentCheck === undefined
@@ -2255,9 +2267,14 @@ function foundationPlan(options) {
2255
2267
  ? []
2256
2268
  : [
2257
2269
  {
2258
- kind: "mergeJson",
2270
+ kind: "mergeJsonTemplate",
2271
+ source: templateSources.foundation,
2272
+ from: "turbo-projections/vue-hono-joint-e2e.json",
2259
2273
  to: "turbo.json",
2260
- value: { tasks: vueHonoJointE2eTurboTasks(vueHonoJointE2e) },
2274
+ replacements: {
2275
+ API_PACKAGE: vueHonoJointE2e.apiPackageName,
2276
+ WEB_PACKAGE: vueHonoJointE2e.webPackageName,
2277
+ },
2261
2278
  multilineArrays: ["tasks.//#test:e2e.dependsOn"],
2262
2279
  },
2263
2280
  ]),
@@ -2265,10 +2282,14 @@ function foundationPlan(options) {
2265
2282
  ? []
2266
2283
  : [
2267
2284
  {
2268
- kind: "mergeJson",
2285
+ kind: "mergeJsonTemplate",
2286
+ source: templateSources.foundation,
2287
+ from: "turbo-projections/deployment.json",
2269
2288
  to: "turbo.json",
2270
- value: {
2271
- tasks: deploymentTurboTasks(deploymentCheck),
2289
+ replacements: {
2290
+ APPLICATION_PACKAGE: deploymentCheck.applicationPackageName,
2291
+ DATABASE_PACKAGE: deploymentCheck.databasePackageName,
2292
+ MIGRATION_PACKAGE: deploymentCheck.migrationPackageName,
2272
2293
  },
2273
2294
  multilineArrays: ["tasks.//#deployment.dependsOn"],
2274
2295
  },
@@ -2277,17 +2298,20 @@ function foundationPlan(options) {
2277
2298
  ? []
2278
2299
  : [
2279
2300
  {
2280
- kind: "mergeJson",
2301
+ kind: "mergeJsonTemplate",
2302
+ source: templateSources.foundation,
2303
+ from: "turbo-projections/database-preparation.json",
2304
+ to: "turbo.json",
2305
+ },
2306
+ ]),
2307
+ ...(rustToolchain === undefined
2308
+ ? []
2309
+ : [
2310
+ {
2311
+ kind: "mergeJsonTemplate",
2312
+ source: templateSources.foundation,
2313
+ from: "turbo-projections/rust-toolchain.json",
2281
2314
  to: "turbo.json",
2282
- value: {
2283
- tasks: databasePreparationTurboTasks(databasePreparation),
2284
- },
2285
- multilineArrays: [
2286
- `tasks.${databasePreparation.migrationPackageName}#typecheck.dependsOn`,
2287
- `tasks.${databasePreparation.consumers["application-dev"]}#typecheck.dependsOn`,
2288
- `tasks.${databasePreparation.consumers["application-dev"]}#dev.dependsOn`,
2289
- `tasks.${databasePreparation.consumers["application-e2e"]}#test:e2e.dependsOn`,
2290
- ],
2291
2315
  },
2292
2316
  ]),
2293
2317
  ...(publicationCandidate === undefined
@@ -2305,7 +2329,14 @@ function foundationPlan(options) {
2305
2329
  source: templateSources.foundation,
2306
2330
  from: `turbo-boundary-tags/${tag}.json`,
2307
2331
  to: "turbo.json",
2308
- multilineArrays: deploymentCheck === undefined ? [] : ["tasks.//#deployment.dependsOn"],
2332
+ multilineArrays: [
2333
+ ...(deploymentCheck === undefined
2334
+ ? []
2335
+ : ["tasks.//#deployment.dependsOn"]),
2336
+ ...(vueHonoJointE2e === undefined
2337
+ ? []
2338
+ : ["tasks.//#test:e2e.dependsOn"]),
2339
+ ],
2309
2340
  })),
2310
2341
  {
2311
2342
  kind: "writeTextTemplate",
@@ -2316,6 +2347,18 @@ function foundationPlan(options) {
2316
2347
  TOOLCHAIN_MIRROR_SLOT_MANIFEST: toolchainMirrorSlotManifest,
2317
2348
  },
2318
2349
  },
2350
+ {
2351
+ kind: "copyFile",
2352
+ source: templateSources.foundation,
2353
+ from: "scripts/task-gates.ts",
2354
+ to: "scripts/task-gates.ts",
2355
+ },
2356
+ {
2357
+ kind: "copyFile",
2358
+ source: templateSources.foundation,
2359
+ from: "scripts/run-turbo-boundaries.ts",
2360
+ to: "scripts/run-turbo-boundaries.ts",
2361
+ },
2319
2362
  {
2320
2363
  kind: "copyFile",
2321
2364
  source: templateSources.foundation,
@@ -7,10 +7,11 @@ function packagePathForLeaf(packageLeafName) {
7
7
  }
8
8
  function packageScripts() {
9
9
  return {
10
- "format:check": "cargo fmt --all -- --check",
11
- "format:write": "cargo fmt --all",
12
- lint: "cargo clippy --workspace --all-targets -- -D warnings",
13
- test: "cargo test --workspace",
10
+ "format:check": "cargo fmt --all -- --check && oxfmt --list-different --no-error-on-unmatched-pattern package.json tsconfig.scripts.json turbo.json scripts",
11
+ "format:write": "cargo fmt --all && oxfmt --write --no-error-on-unmatched-pattern package.json tsconfig.scripts.json turbo.json scripts",
12
+ lint: "cargo clippy --workspace --all-targets -- -D warnings && oxlint --quiet --format=unix scripts",
13
+ test: "node --conditions=source scripts/run-rust-tests.ts",
14
+ typecheck: "tsc -p tsconfig.scripts.json --noEmit --pretty false",
14
15
  };
15
16
  }
16
17
  function rustContribution(options) {
@@ -24,6 +25,15 @@ function rustContribution(options) {
24
25
  const rustChannel = options.context.toolchain.rustVersion ?? "stable";
25
26
  const operations = [
26
27
  { kind: "writeJson", to: `${definition.path}/package.json`, value: {} },
28
+ {
29
+ kind: "writeTextTemplate",
30
+ source: templateSources.rustBin,
31
+ from: "tsconfig.scripts.json",
32
+ to: `${definition.path}/tsconfig.scripts.json`,
33
+ replacements: {
34
+ TYPESCRIPT_CONFIG_PACKAGE: options.context.foundationPackages.typescriptConfiguration.name,
35
+ },
36
+ },
27
37
  {
28
38
  kind: "writeTextTemplate",
29
39
  source: templateSources.rustBin,
@@ -56,6 +66,12 @@ function rustContribution(options) {
56
66
  from: "src/main.rs",
57
67
  to: `${definition.path}/src/main.rs`,
58
68
  },
69
+ {
70
+ kind: "copyFile",
71
+ source: templateSources.foundation,
72
+ from: "scripts/run-rust-tests.ts",
73
+ to: `${definition.path}/scripts/run-rust-tests.ts`,
74
+ },
59
75
  ];
60
76
  return {
61
77
  definition,
@@ -63,7 +79,15 @@ function rustContribution(options) {
63
79
  manifest: {
64
80
  name: definition.name,
65
81
  private: true,
82
+ type: "module",
66
83
  scripts: packageScripts(),
84
+ devDependencies: {
85
+ [options.context.foundationPackages.typescriptConfiguration.name]: "link:../typescript-config",
86
+ "@types/node": "catalog:",
87
+ oxfmt: "catalog:",
88
+ oxlint: "catalog:",
89
+ "typescript-7": "catalog:",
90
+ },
67
91
  engines: { node: options.context.toolchain.nodeLtsMajor },
68
92
  },
69
93
  operations,
@@ -85,6 +109,7 @@ function rustContribution(options) {
85
109
  },
86
110
  },
87
111
  editorCapabilities: ["rust-tooling"],
112
+ typescriptConfigurationPackage: { dependency: "required" },
88
113
  dependencyMaintenance: {
89
114
  ecosystems: [
90
115
  "npm",
@@ -16,11 +16,15 @@ const sharedVueSourceFiles = [
16
16
  "tsconfig.app.json",
17
17
  "tsconfig.test.json",
18
18
  "tsconfig.node.json",
19
+ "vitest.config.ts",
19
20
  "typescript/run-vue-tsc.ts",
20
21
  "src/main.ts",
21
22
  "src/style.css",
23
+ "src/components/CounterButton.vue",
22
24
  "src/stores/counter.ts",
23
- "test/app.test.ts",
25
+ "test/counter.browser.test.ts",
26
+ "test/counter.node.test.ts",
27
+ "TESTING.md",
24
28
  ];
25
29
  export function vueApplicationScripts() {
26
30
  return {
@@ -31,7 +35,9 @@ export function vueApplicationScripts() {
31
35
  lint: "oxlint --quiet --format=unix .",
32
36
  "lint:fix": "oxlint --format=unix . --fix",
33
37
  preview: "vite preview",
34
- test: "vitest run --reporter=agent --silent=passed-only",
38
+ "browser:prepare": "playwright install chromium",
39
+ test: "vitest run --project=node --reporter=agent --silent=passed-only",
40
+ "test:browser": "vitest run --project=browser --reporter=agent --silent=passed-only",
35
41
  "test:e2e": "playwright test",
36
42
  };
37
43
  }
@@ -101,6 +107,9 @@ export function vueApplicationManifest(options) {
101
107
  typescript: "catalog:",
102
108
  vite: "catalog:",
103
109
  vitest: "catalog:",
110
+ "@vitest/browser-playwright": "catalog:",
111
+ playwright: "catalog:",
112
+ "vitest-browser-vue": "catalog:",
104
113
  "vue-tsc": "catalog:",
105
114
  },
106
115
  engines: { node: options.context.toolchain.nodeLtsMajor },
@@ -33,8 +33,8 @@ function packageScripts() {
33
33
  build: "tsc -p tsconfig.build.json --pretty false",
34
34
  postbuild: "node -e \"if (process.platform !== 'win32') require('node:fs').chmodSync('dist/cli.js', 0o755)\"",
35
35
  typecheck: "tsc -p tsconfig.json --noEmit --pretty false",
36
- test: "vitest run test/unit test/integration --reporter=verbose",
37
- "test:e2e": "node --conditions=source test/e2e/run-journeys.ts source distribution",
36
+ test: "node --conditions=source --test --test-reporter=spec --test-reporter=./scripts/node-test-count-reporter.ts --test-reporter-destination=stdout --test-reporter-destination=stderr 'test/unit/**/*.test.ts' 'test/integration/**/*.test.ts'",
37
+ "test:e2e": "node --conditions=source --test --test-timeout=180000 --test-reporter=spec --test-reporter=./scripts/node-test-count-reporter.ts --test-reporter-destination=stdout --test-reporter-destination=stderr 'test/e2e/**/*.test.ts'",
38
38
  prepack: "pnpm exec turbo run build --filter=.",
39
39
  };
40
40
  }
@@ -118,12 +118,24 @@ function cliContribution(options) {
118
118
  from: "test/e2e/run-journeys.ts",
119
119
  to: `${definition.path}/test/e2e/run-journeys.ts`,
120
120
  },
121
+ {
122
+ kind: "copyFile",
123
+ source: templateSources.tsCli,
124
+ from: "test/e2e/run-journeys.test.ts",
125
+ to: `${definition.path}/test/e2e/run-journeys.test.ts`,
126
+ },
121
127
  {
122
128
  kind: "copyFile",
123
129
  source: templateSources.tsCli,
124
130
  from: "test/e2e/journeys/lookup.journey.ts",
125
131
  to: `${definition.path}/test/e2e/journeys/lookup.journey.ts`,
126
132
  },
133
+ ...["node-test-count-reporter.ts"].map((name) => ({
134
+ kind: "copyFile",
135
+ source: templateSources.foundation,
136
+ from: `scripts/${name}`,
137
+ to: `${definition.path}/scripts/${name}`,
138
+ })),
127
139
  ];
128
140
  return {
129
141
  definition,
@@ -146,8 +158,6 @@ function cliContribution(options) {
146
158
  oxlint: "catalog:",
147
159
  "oxlint-tsgolint": "catalog:",
148
160
  "typescript-7": "catalog:",
149
- vite: "catalog:",
150
- vitest: "catalog:",
151
161
  },
152
162
  engines: {
153
163
  node: options.publicationCandidate
@@ -12,6 +12,7 @@ function packageScripts() {
12
12
  lint: "oxlint --quiet --format=unix --ignore-pattern node_modules .",
13
13
  "lint:fix": "oxlint --format=unix . --fix",
14
14
  build: "tsc -p tsconfig.build.json --pretty false",
15
+ test: "node --conditions=source --test --test-reporter=spec --test-reporter=./scripts/node-test-count-reporter.ts --test-reporter-destination=stdout --test-reporter-destination=stderr 'test/**/*.test.ts'",
15
16
  typecheck: "tsc -p tsconfig.json --noEmit --pretty false",
16
17
  };
17
18
  }
@@ -69,6 +70,18 @@ function libraryContribution(options) {
69
70
  from: "turbo.json",
70
71
  to: `${definition.path}/turbo.json`,
71
72
  },
73
+ {
74
+ kind: "copyFile",
75
+ source: templateSources.tsLib,
76
+ from: "test/greet.test.ts",
77
+ to: `${definition.path}/test/greet.test.ts`,
78
+ },
79
+ ...["node-test-count-reporter.ts"].map((name) => ({
80
+ kind: "copyFile",
81
+ source: templateSources.foundation,
82
+ from: `scripts/${name}`,
83
+ to: `${definition.path}/scripts/${name}`,
84
+ })),
72
85
  ];
73
86
  return {
74
87
  definition,