@stll/oxlint-config 0.7.0 → 0.9.0

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.
@@ -0,0 +1,214 @@
1
+ #!/usr/bin/env node
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ //#region \0rolldown/runtime.js
4
+ var __create = Object.create;
5
+ var __defProp = Object.defineProperty;
6
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
7
+ var __getOwnPropNames = Object.getOwnPropertyNames;
8
+ var __getProtoOf = Object.getPrototypeOf;
9
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
12
+ key = keys[i];
13
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
14
+ get: ((k) => from[k]).bind(null, key),
15
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
16
+ });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
21
+ value: mod,
22
+ enumerable: true
23
+ }) : target, mod));
24
+ //#endregion
25
+ let node_fs = require("node:fs");
26
+ let node_child_process = require("node:child_process");
27
+ let node_path = require("node:path");
28
+ node_path = __toESM(node_path, 1);
29
+ //#region src/toolchain-check.ts
30
+ const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
31
+ const scalar = (value) => value.trim().replace(/\s+#.*$/, "").replace(/^["']|["']$/g, "");
32
+ const trackedPath = (file) => !file.split("/").some((part) => part === "node_modules" || part === "vendor");
33
+ /** Check tracked consumer files without traversing dependencies or the working tree. */
34
+ const checkToolchain = ({ root, bunVersion, allowNonBunPackageManagers = [] }) => {
35
+ const files = (0, node_child_process.execFileSync)("git", [
36
+ "ls-files",
37
+ "-z",
38
+ "--cached"
39
+ ], {
40
+ cwd: root,
41
+ encoding: "utf8"
42
+ }).split("\0").filter((file) => file !== "" && trackedPath(file));
43
+ const tracked = new Set(files);
44
+ const diagnostics = [];
45
+ const add = (file, line, message) => {
46
+ diagnostics.push({
47
+ path: file,
48
+ line,
49
+ message
50
+ });
51
+ };
52
+ const read = (file) => {
53
+ try {
54
+ return (0, node_fs.readFileSync)(node_path.default.join(root, file), "utf8");
55
+ } catch {
56
+ add(file, 1, "cannot read tracked file");
57
+ return;
58
+ }
59
+ };
60
+ const checkVersion = (file, line, value, label) => {
61
+ if (value !== bunVersion) add(file, line, `${label} must be ${bunVersion}, found ${String(value)}`);
62
+ };
63
+ const packages = /* @__PURE__ */ new Map();
64
+ for (const file of files.filter((entry) => node_path.default.basename(entry) === "package.json")) {
65
+ const text = read(file);
66
+ if (text === void 0) continue;
67
+ let json;
68
+ try {
69
+ json = JSON.parse(text);
70
+ } catch {
71
+ add(file, 1, "invalid package.json");
72
+ continue;
73
+ }
74
+ if (!isRecord(json)) {
75
+ add(file, 1, "package.json must contain an object");
76
+ continue;
77
+ }
78
+ packages.set(file, {
79
+ manager: json["packageManager"],
80
+ json,
81
+ text
82
+ });
83
+ }
84
+ const catalogSource = (json) => isRecord(json["workspaces"]) ? json["workspaces"] : json;
85
+ const rootCatalogs = catalogSource(packages.get("package.json")?.json ?? {});
86
+ for (const [file, { json, text }] of packages) {
87
+ const lines = text.split(/\r?\n/);
88
+ const reportedLines = /* @__PURE__ */ new Map();
89
+ const propertyLine = (key, value) => {
90
+ const serialized = value === void 0 ? void 0 : JSON.stringify(value);
91
+ const matchKey = `${key}:${serialized ?? ""}`;
92
+ const previous = reportedLines.get(matchKey) ?? -1;
93
+ const index = lines.findIndex((line, lineIndex) => lineIndex > previous && line.includes(`"${key}"`) && (serialized === void 0 || line.includes(serialized)));
94
+ if (index >= 0) reportedLines.set(matchKey, index);
95
+ return Math.max(1, index + 1);
96
+ };
97
+ if (json["packageManager"] !== void 0) {
98
+ if (typeof json["packageManager"] === "string" && json["packageManager"].startsWith("bun@")) checkVersion(file, propertyLine("packageManager"), json["packageManager"].slice(4), "packageManager Bun version");
99
+ else if (!allowNonBunPackageManagers.includes(file)) add(file, propertyLine("packageManager"), "packageManager is not Bun; use --allow-non-bun-package-manager with this path to allow it");
100
+ }
101
+ const checkDependencies = (value, resolveCatalog = false) => {
102
+ if (!isRecord(value) || value["bun-types"] === void 0) return;
103
+ const specifier = value["bun-types"];
104
+ const resolveVersion = () => {
105
+ if (!resolveCatalog || typeof specifier !== "string" || !specifier.startsWith("catalog:")) return specifier;
106
+ const catalogName = specifier.slice(8);
107
+ const source = file === "package.json" ? catalogSource(json) : rootCatalogs;
108
+ const catalog = catalogName === "" ? source["catalog"] : isRecord(source["catalogs"]) && source["catalogs"][catalogName];
109
+ return isRecord(catalog) ? catalog["bun-types"] : void 0;
110
+ };
111
+ checkVersion(file, propertyLine("bun-types", specifier), resolveVersion(), "bun-types");
112
+ };
113
+ checkDependencies(json["dependencies"], true);
114
+ checkDependencies(json["devDependencies"], true);
115
+ checkDependencies(json["catalog"]);
116
+ if (isRecord(json["catalogs"])) for (const catalog of Object.values(json["catalogs"])) checkDependencies(catalog);
117
+ if (isRecord(json["workspaces"])) {
118
+ checkDependencies(json["workspaces"]["catalog"]);
119
+ if (isRecord(json["workspaces"]["catalogs"])) for (const catalog of Object.values(json["workspaces"]["catalogs"])) checkDependencies(catalog);
120
+ }
121
+ }
122
+ for (const file of files) {
123
+ const name = node_path.default.basename(file);
124
+ const workflow = /^\.github\/workflows\/[^/]+\.ya?ml$/.test(file) || /^\.github\/actions\/.+\/action\.ya?ml$/.test(file);
125
+ const dockerfile = name.startsWith("Dockerfile") || name === "Containerfile";
126
+ const versionFile = name === ".bun-version" || name === ".tool-versions";
127
+ const mise = name === "mise.toml" || name === ".mise.toml";
128
+ if (!workflow && !dockerfile && !versionFile && !mise) continue;
129
+ const text = read(file);
130
+ if (text === void 0) continue;
131
+ if (name === ".bun-version") checkVersion(file, 1, scalar(text), ".bun-version");
132
+ let section = "";
133
+ for (const [index, original] of text.split(/\r?\n/).entries()) {
134
+ const line = index + 1;
135
+ if (/^\s*#/.test(original) || original.trim() === "") continue;
136
+ if (workflow) {
137
+ if (original.match(/(?:^\s*(?:-\s*)?|[{,]\s*)["']?bun-version["']?\s*:/) !== null) add(file, line, "bun-version literals are forbidden; use bun-version-file pointing to a package.json with the shared Bun pin");
138
+ const reference = original.match(/(?:^\s*(?:-\s*)?|[{,]\s*)["']?bun-version-file["']?\s*:\s*(?:"([^"]*)"|'([^']*)'|([^,}]*))/);
139
+ if (reference !== null) {
140
+ const target = scalar(reference[1] ?? reference[2] ?? reference[3] ?? "");
141
+ const normalized = node_path.default.posix.normalize(target);
142
+ const pkg = packages.get(normalized);
143
+ if (target === "" || node_path.default.posix.isAbsolute(target) || normalized.startsWith("../") || !tracked.has(normalized) || node_path.default.basename(normalized) !== "package.json" || pkg?.manager !== `bun@${bunVersion}`) add(file, line, `bun-version-file must reference a tracked package.json with packageManager bun@${bunVersion}, found ${target}`);
144
+ }
145
+ }
146
+ if (dockerfile) {
147
+ const image = original.match(/^\s*FROM\s+(?:--\S+\s+)*oven\/bun(?::([^\s@]+))?(?:@\S+)?(?:\s|$)/i);
148
+ if (image !== null) {
149
+ const tag = image[1];
150
+ if (tag !== void 0) {
151
+ const version = tag.match(/^(\d+\.\d+\.\d+)(?:-|$)/)?.[1];
152
+ checkVersion(file, line, version ?? tag, "oven/bun version");
153
+ } else if (!/oven\/bun@/i.test(original)) add(file, line, `oven/bun must use a ${bunVersion} version tag`);
154
+ }
155
+ }
156
+ if (name === ".tool-versions") {
157
+ const entry = original.match(/^\s*bun\s+(.+)$/);
158
+ if (entry !== null) checkVersion(file, line, scalar(entry[1] ?? ""), ".tool-versions Bun version");
159
+ }
160
+ if (mise) {
161
+ const heading = original.match(/^\s*\[([^\]]+)\]/);
162
+ if (heading !== null) section = heading[1] ?? "";
163
+ const checkMiseVersion = (value) => {
164
+ const inlineVersion = [...value.matchAll(/[,{]\s*([\w-]+|"[^"]+"|'[^']+')\s*=\s*("(?:\\.|[^"\\])*"|'[^']*'|[^,{}]+)\s*(?=[,}])/g)].find((field) => scalar(field[1] ?? "") === "version");
165
+ checkVersion(file, line, scalar(inlineVersion?.[2] ?? value), "mise Bun version");
166
+ };
167
+ const entry = original.match(/^\s*["']?bun["']?\s*=\s*(.+)$/);
168
+ if (entry !== null && section === "tools") checkMiseVersion(entry[1] ?? "");
169
+ const dotted = original.match(/^\s*tools\.bun(?:\.version)?\s*=\s*(.+)$/);
170
+ if (dotted !== null && section === "") checkMiseVersion(dotted[1] ?? "");
171
+ const tableVersion = original.match(/^\s*version\s*=\s*(.+)$/);
172
+ if (tableVersion !== null && section === "tools.bun") checkMiseVersion(tableVersion[1] ?? "");
173
+ const inlineTools = original.match(/^\s*tools\s*=\s*\{(.*)\}/);
174
+ if (inlineTools !== null && section === "") {
175
+ const inlineBun = inlineTools[1]?.match(/(?:^|,)\s*["']?bun["']?\s*=\s*(\{[^}]*\}|[^,}]+)/);
176
+ if (inlineBun !== null && inlineBun !== void 0) checkMiseVersion(inlineBun[1] ?? "");
177
+ }
178
+ }
179
+ }
180
+ }
181
+ return diagnostics;
182
+ };
183
+ //#endregion
184
+ //#region src/toolchain-check-cli.ts
185
+ try {
186
+ const allowNonBunPackageManagers = [];
187
+ const args = process.argv.slice(2);
188
+ for (let index = 0; index < args.length; index += 1) {
189
+ const argument = args[index];
190
+ if (argument === "--help") {
191
+ process.stdout.write("Usage: stll-toolchain-check [--allow-non-bun-package-manager <tracked package.json path>]\n");
192
+ process.exit(0);
193
+ }
194
+ const value = args.at(index + 1);
195
+ if (argument !== "--allow-non-bun-package-manager" || value === void 0 || value.startsWith("--")) throw new Error(`unexpected or incomplete argument: ${argument}`);
196
+ allowNonBunPackageManagers.push(value);
197
+ index += 1;
198
+ }
199
+ const toolchain = JSON.parse((0, node_fs.readFileSync)(new URL("../toolchain.json", require("url").pathToFileURL(__filename).href), "utf8"));
200
+ if (typeof toolchain !== "object" || toolchain === null || !("bun" in toolchain) || typeof toolchain.bun !== "string") throw new Error("installed toolchain.json must define a Bun version");
201
+ const diagnostics = checkToolchain({
202
+ root: process.cwd(),
203
+ bunVersion: toolchain.bun,
204
+ allowNonBunPackageManagers
205
+ });
206
+ for (const diagnostic of diagnostics) process.stderr.write(`${diagnostic.path}:${diagnostic.line}: ${diagnostic.message}\n`);
207
+ if (diagnostics.length > 0) process.exitCode = 1;
208
+ } catch (error) {
209
+ process.stderr.write(`toolchain-check:1: ${error instanceof Error ? error.message : String(error)}\n`);
210
+ process.exitCode = 1;
211
+ }
212
+ //#endregion
213
+
214
+ //# sourceMappingURL=toolchain-check-cli.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolchain-check-cli.cjs","names":["path"],"sources":["../src/toolchain-check.ts","../src/toolchain-check-cli.ts"],"sourcesContent":["import { execFileSync } from \"node:child_process\";\nimport { readFileSync } from \"node:fs\";\nimport path from \"node:path\";\n\nexport type ToolchainDiagnostic = {\n path: string;\n line: number;\n message: string;\n};\n\nexport type CheckToolchainOptions = {\n root: string;\n bunVersion: string;\n allowNonBunPackageManagers?: readonly string[];\n};\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nconst scalar = (value: string) =>\n value\n .trim()\n .replace(/\\s+#.*$/, \"\")\n .replace(/^[\"']|[\"']$/g, \"\");\n\nconst trackedPath = (file: string) =>\n !file.split(\"/\").some((part) => part === \"node_modules\" || part === \"vendor\");\n\n/** Check tracked consumer files without traversing dependencies or the working tree. */\nexport const checkToolchain = ({\n root,\n bunVersion,\n allowNonBunPackageManagers = [],\n}: CheckToolchainOptions): ToolchainDiagnostic[] => {\n const files = execFileSync(\"git\", [\"ls-files\", \"-z\", \"--cached\"], {\n cwd: root,\n encoding: \"utf8\",\n })\n .split(\"\\0\")\n .filter((file) => file !== \"\" && trackedPath(file));\n const tracked = new Set(files);\n const diagnostics: ToolchainDiagnostic[] = [];\n const add = (file: string, line: number, message: string) => {\n diagnostics.push({ path: file, line, message });\n };\n const read = (file: string): string | undefined => {\n try {\n return readFileSync(path.join(root, file), \"utf8\");\n } catch {\n add(file, 1, \"cannot read tracked file\");\n return undefined;\n }\n };\n const checkVersion = (\n file: string,\n line: number,\n value: unknown,\n label: string,\n ) => {\n if (value !== bunVersion) {\n add(file, line, `${label} must be ${bunVersion}, found ${String(value)}`);\n }\n };\n const packages = new Map<\n string,\n { manager: unknown; json: Record<string, unknown>; text: string }\n >();\n for (const file of files.filter(\n (entry) => path.basename(entry) === \"package.json\",\n )) {\n const text = read(file);\n if (text === undefined) continue;\n let json: unknown;\n try {\n json = JSON.parse(text);\n } catch {\n add(file, 1, \"invalid package.json\");\n continue;\n }\n if (!isRecord(json)) {\n add(file, 1, \"package.json must contain an object\");\n continue;\n }\n packages.set(file, { manager: json[\"packageManager\"], json, text });\n }\n const catalogSource = (json: Record<string, unknown>) =>\n isRecord(json[\"workspaces\"]) ? json[\"workspaces\"] : json;\n const rootCatalogs = catalogSource(packages.get(\"package.json\")?.json ?? {});\n for (const [file, { json, text }] of packages) {\n const lines = text.split(/\\r?\\n/);\n const reportedLines = new Map<string, number>();\n const propertyLine = (key: string, value?: unknown) => {\n const serialized =\n value === undefined ? undefined : JSON.stringify(value);\n const matchKey = `${key}:${serialized ?? \"\"}`;\n const previous = reportedLines.get(matchKey) ?? -1;\n const index = lines.findIndex(\n (line, lineIndex) =>\n lineIndex > previous &&\n line.includes(`\"${key}\"`) &&\n (serialized === undefined || line.includes(serialized)),\n );\n if (index >= 0) reportedLines.set(matchKey, index);\n return Math.max(1, index + 1);\n };\n if (json[\"packageManager\"] !== undefined) {\n if (\n typeof json[\"packageManager\"] === \"string\" &&\n json[\"packageManager\"].startsWith(\"bun@\")\n ) {\n checkVersion(\n file,\n propertyLine(\"packageManager\"),\n json[\"packageManager\"].slice(4),\n \"packageManager Bun version\",\n );\n } else if (!allowNonBunPackageManagers.includes(file)) {\n add(\n file,\n propertyLine(\"packageManager\"),\n \"packageManager is not Bun; use --allow-non-bun-package-manager with this path to allow it\",\n );\n }\n }\n const checkDependencies = (value: unknown, resolveCatalog = false) => {\n if (!isRecord(value) || value[\"bun-types\"] === undefined) return;\n const specifier = value[\"bun-types\"];\n const resolveVersion = () => {\n if (\n !resolveCatalog ||\n typeof specifier !== \"string\" ||\n !specifier.startsWith(\"catalog:\")\n )\n return specifier;\n const catalogName = specifier.slice(\"catalog:\".length);\n const source =\n file === \"package.json\" ? catalogSource(json) : rootCatalogs;\n const catalog =\n catalogName === \"\"\n ? source[\"catalog\"]\n : isRecord(source[\"catalogs\"]) && source[\"catalogs\"][catalogName];\n return isRecord(catalog) ? catalog[\"bun-types\"] : undefined;\n };\n checkVersion(\n file,\n propertyLine(\"bun-types\", specifier),\n resolveVersion(),\n \"bun-types\",\n );\n };\n checkDependencies(json[\"dependencies\"], true);\n checkDependencies(json[\"devDependencies\"], true);\n checkDependencies(json[\"catalog\"]);\n if (isRecord(json[\"catalogs\"])) {\n for (const catalog of Object.values(json[\"catalogs\"]))\n checkDependencies(catalog);\n }\n if (isRecord(json[\"workspaces\"])) {\n checkDependencies(json[\"workspaces\"][\"catalog\"]);\n if (isRecord(json[\"workspaces\"][\"catalogs\"])) {\n for (const catalog of Object.values(json[\"workspaces\"][\"catalogs\"]))\n checkDependencies(catalog);\n }\n }\n }\n for (const file of files) {\n const name = path.basename(file);\n const workflow =\n /^\\.github\\/workflows\\/[^/]+\\.ya?ml$/.test(file) ||\n /^\\.github\\/actions\\/.+\\/action\\.ya?ml$/.test(file);\n const dockerfile =\n name.startsWith(\"Dockerfile\") || name === \"Containerfile\";\n const versionFile = name === \".bun-version\" || name === \".tool-versions\";\n const mise = name === \"mise.toml\" || name === \".mise.toml\";\n if (!workflow && !dockerfile && !versionFile && !mise) continue;\n const text = read(file);\n if (text === undefined) continue;\n if (name === \".bun-version\")\n checkVersion(file, 1, scalar(text), \".bun-version\");\n let section = \"\";\n for (const [index, original] of text.split(/\\r?\\n/).entries()) {\n const line = index + 1;\n if (/^\\s*#/.test(original) || original.trim() === \"\") continue;\n if (workflow) {\n const pin = original.match(\n /(?:^\\s*(?:-\\s*)?|[{,]\\s*)[\"']?bun-version[\"']?\\s*:/,\n );\n if (pin !== null)\n add(\n file,\n line,\n \"bun-version literals are forbidden; use bun-version-file pointing to a package.json with the shared Bun pin\",\n );\n const reference = original.match(\n /(?:^\\s*(?:-\\s*)?|[{,]\\s*)[\"']?bun-version-file[\"']?\\s*:\\s*(?:\"([^\"]*)\"|'([^']*)'|([^,}]*))/,\n );\n if (reference !== null) {\n const target = scalar(\n reference[1] ?? reference[2] ?? reference[3] ?? \"\",\n );\n const normalized = path.posix.normalize(target);\n const pkg = packages.get(normalized);\n if (\n target === \"\" ||\n path.posix.isAbsolute(target) ||\n normalized.startsWith(\"../\") ||\n !tracked.has(normalized) ||\n path.basename(normalized) !== \"package.json\" ||\n pkg?.manager !== `bun@${bunVersion}`\n ) {\n add(\n file,\n line,\n `bun-version-file must reference a tracked package.json with packageManager bun@${bunVersion}, found ${target}`,\n );\n }\n }\n }\n if (dockerfile) {\n const image = original.match(\n /^\\s*FROM\\s+(?:--\\S+\\s+)*oven\\/bun(?::([^\\s@]+))?(?:@\\S+)?(?:\\s|$)/i,\n );\n if (image !== null) {\n const tag = image[1];\n if (tag !== undefined) {\n const version = tag.match(/^(\\d+\\.\\d+\\.\\d+)(?:-|$)/)?.[1];\n checkVersion(file, line, version ?? tag, \"oven/bun version\");\n } else if (!/oven\\/bun@/i.test(original)) {\n add(file, line, `oven/bun must use a ${bunVersion} version tag`);\n }\n }\n }\n if (name === \".tool-versions\") {\n const entry = original.match(/^\\s*bun\\s+(.+)$/);\n if (entry !== null)\n checkVersion(\n file,\n line,\n scalar(entry[1] ?? \"\"),\n \".tool-versions Bun version\",\n );\n }\n if (mise) {\n const heading = original.match(/^\\s*\\[([^\\]]+)\\]/);\n if (heading !== null) section = heading[1] ?? \"\";\n const checkMiseVersion = (value: string) => {\n const inlineVersion = [\n ...value.matchAll(\n /[,{]\\s*([\\w-]+|\"[^\"]+\"|'[^']+')\\s*=\\s*(\"(?:\\\\.|[^\"\\\\])*\"|'[^']*'|[^,{}]+)\\s*(?=[,}])/g,\n ),\n ].find((field) => scalar(field[1] ?? \"\") === \"version\");\n checkVersion(\n file,\n line,\n scalar(inlineVersion?.[2] ?? value),\n \"mise Bun version\",\n );\n };\n const entry = original.match(/^\\s*[\"']?bun[\"']?\\s*=\\s*(.+)$/);\n if (entry !== null && section === \"tools\")\n checkMiseVersion(entry[1] ?? \"\");\n const dotted = original.match(\n /^\\s*tools\\.bun(?:\\.version)?\\s*=\\s*(.+)$/,\n );\n if (dotted !== null && section === \"\")\n checkMiseVersion(dotted[1] ?? \"\");\n const tableVersion = original.match(/^\\s*version\\s*=\\s*(.+)$/);\n if (tableVersion !== null && section === \"tools.bun\")\n checkMiseVersion(tableVersion[1] ?? \"\");\n const inlineTools = original.match(/^\\s*tools\\s*=\\s*\\{(.*)\\}/);\n if (inlineTools !== null && section === \"\") {\n const inlineBun = inlineTools[1]?.match(\n /(?:^|,)\\s*[\"']?bun[\"']?\\s*=\\s*(\\{[^}]*\\}|[^,}]+)/,\n );\n if (inlineBun !== null && inlineBun !== undefined)\n checkMiseVersion(inlineBun[1] ?? \"\");\n }\n }\n }\n }\n return diagnostics;\n};\n","#!/usr/bin/env node\nimport { readFileSync } from \"node:fs\";\n\nimport { checkToolchain } from \"./toolchain-check\";\n\ntry {\n const allowNonBunPackageManagers: string[] = [];\n const args = process.argv.slice(2);\n for (let index = 0; index < args.length; index += 1) {\n const argument = args[index];\n if (argument === \"--help\") {\n process.stdout.write(\n \"Usage: stll-toolchain-check [--allow-non-bun-package-manager <tracked package.json path>]\\n\",\n );\n process.exit(0);\n }\n const value = args.at(index + 1);\n if (\n argument !== \"--allow-non-bun-package-manager\" ||\n value === undefined ||\n value.startsWith(\"--\")\n ) {\n throw new Error(`unexpected or incomplete argument: ${argument}`);\n }\n allowNonBunPackageManagers.push(value);\n index += 1;\n }\n const toolchain: unknown = JSON.parse(\n readFileSync(new URL(\"../toolchain.json\", import.meta.url), \"utf8\"),\n );\n if (\n typeof toolchain !== \"object\" ||\n toolchain === null ||\n !(\"bun\" in toolchain) ||\n typeof toolchain.bun !== \"string\"\n ) {\n throw new Error(\"installed toolchain.json must define a Bun version\");\n }\n const diagnostics = checkToolchain({\n root: process.cwd(),\n bunVersion: toolchain.bun,\n allowNonBunPackageManagers,\n });\n for (const diagnostic of diagnostics)\n process.stderr.write(\n `${diagnostic.path}:${diagnostic.line}: ${diagnostic.message}\\n`,\n );\n if (diagnostics.length > 0) process.exitCode = 1;\n} catch (error) {\n process.stderr.write(\n `toolchain-check:1: ${error instanceof Error ? error.message : String(error)}\\n`,\n );\n process.exitCode = 1;\n}\n"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,191 @@
1
+ #!/usr/bin/env node
2
+ import { readFileSync } from "node:fs";
3
+ import { execFileSync } from "node:child_process";
4
+ import path from "node:path";
5
+ //#region src/toolchain-check.ts
6
+ const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
7
+ const scalar = (value) => value.trim().replace(/\s+#.*$/, "").replace(/^["']|["']$/g, "");
8
+ const trackedPath = (file) => !file.split("/").some((part) => part === "node_modules" || part === "vendor");
9
+ /** Check tracked consumer files without traversing dependencies or the working tree. */
10
+ const checkToolchain = ({ root, bunVersion, allowNonBunPackageManagers = [] }) => {
11
+ const files = execFileSync("git", [
12
+ "ls-files",
13
+ "-z",
14
+ "--cached"
15
+ ], {
16
+ cwd: root,
17
+ encoding: "utf8"
18
+ }).split("\0").filter((file) => file !== "" && trackedPath(file));
19
+ const tracked = new Set(files);
20
+ const diagnostics = [];
21
+ const add = (file, line, message) => {
22
+ diagnostics.push({
23
+ path: file,
24
+ line,
25
+ message
26
+ });
27
+ };
28
+ const read = (file) => {
29
+ try {
30
+ return readFileSync(path.join(root, file), "utf8");
31
+ } catch {
32
+ add(file, 1, "cannot read tracked file");
33
+ return;
34
+ }
35
+ };
36
+ const checkVersion = (file, line, value, label) => {
37
+ if (value !== bunVersion) add(file, line, `${label} must be ${bunVersion}, found ${String(value)}`);
38
+ };
39
+ const packages = /* @__PURE__ */ new Map();
40
+ for (const file of files.filter((entry) => path.basename(entry) === "package.json")) {
41
+ const text = read(file);
42
+ if (text === void 0) continue;
43
+ let json;
44
+ try {
45
+ json = JSON.parse(text);
46
+ } catch {
47
+ add(file, 1, "invalid package.json");
48
+ continue;
49
+ }
50
+ if (!isRecord(json)) {
51
+ add(file, 1, "package.json must contain an object");
52
+ continue;
53
+ }
54
+ packages.set(file, {
55
+ manager: json["packageManager"],
56
+ json,
57
+ text
58
+ });
59
+ }
60
+ const catalogSource = (json) => isRecord(json["workspaces"]) ? json["workspaces"] : json;
61
+ const rootCatalogs = catalogSource(packages.get("package.json")?.json ?? {});
62
+ for (const [file, { json, text }] of packages) {
63
+ const lines = text.split(/\r?\n/);
64
+ const reportedLines = /* @__PURE__ */ new Map();
65
+ const propertyLine = (key, value) => {
66
+ const serialized = value === void 0 ? void 0 : JSON.stringify(value);
67
+ const matchKey = `${key}:${serialized ?? ""}`;
68
+ const previous = reportedLines.get(matchKey) ?? -1;
69
+ const index = lines.findIndex((line, lineIndex) => lineIndex > previous && line.includes(`"${key}"`) && (serialized === void 0 || line.includes(serialized)));
70
+ if (index >= 0) reportedLines.set(matchKey, index);
71
+ return Math.max(1, index + 1);
72
+ };
73
+ if (json["packageManager"] !== void 0) {
74
+ if (typeof json["packageManager"] === "string" && json["packageManager"].startsWith("bun@")) checkVersion(file, propertyLine("packageManager"), json["packageManager"].slice(4), "packageManager Bun version");
75
+ else if (!allowNonBunPackageManagers.includes(file)) add(file, propertyLine("packageManager"), "packageManager is not Bun; use --allow-non-bun-package-manager with this path to allow it");
76
+ }
77
+ const checkDependencies = (value, resolveCatalog = false) => {
78
+ if (!isRecord(value) || value["bun-types"] === void 0) return;
79
+ const specifier = value["bun-types"];
80
+ const resolveVersion = () => {
81
+ if (!resolveCatalog || typeof specifier !== "string" || !specifier.startsWith("catalog:")) return specifier;
82
+ const catalogName = specifier.slice(8);
83
+ const source = file === "package.json" ? catalogSource(json) : rootCatalogs;
84
+ const catalog = catalogName === "" ? source["catalog"] : isRecord(source["catalogs"]) && source["catalogs"][catalogName];
85
+ return isRecord(catalog) ? catalog["bun-types"] : void 0;
86
+ };
87
+ checkVersion(file, propertyLine("bun-types", specifier), resolveVersion(), "bun-types");
88
+ };
89
+ checkDependencies(json["dependencies"], true);
90
+ checkDependencies(json["devDependencies"], true);
91
+ checkDependencies(json["catalog"]);
92
+ if (isRecord(json["catalogs"])) for (const catalog of Object.values(json["catalogs"])) checkDependencies(catalog);
93
+ if (isRecord(json["workspaces"])) {
94
+ checkDependencies(json["workspaces"]["catalog"]);
95
+ if (isRecord(json["workspaces"]["catalogs"])) for (const catalog of Object.values(json["workspaces"]["catalogs"])) checkDependencies(catalog);
96
+ }
97
+ }
98
+ for (const file of files) {
99
+ const name = path.basename(file);
100
+ const workflow = /^\.github\/workflows\/[^/]+\.ya?ml$/.test(file) || /^\.github\/actions\/.+\/action\.ya?ml$/.test(file);
101
+ const dockerfile = name.startsWith("Dockerfile") || name === "Containerfile";
102
+ const versionFile = name === ".bun-version" || name === ".tool-versions";
103
+ const mise = name === "mise.toml" || name === ".mise.toml";
104
+ if (!workflow && !dockerfile && !versionFile && !mise) continue;
105
+ const text = read(file);
106
+ if (text === void 0) continue;
107
+ if (name === ".bun-version") checkVersion(file, 1, scalar(text), ".bun-version");
108
+ let section = "";
109
+ for (const [index, original] of text.split(/\r?\n/).entries()) {
110
+ const line = index + 1;
111
+ if (/^\s*#/.test(original) || original.trim() === "") continue;
112
+ if (workflow) {
113
+ if (original.match(/(?:^\s*(?:-\s*)?|[{,]\s*)["']?bun-version["']?\s*:/) !== null) add(file, line, "bun-version literals are forbidden; use bun-version-file pointing to a package.json with the shared Bun pin");
114
+ const reference = original.match(/(?:^\s*(?:-\s*)?|[{,]\s*)["']?bun-version-file["']?\s*:\s*(?:"([^"]*)"|'([^']*)'|([^,}]*))/);
115
+ if (reference !== null) {
116
+ const target = scalar(reference[1] ?? reference[2] ?? reference[3] ?? "");
117
+ const normalized = path.posix.normalize(target);
118
+ const pkg = packages.get(normalized);
119
+ if (target === "" || path.posix.isAbsolute(target) || normalized.startsWith("../") || !tracked.has(normalized) || path.basename(normalized) !== "package.json" || pkg?.manager !== `bun@${bunVersion}`) add(file, line, `bun-version-file must reference a tracked package.json with packageManager bun@${bunVersion}, found ${target}`);
120
+ }
121
+ }
122
+ if (dockerfile) {
123
+ const image = original.match(/^\s*FROM\s+(?:--\S+\s+)*oven\/bun(?::([^\s@]+))?(?:@\S+)?(?:\s|$)/i);
124
+ if (image !== null) {
125
+ const tag = image[1];
126
+ if (tag !== void 0) {
127
+ const version = tag.match(/^(\d+\.\d+\.\d+)(?:-|$)/)?.[1];
128
+ checkVersion(file, line, version ?? tag, "oven/bun version");
129
+ } else if (!/oven\/bun@/i.test(original)) add(file, line, `oven/bun must use a ${bunVersion} version tag`);
130
+ }
131
+ }
132
+ if (name === ".tool-versions") {
133
+ const entry = original.match(/^\s*bun\s+(.+)$/);
134
+ if (entry !== null) checkVersion(file, line, scalar(entry[1] ?? ""), ".tool-versions Bun version");
135
+ }
136
+ if (mise) {
137
+ const heading = original.match(/^\s*\[([^\]]+)\]/);
138
+ if (heading !== null) section = heading[1] ?? "";
139
+ const checkMiseVersion = (value) => {
140
+ const inlineVersion = [...value.matchAll(/[,{]\s*([\w-]+|"[^"]+"|'[^']+')\s*=\s*("(?:\\.|[^"\\])*"|'[^']*'|[^,{}]+)\s*(?=[,}])/g)].find((field) => scalar(field[1] ?? "") === "version");
141
+ checkVersion(file, line, scalar(inlineVersion?.[2] ?? value), "mise Bun version");
142
+ };
143
+ const entry = original.match(/^\s*["']?bun["']?\s*=\s*(.+)$/);
144
+ if (entry !== null && section === "tools") checkMiseVersion(entry[1] ?? "");
145
+ const dotted = original.match(/^\s*tools\.bun(?:\.version)?\s*=\s*(.+)$/);
146
+ if (dotted !== null && section === "") checkMiseVersion(dotted[1] ?? "");
147
+ const tableVersion = original.match(/^\s*version\s*=\s*(.+)$/);
148
+ if (tableVersion !== null && section === "tools.bun") checkMiseVersion(tableVersion[1] ?? "");
149
+ const inlineTools = original.match(/^\s*tools\s*=\s*\{(.*)\}/);
150
+ if (inlineTools !== null && section === "") {
151
+ const inlineBun = inlineTools[1]?.match(/(?:^|,)\s*["']?bun["']?\s*=\s*(\{[^}]*\}|[^,}]+)/);
152
+ if (inlineBun !== null && inlineBun !== void 0) checkMiseVersion(inlineBun[1] ?? "");
153
+ }
154
+ }
155
+ }
156
+ }
157
+ return diagnostics;
158
+ };
159
+ //#endregion
160
+ //#region src/toolchain-check-cli.ts
161
+ try {
162
+ const allowNonBunPackageManagers = [];
163
+ const args = process.argv.slice(2);
164
+ for (let index = 0; index < args.length; index += 1) {
165
+ const argument = args[index];
166
+ if (argument === "--help") {
167
+ process.stdout.write("Usage: stll-toolchain-check [--allow-non-bun-package-manager <tracked package.json path>]\n");
168
+ process.exit(0);
169
+ }
170
+ const value = args.at(index + 1);
171
+ if (argument !== "--allow-non-bun-package-manager" || value === void 0 || value.startsWith("--")) throw new Error(`unexpected or incomplete argument: ${argument}`);
172
+ allowNonBunPackageManagers.push(value);
173
+ index += 1;
174
+ }
175
+ const toolchain = JSON.parse(readFileSync(new URL("../toolchain.json", import.meta.url), "utf8"));
176
+ if (typeof toolchain !== "object" || toolchain === null || !("bun" in toolchain) || typeof toolchain.bun !== "string") throw new Error("installed toolchain.json must define a Bun version");
177
+ const diagnostics = checkToolchain({
178
+ root: process.cwd(),
179
+ bunVersion: toolchain.bun,
180
+ allowNonBunPackageManagers
181
+ });
182
+ for (const diagnostic of diagnostics) process.stderr.write(`${diagnostic.path}:${diagnostic.line}: ${diagnostic.message}\n`);
183
+ if (diagnostics.length > 0) process.exitCode = 1;
184
+ } catch (error) {
185
+ process.stderr.write(`toolchain-check:1: ${error instanceof Error ? error.message : String(error)}\n`);
186
+ process.exitCode = 1;
187
+ }
188
+ //#endregion
189
+ export {};
190
+
191
+ //# sourceMappingURL=toolchain-check-cli.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolchain-check-cli.mjs","names":[],"sources":["../src/toolchain-check.ts","../src/toolchain-check-cli.ts"],"sourcesContent":["import { execFileSync } from \"node:child_process\";\nimport { readFileSync } from \"node:fs\";\nimport path from \"node:path\";\n\nexport type ToolchainDiagnostic = {\n path: string;\n line: number;\n message: string;\n};\n\nexport type CheckToolchainOptions = {\n root: string;\n bunVersion: string;\n allowNonBunPackageManagers?: readonly string[];\n};\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nconst scalar = (value: string) =>\n value\n .trim()\n .replace(/\\s+#.*$/, \"\")\n .replace(/^[\"']|[\"']$/g, \"\");\n\nconst trackedPath = (file: string) =>\n !file.split(\"/\").some((part) => part === \"node_modules\" || part === \"vendor\");\n\n/** Check tracked consumer files without traversing dependencies or the working tree. */\nexport const checkToolchain = ({\n root,\n bunVersion,\n allowNonBunPackageManagers = [],\n}: CheckToolchainOptions): ToolchainDiagnostic[] => {\n const files = execFileSync(\"git\", [\"ls-files\", \"-z\", \"--cached\"], {\n cwd: root,\n encoding: \"utf8\",\n })\n .split(\"\\0\")\n .filter((file) => file !== \"\" && trackedPath(file));\n const tracked = new Set(files);\n const diagnostics: ToolchainDiagnostic[] = [];\n const add = (file: string, line: number, message: string) => {\n diagnostics.push({ path: file, line, message });\n };\n const read = (file: string): string | undefined => {\n try {\n return readFileSync(path.join(root, file), \"utf8\");\n } catch {\n add(file, 1, \"cannot read tracked file\");\n return undefined;\n }\n };\n const checkVersion = (\n file: string,\n line: number,\n value: unknown,\n label: string,\n ) => {\n if (value !== bunVersion) {\n add(file, line, `${label} must be ${bunVersion}, found ${String(value)}`);\n }\n };\n const packages = new Map<\n string,\n { manager: unknown; json: Record<string, unknown>; text: string }\n >();\n for (const file of files.filter(\n (entry) => path.basename(entry) === \"package.json\",\n )) {\n const text = read(file);\n if (text === undefined) continue;\n let json: unknown;\n try {\n json = JSON.parse(text);\n } catch {\n add(file, 1, \"invalid package.json\");\n continue;\n }\n if (!isRecord(json)) {\n add(file, 1, \"package.json must contain an object\");\n continue;\n }\n packages.set(file, { manager: json[\"packageManager\"], json, text });\n }\n const catalogSource = (json: Record<string, unknown>) =>\n isRecord(json[\"workspaces\"]) ? json[\"workspaces\"] : json;\n const rootCatalogs = catalogSource(packages.get(\"package.json\")?.json ?? {});\n for (const [file, { json, text }] of packages) {\n const lines = text.split(/\\r?\\n/);\n const reportedLines = new Map<string, number>();\n const propertyLine = (key: string, value?: unknown) => {\n const serialized =\n value === undefined ? undefined : JSON.stringify(value);\n const matchKey = `${key}:${serialized ?? \"\"}`;\n const previous = reportedLines.get(matchKey) ?? -1;\n const index = lines.findIndex(\n (line, lineIndex) =>\n lineIndex > previous &&\n line.includes(`\"${key}\"`) &&\n (serialized === undefined || line.includes(serialized)),\n );\n if (index >= 0) reportedLines.set(matchKey, index);\n return Math.max(1, index + 1);\n };\n if (json[\"packageManager\"] !== undefined) {\n if (\n typeof json[\"packageManager\"] === \"string\" &&\n json[\"packageManager\"].startsWith(\"bun@\")\n ) {\n checkVersion(\n file,\n propertyLine(\"packageManager\"),\n json[\"packageManager\"].slice(4),\n \"packageManager Bun version\",\n );\n } else if (!allowNonBunPackageManagers.includes(file)) {\n add(\n file,\n propertyLine(\"packageManager\"),\n \"packageManager is not Bun; use --allow-non-bun-package-manager with this path to allow it\",\n );\n }\n }\n const checkDependencies = (value: unknown, resolveCatalog = false) => {\n if (!isRecord(value) || value[\"bun-types\"] === undefined) return;\n const specifier = value[\"bun-types\"];\n const resolveVersion = () => {\n if (\n !resolveCatalog ||\n typeof specifier !== \"string\" ||\n !specifier.startsWith(\"catalog:\")\n )\n return specifier;\n const catalogName = specifier.slice(\"catalog:\".length);\n const source =\n file === \"package.json\" ? catalogSource(json) : rootCatalogs;\n const catalog =\n catalogName === \"\"\n ? source[\"catalog\"]\n : isRecord(source[\"catalogs\"]) && source[\"catalogs\"][catalogName];\n return isRecord(catalog) ? catalog[\"bun-types\"] : undefined;\n };\n checkVersion(\n file,\n propertyLine(\"bun-types\", specifier),\n resolveVersion(),\n \"bun-types\",\n );\n };\n checkDependencies(json[\"dependencies\"], true);\n checkDependencies(json[\"devDependencies\"], true);\n checkDependencies(json[\"catalog\"]);\n if (isRecord(json[\"catalogs\"])) {\n for (const catalog of Object.values(json[\"catalogs\"]))\n checkDependencies(catalog);\n }\n if (isRecord(json[\"workspaces\"])) {\n checkDependencies(json[\"workspaces\"][\"catalog\"]);\n if (isRecord(json[\"workspaces\"][\"catalogs\"])) {\n for (const catalog of Object.values(json[\"workspaces\"][\"catalogs\"]))\n checkDependencies(catalog);\n }\n }\n }\n for (const file of files) {\n const name = path.basename(file);\n const workflow =\n /^\\.github\\/workflows\\/[^/]+\\.ya?ml$/.test(file) ||\n /^\\.github\\/actions\\/.+\\/action\\.ya?ml$/.test(file);\n const dockerfile =\n name.startsWith(\"Dockerfile\") || name === \"Containerfile\";\n const versionFile = name === \".bun-version\" || name === \".tool-versions\";\n const mise = name === \"mise.toml\" || name === \".mise.toml\";\n if (!workflow && !dockerfile && !versionFile && !mise) continue;\n const text = read(file);\n if (text === undefined) continue;\n if (name === \".bun-version\")\n checkVersion(file, 1, scalar(text), \".bun-version\");\n let section = \"\";\n for (const [index, original] of text.split(/\\r?\\n/).entries()) {\n const line = index + 1;\n if (/^\\s*#/.test(original) || original.trim() === \"\") continue;\n if (workflow) {\n const pin = original.match(\n /(?:^\\s*(?:-\\s*)?|[{,]\\s*)[\"']?bun-version[\"']?\\s*:/,\n );\n if (pin !== null)\n add(\n file,\n line,\n \"bun-version literals are forbidden; use bun-version-file pointing to a package.json with the shared Bun pin\",\n );\n const reference = original.match(\n /(?:^\\s*(?:-\\s*)?|[{,]\\s*)[\"']?bun-version-file[\"']?\\s*:\\s*(?:\"([^\"]*)\"|'([^']*)'|([^,}]*))/,\n );\n if (reference !== null) {\n const target = scalar(\n reference[1] ?? reference[2] ?? reference[3] ?? \"\",\n );\n const normalized = path.posix.normalize(target);\n const pkg = packages.get(normalized);\n if (\n target === \"\" ||\n path.posix.isAbsolute(target) ||\n normalized.startsWith(\"../\") ||\n !tracked.has(normalized) ||\n path.basename(normalized) !== \"package.json\" ||\n pkg?.manager !== `bun@${bunVersion}`\n ) {\n add(\n file,\n line,\n `bun-version-file must reference a tracked package.json with packageManager bun@${bunVersion}, found ${target}`,\n );\n }\n }\n }\n if (dockerfile) {\n const image = original.match(\n /^\\s*FROM\\s+(?:--\\S+\\s+)*oven\\/bun(?::([^\\s@]+))?(?:@\\S+)?(?:\\s|$)/i,\n );\n if (image !== null) {\n const tag = image[1];\n if (tag !== undefined) {\n const version = tag.match(/^(\\d+\\.\\d+\\.\\d+)(?:-|$)/)?.[1];\n checkVersion(file, line, version ?? tag, \"oven/bun version\");\n } else if (!/oven\\/bun@/i.test(original)) {\n add(file, line, `oven/bun must use a ${bunVersion} version tag`);\n }\n }\n }\n if (name === \".tool-versions\") {\n const entry = original.match(/^\\s*bun\\s+(.+)$/);\n if (entry !== null)\n checkVersion(\n file,\n line,\n scalar(entry[1] ?? \"\"),\n \".tool-versions Bun version\",\n );\n }\n if (mise) {\n const heading = original.match(/^\\s*\\[([^\\]]+)\\]/);\n if (heading !== null) section = heading[1] ?? \"\";\n const checkMiseVersion = (value: string) => {\n const inlineVersion = [\n ...value.matchAll(\n /[,{]\\s*([\\w-]+|\"[^\"]+\"|'[^']+')\\s*=\\s*(\"(?:\\\\.|[^\"\\\\])*\"|'[^']*'|[^,{}]+)\\s*(?=[,}])/g,\n ),\n ].find((field) => scalar(field[1] ?? \"\") === \"version\");\n checkVersion(\n file,\n line,\n scalar(inlineVersion?.[2] ?? value),\n \"mise Bun version\",\n );\n };\n const entry = original.match(/^\\s*[\"']?bun[\"']?\\s*=\\s*(.+)$/);\n if (entry !== null && section === \"tools\")\n checkMiseVersion(entry[1] ?? \"\");\n const dotted = original.match(\n /^\\s*tools\\.bun(?:\\.version)?\\s*=\\s*(.+)$/,\n );\n if (dotted !== null && section === \"\")\n checkMiseVersion(dotted[1] ?? \"\");\n const tableVersion = original.match(/^\\s*version\\s*=\\s*(.+)$/);\n if (tableVersion !== null && section === \"tools.bun\")\n checkMiseVersion(tableVersion[1] ?? \"\");\n const inlineTools = original.match(/^\\s*tools\\s*=\\s*\\{(.*)\\}/);\n if (inlineTools !== null && section === \"\") {\n const inlineBun = inlineTools[1]?.match(\n /(?:^|,)\\s*[\"']?bun[\"']?\\s*=\\s*(\\{[^}]*\\}|[^,}]+)/,\n );\n if (inlineBun !== null && inlineBun !== undefined)\n checkMiseVersion(inlineBun[1] ?? \"\");\n }\n }\n }\n }\n return diagnostics;\n};\n","#!/usr/bin/env node\nimport { readFileSync } from \"node:fs\";\n\nimport { checkToolchain } from \"./toolchain-check\";\n\ntry {\n const allowNonBunPackageManagers: string[] = [];\n const args = process.argv.slice(2);\n for (let index = 0; index < args.length; index += 1) {\n const argument = args[index];\n if (argument === \"--help\") {\n process.stdout.write(\n \"Usage: stll-toolchain-check [--allow-non-bun-package-manager <tracked package.json path>]\\n\",\n );\n process.exit(0);\n }\n const value = args.at(index + 1);\n if (\n argument !== \"--allow-non-bun-package-manager\" ||\n value === undefined ||\n value.startsWith(\"--\")\n ) {\n throw new Error(`unexpected or incomplete argument: ${argument}`);\n }\n allowNonBunPackageManagers.push(value);\n index += 1;\n }\n const toolchain: unknown = JSON.parse(\n readFileSync(new URL(\"../toolchain.json\", import.meta.url), \"utf8\"),\n );\n if (\n typeof toolchain !== \"object\" ||\n toolchain === null ||\n !(\"bun\" in toolchain) ||\n typeof toolchain.bun !== \"string\"\n ) {\n throw new Error(\"installed toolchain.json must define a Bun version\");\n }\n const diagnostics = checkToolchain({\n root: process.cwd(),\n bunVersion: toolchain.bun,\n allowNonBunPackageManagers,\n });\n for (const diagnostic of diagnostics)\n process.stderr.write(\n `${diagnostic.path}:${diagnostic.line}: ${diagnostic.message}\\n`,\n );\n if (diagnostics.length > 0) process.exitCode = 1;\n} catch (error) {\n process.stderr.write(\n `toolchain-check:1: ${error instanceof Error ? error.message : String(error)}\\n`,\n );\n process.exitCode = 1;\n}\n"],"mappings":"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"}