@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.
Files changed (43) hide show
  1. package/dist/cli.js +66 -89
  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 +55 -53
  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/project-github.d.ts +36 -0
  19. package/dist/project-github.d.ts.map +1 -0
  20. package/dist/project-github.js +96 -0
  21. package/dist/renderer.d.ts.map +1 -1
  22. package/dist/renderer.js +0 -3
  23. package/dist/rust-bin.d.ts +7 -1
  24. package/dist/rust-bin.d.ts.map +1 -1
  25. package/dist/rust-bin.js +70 -36
  26. package/dist/toolchain-resolution.d.ts +35 -0
  27. package/dist/toolchain-resolution.d.ts.map +1 -0
  28. package/dist/toolchain-resolution.js +192 -0
  29. package/dist/ts-lib.d.ts +7 -1
  30. package/dist/ts-lib.d.ts.map +1 -1
  31. package/dist/ts-lib.js +87 -54
  32. package/dist/vue-app.d.ts +1 -0
  33. package/dist/vue-app.d.ts.map +1 -1
  34. package/dist/vue-app.js +70 -68
  35. package/dist/vue-hono-app.d.ts +3 -0
  36. package/dist/vue-hono-app.d.ts.map +1 -1
  37. package/dist/vue-hono-app.js +111 -107
  38. package/package.json +2 -1
  39. package/templates/rust-bin/.github/dependabot.yml +4 -0
  40. package/templates/rust-bin/.github/workflows/check.yml +6 -1
  41. package/dist/post-commands.d.ts +0 -40
  42. package/dist/post-commands.d.ts.map +0 -1
  43. 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 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"]
@@ -151,24 +178,31 @@ function operationsForRustBin(projectName) {
151
178
  }
152
179
  },
153
180
  {
154
- kind: "copyFile",
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: "copyFile",
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(cargoPackageNameFromDir(targetDir))
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
- 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":"AAoLA,wBAAsB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAOvE"}
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
- function projectNameFromDir(targetDir) {
10
- return path.basename(path.resolve(targetDir));
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(projectName) {
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: "22"
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(projectName) {
79
+ function operationsForTsLib(context) {
49
80
  return [
50
81
  {
51
82
  kind: "writeJson",
52
83
  to: "package.json",
53
- value: packageJson(projectName),
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: generatedBy
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
- image: "mcr.microsoft.com/devcontainers/typescript-node:22",
148
- postCreateCommand: "corepack enable && pnpm install",
149
- customizations: {
150
- vscode: {
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: "copyFile",
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: "copyFile",
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(projectNameFromDir(targetDir))
212
+ operations: operationsForTsLib(generationContext),
180
213
  });
181
214
  }
package/dist/vue-app.d.ts CHANGED
@@ -1,2 +1,3 @@
1
+ export declare function projectVueAppPackageScripts(): Record<string, string>;
1
2
  export declare function initVueAppProject(targetDir: string): Promise<void>;
2
3
  //# sourceMappingURL=vue-app.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"vue-app.d.ts","sourceRoot":"","sources":["../src/vue-app.ts"],"names":[],"mappings":"AA4SA,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAOxE"}
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"}