@ykdz/template 0.0.33 → 0.0.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/dist/application.d.ts +2 -1
  2. package/dist/application.js +64 -75
  3. package/dist/main.js +6 -2
  4. package/node_modules/@ykdz/template-builtin-presets/dist/src/foundation.d.ts +50 -36
  5. package/node_modules/@ykdz/template-builtin-presets/dist/src/foundation.js +970 -365
  6. package/node_modules/@ykdz/template-builtin-presets/dist/src/generation-record.d.ts +24 -0
  7. package/node_modules/@ykdz/template-builtin-presets/dist/src/generation-record.js +154 -0
  8. package/node_modules/@ykdz/template-builtin-presets/dist/src/index.d.ts +2 -2
  9. package/node_modules/@ykdz/template-builtin-presets/dist/src/index.js +1 -1
  10. package/node_modules/@ykdz/template-builtin-presets/dist/src/rust-bin/definition.d.ts +31 -2
  11. package/node_modules/@ykdz/template-builtin-presets/dist/src/rust-bin/definition.js +29 -33
  12. package/node_modules/@ykdz/template-builtin-presets/dist/src/shared/development-container.d.ts +1 -0
  13. package/node_modules/@ykdz/template-builtin-presets/dist/src/shared/development-container.js +17 -0
  14. package/node_modules/@ykdz/template-builtin-presets/dist/src/shared/typescript.d.ts +4 -3
  15. package/node_modules/@ykdz/template-builtin-presets/dist/src/shared/typescript.js +9 -5
  16. package/node_modules/@ykdz/template-builtin-presets/dist/src/shared/vue.d.ts +1 -1
  17. package/node_modules/@ykdz/template-builtin-presets/dist/src/shared/vue.js +1 -2
  18. package/node_modules/@ykdz/template-builtin-presets/dist/src/ts-cli/definition.d.ts +31 -2
  19. package/node_modules/@ykdz/template-builtin-presets/dist/src/ts-cli/definition.js +79 -58
  20. package/node_modules/@ykdz/template-builtin-presets/dist/src/ts-lib/definition.d.ts +31 -2
  21. package/node_modules/@ykdz/template-builtin-presets/dist/src/ts-lib/definition.js +31 -23
  22. package/node_modules/@ykdz/template-builtin-presets/dist/src/vike-app/definition.d.ts +22 -2
  23. package/node_modules/@ykdz/template-builtin-presets/dist/src/vike-app/definition.js +61 -35
  24. package/node_modules/@ykdz/template-builtin-presets/dist/src/vue-app/definition.d.ts +26 -2
  25. package/node_modules/@ykdz/template-builtin-presets/dist/src/vue-app/definition.js +19 -8
  26. package/node_modules/@ykdz/template-builtin-presets/dist/src/vue-hono-app/definition.d.ts +22 -2
  27. package/node_modules/@ykdz/template-builtin-presets/dist/src/vue-hono-app/definition.js +31 -21
  28. package/node_modules/@ykdz/template-builtin-presets/package.json +12 -11
  29. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/.github/workflows/check-deployment-diagnostics.yml +1 -1
  30. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/.github/workflows/check-deployment.yml +1 -1
  31. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/.pnpmfile.mjs +19 -0
  32. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/gitignore +1 -0
  33. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/tsconfig.packing-hook.json +8 -0
  34. package/node_modules/@ykdz/template-builtin-presets/templates/shared/devcontainer/github-cli.Dockerfile +9 -0
  35. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/CHANGELOG.md.template +17 -0
  36. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/RELEASING.md +17 -0
  37. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/artifact.ts +1271 -0
  38. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/changelog.ts +283 -0
  39. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/check-artifact.ts +99 -0
  40. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/check-readiness.ts +66 -0
  41. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/cli-command-identity.ts +4 -0
  42. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/handoff.ts +450 -0
  43. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/publish.ts +483 -0
  44. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/readiness.ts +1125 -0
  45. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/release.ts +819 -0
  46. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/release.yml +119 -0
  47. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/root-tsconfig.json +13 -0
  48. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/tsconfig.json +4 -0
  49. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/turbo.json +6 -0
  50. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication-setup/README.md +48 -0
  51. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication-setup/assets/CHANGELOG.md.template +17 -0
  52. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication-setup/assets/LICENSE-APACHE-2.0.txt +202 -0
  53. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication-setup/assets/LICENSE-MIT.txt +21 -0
  54. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication-setup/assets/README.md.template +5 -0
  55. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication-setup/bridge.ts +3336 -0
  56. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication-setup/setup.sh +221 -0
  57. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/src/cli-command-identity.ts +133 -0
  58. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/src/cli.ts +4 -3
  59. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/src/main.ts +5 -4
  60. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/test/integration/command.test.ts +14 -13
  61. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/test/unit/cli-command-identity.test.ts +76 -0
  62. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/tsconfig.build.json +2 -0
  63. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/db/src/readiness.ts +1 -1
  64. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/db/test/global-setup.ts +21 -0
  65. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/db/tsconfig.json +6 -1
  66. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/db/vitest.config.ts +7 -0
  67. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/db-migrations/drizzle.config.ts +5 -1
  68. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/web/playwright.config.ts +102 -22
  69. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/web/test/playwright-teardown.ts +12 -0
  70. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/web/vite.config.ts +39 -1
  71. package/node_modules/@ykdz/template-builtin-presets/templates/vue-app/playwright.config.ts +48 -7
  72. package/node_modules/@ykdz/template-builtin-presets/templates/vue-hono-app/web/playwright.config.ts +59 -8
  73. package/node_modules/@ykdz/template-core/dist/module-graph.d.ts +15 -53
  74. package/node_modules/@ykdz/template-core/dist/module-graph.js +134 -101
  75. package/node_modules/@ykdz/template-core/dist/package-contribution.d.ts +13 -1
  76. package/node_modules/@ykdz/template-core/dist/package-contribution.js +92 -0
  77. package/node_modules/@ykdz/template-core/dist/pnpm-workspace.yaml +14 -10
  78. package/node_modules/@ykdz/template-core/dist/preset-definition.d.ts +71 -13
  79. package/node_modules/@ykdz/template-core/dist/preset-definition.js +16 -1
  80. package/node_modules/@ykdz/template-core/dist/project-blueprint.d.ts +56 -0
  81. package/node_modules/@ykdz/template-core/dist/project-blueprint.js +271 -0
  82. package/node_modules/@ykdz/template-core/dist/project-linking-v2.d.ts +2 -2
  83. package/node_modules/@ykdz/template-core/dist/project-linking-v2.js +2 -2
  84. package/node_modules/@ykdz/template-core/dist/project-projection.d.ts +2 -1
  85. package/node_modules/@ykdz/template-core/dist/project-projection.js +107 -20
  86. package/node_modules/@ykdz/template-core/dist/renderer.d.ts +0 -2
  87. package/node_modules/@ykdz/template-core/dist/renderer.js +17 -38
  88. package/node_modules/@ykdz/template-core/dist/template-boundary-check.d.ts +2 -2
  89. package/node_modules/@ykdz/template-core/dist/template-boundary-check.js +6 -0
  90. package/node_modules/@ykdz/template-core/dist/toolchain-resolution.d.ts +2 -0
  91. package/node_modules/@ykdz/template-core/dist/toolchain-resolution.js +9 -3
  92. package/package.json +3 -3
  93. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/db-migrations/scripts/prepare-database.ts +0 -45
  94. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/web/scripts/run-playwright.ts +0 -151
  95. package/node_modules/@ykdz/template-builtin-presets/templates/vue-app/scripts/run-playwright.ts +0 -62
  96. package/node_modules/@ykdz/template-builtin-presets/templates/vue-hono-app/web/scripts/run-playwright.ts +0 -103
  97. package/node_modules/@ykdz/template-core/dist/project-blueprint-v2.d.ts +0 -33
  98. package/node_modules/@ykdz/template-core/dist/project-blueprint-v2.js +0 -182
@@ -2,7 +2,7 @@ export const nodeReleaseIndexUrl = "https://nodejs.org/dist/index.json";
2
2
  export const pnpmRegistryUrl = "https://registry.npmjs.org/pnpm";
3
3
  const bundledFallbackToolchain = {
4
4
  nodeLtsMajor: nodeLtsMajor("24"),
5
- packageManagerPin: packageManagerPin("11.11.0"),
5
+ packageManagerPin: packageManagerPin("11.21.0"),
6
6
  };
7
7
  export async function resolveToolchainVersions(options = {}) {
8
8
  const source = options.source ?? "online";
@@ -66,14 +66,20 @@ function fallbackResult(diagnostics) {
66
66
  diagnostics,
67
67
  };
68
68
  }
69
+ export function isValidNodeLtsMajor(value) {
70
+ return /^\d+$/.test(value);
71
+ }
72
+ export function isValidPackageManagerPin(value) {
73
+ return /^pnpm@\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$/.test(value);
74
+ }
69
75
  function nodeLtsMajor(value) {
70
- if (!/^\d+$/.test(value)) {
76
+ if (!isValidNodeLtsMajor(value)) {
71
77
  throw new Error(`Invalid Node LTS major: ${value}`);
72
78
  }
73
79
  return { kind: "NodeLtsMajor", value };
74
80
  }
75
81
  function packageManagerPin(version) {
76
- if (!/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$/.test(version)) {
82
+ if (!isValidPackageManagerPin(`pnpm@${version}`)) {
77
83
  throw new Error(`Invalid pnpm version: ${version}`);
78
84
  }
79
85
  return { kind: "PackageManagerPin", value: `pnpm@${version}` };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ykdz/template",
3
- "version": "0.0.33",
3
+ "version": "0.0.36",
4
4
  "private": false,
5
5
  "description": "Project template generator for YKDZ starter projects.",
6
6
  "keywords": [
@@ -67,9 +67,9 @@
67
67
  "@types/node": "^24.13.3",
68
68
  "@ykdz/template-builtin-presets-source": "link:../builtin-presets",
69
69
  "@ykdz/template-core-source": "link:../core",
70
- "execa": "^10.0.0",
70
+ "execa": "^10.0.1",
71
71
  "oxfmt": "^0.58.0",
72
- "oxlint": "^1.73.0",
72
+ "oxlint": "^1.77.0",
73
73
  "oxlint-tsgolint": "^7.0.2001",
74
74
  "typescript-7": "npm:typescript@^7.0.2",
75
75
  "vitest": "^4.1.10"
@@ -1,45 +0,0 @@
1
- import { execFileSync } from "node:child_process";
2
- import { mkdirSync, rmSync } from "node:fs";
3
- import path from "node:path";
4
-
5
- const mode = process.argv[2];
6
-
7
- if (mode !== "dev" && mode !== "test") {
8
- throw new Error("Usage: node scripts/prepare-database.ts <dev|test>");
9
- }
10
-
11
- const packageDirectory = process.cwd();
12
- const databaseFile = process.env.DATABASE_FILE
13
- ? path.resolve(
14
- process.env.INIT_CWD ?? packageDirectory,
15
- process.env.DATABASE_FILE,
16
- )
17
- : path.resolve(packageDirectory, "../../apps/web/data/app.sqlite");
18
- const environment = { ...process.env, DATABASE_FILE: databaseFile };
19
-
20
- mkdirSync(path.dirname(databaseFile), { recursive: true });
21
- if (mode === "test") {
22
- rmSync(databaseFile, { force: true });
23
- }
24
-
25
- execFileSync("pnpm", ["run", "db:push"], {
26
- cwd: packageDirectory,
27
- env: environment,
28
- stdio: "inherit",
29
- });
30
- const databasePackageName = process.env.DATABASE_PACKAGE_NAME;
31
- if (!databasePackageName) {
32
- throw new Error(
33
- "DATABASE_PACKAGE_NAME must name the database Package Boundary",
34
- );
35
- }
36
-
37
- execFileSync(
38
- "pnpm",
39
- ["--filter", databasePackageName, "run", "db:seed:example"],
40
- {
41
- cwd: packageDirectory,
42
- env: environment,
43
- stdio: "inherit",
44
- },
45
- );
@@ -1,151 +0,0 @@
1
- import { spawn } from "node:child_process";
2
- import { mkdir, rm } from "node:fs/promises";
3
- import { createServer } from "node:net";
4
- import path from "node:path";
5
- import { fileURLToPath } from "node:url";
6
-
7
- const databaseFile = fileURLToPath(
8
- new URL("../node_modules/.tmp/e2e.sqlite", import.meta.url),
9
- );
10
- const externalBaseUrlName = "PLAYWRIGHT_EXTERNAL_BASE_URL";
11
- const externalReadinessTimeoutMs = 30_000;
12
-
13
- function externalBaseUrl(): string | undefined {
14
- if (!Object.hasOwn(process.env, externalBaseUrlName)) {
15
- return undefined;
16
- }
17
-
18
- const value = process.env[externalBaseUrlName]?.trim();
19
- if (!value) {
20
- throw new Error(`${externalBaseUrlName} must be a non-empty HTTP(S) URL`);
21
- }
22
-
23
- let url: URL;
24
- try {
25
- url = new URL(value);
26
- } catch {
27
- throw new Error(`${externalBaseUrlName} must be a valid HTTP(S) URL`);
28
- }
29
-
30
- if (url.protocol !== "http:" && url.protocol !== "https:") {
31
- throw new Error(`${externalBaseUrlName} must use HTTP or HTTPS`);
32
- }
33
-
34
- return url.toString();
35
- }
36
-
37
- async function availablePort(): Promise<string> {
38
- return await new Promise((resolve, reject) => {
39
- const server = createServer();
40
-
41
- server.once("error", reject);
42
- server.listen(0, "127.0.0.1", () => {
43
- const address = server.address();
44
-
45
- if (typeof address !== "object" || address === null) {
46
- server.close(() => {
47
- reject(new Error("Could not allocate a Playwright web port"));
48
- });
49
- return;
50
- }
51
-
52
- const port = String(address.port);
53
- server.close((error) => {
54
- if (error) {
55
- reject(error);
56
- return;
57
- }
58
-
59
- resolve(port);
60
- });
61
- });
62
- });
63
- }
64
-
65
- async function awaitExternalService(baseUrl: string): Promise<void> {
66
- const deadline = Date.now() + externalReadinessTimeoutMs;
67
-
68
- while (Date.now() < deadline) {
69
- try {
70
- const response = await fetch(baseUrl, {
71
- signal: AbortSignal.timeout(2_000),
72
- });
73
- if (response.ok) {
74
- return;
75
- }
76
- } catch {
77
- // The externally managed service may still be starting.
78
- }
79
-
80
- await new Promise((resolve) => setTimeout(resolve, 250));
81
- }
82
-
83
- throw new Error(
84
- `External Playwright service at ${baseUrl} was not ready within ${externalReadinessTimeoutMs}ms`,
85
- );
86
- }
87
-
88
- async function localPlaywrightEnv(): Promise<NodeJS.ProcessEnv> {
89
- return {
90
- ...process.env,
91
- DATABASE_FILE: process.env.DATABASE_FILE ?? databaseFile,
92
- PLAYWRIGHT_WEB_PORT:
93
- process.env.PLAYWRIGHT_WEB_PORT ?? (await availablePort()),
94
- };
95
- }
96
-
97
- const externalServiceUrl = externalBaseUrl();
98
- const env = externalServiceUrl
99
- ? { ...process.env }
100
- : await localPlaywrightEnv();
101
- const localDatabaseFile = externalServiceUrl ? undefined : env.DATABASE_FILE;
102
- delete env.NO_COLOR;
103
-
104
- if (externalServiceUrl) {
105
- await awaitExternalService(externalServiceUrl);
106
- } else {
107
- await mkdir(path.dirname(localDatabaseFile!), { recursive: true });
108
- await rm(localDatabaseFile!, { force: true });
109
- }
110
-
111
- const command = process.platform === "win32" ? "playwright.cmd" : "playwright";
112
- const child = spawn(command, ["test", ...process.argv.slice(2)], {
113
- env,
114
- stdio: "inherit",
115
- });
116
-
117
- const forwardedSignals = ["SIGINT", "SIGTERM"] as const;
118
- const forwardSignal = (signal: NodeJS.Signals): void => {
119
- child.kill(signal);
120
- };
121
- for (const signal of forwardedSignals) {
122
- process.once(signal, forwardSignal);
123
- }
124
-
125
- try {
126
- const result = await new Promise<{
127
- code: number | null;
128
- signal: NodeJS.Signals | null;
129
- }>((resolve, reject) => {
130
- child.once("error", reject);
131
- child.once("exit", (code, signal) => resolve({ code, signal }));
132
- });
133
-
134
- if (result.signal) {
135
- console.error(`Playwright exited with signal ${result.signal}`);
136
- process.exitCode = 1;
137
- } else {
138
- process.exitCode = result.code ?? 1;
139
- }
140
- } catch (error) {
141
- console.error(error);
142
- process.exitCode = 1;
143
- } finally {
144
- for (const signal of forwardedSignals) {
145
- process.removeListener(signal, forwardSignal);
146
- }
147
-
148
- if (localDatabaseFile) {
149
- await rm(localDatabaseFile, { force: true });
150
- }
151
- }
@@ -1,62 +0,0 @@
1
- import { spawn } from "node:child_process";
2
- import { createServer } from "node:net";
3
-
4
- async function availablePort(): Promise<string> {
5
- return await new Promise((resolve, reject) => {
6
- const server = createServer();
7
-
8
- server.once("error", reject);
9
- server.listen(0, "127.0.0.1", () => {
10
- const address = server.address();
11
-
12
- if (typeof address !== "object" || address === null) {
13
- server.close(() => {
14
- reject(new Error("Could not allocate a Playwright web port"));
15
- });
16
- return;
17
- }
18
-
19
- const port = String(address.port);
20
- server.close((error) => {
21
- if (error) {
22
- reject(error);
23
- return;
24
- }
25
-
26
- resolve(port);
27
- });
28
- });
29
- });
30
- }
31
-
32
- async function playwrightEnv(): Promise<NodeJS.ProcessEnv> {
33
- return {
34
- ...process.env,
35
- PLAYWRIGHT_WEB_PORT:
36
- process.env.PLAYWRIGHT_WEB_PORT ?? (await availablePort()),
37
- };
38
- }
39
-
40
- const env = await playwrightEnv();
41
- delete env.NO_COLOR;
42
-
43
- const command = process.platform === "win32" ? "playwright.cmd" : "playwright";
44
- const child = spawn(command, ["test", ...process.argv.slice(2)], {
45
- env,
46
- stdio: "inherit",
47
- });
48
-
49
- child.once("error", (error: Error) => {
50
- console.error(error);
51
- process.exitCode = 1;
52
- });
53
-
54
- child.once("exit", (code: number | null, signal: NodeJS.Signals | null) => {
55
- if (signal) {
56
- console.error(`Playwright exited with signal ${signal}`);
57
- process.exitCode = 1;
58
- return;
59
- }
60
-
61
- process.exitCode = code ?? 1;
62
- });
@@ -1,103 +0,0 @@
1
- import { spawn } from "node:child_process";
2
- import { createServer } from "node:net";
3
-
4
- async function listenOnAvailablePort(): Promise<{
5
- readonly port: string;
6
- readonly server: ReturnType<typeof createServer>;
7
- }> {
8
- return await new Promise((resolve, reject) => {
9
- const server = createServer();
10
-
11
- server.once("error", reject);
12
- server.listen(0, "127.0.0.1", () => {
13
- const address = server.address();
14
-
15
- if (typeof address !== "object" || address === null) {
16
- server.close(() => {
17
- reject(new Error("Could not allocate a Playwright server port"));
18
- });
19
- return;
20
- }
21
-
22
- resolve({ port: String(address.port), server });
23
- });
24
- });
25
- }
26
-
27
- async function availablePorts(count: number): Promise<string[]> {
28
- const leases: Array<{
29
- readonly port: string;
30
- readonly server: ReturnType<typeof createServer>;
31
- }> = [];
32
-
33
- try {
34
- for (let index = 0; index < count; index += 1) {
35
- leases.push(await listenOnAvailablePort());
36
- }
37
-
38
- return leases.map((lease) => lease.port);
39
- } finally {
40
- await Promise.all(
41
- leases.map(
42
- (lease) =>
43
- new Promise<void>((resolve, reject) => {
44
- lease.server.close((error) => {
45
- if (error) {
46
- reject(error);
47
- return;
48
- }
49
-
50
- resolve();
51
- });
52
- }),
53
- ),
54
- );
55
- }
56
- }
57
-
58
- async function playwrightEnv(): Promise<NodeJS.ProcessEnv> {
59
- const missingPortNames = [
60
- process.env.PLAYWRIGHT_API_PORT === undefined
61
- ? "PLAYWRIGHT_API_PORT"
62
- : undefined,
63
- process.env.PLAYWRIGHT_WEB_PORT === undefined
64
- ? "PLAYWRIGHT_WEB_PORT"
65
- : undefined,
66
- ].filter((name) => name !== undefined);
67
- const ports = await availablePorts(missingPortNames.length);
68
- const allocatedPorts = Object.fromEntries(
69
- missingPortNames.map((name, index) => [name, ports[index]]),
70
- );
71
-
72
- return {
73
- ...process.env,
74
- PLAYWRIGHT_API_PORT:
75
- process.env.PLAYWRIGHT_API_PORT ?? allocatedPorts.PLAYWRIGHT_API_PORT,
76
- PLAYWRIGHT_WEB_PORT:
77
- process.env.PLAYWRIGHT_WEB_PORT ?? allocatedPorts.PLAYWRIGHT_WEB_PORT,
78
- };
79
- }
80
-
81
- const env = await playwrightEnv();
82
- delete env.NO_COLOR;
83
-
84
- const command = process.platform === "win32" ? "playwright.cmd" : "playwright";
85
- const child = spawn(command, ["test", ...process.argv.slice(2)], {
86
- env,
87
- stdio: "inherit",
88
- });
89
-
90
- child.once("error", (error: Error) => {
91
- console.error(error);
92
- process.exitCode = 1;
93
- });
94
-
95
- child.once("exit", (code: number | null, signal: NodeJS.Signals | null) => {
96
- if (signal) {
97
- console.error(`Playwright exited with signal ${signal}`);
98
- process.exitCode = 1;
99
- return;
100
- }
101
-
102
- process.exitCode = code ?? 1;
103
- });
@@ -1,33 +0,0 @@
1
- /**
2
- * The durable, preset-agnostic topology used by local template follow-up
3
- * operations. Preset provenance deliberately belongs in Generation Record.
4
- */
5
- export type PackageRole = "cli-tool" | "runtime-service" | "shared-library" | "native-package";
6
- export type PackageDefinition = {
7
- readonly name: string;
8
- readonly path: string;
9
- readonly role: PackageRole;
10
- };
11
- export type PackageLinkIntent = {
12
- readonly consumerPackagePath: string;
13
- readonly providerPackagePath: string;
14
- };
15
- export type ProjectBlueprintV2 = {
16
- readonly schemaVersion: 2;
17
- readonly packages: readonly PackageDefinition[];
18
- readonly packageLinkIntents?: readonly PackageLinkIntent[];
19
- };
20
- export type BlueprintV2ValidationIssue = {
21
- readonly path: string;
22
- readonly message: string;
23
- };
24
- export type BlueprintV2ValidationResult = {
25
- readonly ok: true;
26
- readonly value: ProjectBlueprintV2;
27
- } | {
28
- readonly ok: false;
29
- readonly issues: readonly BlueprintV2ValidationIssue[];
30
- };
31
- /** Validates persisted metadata before it is used to plan or render changes. */
32
- export declare function validateProjectBlueprintV2(value: unknown): BlueprintV2ValidationResult;
33
- export declare function assertProjectBlueprintV2(value: unknown): ProjectBlueprintV2;
@@ -1,182 +0,0 @@
1
- const packageName = /^@[a-z0-9][a-z0-9-]*\/[a-z0-9][a-z0-9-]*$/;
2
- const packagePath = /^[a-z0-9][a-z0-9-]*\/[a-z0-9][a-z0-9-]*$/;
3
- const reservedWorkspaceCollections = new Set([
4
- ".git",
5
- ".github",
6
- ".devcontainer",
7
- ".template",
8
- "node_modules",
9
- "dist",
10
- "target",
11
- ]);
12
- const roles = new Set([
13
- "cli-tool",
14
- "runtime-service",
15
- "shared-library",
16
- "native-package",
17
- ]);
18
- function isRecord(value) {
19
- return typeof value === "object" && value !== null && !Array.isArray(value);
20
- }
21
- function reportUnknownKeys(value, allowed, path, issues) {
22
- for (const key of Object.keys(value)) {
23
- if (!allowed.includes(key)) {
24
- issues.push({
25
- path: `${path}.${key}`,
26
- message: "Unknown Blueprint v2 field",
27
- });
28
- }
29
- }
30
- }
31
- /** Validates persisted metadata before it is used to plan or render changes. */
32
- export function validateProjectBlueprintV2(value) {
33
- const issues = [];
34
- if (!isRecord(value)) {
35
- return {
36
- ok: false,
37
- issues: [
38
- { path: ".", message: "Local Template Metadata must be an object" },
39
- ],
40
- };
41
- }
42
- reportUnknownKeys(value, ["schemaVersion", "packages", "packageLinkIntents"], ".", issues);
43
- if (value.schemaVersion !== 2) {
44
- issues.push({
45
- path: ".schemaVersion",
46
- message: `Unsupported Local Template Metadata schema version ${String(value.schemaVersion)}; expected 2`,
47
- });
48
- }
49
- if (!Array.isArray(value.packages)) {
50
- issues.push({
51
- path: ".packages",
52
- message: "Package Definitions must be an array",
53
- });
54
- }
55
- const definitions = [];
56
- if (Array.isArray(value.packages)) {
57
- for (const [index, item] of value.packages.entries()) {
58
- const itemPath = `.packages[${index}]`;
59
- if (!isRecord(item)) {
60
- issues.push({
61
- path: itemPath,
62
- message: "Package Definition must be an object",
63
- });
64
- continue;
65
- }
66
- reportUnknownKeys(item, ["name", "path", "role"], itemPath, issues);
67
- const workspaceCollection = typeof item.path === "string" ? item.path.split("/", 1)[0] : undefined;
68
- const usesReservedWorkspaceCollection = workspaceCollection !== undefined &&
69
- reservedWorkspaceCollections.has(workspaceCollection);
70
- if (typeof item.name !== "string" || !packageName.test(item.name)) {
71
- issues.push({
72
- path: `${itemPath}.name`,
73
- message: "Package name must be a scoped lowercase package name",
74
- });
75
- }
76
- if (usesReservedWorkspaceCollection) {
77
- issues.push({
78
- path: `${itemPath}.path`,
79
- message: `Package Path ${item.path} uses reserved workspace collection ${workspaceCollection}`,
80
- });
81
- }
82
- else if (typeof item.path !== "string" ||
83
- !packagePath.test(item.path)) {
84
- issues.push({
85
- path: `${itemPath}.path`,
86
- message: "Package Path must be exactly two safe path segments",
87
- });
88
- }
89
- if (typeof item.role !== "string" ||
90
- !roles.has(item.role)) {
91
- issues.push({
92
- path: `${itemPath}.role`,
93
- message: "Package Role must be cli-tool, runtime-service, shared-library, or native-package",
94
- });
95
- }
96
- if (typeof item.name === "string" &&
97
- typeof item.path === "string" &&
98
- typeof item.role === "string" &&
99
- packageName.test(item.name) &&
100
- packagePath.test(item.path) &&
101
- !usesReservedWorkspaceCollection &&
102
- roles.has(item.role)) {
103
- definitions.push(item);
104
- }
105
- }
106
- }
107
- for (const [property, label] of [
108
- ["name", "Package name"],
109
- ["path", "Package Path"],
110
- ]) {
111
- const seen = new Set();
112
- for (const definition of definitions) {
113
- const member = definition[property];
114
- if (seen.has(member))
115
- issues.push({
116
- path: ".packages",
117
- message: `${label} must be unique: ${member}`,
118
- });
119
- seen.add(member);
120
- }
121
- }
122
- if (value.packageLinkIntents !== undefined &&
123
- !Array.isArray(value.packageLinkIntents)) {
124
- issues.push({
125
- path: ".packageLinkIntents",
126
- message: "Package Link Intents must be an array",
127
- });
128
- }
129
- const paths = new Set(definitions.map((definition) => definition.path));
130
- const links = new Set();
131
- if (Array.isArray(value.packageLinkIntents)) {
132
- for (const [index, item] of value.packageLinkIntents.entries()) {
133
- const itemPath = `.packageLinkIntents[${index}]`;
134
- if (!isRecord(item)) {
135
- issues.push({
136
- path: itemPath,
137
- message: "Package Link Intent must be an object",
138
- });
139
- continue;
140
- }
141
- reportUnknownKeys(item, ["consumerPackagePath", "providerPackagePath"], itemPath, issues);
142
- const consumer = item.consumerPackagePath;
143
- const provider = item.providerPackagePath;
144
- if (typeof consumer !== "string" || !paths.has(consumer))
145
- issues.push({
146
- path: `${itemPath}.consumerPackagePath`,
147
- message: "Package Link Intent references an unknown consumer package",
148
- });
149
- if (typeof provider !== "string" || !paths.has(provider))
150
- issues.push({
151
- path: `${itemPath}.providerPackagePath`,
152
- message: "Package Link Intent references an unknown provider package",
153
- });
154
- if (consumer === provider && typeof consumer === "string")
155
- issues.push({
156
- path: itemPath,
157
- message: "Package Link Intent cannot link a package to itself",
158
- });
159
- if (typeof consumer === "string" && typeof provider === "string") {
160
- const key = `${consumer}\u0000${provider}`;
161
- if (links.has(key))
162
- issues.push({
163
- path: itemPath,
164
- message: "Package Link Intent must be unique",
165
- });
166
- links.add(key);
167
- }
168
- }
169
- }
170
- return issues.length === 0
171
- ? { ok: true, value: value }
172
- : { ok: false, issues };
173
- }
174
- export function assertProjectBlueprintV2(value) {
175
- const result = validateProjectBlueprintV2(value);
176
- if (!result.ok) {
177
- throw new Error(result.issues
178
- .map((issue) => `${issue.path}: ${issue.message}`)
179
- .join("\n"));
180
- }
181
- return result.value;
182
- }