@ykdz/template 0.0.1 → 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.
- package/dist/src/cli.d.ts.map +1 -0
- package/dist/{cli.js → src/cli.js} +126 -128
- package/dist/{declarations.d.ts → src/declarations.d.ts} +1 -2
- package/dist/src/declarations.d.ts.map +1 -0
- package/dist/{declarations.js → src/declarations.js} +2 -109
- package/dist/src/dependency-catalog.d.ts +10 -0
- package/dist/src/dependency-catalog.d.ts.map +1 -0
- package/dist/src/dependency-catalog.js +63 -0
- package/dist/src/devcontainer.d.ts +18 -0
- package/dist/src/devcontainer.d.ts.map +1 -0
- package/dist/src/devcontainer.js +24 -0
- package/dist/src/editor-customization.d.ts +13 -0
- package/dist/src/editor-customization.d.ts.map +1 -0
- package/dist/src/editor-customization.js +101 -0
- package/dist/src/generation-context.d.ts +24 -0
- package/dist/src/generation-context.d.ts.map +1 -0
- package/dist/src/generation-context.js +12 -0
- package/dist/src/module-graph.d.ts +31 -0
- package/dist/src/module-graph.d.ts.map +1 -0
- package/dist/src/module-graph.js +48 -0
- package/dist/src/next-step-instructions.d.ts +21 -0
- package/dist/src/next-step-instructions.d.ts.map +1 -0
- package/dist/src/next-step-instructions.js +89 -0
- package/dist/src/package-addition.d.ts.map +1 -0
- package/dist/src/package-addition.js +188 -0
- package/dist/src/preset-projection.d.ts +66 -0
- package/dist/src/preset-projection.d.ts.map +1 -0
- package/dist/src/preset-projection.js +7 -0
- package/dist/src/project-github.d.ts +29 -0
- package/dist/src/project-github.d.ts.map +1 -0
- package/dist/src/project-github.js +63 -0
- package/dist/src/renderer.d.ts.map +1 -0
- package/dist/{renderer.js → src/renderer.js} +0 -3
- package/dist/src/runtime-paths.d.ts +2 -0
- package/dist/src/runtime-paths.d.ts.map +1 -0
- package/dist/src/runtime-paths.js +11 -0
- package/dist/src/toolchain-resolution.d.ts +35 -0
- package/dist/src/toolchain-resolution.d.ts.map +1 -0
- package/dist/src/toolchain-resolution.js +192 -0
- package/dist/templates/hono-api/projection.d.ts +7 -0
- package/dist/templates/hono-api/projection.d.ts.map +1 -0
- package/dist/templates/hono-api/projection.js +377 -0
- package/dist/templates/projection-plans.d.ts +8 -0
- package/dist/templates/projection-plans.d.ts.map +1 -0
- package/dist/templates/projection-plans.js +94 -0
- package/dist/templates/registry.d.ts +8 -0
- package/dist/templates/registry.d.ts.map +1 -0
- package/dist/templates/registry.js +42 -0
- package/dist/templates/rust-bin/projection.d.ts +10 -0
- package/dist/templates/rust-bin/projection.d.ts.map +1 -0
- package/dist/templates/rust-bin/projection.js +282 -0
- package/dist/templates/ts-lib/projection.d.ts +7 -0
- package/dist/templates/ts-lib/projection.d.ts.map +1 -0
- package/dist/templates/ts-lib/projection.js +372 -0
- package/dist/templates/vue-app/projection.d.ts +7 -0
- package/dist/templates/vue-app/projection.d.ts.map +1 -0
- package/dist/templates/vue-app/projection.js +594 -0
- package/dist/templates/vue-hono-app/projection.d.ts +9 -0
- package/dist/templates/vue-hono-app/projection.d.ts.map +1 -0
- package/dist/templates/vue-hono-app/projection.js +589 -0
- package/package.json +30 -24
- package/pnpm-workspace.yaml +34 -0
- package/templates/hono-api/projection.ts +453 -0
- package/templates/projection-plans.ts +135 -0
- package/templates/registry.ts +59 -0
- package/templates/rust-bin/.github/dependabot.yml +4 -0
- package/templates/rust-bin/.github/workflows/check.yml +6 -1
- package/templates/rust-bin/projection.ts +346 -0
- package/templates/ts-lib/projection.ts +454 -0
- package/templates/vue-app/projection.ts +687 -0
- package/templates/vue-app/test/e2e/app.spec.ts +4 -1
- package/templates/vue-hono-app/projection.ts +669 -0
- package/templates/vue-hono-app/web/test/e2e/app.spec.ts +4 -1
- package/dist/cli.d.ts.map +0 -1
- package/dist/declarations.d.ts.map +0 -1
- package/dist/hono-api.d.ts +0 -2
- package/dist/hono-api.d.ts.map +0 -1
- package/dist/hono-api.js +0 -208
- package/dist/package-addition.d.ts.map +0 -1
- package/dist/package-addition.js +0 -560
- package/dist/post-commands.d.ts +0 -40
- package/dist/post-commands.d.ts.map +0 -1
- package/dist/post-commands.js +0 -154
- package/dist/renderer.d.ts.map +0 -1
- package/dist/rust-bin.d.ts +0 -2
- package/dist/rust-bin.d.ts.map +0 -1
- package/dist/rust-bin.js +0 -174
- package/dist/ts-lib.d.ts +0 -2
- package/dist/ts-lib.d.ts.map +0 -1
- package/dist/ts-lib.js +0 -181
- package/dist/vue-app.d.ts +0 -2
- package/dist/vue-app.d.ts.map +0 -1
- package/dist/vue-app.js +0 -299
- package/dist/vue-hono-app.d.ts +0 -4
- package/dist/vue-hono-app.d.ts.map +0 -1
- package/dist/vue-hono-app.js +0 -436
- package/templates/shared/oxc/package.json +0 -18
- package/templates/shared/oxc/tsconfig.json +0 -11
- /package/dist/{cli.d.ts → src/cli.d.ts} +0 -0
- /package/dist/{package-addition.d.ts → src/package-addition.d.ts} +0 -0
- /package/dist/{renderer.d.ts → src/renderer.d.ts} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":""}
|
|
@@ -2,14 +2,12 @@
|
|
|
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 {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { initVueHonoAppProject } from "./vue-hono-app.js";
|
|
9
|
-
import { initVueAppProject } from "./vue-app.js";
|
|
5
|
+
import { findBuiltInPresetProjection, projectPresetThroughRegistry, } from "../templates/registry.js";
|
|
6
|
+
import { blueprintJsonSchema, builtInPresets, presetFileJsonSchema, validatePresetFile, validateProjectBlueprint, } from "./declarations.js";
|
|
7
|
+
import { assembleGenerationContext, } from "./generation-context.js";
|
|
10
8
|
import { addPackage } from "./package-addition.js";
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
9
|
+
import { planNextStepInstructionsForProjection, } from "./preset-projection.js";
|
|
10
|
+
import { resolveToolchainVersions, } from "./toolchain-resolution.js";
|
|
13
11
|
function usage() {
|
|
14
12
|
return [
|
|
15
13
|
"Usage:",
|
|
@@ -26,9 +24,8 @@ function usage() {
|
|
|
26
24
|
" --name <name> Package name to add",
|
|
27
25
|
" --scope <name> Package scope for workspace package names",
|
|
28
26
|
" --yes Accept defaults for non-interactive generation",
|
|
29
|
-
" --ready Run template-maintained Post Commands after writing files",
|
|
30
27
|
" --dry-run Print the planned generation without writing files",
|
|
31
|
-
" --json Print machine-readable output"
|
|
28
|
+
" --json Print machine-readable output",
|
|
32
29
|
].join("\n");
|
|
33
30
|
}
|
|
34
31
|
function printJson(value) {
|
|
@@ -49,12 +46,14 @@ async function readJsonDeclaration(filePath) {
|
|
|
49
46
|
}
|
|
50
47
|
}
|
|
51
48
|
function formatValidationIssues(issues) {
|
|
52
|
-
return issues
|
|
49
|
+
return issues
|
|
50
|
+
.map((issue) => ` - ${issue.path}: ${issue.message}`)
|
|
51
|
+
.join("\n");
|
|
53
52
|
}
|
|
54
53
|
function formatPresetCatalog() {
|
|
55
54
|
return [
|
|
56
55
|
"Built-in presets",
|
|
57
|
-
...builtInPresets.map((preset) => ` ${preset.name.padEnd(8)} ${preset.title} (${preset.generation}) - ${preset.description}`)
|
|
56
|
+
...builtInPresets.map((preset) => ` ${preset.name.padEnd(8)} ${preset.title} (${preset.generation}) - ${preset.description}`),
|
|
58
57
|
].join("\n");
|
|
59
58
|
}
|
|
60
59
|
function parseInitOptions(args) {
|
|
@@ -63,7 +62,6 @@ function parseInitOptions(args) {
|
|
|
63
62
|
let yes = false;
|
|
64
63
|
let dryRun = false;
|
|
65
64
|
let json = false;
|
|
66
|
-
let ready = false;
|
|
67
65
|
let scope;
|
|
68
66
|
for (let index = 2; index < args.length; index += 1) {
|
|
69
67
|
const arg = args[index];
|
|
@@ -75,10 +73,6 @@ function parseInitOptions(args) {
|
|
|
75
73
|
dryRun = true;
|
|
76
74
|
continue;
|
|
77
75
|
}
|
|
78
|
-
if (arg === "--ready") {
|
|
79
|
-
ready = true;
|
|
80
|
-
continue;
|
|
81
|
-
}
|
|
82
76
|
if (arg === "--json") {
|
|
83
77
|
json = true;
|
|
84
78
|
continue;
|
|
@@ -106,7 +100,7 @@ function parseInitOptions(args) {
|
|
|
106
100
|
if (!dir) {
|
|
107
101
|
throw new Error("init requires a target directory");
|
|
108
102
|
}
|
|
109
|
-
return { dir, preset, yes, dryRun, json,
|
|
103
|
+
return { dir, preset, yes, dryRun, json, scope };
|
|
110
104
|
}
|
|
111
105
|
function normalizeNpmScope(value) {
|
|
112
106
|
if (value !== value.trim() || /\s/.test(value)) {
|
|
@@ -121,35 +115,40 @@ function normalizeNpmScope(value) {
|
|
|
121
115
|
function supportedPreset(name) {
|
|
122
116
|
const preset = builtInPresets.find((candidate) => candidate.name === name && candidate.generation === "supported");
|
|
123
117
|
if (!preset) {
|
|
124
|
-
throw new Error(
|
|
118
|
+
throw new Error(formatSupportedPresetError());
|
|
125
119
|
}
|
|
126
120
|
return preset;
|
|
127
121
|
}
|
|
128
|
-
function
|
|
129
|
-
|
|
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`;
|
|
130
127
|
}
|
|
131
|
-
function
|
|
132
|
-
|
|
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)}`;
|
|
133
133
|
}
|
|
134
134
|
function blueprintForInit(options) {
|
|
135
135
|
const preset = supportedPreset(options.preset);
|
|
136
|
-
const
|
|
137
|
-
|
|
136
|
+
const projection = findBuiltInPresetProjection(preset.name);
|
|
137
|
+
if (projection) {
|
|
138
|
+
return projection.blueprint({
|
|
139
|
+
targetDir: options.dir,
|
|
140
|
+
scope: options.scope,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
138
143
|
const blueprint = {
|
|
139
144
|
schemaVersion: 1,
|
|
140
145
|
preset: preset.name,
|
|
141
146
|
projectKind: preset.supportedProjectKinds[0],
|
|
142
|
-
features: [...preset.features]
|
|
147
|
+
features: [...preset.features],
|
|
143
148
|
};
|
|
144
149
|
if (preset.supportedPackageManagers[0]) {
|
|
145
150
|
blueprint.packageManager = preset.supportedPackageManagers[0];
|
|
146
151
|
}
|
|
147
|
-
if (preset.name === "vue-hono-app") {
|
|
148
|
-
blueprint.packages = [
|
|
149
|
-
{ name: `@${packageScope}/web`, path: "apps/web" },
|
|
150
|
-
{ name: `@${packageScope}/api`, path: "apps/api" }
|
|
151
|
-
];
|
|
152
|
-
}
|
|
153
152
|
return blueprint;
|
|
154
153
|
}
|
|
155
154
|
function formatBlueprintSummary(targetDir, blueprint) {
|
|
@@ -157,7 +156,7 @@ function formatBlueprintSummary(targetDir, blueprint) {
|
|
|
157
156
|
"Project Blueprint",
|
|
158
157
|
` Target: ${targetDir}`,
|
|
159
158
|
` Preset: ${blueprint.preset}`,
|
|
160
|
-
` Project kind: ${blueprint.projectKind}
|
|
159
|
+
` Project kind: ${blueprint.projectKind}`,
|
|
161
160
|
];
|
|
162
161
|
if (blueprint.packageManager) {
|
|
163
162
|
lines.push(` Package manager: ${blueprint.packageManager}`);
|
|
@@ -171,103 +170,95 @@ function formatBlueprintSummary(targetDir, blueprint) {
|
|
|
171
170
|
lines.push(` Features: ${blueprint.features.join(", ")}`);
|
|
172
171
|
return lines.join("\n");
|
|
173
172
|
}
|
|
174
|
-
function
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
return ["Post Commands:", " (none)"].join("\n");
|
|
180
|
-
}
|
|
173
|
+
function formatProjectionNextSteps(targetDir, projectionPlan) {
|
|
174
|
+
const steps = planNextStepInstructionsForProjection({
|
|
175
|
+
targetDir,
|
|
176
|
+
plan: projectionPlan,
|
|
177
|
+
});
|
|
181
178
|
return [
|
|
182
|
-
"
|
|
183
|
-
...
|
|
179
|
+
"Next Step Instructions:",
|
|
180
|
+
...steps.map((step) => ` ${step.label}: ${step.display}`),
|
|
184
181
|
].join("\n");
|
|
185
182
|
}
|
|
186
|
-
function
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
183
|
+
function toolchainReport(toolchain) {
|
|
184
|
+
return {
|
|
185
|
+
nodeLtsMajor: toolchain.nodeLtsMajor.value,
|
|
186
|
+
packageManagerPin: toolchain.packageManagerPin.value,
|
|
187
|
+
source: toolchain.source,
|
|
188
|
+
diagnostics: [...toolchain.diagnostics],
|
|
189
|
+
};
|
|
191
190
|
}
|
|
192
|
-
function
|
|
191
|
+
function formatToolchainReport(toolchain) {
|
|
193
192
|
return [
|
|
194
|
-
"
|
|
195
|
-
|
|
193
|
+
"Toolchain Resolution:",
|
|
194
|
+
` Source: ${toolchain.source}`,
|
|
195
|
+
` Node LTS major: ${toolchain.nodeLtsMajor.value}`,
|
|
196
|
+
` Package Manager Pin: ${toolchain.packageManagerPin.value}`,
|
|
197
|
+
...toolchain.diagnostics.map((diagnostic) => ` ${diagnostic}`),
|
|
196
198
|
].join("\n");
|
|
197
199
|
}
|
|
198
|
-
function
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
args: [...command.args],
|
|
205
|
-
cwd: command.cwd
|
|
206
|
-
})),
|
|
207
|
-
run: executions
|
|
208
|
-
.filter((execution) => execution.status === "run")
|
|
209
|
-
.map((execution) => ({
|
|
210
|
-
id: execution.command.id,
|
|
211
|
-
exitCode: execution.exitCode
|
|
212
|
-
})),
|
|
213
|
-
failed: executions
|
|
214
|
-
.filter((execution) => execution.status === "failed")
|
|
215
|
-
.map((execution) => ({
|
|
216
|
-
id: execution.command.id,
|
|
217
|
-
exitCode: execution.exitCode,
|
|
218
|
-
error: execution.error
|
|
219
|
-
})),
|
|
220
|
-
skipped
|
|
221
|
-
};
|
|
222
|
-
}
|
|
223
|
-
function failedPostCommand(executions) {
|
|
224
|
-
return executions.find((execution) => execution.status === "failed");
|
|
200
|
+
function toolchainResolutionSourceFromEnv() {
|
|
201
|
+
if (process.env.TEMPLATE_TOOLCHAIN_RESOLUTION === "online" ||
|
|
202
|
+
process.env.TEMPLATE_TOOLCHAIN_RESOLUTION === "bundled-fallback") {
|
|
203
|
+
return process.env.TEMPLATE_TOOLCHAIN_RESOLUTION;
|
|
204
|
+
}
|
|
205
|
+
return undefined;
|
|
225
206
|
}
|
|
226
|
-
function
|
|
227
|
-
|
|
207
|
+
async function generationContextForInit(options, blueprint) {
|
|
208
|
+
if (!findBuiltInPresetProjection(options.preset)) {
|
|
209
|
+
return undefined;
|
|
210
|
+
}
|
|
211
|
+
return assembleGenerationContext({
|
|
212
|
+
targetDir: options.dir,
|
|
213
|
+
blueprint,
|
|
214
|
+
toolchain: await resolveToolchainVersions({
|
|
215
|
+
source: toolchainResolutionSourceFromEnv(),
|
|
216
|
+
nodeReleaseIndexUrl: process.env.TEMPLATE_TOOLCHAIN_NODE_RELEASE_INDEX_URL,
|
|
217
|
+
pnpmRegistryUrl: process.env.TEMPLATE_TOOLCHAIN_PNPM_REGISTRY_URL,
|
|
218
|
+
}),
|
|
219
|
+
});
|
|
228
220
|
}
|
|
229
|
-
async function generateInitProject(options) {
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
}
|
|
238
|
-
if (options.preset === "vue-app") {
|
|
239
|
-
await initVueAppProject(options.dir);
|
|
240
|
-
return;
|
|
241
|
-
}
|
|
242
|
-
if (options.preset === "vue-hono-app") {
|
|
243
|
-
await initVueHonoAppProject(options.dir, { scope: options.scope });
|
|
244
|
-
return;
|
|
245
|
-
}
|
|
246
|
-
if (options.preset === "rust-bin") {
|
|
247
|
-
await initRustBinProject(options.dir);
|
|
221
|
+
async function generateInitProject(options, 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 });
|
|
248
229
|
return;
|
|
249
230
|
}
|
|
250
|
-
throw new Error(
|
|
231
|
+
throw new Error(formatSupportedPresetError());
|
|
251
232
|
}
|
|
252
|
-
function printInitComplete(options, blueprint,
|
|
253
|
-
const
|
|
233
|
+
function printInitComplete(options, blueprint, generationContext) {
|
|
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
|
+
});
|
|
254
244
|
if (options.json) {
|
|
255
245
|
printJson({
|
|
256
246
|
command: "init",
|
|
257
247
|
dryRun: false,
|
|
258
|
-
ready: options.ready,
|
|
259
248
|
targetDir: options.dir,
|
|
260
249
|
blueprint,
|
|
261
|
-
|
|
262
|
-
|
|
250
|
+
toolchain: generationContext
|
|
251
|
+
? toolchainReport(generationContext.toolchain)
|
|
252
|
+
: undefined,
|
|
253
|
+
nextSteps,
|
|
263
254
|
});
|
|
264
255
|
return;
|
|
265
256
|
}
|
|
266
257
|
console.log(`Initialized ${options.preset} project in ${options.dir}`);
|
|
267
|
-
if (
|
|
268
|
-
console.log(
|
|
258
|
+
if (generationContext) {
|
|
259
|
+
console.log(formatToolchainReport(generationContext.toolchain));
|
|
269
260
|
}
|
|
270
|
-
console.log(
|
|
261
|
+
console.log(formatProjectionNextSteps(options.dir, projectionPlan));
|
|
271
262
|
}
|
|
272
263
|
function isInteractiveTerminal() {
|
|
273
264
|
return Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
@@ -276,11 +267,12 @@ async function confirmInit(targetDir, blueprint) {
|
|
|
276
267
|
console.log(formatBlueprintSummary(targetDir, blueprint));
|
|
277
268
|
const readline = createInterface({
|
|
278
269
|
input: process.stdin,
|
|
279
|
-
output: process.stdout
|
|
270
|
+
output: process.stdout,
|
|
280
271
|
});
|
|
281
272
|
try {
|
|
282
273
|
const answer = await readline.question("Generate this project? [y/N] ");
|
|
283
|
-
return answer.trim().toLowerCase() === "y" ||
|
|
274
|
+
return (answer.trim().toLowerCase() === "y" ||
|
|
275
|
+
answer.trim().toLowerCase() === "yes");
|
|
284
276
|
}
|
|
285
277
|
finally {
|
|
286
278
|
readline.close();
|
|
@@ -365,23 +357,35 @@ async function main(args) {
|
|
|
365
357
|
const options = parseInitOptions(args);
|
|
366
358
|
const blueprint = blueprintForInit(options);
|
|
367
359
|
if (options.dryRun) {
|
|
368
|
-
const
|
|
369
|
-
|
|
370
|
-
|
|
360
|
+
const generationContext = await generationContextForInit(options, blueprint);
|
|
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({
|
|
368
|
+
targetDir: options.dir,
|
|
369
|
+
plan: projectionPlan,
|
|
371
370
|
});
|
|
372
371
|
if (options.json) {
|
|
373
372
|
printJson({
|
|
374
373
|
command: "init",
|
|
375
374
|
dryRun: true,
|
|
376
|
-
ready: options.ready,
|
|
377
375
|
targetDir: options.dir,
|
|
378
376
|
blueprint,
|
|
379
|
-
|
|
377
|
+
toolchain: generationContext
|
|
378
|
+
? toolchainReport(generationContext.toolchain)
|
|
379
|
+
: undefined,
|
|
380
|
+
nextSteps,
|
|
380
381
|
});
|
|
381
382
|
return;
|
|
382
383
|
}
|
|
383
384
|
console.log(formatBlueprintSummary(options.dir, blueprint));
|
|
384
|
-
|
|
385
|
+
if (generationContext) {
|
|
386
|
+
console.log(formatToolchainReport(generationContext.toolchain));
|
|
387
|
+
}
|
|
388
|
+
console.log(formatProjectionNextSteps(options.dir, projectionPlan));
|
|
385
389
|
return;
|
|
386
390
|
}
|
|
387
391
|
if (!options.yes && (options.json || !isInteractiveTerminal())) {
|
|
@@ -390,24 +394,18 @@ async function main(args) {
|
|
|
390
394
|
if (!options.yes && !(await confirmInit(options.dir, blueprint))) {
|
|
391
395
|
throw new Error("Init cancelled");
|
|
392
396
|
}
|
|
393
|
-
const
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
});
|
|
397
|
-
await generateInitProject(options);
|
|
398
|
-
const executions = options.ready ? await runPostCommands({ plan: postCommandPlan }) : [];
|
|
399
|
-
const failedExecution = failedPostCommand(executions);
|
|
400
|
-
printInitComplete(options, blueprint, postCommandReport(postCommandPlan.commands, executions, options.ready
|
|
401
|
-
? []
|
|
402
|
-
: skippedPostCommands(postCommandPlan.commands, "ready-mode-not-requested")));
|
|
403
|
-
if (failedExecution) {
|
|
404
|
-
throw new Error(failedExecution.error);
|
|
405
|
-
}
|
|
397
|
+
const generationContext = await generationContextForInit(options, blueprint);
|
|
398
|
+
await generateInitProject(options, generationContext);
|
|
399
|
+
printInitComplete(options, blueprint, generationContext);
|
|
406
400
|
return;
|
|
407
401
|
}
|
|
408
402
|
if (command === "add" && args[1] === "package") {
|
|
409
403
|
const options = parseAddPackageOptions(args);
|
|
410
|
-
await addPackage({
|
|
404
|
+
await addPackage({
|
|
405
|
+
cwd: process.cwd(),
|
|
406
|
+
preset: options.preset,
|
|
407
|
+
name: options.name,
|
|
408
|
+
});
|
|
411
409
|
console.log(`Added ${options.preset} package ${options.name}`);
|
|
412
410
|
return;
|
|
413
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:
|
|
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
|
-
|
|
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: [],
|
|
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
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
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
|
+
readonly settings?: Record<string, unknown>;
|
|
17
|
+
}): Record<string, unknown>;
|
|
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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
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
|
+
...(options.settings ? { settings: options.settings } : {}),
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
}
|