@ykdz/template 0.0.0 → 0.0.2

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 (75) hide show
  1. package/dist/cli.js +94 -44
  2. package/dist/declarations.js +1 -1
  3. package/dist/devcontainer.d.ts +17 -0
  4. package/dist/devcontainer.d.ts.map +1 -0
  5. package/dist/devcontainer.js +23 -0
  6. package/dist/generation-context.d.ts +24 -0
  7. package/dist/generation-context.d.ts.map +1 -0
  8. package/dist/generation-context.js +12 -0
  9. package/dist/hono-api.d.ts +1 -0
  10. package/dist/hono-api.d.ts.map +1 -1
  11. package/dist/hono-api.js +63 -100
  12. package/dist/module-graph.d.ts +45 -0
  13. package/dist/module-graph.d.ts.map +1 -0
  14. package/dist/module-graph.js +187 -0
  15. package/dist/next-step-instructions.d.ts +22 -0
  16. package/dist/next-step-instructions.d.ts.map +1 -0
  17. package/dist/next-step-instructions.js +99 -0
  18. package/dist/package-addition.d.ts.map +1 -1
  19. package/dist/package-addition.js +31 -51
  20. package/dist/project-github.d.ts +36 -0
  21. package/dist/project-github.d.ts.map +1 -0
  22. package/dist/project-github.js +96 -0
  23. package/dist/renderer.d.ts +2 -0
  24. package/dist/renderer.d.ts.map +1 -1
  25. package/dist/renderer.js +7 -4
  26. package/dist/rust-bin.d.ts +7 -1
  27. package/dist/rust-bin.d.ts.map +1 -1
  28. package/dist/rust-bin.js +68 -66
  29. package/dist/toolchain-resolution.d.ts +35 -0
  30. package/dist/toolchain-resolution.d.ts.map +1 -0
  31. package/dist/toolchain-resolution.js +192 -0
  32. package/dist/ts-lib.d.ts +7 -1
  33. package/dist/ts-lib.d.ts.map +1 -1
  34. package/dist/ts-lib.js +95 -101
  35. package/dist/vue-app.d.ts +1 -0
  36. package/dist/vue-app.d.ts.map +1 -1
  37. package/dist/vue-app.js +78 -116
  38. package/dist/vue-hono-app.d.ts +3 -0
  39. package/dist/vue-hono-app.d.ts.map +1 -1
  40. package/dist/vue-hono-app.js +126 -170
  41. package/package.json +24 -16
  42. package/templates/hono-api/.github/dependabot.yml +10 -0
  43. package/templates/hono-api/.github/workflows/check.yml +19 -0
  44. package/templates/hono-api/src/server.ts +3 -2
  45. package/templates/hono-api/vitest.config.ts +5 -4
  46. package/templates/rust-bin/.github/dependabot.yml +14 -0
  47. package/templates/rust-bin/.github/workflows/check.yml +23 -0
  48. package/templates/shared/oxc/node/oxlint.config.ts +9 -0
  49. package/templates/shared/oxc/oxfmt.config.ts +8 -0
  50. package/templates/shared/oxc/package.json +18 -0
  51. package/templates/shared/oxc/tsconfig.json +11 -0
  52. package/templates/shared/oxc/vue/oxlint.config.ts +9 -0
  53. package/templates/ts-lib/.github/dependabot.yml +10 -0
  54. package/templates/ts-lib/.github/workflows/check.yml +19 -0
  55. package/templates/vue-app/.github/dependabot.yml +10 -0
  56. package/templates/vue-app/.github/workflows/check.yml +20 -0
  57. package/templates/vue-app/playwright.config.ts +5 -5
  58. package/templates/vue-app/src/App.vue +15 -5
  59. package/templates/vue-app/src/main.ts +2 -0
  60. package/templates/vue-app/test/app.test.ts +1 -0
  61. package/templates/vue-app/test/e2e/app.spec.ts +3 -1
  62. package/templates/vue-app/vite.config.ts +6 -5
  63. package/templates/vue-app/vitest.config.ts +5 -4
  64. package/templates/vue-hono-app/.github/dependabot.yml +10 -0
  65. package/templates/vue-hono-app/.github/workflows/check.yml +20 -0
  66. package/templates/vue-hono-app/api/src/server.ts +3 -2
  67. package/templates/vue-hono-app/api/vitest.config.ts +2 -2
  68. package/templates/vue-hono-app/web/playwright.config.ts +9 -7
  69. package/templates/vue-hono-app/web/src/App.vue +12 -4
  70. package/templates/vue-hono-app/web/src/api.ts +1 -1
  71. package/templates/vue-hono-app/web/src/main.ts +2 -0
  72. package/templates/vue-hono-app/web/test/app.test.ts +1 -0
  73. package/templates/vue-hono-app/web/test/e2e/app.spec.ts +3 -1
  74. package/templates/vue-hono-app/web/vite.config.ts +13 -10
  75. package/templates/vue-hono-app/web/vitest.config.ts +6 -5
package/dist/cli.js CHANGED
@@ -8,7 +8,10 @@ import { initTsLibProject } from "./ts-lib.js";
8
8
  import { initVueHonoAppProject } from "./vue-hono-app.js";
9
9
  import { initVueAppProject } from "./vue-app.js";
10
10
  import { addPackage } from "./package-addition.js";
11
- import { blueprintJsonSchema, builtInPresets, presetFileJsonSchema, validatePresetFile, validateProjectBlueprint } from "./declarations.js";
11
+ import { assembleGenerationContext } from "./generation-context.js";
12
+ import { planNextStepInstructions, } from "./next-step-instructions.js";
13
+ import { blueprintJsonSchema, builtInPresets, presetFileJsonSchema, validatePresetFile, validateProjectBlueprint, } from "./declarations.js";
14
+ import { resolveToolchainVersions, } from "./toolchain-resolution.js";
12
15
  function usage() {
13
16
  return [
14
17
  "Usage:",
@@ -26,7 +29,7 @@ function usage() {
26
29
  " --scope <name> Package scope for workspace package names",
27
30
  " --yes Accept defaults for non-interactive generation",
28
31
  " --dry-run Print the planned generation without writing files",
29
- " --json Print machine-readable output"
32
+ " --json Print machine-readable output",
30
33
  ].join("\n");
31
34
  }
32
35
  function printJson(value) {
@@ -52,7 +55,7 @@ function formatValidationIssues(issues) {
52
55
  function formatPresetCatalog() {
53
56
  return [
54
57
  "Built-in presets",
55
- ...builtInPresets.map((preset) => ` ${preset.name.padEnd(8)} ${preset.title} (${preset.generation}) - ${preset.description}`)
58
+ ...builtInPresets.map((preset) => ` ${preset.name.padEnd(8)} ${preset.title} (${preset.generation}) - ${preset.description}`),
56
59
  ].join("\n");
57
60
  }
58
61
  function parseInitOptions(args) {
@@ -132,7 +135,7 @@ function blueprintForInit(options) {
132
135
  schemaVersion: 1,
133
136
  preset: preset.name,
134
137
  projectKind: preset.supportedProjectKinds[0],
135
- features: [...preset.features]
138
+ features: [...preset.features],
136
139
  };
137
140
  if (preset.supportedPackageManagers[0]) {
138
141
  blueprint.packageManager = preset.supportedPackageManagers[0];
@@ -140,7 +143,7 @@ function blueprintForInit(options) {
140
143
  if (preset.name === "vue-hono-app") {
141
144
  blueprint.packages = [
142
145
  { name: `@${packageScope}/web`, path: "apps/web" },
143
- { name: `@${packageScope}/api`, path: "apps/api" }
146
+ { name: `@${packageScope}/api`, path: "apps/api" },
144
147
  ];
145
148
  }
146
149
  return blueprint;
@@ -150,7 +153,7 @@ function formatBlueprintSummary(targetDir, blueprint) {
150
153
  "Project Blueprint",
151
154
  ` Target: ${targetDir}`,
152
155
  ` Preset: ${blueprint.preset}`,
153
- ` Project kind: ${blueprint.projectKind}`
156
+ ` Project kind: ${blueprint.projectKind}`,
154
157
  ];
155
158
  if (blueprint.packageManager) {
156
159
  lines.push(` Package manager: ${blueprint.packageManager}`);
@@ -164,31 +167,92 @@ function formatBlueprintSummary(targetDir, blueprint) {
164
167
  lines.push(` Features: ${blueprint.features.join(", ")}`);
165
168
  return lines.join("\n");
166
169
  }
167
- function nextStepsForPreset(preset) {
168
- if (preset === "rust-bin") {
169
- return ["cd <target>", "./scripts/check"];
170
- }
171
- return ["cd <target>", "pnpm install", "pnpm run check"];
172
- }
173
170
  function formatNextSteps(targetDir, preset) {
171
+ const plan = planNextStepInstructions({ preset, targetDir });
174
172
  return [
175
- "Next steps:",
176
- ...nextStepsForPreset(preset).map((step) => ` ${step.replace("<target>", targetDir)}`)
173
+ "Next Step Instructions:",
174
+ ...plan.steps.map((step) => ` ${step.label}: ${step.display}`),
177
175
  ].join("\n");
178
176
  }
179
- function printInitComplete(options, blueprint) {
177
+ function toolchainReport(toolchain) {
178
+ return {
179
+ nodeLtsMajor: toolchain.nodeLtsMajor.value,
180
+ packageManagerPin: toolchain.packageManagerPin.value,
181
+ source: toolchain.source,
182
+ diagnostics: [...toolchain.diagnostics],
183
+ };
184
+ }
185
+ function formatToolchainReport(toolchain) {
186
+ return [
187
+ "Toolchain Resolution:",
188
+ ` Source: ${toolchain.source}`,
189
+ ` Node LTS major: ${toolchain.nodeLtsMajor.value}`,
190
+ ` Package Manager Pin: ${toolchain.packageManagerPin.value}`,
191
+ ...toolchain.diagnostics.map((diagnostic) => ` ${diagnostic}`),
192
+ ].join("\n");
193
+ }
194
+ function toolchainResolutionSourceFromEnv() {
195
+ if (process.env.TEMPLATE_TOOLCHAIN_RESOLUTION === "online" ||
196
+ process.env.TEMPLATE_TOOLCHAIN_RESOLUTION === "bundled-fallback") {
197
+ return process.env.TEMPLATE_TOOLCHAIN_RESOLUTION;
198
+ }
199
+ return undefined;
200
+ }
201
+ async function generationContextForInit(options, blueprint) {
202
+ if (options.preset !== "ts-lib" && options.preset !== "rust-bin") {
203
+ return undefined;
204
+ }
205
+ return assembleGenerationContext({
206
+ targetDir: options.dir,
207
+ blueprint,
208
+ toolchain: await resolveToolchainVersions({
209
+ source: toolchainResolutionSourceFromEnv(),
210
+ nodeReleaseIndexUrl: process.env.TEMPLATE_TOOLCHAIN_NODE_RELEASE_INDEX_URL,
211
+ pnpmRegistryUrl: process.env.TEMPLATE_TOOLCHAIN_PNPM_REGISTRY_URL,
212
+ }),
213
+ });
214
+ }
215
+ 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 });
234
+ return;
235
+ }
236
+ throw new Error("Only the ts-lib, hono-api, vue-app, vue-hono-app, and rust-bin presets are supported in this version");
237
+ }
238
+ function printInitComplete(options, blueprint, generationContext) {
180
239
  const preset = blueprint.preset;
240
+ const nextSteps = planNextStepInstructions({ preset, targetDir: options.dir }).steps;
181
241
  if (options.json) {
182
242
  printJson({
183
243
  command: "init",
184
244
  dryRun: false,
185
245
  targetDir: options.dir,
186
246
  blueprint,
187
- nextSteps: nextStepsForPreset(preset).map((step) => step.replace("<target>", options.dir))
247
+ toolchain: generationContext ? toolchainReport(generationContext.toolchain) : undefined,
248
+ nextSteps,
188
249
  });
189
250
  return;
190
251
  }
191
252
  console.log(`Initialized ${options.preset} project in ${options.dir}`);
253
+ if (generationContext) {
254
+ console.log(formatToolchainReport(generationContext.toolchain));
255
+ }
192
256
  console.log(formatNextSteps(options.dir, preset));
193
257
  }
194
258
  function isInteractiveTerminal() {
@@ -198,7 +262,7 @@ async function confirmInit(targetDir, blueprint) {
198
262
  console.log(formatBlueprintSummary(targetDir, blueprint));
199
263
  const readline = createInterface({
200
264
  input: process.stdin,
201
- output: process.stdout
265
+ output: process.stdout,
202
266
  });
203
267
  try {
204
268
  const answer = await readline.question("Generate this project? [y/N] ");
@@ -287,16 +351,24 @@ async function main(args) {
287
351
  const options = parseInitOptions(args);
288
352
  const blueprint = blueprintForInit(options);
289
353
  if (options.dryRun) {
354
+ const generationContext = await generationContextForInit(options, blueprint);
355
+ const nextSteps = planNextStepInstructions({
356
+ preset: blueprint.preset,
357
+ targetDir: options.dir,
358
+ }).steps;
290
359
  if (options.json) {
291
360
  printJson({
292
361
  command: "init",
293
362
  dryRun: true,
294
363
  targetDir: options.dir,
295
- blueprint
364
+ blueprint,
365
+ toolchain: generationContext ? toolchainReport(generationContext.toolchain) : undefined,
366
+ nextSteps,
296
367
  });
297
368
  return;
298
369
  }
299
370
  console.log(formatBlueprintSummary(options.dir, blueprint));
371
+ console.log(formatNextSteps(options.dir, blueprint.preset));
300
372
  return;
301
373
  }
302
374
  if (!options.yes && (options.json || !isInteractiveTerminal())) {
@@ -305,32 +377,10 @@ async function main(args) {
305
377
  if (!options.yes && !(await confirmInit(options.dir, blueprint))) {
306
378
  throw new Error("Init cancelled");
307
379
  }
308
- if (options.preset === "ts-lib") {
309
- await initTsLibProject(options.dir);
310
- printInitComplete(options, blueprint);
311
- return;
312
- }
313
- if (options.preset === "hono-api") {
314
- await initHonoApiProject(options.dir);
315
- printInitComplete(options, blueprint);
316
- return;
317
- }
318
- if (options.preset === "vue-app") {
319
- await initVueAppProject(options.dir);
320
- printInitComplete(options, blueprint);
321
- return;
322
- }
323
- if (options.preset === "vue-hono-app") {
324
- await initVueHonoAppProject(options.dir, { scope: options.scope });
325
- printInitComplete(options, blueprint);
326
- return;
327
- }
328
- if (options.preset === "rust-bin") {
329
- await initRustBinProject(options.dir);
330
- printInitComplete(options, blueprint);
331
- return;
332
- }
333
- throw new Error("Only the ts-lib, hono-api, vue-app, vue-hono-app, and rust-bin presets are supported in this version");
380
+ const generationContext = await generationContextForInit(options, blueprint);
381
+ await generateInitProject(options, generationContext);
382
+ printInitComplete(options, blueprint, generationContext);
383
+ return;
334
384
  }
335
385
  if (command === "add" && args[1] === "package") {
336
386
  const options = parseAddPackageOptions(args);
@@ -77,7 +77,7 @@ export const builtInPresets = [
77
77
  title: "Rust binary",
78
78
  description: "Single-package Rust native binary with rustfmt, clippy, and cargo tests.",
79
79
  generation: "supported",
80
- supportedPackageManagers: [],
80
+ supportedPackageManagers: ["pnpm"],
81
81
  supportedProjectKinds: ["single-package"],
82
82
  features: [
83
83
  "root-check",
@@ -0,0 +1,17 @@
1
+ export type DevcontainerNodeFeatureOptions = {
2
+ readonly nodeVersion: string;
3
+ readonly packageManagerPin: string;
4
+ };
5
+ export type DevcontainerNodeFeature = {
6
+ readonly version: string;
7
+ readonly pnpmVersion: string;
8
+ };
9
+ export declare function pnpmVersionFromPackageManagerPin(packageManagerPin: string): string;
10
+ export declare function devcontainerNodeFeature(options: DevcontainerNodeFeatureOptions): Record<"ghcr.io/devcontainers/features/node:1", DevcontainerNodeFeature>;
11
+ export declare function nodePnpmDevcontainer(options: {
12
+ readonly name: string;
13
+ readonly nodeVersion: string;
14
+ readonly packageManagerPin: string;
15
+ readonly extensions: readonly string[];
16
+ }): Record<string, unknown>;
17
+ //# 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,CAAC,iBAAiB,EAAE,MAAM,GAAG,MAAM,CAElF;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;CACxC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAW1B"}
@@ -0,0 +1,23 @@
1
+ export function pnpmVersionFromPackageManagerPin(packageManagerPin) {
2
+ return packageManagerPin.replace(/^pnpm@/, "");
3
+ }
4
+ export function devcontainerNodeFeature(options) {
5
+ return {
6
+ "ghcr.io/devcontainers/features/node:1": {
7
+ version: options.nodeVersion,
8
+ pnpmVersion: pnpmVersionFromPackageManagerPin(options.packageManagerPin),
9
+ },
10
+ };
11
+ }
12
+ export function nodePnpmDevcontainer(options) {
13
+ return {
14
+ name: options.name,
15
+ image: `mcr.microsoft.com/devcontainers/typescript-node:${options.nodeVersion}`,
16
+ features: devcontainerNodeFeature(options),
17
+ customizations: {
18
+ vscode: {
19
+ extensions: options.extensions,
20
+ },
21
+ },
22
+ };
23
+ }
@@ -0,0 +1,24 @@
1
+ import type { PackageManager, PresetName, ProjectBlueprint } from "./declarations.js";
2
+ import type { ResolvedToolchainVersions } from "./toolchain-resolution.js";
3
+ export type ProjectName = {
4
+ readonly kind: "ProjectName";
5
+ readonly value: string;
6
+ };
7
+ export type GenerationPackageManager = {
8
+ readonly kind: "PackageManager";
9
+ readonly value: PackageManager;
10
+ };
11
+ export type GenerationContext = {
12
+ readonly projectName: ProjectName;
13
+ readonly preset: PresetName;
14
+ readonly packageManager?: GenerationPackageManager;
15
+ readonly blueprint: ProjectBlueprint;
16
+ readonly toolchain: ResolvedToolchainVersions;
17
+ };
18
+ export type AssembleGenerationContextOptions = {
19
+ readonly targetDir: string;
20
+ readonly blueprint: ProjectBlueprint;
21
+ readonly toolchain: ResolvedToolchainVersions;
22
+ };
23
+ export declare function assembleGenerationContext(options: AssembleGenerationContextOptions): GenerationContext;
24
+ //# sourceMappingURL=generation-context.d.ts.map
@@ -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,UAAU,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACtF,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,UAAU,CAAC;IAC5B,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"}
@@ -0,0 +1,12 @@
1
+ import path from "node:path";
2
+ export function assembleGenerationContext(options) {
3
+ return {
4
+ projectName: { kind: "ProjectName", value: path.basename(path.resolve(options.targetDir)) },
5
+ preset: options.blueprint.preset,
6
+ packageManager: options.blueprint.packageManager
7
+ ? { kind: "PackageManager", value: options.blueprint.packageManager }
8
+ : undefined,
9
+ blueprint: options.blueprint,
10
+ toolchain: options.toolchain,
11
+ };
12
+ }
@@ -1,2 +1,3 @@
1
+ export declare function projectHonoApiPackageScripts(): Record<string, string>;
1
2
  export declare function initHonoApiProject(targetDir: string): Promise<void>;
2
3
  //# sourceMappingURL=hono-api.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"hono-api.d.ts","sourceRoot":"","sources":["../src/hono-api.ts"],"names":[],"mappings":"AAwPA,wBAAsB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMzE"}
1
+ {"version":3,"file":"hono-api.d.ts","sourceRoot":"","sources":["../src/hono-api.ts"],"names":[],"mappings":"AAiCA,wBAAgB,4BAA4B,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAarE;AAgLD,wBAAsB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAOzE"}
package/dist/hono-api.js CHANGED
@@ -1,5 +1,8 @@
1
1
  import path from "node:path";
2
2
  import { fileURLToPath } from "node:url";
3
+ import { nodePnpmDevcontainer } from "./devcontainer.js";
4
+ import { planNodeChecks, planNodeFixes, renderFixCommand, renderRootCheckCommand, } from "./module-graph.js";
5
+ import { projectPresetDependabotConfig, projectPresetGithubCheckWorkflow } from "./project-github.js";
3
6
  import { renderNewProject } from "./renderer.js";
4
7
  const features = [
5
8
  "pnpm-catalog",
@@ -9,37 +12,40 @@ const features = [
9
12
  "fix-command",
10
13
  "devcontainer",
11
14
  "github-actions",
12
- "dependabot"
15
+ "dependabot",
13
16
  ];
14
17
  const generatedBy = {
15
18
  packageName: "@ykdz/template",
16
19
  version: "0.0.0",
17
- command: "template init --preset hono-api"
20
+ command: "template init --preset hono-api",
18
21
  };
19
22
  function projectNameFromDir(targetDir) {
20
23
  return path.basename(path.resolve(targetDir));
21
24
  }
25
+ export function projectHonoApiPackageScripts() {
26
+ return {
27
+ build: "tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json",
28
+ check: renderRootCheckCommand(planNodeChecks("hono-api")),
29
+ fix: renderFixCommand(planNodeFixes("hono-api")),
30
+ "format:check": "oxfmt --check .",
31
+ "format:write": "oxfmt --write .",
32
+ lint: "oxlint . --deny-warnings",
33
+ "lint:fix": "oxlint . --fix --deny-warnings",
34
+ start: "node dist/server.js",
35
+ test: "vitest run",
36
+ typecheck: "tsc -p tsconfig.json --noEmit",
37
+ };
38
+ }
22
39
  function packageJson(projectName) {
23
40
  return {
24
41
  name: projectName,
25
42
  version: "0.0.0",
26
43
  private: true,
27
44
  type: "module",
28
- scripts: {
29
- build: "tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json",
30
- check: "pnpm run format:check && pnpm run lint && pnpm run typecheck && pnpm run build && pnpm run test",
31
- fix: "pnpm run format:write && pnpm run lint:fix",
32
- "format:check": "oxfmt --check .",
33
- "format:write": "oxfmt --write .",
34
- lint: "oxlint . --deny-warnings",
35
- "lint:fix": "oxlint . --fix --deny-warnings",
36
- start: "node dist/server.js",
37
- test: "vitest run",
38
- typecheck: "tsc -p tsconfig.json --noEmit"
39
- },
45
+ scripts: projectHonoApiPackageScripts(),
40
46
  dependencies: {
41
47
  "@hono/node-server": "catalog:",
42
- hono: "catalog:"
48
+ hono: "catalog:",
43
49
  },
44
50
  devDependencies: {
45
51
  "@types/node": "catalog:",
@@ -47,12 +53,12 @@ function packageJson(projectName) {
47
53
  oxlint: "catalog:",
48
54
  "tsc-alias": "catalog:",
49
55
  typescript: "catalog:",
50
- vitest: "catalog:"
56
+ vitest: "catalog:",
51
57
  },
52
58
  engines: {
53
- node: ">=22.0.0"
59
+ node: "22",
54
60
  },
55
- packageManager: "pnpm@10.0.0"
61
+ packageManager: "pnpm@10.0.0",
56
62
  };
57
63
  }
58
64
  function operationsForHonoApi(projectName) {
@@ -60,7 +66,7 @@ function operationsForHonoApi(projectName) {
60
66
  {
61
67
  kind: "writeJson",
62
68
  to: "package.json",
63
- value: packageJson(projectName)
69
+ value: packageJson(projectName),
64
70
  },
65
71
  {
66
72
  kind: "writeText",
@@ -78,8 +84,8 @@ function operationsForHonoApi(projectName) {
78
84
  " tsc-alias: ^1.8.17",
79
85
  " typescript: ^5.8.0",
80
86
  " vitest: ^4.1.9",
81
- ""
82
- ].join("\n")
87
+ "",
88
+ ].join("\n"),
83
89
  },
84
90
  {
85
91
  kind: "writeJson",
@@ -90,15 +96,15 @@ function operationsForHonoApi(projectName) {
90
96
  moduleResolution: "NodeNext",
91
97
  noEmitOnError: true,
92
98
  paths: {
93
- "@/*": ["./src/*"]
99
+ "@/*": ["./src/*"],
94
100
  },
95
101
  skipLibCheck: false,
96
102
  strict: true,
97
103
  target: "ES2022",
98
- types: ["node", "vitest/globals"]
104
+ types: ["node", "vitest/globals"],
99
105
  },
100
- include: ["src/**/*.ts", "test/**/*.ts", "vitest.config.ts"]
101
- }
106
+ include: ["src/**/*.ts", "test/**/*.ts", "vitest.config.ts"],
107
+ },
102
108
  },
103
109
  {
104
110
  kind: "writeJson",
@@ -108,55 +114,47 @@ function operationsForHonoApi(projectName) {
108
114
  compilerOptions: {
109
115
  outDir: "dist",
110
116
  rootDir: "src",
111
- types: ["node"]
117
+ types: ["node"],
112
118
  },
113
- include: ["src/**/*.ts"]
114
- }
119
+ include: ["src/**/*.ts"],
120
+ },
115
121
  },
116
122
  {
117
- kind: "writeJson",
118
- to: ".oxlintrc.json",
119
- value: {
120
- categories: {
121
- correctness: "error",
122
- suspicious: "error"
123
- },
124
- plugins: ["typescript", "oxc"]
125
- }
123
+ kind: "copyFile",
124
+ sourceRoot: "sharedOxc",
125
+ from: "node/oxlint.config.ts",
126
+ to: "oxlint.config.ts",
126
127
  },
127
128
  {
128
- kind: "writeJson",
129
- to: ".oxfmtrc.json",
130
- value: {
131
- printWidth: 100,
132
- singleQuote: false,
133
- trailingComma: "none"
134
- }
129
+ kind: "copyFile",
130
+ sourceRoot: "sharedOxc",
131
+ from: "oxfmt.config.ts",
132
+ to: "oxfmt.config.ts",
135
133
  },
136
134
  {
137
135
  kind: "writeText",
138
136
  to: ".gitignore",
139
- text: ["node_modules", "dist", ".env", ""].join("\n")
137
+ text: ["node_modules", "dist", ".env", ""].join("\n"),
140
138
  },
141
139
  {
142
140
  kind: "copyFile",
143
141
  from: "src/app.ts",
144
- to: "src/app.ts"
142
+ to: "src/app.ts",
145
143
  },
146
144
  {
147
145
  kind: "copyFile",
148
146
  from: "src/server.ts",
149
- to: "src/server.ts"
147
+ to: "src/server.ts",
150
148
  },
151
149
  {
152
150
  kind: "copyFile",
153
151
  from: "test/app.test.ts",
154
- to: "test/app.test.ts"
152
+ to: "test/app.test.ts",
155
153
  },
156
154
  {
157
155
  kind: "copyFile",
158
156
  from: "vitest.config.ts",
159
- to: "vitest.config.ts"
157
+ to: "vitest.config.ts",
160
158
  },
161
159
  {
162
160
  kind: "writeJson",
@@ -166,82 +164,47 @@ function operationsForHonoApi(projectName) {
166
164
  preset: "hono-api",
167
165
  packageManager: "pnpm",
168
166
  projectKind: "single-package",
169
- features
170
- }
167
+ features,
168
+ },
171
169
  },
172
170
  {
173
171
  kind: "writeJson",
174
172
  to: ".project-kit/generated-by.json",
175
- value: generatedBy
173
+ value: generatedBy,
176
174
  },
177
175
  {
178
176
  kind: "writeJson",
179
177
  to: ".devcontainer/devcontainer.json",
180
- value: {
178
+ value: nodePnpmDevcontainer({
181
179
  name: `${projectName} API development`,
182
- image: "mcr.microsoft.com/devcontainers/typescript-node:22",
183
- postCreateCommand: "corepack enable && pnpm install",
184
- customizations: {
185
- vscode: {
186
- extensions: ["oxc.oxc-vscode"]
187
- }
188
- }
189
- }
180
+ nodeVersion: "22",
181
+ packageManagerPin: "pnpm@10.0.0",
182
+ extensions: ["oxc.oxc-vscode"],
183
+ }),
190
184
  },
191
185
  {
192
186
  kind: "writeText",
193
187
  to: ".github/workflows/check.yml",
194
- text: [
195
- "name: Check",
196
- "",
197
- "on:",
198
- " pull_request:",
199
- " push:",
200
- " branches:",
201
- " - main",
202
- "",
203
- "jobs:",
204
- " check:",
205
- " runs-on: ubuntu-latest",
206
- " steps:",
207
- " - uses: actions/checkout@v4",
208
- " - uses: pnpm/action-setup@v4",
209
- " with:",
210
- " version: 10.0.0",
211
- " - uses: actions/setup-node@v4",
212
- " with:",
213
- " node-version: 22",
214
- " - run: pnpm install",
215
- " - run: pnpm run check",
216
- ""
217
- ].join("\n")
188
+ text: projectPresetGithubCheckWorkflow("hono-api"),
218
189
  },
219
190
  {
220
191
  kind: "writeText",
221
192
  to: ".github/dependabot.yml",
222
- text: [
223
- "version: 2",
224
- "updates:",
225
- " - package-ecosystem: npm",
226
- " directory: /",
227
- " schedule:",
228
- " interval: weekly",
229
- " - package-ecosystem: github-actions",
230
- " directory: /",
231
- " schedule:",
232
- " interval: weekly",
233
- ""
234
- ].join("\n")
235
- }
193
+ text: projectPresetDependabotConfig("hono-api"),
194
+ },
236
195
  ];
237
196
  }
238
197
  function templateSourceRoot() {
239
198
  return path.join(path.dirname(fileURLToPath(import.meta.url)), "..", "templates", "hono-api");
240
199
  }
200
+ function sharedOxcSourceRoot() {
201
+ return path.join(path.dirname(fileURLToPath(import.meta.url)), "..", "templates", "shared", "oxc");
202
+ }
241
203
  export async function initHonoApiProject(targetDir) {
242
204
  await renderNewProject({
243
205
  sourceRoot: templateSourceRoot(),
206
+ sourceRoots: { sharedOxc: sharedOxcSourceRoot() },
244
207
  targetRoot: targetDir,
245
- operations: operationsForHonoApi(projectNameFromDir(targetDir))
208
+ operations: operationsForHonoApi(projectNameFromDir(targetDir)),
246
209
  });
247
210
  }