@ykdz/template 0.0.1 → 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.
- package/dist/cli.js +66 -89
- package/dist/declarations.js +1 -1
- package/dist/devcontainer.d.ts +17 -0
- package/dist/devcontainer.d.ts.map +1 -0
- package/dist/devcontainer.js +23 -0
- package/dist/generation-context.d.ts +24 -0
- package/dist/generation-context.d.ts.map +1 -0
- package/dist/generation-context.js +12 -0
- package/dist/hono-api.d.ts +1 -0
- package/dist/hono-api.d.ts.map +1 -1
- package/dist/hono-api.js +55 -53
- package/dist/module-graph.d.ts +45 -0
- package/dist/module-graph.d.ts.map +1 -0
- package/dist/module-graph.js +187 -0
- package/dist/next-step-instructions.d.ts +22 -0
- package/dist/next-step-instructions.d.ts.map +1 -0
- package/dist/next-step-instructions.js +99 -0
- package/dist/project-github.d.ts +36 -0
- package/dist/project-github.d.ts.map +1 -0
- package/dist/project-github.js +96 -0
- package/dist/renderer.d.ts.map +1 -1
- package/dist/renderer.js +0 -3
- package/dist/rust-bin.d.ts +7 -1
- package/dist/rust-bin.d.ts.map +1 -1
- package/dist/rust-bin.js +70 -36
- package/dist/toolchain-resolution.d.ts +35 -0
- package/dist/toolchain-resolution.d.ts.map +1 -0
- package/dist/toolchain-resolution.js +192 -0
- package/dist/ts-lib.d.ts +7 -1
- package/dist/ts-lib.d.ts.map +1 -1
- package/dist/ts-lib.js +87 -54
- package/dist/vue-app.d.ts +1 -0
- package/dist/vue-app.d.ts.map +1 -1
- package/dist/vue-app.js +70 -68
- package/dist/vue-hono-app.d.ts +3 -0
- package/dist/vue-hono-app.d.ts.map +1 -1
- package/dist/vue-hono-app.js +111 -107
- package/package.json +2 -1
- package/templates/rust-bin/.github/dependabot.yml +4 -0
- package/templates/rust-bin/.github/workflows/check.yml +6 -1
- 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/rust-bin.js
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { fileURLToPath } from "node:url";
|
|
3
|
+
import { devcontainerNodeFeature } from "./devcontainer.js";
|
|
4
|
+
import { assembleGenerationContext } from "./generation-context.js";
|
|
5
|
+
import { planRustBinChecks, planRustBinFixes, renderFixCommand, renderRootCheckCommand, } from "./module-graph.js";
|
|
6
|
+
import { projectPresetDependabotConfig, projectRustBinGithubCheckWorkflow } from "./project-github.js";
|
|
3
7
|
import { renderNewProject } from "./renderer.js";
|
|
8
|
+
import { resolveToolchainVersions } from "./toolchain-resolution.js";
|
|
4
9
|
const features = [
|
|
5
10
|
"root-check",
|
|
6
11
|
"fix-command",
|
|
@@ -15,6 +20,13 @@ const generatedBy = {
|
|
|
15
20
|
version: "0.0.0",
|
|
16
21
|
command: "template init --preset rust-bin"
|
|
17
22
|
};
|
|
23
|
+
const rustBinBlueprint = {
|
|
24
|
+
schemaVersion: 1,
|
|
25
|
+
preset: "rust-bin",
|
|
26
|
+
packageManager: "pnpm",
|
|
27
|
+
projectKind: "single-package",
|
|
28
|
+
features: [...features],
|
|
29
|
+
};
|
|
18
30
|
function cargoPackageNameFromDir(targetDir) {
|
|
19
31
|
const directoryName = path.basename(path.resolve(targetDir));
|
|
20
32
|
const slug = directoryName
|
|
@@ -68,8 +80,46 @@ function cargoLock(projectName) {
|
|
|
68
80
|
""
|
|
69
81
|
].join("\n");
|
|
70
82
|
}
|
|
71
|
-
function
|
|
83
|
+
export function projectRustBinPackageScripts() {
|
|
84
|
+
return {
|
|
85
|
+
check: renderRootCheckCommand(planRustBinChecks()),
|
|
86
|
+
fix: renderFixCommand(planRustBinFixes()),
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
function packageJson(context, projectName) {
|
|
90
|
+
return {
|
|
91
|
+
name: projectName,
|
|
92
|
+
version: "0.0.0",
|
|
93
|
+
private: true,
|
|
94
|
+
scripts: projectRustBinPackageScripts(),
|
|
95
|
+
engines: {
|
|
96
|
+
node: context.toolchain.nodeLtsMajor.value,
|
|
97
|
+
},
|
|
98
|
+
packageManager: context.toolchain.packageManagerPin.value,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
function generationRecord(context) {
|
|
102
|
+
return {
|
|
103
|
+
...generatedBy,
|
|
104
|
+
toolchain: {
|
|
105
|
+
nodeLtsMajor: context.toolchain.nodeLtsMajor.value,
|
|
106
|
+
packageManagerPin: context.toolchain.packageManagerPin.value,
|
|
107
|
+
source: context.toolchain.source,
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
function operationsForRustBin(context, projectName) {
|
|
72
112
|
return [
|
|
113
|
+
{
|
|
114
|
+
kind: "writeJson",
|
|
115
|
+
to: "package.json",
|
|
116
|
+
value: packageJson(context, projectName),
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
kind: "writeText",
|
|
120
|
+
to: "pnpm-workspace.yaml",
|
|
121
|
+
text: ["packages:", " - .", ""].join("\n"),
|
|
122
|
+
},
|
|
73
123
|
{
|
|
74
124
|
kind: "writeText",
|
|
75
125
|
to: "Cargo.toml",
|
|
@@ -95,41 +145,15 @@ function operationsForRustBin(projectName) {
|
|
|
95
145
|
from: "src/main.rs",
|
|
96
146
|
to: "src/main.rs"
|
|
97
147
|
},
|
|
98
|
-
{
|
|
99
|
-
kind: "writeText",
|
|
100
|
-
to: "scripts/check",
|
|
101
|
-
text: [
|
|
102
|
-
"#!/usr/bin/env sh",
|
|
103
|
-
"set -eu",
|
|
104
|
-
"",
|
|
105
|
-
"echo cargo fmt --all -- --check",
|
|
106
|
-
"cargo fmt --all -- --check",
|
|
107
|
-
"echo cargo clippy --workspace --all-targets -- -D warnings",
|
|
108
|
-
"cargo clippy --workspace --all-targets -- -D warnings",
|
|
109
|
-
"echo cargo test --workspace",
|
|
110
|
-
"cargo test --workspace",
|
|
111
|
-
""
|
|
112
|
-
].join("\n")
|
|
113
|
-
},
|
|
114
|
-
{
|
|
115
|
-
kind: "setExecutable",
|
|
116
|
-
path: "scripts/check",
|
|
117
|
-
executable: true
|
|
118
|
-
},
|
|
119
148
|
{
|
|
120
149
|
kind: "writeJson",
|
|
121
150
|
to: ".project-kit/blueprint.json",
|
|
122
|
-
value:
|
|
123
|
-
schemaVersion: 1,
|
|
124
|
-
preset: "rust-bin",
|
|
125
|
-
projectKind: "single-package",
|
|
126
|
-
features
|
|
127
|
-
}
|
|
151
|
+
value: rustBinBlueprint
|
|
128
152
|
},
|
|
129
153
|
{
|
|
130
154
|
kind: "writeJson",
|
|
131
155
|
to: ".project-kit/generated-by.json",
|
|
132
|
-
value:
|
|
156
|
+
value: generationRecord(context)
|
|
133
157
|
},
|
|
134
158
|
{
|
|
135
159
|
kind: "writeJson",
|
|
@@ -137,12 +161,15 @@ function operationsForRustBin(projectName) {
|
|
|
137
161
|
value: {
|
|
138
162
|
name: `${projectName} Rust development`,
|
|
139
163
|
image: "mcr.microsoft.com/devcontainers/rust:1",
|
|
164
|
+
features: devcontainerNodeFeature({
|
|
165
|
+
nodeVersion: context.toolchain.nodeLtsMajor.value,
|
|
166
|
+
packageManagerPin: context.toolchain.packageManagerPin.value,
|
|
167
|
+
}),
|
|
140
168
|
mounts: [
|
|
141
169
|
"source=${localWorkspaceFolderBasename}-cargo-registry,target=/usr/local/cargo/registry,type=volume",
|
|
142
170
|
"source=${localWorkspaceFolderBasename}-cargo-git,target=/usr/local/cargo/git,type=volume",
|
|
143
171
|
"source=${localWorkspaceFolderBasename}-target,target=${containerWorkspaceFolder}/target,type=volume"
|
|
144
172
|
],
|
|
145
|
-
postCreateCommand: "rustup component add rustfmt clippy && cargo fetch",
|
|
146
173
|
customizations: {
|
|
147
174
|
vscode: {
|
|
148
175
|
extensions: ["rust-lang.rust-analyzer", "tamasfe.even-better-toml"]
|
|
@@ -151,24 +178,31 @@ function operationsForRustBin(projectName) {
|
|
|
151
178
|
}
|
|
152
179
|
},
|
|
153
180
|
{
|
|
154
|
-
kind: "
|
|
155
|
-
from: ".github/workflows/check.yml",
|
|
181
|
+
kind: "writeText",
|
|
156
182
|
to: ".github/workflows/check.yml",
|
|
183
|
+
text: projectRustBinGithubCheckWorkflow(),
|
|
157
184
|
},
|
|
158
185
|
{
|
|
159
|
-
kind: "
|
|
160
|
-
from: ".github/dependabot.yml",
|
|
186
|
+
kind: "writeText",
|
|
161
187
|
to: ".github/dependabot.yml",
|
|
188
|
+
text: projectPresetDependabotConfig("rust-bin"),
|
|
162
189
|
}
|
|
163
190
|
];
|
|
164
191
|
}
|
|
165
192
|
function templateSourceRoot() {
|
|
166
193
|
return path.join(path.dirname(fileURLToPath(import.meta.url)), "..", "templates", "rust-bin");
|
|
167
194
|
}
|
|
168
|
-
export async function initRustBinProject(targetDir) {
|
|
195
|
+
export async function initRustBinProject(targetDir, options) {
|
|
196
|
+
const generationContext = options?.generationContext ??
|
|
197
|
+
assembleGenerationContext({
|
|
198
|
+
targetDir,
|
|
199
|
+
blueprint: rustBinBlueprint,
|
|
200
|
+
toolchain: await resolveToolchainVersions(),
|
|
201
|
+
});
|
|
202
|
+
const projectName = cargoPackageNameFromDir(targetDir);
|
|
169
203
|
await renderNewProject({
|
|
170
204
|
sourceRoot: templateSourceRoot(),
|
|
171
205
|
targetRoot: targetDir,
|
|
172
|
-
operations: operationsForRustBin(
|
|
206
|
+
operations: operationsForRustBin(generationContext, projectName)
|
|
173
207
|
});
|
|
174
208
|
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export type ToolchainResolutionSource = "online" | "bundled-fallback";
|
|
2
|
+
export type NodeLtsMajor = {
|
|
3
|
+
readonly kind: "NodeLtsMajor";
|
|
4
|
+
readonly value: string;
|
|
5
|
+
};
|
|
6
|
+
export type PackageManagerPin = {
|
|
7
|
+
readonly kind: "PackageManagerPin";
|
|
8
|
+
readonly value: `pnpm@${string}`;
|
|
9
|
+
};
|
|
10
|
+
export type ResolvedToolchainVersions = {
|
|
11
|
+
readonly nodeLtsMajor: NodeLtsMajor;
|
|
12
|
+
readonly packageManagerPin: PackageManagerPin;
|
|
13
|
+
readonly source: ToolchainResolutionSource;
|
|
14
|
+
readonly diagnostics: string[];
|
|
15
|
+
};
|
|
16
|
+
export type ResolveToolchainVersionsOptions = {
|
|
17
|
+
readonly source?: ToolchainResolutionSource | "auto";
|
|
18
|
+
readonly fetchJson?: (url: string) => Promise<unknown>;
|
|
19
|
+
readonly nodeReleaseIndexUrl?: string;
|
|
20
|
+
readonly pnpmRegistryUrl?: string;
|
|
21
|
+
};
|
|
22
|
+
export declare const nodeReleaseIndexUrl = "https://nodejs.org/dist/index.json";
|
|
23
|
+
export declare const pnpmRegistryUrl = "https://registry.npmjs.org/pnpm";
|
|
24
|
+
type OnlineToolchainResolutionContractOptions = {
|
|
25
|
+
readonly fetchJson?: (url: string) => Promise<unknown>;
|
|
26
|
+
};
|
|
27
|
+
export type OnlineToolchainResolutionContractResult = {
|
|
28
|
+
readonly nodeLtsMajor: NodeLtsMajor;
|
|
29
|
+
readonly packageManagerPin: PackageManagerPin;
|
|
30
|
+
readonly diagnostics: string[];
|
|
31
|
+
};
|
|
32
|
+
export declare function resolveToolchainVersions(options?: ResolveToolchainVersionsOptions): Promise<ResolvedToolchainVersions>;
|
|
33
|
+
export declare function checkOnlineToolchainResolutionContract(options?: OnlineToolchainResolutionContractOptions): Promise<OnlineToolchainResolutionContractResult>;
|
|
34
|
+
export {};
|
|
35
|
+
//# sourceMappingURL=toolchain-resolution.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toolchain-resolution.d.ts","sourceRoot":"","sources":["../src/toolchain-resolution.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,yBAAyB,GAAG,QAAQ,GAAG,kBAAkB,CAAC;AAEtE,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC;IACnC,QAAQ,CAAC,KAAK,EAAE,QAAQ,MAAM,EAAE,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACtC,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC;IACpC,QAAQ,CAAC,iBAAiB,EAAE,iBAAiB,CAAC;IAC9C,QAAQ,CAAC,MAAM,EAAE,yBAAyB,CAAC;IAC3C,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,+BAA+B,GAAG;IAC5C,QAAQ,CAAC,MAAM,CAAC,EAAE,yBAAyB,GAAG,MAAM,CAAC;IACrD,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACvD,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IACtC,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;CACnC,CAAC;AAEF,eAAO,MAAM,mBAAmB,uCAAuC,CAAC;AACxE,eAAO,MAAM,eAAe,oCAAoC,CAAC;AAEjE,KAAK,wCAAwC,GAAG;IAC9C,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CACxD,CAAC;AAEF,MAAM,MAAM,uCAAuC,GAAG;IACpD,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC;IACpC,QAAQ,CAAC,iBAAiB,EAAE,iBAAiB,CAAC;IAC9C,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,CAAC;CAChC,CAAC;AAmBF,wBAAsB,wBAAwB,CAC5C,OAAO,GAAE,+BAAoC,GAC5C,OAAO,CAAC,yBAAyB,CAAC,CAiCpC;AAED,wBAAsB,sCAAsC,CAC1D,OAAO,GAAE,wCAA6C,GACrD,OAAO,CAAC,uCAAuC,CAAC,CAwBlD"}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
export const nodeReleaseIndexUrl = "https://nodejs.org/dist/index.json";
|
|
2
|
+
export const pnpmRegistryUrl = "https://registry.npmjs.org/pnpm";
|
|
3
|
+
const bundledFallbackToolchain = {
|
|
4
|
+
nodeLtsMajor: nodeLtsMajor("22"),
|
|
5
|
+
packageManagerPin: packageManagerPin("10.0.0"),
|
|
6
|
+
};
|
|
7
|
+
export async function resolveToolchainVersions(options = {}) {
|
|
8
|
+
const source = options.source ?? "online";
|
|
9
|
+
if (source === "bundled-fallback") {
|
|
10
|
+
return fallbackResult([]);
|
|
11
|
+
}
|
|
12
|
+
try {
|
|
13
|
+
const fetchJson = options.fetchJson ?? fetchOfficialJson;
|
|
14
|
+
const nodeReleases = parseNodeReleaseIndex(await fetchJson(options.nodeReleaseIndexUrl ?? nodeReleaseIndexUrl));
|
|
15
|
+
const nodeMajor = latestLtsMajor(nodeReleases);
|
|
16
|
+
const pnpmMetadata = parsePnpmRegistryMetadata(await fetchJson(options.pnpmRegistryUrl ?? pnpmRegistryUrl));
|
|
17
|
+
const pnpmVersion = latestCompatiblePnpmVersion(pnpmMetadata, Number(nodeMajor.value));
|
|
18
|
+
return {
|
|
19
|
+
nodeLtsMajor: nodeMajor,
|
|
20
|
+
packageManagerPin: packageManagerPin(pnpmVersion),
|
|
21
|
+
source: "online",
|
|
22
|
+
diagnostics: [],
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
27
|
+
return fallbackResult([
|
|
28
|
+
`Using bundled fallback toolchain metadata because online resolution failed: ${message}`,
|
|
29
|
+
]);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export async function checkOnlineToolchainResolutionContract(options = {}) {
|
|
33
|
+
const fetchJson = options.fetchJson ?? fetchOfficialJson;
|
|
34
|
+
const nodeMajor = await contractPhase("Node source parsing", async () => {
|
|
35
|
+
const nodeReleases = parseNodeReleaseIndex(await fetchJson(nodeReleaseIndexUrl));
|
|
36
|
+
return latestLtsMajor(nodeReleases);
|
|
37
|
+
});
|
|
38
|
+
const pnpmMetadata = await contractPhase("pnpm source parsing", async () => parsePnpmRegistryMetadata(await fetchJson(pnpmRegistryUrl)));
|
|
39
|
+
const pnpmVersion = await contractPhase("compatibility selection", async () => latestCompatiblePnpmVersion(pnpmMetadata, Number(nodeMajor.value)));
|
|
40
|
+
return {
|
|
41
|
+
nodeLtsMajor: nodeMajor,
|
|
42
|
+
packageManagerPin: packageManagerPin(pnpmVersion),
|
|
43
|
+
diagnostics: [
|
|
44
|
+
`Node source parsing succeeded; latest LTS major is ${nodeMajor.value}.`,
|
|
45
|
+
`pnpm source parsing succeeded; latest compatible pnpm release is ${pnpmVersion}.`,
|
|
46
|
+
`Compatibility selection succeeded for pnpm@${pnpmVersion} on Node ${nodeMajor.value}.`,
|
|
47
|
+
],
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
async function contractPhase(phase, operation) {
|
|
51
|
+
try {
|
|
52
|
+
return await operation();
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
56
|
+
throw new Error(`Online toolchain resolution contract failed during ${phase}: ${message}`, error instanceof Error ? { cause: error } : undefined);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function fallbackResult(diagnostics) {
|
|
60
|
+
return {
|
|
61
|
+
nodeLtsMajor: bundledFallbackToolchain.nodeLtsMajor,
|
|
62
|
+
packageManagerPin: bundledFallbackToolchain.packageManagerPin,
|
|
63
|
+
source: "bundled-fallback",
|
|
64
|
+
diagnostics,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function nodeLtsMajor(value) {
|
|
68
|
+
if (!/^\d+$/.test(value)) {
|
|
69
|
+
throw new Error(`Invalid Node LTS major: ${value}`);
|
|
70
|
+
}
|
|
71
|
+
return { kind: "NodeLtsMajor", value };
|
|
72
|
+
}
|
|
73
|
+
function packageManagerPin(version) {
|
|
74
|
+
if (!/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$/.test(version)) {
|
|
75
|
+
throw new Error(`Invalid pnpm version: ${version}`);
|
|
76
|
+
}
|
|
77
|
+
return { kind: "PackageManagerPin", value: `pnpm@${version}` };
|
|
78
|
+
}
|
|
79
|
+
async function fetchOfficialJson(url) {
|
|
80
|
+
const response = await fetch(url, {
|
|
81
|
+
headers: { accept: "application/json" },
|
|
82
|
+
});
|
|
83
|
+
if (!response.ok) {
|
|
84
|
+
throw new Error(`GET ${url} failed with HTTP ${response.status}`);
|
|
85
|
+
}
|
|
86
|
+
return response.json();
|
|
87
|
+
}
|
|
88
|
+
function parseNodeReleaseIndex(value) {
|
|
89
|
+
if (!Array.isArray(value)) {
|
|
90
|
+
throw new Error("Node release index was not an array");
|
|
91
|
+
}
|
|
92
|
+
return value.map((entry) => {
|
|
93
|
+
if (!isRecord(entry)) {
|
|
94
|
+
throw new Error("Node release entry was not an object");
|
|
95
|
+
}
|
|
96
|
+
const version = entry.version;
|
|
97
|
+
const lts = entry.lts;
|
|
98
|
+
if (typeof version !== "string" ||
|
|
99
|
+
(typeof lts !== "string" && typeof lts !== "boolean")) {
|
|
100
|
+
throw new Error("Node release entry is missing version or lts");
|
|
101
|
+
}
|
|
102
|
+
return { version, lts };
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
function latestLtsMajor(releases) {
|
|
106
|
+
const majors = releases
|
|
107
|
+
.filter((release) => release.lts !== false)
|
|
108
|
+
.map((release) => release.version.match(/^v(\d+)\./)?.[1])
|
|
109
|
+
.filter((major) => major !== undefined)
|
|
110
|
+
.map(Number);
|
|
111
|
+
if (majors.length === 0) {
|
|
112
|
+
throw new Error("Node release index did not contain any LTS releases");
|
|
113
|
+
}
|
|
114
|
+
return nodeLtsMajor(String(Math.max(...majors)));
|
|
115
|
+
}
|
|
116
|
+
function parsePnpmRegistryMetadata(value) {
|
|
117
|
+
if (!isRecord(value) || !isRecord(value.versions)) {
|
|
118
|
+
throw new Error("pnpm registry metadata is missing versions");
|
|
119
|
+
}
|
|
120
|
+
const versions = {};
|
|
121
|
+
for (const [version, metadata] of Object.entries(value.versions)) {
|
|
122
|
+
if (!isRecord(metadata)) {
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
versions[version] = {
|
|
126
|
+
engines: isRecord(metadata.engines)
|
|
127
|
+
? {
|
|
128
|
+
node: typeof metadata.engines.node === "string"
|
|
129
|
+
? metadata.engines.node
|
|
130
|
+
: undefined,
|
|
131
|
+
}
|
|
132
|
+
: undefined,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
return { versions };
|
|
136
|
+
}
|
|
137
|
+
function latestCompatiblePnpmVersion(metadata, nodeMajor) {
|
|
138
|
+
const candidates = Object.entries(metadata.versions)
|
|
139
|
+
.filter(([version]) => /^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$/.test(version))
|
|
140
|
+
.filter(([, packageMetadata]) => nodeSatisfiesRange(nodeMajor, packageMetadata.engines?.node))
|
|
141
|
+
.map(([version]) => version)
|
|
142
|
+
.sort(compareSemver);
|
|
143
|
+
const latest = candidates.at(-1);
|
|
144
|
+
if (!latest) {
|
|
145
|
+
throw new Error(`pnpm registry metadata did not contain a release compatible with Node ${nodeMajor}`);
|
|
146
|
+
}
|
|
147
|
+
return latest;
|
|
148
|
+
}
|
|
149
|
+
function nodeSatisfiesRange(nodeMajor, range) {
|
|
150
|
+
if (!range) {
|
|
151
|
+
return true;
|
|
152
|
+
}
|
|
153
|
+
return range
|
|
154
|
+
.split(/\s+/)
|
|
155
|
+
.filter(Boolean)
|
|
156
|
+
.every((comparator) => nodeSatisfiesComparator(nodeMajor, comparator));
|
|
157
|
+
}
|
|
158
|
+
function nodeSatisfiesComparator(nodeMajor, comparator) {
|
|
159
|
+
const match = comparator.match(/^(>=|>|<=|<|=)?(\d+)(?:\.\d+){0,2}$/);
|
|
160
|
+
if (!match) {
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
const operator = match[1] ?? "=";
|
|
164
|
+
const major = Number(match[2]);
|
|
165
|
+
if (operator === ">=") {
|
|
166
|
+
return nodeMajor >= major;
|
|
167
|
+
}
|
|
168
|
+
if (operator === ">") {
|
|
169
|
+
return nodeMajor > major;
|
|
170
|
+
}
|
|
171
|
+
if (operator === "<=") {
|
|
172
|
+
return nodeMajor <= major;
|
|
173
|
+
}
|
|
174
|
+
if (operator === "<") {
|
|
175
|
+
return nodeMajor < major;
|
|
176
|
+
}
|
|
177
|
+
return nodeMajor === major;
|
|
178
|
+
}
|
|
179
|
+
function compareSemver(left, right) {
|
|
180
|
+
const leftParts = left.split(/[.-]/).slice(0, 3).map(Number);
|
|
181
|
+
const rightParts = right.split(/[.-]/).slice(0, 3).map(Number);
|
|
182
|
+
for (let index = 0; index < 3; index += 1) {
|
|
183
|
+
const difference = (leftParts[index] ?? 0) - (rightParts[index] ?? 0);
|
|
184
|
+
if (difference !== 0) {
|
|
185
|
+
return difference;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return left.localeCompare(right);
|
|
189
|
+
}
|
|
190
|
+
function isRecord(value) {
|
|
191
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
192
|
+
}
|
package/dist/ts-lib.d.ts
CHANGED
|
@@ -1,2 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
import { type GenerationContext } from "./generation-context.js";
|
|
2
|
+
type InitTsLibProjectOptions = {
|
|
3
|
+
readonly generationContext?: GenerationContext;
|
|
4
|
+
};
|
|
5
|
+
export declare function projectTsLibPackageScripts(): Record<string, string>;
|
|
6
|
+
export declare function initTsLibProject(targetDir: string, options?: InitTsLibProjectOptions): Promise<void>;
|
|
7
|
+
export {};
|
|
2
8
|
//# sourceMappingURL=ts-lib.d.ts.map
|
package/dist/ts-lib.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ts-lib.d.ts","sourceRoot":"","sources":["../src/ts-lib.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ts-lib.d.ts","sourceRoot":"","sources":["../src/ts-lib.ts"],"names":[],"mappings":"AAIA,OAAO,EAA6B,KAAK,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAiB5F,KAAK,uBAAuB,GAAG;IAC7B,QAAQ,CAAC,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;CAChD,CAAC;AAmBF,wBAAgB,0BAA0B,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAWnE;AA4KD,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,uBAAuB,GAChC,OAAO,CAAC,IAAI,CAAC,CAef"}
|
package/dist/ts-lib.js
CHANGED
|
@@ -1,17 +1,47 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { fileURLToPath } from "node:url";
|
|
3
|
+
import { nodePnpmDevcontainer } from "./devcontainer.js";
|
|
4
|
+
import { assembleGenerationContext } from "./generation-context.js";
|
|
5
|
+
import { planTsLibChecks, planTsLibFixes, renderFixCommand, renderRootCheckCommand, } from "./module-graph.js";
|
|
6
|
+
import { projectPresetDependabotConfig, projectTsLibGithubCheckWorkflow } from "./project-github.js";
|
|
3
7
|
import { renderNewProject } from "./renderer.js";
|
|
8
|
+
import { resolveToolchainVersions } from "./toolchain-resolution.js";
|
|
4
9
|
const generatedBy = {
|
|
5
10
|
packageName: "@ykdz/template",
|
|
6
11
|
version: "0.0.0",
|
|
7
|
-
command: "template init --preset ts-lib"
|
|
12
|
+
command: "template init --preset ts-lib",
|
|
8
13
|
};
|
|
9
|
-
|
|
10
|
-
|
|
14
|
+
const tsLibBlueprint = {
|
|
15
|
+
schemaVersion: 1,
|
|
16
|
+
preset: "ts-lib",
|
|
17
|
+
packageManager: "pnpm",
|
|
18
|
+
projectKind: "single-package",
|
|
19
|
+
features: [
|
|
20
|
+
"pnpm-catalog",
|
|
21
|
+
"oxc-format-lint",
|
|
22
|
+
"strict-typescript",
|
|
23
|
+
"root-check",
|
|
24
|
+
"fix-command",
|
|
25
|
+
"devcontainer",
|
|
26
|
+
"github-actions",
|
|
27
|
+
"dependabot",
|
|
28
|
+
],
|
|
29
|
+
};
|
|
30
|
+
export function projectTsLibPackageScripts() {
|
|
31
|
+
return {
|
|
32
|
+
build: "tsc -p tsconfig.json && tsc-alias -p tsconfig.json",
|
|
33
|
+
check: renderRootCheckCommand(planTsLibChecks()),
|
|
34
|
+
fix: renderFixCommand(planTsLibFixes()),
|
|
35
|
+
"format:check": "oxfmt --check .",
|
|
36
|
+
"format:write": "oxfmt --write .",
|
|
37
|
+
lint: "oxlint . --deny-warnings",
|
|
38
|
+
"lint:fix": "oxlint . --fix --deny-warnings",
|
|
39
|
+
typecheck: "tsc -p tsconfig.json --noEmit",
|
|
40
|
+
};
|
|
11
41
|
}
|
|
12
|
-
function packageJson(
|
|
42
|
+
function packageJson(context) {
|
|
13
43
|
return {
|
|
14
|
-
name: projectName,
|
|
44
|
+
name: context.projectName.value,
|
|
15
45
|
version: "0.0.0",
|
|
16
46
|
private: true,
|
|
17
47
|
files: ["dist"],
|
|
@@ -19,39 +49,40 @@ function packageJson(projectName) {
|
|
|
19
49
|
exports: {
|
|
20
50
|
".": {
|
|
21
51
|
default: "./dist/index.js",
|
|
22
|
-
types: "./dist/index.d.ts"
|
|
23
|
-
}
|
|
24
|
-
},
|
|
25
|
-
scripts: {
|
|
26
|
-
build: "tsc -p tsconfig.json && tsc-alias -p tsconfig.json",
|
|
27
|
-
check: "pnpm run typecheck && pnpm run lint && pnpm run format:check",
|
|
28
|
-
fix: "pnpm run format:write && pnpm run lint:fix",
|
|
29
|
-
"format:check": "oxfmt --check .",
|
|
30
|
-
"format:write": "oxfmt --write .",
|
|
31
|
-
lint: "oxlint . --deny-warnings",
|
|
32
|
-
"lint:fix": "oxlint . --fix --deny-warnings",
|
|
33
|
-
typecheck: "tsc -p tsconfig.json --noEmit"
|
|
52
|
+
types: "./dist/index.d.ts",
|
|
53
|
+
},
|
|
34
54
|
},
|
|
55
|
+
scripts: projectTsLibPackageScripts(),
|
|
35
56
|
devDependencies: {
|
|
36
57
|
"@types/node": "catalog:",
|
|
37
58
|
oxfmt: "catalog:",
|
|
38
59
|
oxlint: "catalog:",
|
|
39
60
|
"tsc-alias": "catalog:",
|
|
40
|
-
typescript: "catalog:"
|
|
61
|
+
typescript: "catalog:",
|
|
41
62
|
},
|
|
42
63
|
engines: {
|
|
43
|
-
node:
|
|
64
|
+
node: context.toolchain.nodeLtsMajor.value,
|
|
65
|
+
},
|
|
66
|
+
packageManager: context.toolchain.packageManagerPin.value,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
function generationRecord(context) {
|
|
70
|
+
return {
|
|
71
|
+
...generatedBy,
|
|
72
|
+
toolchain: {
|
|
73
|
+
nodeLtsMajor: context.toolchain.nodeLtsMajor.value,
|
|
74
|
+
packageManagerPin: context.toolchain.packageManagerPin.value,
|
|
75
|
+
source: context.toolchain.source,
|
|
44
76
|
},
|
|
45
|
-
packageManager: "pnpm@10.0.0"
|
|
46
77
|
};
|
|
47
78
|
}
|
|
48
|
-
function operationsForTsLib(
|
|
79
|
+
function operationsForTsLib(context) {
|
|
49
80
|
return [
|
|
50
81
|
{
|
|
51
82
|
kind: "writeJson",
|
|
52
83
|
to: "package.json",
|
|
53
|
-
value: packageJson(
|
|
54
|
-
multilineArrays: ["files"]
|
|
84
|
+
value: packageJson(context),
|
|
85
|
+
multilineArrays: ["files"],
|
|
55
86
|
},
|
|
56
87
|
{
|
|
57
88
|
kind: "writeText",
|
|
@@ -66,8 +97,8 @@ function operationsForTsLib(projectName) {
|
|
|
66
97
|
" oxlint: ^1.71.0",
|
|
67
98
|
" tsc-alias: ^1.8.17",
|
|
68
99
|
" typescript: ^5.8.0",
|
|
69
|
-
""
|
|
70
|
-
].join("\n")
|
|
100
|
+
"",
|
|
101
|
+
].join("\n"),
|
|
71
102
|
},
|
|
72
103
|
{
|
|
73
104
|
kind: "writeJson",
|
|
@@ -81,38 +112,38 @@ function operationsForTsLib(projectName) {
|
|
|
81
112
|
noEmitOnError: true,
|
|
82
113
|
outDir: "dist",
|
|
83
114
|
paths: {
|
|
84
|
-
"@/*": ["./src/*"]
|
|
115
|
+
"@/*": ["./src/*"],
|
|
85
116
|
},
|
|
86
117
|
rootDir: "src",
|
|
87
118
|
skipLibCheck: false,
|
|
88
119
|
strict: true,
|
|
89
120
|
target: "ES2022",
|
|
90
|
-
types: ["node"]
|
|
121
|
+
types: ["node"],
|
|
91
122
|
},
|
|
92
|
-
include: ["src/**/*.ts"]
|
|
93
|
-
}
|
|
123
|
+
include: ["src/**/*.ts"],
|
|
124
|
+
},
|
|
94
125
|
},
|
|
95
126
|
{
|
|
96
127
|
kind: "copyFile",
|
|
97
128
|
sourceRoot: "sharedOxc",
|
|
98
129
|
from: "node/oxlint.config.ts",
|
|
99
|
-
to: "oxlint.config.ts"
|
|
130
|
+
to: "oxlint.config.ts",
|
|
100
131
|
},
|
|
101
132
|
{
|
|
102
133
|
kind: "copyFile",
|
|
103
134
|
sourceRoot: "sharedOxc",
|
|
104
135
|
from: "oxfmt.config.ts",
|
|
105
|
-
to: "oxfmt.config.ts"
|
|
136
|
+
to: "oxfmt.config.ts",
|
|
106
137
|
},
|
|
107
138
|
{
|
|
108
139
|
kind: "writeText",
|
|
109
140
|
to: ".gitignore",
|
|
110
|
-
text: ["node_modules", "dist", ".env", ""].join("\n")
|
|
141
|
+
text: ["node_modules", "dist", ".env", ""].join("\n"),
|
|
111
142
|
},
|
|
112
143
|
{
|
|
113
144
|
kind: "copyFile",
|
|
114
145
|
from: "src/index.ts",
|
|
115
|
-
to: "src/index.ts"
|
|
146
|
+
to: "src/index.ts",
|
|
116
147
|
},
|
|
117
148
|
{
|
|
118
149
|
kind: "writeJson",
|
|
@@ -130,39 +161,35 @@ function operationsForTsLib(projectName) {
|
|
|
130
161
|
"fix-command",
|
|
131
162
|
"devcontainer",
|
|
132
163
|
"github-actions",
|
|
133
|
-
"dependabot"
|
|
134
|
-
]
|
|
135
|
-
}
|
|
164
|
+
"dependabot",
|
|
165
|
+
],
|
|
166
|
+
},
|
|
136
167
|
},
|
|
137
168
|
{
|
|
138
169
|
kind: "writeJson",
|
|
139
170
|
to: ".project-kit/generated-by.json",
|
|
140
|
-
value:
|
|
171
|
+
value: generationRecord(context),
|
|
141
172
|
},
|
|
142
173
|
{
|
|
143
174
|
kind: "writeJson",
|
|
144
175
|
to: ".devcontainer/devcontainer.json",
|
|
145
|
-
value: {
|
|
146
|
-
name: `${projectName} development`,
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
extensions: ["oxc.oxc-vscode"]
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
}
|
|
176
|
+
value: nodePnpmDevcontainer({
|
|
177
|
+
name: `${context.projectName.value} development`,
|
|
178
|
+
nodeVersion: context.toolchain.nodeLtsMajor.value,
|
|
179
|
+
packageManagerPin: context.toolchain.packageManagerPin.value,
|
|
180
|
+
extensions: ["oxc.oxc-vscode"],
|
|
181
|
+
}),
|
|
155
182
|
},
|
|
156
183
|
{
|
|
157
|
-
kind: "
|
|
158
|
-
from: ".github/workflows/check.yml",
|
|
184
|
+
kind: "writeText",
|
|
159
185
|
to: ".github/workflows/check.yml",
|
|
186
|
+
text: projectTsLibGithubCheckWorkflow(),
|
|
160
187
|
},
|
|
161
188
|
{
|
|
162
|
-
kind: "
|
|
163
|
-
from: ".github/dependabot.yml",
|
|
189
|
+
kind: "writeText",
|
|
164
190
|
to: ".github/dependabot.yml",
|
|
165
|
-
|
|
191
|
+
text: projectPresetDependabotConfig("ts-lib"),
|
|
192
|
+
},
|
|
166
193
|
];
|
|
167
194
|
}
|
|
168
195
|
function templateSourceRoot() {
|
|
@@ -171,11 +198,17 @@ function templateSourceRoot() {
|
|
|
171
198
|
function sharedOxcSourceRoot() {
|
|
172
199
|
return path.join(path.dirname(fileURLToPath(import.meta.url)), "..", "templates", "shared", "oxc");
|
|
173
200
|
}
|
|
174
|
-
export async function initTsLibProject(targetDir) {
|
|
201
|
+
export async function initTsLibProject(targetDir, options) {
|
|
202
|
+
const generationContext = options?.generationContext ??
|
|
203
|
+
assembleGenerationContext({
|
|
204
|
+
targetDir,
|
|
205
|
+
blueprint: tsLibBlueprint,
|
|
206
|
+
toolchain: await resolveToolchainVersions(),
|
|
207
|
+
});
|
|
175
208
|
await renderNewProject({
|
|
176
209
|
sourceRoot: templateSourceRoot(),
|
|
177
210
|
sourceRoots: { sharedOxc: sharedOxcSourceRoot() },
|
|
178
211
|
targetRoot: targetDir,
|
|
179
|
-
operations: operationsForTsLib(
|
|
212
|
+
operations: operationsForTsLib(generationContext),
|
|
180
213
|
});
|
|
181
214
|
}
|
package/dist/vue-app.d.ts
CHANGED
package/dist/vue-app.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vue-app.d.ts","sourceRoot":"","sources":["../src/vue-app.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"vue-app.d.ts","sourceRoot":"","sources":["../src/vue-app.ts"],"names":[],"mappings":"AAiCA,wBAAgB,2BAA2B,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAepE;AAyQD,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAOxE"}
|