@ykdz/template 0.0.0 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/dist/cli.js +94 -44
  2. package/dist/declarations.js +1 -1
  3. package/dist/devcontainer.d.ts +17 -0
  4. package/dist/devcontainer.d.ts.map +1 -0
  5. package/dist/devcontainer.js +23 -0
  6. package/dist/generation-context.d.ts +24 -0
  7. package/dist/generation-context.d.ts.map +1 -0
  8. package/dist/generation-context.js +12 -0
  9. package/dist/hono-api.d.ts +1 -0
  10. package/dist/hono-api.d.ts.map +1 -1
  11. package/dist/hono-api.js +63 -100
  12. package/dist/module-graph.d.ts +45 -0
  13. package/dist/module-graph.d.ts.map +1 -0
  14. package/dist/module-graph.js +187 -0
  15. package/dist/next-step-instructions.d.ts +22 -0
  16. package/dist/next-step-instructions.d.ts.map +1 -0
  17. package/dist/next-step-instructions.js +99 -0
  18. package/dist/package-addition.d.ts.map +1 -1
  19. package/dist/package-addition.js +31 -51
  20. package/dist/project-github.d.ts +36 -0
  21. package/dist/project-github.d.ts.map +1 -0
  22. package/dist/project-github.js +96 -0
  23. package/dist/renderer.d.ts +2 -0
  24. package/dist/renderer.d.ts.map +1 -1
  25. package/dist/renderer.js +7 -4
  26. package/dist/rust-bin.d.ts +7 -1
  27. package/dist/rust-bin.d.ts.map +1 -1
  28. package/dist/rust-bin.js +68 -66
  29. package/dist/toolchain-resolution.d.ts +35 -0
  30. package/dist/toolchain-resolution.d.ts.map +1 -0
  31. package/dist/toolchain-resolution.js +192 -0
  32. package/dist/ts-lib.d.ts +7 -1
  33. package/dist/ts-lib.d.ts.map +1 -1
  34. package/dist/ts-lib.js +95 -101
  35. package/dist/vue-app.d.ts +1 -0
  36. package/dist/vue-app.d.ts.map +1 -1
  37. package/dist/vue-app.js +78 -116
  38. package/dist/vue-hono-app.d.ts +3 -0
  39. package/dist/vue-hono-app.d.ts.map +1 -1
  40. package/dist/vue-hono-app.js +126 -170
  41. package/package.json +24 -16
  42. package/templates/hono-api/.github/dependabot.yml +10 -0
  43. package/templates/hono-api/.github/workflows/check.yml +19 -0
  44. package/templates/hono-api/src/server.ts +3 -2
  45. package/templates/hono-api/vitest.config.ts +5 -4
  46. package/templates/rust-bin/.github/dependabot.yml +14 -0
  47. package/templates/rust-bin/.github/workflows/check.yml +23 -0
  48. package/templates/shared/oxc/node/oxlint.config.ts +9 -0
  49. package/templates/shared/oxc/oxfmt.config.ts +8 -0
  50. package/templates/shared/oxc/package.json +18 -0
  51. package/templates/shared/oxc/tsconfig.json +11 -0
  52. package/templates/shared/oxc/vue/oxlint.config.ts +9 -0
  53. package/templates/ts-lib/.github/dependabot.yml +10 -0
  54. package/templates/ts-lib/.github/workflows/check.yml +19 -0
  55. package/templates/vue-app/.github/dependabot.yml +10 -0
  56. package/templates/vue-app/.github/workflows/check.yml +20 -0
  57. package/templates/vue-app/playwright.config.ts +5 -5
  58. package/templates/vue-app/src/App.vue +15 -5
  59. package/templates/vue-app/src/main.ts +2 -0
  60. package/templates/vue-app/test/app.test.ts +1 -0
  61. package/templates/vue-app/test/e2e/app.spec.ts +3 -1
  62. package/templates/vue-app/vite.config.ts +6 -5
  63. package/templates/vue-app/vitest.config.ts +5 -4
  64. package/templates/vue-hono-app/.github/dependabot.yml +10 -0
  65. package/templates/vue-hono-app/.github/workflows/check.yml +20 -0
  66. package/templates/vue-hono-app/api/src/server.ts +3 -2
  67. package/templates/vue-hono-app/api/vitest.config.ts +2 -2
  68. package/templates/vue-hono-app/web/playwright.config.ts +9 -7
  69. package/templates/vue-hono-app/web/src/App.vue +12 -4
  70. package/templates/vue-hono-app/web/src/api.ts +1 -1
  71. package/templates/vue-hono-app/web/src/main.ts +2 -0
  72. package/templates/vue-hono-app/web/test/app.test.ts +1 -0
  73. package/templates/vue-hono-app/web/test/e2e/app.spec.ts +3 -1
  74. package/templates/vue-hono-app/web/vite.config.ts +13 -10
  75. package/templates/vue-hono-app/web/vitest.config.ts +6 -5
@@ -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;CACZ,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,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,UAAU,EAAE,eAAe,EAAE,CAAC;CAC/B,CAAC;AA8eF,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"}
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 from = resolveContainedPath(options.sourceRoot, expandTemplatePath(operation.from, variables));
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
  }
@@ -1,2 +1,8 @@
1
- export declare function initRustBinProject(targetDir: string): Promise<void>;
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
@@ -1 +1 @@
1
- {"version":3,"file":"rust-bin.d.ts","sourceRoot":"","sources":["../src/rust-bin.ts"],"names":[],"mappings":"AAgNA,wBAAsB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMzE"}
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 operationsForRustBin(projectName) {
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: generatedBy
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(cargoPackageNameFromDir(targetDir))
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
- export declare function initTsLibProject(targetDir: string): Promise<void>;
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
@@ -1 +1 @@
1
- {"version":3,"file":"ts-lib.d.ts","sourceRoot":"","sources":["../src/ts-lib.ts"],"names":[],"mappings":"AA2NA,wBAAsB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMvE"}
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"}