@ykdz/template 0.0.41 → 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 (81) hide show
  1. package/node_modules/@ykdz/template-builtin-presets/dist/src/foundation.js +111 -99
  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 +7 -1
  15. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/gitignore +1 -0
  16. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/pnpm-workspace.yaml +3 -0
  17. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/scripts/node-test-count-reporter.ts +31 -0
  18. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/scripts/run-rust-tests.ts +100 -0
  19. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/scripts/run-turbo-boundaries.ts +74 -0
  20. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/scripts/task-gates.ts +589 -0
  21. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/turbo-projections/database-preparation.json +17 -0
  22. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/turbo-projections/deployment.json +13 -0
  23. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/turbo-projections/rust-toolchain.json +5 -0
  24. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/turbo-projections/vue-hono-joint-e2e.json +13 -0
  25. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/turbo.json +14 -15
  26. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/typescript-config/turbo.json +30 -1
  27. package/node_modules/@ykdz/template-builtin-presets/templates/rust-bin/tsconfig.scripts.json +12 -0
  28. package/node_modules/@ykdz/template-builtin-presets/templates/rust-bin/turbo.json +19 -4
  29. package/node_modules/@ykdz/template-builtin-presets/templates/shared/vue/TESTING.md +7 -0
  30. package/node_modules/@ykdz/template-builtin-presets/templates/shared/vue/src/components/CounterButton.vue +18 -0
  31. package/node_modules/@ykdz/template-builtin-presets/templates/shared/vue/test/counter.browser.test.ts +16 -0
  32. package/node_modules/@ykdz/template-builtin-presets/templates/shared/vue/test/{app.test.ts → counter.node.test.ts} +1 -0
  33. package/node_modules/@ykdz/template-builtin-presets/templates/shared/vue/tsconfig.test.json +1 -1
  34. package/node_modules/@ykdz/template-builtin-presets/templates/shared/vue/vitest.config.ts +50 -0
  35. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/check-artifact.ts +16 -5
  36. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/release.yml +5 -2
  37. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/turbo.json +5 -2
  38. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication-setup/bridge.ts +1 -1
  39. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/src/cli-command-identity.ts +0 -45
  40. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/test/e2e/run-journeys.test.ts +11 -0
  41. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/test/integration/command.test.ts +43 -39
  42. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/test/unit/cli-command-identity.test.ts +52 -52
  43. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/tsconfig.json +1 -1
  44. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/turbo.json +58 -3
  45. package/node_modules/@ykdz/template-builtin-presets/templates/ts-lib/test/greet.test.ts +20 -0
  46. package/node_modules/@ykdz/template-builtin-presets/templates/ts-lib/tsconfig.json +1 -1
  47. package/node_modules/@ykdz/template-builtin-presets/templates/ts-lib/turbo.json +44 -1
  48. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/db/test/todos.test.ts +8 -11
  49. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/db/turbo.json +38 -1
  50. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/db-migrations/turbo.json +44 -1
  51. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/web/playwright.config.ts +18 -2
  52. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/web/test/counter.browser.test.ts +14 -0
  53. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/web/tsconfig.test.json +8 -2
  54. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/web/turbo.json +61 -1
  55. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/web/vitest.config.ts +29 -2
  56. package/node_modules/@ykdz/template-builtin-presets/templates/vue-app/src/App.vue +2 -12
  57. package/node_modules/@ykdz/template-builtin-presets/templates/vue-app/turbo.json +60 -2
  58. package/node_modules/@ykdz/template-builtin-presets/templates/vue-hono-app/api/test/app.test.ts +7 -6
  59. package/node_modules/@ykdz/template-builtin-presets/templates/vue-hono-app/api/tsconfig.json +2 -7
  60. package/node_modules/@ykdz/template-builtin-presets/templates/vue-hono-app/api/turbo.json +46 -1
  61. package/node_modules/@ykdz/template-builtin-presets/templates/vue-hono-app/web/src/App.vue +2 -11
  62. package/node_modules/@ykdz/template-builtin-presets/templates/vue-hono-app/web/turbo.json +57 -1
  63. package/node_modules/@ykdz/template-core/dist/ci-diagnostic-artifact.d.ts +1 -1
  64. package/node_modules/@ykdz/template-core/dist/ci-diagnostic-artifact.js +6 -3
  65. package/node_modules/@ykdz/template-core/dist/module-graph.d.ts +0 -9
  66. package/node_modules/@ykdz/template-core/dist/module-graph.js +0 -40
  67. package/node_modules/@ykdz/template-core/dist/package-contribution.d.ts +2 -2
  68. package/node_modules/@ykdz/template-core/dist/package-contribution.js +2 -44
  69. package/node_modules/@ykdz/template-core/dist/pnpm-workspace.yaml +3 -0
  70. package/node_modules/@ykdz/template-core/dist/project-github.js +7 -3
  71. package/node_modules/@ykdz/template-core/dist/renderer.d.ts +1 -0
  72. package/node_modules/@ykdz/template-core/dist/renderer.js +39 -1
  73. package/node_modules/@ykdz/template-core/dist/template-boundary-check.js +34 -16
  74. package/node_modules/@ykdz/template-core/package.json +0 -5
  75. package/package.json +4 -10
  76. package/node_modules/@ykdz/template-builtin-presets/templates/rust-bin/.github/workflows/check.yml +0 -23
  77. package/node_modules/@ykdz/template-builtin-presets/templates/ts-lib/.github/workflows/check.yml +0 -19
  78. package/node_modules/@ykdz/template-builtin-presets/templates/vue-app/.github/workflows/check.yml +0 -20
  79. package/node_modules/@ykdz/template-builtin-presets/templates/vue-app/vitest.config.ts +0 -8
  80. package/node_modules/@ykdz/template-builtin-presets/templates/vue-hono-app/api/vitest.config.ts +0 -15
  81. 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";
@@ -884,32 +884,19 @@ function databasePreparationCommands(preparation) {
884
884
  dev: `pnpm run database:prepare:dev && turbo watch dev --filter=${preparation.consumers["application-dev"]}`,
885
885
  };
886
886
  }
887
- function databasePreparationTurboTasks(preparation) {
887
+ function databasePreparationRootTurboTasks() {
888
888
  return {
889
- "//#database:prepare:dev": { cache: false },
890
- "//#database:prepare:test": { cache: false },
891
- "//#database:prepare:e2e": { cache: false },
892
- [`${preparation.databasePackageName}#test`]: {
893
- dependsOn: ["//#database:prepare:test"],
894
- },
895
- [`${preparation.migrationPackageName}#typecheck`]: {
896
- dependsOn: [`${preparation.databasePackageName}#build`],
897
- },
898
- [`${preparation.consumers["application-dev"]}#typecheck`]: {
899
- dependsOn: [`${preparation.databasePackageName}#build`],
889
+ "//#database:prepare:dev": {
890
+ cache: false,
891
+ tags: ["work:preparation"],
900
892
  },
901
- [`${preparation.consumers["application-dev"]}#dev`]: {
902
- dependsOn: [`${preparation.databasePackageName}#build`],
893
+ "//#database:prepare:test": {
903
894
  cache: false,
904
- persistent: true,
895
+ tags: ["work:preparation"],
905
896
  },
906
- [`${preparation.consumers["application-e2e"]}#test:e2e`]: {
907
- dependsOn: [
908
- "//#database:prepare:e2e",
909
- `${preparation.databasePackageName}#build`,
910
- "build",
911
- ],
897
+ "//#database:prepare:e2e": {
912
898
  cache: false,
899
+ tags: ["work:preparation"],
913
900
  },
914
901
  };
915
902
  }
@@ -922,14 +909,20 @@ function deploymentTurboTasks(deploymentCheck) {
922
909
  `${deploymentCheck.migrationPackageName}#build`,
923
910
  ],
924
911
  cache: false,
912
+ tags: ["quality:heavy"],
925
913
  },
926
914
  };
927
915
  }
928
916
  function vueHonoJointE2eTurboTasks(e2e) {
929
917
  return {
930
918
  "//#test:e2e": {
931
- dependsOn: [`${e2e.apiPackageName}#build`, `${e2e.webPackageName}#build`],
919
+ dependsOn: [
920
+ `${e2e.apiPackageName}#build`,
921
+ `${e2e.webPackageName}#build`,
922
+ `${e2e.webPackageName}#browser:prepare`,
923
+ ],
932
924
  cache: false,
925
+ tags: ["quality:heavy"],
933
926
  },
934
927
  };
935
928
  }
@@ -1201,7 +1194,6 @@ function assertRootCapabilityManifestTruth(options) {
1201
1194
  ? {}
1202
1195
  : {
1203
1196
  deployment: "node --conditions=source scripts/check-standalone-deployment.ts",
1204
- "check:deployment": renderDeploymentCheckCommand(),
1205
1197
  }),
1206
1198
  ...(options.vueHonoJointE2e === undefined
1207
1199
  ? {}
@@ -1243,13 +1235,7 @@ function assertCapabilityPackageTurboInheritanceTruth(options) {
1243
1235
  throw new Error(`${options.label} requires exact Turbo extends truth`);
1244
1236
  }
1245
1237
  }
1246
- function effectiveCapabilityTaskDependencies(options) {
1247
- if (options.localTask === undefined) {
1248
- if (!isRecord(options.inheritedTask)) {
1249
- throw new Error(`${options.label} requires Turbo task ${options.taskName}`);
1250
- }
1251
- return options.inheritedTask.dependsOn;
1252
- }
1238
+ function localCapabilityTaskDependencies(options) {
1253
1239
  if (!isRecord(options.localTask)) {
1254
1240
  throw new Error(`${options.label} requires Turbo task ${options.taskName}`);
1255
1241
  }
@@ -1257,24 +1243,11 @@ function effectiveCapabilityTaskDependencies(options) {
1257
1243
  if (extendsValue !== undefined && typeof extendsValue !== "boolean") {
1258
1244
  throw new Error(`${options.label} requires Turbo task ${options.taskName} extends truth`);
1259
1245
  }
1260
- if (extendsValue === false || options.localTask.dependsOn !== undefined) {
1261
- return options.localTask.dependsOn;
1262
- }
1263
- if (!isRecord(options.inheritedTask)) {
1264
- throw new Error(`${options.label} requires Turbo task ${options.taskName}`);
1265
- }
1266
- return options.inheritedTask.dependsOn;
1246
+ return options.localTask.dependsOn;
1267
1247
  }
1268
1248
  function assertCapabilityConsumerTurboTruth(options) {
1269
1249
  const turboByPackagePath = new Map();
1270
- for (const [qualifiedTaskName, expectedTask] of Object.entries(options.expectedTasks)) {
1271
- if (expectedTask.dependsOn === undefined)
1272
- continue;
1273
- const separator = qualifiedTaskName.lastIndexOf("#");
1274
- if (separator <= 0)
1275
- continue;
1276
- const packageName = qualifiedTaskName.slice(0, separator);
1277
- const taskName = qualifiedTaskName.slice(separator + 1);
1250
+ const assertPackageTaskTruth = (packageName, taskName, expectedTask) => {
1278
1251
  const contribution = requireContributionByName(options.packageByName, packageName, "Database Preparation");
1279
1252
  const packageTurbo = turboByPackagePath.get(contribution.definition.path) ??
1280
1253
  readRepositoryJsonRecord({
@@ -1291,17 +1264,46 @@ function assertCapabilityConsumerTurboTruth(options) {
1291
1264
  label: `Package Addition ${contribution.definition.name} Turbo Truth`,
1292
1265
  });
1293
1266
  const localTask = packageTurbo.tasks[taskName];
1294
- const localDependencies = effectiveCapabilityTaskDependencies({
1267
+ localCapabilityTaskDependencies({
1295
1268
  localTask,
1296
- inheritedTask: expectedTask,
1297
1269
  label: `Package Addition ${contribution.definition.name} Turbo Truth`,
1298
1270
  taskName,
1299
1271
  });
1300
- if (!Array.isArray(localDependencies) ||
1301
- expectedTask.dependsOn.some((expectedDependency) => !localDependencies.includes(expectedDependency))) {
1302
- throw new Error(`Package Addition ${contribution.definition.name} Turbo Truth requires Turbo task ${taskName} dependsOn`);
1303
- }
1304
- }
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
+ });
1305
1307
  for (const packageName of options.buildConsumerPackageNames) {
1306
1308
  const contribution = requireContributionByName(options.packageByName, packageName, "Database Preparation");
1307
1309
  const packageTurbo = turboByPackagePath.get(contribution.definition.path) ??
@@ -1319,21 +1321,14 @@ function assertCapabilityConsumerTurboTruth(options) {
1319
1321
  label: `Package Addition ${contribution.definition.name} Turbo Truth`,
1320
1322
  });
1321
1323
  const localBuild = packageTurbo.tasks.build;
1322
- const qualifiedBuild = isRecord(options.rootTurbo.tasks)
1323
- ? options.rootTurbo.tasks[`${packageName}#build`]
1324
- : undefined;
1325
- const genericBuild = isRecord(options.rootTurbo.tasks)
1326
- ? options.rootTurbo.tasks.build
1327
- : undefined;
1328
- const dependencies = effectiveCapabilityTaskDependencies({
1324
+ const dependencies = localCapabilityTaskDependencies({
1329
1325
  localTask: localBuild,
1330
- inheritedTask: qualifiedBuild === undefined ? genericBuild : qualifiedBuild,
1331
1326
  label: `Package Addition ${contribution.definition.name} Turbo Truth`,
1332
1327
  taskName: "build",
1333
1328
  });
1334
1329
  if (!Array.isArray(dependencies) ||
1335
1330
  !dependencies.some((dependency) => dependency === "^build" ||
1336
- dependency === `${options.databasePackageName}#build`)) {
1331
+ dependency === `${options.preparation.databasePackageName}#build`)) {
1337
1332
  throw new Error(`Package Addition ${contribution.definition.name} Turbo Truth requires Turbo task build dependsOn`);
1338
1333
  }
1339
1334
  }
@@ -1354,7 +1349,7 @@ function assertCapabilityTurboTruth(options) {
1354
1349
  expectedTasks: {
1355
1350
  ...(options.databasePreparation === undefined
1356
1351
  ? {}
1357
- : databasePreparationTurboTasks(options.databasePreparation)),
1352
+ : databasePreparationRootTurboTasks()),
1358
1353
  ...(options.deploymentCheck === undefined
1359
1354
  ? {}
1360
1355
  : deploymentTurboTasks(options.deploymentCheck)),
@@ -1379,13 +1374,11 @@ function assertCapabilityTurboTruth(options) {
1379
1374
  });
1380
1375
  assertCapabilityConsumerTurboTruth({
1381
1376
  repositoryRoot: options.repositoryRoot,
1382
- rootTurbo,
1383
- expectedTasks: databasePreparationTurboTasks(options.databasePreparation),
1377
+ preparation: options.databasePreparation,
1384
1378
  buildConsumerPackageNames: [
1385
1379
  options.databasePreparation.migrationPackageName,
1386
1380
  ...new Set(Object.values(options.databasePreparation.consumers)),
1387
1381
  ],
1388
- databasePackageName: options.databasePreparation.databasePackageName,
1389
1382
  packageByName: options.packageByName,
1390
1383
  });
1391
1384
  }
@@ -1776,17 +1769,6 @@ function publicCliCandidate(contributions) {
1776
1769
  }
1777
1770
  return candidate;
1778
1771
  }
1779
- function renderPublicationRootCheckCommand(candidatePackagePath) {
1780
- return [
1781
- "pnpm run boundaries",
1782
- renderTurboRunCommand(["format:check", "lint", "typecheck", "test"], [], {
1783
- continueAfterFailure: true,
1784
- taskPrefix: true,
1785
- }),
1786
- renderTurboRunCommand(["build", "test:e2e"], [`--filter=!./${candidatePackagePath}`], { continueAfterFailure: true, taskPrefix: true }),
1787
- "pnpm run publication:artifact",
1788
- ].join(" && ");
1789
- }
1790
1772
  /**
1791
1773
  * 票 26 清单单源:把 plan 声明的镜像槽位集合投影成生成检查器携带的清单文本。
1792
1774
  * 转义 `$` 是必要的:清单文本注入模板字面量,未转义的 `$` 会被当成 TypeScript 插值。
@@ -2042,14 +2024,14 @@ function foundationPlan(options) {
2042
2024
  },
2043
2025
  }),
2044
2026
  scripts: {
2045
- check: publicationCandidate === undefined
2046
- ? renderRootCheckCommand()
2047
- : 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",
2048
2030
  // Cargo 会在首次代理调用时按根 rust-toolchain.toml 安装版本与组件;先经唯一根任务完成解析,再并行运行各 Rust 包的 Cargo 检查。
2049
2031
  ...(rustToolchain === undefined
2050
2032
  ? {}
2051
2033
  : { "toolchain:prepare": "cargo --version" }),
2052
- 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",
2053
2035
  ...(databasePreparation === undefined
2054
2036
  ? {}
2055
2037
  : databasePreparationCommands(databasePreparation)),
@@ -2063,10 +2045,9 @@ function foundationPlan(options) {
2063
2045
  ? {}
2064
2046
  : {
2065
2047
  deployment: "node --conditions=source scripts/check-standalone-deployment.ts",
2066
- "check:deployment": renderDeploymentCheckCommand(),
2067
2048
  }),
2068
2049
  ...(rootOwnedE2e ? { "test:e2e": "playwright test" } : {}),
2069
- fix: renderFixCommand(),
2050
+ fix: "node --conditions=source scripts/task-gates.ts fix",
2070
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}`,
2071
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}`,
2072
2053
  lint: deploymentCheck === undefined
@@ -2286,9 +2267,14 @@ function foundationPlan(options) {
2286
2267
  ? []
2287
2268
  : [
2288
2269
  {
2289
- kind: "mergeJson",
2270
+ kind: "mergeJsonTemplate",
2271
+ source: templateSources.foundation,
2272
+ from: "turbo-projections/vue-hono-joint-e2e.json",
2290
2273
  to: "turbo.json",
2291
- value: { tasks: vueHonoJointE2eTurboTasks(vueHonoJointE2e) },
2274
+ replacements: {
2275
+ API_PACKAGE: vueHonoJointE2e.apiPackageName,
2276
+ WEB_PACKAGE: vueHonoJointE2e.webPackageName,
2277
+ },
2292
2278
  multilineArrays: ["tasks.//#test:e2e.dependsOn"],
2293
2279
  },
2294
2280
  ]),
@@ -2296,10 +2282,14 @@ function foundationPlan(options) {
2296
2282
  ? []
2297
2283
  : [
2298
2284
  {
2299
- kind: "mergeJson",
2285
+ kind: "mergeJsonTemplate",
2286
+ source: templateSources.foundation,
2287
+ from: "turbo-projections/deployment.json",
2300
2288
  to: "turbo.json",
2301
- value: {
2302
- tasks: deploymentTurboTasks(deploymentCheck),
2289
+ replacements: {
2290
+ APPLICATION_PACKAGE: deploymentCheck.applicationPackageName,
2291
+ DATABASE_PACKAGE: deploymentCheck.databasePackageName,
2292
+ MIGRATION_PACKAGE: deploymentCheck.migrationPackageName,
2303
2293
  },
2304
2294
  multilineArrays: ["tasks.//#deployment.dependsOn"],
2305
2295
  },
@@ -2308,17 +2298,20 @@ function foundationPlan(options) {
2308
2298
  ? []
2309
2299
  : [
2310
2300
  {
2311
- 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",
2312
2314
  to: "turbo.json",
2313
- value: {
2314
- tasks: databasePreparationTurboTasks(databasePreparation),
2315
- },
2316
- multilineArrays: [
2317
- `tasks.${databasePreparation.migrationPackageName}#typecheck.dependsOn`,
2318
- `tasks.${databasePreparation.consumers["application-dev"]}#typecheck.dependsOn`,
2319
- `tasks.${databasePreparation.consumers["application-dev"]}#dev.dependsOn`,
2320
- `tasks.${databasePreparation.consumers["application-e2e"]}#test:e2e.dependsOn`,
2321
- ],
2322
2315
  },
2323
2316
  ]),
2324
2317
  ...(publicationCandidate === undefined
@@ -2336,7 +2329,14 @@ function foundationPlan(options) {
2336
2329
  source: templateSources.foundation,
2337
2330
  from: `turbo-boundary-tags/${tag}.json`,
2338
2331
  to: "turbo.json",
2339
- 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
+ ],
2340
2340
  })),
2341
2341
  {
2342
2342
  kind: "writeTextTemplate",
@@ -2347,6 +2347,18 @@ function foundationPlan(options) {
2347
2347
  TOOLCHAIN_MIRROR_SLOT_MANIFEST: toolchainMirrorSlotManifest,
2348
2348
  },
2349
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
+ },
2350
2362
  {
2351
2363
  kind: "copyFile",
2352
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,