@ykdz/template 0.0.2 → 0.0.4

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 (95) hide show
  1. package/README.md +1 -1
  2. package/dist/src/cli.d.ts +2 -0
  3. package/dist/{cli.js → src/cli.js} +91 -58
  4. package/dist/{declarations.d.ts → src/declarations.d.ts} +3 -5
  5. package/dist/{declarations.js → src/declarations.js} +48 -145
  6. package/dist/src/dependency-catalog.d.ts +18 -0
  7. package/dist/src/dependency-catalog.js +132 -0
  8. package/dist/src/devcontainer.d.ts +58 -0
  9. package/dist/src/devcontainer.js +202 -0
  10. package/dist/src/editor-customization.d.ts +12 -0
  11. package/dist/src/editor-customization.js +108 -0
  12. package/dist/{generation-context.d.ts → src/generation-context.d.ts} +2 -3
  13. package/dist/{generation-context.js → src/generation-context.js} +4 -1
  14. package/dist/src/module-graph.d.ts +34 -0
  15. package/dist/src/module-graph.js +58 -0
  16. package/dist/{next-step-instructions.d.ts → src/next-step-instructions.d.ts} +2 -4
  17. package/dist/{next-step-instructions.js → src/next-step-instructions.js} +49 -24
  18. package/dist/{package-addition.d.ts → src/package-addition.d.ts} +1 -1
  19. package/dist/src/package-addition.js +343 -0
  20. package/dist/src/preset-projection.d.ts +66 -0
  21. package/dist/src/preset-projection.js +7 -0
  22. package/dist/{project-github.d.ts → src/project-github.d.ts} +3 -9
  23. package/dist/{project-github.js → src/project-github.js} +27 -42
  24. package/dist/{renderer.d.ts → src/renderer.d.ts} +16 -2
  25. package/dist/{renderer.js → src/renderer.js} +95 -12
  26. package/dist/src/runtime-paths.d.ts +1 -0
  27. package/dist/src/runtime-paths.js +11 -0
  28. package/dist/src/template-boundary-check.d.ts +34 -0
  29. package/dist/src/template-boundary-check.js +448 -0
  30. package/dist/{toolchain-resolution.d.ts → src/toolchain-resolution.d.ts} +0 -1
  31. package/dist/{toolchain-resolution.js → src/toolchain-resolution.js} +1 -1
  32. package/dist/templates/hono-api/projection.d.ts +6 -0
  33. package/dist/templates/hono-api/projection.js +538 -0
  34. package/dist/templates/projection-plans.d.ts +7 -0
  35. package/dist/templates/projection-plans.js +94 -0
  36. package/dist/templates/registry.d.ts +7 -0
  37. package/dist/templates/registry.js +42 -0
  38. package/dist/templates/rust-bin/projection.d.ts +9 -0
  39. package/dist/templates/rust-bin/projection.js +390 -0
  40. package/dist/templates/ts-lib/projection.d.ts +6 -0
  41. package/dist/templates/ts-lib/projection.js +523 -0
  42. package/dist/templates/vue-app/projection.d.ts +6 -0
  43. package/dist/templates/vue-app/projection.js +757 -0
  44. package/dist/templates/vue-hono-app/projection.d.ts +8 -0
  45. package/dist/templates/vue-hono-app/projection.js +693 -0
  46. package/package.json +38 -28
  47. package/pnpm-workspace.yaml +35 -0
  48. package/templates/hono-api/.github/dependabot.yml +13 -0
  49. package/templates/rust-bin/.github/dependabot.yml +18 -1
  50. package/templates/rust-bin/rust-toolchain.toml +3 -0
  51. package/templates/rust-bin/rustfmt.toml +2 -0
  52. package/templates/shared/devcontainer/browser-test.Dockerfile +2 -0
  53. package/templates/shared/devcontainer/node-pnpm.Dockerfile +6 -0
  54. package/templates/shared/devcontainer/rust.Dockerfile +16 -0
  55. package/templates/shared/editor-customization/capabilities.json +56 -0
  56. package/templates/ts-lib/.github/dependabot.yml +13 -0
  57. package/templates/ts-lib/src/index.ts +5 -1
  58. package/templates/vue-app/.github/dependabot.yml +13 -0
  59. package/templates/vue-app/.github/workflows/check.yml +1 -1
  60. package/templates/vue-app/test/e2e/app.spec.ts +4 -1
  61. package/templates/vue-hono-app/.github/dependabot.yml +13 -0
  62. package/templates/vue-hono-app/web/test/e2e/app.spec.ts +4 -1
  63. package/dist/cli.d.ts +0 -3
  64. package/dist/cli.d.ts.map +0 -1
  65. package/dist/declarations.d.ts.map +0 -1
  66. package/dist/devcontainer.d.ts +0 -17
  67. package/dist/devcontainer.d.ts.map +0 -1
  68. package/dist/devcontainer.js +0 -23
  69. package/dist/generation-context.d.ts.map +0 -1
  70. package/dist/hono-api.d.ts +0 -3
  71. package/dist/hono-api.d.ts.map +0 -1
  72. package/dist/hono-api.js +0 -210
  73. package/dist/module-graph.d.ts +0 -45
  74. package/dist/module-graph.d.ts.map +0 -1
  75. package/dist/module-graph.js +0 -187
  76. package/dist/next-step-instructions.d.ts.map +0 -1
  77. package/dist/package-addition.d.ts.map +0 -1
  78. package/dist/package-addition.js +0 -560
  79. package/dist/project-github.d.ts.map +0 -1
  80. package/dist/renderer.d.ts.map +0 -1
  81. package/dist/rust-bin.d.ts +0 -8
  82. package/dist/rust-bin.d.ts.map +0 -1
  83. package/dist/rust-bin.js +0 -208
  84. package/dist/toolchain-resolution.d.ts.map +0 -1
  85. package/dist/ts-lib.d.ts +0 -8
  86. package/dist/ts-lib.d.ts.map +0 -1
  87. package/dist/ts-lib.js +0 -214
  88. package/dist/vue-app.d.ts +0 -3
  89. package/dist/vue-app.d.ts.map +0 -1
  90. package/dist/vue-app.js +0 -301
  91. package/dist/vue-hono-app.d.ts +0 -7
  92. package/dist/vue-hono-app.d.ts.map +0 -1
  93. package/dist/vue-hono-app.js +0 -440
  94. package/templates/shared/oxc/package.json +0 -18
  95. package/templates/shared/oxc/tsconfig.json +0 -11
package/README.md CHANGED
@@ -12,7 +12,7 @@ Available commands:
12
12
 
13
13
  ```sh
14
14
  template init <dir> --preset <name> --yes
15
- template add package --preset <name> --name <name>
15
+ template add package --preset <name> --name <name> [--path <package-path>]
16
16
  template presets
17
17
  template schema preset
18
18
  template schema blueprint
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -2,21 +2,17 @@
2
2
  import { readFile } from "node:fs/promises";
3
3
  import path from "node:path";
4
4
  import { createInterface } from "node:readline/promises";
5
- import { initHonoApiProject } from "./hono-api.js";
6
- import { initRustBinProject } from "./rust-bin.js";
7
- import { initTsLibProject } from "./ts-lib.js";
8
- import { initVueHonoAppProject } from "./vue-hono-app.js";
9
- import { initVueAppProject } from "./vue-app.js";
10
- import { addPackage } from "./package-addition.js";
11
- import { assembleGenerationContext } from "./generation-context.js";
12
- import { planNextStepInstructions, } from "./next-step-instructions.js";
5
+ import { findBuiltInPresetProjection, projectPresetThroughRegistry, } from "../templates/registry.js";
13
6
  import { blueprintJsonSchema, builtInPresets, presetFileJsonSchema, validatePresetFile, validateProjectBlueprint, } from "./declarations.js";
7
+ import { assembleGenerationContext, } from "./generation-context.js";
8
+ import { addPackage } from "./package-addition.js";
9
+ import { planNextStepInstructionsForProjection, } from "./preset-projection.js";
14
10
  import { resolveToolchainVersions, } from "./toolchain-resolution.js";
15
11
  function usage() {
16
12
  return [
17
13
  "Usage:",
18
14
  " template init <dir> --preset <name> --yes",
19
- " template add package --preset <name> --name <name>",
15
+ " template add package --preset <name> --name <name> [--path <package-path>]",
20
16
  " template presets",
21
17
  " template schema preset",
22
18
  " template schema blueprint",
@@ -26,6 +22,7 @@ function usage() {
26
22
  "Options:",
27
23
  " --preset <name> Project preset to generate",
28
24
  " --name <name> Package name to add",
25
+ " --path <path> Two-segment Package Path to add",
29
26
  " --scope <name> Package scope for workspace package names",
30
27
  " --yes Accept defaults for non-interactive generation",
31
28
  " --dry-run Print the planned generation without writing files",
@@ -50,7 +47,9 @@ async function readJsonDeclaration(filePath) {
50
47
  }
51
48
  }
52
49
  function formatValidationIssues(issues) {
53
- return issues.map((issue) => ` - ${issue.path}: ${issue.message}`).join("\n");
50
+ return issues
51
+ .map((issue) => ` - ${issue.path}: ${issue.message}`)
52
+ .join("\n");
54
53
  }
55
54
  function formatPresetCatalog() {
56
55
  return [
@@ -117,20 +116,31 @@ function normalizeNpmScope(value) {
117
116
  function supportedPreset(name) {
118
117
  const preset = builtInPresets.find((candidate) => candidate.name === name && candidate.generation === "supported");
119
118
  if (!preset) {
120
- throw new Error("Only the ts-lib, hono-api, vue-app, vue-hono-app, and rust-bin presets are supported in this version");
119
+ throw new Error(formatSupportedPresetError());
121
120
  }
122
121
  return preset;
123
122
  }
124
- function projectNameFromDir(targetDir) {
125
- return path.basename(path.resolve(targetDir));
123
+ function formatSupportedPresetError() {
124
+ const supportedPresetNames = builtInPresets
125
+ .filter((preset) => preset.generation === "supported")
126
+ .map((preset) => preset.name);
127
+ return `Only the ${formatList(supportedPresetNames)} presets are supported in this version`;
126
128
  }
127
- function scopeFromOptions(projectName, scope) {
128
- return scope ?? projectName;
129
+ function formatList(values) {
130
+ if (values.length <= 1) {
131
+ return values[0] ?? "";
132
+ }
133
+ return `${values.slice(0, -1).join(", ")}, and ${values.at(-1)}`;
129
134
  }
130
135
  function blueprintForInit(options) {
131
136
  const preset = supportedPreset(options.preset);
132
- const projectName = projectNameFromDir(options.dir);
133
- const packageScope = scopeFromOptions(projectName, options.scope);
137
+ const projection = findBuiltInPresetProjection(preset.name);
138
+ if (projection) {
139
+ return projection.blueprint({
140
+ targetDir: options.dir,
141
+ scope: options.scope,
142
+ });
143
+ }
134
144
  const blueprint = {
135
145
  schemaVersion: 1,
136
146
  preset: preset.name,
@@ -140,12 +150,6 @@ function blueprintForInit(options) {
140
150
  if (preset.supportedPackageManagers[0]) {
141
151
  blueprint.packageManager = preset.supportedPackageManagers[0];
142
152
  }
143
- if (preset.name === "vue-hono-app") {
144
- blueprint.packages = [
145
- { name: `@${packageScope}/web`, path: "apps/web" },
146
- { name: `@${packageScope}/api`, path: "apps/api" },
147
- ];
148
- }
149
153
  return blueprint;
150
154
  }
151
155
  function formatBlueprintSummary(targetDir, blueprint) {
@@ -167,11 +171,14 @@ function formatBlueprintSummary(targetDir, blueprint) {
167
171
  lines.push(` Features: ${blueprint.features.join(", ")}`);
168
172
  return lines.join("\n");
169
173
  }
170
- function formatNextSteps(targetDir, preset) {
171
- const plan = planNextStepInstructions({ preset, targetDir });
174
+ function formatProjectionNextSteps(targetDir, projectionPlan) {
175
+ const steps = planNextStepInstructionsForProjection({
176
+ targetDir,
177
+ plan: projectionPlan,
178
+ });
172
179
  return [
173
180
  "Next Step Instructions:",
174
- ...plan.steps.map((step) => ` ${step.label}: ${step.display}`),
181
+ ...steps.map((step) => ` ${step.label}: ${step.display}`),
175
182
  ].join("\n");
176
183
  }
177
184
  function toolchainReport(toolchain) {
@@ -199,7 +206,7 @@ function toolchainResolutionSourceFromEnv() {
199
206
  return undefined;
200
207
  }
201
208
  async function generationContextForInit(options, blueprint) {
202
- if (options.preset !== "ts-lib" && options.preset !== "rust-bin") {
209
+ if (!findBuiltInPresetProjection(options.preset)) {
203
210
  return undefined;
204
211
  }
205
212
  return assembleGenerationContext({
@@ -213,38 +220,37 @@ async function generationContextForInit(options, blueprint) {
213
220
  });
214
221
  }
215
222
  async function generateInitProject(options, generationContext) {
216
- if (options.preset === "ts-lib") {
217
- await initTsLibProject(options.dir, { generationContext });
218
- return;
219
- }
220
- if (options.preset === "hono-api") {
221
- await initHonoApiProject(options.dir);
222
- return;
223
- }
224
- if (options.preset === "vue-app") {
225
- await initVueAppProject(options.dir);
226
- return;
227
- }
228
- if (options.preset === "vue-hono-app") {
229
- await initVueHonoAppProject(options.dir, { scope: options.scope });
230
- return;
231
- }
232
- if (options.preset === "rust-bin") {
233
- await initRustBinProject(options.dir, { generationContext });
223
+ const projection = findBuiltInPresetProjection(options.preset);
224
+ if (projection) {
225
+ if (!generationContext) {
226
+ throw new Error(`Missing Generation Context for Preset Projection: ${options.preset}`);
227
+ }
228
+ const plan = projection.project(generationContext);
229
+ await projection.render({ targetDir: options.dir, plan });
234
230
  return;
235
231
  }
236
- throw new Error("Only the ts-lib, hono-api, vue-app, vue-hono-app, and rust-bin presets are supported in this version");
232
+ throw new Error(formatSupportedPresetError());
237
233
  }
238
234
  function printInitComplete(options, blueprint, generationContext) {
239
- const preset = blueprint.preset;
240
- const nextSteps = planNextStepInstructions({ preset, targetDir: options.dir }).steps;
235
+ const projectionPlan = generationContext
236
+ ? projectPresetThroughRegistry(generationContext)
237
+ : undefined;
238
+ if (!projectionPlan) {
239
+ throw new Error(`Missing Preset Projection plan: ${blueprint.preset}`);
240
+ }
241
+ const nextSteps = planNextStepInstructionsForProjection({
242
+ targetDir: options.dir,
243
+ plan: projectionPlan,
244
+ });
241
245
  if (options.json) {
242
246
  printJson({
243
247
  command: "init",
244
248
  dryRun: false,
245
249
  targetDir: options.dir,
246
250
  blueprint,
247
- toolchain: generationContext ? toolchainReport(generationContext.toolchain) : undefined,
251
+ toolchain: generationContext
252
+ ? toolchainReport(generationContext.toolchain)
253
+ : undefined,
248
254
  nextSteps,
249
255
  });
250
256
  return;
@@ -253,7 +259,7 @@ function printInitComplete(options, blueprint, generationContext) {
253
259
  if (generationContext) {
254
260
  console.log(formatToolchainReport(generationContext.toolchain));
255
261
  }
256
- console.log(formatNextSteps(options.dir, preset));
262
+ console.log(formatProjectionNextSteps(options.dir, projectionPlan));
257
263
  }
258
264
  function isInteractiveTerminal() {
259
265
  return Boolean(process.stdin.isTTY && process.stdout.isTTY);
@@ -266,7 +272,8 @@ async function confirmInit(targetDir, blueprint) {
266
272
  });
267
273
  try {
268
274
  const answer = await readline.question("Generate this project? [y/N] ");
269
- return answer.trim().toLowerCase() === "y" || answer.trim().toLowerCase() === "yes";
275
+ return (answer.trim().toLowerCase() === "y" ||
276
+ answer.trim().toLowerCase() === "yes");
270
277
  }
271
278
  finally {
272
279
  readline.close();
@@ -275,6 +282,7 @@ async function confirmInit(targetDir, blueprint) {
275
282
  function parseAddPackageOptions(args) {
276
283
  let preset = "";
277
284
  let name = "";
285
+ let packagePath;
278
286
  for (let index = 2; index < args.length; index += 1) {
279
287
  const arg = args[index];
280
288
  if (arg === "--preset") {
@@ -295,6 +303,15 @@ function parseAddPackageOptions(args) {
295
303
  index += 1;
296
304
  continue;
297
305
  }
306
+ if (arg === "--path") {
307
+ const value = args[index + 1];
308
+ if (!value) {
309
+ throw new Error("--path requires a value");
310
+ }
311
+ packagePath = value;
312
+ index += 1;
313
+ continue;
314
+ }
298
315
  throw new Error(`Unknown option: ${arg}`);
299
316
  }
300
317
  if (!preset) {
@@ -303,7 +320,7 @@ function parseAddPackageOptions(args) {
303
320
  if (!name) {
304
321
  throw new Error("add package requires --name");
305
322
  }
306
- return { preset, name };
323
+ return { preset, name, path: packagePath };
307
324
  }
308
325
  async function main(args) {
309
326
  const command = args[0];
@@ -352,23 +369,34 @@ async function main(args) {
352
369
  const blueprint = blueprintForInit(options);
353
370
  if (options.dryRun) {
354
371
  const generationContext = await generationContextForInit(options, blueprint);
355
- const nextSteps = planNextStepInstructions({
356
- preset: blueprint.preset,
372
+ const projectionPlan = generationContext
373
+ ? projectPresetThroughRegistry(generationContext)
374
+ : undefined;
375
+ if (!projectionPlan) {
376
+ throw new Error(`Missing Preset Projection plan: ${blueprint.preset}`);
377
+ }
378
+ const nextSteps = planNextStepInstructionsForProjection({
357
379
  targetDir: options.dir,
358
- }).steps;
380
+ plan: projectionPlan,
381
+ });
359
382
  if (options.json) {
360
383
  printJson({
361
384
  command: "init",
362
385
  dryRun: true,
363
386
  targetDir: options.dir,
364
387
  blueprint,
365
- toolchain: generationContext ? toolchainReport(generationContext.toolchain) : undefined,
388
+ toolchain: generationContext
389
+ ? toolchainReport(generationContext.toolchain)
390
+ : undefined,
366
391
  nextSteps,
367
392
  });
368
393
  return;
369
394
  }
370
395
  console.log(formatBlueprintSummary(options.dir, blueprint));
371
- console.log(formatNextSteps(options.dir, blueprint.preset));
396
+ if (generationContext) {
397
+ console.log(formatToolchainReport(generationContext.toolchain));
398
+ }
399
+ console.log(formatProjectionNextSteps(options.dir, projectionPlan));
372
400
  return;
373
401
  }
374
402
  if (!options.yes && (options.json || !isInteractiveTerminal())) {
@@ -384,7 +412,12 @@ async function main(args) {
384
412
  }
385
413
  if (command === "add" && args[1] === "package") {
386
414
  const options = parseAddPackageOptions(args);
387
- await addPackage({ cwd: process.cwd(), preset: options.preset, name: options.name });
415
+ await addPackage({
416
+ cwd: process.cwd(),
417
+ preset: options.preset,
418
+ name: options.name,
419
+ path: options.path,
420
+ });
388
421
  console.log(`Added ${options.preset} package ${options.name}`);
389
422
  return;
390
423
  }
@@ -1,7 +1,6 @@
1
1
  import * as v from "valibot";
2
- export type PresetName = "ts-lib" | "hono-api" | "vue-app" | "vue-hono-app" | "rust-bin" | "ts-app" | "node-cli";
3
2
  export type BuiltInPreset = {
4
- name: PresetName;
3
+ name: string;
5
4
  title: string;
6
5
  description: string;
7
6
  generation: "supported" | "future";
@@ -68,7 +67,7 @@ export declare const presetFileJsonSchema: {
68
67
  readonly type: "array";
69
68
  readonly minItems: 1;
70
69
  readonly items: {
71
- readonly enum: readonly ["single-package", "multi-package"];
70
+ readonly enum: readonly ["multi-package"];
72
71
  };
73
72
  readonly uniqueItems: true;
74
73
  };
@@ -100,7 +99,7 @@ export declare const blueprintJsonSchema: {
100
99
  readonly enum: readonly ["pnpm"];
101
100
  };
102
101
  readonly projectKind: {
103
- readonly enum: readonly ["single-package", "multi-package"];
102
+ readonly enum: readonly ["multi-package"];
104
103
  };
105
104
  readonly features: {
106
105
  readonly type: "array";
@@ -163,4 +162,3 @@ export type ValidationResult<T> = {
163
162
  export declare function validatePresetFile(input: unknown): ValidationResult<PresetFile>;
164
163
  export declare function findBuiltInPreset(name: string): BuiltInPreset | undefined;
165
164
  export declare function validateProjectBlueprint(input: unknown): ValidationResult<ProjectBlueprint>;
166
- //# sourceMappingURL=declarations.d.ts.map
@@ -1,113 +1,6 @@
1
1
  import * as v from "valibot";
2
- export const builtInPresets = [
3
- {
4
- name: "ts-lib",
5
- title: "TypeScript library",
6
- description: "Strict TypeScript package with pnpm catalog tooling.",
7
- generation: "supported",
8
- supportedPackageManagers: ["pnpm"],
9
- supportedProjectKinds: ["single-package"],
10
- features: [
11
- "pnpm-catalog",
12
- "oxc-format-lint",
13
- "strict-typescript",
14
- "root-check",
15
- "fix-command",
16
- "devcontainer",
17
- "github-actions",
18
- "dependabot"
19
- ]
20
- },
21
- {
22
- name: "hono-api",
23
- title: "Hono API",
24
- description: "Single-package Hono Node API with strict TypeScript tooling.",
25
- generation: "supported",
26
- supportedPackageManagers: ["pnpm"],
27
- supportedProjectKinds: ["single-package"],
28
- features: [
29
- "pnpm-catalog",
30
- "oxc-format-lint",
31
- "strict-typescript",
32
- "root-check",
33
- "fix-command",
34
- "devcontainer",
35
- "github-actions",
36
- "dependabot"
37
- ]
38
- },
39
- {
40
- name: "vue-app",
41
- title: "Vue app",
42
- description: "Single-package Vue app with Vite, Tailwind, Pinia, and test tooling.",
43
- generation: "supported",
44
- supportedPackageManagers: ["pnpm"],
45
- supportedProjectKinds: ["single-package"],
46
- features: [
47
- "pnpm-catalog",
48
- "oxc-format-lint",
49
- "strict-typescript",
50
- "root-check",
51
- "fix-command",
52
- "devcontainer",
53
- "github-actions",
54
- "dependabot"
55
- ]
56
- },
57
- {
58
- name: "vue-hono-app",
59
- title: "Vue Hono app",
60
- description: "Full-stack Vue and Hono workspace with Hono RPC typing.",
61
- generation: "supported",
62
- supportedPackageManagers: ["pnpm"],
63
- supportedProjectKinds: ["multi-package"],
64
- features: [
65
- "pnpm-catalog",
66
- "oxc-format-lint",
67
- "strict-typescript",
68
- "root-check",
69
- "fix-command",
70
- "devcontainer",
71
- "github-actions",
72
- "dependabot"
73
- ]
74
- },
75
- {
76
- name: "rust-bin",
77
- title: "Rust binary",
78
- description: "Single-package Rust native binary with rustfmt, clippy, and cargo tests.",
79
- generation: "supported",
80
- supportedPackageManagers: ["pnpm"],
81
- supportedProjectKinds: ["single-package"],
82
- features: [
83
- "root-check",
84
- "fix-command",
85
- "devcontainer",
86
- "github-actions",
87
- "dependabot",
88
- "rustfmt-clippy",
89
- "cargo-test"
90
- ]
91
- },
92
- {
93
- name: "ts-app",
94
- title: "TypeScript application",
95
- description: "Future application preset metadata.",
96
- generation: "future",
97
- supportedPackageManagers: ["pnpm"],
98
- supportedProjectKinds: ["single-package"],
99
- features: []
100
- },
101
- {
102
- name: "node-cli",
103
- title: "Node.js CLI",
104
- description: "Future command-line preset metadata.",
105
- generation: "future",
106
- supportedPackageManagers: ["pnpm"],
107
- supportedProjectKinds: ["single-package"],
108
- features: []
109
- }
110
- ];
2
+ import { builtInPresetMetadata } from "../templates/registry.js";
3
+ export const builtInPresets = builtInPresetMetadata;
111
4
  const featureNames = [
112
5
  "pnpm-catalog",
113
6
  "oxc-format-lint",
@@ -119,7 +12,7 @@ const featureNames = [
119
12
  "dependabot",
120
13
  "rustfmt-clippy",
121
14
  "cargo-test",
122
- "native-binary-release"
15
+ "native-binary-release",
123
16
  ];
124
17
  export const presetFileJsonSchema = {
125
18
  $schema: "https://json-schema.org/draft/2020-12/schema",
@@ -134,7 +27,7 @@ export const presetFileJsonSchema = {
134
27
  "description",
135
28
  "supportedPackageManagers",
136
29
  "supportedProjectKinds",
137
- "features"
30
+ "features",
138
31
  ],
139
32
  properties: {
140
33
  schemaVersion: { const: 1 },
@@ -144,20 +37,20 @@ export const presetFileJsonSchema = {
144
37
  supportedPackageManagers: {
145
38
  type: "array",
146
39
  items: { enum: ["pnpm"] },
147
- uniqueItems: true
40
+ uniqueItems: true,
148
41
  },
149
42
  supportedProjectKinds: {
150
43
  type: "array",
151
44
  minItems: 1,
152
- items: { enum: ["single-package", "multi-package"] },
153
- uniqueItems: true
45
+ items: { enum: ["multi-package"] },
46
+ uniqueItems: true,
154
47
  },
155
48
  features: {
156
49
  type: "array",
157
50
  items: { enum: featureNames },
158
- uniqueItems: true
159
- }
160
- }
51
+ uniqueItems: true,
52
+ },
53
+ },
161
54
  };
162
55
  export const blueprintJsonSchema = {
163
56
  $schema: "https://json-schema.org/draft/2020-12/schema",
@@ -170,11 +63,11 @@ export const blueprintJsonSchema = {
170
63
  schemaVersion: { const: 1 },
171
64
  preset: { type: "string", minLength: 1 },
172
65
  packageManager: { enum: ["pnpm"] },
173
- projectKind: { enum: ["single-package", "multi-package"] },
66
+ projectKind: { enum: ["multi-package"] },
174
67
  features: {
175
68
  type: "array",
176
69
  items: { enum: featureNames },
177
- uniqueItems: true
70
+ uniqueItems: true,
178
71
  },
179
72
  packages: {
180
73
  type: "array",
@@ -184,15 +77,18 @@ export const blueprintJsonSchema = {
184
77
  required: ["name", "path"],
185
78
  properties: {
186
79
  name: { type: "string", minLength: 1 },
187
- path: { type: "string", minLength: 1 }
188
- }
189
- }
190
- }
191
- }
80
+ path: { type: "string", minLength: 1 },
81
+ },
82
+ },
83
+ },
84
+ },
192
85
  };
193
86
  const nonEmptyString = v.pipe(v.string(), v.minLength(1));
194
87
  const packageManagerSchema = v.picklist(["pnpm"]);
195
- const projectKindSchema = v.picklist(["single-package", "multi-package"]);
88
+ const projectKindSchema = v.picklist([
89
+ "single-package",
90
+ "multi-package",
91
+ ]);
196
92
  const featureNameSchema = v.picklist(featureNames);
197
93
  export const presetFileSchema = v.strictObject({
198
94
  schemaVersion: v.literal(1),
@@ -201,7 +97,7 @@ export const presetFileSchema = v.strictObject({
201
97
  description: nonEmptyString,
202
98
  supportedPackageManagers: v.array(packageManagerSchema),
203
99
  supportedProjectKinds: v.pipe(v.array(projectKindSchema), v.minLength(1)),
204
- features: v.array(featureNameSchema)
100
+ features: v.array(featureNameSchema),
205
101
  });
206
102
  export const projectBlueprintSchema = v.strictObject({
207
103
  schemaVersion: v.literal(1),
@@ -211,8 +107,8 @@ export const projectBlueprintSchema = v.strictObject({
211
107
  features: v.array(featureNameSchema),
212
108
  packages: v.optional(v.array(v.strictObject({
213
109
  name: nonEmptyString,
214
- path: nonEmptyString
215
- })))
110
+ path: nonEmptyString,
111
+ }))),
216
112
  });
217
113
  function formatIssuePath(issue) {
218
114
  if (!issue.path || issue.path.length === 0) {
@@ -223,7 +119,7 @@ function formatIssuePath(issue) {
223
119
  function shapeIssues(issues) {
224
120
  return issues.map((issue) => ({
225
121
  path: formatIssuePath(issue),
226
- message: issue.message
122
+ message: issue.message,
227
123
  }));
228
124
  }
229
125
  function duplicateIssues(values, path) {
@@ -237,7 +133,7 @@ function duplicateIssues(values, path) {
237
133
  }
238
134
  return [...duplicates].map((value) => ({
239
135
  path,
240
- message: `Duplicate value: ${value}`
136
+ message: `Duplicate value: ${value}`,
241
137
  }));
242
138
  }
243
139
  function generationSupportIssue(preset, path) {
@@ -246,7 +142,13 @@ function generationSupportIssue(preset, path) {
246
142
  }
247
143
  return {
248
144
  path,
249
- message: `Preset ${preset.name} is not supported for generation in this version`
145
+ message: `Preset ${preset.name} is not supported for generation in this version`,
146
+ };
147
+ }
148
+ function unsupportedSinglePackageProjectShapeIssue(path) {
149
+ return {
150
+ path,
151
+ message: "single-package Project Shape is unsupported in V1; use the workspace monorepo Project Shape",
250
152
  };
251
153
  }
252
154
  export function validatePresetFile(input) {
@@ -257,8 +159,11 @@ export function validatePresetFile(input) {
257
159
  const semanticIssues = [
258
160
  ...duplicateIssues(result.output.supportedPackageManagers, "$.supportedPackageManagers"),
259
161
  ...duplicateIssues(result.output.supportedProjectKinds, "$.supportedProjectKinds"),
260
- ...duplicateIssues(result.output.features, "$.features")
162
+ ...duplicateIssues(result.output.features, "$.features"),
261
163
  ];
164
+ if (result.output.supportedProjectKinds.includes("single-package")) {
165
+ semanticIssues.push(unsupportedSinglePackageProjectShapeIssue("$.supportedProjectKinds"));
166
+ }
262
167
  const builtInPreset = findBuiltInPreset(result.output.name);
263
168
  const unsupportedGeneration = builtInPreset
264
169
  ? generationSupportIssue(builtInPreset, "$.name")
@@ -282,12 +187,15 @@ export function validateProjectBlueprint(input) {
282
187
  const blueprint = result.output;
283
188
  const preset = findBuiltInPreset(blueprint.preset);
284
189
  const semanticIssues = [
285
- ...duplicateIssues(blueprint.features, "$.features")
190
+ ...duplicateIssues(blueprint.features, "$.features"),
286
191
  ];
192
+ if (blueprint.projectKind === "single-package") {
193
+ semanticIssues.push(unsupportedSinglePackageProjectShapeIssue("$.projectKind"));
194
+ }
287
195
  if (!preset) {
288
196
  semanticIssues.push({
289
197
  path: "$.preset",
290
- message: `Unknown built-in preset: ${blueprint.preset}`
198
+ message: `Unknown built-in preset: ${blueprint.preset}`,
291
199
  });
292
200
  }
293
201
  else {
@@ -299,19 +207,20 @@ export function validateProjectBlueprint(input) {
299
207
  !preset.supportedPackageManagers.includes(blueprint.packageManager)) {
300
208
  semanticIssues.push({
301
209
  path: "$.packageManager",
302
- message: `${blueprint.packageManager} is not supported by preset ${preset.name}`
210
+ message: `${blueprint.packageManager} is not supported by preset ${preset.name}`,
303
211
  });
304
212
  }
305
- if (!blueprint.packageManager && preset.supportedPackageManagers.length > 0) {
213
+ if (!blueprint.packageManager &&
214
+ preset.supportedPackageManagers.length > 0) {
306
215
  semanticIssues.push({
307
216
  path: "$.packageManager",
308
- message: `packageManager is required by preset ${preset.name}`
217
+ message: `packageManager is required by preset ${preset.name}`,
309
218
  });
310
219
  }
311
220
  if (!preset.supportedProjectKinds.includes(blueprint.projectKind)) {
312
221
  semanticIssues.push({
313
222
  path: "$.projectKind",
314
- message: `${blueprint.projectKind} is not supported by preset ${preset.name}`
223
+ message: `${blueprint.projectKind} is not supported by preset ${preset.name}`,
315
224
  });
316
225
  }
317
226
  const supportedFeatures = new Set(preset.features);
@@ -319,18 +228,12 @@ export function validateProjectBlueprint(input) {
319
228
  if (!supportedFeatures.has(feature)) {
320
229
  semanticIssues.push({
321
230
  path: "$.features",
322
- message: `${feature} is not supported by preset ${preset.name}`
231
+ message: `${feature} is not supported by preset ${preset.name}`,
323
232
  });
324
233
  }
325
234
  }
326
235
  }
327
236
  if (blueprint.packages) {
328
- if (blueprint.projectKind === "single-package" && blueprint.packages.length > 1) {
329
- semanticIssues.push({
330
- path: "$.packages",
331
- message: "single-package blueprints support exactly one package"
332
- });
333
- }
334
237
  semanticIssues.push(...duplicateIssues(blueprint.packages.map((projectPackage) => projectPackage.name), "$.packages.name"), ...duplicateIssues(blueprint.packages.map((projectPackage) => projectPackage.path), "$.packages.path"));
335
238
  }
336
239
  if (semanticIssues.length > 0) {
@@ -0,0 +1,18 @@
1
+ export type TemplateDependencyCatalog = Record<string, string>;
2
+ export type GeneratedDependencyCatalogOptions = {
3
+ readonly dependencies: readonly string[];
4
+ readonly packages?: readonly string[];
5
+ readonly allowBuilds?: Record<string, boolean>;
6
+ };
7
+ export type GeneratedPackageManifestDependencies = {
8
+ readonly dependencies?: Record<string, string>;
9
+ readonly devDependencies?: Record<string, string>;
10
+ readonly optionalDependencies?: Record<string, string>;
11
+ readonly peerDependencies?: Record<string, string>;
12
+ };
13
+ export declare function loadTemplateDependencyCatalog(): TemplateDependencyCatalog;
14
+ export declare function selectTemplateDependencyCatalogEntries(dependencies: readonly string[], catalog?: TemplateDependencyCatalog): TemplateDependencyCatalog;
15
+ export declare function collectGeneratedManifestCatalogDependencies(manifests: readonly GeneratedPackageManifestDependencies[]): string[];
16
+ export declare function collectGeneratedManifestCatalogReferences(manifests: readonly GeneratedPackageManifestDependencies[]): string[];
17
+ export declare function pnpmWorkspaceYamlWithCatalogDependencies(workspaceYaml: string, dependencies: readonly string[], templateCatalog?: TemplateDependencyCatalog): string;
18
+ export declare function renderGeneratedPnpmWorkspaceYaml(options: GeneratedDependencyCatalogOptions): string;