@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.
- package/dist/cli.js +94 -44
- 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 +63 -100
- 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/package-addition.d.ts.map +1 -1
- package/dist/package-addition.js +31 -51
- 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 +2 -0
- package/dist/renderer.d.ts.map +1 -1
- package/dist/renderer.js +7 -4
- package/dist/rust-bin.d.ts +7 -1
- package/dist/rust-bin.d.ts.map +1 -1
- package/dist/rust-bin.js +68 -66
- 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 +95 -101
- package/dist/vue-app.d.ts +1 -0
- package/dist/vue-app.d.ts.map +1 -1
- package/dist/vue-app.js +78 -116
- 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 +126 -170
- package/package.json +24 -16
- package/templates/hono-api/.github/dependabot.yml +10 -0
- package/templates/hono-api/.github/workflows/check.yml +19 -0
- package/templates/hono-api/src/server.ts +3 -2
- package/templates/hono-api/vitest.config.ts +5 -4
- package/templates/rust-bin/.github/dependabot.yml +14 -0
- package/templates/rust-bin/.github/workflows/check.yml +23 -0
- package/templates/shared/oxc/node/oxlint.config.ts +9 -0
- package/templates/shared/oxc/oxfmt.config.ts +8 -0
- package/templates/shared/oxc/package.json +18 -0
- package/templates/shared/oxc/tsconfig.json +11 -0
- package/templates/shared/oxc/vue/oxlint.config.ts +9 -0
- package/templates/ts-lib/.github/dependabot.yml +10 -0
- package/templates/ts-lib/.github/workflows/check.yml +19 -0
- package/templates/vue-app/.github/dependabot.yml +10 -0
- package/templates/vue-app/.github/workflows/check.yml +20 -0
- package/templates/vue-app/playwright.config.ts +5 -5
- package/templates/vue-app/src/App.vue +15 -5
- package/templates/vue-app/src/main.ts +2 -0
- package/templates/vue-app/test/app.test.ts +1 -0
- package/templates/vue-app/test/e2e/app.spec.ts +3 -1
- package/templates/vue-app/vite.config.ts +6 -5
- package/templates/vue-app/vitest.config.ts +5 -4
- package/templates/vue-hono-app/.github/dependabot.yml +10 -0
- package/templates/vue-hono-app/.github/workflows/check.yml +20 -0
- package/templates/vue-hono-app/api/src/server.ts +3 -2
- package/templates/vue-hono-app/api/vitest.config.ts +2 -2
- package/templates/vue-hono-app/web/playwright.config.ts +9 -7
- package/templates/vue-hono-app/web/src/App.vue +12 -4
- package/templates/vue-hono-app/web/src/api.ts +1 -1
- package/templates/vue-hono-app/web/src/main.ts +2 -0
- package/templates/vue-hono-app/web/test/app.test.ts +1 -0
- package/templates/vue-hono-app/web/test/e2e/app.spec.ts +3 -1
- package/templates/vue-hono-app/web/vite.config.ts +13 -10
- package/templates/vue-hono-app/web/vitest.config.ts +6 -5
package/dist/renderer.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"AAgBA,KAAK,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE9C,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,UAAU,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"AAgBA,KAAK,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE9C,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,UAAU,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,WAAW,CAAC;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,OAAO,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,WAAW,CAAC;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,WAAW,CAAC;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,IAAI,EAAE,eAAe,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACpC,IAAI,EAAE,gBAAgB,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,YAAY,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACtC,CAAC;AAEF,MAAM,MAAM,eAAe,GACvB,iBAAiB,GACjB,kBAAkB,GAClB,kBAAkB,GAClB,kBAAkB,GAClB,sBAAsB,GACtB,uBAAuB,CAAC;AAE5B,MAAM,MAAM,oBAAoB,GAAG;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,UAAU,EAAE,eAAe,EAAE,CAAC;CAC/B,CAAC;AAmfF,wBAAsB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkChF;AAiCD,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAmBnF"}
|
package/dist/renderer.js
CHANGED
|
@@ -30,7 +30,13 @@ function expandOperationPath(relativePath, options) {
|
|
|
30
30
|
}
|
|
31
31
|
async function renderCopyFile(operation, options) {
|
|
32
32
|
const variables = options.variables ?? {};
|
|
33
|
-
const
|
|
33
|
+
const sourceRoot = operation.sourceRoot === undefined
|
|
34
|
+
? options.sourceRoot
|
|
35
|
+
: options.sourceRoots?.[operation.sourceRoot];
|
|
36
|
+
if (sourceRoot === undefined) {
|
|
37
|
+
throw new Error(`Unknown renderer source root: ${operation.sourceRoot}`);
|
|
38
|
+
}
|
|
39
|
+
const from = resolveContainedPath(sourceRoot, expandTemplatePath(operation.from, variables));
|
|
34
40
|
const to = resolveContainedPath(options.targetRoot, expandTemplatePath(operation.to, variables));
|
|
35
41
|
const sourceMode = (await stat(from)).mode;
|
|
36
42
|
await mkdir(path.dirname(to), { recursive: true });
|
|
@@ -163,9 +169,6 @@ function assertFoundationTextPath(relativePath) {
|
|
|
163
169
|
["Cargo.toml", "Cargo.lock", "rustfmt.toml"].includes(normalizedPath)) {
|
|
164
170
|
return;
|
|
165
171
|
}
|
|
166
|
-
if (normalizedPath === "scripts/check") {
|
|
167
|
-
return;
|
|
168
|
-
}
|
|
169
172
|
if (/^\.github\/workflows\/[A-Za-z0-9._-]+\.ya?ml$/.test(normalizedPath)) {
|
|
170
173
|
return;
|
|
171
174
|
}
|
package/dist/rust-bin.d.ts
CHANGED
|
@@ -1,2 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
import { type GenerationContext } from "./generation-context.js";
|
|
2
|
+
type InitRustBinProjectOptions = {
|
|
3
|
+
readonly generationContext?: GenerationContext;
|
|
4
|
+
};
|
|
5
|
+
export declare function projectRustBinPackageScripts(): Record<string, string>;
|
|
6
|
+
export declare function initRustBinProject(targetDir: string, options?: InitRustBinProjectOptions): Promise<void>;
|
|
7
|
+
export {};
|
|
2
8
|
//# sourceMappingURL=rust-bin.d.ts.map
|
package/dist/rust-bin.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rust-bin.d.ts","sourceRoot":"","sources":["../src/rust-bin.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"rust-bin.d.ts","sourceRoot":"","sources":["../src/rust-bin.ts"],"names":[],"mappings":"AAIA,OAAO,EAA6B,KAAK,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AA2B5F,KAAK,yBAAyB,GAAG;IAC/B,QAAQ,CAAC,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;CAChD,CAAC;AAmEF,wBAAgB,4BAA4B,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAKrE;AAgHD,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,yBAAyB,GAClC,OAAO,CAAC,IAAI,CAAC,CAef"}
|
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"]
|
|
@@ -153,54 +180,29 @@ function operationsForRustBin(projectName) {
|
|
|
153
180
|
{
|
|
154
181
|
kind: "writeText",
|
|
155
182
|
to: ".github/workflows/check.yml",
|
|
156
|
-
text:
|
|
157
|
-
"name: Check",
|
|
158
|
-
"",
|
|
159
|
-
"on:",
|
|
160
|
-
" pull_request:",
|
|
161
|
-
" push:",
|
|
162
|
-
" branches:",
|
|
163
|
-
" - main",
|
|
164
|
-
"",
|
|
165
|
-
"jobs:",
|
|
166
|
-
" check:",
|
|
167
|
-
" runs-on: ubuntu-latest",
|
|
168
|
-
" steps:",
|
|
169
|
-
" - uses: actions/checkout@v4",
|
|
170
|
-
" - uses: dtolnay/rust-toolchain@stable",
|
|
171
|
-
" with:",
|
|
172
|
-
" components: rustfmt, clippy",
|
|
173
|
-
" - uses: Swatinem/rust-cache@v2",
|
|
174
|
-
" - run: ./scripts/check",
|
|
175
|
-
""
|
|
176
|
-
].join("\n")
|
|
183
|
+
text: projectRustBinGithubCheckWorkflow(),
|
|
177
184
|
},
|
|
178
185
|
{
|
|
179
186
|
kind: "writeText",
|
|
180
187
|
to: ".github/dependabot.yml",
|
|
181
|
-
text:
|
|
182
|
-
"version: 2",
|
|
183
|
-
"updates:",
|
|
184
|
-
" - package-ecosystem: cargo",
|
|
185
|
-
" directory: /",
|
|
186
|
-
" schedule:",
|
|
187
|
-
" interval: weekly",
|
|
188
|
-
" - package-ecosystem: github-actions",
|
|
189
|
-
" directory: /",
|
|
190
|
-
" schedule:",
|
|
191
|
-
" interval: weekly",
|
|
192
|
-
""
|
|
193
|
-
].join("\n")
|
|
188
|
+
text: projectPresetDependabotConfig("rust-bin"),
|
|
194
189
|
}
|
|
195
190
|
];
|
|
196
191
|
}
|
|
197
192
|
function templateSourceRoot() {
|
|
198
193
|
return path.join(path.dirname(fileURLToPath(import.meta.url)), "..", "templates", "rust-bin");
|
|
199
194
|
}
|
|
200
|
-
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);
|
|
201
203
|
await renderNewProject({
|
|
202
204
|
sourceRoot: templateSourceRoot(),
|
|
203
205
|
targetRoot: targetDir,
|
|
204
|
-
operations: operationsForRustBin(
|
|
206
|
+
operations: operationsForRustBin(generationContext, projectName)
|
|
205
207
|
});
|
|
206
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"}
|