@ykdz/template 0.0.2 → 0.0.3

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 (102) hide show
  1. package/dist/src/cli.d.ts.map +1 -0
  2. package/dist/{cli.js → src/cli.js} +77 -56
  3. package/dist/{declarations.d.ts → src/declarations.d.ts} +1 -2
  4. package/dist/src/declarations.d.ts.map +1 -0
  5. package/dist/{declarations.js → src/declarations.js} +2 -109
  6. package/dist/src/dependency-catalog.d.ts +10 -0
  7. package/dist/src/dependency-catalog.d.ts.map +1 -0
  8. package/dist/src/dependency-catalog.js +63 -0
  9. package/dist/{devcontainer.d.ts → src/devcontainer.d.ts} +1 -0
  10. package/dist/src/devcontainer.d.ts.map +1 -0
  11. package/dist/{devcontainer.js → src/devcontainer.js} +1 -0
  12. package/dist/src/editor-customization.d.ts +13 -0
  13. package/dist/src/editor-customization.d.ts.map +1 -0
  14. package/dist/src/editor-customization.js +101 -0
  15. package/dist/{generation-context.d.ts → src/generation-context.d.ts} +2 -2
  16. package/dist/src/generation-context.d.ts.map +1 -0
  17. package/dist/{module-graph.d.ts → src/module-graph.d.ts} +0 -14
  18. package/dist/src/module-graph.d.ts.map +1 -0
  19. package/dist/src/module-graph.js +48 -0
  20. package/dist/{next-step-instructions.d.ts → src/next-step-instructions.d.ts} +2 -3
  21. package/dist/src/next-step-instructions.d.ts.map +1 -0
  22. package/dist/{next-step-instructions.js → src/next-step-instructions.js} +14 -24
  23. package/dist/src/package-addition.d.ts.map +1 -0
  24. package/dist/src/package-addition.js +188 -0
  25. package/dist/src/preset-projection.d.ts +66 -0
  26. package/dist/src/preset-projection.d.ts.map +1 -0
  27. package/dist/src/preset-projection.js +7 -0
  28. package/dist/{project-github.d.ts → src/project-github.d.ts} +0 -7
  29. package/dist/src/project-github.d.ts.map +1 -0
  30. package/dist/{project-github.js → src/project-github.js} +3 -36
  31. package/dist/src/renderer.d.ts.map +1 -0
  32. package/dist/src/runtime-paths.d.ts +2 -0
  33. package/dist/src/runtime-paths.d.ts.map +1 -0
  34. package/dist/src/runtime-paths.js +11 -0
  35. package/dist/src/toolchain-resolution.d.ts.map +1 -0
  36. package/dist/{toolchain-resolution.js → src/toolchain-resolution.js} +1 -1
  37. package/dist/templates/hono-api/projection.d.ts +7 -0
  38. package/dist/templates/hono-api/projection.d.ts.map +1 -0
  39. package/dist/templates/hono-api/projection.js +377 -0
  40. package/dist/templates/projection-plans.d.ts +8 -0
  41. package/dist/templates/projection-plans.d.ts.map +1 -0
  42. package/dist/templates/projection-plans.js +94 -0
  43. package/dist/templates/registry.d.ts +8 -0
  44. package/dist/templates/registry.d.ts.map +1 -0
  45. package/dist/templates/registry.js +42 -0
  46. package/dist/templates/rust-bin/projection.d.ts +10 -0
  47. package/dist/templates/rust-bin/projection.d.ts.map +1 -0
  48. package/dist/templates/rust-bin/projection.js +282 -0
  49. package/dist/templates/ts-lib/projection.d.ts +7 -0
  50. package/dist/templates/ts-lib/projection.d.ts.map +1 -0
  51. package/dist/templates/ts-lib/projection.js +372 -0
  52. package/dist/templates/vue-app/projection.d.ts +7 -0
  53. package/dist/templates/vue-app/projection.d.ts.map +1 -0
  54. package/dist/templates/vue-app/projection.js +594 -0
  55. package/dist/templates/vue-hono-app/projection.d.ts +9 -0
  56. package/dist/templates/vue-hono-app/projection.d.ts.map +1 -0
  57. package/dist/{vue-hono-app.js → templates/vue-hono-app/projection.js} +250 -101
  58. package/package.json +29 -24
  59. package/pnpm-workspace.yaml +34 -0
  60. package/templates/hono-api/projection.ts +453 -0
  61. package/templates/projection-plans.ts +135 -0
  62. package/templates/registry.ts +59 -0
  63. package/templates/rust-bin/projection.ts +346 -0
  64. package/templates/ts-lib/projection.ts +454 -0
  65. package/templates/vue-app/projection.ts +687 -0
  66. package/templates/vue-app/test/e2e/app.spec.ts +4 -1
  67. package/templates/vue-hono-app/projection.ts +669 -0
  68. package/templates/vue-hono-app/web/test/e2e/app.spec.ts +4 -1
  69. package/dist/cli.d.ts.map +0 -1
  70. package/dist/declarations.d.ts.map +0 -1
  71. package/dist/devcontainer.d.ts.map +0 -1
  72. package/dist/generation-context.d.ts.map +0 -1
  73. package/dist/hono-api.d.ts +0 -3
  74. package/dist/hono-api.d.ts.map +0 -1
  75. package/dist/hono-api.js +0 -210
  76. package/dist/module-graph.d.ts.map +0 -1
  77. package/dist/module-graph.js +0 -187
  78. package/dist/next-step-instructions.d.ts.map +0 -1
  79. package/dist/package-addition.d.ts.map +0 -1
  80. package/dist/package-addition.js +0 -560
  81. package/dist/project-github.d.ts.map +0 -1
  82. package/dist/renderer.d.ts.map +0 -1
  83. package/dist/rust-bin.d.ts +0 -8
  84. package/dist/rust-bin.d.ts.map +0 -1
  85. package/dist/rust-bin.js +0 -208
  86. package/dist/toolchain-resolution.d.ts.map +0 -1
  87. package/dist/ts-lib.d.ts +0 -8
  88. package/dist/ts-lib.d.ts.map +0 -1
  89. package/dist/ts-lib.js +0 -214
  90. package/dist/vue-app.d.ts +0 -3
  91. package/dist/vue-app.d.ts.map +0 -1
  92. package/dist/vue-app.js +0 -301
  93. package/dist/vue-hono-app.d.ts +0 -7
  94. package/dist/vue-hono-app.d.ts.map +0 -1
  95. package/templates/shared/oxc/package.json +0 -18
  96. package/templates/shared/oxc/tsconfig.json +0 -11
  97. /package/dist/{cli.d.ts → src/cli.d.ts} +0 -0
  98. /package/dist/{generation-context.js → src/generation-context.js} +0 -0
  99. /package/dist/{package-addition.d.ts → src/package-addition.d.ts} +0 -0
  100. /package/dist/{renderer.d.ts → src/renderer.d.ts} +0 -0
  101. /package/dist/{renderer.js → src/renderer.js} +0 -0
  102. /package/dist/{toolchain-resolution.d.ts → src/toolchain-resolution.d.ts} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":""}
@@ -2,15 +2,11 @@
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 [
@@ -50,7 +46,9 @@ async function readJsonDeclaration(filePath) {
50
46
  }
51
47
  }
52
48
  function formatValidationIssues(issues) {
53
- return issues.map((issue) => ` - ${issue.path}: ${issue.message}`).join("\n");
49
+ return issues
50
+ .map((issue) => ` - ${issue.path}: ${issue.message}`)
51
+ .join("\n");
54
52
  }
55
53
  function formatPresetCatalog() {
56
54
  return [
@@ -117,20 +115,31 @@ function normalizeNpmScope(value) {
117
115
  function supportedPreset(name) {
118
116
  const preset = builtInPresets.find((candidate) => candidate.name === name && candidate.generation === "supported");
119
117
  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");
118
+ throw new Error(formatSupportedPresetError());
121
119
  }
122
120
  return preset;
123
121
  }
124
- function projectNameFromDir(targetDir) {
125
- return path.basename(path.resolve(targetDir));
122
+ function formatSupportedPresetError() {
123
+ const supportedPresetNames = builtInPresets
124
+ .filter((preset) => preset.generation === "supported")
125
+ .map((preset) => preset.name);
126
+ return `Only the ${formatList(supportedPresetNames)} presets are supported in this version`;
126
127
  }
127
- function scopeFromOptions(projectName, scope) {
128
- return scope ?? projectName;
128
+ function formatList(values) {
129
+ if (values.length <= 1) {
130
+ return values[0] ?? "";
131
+ }
132
+ return `${values.slice(0, -1).join(", ")}, and ${values.at(-1)}`;
129
133
  }
130
134
  function blueprintForInit(options) {
131
135
  const preset = supportedPreset(options.preset);
132
- const projectName = projectNameFromDir(options.dir);
133
- const packageScope = scopeFromOptions(projectName, options.scope);
136
+ const projection = findBuiltInPresetProjection(preset.name);
137
+ if (projection) {
138
+ return projection.blueprint({
139
+ targetDir: options.dir,
140
+ scope: options.scope,
141
+ });
142
+ }
134
143
  const blueprint = {
135
144
  schemaVersion: 1,
136
145
  preset: preset.name,
@@ -140,12 +149,6 @@ function blueprintForInit(options) {
140
149
  if (preset.supportedPackageManagers[0]) {
141
150
  blueprint.packageManager = preset.supportedPackageManagers[0];
142
151
  }
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
152
  return blueprint;
150
153
  }
151
154
  function formatBlueprintSummary(targetDir, blueprint) {
@@ -167,11 +170,14 @@ function formatBlueprintSummary(targetDir, blueprint) {
167
170
  lines.push(` Features: ${blueprint.features.join(", ")}`);
168
171
  return lines.join("\n");
169
172
  }
170
- function formatNextSteps(targetDir, preset) {
171
- const plan = planNextStepInstructions({ preset, targetDir });
173
+ function formatProjectionNextSteps(targetDir, projectionPlan) {
174
+ const steps = planNextStepInstructionsForProjection({
175
+ targetDir,
176
+ plan: projectionPlan,
177
+ });
172
178
  return [
173
179
  "Next Step Instructions:",
174
- ...plan.steps.map((step) => ` ${step.label}: ${step.display}`),
180
+ ...steps.map((step) => ` ${step.label}: ${step.display}`),
175
181
  ].join("\n");
176
182
  }
177
183
  function toolchainReport(toolchain) {
@@ -199,7 +205,7 @@ function toolchainResolutionSourceFromEnv() {
199
205
  return undefined;
200
206
  }
201
207
  async function generationContextForInit(options, blueprint) {
202
- if (options.preset !== "ts-lib" && options.preset !== "rust-bin") {
208
+ if (!findBuiltInPresetProjection(options.preset)) {
203
209
  return undefined;
204
210
  }
205
211
  return assembleGenerationContext({
@@ -213,38 +219,37 @@ async function generationContextForInit(options, blueprint) {
213
219
  });
214
220
  }
215
221
  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 });
222
+ const projection = findBuiltInPresetProjection(options.preset);
223
+ if (projection) {
224
+ if (!generationContext) {
225
+ throw new Error(`Missing Generation Context for Preset Projection: ${options.preset}`);
226
+ }
227
+ const plan = projection.project(generationContext);
228
+ await projection.render({ targetDir: options.dir, plan });
234
229
  return;
235
230
  }
236
- throw new Error("Only the ts-lib, hono-api, vue-app, vue-hono-app, and rust-bin presets are supported in this version");
231
+ throw new Error(formatSupportedPresetError());
237
232
  }
238
233
  function printInitComplete(options, blueprint, generationContext) {
239
- const preset = blueprint.preset;
240
- const nextSteps = planNextStepInstructions({ preset, targetDir: options.dir }).steps;
234
+ const projectionPlan = generationContext
235
+ ? projectPresetThroughRegistry(generationContext)
236
+ : undefined;
237
+ if (!projectionPlan) {
238
+ throw new Error(`Missing Preset Projection plan: ${blueprint.preset}`);
239
+ }
240
+ const nextSteps = planNextStepInstructionsForProjection({
241
+ targetDir: options.dir,
242
+ plan: projectionPlan,
243
+ });
241
244
  if (options.json) {
242
245
  printJson({
243
246
  command: "init",
244
247
  dryRun: false,
245
248
  targetDir: options.dir,
246
249
  blueprint,
247
- toolchain: generationContext ? toolchainReport(generationContext.toolchain) : undefined,
250
+ toolchain: generationContext
251
+ ? toolchainReport(generationContext.toolchain)
252
+ : undefined,
248
253
  nextSteps,
249
254
  });
250
255
  return;
@@ -253,7 +258,7 @@ function printInitComplete(options, blueprint, generationContext) {
253
258
  if (generationContext) {
254
259
  console.log(formatToolchainReport(generationContext.toolchain));
255
260
  }
256
- console.log(formatNextSteps(options.dir, preset));
261
+ console.log(formatProjectionNextSteps(options.dir, projectionPlan));
257
262
  }
258
263
  function isInteractiveTerminal() {
259
264
  return Boolean(process.stdin.isTTY && process.stdout.isTTY);
@@ -266,7 +271,8 @@ async function confirmInit(targetDir, blueprint) {
266
271
  });
267
272
  try {
268
273
  const answer = await readline.question("Generate this project? [y/N] ");
269
- return answer.trim().toLowerCase() === "y" || answer.trim().toLowerCase() === "yes";
274
+ return (answer.trim().toLowerCase() === "y" ||
275
+ answer.trim().toLowerCase() === "yes");
270
276
  }
271
277
  finally {
272
278
  readline.close();
@@ -352,23 +358,34 @@ async function main(args) {
352
358
  const blueprint = blueprintForInit(options);
353
359
  if (options.dryRun) {
354
360
  const generationContext = await generationContextForInit(options, blueprint);
355
- const nextSteps = planNextStepInstructions({
356
- preset: blueprint.preset,
361
+ const projectionPlan = generationContext
362
+ ? projectPresetThroughRegistry(generationContext)
363
+ : undefined;
364
+ if (!projectionPlan) {
365
+ throw new Error(`Missing Preset Projection plan: ${blueprint.preset}`);
366
+ }
367
+ const nextSteps = planNextStepInstructionsForProjection({
357
368
  targetDir: options.dir,
358
- }).steps;
369
+ plan: projectionPlan,
370
+ });
359
371
  if (options.json) {
360
372
  printJson({
361
373
  command: "init",
362
374
  dryRun: true,
363
375
  targetDir: options.dir,
364
376
  blueprint,
365
- toolchain: generationContext ? toolchainReport(generationContext.toolchain) : undefined,
377
+ toolchain: generationContext
378
+ ? toolchainReport(generationContext.toolchain)
379
+ : undefined,
366
380
  nextSteps,
367
381
  });
368
382
  return;
369
383
  }
370
384
  console.log(formatBlueprintSummary(options.dir, blueprint));
371
- console.log(formatNextSteps(options.dir, blueprint.preset));
385
+ if (generationContext) {
386
+ console.log(formatToolchainReport(generationContext.toolchain));
387
+ }
388
+ console.log(formatProjectionNextSteps(options.dir, projectionPlan));
372
389
  return;
373
390
  }
374
391
  if (!options.yes && (options.json || !isInteractiveTerminal())) {
@@ -384,7 +401,11 @@ async function main(args) {
384
401
  }
385
402
  if (command === "add" && args[1] === "package") {
386
403
  const options = parseAddPackageOptions(args);
387
- await addPackage({ cwd: process.cwd(), preset: options.preset, name: options.name });
404
+ await addPackage({
405
+ cwd: process.cwd(),
406
+ preset: options.preset,
407
+ name: options.name,
408
+ });
388
409
  console.log(`Added ${options.preset} package ${options.name}`);
389
410
  return;
390
411
  }
@@ -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";
@@ -0,0 +1 @@
1
+ {"version":3,"file":"declarations.d.ts","sourceRoot":"","sources":["../../src/declarations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAC;AAG7B,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,WAAW,GAAG,QAAQ,CAAC;IACnC,wBAAwB,EAAE,SAAS,cAAc,EAAE,CAAC;IACpD,qBAAqB,EAAE,SAAS,WAAW,EAAE,CAAC;IAC9C,QAAQ,EAAE,SAAS,WAAW,EAAE,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC;AAEpC,MAAM,MAAM,WAAW,GAAG,gBAAgB,GAAG,eAAe,CAAC;AAE7D,MAAM,MAAM,WAAW,GACnB,cAAc,GACd,iBAAiB,GACjB,mBAAmB,GACnB,YAAY,GACZ,aAAa,GACb,cAAc,GACd,gBAAgB,GAChB,YAAY,GACZ,gBAAgB,GAChB,YAAY,GACZ,uBAAuB,CAAC;AAE5B,MAAM,MAAM,UAAU,GAAG;IACvB,aAAa,EAAE,CAAC,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,wBAAwB,EAAE,cAAc,EAAE,CAAC;IAC3C,qBAAqB,EAAE,WAAW,EAAE,CAAC;IACrC,QAAQ,EAAE,WAAW,EAAE,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,aAAa,EAAE,CAAC,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,WAAW,EAAE,WAAW,CAAC;IACzB,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,QAAQ,CAAC,EAAE,cAAc,EAAE,CAAC;CAC7B,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,SAAS,aAAa,EAA0B,CAAC;AAgB9E,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqCvB,CAAC;AAEX,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8BtB,CAAC;AAOX,eAAO,MAAM,gBAAgB;;;;;;;;aAQ3B,CAAC;AAEH,eAAO,MAAM,sBAAsB;;;;;;;;;;aAcjC,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,gBAAgB,CAAC,CAAC,IAC1B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,GACtB;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,eAAe,EAAE,CAAA;CAAE,CAAC;AAgD7C,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,gBAAgB,CAAC,UAAU,CAAC,CA2B/E;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAEzE;AAED,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,OAAO,GACb,gBAAgB,CAAC,gBAAgB,CAAC,CAqFpC"}
@@ -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",
@@ -0,0 +1,10 @@
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 declare function loadTemplateDependencyCatalog(): TemplateDependencyCatalog;
8
+ export declare function selectTemplateDependencyCatalogEntries(dependencies: readonly string[], catalog?: TemplateDependencyCatalog): TemplateDependencyCatalog;
9
+ export declare function renderGeneratedPnpmWorkspaceYaml(options: GeneratedDependencyCatalogOptions): string;
10
+ //# sourceMappingURL=dependency-catalog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dependency-catalog.d.ts","sourceRoot":"","sources":["../../src/dependency-catalog.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,yBAAyB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE/D,MAAM,MAAM,iCAAiC,GAAG;IAC9C,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChD,CAAC;AA2CF,wBAAgB,6BAA6B,IAAI,yBAAyB,CAOzE;AAED,wBAAgB,sCAAsC,CACpD,YAAY,EAAE,SAAS,MAAM,EAAE,EAC/B,OAAO,GAAE,yBAA2D,GACnE,yBAAyB,CAe3B;AAMD,wBAAgB,gCAAgC,CAC9C,OAAO,EAAE,iCAAiC,GACzC,MAAM,CA4BR"}
@@ -0,0 +1,63 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import path from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ function templateRepositoryRoot() {
5
+ const moduleDir = path.dirname(fileURLToPath(import.meta.url));
6
+ const candidates = [
7
+ path.resolve(moduleDir, ".."),
8
+ path.resolve(moduleDir, "..", ".."),
9
+ ];
10
+ return (candidates.find((candidate) => existsSync(path.join(candidate, "pnpm-workspace.yaml"))) ?? candidates[0]);
11
+ }
12
+ function parseTemplateDependencyCatalog(workspaceYaml) {
13
+ const catalog = {};
14
+ const lines = workspaceYaml.split(/\r?\n/);
15
+ const catalogStart = lines.findIndex((line) => line === "catalog:");
16
+ if (catalogStart === -1) {
17
+ return catalog;
18
+ }
19
+ for (const line of lines.slice(catalogStart + 1)) {
20
+ if (line.length > 0 && !line.startsWith(" ")) {
21
+ break;
22
+ }
23
+ const match = /^ (?:"([^"]+)"|([^:]+)): (.+)$/.exec(line);
24
+ if (!match) {
25
+ continue;
26
+ }
27
+ catalog[match[1] ?? match[2]] = match[3];
28
+ }
29
+ return catalog;
30
+ }
31
+ export function loadTemplateDependencyCatalog() {
32
+ return parseTemplateDependencyCatalog(readFileSync(path.join(templateRepositoryRoot(), "pnpm-workspace.yaml"), "utf8"));
33
+ }
34
+ export function selectTemplateDependencyCatalogEntries(dependencies, catalog = loadTemplateDependencyCatalog()) {
35
+ const selected = {};
36
+ for (const dependency of [...dependencies].sort()) {
37
+ const version = catalog[dependency];
38
+ if (version === undefined) {
39
+ throw new Error(`Template Dependency Catalog is missing dependency: ${dependency}`);
40
+ }
41
+ selected[dependency] = version;
42
+ }
43
+ return selected;
44
+ }
45
+ function renderCatalogKey(key) {
46
+ return key.startsWith("@") ? JSON.stringify(key) : key;
47
+ }
48
+ export function renderGeneratedPnpmWorkspaceYaml(options) {
49
+ const catalog = selectTemplateDependencyCatalogEntries(options.dependencies);
50
+ const packages = options.packages ?? ["."];
51
+ const lines = [
52
+ "packages:",
53
+ ...packages.map((workspacePackage) => ` - ${workspacePackage}`),
54
+ "",
55
+ ];
56
+ if (options.allowBuilds) {
57
+ lines.push("allowBuilds:", ...Object.entries(options.allowBuilds)
58
+ .sort(([left], [right]) => left.localeCompare(right))
59
+ .map(([dependency, allowed]) => ` ${dependency}: ${allowed}`), "");
60
+ }
61
+ lines.push("catalog:", ...Object.entries(catalog).map(([dependency, version]) => ` ${renderCatalogKey(dependency)}: ${version}`), "");
62
+ return lines.join("\n");
63
+ }
@@ -13,5 +13,6 @@ export declare function nodePnpmDevcontainer(options: {
13
13
  readonly nodeVersion: string;
14
14
  readonly packageManagerPin: string;
15
15
  readonly extensions: readonly string[];
16
+ readonly settings?: Record<string, unknown>;
16
17
  }): Record<string, unknown>;
17
18
  //# sourceMappingURL=devcontainer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"devcontainer.d.ts","sourceRoot":"","sources":["../../src/devcontainer.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,8BAA8B,GAAG;IAC3C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;CACpC,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACpC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B,CAAC;AAEF,wBAAgB,gCAAgC,CAC9C,iBAAiB,EAAE,MAAM,GACxB,MAAM,CAER;AAED,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,8BAA8B,GACtC,MAAM,CAAC,uCAAuC,EAAE,uBAAuB,CAAC,CAO1E;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE;IAC5C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC7C,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAY1B"}
@@ -17,6 +17,7 @@ export function nodePnpmDevcontainer(options) {
17
17
  customizations: {
18
18
  vscode: {
19
19
  extensions: options.extensions,
20
+ ...(options.settings ? { settings: options.settings } : {}),
20
21
  },
21
22
  },
22
23
  };
@@ -0,0 +1,13 @@
1
+ export type EditorCustomizationCapability = "oxc-format-lint" | "rust-tooling" | "tailwind" | "vue" | "vitest";
2
+ export type EditorCustomization = {
3
+ readonly extensions: readonly string[];
4
+ readonly settings: Record<string, unknown>;
5
+ };
6
+ export type EditorCustomizationOptions = {
7
+ readonly oxcConfigPaths?: "nested" | {
8
+ readonly lint?: string;
9
+ readonly formatter?: string;
10
+ };
11
+ };
12
+ export declare function editorCustomizationForCapabilities(capabilities: readonly EditorCustomizationCapability[], options?: EditorCustomizationOptions): EditorCustomization;
13
+ //# sourceMappingURL=editor-customization.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"editor-customization.d.ts","sourceRoot":"","sources":["../../src/editor-customization.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,6BAA6B,GACrC,iBAAiB,GACjB,cAAc,GACd,UAAU,GACV,KAAK,GACL,QAAQ,CAAC;AAEb,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC5C,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,QAAQ,CAAC,cAAc,CAAC,EACpB,QAAQ,GACR;QACE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;KAC7B,CAAC;CACP,CAAC;AA0GF,wBAAgB,kCAAkC,CAChD,YAAY,EAAE,SAAS,6BAA6B,EAAE,EACtD,OAAO,CAAC,EAAE,0BAA0B,GACnC,mBAAmB,CAwBrB"}
@@ -0,0 +1,101 @@
1
+ const capabilityOrder = [
2
+ "oxc-format-lint",
3
+ "vue",
4
+ "tailwind",
5
+ "rust-tooling",
6
+ "vitest",
7
+ ];
8
+ const oxcFormatterSettings = {
9
+ "editor.defaultFormatter": "oxc.oxc-vscode",
10
+ };
11
+ const defaultOxcConfigPaths = {
12
+ formatter: "./oxfmt.config.ts",
13
+ lint: "./oxlint.config.ts",
14
+ };
15
+ function oxcConfigPathSettings(configPaths) {
16
+ if (configPaths === "nested") {
17
+ return {};
18
+ }
19
+ const paths = {
20
+ ...defaultOxcConfigPaths,
21
+ ...configPaths,
22
+ };
23
+ return {
24
+ "oxc.configPath": paths.lint,
25
+ "oxc.fmt.configPath": paths.formatter,
26
+ };
27
+ }
28
+ function oxcProjection(options) {
29
+ return {
30
+ extensions: ["oxc.oxc-vscode"],
31
+ settings: {
32
+ "editor.codeActionsOnSave": {
33
+ "source.format.oxc": "always",
34
+ "source.fixAll.oxc": "always",
35
+ },
36
+ ...oxcFormatterSettings,
37
+ "editor.formatOnPaste": true,
38
+ "editor.formatOnSave": true,
39
+ "editor.formatOnSaveMode": "file",
40
+ "oxc.enable": true,
41
+ ...oxcConfigPathSettings(options?.oxcConfigPaths),
42
+ "[javascript]": oxcFormatterSettings,
43
+ "[json]": oxcFormatterSettings,
44
+ "[markdown]": oxcFormatterSettings,
45
+ "[typescript]": oxcFormatterSettings,
46
+ },
47
+ };
48
+ }
49
+ const capabilityProjections = {
50
+ "oxc-format-lint": oxcProjection(),
51
+ "rust-tooling": {
52
+ extensions: ["rust-lang.rust-analyzer", "tamasfe.even-better-toml"],
53
+ settings: {
54
+ "rust-analyzer.cargo.features": "all",
55
+ "rust-analyzer.check.command": "clippy",
56
+ "rust-analyzer.procMacro.enable": true,
57
+ "[rust]": {
58
+ "editor.defaultFormatter": "rust-lang.rust-analyzer",
59
+ },
60
+ "[toml]": {
61
+ "editor.defaultFormatter": "tamasfe.even-better-toml",
62
+ },
63
+ },
64
+ },
65
+ tailwind: {
66
+ extensions: ["bradlc.vscode-tailwindcss"],
67
+ settings: {},
68
+ },
69
+ vue: {
70
+ extensions: ["Vue.volar"],
71
+ settings: {},
72
+ },
73
+ vitest: {
74
+ extensions: ["vitest.explorer"],
75
+ settings: {},
76
+ },
77
+ };
78
+ function mergeSettings(base, patch) {
79
+ return { ...base, ...patch };
80
+ }
81
+ export function editorCustomizationForCapabilities(capabilities, options) {
82
+ const selected = new Set(capabilities);
83
+ const extensions = new Set();
84
+ let settings = {};
85
+ for (const capability of capabilityOrder) {
86
+ if (!selected.has(capability)) {
87
+ continue;
88
+ }
89
+ const projection = capability === "oxc-format-lint"
90
+ ? oxcProjection(options)
91
+ : capabilityProjections[capability];
92
+ for (const extension of projection.extensions) {
93
+ extensions.add(extension);
94
+ }
95
+ settings = mergeSettings(settings, projection.settings);
96
+ }
97
+ return {
98
+ extensions: [...extensions],
99
+ settings,
100
+ };
101
+ }
@@ -1,4 +1,4 @@
1
- import type { PackageManager, PresetName, ProjectBlueprint } from "./declarations.js";
1
+ import type { PackageManager, ProjectBlueprint } from "./declarations.js";
2
2
  import type { ResolvedToolchainVersions } from "./toolchain-resolution.js";
3
3
  export type ProjectName = {
4
4
  readonly kind: "ProjectName";
@@ -10,7 +10,7 @@ export type GenerationPackageManager = {
10
10
  };
11
11
  export type GenerationContext = {
12
12
  readonly projectName: ProjectName;
13
- readonly preset: PresetName;
13
+ readonly preset: string;
14
14
  readonly packageManager?: GenerationPackageManager;
15
15
  readonly blueprint: ProjectBlueprint;
16
16
  readonly toolchain: ResolvedToolchainVersions;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generation-context.d.ts","sourceRoot":"","sources":["../../src/generation-context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1E,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AAE3E,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAChC,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAClC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,cAAc,CAAC,EAAE,wBAAwB,CAAC;IACnD,QAAQ,CAAC,SAAS,EAAE,gBAAgB,CAAC;IACrC,QAAQ,CAAC,SAAS,EAAE,yBAAyB,CAAC;CAC/C,CAAC;AAEF,MAAM,MAAM,gCAAgC,GAAG;IAC7C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,gBAAgB,CAAC;IACrC,QAAQ,CAAC,SAAS,EAAE,yBAAyB,CAAC;CAC/C,CAAC;AAEF,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,gCAAgC,GACxC,iBAAiB,CAUnB"}
@@ -1,4 +1,3 @@
1
- import type { PresetName } from "./declarations.js";
2
1
  export type PackageBoundaryOwner = {
3
2
  readonly kind: "package-boundary";
4
3
  readonly path: "." | "apps/api" | "apps/web";
@@ -26,19 +25,6 @@ export type CheckPlan = {
26
25
  export type FixPlan = {
27
26
  readonly components: FixComponent[];
28
27
  };
29
- export type NodeCheckPlanTarget = "ts-lib" | "hono-api" | "vue-app" | "vue-hono-root" | "vue-hono-api" | "vue-hono-web";
30
- export type NodeFixPlanTarget = "ts-lib" | "hono-api" | "vue-app" | "vue-hono-root" | "vue-hono-api" | "vue-hono-web";
31
- export declare function selectNodeCheckComponents(target: NodeCheckPlanTarget): CheckComponent[];
32
- export declare function selectNodeFixComponents(target: NodeFixPlanTarget): FixComponent[];
33
- export declare function selectTsLibCheckComponents(): CheckComponent[];
34
- export declare function selectTsLibFixComponents(): FixComponent[];
35
- export declare function planNodeChecks(target: NodeCheckPlanTarget): CheckPlan;
36
- export declare function planNodeFixes(target: NodeFixPlanTarget): FixPlan;
37
- export declare function planRustBinChecks(): CheckPlan;
38
- export declare function planRustBinFixes(): FixPlan;
39
- export declare function planPresetChecks(preset: PresetName): CheckPlan | undefined;
40
- export declare function planTsLibChecks(): CheckPlan;
41
- export declare function planTsLibFixes(): FixPlan;
42
28
  export declare function renderRootCheckCommand(plan: CheckPlan): string;
43
29
  export declare function renderFixCommand(plan: FixPlan): string;
44
30
  export declare function renderPlaywrightBrowserInstallCommand(need: CheckEnvironmentNeed): string;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module-graph.d.ts","sourceRoot":"","sources":["../../src/module-graph.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,oBAAoB,GAAG;IACjC,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAClC,QAAQ,CAAC,IAAI,EAAE,GAAG,GAAG,UAAU,GAAG,UAAU,CAAC;CAC9C,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,oBAAoB,CAAC;AAElD,MAAM,MAAM,kBAAkB,GAC1B,sBAAsB,GACtB,UAAU,GACV,kBAAkB,GAClB,OAAO,GACP,WAAW,GACX,UAAU,GACV,aAAa,GACb,eAAe,GACf,cAAc,GACd,YAAY,CAAC;AAEjB,MAAM,MAAM,gBAAgB,GACxB,kBAAkB,GAClB,cAAc,GACd,WAAW,GACX,eAAe,CAAC;AAEpB,MAAM,MAAM,oBAAoB,GAAG;IACjC,QAAQ,CAAC,IAAI,EAAE,2BAA2B,CAAC;IAC3C,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAClC,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAChC,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,CAAC,UAAU,EAAE,cAAc,EAAE,CAAC;IACtC,QAAQ,CAAC,gBAAgB,EAAE,oBAAoB,EAAE,CAAC;CACnD,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IACpB,QAAQ,CAAC,UAAU,EAAE,YAAY,EAAE,CAAC;CACrC,CAAC;AAwCF,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAE9D;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAEtD;AAED,wBAAgB,qCAAqC,CACnD,IAAI,EAAE,oBAAoB,GACzB,MAAM,CAMR"}