@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
@@ -2,8 +2,64 @@
2
2
  "extends": ["//"],
3
3
  "tags": ["app"],
4
4
  "tasks": {
5
+ "browser:prepare": {
6
+ "cache": false,
7
+ "outputs": [],
8
+ "tags": ["work:preparation"]
9
+ },
5
10
  "build": {
6
- "outputs": ["dist/**"]
11
+ "cache": true,
12
+ "dependsOn": ["^build"],
13
+ "outputs": ["dist/**"],
14
+ "tags": ["quality:light"]
15
+ },
16
+ "dev": {
17
+ "cache": false,
18
+ "outputs": [],
19
+ "tags": ["work:development"]
20
+ },
21
+ "format:check": {
22
+ "cache": true,
23
+ "outputs": [],
24
+ "tags": ["quality:light"]
25
+ },
26
+ "format:write": {
27
+ "cache": false,
28
+ "dependsOn": ["lint:fix"],
29
+ "outputs": [],
30
+ "tags": ["work:repair"]
31
+ },
32
+ "lint": {
33
+ "cache": true,
34
+ "outputs": [],
35
+ "tags": ["quality:light"]
36
+ },
37
+ "lint:fix": {
38
+ "cache": false,
39
+ "outputs": [],
40
+ "tags": ["work:repair"]
41
+ },
42
+ "preview": {
43
+ "cache": false,
44
+ "outputs": [],
45
+ "tags": ["work:development"]
46
+ },
47
+ "test": {
48
+ "cache": true,
49
+ "outputs": [],
50
+ "tags": ["quality:light"]
51
+ },
52
+ "test:browser": {
53
+ "cache": true,
54
+ "dependsOn": ["browser:prepare"],
55
+ "outputs": [],
56
+ "tags": ["quality:heavy"]
57
+ },
58
+ "typecheck": {
59
+ "cache": true,
60
+ "dependsOn": ["^typecheck"],
61
+ "outputs": [],
62
+ "tags": ["quality:light"]
7
63
  }
8
64
  }
9
65
  }
@@ -1,7 +1,7 @@
1
1
  import type { ComponentOwner } from "./module-graph.ts";
2
2
  /** Closed, owner-scoped native evidence a Package Contribution may retain in CI. */
3
3
  export type CiDiagnosticArtifactDeclaration = {
4
- readonly kind: "playwright";
4
+ readonly kind: "playwright" | "vitest-browser";
5
5
  readonly owner: ComponentOwner;
6
6
  };
7
7
  /**
@@ -28,7 +28,7 @@ export function assertCiDiagnosticArtifactDeclaration(value) {
28
28
  if (!isRecord(value) || !hasExactKeys(value, ["kind", "owner"])) {
29
29
  throw new Error("CI Diagnostic Artifact declarations may contain only kind and owner");
30
30
  }
31
- if (value.kind !== "playwright") {
31
+ if (value.kind !== "playwright" && value.kind !== "vitest-browser") {
32
32
  throw new Error("Unsupported CI Diagnostic Artifact kind");
33
33
  }
34
34
  if (!isRecord(value.owner) || !hasExactKeys(value.owner, ["kind", "path"])) {
@@ -42,7 +42,7 @@ export function assertCiDiagnosticArtifactDeclaration(value) {
42
42
  throw new Error("CI Diagnostic Artifact owner has an unsafe Package Boundary path");
43
43
  }
44
44
  return {
45
- kind: "playwright",
45
+ kind: value.kind,
46
46
  owner: value.owner.kind === "workspace-orchestration"
47
47
  ? { kind: "workspace-orchestration", path: "." }
48
48
  : { kind: "package-boundary", path: value.owner.path },
@@ -69,5 +69,8 @@ export function composeCiDiagnosticArtifacts(options) {
69
69
  const key = `${declaration.kind}:${declaration.owner.path}`;
70
70
  artifacts.set(key, declaration);
71
71
  }
72
- return [...artifacts.values()].toSorted((left, right) => left.owner.path.localeCompare(right.owner.path));
72
+ return [...artifacts.values()].toSorted((left, right) => {
73
+ const ownerOrder = left.owner.path.localeCompare(right.owner.path);
74
+ return ownerOrder === 0 ? left.kind.localeCompare(right.kind) : ownerOrder;
75
+ });
73
76
  }
@@ -46,15 +46,6 @@ export declare function normalizeEnvironmentNeeds(options: {
46
46
  export declare function parseEnvironmentNeedsMetadata(value: unknown): EnvironmentNeedsMetadata;
47
47
  export declare function rustToolchainEnvironmentNeed(owner: ComponentOwner): RustToolchainEnvironmentNeed;
48
48
  export declare function dockerEngineEnvironmentNeed(): DockerEngineEnvironmentNeed;
49
- export declare const qualityTaskVocabulary: readonly ["format:check", "lint", "typecheck", "build", "test", "test:e2e"];
50
- export declare function renderTurboRunCommand(taskNames: readonly string[], args?: readonly string[], options?: {
51
- readonly outputLogs?: "errors-only" | "full";
52
- readonly continueAfterFailure?: boolean;
53
- readonly taskPrefix?: boolean;
54
- }): string;
55
- export declare function renderRootCheckCommand(additionalTasks?: readonly string[]): string;
56
- export declare function renderDeploymentCheckCommand(): string;
57
- export declare function renderFixCommand(): string;
58
49
  export declare function playwrightBrowserAssetsEnvironmentNeed(options: {
59
50
  readonly browser: "chromium";
60
51
  readonly owner: ComponentOwner;
@@ -152,46 +152,6 @@ export function rustToolchainEnvironmentNeed(owner) {
152
152
  export function dockerEngineEnvironmentNeed() {
153
153
  return { kind: "docker-engine" };
154
154
  }
155
- export const qualityTaskVocabulary = [
156
- "format:check",
157
- "lint",
158
- "typecheck",
159
- "build",
160
- "test",
161
- "test:e2e",
162
- ];
163
- export function renderTurboRunCommand(taskNames, args = [], options = {}) {
164
- return [
165
- "turbo run",
166
- ...taskNames,
167
- ...args,
168
- ...(options.continueAfterFailure
169
- ? ["--continue=dependencies-successful"]
170
- : []),
171
- `--output-logs=${options.outputLogs ?? "errors-only"}`,
172
- "--log-order=grouped",
173
- ...(options.taskPrefix ? ["--log-prefix=task"] : []),
174
- ].join(" ");
175
- }
176
- export function renderRootCheckCommand(additionalTasks = []) {
177
- return [
178
- "pnpm run boundaries",
179
- renderTurboRunCommand([...qualityTaskVocabulary, ...additionalTasks], [], {
180
- continueAfterFailure: true,
181
- taskPrefix: true,
182
- }),
183
- ].join(" && ");
184
- }
185
- export function renderDeploymentCheckCommand() {
186
- return renderTurboRunCommand(["deployment"], [], { taskPrefix: true });
187
- }
188
- export function renderFixCommand() {
189
- return renderTurboRunCommand(["lint:fix", "format:write"], [], {
190
- continueAfterFailure: true,
191
- outputLogs: "full",
192
- taskPrefix: true,
193
- });
194
- }
195
155
  export function playwrightBrowserAssetsEnvironmentNeed(options) {
196
156
  return {
197
157
  kind: "playwright-browser-assets",
@@ -80,9 +80,9 @@ export type PackageContribution = {
80
80
  /** Closed native CI evidence owned by this Package Boundary. */
81
81
  readonly ciDiagnosticArtifacts?: readonly CiDiagnosticArtifactDeclaration[];
82
82
  };
83
- /** Validates the portable executable name promised by a CLI Package Boundary. */
83
+ /** 校验 CLI 命令名的格式及工作区内是否重名。 */
84
84
  export declare function validateCliCommandName(commandName: string, occupiedCommandNames?: readonly string[]): string;
85
- /** Validates command portability and uniqueness across one complete plan. */
85
+ /** 校验完整生成计划中的命令名格式和唯一性。 */
86
86
  export declare function assertPackageContributionCommandNames(contributions: readonly PackageContribution[]): readonly PackageContribution[];
87
87
  export declare function assertPackageContribution(contribution: PackageContribution, provenance?: {
88
88
  readonly definitionName?: string;
@@ -6,46 +6,7 @@ const operationPath = (operation) => {
6
6
  return operation.path;
7
7
  return "";
8
8
  };
9
- const reservedSystemToolNames = new Set([
10
- "aux",
11
- "bash",
12
- "bun",
13
- "cmd",
14
- "com1",
15
- "com2",
16
- "com3",
17
- "com4",
18
- "com5",
19
- "com6",
20
- "com7",
21
- "com8",
22
- "com9",
23
- "con",
24
- "corepack",
25
- "deno",
26
- "git",
27
- "lpt1",
28
- "lpt2",
29
- "lpt3",
30
- "lpt4",
31
- "lpt5",
32
- "lpt6",
33
- "lpt7",
34
- "lpt8",
35
- "lpt9",
36
- "node",
37
- "nul",
38
- "npm",
39
- "npx",
40
- "pnpm",
41
- "powershell",
42
- "prn",
43
- "pwsh",
44
- "sh",
45
- "yarn",
46
- "zsh",
47
- ]);
48
- /** Validates the portable executable name promised by a CLI Package Boundary. */
9
+ /** 校验 CLI 命令名的格式及工作区内是否重名。 */
49
10
  export function validateCliCommandName(commandName, occupiedCommandNames = []) {
50
11
  if (/[/\\]/u.test(commandName)) {
51
12
  throw new Error(`CLI command name must not be a path; received ${JSON.stringify(commandName)}`);
@@ -62,9 +23,6 @@ export function validateCliCommandName(commandName, occupiedCommandNames = []) {
62
23
  if (!/^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/u.test(commandName)) {
63
24
  throw new Error(`CLI command name must use lowercase ASCII letters, digits, and single hyphens; received ${JSON.stringify(commandName)}`);
64
25
  }
65
- if (reservedSystemToolNames.has(commandName)) {
66
- throw new Error(`CLI command name is a reserved system tool; received ${JSON.stringify(commandName)}`);
67
- }
68
26
  if (occupiedCommandNames.includes(commandName)) {
69
27
  throw new Error(`CLI command name is already used by another workspace package; received ${JSON.stringify(commandName)}`);
70
28
  }
@@ -77,7 +35,7 @@ function manifestBinEntries(contribution) {
77
35
  }
78
36
  return Object.entries(bin);
79
37
  }
80
- /** Validates command portability and uniqueness across one complete plan. */
38
+ /** 校验完整生成计划中的命令名格式和唯一性。 */
81
39
  export function assertPackageContributionCommandNames(contributions) {
82
40
  const commandOwner = new Map();
83
41
  for (const contribution of contributions) {
@@ -26,6 +26,7 @@ catalog:
26
26
  "@devcontainers/cli": 0.89.0
27
27
  "@hono/node-server": ^2.0.12
28
28
  "@playwright/test": 1.64.0
29
+ "@vitest/browser-playwright": ^5.0.0
29
30
  "@tailwindcss/vite": ^4.3.3
30
31
  "@types/node": ^24.13.3
31
32
  "@types/web-bluetooth": ^0.0.21
@@ -48,6 +49,7 @@ catalog:
48
49
  spdx-expression-parse: ^5.0.0
49
50
  "@types/spdx-expression-parse": ^4.0.0
50
51
  pinia: ^4.0.2
52
+ playwright: 1.64.0
51
53
  srvx: ^1.0.0
52
54
  tailwindcss: ^4.3.3
53
55
  tar: ^7.5.22
@@ -60,6 +62,7 @@ catalog:
60
62
  vike: ^0.4.260
61
63
  vike-vue: ^0.9.12
62
64
  vitest: ^5.0.0
65
+ vitest-browser-vue: ^3.1.0
63
66
  vue: ^3.5.40
64
67
  vue-tsc: ^3.3.9
65
68
  yaml: ^2.9.0
@@ -33,10 +33,14 @@ export function projectCheckWorkflowTemplateReplacements(options) {
33
33
  });
34
34
  if (declarations.length === 0)
35
35
  return {};
36
+ const ownerPaths = (kind) => declarations
37
+ .filter((declaration) => declaration.kind === kind)
38
+ .map((declaration) => declaration.owner.path)
39
+ .toSorted()
40
+ .join("\n ");
36
41
  return {
37
- DIAGNOSTIC_OWNER_PATHS: declarations
38
- .map((declaration) => declaration.owner.path)
39
- .join("\n "),
42
+ PLAYWRIGHT_DIAGNOSTIC_OWNER_PATHS: ownerPaths("playwright"),
43
+ VITEST_BROWSER_DIAGNOSTIC_OWNER_PATHS: ownerPaths("vitest-browser"),
40
44
  };
41
45
  }
42
46
  export function projectDependabotConfig(policy) {
@@ -47,6 +47,7 @@ export type MergeJsonTemplateOperation = {
47
47
  from: string;
48
48
  to: string;
49
49
  source: TemplateSourceHandle;
50
+ replacements?: Record<string, string>;
50
51
  multilineArrays?: string[];
51
52
  keyOrder?: readonly string[];
52
53
  nestedKeyOrder?: readonly string[];
@@ -124,13 +124,17 @@ async function renderMergeJson(operation, options) {
124
124
  }
125
125
  async function renderMergeJsonTemplate(operation, options) {
126
126
  const sourcePath = resolveTemplateSource(operation.source, operation.from);
127
+ const sourceText = await readFile(sourcePath, "utf8");
127
128
  let patch;
128
129
  try {
129
- patch = JSON.parse(await readFile(sourcePath, "utf8"));
130
+ patch = JSON.parse(sourceText);
130
131
  }
131
132
  catch (error) {
132
133
  throw new Error(`Invalid JSON Template Source ${operation.from}: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
133
134
  }
135
+ if (operation.replacements !== undefined) {
136
+ patch = replaceJsonTemplateVariables(patch, operation.replacements);
137
+ }
134
138
  await mergeJsonIntoFile({
135
139
  options,
136
140
  patch,
@@ -140,6 +144,40 @@ async function renderMergeJsonTemplate(operation, options) {
140
144
  nestedKeyOrder: operation.nestedKeyOrder,
141
145
  });
142
146
  }
147
+ function replaceJsonTemplateVariables(value, replacements) {
148
+ const used = new Set();
149
+ const replaceString = (source) => source.replaceAll(/\{\{([A-Za-z][A-Za-z0-9_]*)\}\}/g, (_placeholder, name) => {
150
+ const replacement = replacements[name];
151
+ if (replacement === undefined) {
152
+ throw new Error(`JSON 模板缺少变量:${name}`);
153
+ }
154
+ used.add(name);
155
+ return replacement;
156
+ });
157
+ const visit = (current) => {
158
+ if (typeof current === "string") {
159
+ return replaceString(current);
160
+ }
161
+ if (Array.isArray(current)) {
162
+ return current.map(visit);
163
+ }
164
+ if (typeof current === "object" && current !== null) {
165
+ const entries = Object.entries(current).map(([key, nestedValue]) => [replaceString(key), visit(nestedValue)]);
166
+ if (new Set(entries.map(([key]) => key)).size !== entries.length) {
167
+ throw new Error("JSON 模板变量替换后产生重复对象键");
168
+ }
169
+ return Object.fromEntries(entries);
170
+ }
171
+ return current;
172
+ };
173
+ const rendered = visit(value);
174
+ for (const name of Object.keys(replacements)) {
175
+ if (!used.has(name)) {
176
+ throw new Error(`JSON 模板替换项未被使用:${name}`);
177
+ }
178
+ }
179
+ return rendered;
180
+ }
143
181
  async function mergeJsonIntoFile(options) {
144
182
  const to = resolveContainedPath(options.options.targetRoot, options.toPath);
145
183
  let existing = {};
@@ -612,14 +612,20 @@ const workflowTemplateVariants = new Map([
612
612
  ".github/workflows/check-diagnostics.yml",
613
613
  {
614
614
  operationKind: "writeTextTemplate",
615
- replacementKeys: ["DIAGNOSTIC_OWNER_PATHS"],
615
+ replacementKeys: [
616
+ "PLAYWRIGHT_DIAGNOSTIC_OWNER_PATHS",
617
+ "VITEST_BROWSER_DIAGNOSTIC_OWNER_PATHS",
618
+ ],
616
619
  },
617
620
  ],
618
621
  [
619
622
  ".github/workflows/check-deployment-diagnostics.yml",
620
623
  {
621
624
  operationKind: "writeTextTemplate",
622
- replacementKeys: ["DIAGNOSTIC_OWNER_PATHS"],
625
+ replacementKeys: [
626
+ "PLAYWRIGHT_DIAGNOSTIC_OWNER_PATHS",
627
+ "VITEST_BROWSER_DIAGNOSTIC_OWNER_PATHS",
628
+ ],
623
629
  },
624
630
  ],
625
631
  ]);
@@ -650,20 +656,25 @@ function isSafePackageBoundaryPath(value) {
650
656
  function expectedDiagnosticOwnerPaths(options) {
651
657
  const blueprintPackagePaths = options.blueprint.packages.map((packageDefinition) => packageDefinition.path);
652
658
  if (!blueprintPackagePaths.every(isSafePackageBoundaryPath)) {
653
- return { valid: false, value: "" };
659
+ return { valid: false, playwright: "", vitestBrowser: "" };
654
660
  }
655
661
  const blueprintOwners = new Set(blueprintPackagePaths);
656
- const owners = new Set();
662
+ const owners = {
663
+ playwright: new Set(),
664
+ "vitest-browser": new Set(),
665
+ };
657
666
  for (const declaration of options.diagnosticArtifactDeclarations) {
658
667
  if (!isRecord(declaration) ||
659
668
  !hasExactKeys(declaration, ["kind", "owner"])) {
660
- return { valid: false, value: "" };
669
+ return { valid: false, playwright: "", vitestBrowser: "" };
661
670
  }
662
- if (declaration.kind !== "playwright" || !isRecord(declaration.owner)) {
663
- return { valid: false, value: "" };
671
+ if ((declaration.kind !== "playwright" &&
672
+ declaration.kind !== "vitest-browser") ||
673
+ !isRecord(declaration.owner)) {
674
+ return { valid: false, playwright: "", vitestBrowser: "" };
664
675
  }
665
676
  if (!hasExactKeys(declaration.owner, ["kind", "path"])) {
666
- return { valid: false, value: "" };
677
+ return { valid: false, playwright: "", vitestBrowser: "" };
667
678
  }
668
679
  const ownerPath = declaration.owner.path;
669
680
  const workspaceOwner = declaration.owner.kind === "workspace-orchestration" && ownerPath === ".";
@@ -672,13 +683,16 @@ function expectedDiagnosticOwnerPaths(options) {
672
683
  isSafePackageBoundaryPath(ownerPath) &&
673
684
  blueprintOwners.has(ownerPath);
674
685
  if (!workspaceOwner && !packageOwner) {
675
- return { valid: false, value: "" };
686
+ return { valid: false, playwright: "", vitestBrowser: "" };
676
687
  }
677
- owners.add(ownerPath);
688
+ owners[declaration.kind].add(ownerPath);
678
689
  }
679
690
  return {
680
691
  valid: true,
681
- value: [...owners].toSorted().join("\n "),
692
+ playwright: [...owners.playwright].toSorted().join("\n "),
693
+ vitestBrowser: [...owners["vitest-browser"]]
694
+ .toSorted()
695
+ .join("\n "),
682
696
  };
683
697
  }
684
698
  function sourceFileForWorkflowOperation(options) {
@@ -723,21 +737,25 @@ async function protectedWorkflowProjectionViolations(plans) {
723
737
  : undefined;
724
738
  const replacementValid = operation?.kind === "writeTextTemplate" &&
725
739
  hasExactReplacementKeys(operation.replacements, [
726
- "DIAGNOSTIC_OWNER_PATHS",
740
+ "PLAYWRIGHT_DIAGNOSTIC_OWNER_PATHS",
741
+ "VITEST_BROWSER_DIAGNOSTIC_OWNER_PATHS",
727
742
  ]) &&
728
- operation.replacements.DIAGNOSTIC_OWNER_PATHS ===
729
- expectedDiagnosticOwners.value;
743
+ operation.replacements.PLAYWRIGHT_DIAGNOSTIC_OWNER_PATHS ===
744
+ expectedDiagnosticOwners.playwright &&
745
+ operation.replacements.VITEST_BROWSER_DIAGNOSTIC_OWNER_PATHS ===
746
+ expectedDiagnosticOwners.vitestBrowser;
730
747
  const sourceBackedExactlyOnce = matchingOperations.length === 1 &&
731
748
  operation !== undefined &&
732
749
  (operation.kind === "copyFile" || operation.kind === "writeTextTemplate");
733
- const diagnosticsExpected = expectedDiagnosticOwners.value !== "";
750
+ const diagnosticsExpected = expectedDiagnosticOwners.playwright !== "" ||
751
+ expectedDiagnosticOwners.vitestBrowser !== "";
734
752
  const operationValid = expectedDiagnosticOwners.valid &&
735
753
  sourceBackedExactlyOnce &&
736
754
  variant !== undefined &&
737
755
  operation?.kind === variant.operationKind &&
738
756
  (operation.kind === "copyFile"
739
757
  ? variant.replacementKeys.length === 0 && !diagnosticsExpected
740
- : variant.replacementKeys.length === 1 &&
758
+ : variant.replacementKeys.length === 2 &&
741
759
  diagnosticsExpected &&
742
760
  replacementValid);
743
761
  if (operationValid)
@@ -36,10 +36,5 @@
36
36
  },
37
37
  "peerDependencies": {
38
38
  "typescript": ">=6 <7"
39
- },
40
- "turbo": {
41
- "tags": [
42
- "template-core"
43
- ]
44
39
  }
45
40
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ykdz/template",
3
- "version": "0.0.41",
3
+ "version": "0.0.42",
4
4
  "private": false,
5
5
  "description": "Project template generator for YKDZ starter projects.",
6
6
  "keywords": [
@@ -67,8 +67,7 @@
67
67
  "oxfmt": "^0.71.0",
68
68
  "oxlint": "^1.77.0",
69
69
  "oxlint-tsgolint": "^7.0.2001",
70
- "typescript-7": "npm:typescript@^7.0.2",
71
- "vitest": "^5.0.0"
70
+ "typescript-7": "npm:typescript@^7.0.2"
72
71
  },
73
72
  "bundleDependencies": [
74
73
  "@valibot/to-json-schema",
@@ -88,11 +87,6 @@
88
87
  "engines": {
89
88
  "node": "^24.21.0"
90
89
  },
91
- "turbo": {
92
- "tags": [
93
- "template-cli"
94
- ]
95
- },
96
90
  "scripts": {
97
91
  "build": "rm -rf dist && tsc -p tsconfig.build.json",
98
92
  "format:check": "oxfmt --list-different --config ../../oxfmt.config.ts .",
@@ -100,8 +94,8 @@
100
94
  "lint": "oxlint --quiet --format=unix --config ../../oxlint.config.ts --ignore-pattern dist .",
101
95
  "lint:fix": "oxlint --format=unix --config ../../oxlint.config.ts --ignore-pattern dist . --fix",
102
96
  "pack:bundled": "pnpm --config.node-linker=hoisted pack",
103
- "publish:bundled": "pnpm --config.node-linker=hoisted publish",
104
- "test": "vitest run --config vitest.config.ts test/unit test/integration --reporter=verbose",
97
+ "test": "node --conditions=source --experimental-strip-types --test --test-concurrency=2 --test-timeout=60000 --test-reporter=spec --test-reporter=@ykdz/template-builtin-presets/node-test-count-reporter --test-reporter-destination=stdout --test-reporter-destination=stderr 'test/**/*.light.test.ts'",
98
+ "test:integration": "node --conditions=source --experimental-strip-types --test --test-concurrency=1 --test-timeout=300000 --test-reporter=spec --test-reporter=@ykdz/template-builtin-presets/node-test-count-reporter --test-reporter-destination=stdout --test-reporter-destination=stderr 'test/**/*.integration.test.ts'",
105
99
  "test:e2e": "node --conditions=source test/e2e/check-source-and-distribution.ts",
106
100
  "typecheck": "tsc -p tsconfig.json --noEmit --pretty false"
107
101
  }
@@ -1,23 +0,0 @@
1
- name: Check
2
-
3
- on:
4
- pull_request:
5
- push:
6
- branches:
7
- - main
8
-
9
- jobs:
10
- check:
11
- runs-on: ubuntu-latest
12
- steps:
13
- - uses: actions/checkout@v7
14
- - uses: actions/setup-node@v7
15
- with:
16
- node-version-file: package.json
17
- - run: corepack enable
18
- - uses: dtolnay/rust-toolchain@stable
19
- with:
20
- components: rustfmt, clippy
21
- - uses: Swatinem/rust-cache@v2
22
- - run: pnpm install
23
- - run: pnpm run check
@@ -1,19 +0,0 @@
1
- name: Check
2
-
3
- on:
4
- pull_request:
5
- push:
6
- branches:
7
- - main
8
-
9
- jobs:
10
- check:
11
- runs-on: ubuntu-latest
12
- steps:
13
- - uses: actions/checkout@v7
14
- - uses: actions/setup-node@v7
15
- with:
16
- node-version-file: package.json
17
- - run: corepack enable
18
- - run: pnpm install
19
- - run: pnpm run check
@@ -1,20 +0,0 @@
1
- name: Check
2
-
3
- on:
4
- pull_request:
5
- push:
6
- branches:
7
- - main
8
-
9
- jobs:
10
- check:
11
- runs-on: ubuntu-latest
12
- steps:
13
- - uses: actions/checkout@v7
14
- - uses: actions/setup-node@v7
15
- with:
16
- node-version-file: package.json
17
- - run: corepack enable
18
- - run: pnpm install
19
- - run: pnpm --filter ./apps/web exec playwright install --with-deps chromium
20
- - run: pnpm run check
@@ -1,8 +0,0 @@
1
- import { defineConfig } from "vitest/config";
2
-
3
- export default defineConfig({
4
- test: {
5
- exclude: ["test/e2e/**", "node_modules/**", "dist/**"],
6
- globals: true,
7
- },
8
- });
@@ -1,15 +0,0 @@
1
- import { defineConfig } from "vitest/config";
2
-
3
- export default defineConfig({
4
- resolve: {
5
- conditions: ["source"],
6
- },
7
- ssr: {
8
- resolve: {
9
- conditions: ["source"],
10
- },
11
- },
12
- test: {
13
- globals: true,
14
- },
15
- });
@@ -1,10 +0,0 @@
1
- import vue from "@vitejs/plugin-vue";
2
- import { defineConfig } from "vitest/config";
3
-
4
- export default defineConfig({
5
- plugins: [vue()],
6
- test: {
7
- exclude: ["test/e2e/**", "node_modules/**", "dist/**"],
8
- globals: true,
9
- },
10
- });