@stll/oxlint-config 1.9.0 → 2.0.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.
- package/README.md +93 -63
- package/dist/cloud-setup-cli.cjs +1 -2
- package/dist/cloud-setup-cli.cjs.map +1 -1
- package/dist/cloud-setup-cli.mjs +1 -2
- package/dist/cloud-setup-cli.mjs.map +1 -1
- package/dist/dependabot.d.cts +0 -19
- package/dist/dependabot.d.mts +0 -19
- package/dist/git-tracked-output.cjs +1 -1
- package/dist/git-tracked-output.mjs +1 -1
- package/dist/publish-artifact-syntax.cjs +1 -1
- package/dist/publish-artifact-syntax.mjs +1 -1
- package/dist/publish-contract-cli.cjs +2 -2
- package/dist/publish-contract-cli.mjs +2 -2
- package/dist/quarantine-cli.cjs +3 -2
- package/dist/quarantine-cli.cjs.map +1 -1
- package/dist/quarantine-cli.mjs +3 -2
- package/dist/quarantine-cli.mjs.map +1 -1
- package/dist/quarantine-policy.d.cts +25 -2
- package/dist/quarantine-policy.d.mts +25 -2
- package/dist/quarantine-policy2.cjs +177 -5
- package/dist/quarantine-policy2.cjs.map +1 -1
- package/dist/quarantine-policy2.mjs +166 -6
- package/dist/quarantine-policy2.mjs.map +1 -1
- package/dist/toolchain-changed-cli.cjs +1477 -2
- package/dist/toolchain-changed-cli.cjs.map +1 -1
- package/dist/toolchain-changed-cli.mjs +1474 -1
- package/dist/toolchain-changed-cli.mjs.map +1 -1
- package/dist/toolchain-check-cli.cjs +2 -0
- package/dist/toolchain-check-cli.cjs.map +1 -1
- package/dist/toolchain-check-cli.mjs +2 -0
- package/dist/toolchain-check-cli.mjs.map +1 -1
- package/dist/toolchain-guard.cjs +351 -242
- package/dist/toolchain-guard.cjs.map +1 -1
- package/dist/toolchain-guard.mjs +347 -244
- package/dist/toolchain-guard.mjs.map +1 -1
- package/dist/toolchain-inputs.cjs +13 -40
- package/dist/toolchain-inputs.cjs.map +1 -1
- package/dist/toolchain-inputs.mjs +13 -40
- package/dist/toolchain-inputs.mjs.map +1 -1
- package/dist/toolchain-schema.cjs +2 -44
- package/dist/toolchain-schema.cjs.map +1 -1
- package/dist/toolchain-schema.mjs +2 -44
- package/dist/toolchain-schema.mjs.map +1 -1
- package/dist/typecheck-probe-cli.cjs +40 -2
- package/dist/typecheck-probe-cli.cjs.map +1 -1
- package/dist/typecheck-probe-cli.mjs +39 -1
- package/dist/typecheck-probe-cli.mjs.map +1 -1
- package/package.json +3 -4
- package/toolchain.json +2 -28
- package/dist/toolchain-bun.cjs +0 -34
- package/dist/toolchain-bun.cjs.map +0 -1
- package/dist/toolchain-bun.mjs +0 -23
- package/dist/toolchain-bun.mjs.map +0 -1
- package/dist/toolchain-changed.cjs +0 -1484
- package/dist/toolchain-changed.cjs.map +0 -1
- package/dist/toolchain-changed.mjs +0 -1477
- package/dist/toolchain-changed.mjs.map +0 -1
- package/dist/typecheck-parity-cli.cjs +0 -71
- package/dist/typecheck-parity-cli.cjs.map +0 -1
- package/dist/typecheck-parity-cli.d.cts +0 -1
- package/dist/typecheck-parity-cli.d.mts +0 -1
- package/dist/typecheck-parity-cli.mjs +0 -71
- package/dist/typecheck-parity-cli.mjs.map +0 -1
- package/dist/typecheck-parity.cjs +0 -908
- package/dist/typecheck-parity.cjs.map +0 -1
- package/dist/typecheck-parity.mjs +0 -897
- package/dist/typecheck-parity.mjs.map +0 -1
|
@@ -313,43 +313,6 @@ const parseToolchainPolicy = (input) => {
|
|
|
313
313
|
if (!/^\d+\.\d+(?:\.\d+)?$/.test(python)) throw new Error("Python must be an exact minor or patch release");
|
|
314
314
|
if (!/^\d+\.\d+\.\d+$/.test(rust)) throw new Error("Rust must be an exact stable release");
|
|
315
315
|
if (!consumerTypescript.startsWith("6.") || consumerTypescript.includes("-") || consumerTypescript.includes("+")) throw new Error("consumerTypescript must be an exact stable TypeScript 6 release");
|
|
316
|
-
const compatibility = input["typescript6Compatibility"];
|
|
317
|
-
if (!record(compatibility)) throw new Error("missing TypeScript compatibility policy");
|
|
318
|
-
const version = string(compatibility, "version");
|
|
319
|
-
const packageAlias = string(compatibility, "packageAlias");
|
|
320
|
-
if ((0, semver.valid)(version) !== version) throw new Error("TypeScript compatibility must be an exact release");
|
|
321
|
-
const layouts = input["typescriptInstallLayouts"];
|
|
322
|
-
if (!Array.isArray(layouts) || layouts.length === 0) throw new Error("missing TypeScript install layouts");
|
|
323
|
-
const typescriptInstallLayouts = layouts.map((layout) => {
|
|
324
|
-
if (!record(layout)) throw new Error("invalid TypeScript install layout");
|
|
325
|
-
const compilerPackage = string(layout, "compilerPackage");
|
|
326
|
-
const compilerSpecifier = string(layout, "compilerSpecifier");
|
|
327
|
-
const typecheckCommand = string(layout, "typecheckCommand");
|
|
328
|
-
switch (layout["type"]) {
|
|
329
|
-
case "direct":
|
|
330
|
-
if (compilerSpecifier !== typescript || compilerPackage !== "typescript") throw new Error("direct TypeScript layout differs from shared version");
|
|
331
|
-
return {
|
|
332
|
-
type: "direct",
|
|
333
|
-
compilerPackage,
|
|
334
|
-
compilerSpecifier,
|
|
335
|
-
typecheckCommand
|
|
336
|
-
};
|
|
337
|
-
case "split-compatibility": {
|
|
338
|
-
const compatibilityPackage = string(layout, "compatibilityPackage");
|
|
339
|
-
const compatibilitySpecifier = string(layout, "compatibilitySpecifier");
|
|
340
|
-
if (compilerSpecifier !== `npm:typescript@${typescript}` || compatibilitySpecifier !== version) throw new Error("split TypeScript layout differs from shared versions");
|
|
341
|
-
return {
|
|
342
|
-
type: "split-compatibility",
|
|
343
|
-
compilerPackage,
|
|
344
|
-
compilerSpecifier,
|
|
345
|
-
compatibilityPackage,
|
|
346
|
-
compatibilitySpecifier,
|
|
347
|
-
typecheckCommand
|
|
348
|
-
};
|
|
349
|
-
}
|
|
350
|
-
default: throw new Error("unsupported TypeScript install layout");
|
|
351
|
-
}
|
|
352
|
-
});
|
|
353
316
|
const actionsInput = input["actions"];
|
|
354
317
|
if (!record(actionsInput) || Object.keys(actionsInput).length === 0) throw new Error("missing approved actions");
|
|
355
318
|
const actions = {};
|
|
@@ -409,11 +372,6 @@ const parseToolchainPolicy = (input) => {
|
|
|
409
372
|
rust,
|
|
410
373
|
packages,
|
|
411
374
|
actions,
|
|
412
|
-
typescriptInstallLayouts,
|
|
413
|
-
typescript6Compatibility: {
|
|
414
|
-
version,
|
|
415
|
-
packageAlias
|
|
416
|
-
},
|
|
417
375
|
dependabot: {
|
|
418
376
|
schedule,
|
|
419
377
|
cooldown: { defaultDays },
|
|
@@ -423,8 +381,8 @@ const parseToolchainPolicy = (input) => {
|
|
|
423
381
|
...Object.keys(packages),
|
|
424
382
|
"npm",
|
|
425
383
|
"pnpm",
|
|
426
|
-
|
|
427
|
-
|
|
384
|
+
"typescript",
|
|
385
|
+
"@typescript/native",
|
|
428
386
|
"bun-types"
|
|
429
387
|
])],
|
|
430
388
|
ignoredActions: Object.keys(actions),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toolchain-schema.cjs","names":["record","path","workspaceContains","parseToml","isFormatterConfigPath","githubAutomationFileKind","isLefthookConfigPath","parseDocument","isDockerDefinitionPath","isShellScript","valid","nodePolicyValid"],"sources":["../src/toolchain-formatter.ts","../src/toolchain-schema.ts"],"sourcesContent":["import path from \"node:path\";\nimport picomatch from \"picomatch\";\nimport { parse as parseToml } from \"smol-toml\";\nimport { parseDocument } from \"yaml\";\n\nimport {\n githubAutomationFileKind,\n isDockerDefinitionPath,\n isFormatterConfigPath,\n isLefthookConfigPath,\n isShellScript,\n} from \"./toolchain-inputs\";\nimport { workspaceContains } from \"./toolchain-workspaces\";\n\nexport const formatterRule = \"formatter-policy\" as const;\n\ntype Diagnostic = {\n rule: typeof formatterRule;\n path: string;\n line: number;\n message: string;\n};\n\nexport type FormatterStyle = Readonly<Record<string, unknown>>;\n\nexport type FormatterPolicy = {\n command: \"bun fmt\";\n style: FormatterStyle;\n /** Generated files every repository leaves to their generators. */\n ignorePatterns: readonly string[];\n};\n\n/** Repository-owned [fmt] keys: what to skip, and the Tailwind entry point. */\nexport const repositoryFormatKeys = [\n \"ignorePatterns\",\n \"sortTailwindcss\",\n] as const;\n\nconst record = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\n/** One style for every repository; only repository-owned keys may differ. */\nexport const parseFormatterPolicy = (input: unknown): FormatterPolicy => {\n if (\n !record(input) ||\n Object.keys(input).some(\n (key) => key !== \"command\" && key !== \"style\" && key !== \"ignorePatterns\",\n )\n )\n throw new Error(\n \"toolchain.json formatter accepts only command, style and ignorePatterns\",\n );\n if (input[\"command\"] !== \"bun fmt\")\n throw new Error(\"toolchain.json formatter command must be bun fmt\");\n const style = input[\"style\"];\n if (!record(style) || Object.keys(style).length === 0)\n throw new Error(\"toolchain.json formatter style must be a nonempty table\");\n for (const key of Object.keys(style))\n if (repositoryFormatKeys.some((owned) => owned === key))\n throw new Error(\n `toolchain.json formatter style cannot own the repository key ${key}`,\n );\n const ignorePatterns = input[\"ignorePatterns\"];\n if (\n !Array.isArray(ignorePatterns) ||\n !ignorePatterns.every(\n (pattern): pattern is string =>\n typeof pattern === \"string\" && pattern !== \"\",\n )\n )\n throw new Error(\n \"toolchain.json formatter ignorePatterns must be nonempty strings\",\n );\n return { command: \"bun fmt\", style, ignorePatterns };\n};\n\nconst tomlValue = (value: unknown): string => {\n if (Array.isArray(value)) return `[${value.map(tomlValue).join(\", \")}]`;\n if (record(value))\n return `{ ${Object.entries(value)\n .map(([key, entry]) => `${key} = ${tomlValue(entry)}`)\n .join(\", \")} }`;\n return JSON.stringify(value);\n};\n\nconst tomlLines = (entries: readonly (readonly [string, unknown])[]) =>\n entries.map(([key, value]) => `${key} = ${tomlValue(value)}\\n`).join(\"\");\n\n/** Render the shared bunfig.toml [fmt] tables. */\nexport const sharedFormatTables = (policy: FormatterPolicy) => {\n const entries = Object.entries(policy.style);\n let output = `[fmt]\\n${tomlLines(\n entries.filter(([, value]) => !record(value)),\n )}ignorePatterns = ${tomlValue(policy.ignorePatterns)}\\n`;\n for (const [name, table] of entries)\n if (record(table))\n output += `\\n[fmt.${name}]\\n${tomlLines(Object.entries(table))}`;\n return output;\n};\n\nconst stableJson = (value: unknown): string =>\n JSON.stringify(value, (_key, entry: unknown) =>\n record(entry)\n ? Object.fromEntries(\n Object.entries(entry).toSorted(([left], [right]) =>\n left.localeCompare(right),\n ),\n )\n : entry,\n );\n\n// Every alternative formatter is rejected, not only the one being replaced.\nconst formatterPackage = (name: string) =>\n name === \"oxfmt\" ||\n name === \"prettier\" ||\n name === \"dprint\" ||\n name === \"@biomejs/biome\" ||\n name.startsWith(\"@dprint/\") ||\n /^(?:@[^/]+\\/)?prettier-plugin-/.test(name);\n\nconst dependencyFields = [\n \"dependencies\",\n \"devDependencies\",\n \"optionalDependencies\",\n \"peerDependencies\",\n \"overrides\",\n \"resolutions\",\n \"catalog\",\n] as const;\n\nconst declaredPackages = (manifest: Record<string, unknown>) => {\n const tables: unknown[] = dependencyFields.map((field) => manifest[field]);\n const workspaces = manifest[\"workspaces\"];\n for (const owner of [manifest, record(workspaces) ? workspaces : {}]) {\n if (owner !== manifest) tables.push(owner[\"catalog\"]);\n const catalogs = owner[\"catalogs\"];\n if (record(catalogs)) tables.push(...Object.values(catalogs));\n }\n return tables.flatMap((table) => (record(table) ? Object.keys(table) : []));\n};\n\nconst shellWords = (command: string) =>\n command\n .split(/[\\s;&|()<>`]+/u)\n .map((word) => word.replace(/^[\"']+|[\"']+$/gu, \"\"))\n .filter((word) => word !== \"\");\n\n/** Over-approximate: any formatter executable named as a word is an invocation. */\nconst invokesFormatter = (command: string) => {\n const words = shellWords(command);\n return words.some((word, index) => {\n const name = path.posix.basename(word);\n if (name === \"oxfmt\" || name === \"prettier\" || name === \"dprint\")\n return true;\n return (\n name === \"biome\" &&\n [\"format\", \"check\", \"ci\"].includes(words.at(index + 1) ?? \"\")\n );\n });\n};\n\nconst lineOf = (text: string, needle: string) =>\n Math.max(\n 1,\n text.split(/\\r?\\n/u).findIndex((line) => line.includes(needle)) + 1,\n );\n\n/** Collect every `run` string of a workflow, composite action or hook config. */\nconst runValues = (value: unknown): string[] => {\n if (Array.isArray(value)) return value.flatMap(runValues);\n if (!record(value)) return [];\n return Object.entries(value).flatMap(([key, entry]) =>\n key === \"run\" && typeof entry === \"string\" ? [entry] : runValues(entry),\n );\n};\n\nconst commandLines = (commands: readonly string[]) =>\n commands.flatMap((command) =>\n command\n .replace(/\\\\\\r?\\n/gu, \" \")\n .split(/\\r?\\n|&&|;/u)\n .map((line) => line.trim()),\n );\n\nconst isBunFormat = (line: string, flag: \"--check\" | \"--staged\") => {\n const words = shellWords(line);\n // Only flags may follow: a path operand narrows the check below the repository.\n return (\n words[0] === \"bun\" &&\n words[1] === \"fmt\" &&\n words.slice(2).includes(flag) &&\n words.slice(2).every((word) => word.startsWith(\"-\"))\n );\n};\n\n/** Package directories that the root workspaces patterns select. */\nconst workspacePackageRoots = (files: Record<string, string>) => {\n let manifest: unknown;\n try {\n manifest = JSON.parse(files[\"package.json\"] ?? \"\");\n } catch {\n return [];\n }\n if (!record(manifest)) return [];\n const declared = manifest[\"workspaces\"];\n // Bun accepts the array form and the { packages } object form.\n const patterns = record(declared) ? declared[\"packages\"] : declared;\n return Object.keys(files)\n .filter(\n (file) =>\n file.endsWith(\"/package.json\") &&\n workspaceContains({\n directory: \".\",\n file,\n patterns,\n rootMembership: \"patterns\",\n }),\n )\n .map((file) => path.posix.dirname(file));\n};\n\n// Representative package files: the manifest and common source layouts and\n// extensions. An ignore that matches any of them drops package sources.\nconst packageSourceProbes = [\n \"package.json\",\n \"index.ts\",\n \"index.js\",\n \"src/index.ts\",\n \"src/index.tsx\",\n \"src/index.js\",\n \"src/index.mjs\",\n \"src/main.ts\",\n \"src/nested/module.ts\",\n \"src/nested/component.tsx\",\n \"lib/index.ts\",\n \"lib/index.js\",\n] as const;\n\n/**\n * Ignore-file matching at one path level: a trailing slash limits a pattern to\n * directories, and a leading or inner slash anchors it at the root; otherwise\n * it matches at any depth.\n */\nconst matchesLevel = (pattern: string, level: string, directory: boolean) => {\n if (pattern.endsWith(\"/\") && !directory) return false;\n const anchored = pattern.replace(/\\/+$/u, \"\").includes(\"/\");\n const body = pattern.replace(/^\\/+|\\/+$/gu, \"\");\n // An empty pattern (\"/\") matches nothing.\n if (body === \"\") return false;\n const globs = anchored ? [body] : [body, `**/${body}`];\n return globs.some((glob) => picomatch.isMatch(level, glob, { dot: true }));\n};\n\n/** The patterns that match a path or one of its directories. */\nconst ignoringPatterns = (patterns: readonly string[], file: string) => {\n const parts = file.split(\"/\");\n return patterns.filter((pattern) =>\n parts.some((_, index) =>\n matchesLevel(\n pattern,\n parts.slice(0, index + 1).join(\"/\"),\n index < parts.length - 1,\n ),\n ),\n );\n};\n\nconst checkFormatConfig = (\n bunfig: string,\n policy: FormatterPolicy,\n packageRoots: readonly string[],\n): string[] => {\n let parsed: Record<string, unknown>;\n try {\n parsed = parseToml(bunfig);\n } catch {\n return [\"bunfig.toml must be valid TOML\"];\n }\n const fmt = parsed[\"fmt\"];\n if (!record(fmt))\n return [\n `bunfig.toml requires a [fmt] table: bun fmt reads its configuration only from there; start from:\\n${sharedFormatTables(policy)}`,\n ];\n const errors: string[] = [];\n for (const key of Object.keys(fmt))\n if (\n !Object.hasOwn(policy.style, key) &&\n !repositoryFormatKeys.some((owned) => owned === key)\n )\n errors.push(\n `bunfig.toml [fmt] ${key} is not part of the shared style; every repository formats alike`,\n );\n const ignored = Array.isArray(fmt[\"ignorePatterns\"])\n ? fmt[\"ignorePatterns\"]\n : [];\n const missing = policy.ignorePatterns.filter(\n (pattern) => !ignored.includes(pattern),\n );\n if (missing.length > 0)\n errors.push(\n `bunfig.toml [fmt] ignorePatterns must include the shared generated files: ${missing.join(\", \")}`,\n );\n // Ignores are for generated or vendored paths; one that covers a workspace\n // package silently drops its sources from bun fmt --check. Negations are not\n // accepted, so every listed pattern only ever removes files.\n const patterns = ignored.filter(\n (pattern): pattern is string => typeof pattern === \"string\",\n );\n for (const pattern of patterns)\n if (pattern.startsWith(\"!\"))\n errors.push(\n `bunfig.toml [fmt] ignorePatterns entry ${pattern} re-includes files; list only generated or vendored paths`,\n );\n const positives = patterns.filter((pattern) => !pattern.startsWith(\"!\"));\n const covered = new Map<string, string[]>();\n for (const root of packageRoots)\n for (const probe of packageSourceProbes) {\n for (const pattern of ignoringPatterns(positives, `${root}/${probe}`)) {\n if (policy.ignorePatterns.includes(pattern)) continue;\n const roots = covered.get(pattern) ?? [];\n if (!roots.includes(root)) roots.push(root);\n covered.set(pattern, roots);\n }\n }\n for (const pattern of patterns) {\n const roots = covered.get(pattern);\n if (roots !== undefined)\n errors.push(\n `bunfig.toml [fmt] ignorePatterns entry ${pattern} covers workspace packages (${roots.join(\", \")}); ignore only their generated or vendored paths`,\n );\n }\n for (const [key, value] of Object.entries(policy.style))\n if (stableJson(fmt[key]) !== stableJson(value))\n errors.push(\n `bunfig.toml [fmt] ${key} must equal the shared style:\\n${sharedFormatTables(policy)}`,\n );\n return errors;\n};\n\ntype CheckFormatterOptions = {\n files: Record<string, string>;\n policy: FormatterPolicy;\n usesBun: boolean;\n};\n\n/** bun fmt is the only formatter: one config table, staged hooks and a full CI check. */\nexport const checkFormatter = ({\n files,\n policy,\n usesBun,\n}: CheckFormatterOptions): Diagnostic[] => {\n const diagnostics: Diagnostic[] = [];\n const add = (file: string, line: number, message: string) =>\n diagnostics.push({ rule: formatterRule, path: file, line, message });\n const workflowCommands: string[] = [];\n for (const [file, text] of Object.entries(files)) {\n const name = path.posix.basename(file);\n if (isFormatterConfigPath(file))\n add(\n file,\n 1,\n \"formatter configuration belongs in bunfig.toml [fmt]; remove this file\",\n );\n if (name === \"package.json\") {\n let manifest: unknown;\n try {\n manifest = JSON.parse(text);\n } catch {\n // Package diagnostics already reject malformed manifests.\n continue;\n }\n if (!record(manifest)) continue;\n for (const dependency of declaredPackages(manifest))\n if (formatterPackage(dependency))\n add(\n file,\n lineOf(text, JSON.stringify(dependency)),\n `${dependency} is not allowed: bun fmt is the only formatter`,\n );\n if (manifest[\"prettier\"] !== undefined)\n add(\n file,\n lineOf(text, '\"prettier\"'),\n \"package.json prettier configuration belongs in bunfig.toml [fmt]\",\n );\n const scripts = manifest[\"scripts\"];\n if (record(scripts))\n for (const [script, command] of Object.entries(scripts)) {\n if (script === \"fmt\")\n add(\n file,\n lineOf(text, '\"fmt\"'),\n \"a package script named fmt shadows bun fmt; remove it\",\n );\n if (typeof command === \"string\" && invokesFormatter(command))\n add(\n file,\n lineOf(text, JSON.stringify(script)),\n `script ${script} runs another formatter; use bun fmt`,\n );\n }\n continue;\n }\n if (file === \".changeset/config.json\") {\n try {\n const config: unknown = JSON.parse(text);\n if (record(config) && config[\"format\"] !== false)\n add(\n file,\n lineOf(text, '\"format\"'),\n \"changesets must not run a formatter (format: false); format releases with bun fmt\",\n );\n } catch {\n add(file, 1, \"changeset configuration must be valid JSON\");\n }\n continue;\n }\n const automation = githubAutomationFileKind(file);\n if (automation !== undefined || isLefthookConfigPath(file)) {\n const document = parseDocument(text);\n if (document.errors.length > 0) continue;\n const parsed: unknown = document.toJS();\n const commands = runValues(parsed);\n for (const command of commands)\n if (invokesFormatter(command))\n add(\n file,\n lineOf(text, command.split(/\\r?\\n/u)[0] ?? command),\n \"command runs another formatter; use bun fmt\",\n );\n if (automation === \"workflow\") workflowCommands.push(...commands);\n if (isLefthookConfigPath(file) && usesBun) {\n const preCommit = record(parsed) ? parsed[\"pre-commit\"] : undefined;\n if (\n !commandLines(runValues(preCommit)).some((line) =>\n isBunFormat(line, \"--staged\"),\n )\n )\n add(\n file,\n lineOf(text, \"pre-commit\"),\n \"lefthook pre-commit must run bun fmt --staged\",\n );\n }\n continue;\n }\n if (\n text !== \"\" &&\n (isDockerDefinitionPath(file) || isShellScript(file, text))\n )\n for (const [index, line] of text.split(/\\r?\\n/u).entries())\n if (!line.trimStart().startsWith(\"#\") && invokesFormatter(line))\n add(file, index + 1, \"command runs another formatter; use bun fmt\");\n }\n if (!usesBun) return diagnostics;\n const bunfig = files[\"bunfig.toml\"];\n if (bunfig !== undefined)\n for (const message of checkFormatConfig(\n bunfig,\n policy,\n workspacePackageRoots(files),\n ))\n add(\"bunfig.toml\", lineOf(bunfig, \"[fmt\"), message);\n const hasWorkflows = Object.keys(files).some(\n (file) => githubAutomationFileKind(file) === \"workflow\",\n );\n if (\n hasWorkflows &&\n !commandLines(workflowCommands).some((line) => isBunFormat(line, \"--check\"))\n )\n add(\n \".github/workflows\",\n 1,\n \"a workflow must run bun fmt --check over the whole repository\",\n );\n return diagnostics;\n};\n","import { valid } from \"semver\";\n\nimport { parseFormatterPolicy } from \"./toolchain-formatter\";\nimport { nodePolicyValid } from \"./toolchain-node\";\n\nexport const packagePinKeys = [\n \"oxlint\",\n \"oxlint-tsgolint\",\n \"@oxlint/plugins\",\n \"@stll/oxlint-plugin\",\n \"lefthook\",\n] as const;\n\nexport const valkeyArchitectures = [\"amd64\", \"arm64\"] as const;\nexport const valkeyArtifactPackages = {\n server: \"valkey-server\",\n tools: \"valkey-tools\",\n} as const;\n\nconst record = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nconst artifactRecord = (value: unknown, keys: readonly string[]) => {\n if (\n !record(value) ||\n Object.keys(value).some((key) => !keys.includes(key)) ||\n keys.some((key) => !Object.hasOwn(value, key))\n )\n throw new Error(\n \"valkeyArtifacts requires complete, closed artifact objects\",\n );\n return value;\n};\n\nconst parseValkeyArtifacts = (input: unknown, version: string) => {\n const architectures = artifactRecord(input, valkeyArchitectures);\n const line = version.split(\".\").slice(0, 2).join(\".\");\n const parseArchitecture = (\n architecture: (typeof valkeyArchitectures)[number],\n ) => {\n const packages = artifactRecord(\n architectures[architecture],\n Object.keys(valkeyArtifactPackages),\n );\n const parseArtifact = (kind: keyof typeof valkeyArtifactPackages) => {\n const artifact = artifactRecord(packages[kind], [\"url\", \"sha256\"]);\n const url = artifact[\"url\"];\n const sha256 = artifact[\"sha256\"];\n const expected = `https://download.valkey.io/packaging/valkey-${line}/deb/ubuntu2404/${architecture}/${valkeyArtifactPackages[kind]}_${version}-1.noble_${architecture}.deb`;\n if (typeof url !== \"string\" || url !== expected)\n throw new Error(\n \"valkeyArtifacts URL must select the exact official versioned Ubuntu artifact\",\n );\n if (typeof sha256 !== \"string\" || !/^[a-f0-9]{64}$/.test(sha256))\n throw new Error(\"valkeyArtifacts requires a lowercase SHA256 pin\");\n return { url, sha256 };\n };\n return {\n server: parseArtifact(\"server\"),\n tools: parseArtifact(\"tools\"),\n } satisfies Record<\n keyof typeof valkeyArtifactPackages,\n ReturnType<typeof parseArtifact>\n >;\n };\n return {\n amd64: parseArchitecture(\"amd64\"),\n arm64: parseArchitecture(\"arm64\"),\n } satisfies Record<\n (typeof valkeyArchitectures)[number],\n ReturnType<typeof parseArchitecture>\n >;\n};\n\n/** Reject unsupported or incomplete installed policies before inspecting a consumer. */\nexport const parseToolchainPolicy = (input: unknown) => {\n if (!record(input) || input[\"schemaVersion\"] !== 1)\n throw new Error(\"toolchain.json must use schemaVersion 1\");\n const string = (object: Record<string, unknown>, key: string) => {\n const value = object[key];\n if (typeof value !== \"string\" || value.trim() === \"\")\n throw new Error(`toolchain.json requires a nonempty ${key}`);\n return value;\n };\n const packages: Record<string, string> = {};\n for (const key of packagePinKeys) packages[key] = string(input, key);\n const bun = string(input, \"bun\");\n const typescript = string(input, \"typescript\");\n const node = string(input, \"node\");\n const consumerNode = string(input, \"consumerNode\");\n const consumerNpm = string(input, \"consumerNpm\");\n const consumerPnpm = string(input, \"consumerPnpm\");\n const consumerTypescript = string(input, \"consumerTypescript\");\n const python = string(input, \"python\");\n const postgres = string(input, \"postgres\");\n const valkey = string(input, \"valkey\");\n const rust = string(input, \"rust\");\n for (const [name, value] of Object.entries({\n ...packages,\n bun,\n typescript,\n consumerNpm,\n consumerPnpm,\n consumerTypescript,\n }))\n if (valid(value) !== value)\n throw new Error(`toolchain.json ${name} must be an exact release`);\n if (!/^[1-9]\\d*$/.test(postgres) || !Number.isSafeInteger(Number(postgres)))\n throw new Error(\"PostgreSQL must be a canonical positive major\");\n if (valid(valkey) !== valkey || !/^\\d+\\.\\d+\\.\\d+$/.test(valkey))\n throw new Error(\"Valkey must be an exact stable release\");\n const valkeyArtifacts = parseValkeyArtifacts(\n input[\"valkeyArtifacts\"],\n valkey,\n );\n if (!nodePolicyValid(node))\n throw new Error(\"Node must be a canonical major N.x series\");\n if (\n valid(consumerNode) !== consumerNode ||\n !consumerNode.startsWith(\"22.\") ||\n consumerNode.includes(\"-\") ||\n consumerNode.includes(\"+\")\n )\n throw new Error(\"consumerNode must be an exact stable Node 22 release\");\n if (!/^\\d+\\.\\d+(?:\\.\\d+)?$/.test(python))\n throw new Error(\"Python must be an exact minor or patch release\");\n if (!/^\\d+\\.\\d+\\.\\d+$/.test(rust))\n throw new Error(\"Rust must be an exact stable release\");\n if (\n !consumerTypescript.startsWith(\"6.\") ||\n consumerTypescript.includes(\"-\") ||\n consumerTypescript.includes(\"+\")\n )\n throw new Error(\n \"consumerTypescript must be an exact stable TypeScript 6 release\",\n );\n const compatibility = input[\"typescript6Compatibility\"];\n if (!record(compatibility))\n throw new Error(\"missing TypeScript compatibility policy\");\n const version = string(compatibility, \"version\");\n const packageAlias = string(compatibility, \"packageAlias\");\n if (valid(version) !== version)\n throw new Error(\"TypeScript compatibility must be an exact release\");\n const layouts = input[\"typescriptInstallLayouts\"];\n if (!Array.isArray(layouts) || layouts.length === 0)\n throw new Error(\"missing TypeScript install layouts\");\n const typescriptInstallLayouts = layouts.map((layout: unknown) => {\n if (!record(layout)) throw new Error(\"invalid TypeScript install layout\");\n const compilerPackage = string(layout, \"compilerPackage\");\n const compilerSpecifier = string(layout, \"compilerSpecifier\");\n const typecheckCommand = string(layout, \"typecheckCommand\");\n switch (layout[\"type\"]) {\n case \"direct\":\n if (\n compilerSpecifier !== typescript ||\n compilerPackage !== \"typescript\"\n )\n throw new Error(\n \"direct TypeScript layout differs from shared version\",\n );\n return {\n type: \"direct\",\n compilerPackage,\n compilerSpecifier,\n typecheckCommand,\n } as const;\n case \"split-compatibility\": {\n const compatibilityPackage = string(layout, \"compatibilityPackage\");\n const compatibilitySpecifier = string(layout, \"compatibilitySpecifier\");\n if (\n compilerSpecifier !== `npm:typescript@${typescript}` ||\n compatibilitySpecifier !== version\n )\n throw new Error(\n \"split TypeScript layout differs from shared versions\",\n );\n return {\n type: \"split-compatibility\",\n compilerPackage,\n compilerSpecifier,\n compatibilityPackage,\n compatibilitySpecifier,\n typecheckCommand,\n } as const;\n }\n default:\n throw new Error(\"unsupported TypeScript install layout\");\n }\n });\n const actionsInput = input[\"actions\"];\n if (!record(actionsInput) || Object.keys(actionsInput).length === 0)\n throw new Error(\"missing approved actions\");\n const actions: Record<string, { sha: string; version: string }> = {};\n for (const [name, action] of Object.entries(actionsInput)) {\n if (!record(action)) throw new Error(`invalid action policy: ${name}`);\n const sha = string(action, \"sha\");\n const actionVersion = string(action, \"version\");\n if (!/^[a-f0-9]{40}$/.test(sha) || !/^v\\d+(?:\\.\\d+)*$/.test(actionVersion))\n throw new Error(`invalid action SHA/version: ${name}`);\n actions[name] = { sha, version: actionVersion };\n }\n const dependabotInput = input[\"dependabot\"];\n if (\n !record(dependabotInput) ||\n !record(dependabotInput[\"schedule\"]) ||\n !record(dependabotInput[\"cooldown\"]) ||\n !record(dependabotInput[\"groups\"])\n )\n throw new Error(\"missing Dependabot policy\");\n const scheduleInput = dependabotInput[\"schedule\"];\n const schedule = {\n interval: string(scheduleInput, \"interval\"),\n day: string(scheduleInput, \"day\"),\n time: string(scheduleInput, \"time\"),\n timezone: string(scheduleInput, \"timezone\"),\n };\n const defaultDays = dependabotInput[\"cooldown\"][\"defaultDays\"];\n if (\n typeof defaultDays !== \"number\" ||\n !Number.isInteger(defaultDays) ||\n defaultDays < 5\n )\n throw new Error(\"Dependabot cooldown must be at least five days\");\n const strings = (value: unknown): string[] => {\n if (\n !Array.isArray(value) ||\n !value.every((entry: unknown) => typeof entry === \"string\")\n )\n throw new Error(\"Dependabot group values must be string arrays\");\n return value;\n };\n // First-party reusable workflows move by commit, without a semver update\n // type, and must land together; they precede the shared semver groups.\n const actionGroupsInput = dependabotInput[\"actionGroups\"];\n if (!record(actionGroupsInput))\n throw new Error(\"missing Dependabot action groups\");\n const actionGroups: Record<string, { patterns: string[] }> = {};\n for (const [name, group] of Object.entries(actionGroupsInput)) {\n if (!record(group) || Object.keys(group).some((key) => key !== \"patterns\"))\n throw new Error(`invalid Dependabot action group: ${name}`);\n actionGroups[name] = { patterns: strings(group[\"patterns\"]) };\n }\n const groups: Record<string, { patterns: string[]; updateTypes: string[] }> =\n {};\n for (const [name, group] of Object.entries(dependabotInput[\"groups\"])) {\n if (!record(group)) throw new Error(`invalid Dependabot group: ${name}`);\n groups[name] = {\n patterns: strings(group[\"patterns\"]),\n updateTypes: strings(group[\"updateTypes\"]),\n };\n }\n return {\n bun,\n formatter: parseFormatterPolicy(input[\"formatter\"]),\n typescript,\n node,\n postgres,\n valkey,\n valkeyArtifacts,\n consumerNode,\n consumerNpm,\n consumerPnpm,\n consumerTypescript,\n python,\n rust,\n packages,\n actions,\n typescriptInstallLayouts,\n typescript6Compatibility: { version, packageAlias },\n dependabot: {\n schedule,\n cooldown: { defaultDays },\n actionGroups,\n groups,\n ignoredPackages: [\n ...new Set([\n ...Object.keys(packages),\n // The consumer package managers move only with a reviewed\n // consumerNpm or consumerPnpm change.\n \"npm\",\n \"pnpm\",\n ...typescriptInstallLayouts.flatMap((layout) =>\n layout.type === \"direct\"\n ? [layout.compilerPackage]\n : [layout.compilerPackage, layout.compatibilityPackage],\n ),\n packageAlias,\n \"bun-types\",\n ]),\n ],\n ignoredActions: Object.keys(actions),\n ignoredImages: [\"node\", \"python\", \"oven/bun\"],\n },\n };\n};\n"],"mappings":";;;;;;;;;;AAcA,MAAa,gBAAgB;;AAmB7B,MAAa,uBAAuB,CAClC,kBACA,iBACF;AAEA,MAAMA,YAAU,UACd,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;;AAGrE,MAAa,wBAAwB,UAAoC;CACvE,IACE,CAACA,SAAO,KAAK,KACb,OAAO,KAAK,KAAK,CAAC,CAAC,MAChB,QAAQ,QAAQ,aAAa,QAAQ,WAAW,QAAQ,gBAC3D,GAEA,MAAM,IAAI,MACR,yEACF;CACF,IAAI,MAAM,eAAe,WACvB,MAAM,IAAI,MAAM,kDAAkD;CACpE,MAAM,QAAQ,MAAM;CACpB,IAAI,CAACA,SAAO,KAAK,KAAK,OAAO,KAAK,KAAK,CAAC,CAAC,WAAW,GAClD,MAAM,IAAI,MAAM,yDAAyD;CAC3E,KAAK,MAAM,OAAO,OAAO,KAAK,KAAK,GACjC,IAAI,qBAAqB,MAAM,UAAU,UAAU,GAAG,GACpD,MAAM,IAAI,MACR,gEAAgE,KAClE;CACJ,MAAM,iBAAiB,MAAM;CAC7B,IACE,CAAC,MAAM,QAAQ,cAAc,KAC7B,CAAC,eAAe,OACb,YACC,OAAO,YAAY,YAAY,YAAY,EAC/C,GAEA,MAAM,IAAI,MACR,kEACF;CACF,OAAO;EAAE,SAAS;EAAW;EAAO;CAAe;AACrD;AAEA,MAAM,aAAa,UAA2B;CAC5C,IAAI,MAAM,QAAQ,KAAK,GAAG,OAAO,IAAI,MAAM,IAAI,SAAS,CAAC,CAAC,KAAK,IAAI,EAAE;CACrE,IAAIA,SAAO,KAAK,GACd,OAAO,KAAK,OAAO,QAAQ,KAAK,CAAC,CAC9B,KAAK,CAAC,KAAK,WAAW,GAAG,IAAI,KAAK,UAAU,KAAK,GAAG,CAAC,CACrD,KAAK,IAAI,EAAE;CAChB,OAAO,KAAK,UAAU,KAAK;AAC7B;AAEA,MAAM,aAAa,YACjB,QAAQ,KAAK,CAAC,KAAK,WAAW,GAAG,IAAI,KAAK,UAAU,KAAK,EAAE,GAAG,CAAC,CAAC,KAAK,EAAE;;AAGzE,MAAa,sBAAsB,WAA4B;CAC7D,MAAM,UAAU,OAAO,QAAQ,OAAO,KAAK;CAC3C,IAAI,SAAS,UAAU,UACrB,QAAQ,QAAQ,GAAG,WAAW,CAACA,SAAO,KAAK,CAAC,CAC9C,EAAE,mBAAmB,UAAU,OAAO,cAAc,EAAE;CACtD,KAAK,MAAM,CAAC,MAAM,UAAU,SAC1B,IAAIA,SAAO,KAAK,GACd,UAAU,UAAU,KAAK,KAAK,UAAU,OAAO,QAAQ,KAAK,CAAC;CACjE,OAAO;AACT;AAEA,MAAM,cAAc,UAClB,KAAK,UAAU,QAAQ,MAAM,UAC3BA,SAAO,KAAK,IACR,OAAO,YACL,OAAO,QAAQ,KAAK,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,WACvC,KAAK,cAAc,KAAK,CAC1B,CACF,IACA,KACN;AAGF,MAAM,oBAAoB,SACxB,SAAS,WACT,SAAS,cACT,SAAS,YACT,SAAS,oBACT,KAAK,WAAW,UAAU,KAC1B,iCAAiC,KAAK,IAAI;AAE5C,MAAM,mBAAmB;CACvB;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,MAAM,oBAAoB,aAAsC;CAC9D,MAAM,SAAoB,iBAAiB,KAAK,UAAU,SAAS,MAAM;CACzE,MAAM,aAAa,SAAS;CAC5B,KAAK,MAAM,SAAS,CAAC,UAAUA,SAAO,UAAU,IAAI,aAAa,CAAC,CAAC,GAAG;EACpE,IAAI,UAAU,UAAU,OAAO,KAAK,MAAM,UAAU;EACpD,MAAM,WAAW,MAAM;EACvB,IAAIA,SAAO,QAAQ,GAAG,OAAO,KAAK,GAAG,OAAO,OAAO,QAAQ,CAAC;CAC9D;CACA,OAAO,OAAO,SAAS,UAAWA,SAAO,KAAK,IAAI,OAAO,KAAK,KAAK,IAAI,CAAC,CAAE;AAC5E;AAEA,MAAM,cAAc,YAClB,QACG,MAAM,gBAAgB,CAAC,CACvB,KAAK,SAAS,KAAK,QAAQ,mBAAmB,EAAE,CAAC,CAAC,CAClD,QAAQ,SAAS,SAAS,EAAE;;AAGjC,MAAM,oBAAoB,YAAoB;CAC5C,MAAM,QAAQ,WAAW,OAAO;CAChC,OAAO,MAAM,MAAM,MAAM,UAAU;EACjC,MAAM,OAAOC,UAAAA,QAAK,MAAM,SAAS,IAAI;EACrC,IAAI,SAAS,WAAW,SAAS,cAAc,SAAS,UACtD,OAAO;EACT,OACE,SAAS,WACT;GAAC;GAAU;GAAS;EAAI,CAAC,CAAC,SAAS,MAAM,GAAG,QAAQ,CAAC,KAAK,EAAE;CAEhE,CAAC;AACH;AAEA,MAAM,UAAU,MAAc,WAC5B,KAAK,IACH,GACA,KAAK,MAAM,QAAQ,CAAC,CAAC,WAAW,SAAS,KAAK,SAAS,MAAM,CAAC,IAAI,CACpE;;AAGF,MAAM,aAAa,UAA6B;CAC9C,IAAI,MAAM,QAAQ,KAAK,GAAG,OAAO,MAAM,QAAQ,SAAS;CACxD,IAAI,CAACD,SAAO,KAAK,GAAG,OAAO,CAAC;CAC5B,OAAO,OAAO,QAAQ,KAAK,CAAC,CAAC,SAAS,CAAC,KAAK,WAC1C,QAAQ,SAAS,OAAO,UAAU,WAAW,CAAC,KAAK,IAAI,UAAU,KAAK,CACxE;AACF;AAEA,MAAM,gBAAgB,aACpB,SAAS,SAAS,YAChB,QACG,QAAQ,aAAa,GAAG,CAAC,CACzB,MAAM,aAAa,CAAC,CACpB,KAAK,SAAS,KAAK,KAAK,CAAC,CAC9B;AAEF,MAAM,eAAe,MAAc,SAAiC;CAClE,MAAM,QAAQ,WAAW,IAAI;CAE7B,OACE,MAAM,OAAO,SACb,MAAM,OAAO,SACb,MAAM,MAAM,CAAC,CAAC,CAAC,SAAS,IAAI,KAC5B,MAAM,MAAM,CAAC,CAAC,CAAC,OAAO,SAAS,KAAK,WAAW,GAAG,CAAC;AAEvD;;AAGA,MAAM,yBAAyB,UAAkC;CAC/D,IAAI;CACJ,IAAI;EACF,WAAW,KAAK,MAAM,MAAM,mBAAmB,EAAE;CACnD,QAAQ;EACN,OAAO,CAAC;CACV;CACA,IAAI,CAACA,SAAO,QAAQ,GAAG,OAAO,CAAC;CAC/B,MAAM,WAAW,SAAS;CAE1B,MAAM,WAAWA,SAAO,QAAQ,IAAI,SAAS,cAAc;CAC3D,OAAO,OAAO,KAAK,KAAK,CAAC,CACtB,QACE,SACC,KAAK,SAAS,eAAe,KAC7BE,yBAAAA,kBAAkB;EAChB,WAAW;EACX;EACA;EACA,gBAAgB;CAClB,CAAC,CACL,CAAC,CACA,KAAK,SAASD,UAAAA,QAAK,MAAM,QAAQ,IAAI,CAAC;AAC3C;AAIA,MAAM,sBAAsB;CAC1B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;;;;;;AAOA,MAAM,gBAAgB,SAAiB,OAAe,cAAuB;CAC3E,IAAI,QAAQ,SAAS,GAAG,KAAK,CAAC,WAAW,OAAO;CAChD,MAAM,WAAW,QAAQ,QAAQ,SAAS,EAAE,CAAC,CAAC,SAAS,GAAG;CAC1D,MAAM,OAAO,QAAQ,QAAQ,eAAe,EAAE;CAE9C,IAAI,SAAS,IAAI,OAAO;CAExB,QADc,WAAW,CAAC,IAAI,IAAI,CAAC,MAAM,MAAM,MAAM,EAAA,CACxC,MAAM,SAAS,UAAA,QAAU,QAAQ,OAAO,MAAM,EAAE,KAAK,KAAK,CAAC,CAAC;AAC3E;;AAGA,MAAM,oBAAoB,UAA6B,SAAiB;CACtE,MAAM,QAAQ,KAAK,MAAM,GAAG;CAC5B,OAAO,SAAS,QAAQ,YACtB,MAAM,MAAM,GAAG,UACb,aACE,SACA,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,KAAK,GAAG,GAClC,QAAQ,MAAM,SAAS,CACzB,CACF,CACF;AACF;AAEA,MAAM,qBACJ,QACA,QACA,iBACa;CACb,IAAI;CACJ,IAAI;EACF,UAAA,GAASE,UAAAA,MAAAA,CAAU,MAAM;CAC3B,QAAQ;EACN,OAAO,CAAC,gCAAgC;CAC1C;CACA,MAAM,MAAM,OAAO;CACnB,IAAI,CAACH,SAAO,GAAG,GACb,OAAO,CACL,qGAAqG,mBAAmB,MAAM,GAChI;CACF,MAAM,SAAmB,CAAC;CAC1B,KAAK,MAAM,OAAO,OAAO,KAAK,GAAG,GAC/B,IACE,CAAC,OAAO,OAAO,OAAO,OAAO,GAAG,KAChC,CAAC,qBAAqB,MAAM,UAAU,UAAU,GAAG,GAEnD,OAAO,KACL,qBAAqB,IAAI,iEAC3B;CACJ,MAAM,UAAU,MAAM,QAAQ,IAAI,iBAAiB,IAC/C,IAAI,oBACJ,CAAC;CACL,MAAM,UAAU,OAAO,eAAe,QACnC,YAAY,CAAC,QAAQ,SAAS,OAAO,CACxC;CACA,IAAI,QAAQ,SAAS,GACnB,OAAO,KACL,6EAA6E,QAAQ,KAAK,IAAI,GAChG;CAIF,MAAM,WAAW,QAAQ,QACtB,YAA+B,OAAO,YAAY,QACrD;CACA,KAAK,MAAM,WAAW,UACpB,IAAI,QAAQ,WAAW,GAAG,GACxB,OAAO,KACL,0CAA0C,QAAQ,0DACpD;CACJ,MAAM,YAAY,SAAS,QAAQ,YAAY,CAAC,QAAQ,WAAW,GAAG,CAAC;CACvE,MAAM,0BAAU,IAAI,IAAsB;CAC1C,KAAK,MAAM,QAAQ,cACjB,KAAK,MAAM,SAAS,qBAClB,KAAK,MAAM,WAAW,iBAAiB,WAAW,GAAG,KAAK,GAAG,OAAO,GAAG;EACrE,IAAI,OAAO,eAAe,SAAS,OAAO,GAAG;EAC7C,MAAM,QAAQ,QAAQ,IAAI,OAAO,KAAK,CAAC;EACvC,IAAI,CAAC,MAAM,SAAS,IAAI,GAAG,MAAM,KAAK,IAAI;EAC1C,QAAQ,IAAI,SAAS,KAAK;CAC5B;CAEJ,KAAK,MAAM,WAAW,UAAU;EAC9B,MAAM,QAAQ,QAAQ,IAAI,OAAO;EACjC,IAAI,UAAU,KAAA,GACZ,OAAO,KACL,0CAA0C,QAAQ,8BAA8B,MAAM,KAAK,IAAI,EAAE,iDACnG;CACJ;CACA,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,OAAO,KAAK,GACpD,IAAI,WAAW,IAAI,IAAI,MAAM,WAAW,KAAK,GAC3C,OAAO,KACL,qBAAqB,IAAI,iCAAiC,mBAAmB,MAAM,GACrF;CACJ,OAAO;AACT;;AASA,MAAa,kBAAkB,EAC7B,OACA,QACA,cACyC;CACzC,MAAM,cAA4B,CAAC;CACnC,MAAM,OAAO,MAAc,MAAc,YACvC,YAAY,KAAK;EAAE,MAAM;EAAe,MAAM;EAAM;EAAM;CAAQ,CAAC;CACrE,MAAM,mBAA6B,CAAC;CACpC,KAAK,MAAM,CAAC,MAAM,SAAS,OAAO,QAAQ,KAAK,GAAG;EAChD,MAAM,OAAOC,UAAAA,QAAK,MAAM,SAAS,IAAI;EACrC,IAAIG,yBAAAA,sBAAsB,IAAI,GAC5B,IACE,MACA,GACA,wEACF;EACF,IAAI,SAAS,gBAAgB;GAC3B,IAAI;GACJ,IAAI;IACF,WAAW,KAAK,MAAM,IAAI;GAC5B,QAAQ;IAEN;GACF;GACA,IAAI,CAACJ,SAAO,QAAQ,GAAG;GACvB,KAAK,MAAM,cAAc,iBAAiB,QAAQ,GAChD,IAAI,iBAAiB,UAAU,GAC7B,IACE,MACA,OAAO,MAAM,KAAK,UAAU,UAAU,CAAC,GACvC,GAAG,WAAW,+CAChB;GACJ,IAAI,SAAS,gBAAgB,KAAA,GAC3B,IACE,MACA,OAAO,MAAM,cAAY,GACzB,kEACF;GACF,MAAM,UAAU,SAAS;GACzB,IAAIA,SAAO,OAAO,GAChB,KAAK,MAAM,CAAC,QAAQ,YAAY,OAAO,QAAQ,OAAO,GAAG;IACvD,IAAI,WAAW,OACb,IACE,MACA,OAAO,MAAM,SAAO,GACpB,uDACF;IACF,IAAI,OAAO,YAAY,YAAY,iBAAiB,OAAO,GACzD,IACE,MACA,OAAO,MAAM,KAAK,UAAU,MAAM,CAAC,GACnC,UAAU,OAAO,qCACnB;GACJ;GACF;EACF;EACA,IAAI,SAAS,0BAA0B;GACrC,IAAI;IACF,MAAM,SAAkB,KAAK,MAAM,IAAI;IACvC,IAAIA,SAAO,MAAM,KAAK,OAAO,cAAc,OACzC,IACE,MACA,OAAO,MAAM,YAAU,GACvB,mFACF;GACJ,QAAQ;IACN,IAAI,MAAM,GAAG,4CAA4C;GAC3D;GACA;EACF;EACA,MAAM,aAAaK,yBAAAA,yBAAyB,IAAI;EAChD,IAAI,eAAe,KAAA,KAAaC,yBAAAA,qBAAqB,IAAI,GAAG;GAC1D,MAAM,YAAA,GAAWC,KAAAA,cAAAA,CAAc,IAAI;GACnC,IAAI,SAAS,OAAO,SAAS,GAAG;GAChC,MAAM,SAAkB,SAAS,KAAK;GACtC,MAAM,WAAW,UAAU,MAAM;GACjC,KAAK,MAAM,WAAW,UACpB,IAAI,iBAAiB,OAAO,GAC1B,IACE,MACA,OAAO,MAAM,QAAQ,MAAM,QAAQ,CAAC,CAAC,MAAM,OAAO,GAClD,6CACF;GACJ,IAAI,eAAe,YAAY,iBAAiB,KAAK,GAAG,QAAQ;GAChE,IAAID,yBAAAA,qBAAqB,IAAI,KAAK,SAAS;IACzC,MAAM,YAAYN,SAAO,MAAM,IAAI,OAAO,gBAAgB,KAAA;IAC1D,IACE,CAAC,aAAa,UAAU,SAAS,CAAC,CAAC,CAAC,MAAM,SACxC,YAAY,MAAM,UAAU,CAC9B,GAEA,IACE,MACA,OAAO,MAAM,YAAY,GACzB,+CACF;GACJ;GACA;EACF;EACA,IACE,SAAS,OACRQ,yBAAAA,uBAAuB,IAAI,KAAKC,yBAAAA,cAAc,MAAM,IAAI,IAEpD;QAAA,MAAM,CAAC,OAAO,SAAS,KAAK,MAAM,QAAQ,CAAC,CAAC,QAAQ,GACvD,IAAI,CAAC,KAAK,UAAU,CAAC,CAAC,WAAW,GAAG,KAAK,iBAAiB,IAAI,GAC5D,IAAI,MAAM,QAAQ,GAAG,6CAA6C;EAAA;CAC1E;CACA,IAAI,CAAC,SAAS,OAAO;CACrB,MAAM,SAAS,MAAM;CACrB,IAAI,WAAW,KAAA,GACb,KAAK,MAAM,WAAW,kBACpB,QACA,QACA,sBAAsB,KAAK,CAC7B,GACE,IAAI,eAAe,OAAO,QAAQ,MAAM,GAAG,OAAO;CAItD,IAHqB,OAAO,KAAK,KAAK,CAAC,CAAC,MACrC,SAASJ,yBAAAA,yBAAyB,IAAI,MAAM,UAGlC,KACX,CAAC,aAAa,gBAAgB,CAAC,CAAC,MAAM,SAAS,YAAY,MAAM,SAAS,CAAC,GAE3E,IACE,qBACA,GACA,+DACF;CACF,OAAO;AACT;;;ACvdA,MAAa,iBAAiB;CAC5B;CACA;CACA;CACA;CACA;AACF;AAEA,MAAa,sBAAsB,CAAC,SAAS,OAAO;AACpD,MAAa,yBAAyB;CACpC,QAAQ;CACR,OAAO;AACT;AAEA,MAAM,UAAU,UACd,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAErE,MAAM,kBAAkB,OAAgB,SAA4B;CAClE,IACE,CAAC,OAAO,KAAK,KACb,OAAO,KAAK,KAAK,CAAC,CAAC,MAAM,QAAQ,CAAC,KAAK,SAAS,GAAG,CAAC,KACpD,KAAK,MAAM,QAAQ,CAAC,OAAO,OAAO,OAAO,GAAG,CAAC,GAE7C,MAAM,IAAI,MACR,4DACF;CACF,OAAO;AACT;AAEA,MAAM,wBAAwB,OAAgB,YAAoB;CAChE,MAAM,gBAAgB,eAAe,OAAO,mBAAmB;CAC/D,MAAM,OAAO,QAAQ,MAAM,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG;CACpD,MAAM,qBACJ,iBACG;EACH,MAAM,WAAW,eACf,cAAc,eACd,OAAO,KAAK,sBAAsB,CACpC;EACA,MAAM,iBAAiB,SAA8C;GACnE,MAAM,WAAW,eAAe,SAAS,OAAO,CAAC,OAAO,QAAQ,CAAC;GACjE,MAAM,MAAM,SAAS;GACrB,MAAM,SAAS,SAAS;GACxB,MAAM,WAAW,+CAA+C,KAAK,kBAAkB,aAAa,GAAG,uBAAuB,MAAM,GAAG,QAAQ,WAAW,aAAa;GACvK,IAAI,OAAO,QAAQ,YAAY,QAAQ,UACrC,MAAM,IAAI,MACR,8EACF;GACF,IAAI,OAAO,WAAW,YAAY,CAAC,iBAAiB,KAAK,MAAM,GAC7D,MAAM,IAAI,MAAM,iDAAiD;GACnE,OAAO;IAAE;IAAK;GAAO;EACvB;EACA,OAAO;GACL,QAAQ,cAAc,QAAQ;GAC9B,OAAO,cAAc,OAAO;EAC9B;CAIF;CACA,OAAO;EACL,OAAO,kBAAkB,OAAO;EAChC,OAAO,kBAAkB,OAAO;CAClC;AAIF;;AAGA,MAAa,wBAAwB,UAAmB;CACtD,IAAI,CAAC,OAAO,KAAK,KAAK,MAAM,qBAAqB,GAC/C,MAAM,IAAI,MAAM,yCAAyC;CAC3D,MAAM,UAAU,QAAiC,QAAgB;EAC/D,MAAM,QAAQ,OAAO;EACrB,IAAI,OAAO,UAAU,YAAY,MAAM,KAAK,MAAM,IAChD,MAAM,IAAI,MAAM,sCAAsC,KAAK;EAC7D,OAAO;CACT;CACA,MAAM,WAAmC,CAAC;CAC1C,KAAK,MAAM,OAAO,gBAAgB,SAAS,OAAO,OAAO,OAAO,GAAG;CACnE,MAAM,MAAM,OAAO,OAAO,KAAK;CAC/B,MAAM,aAAa,OAAO,OAAO,YAAY;CAC7C,MAAM,OAAO,OAAO,OAAO,MAAM;CACjC,MAAM,eAAe,OAAO,OAAO,cAAc;CACjD,MAAM,cAAc,OAAO,OAAO,aAAa;CAC/C,MAAM,eAAe,OAAO,OAAO,cAAc;CACjD,MAAM,qBAAqB,OAAO,OAAO,oBAAoB;CAC7D,MAAM,SAAS,OAAO,OAAO,QAAQ;CACrC,MAAM,WAAW,OAAO,OAAO,UAAU;CACzC,MAAM,SAAS,OAAO,OAAO,QAAQ;CACrC,MAAM,OAAO,OAAO,OAAO,MAAM;CACjC,KAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ;EACzC,GAAG;EACH;EACA;EACA;EACA;EACA;CACF,CAAC,GACC,KAAA,GAAIK,OAAAA,MAAAA,CAAM,KAAK,MAAM,OACnB,MAAM,IAAI,MAAM,kBAAkB,KAAK,0BAA0B;CACrE,IAAI,CAAC,aAAa,KAAK,QAAQ,KAAK,CAAC,OAAO,cAAc,OAAO,QAAQ,CAAC,GACxE,MAAM,IAAI,MAAM,+CAA+C;CACjE,KAAA,GAAIA,OAAAA,MAAAA,CAAM,MAAM,MAAM,UAAU,CAAC,kBAAkB,KAAK,MAAM,GAC5D,MAAM,IAAI,MAAM,wCAAwC;CAC1D,MAAM,kBAAkB,qBACtB,MAAM,oBACN,MACF;CACA,IAAI,CAACC,yBAAAA,gBAAgB,IAAI,GACvB,MAAM,IAAI,MAAM,2CAA2C;CAC7D,KAAA,GACED,OAAAA,MAAAA,CAAM,YAAY,MAAM,gBACxB,CAAC,aAAa,WAAW,KAAK,KAC9B,aAAa,SAAS,GAAG,KACzB,aAAa,SAAS,GAAG,GAEzB,MAAM,IAAI,MAAM,sDAAsD;CACxE,IAAI,CAAC,uBAAuB,KAAK,MAAM,GACrC,MAAM,IAAI,MAAM,gDAAgD;CAClE,IAAI,CAAC,kBAAkB,KAAK,IAAI,GAC9B,MAAM,IAAI,MAAM,sCAAsC;CACxD,IACE,CAAC,mBAAmB,WAAW,IAAI,KACnC,mBAAmB,SAAS,GAAG,KAC/B,mBAAmB,SAAS,GAAG,GAE/B,MAAM,IAAI,MACR,iEACF;CACF,MAAM,gBAAgB,MAAM;CAC5B,IAAI,CAAC,OAAO,aAAa,GACvB,MAAM,IAAI,MAAM,yCAAyC;CAC3D,MAAM,UAAU,OAAO,eAAe,SAAS;CAC/C,MAAM,eAAe,OAAO,eAAe,cAAc;CACzD,KAAA,GAAIA,OAAAA,MAAAA,CAAM,OAAO,MAAM,SACrB,MAAM,IAAI,MAAM,mDAAmD;CACrE,MAAM,UAAU,MAAM;CACtB,IAAI,CAAC,MAAM,QAAQ,OAAO,KAAK,QAAQ,WAAW,GAChD,MAAM,IAAI,MAAM,oCAAoC;CACtD,MAAM,2BAA2B,QAAQ,KAAK,WAAoB;EAChE,IAAI,CAAC,OAAO,MAAM,GAAG,MAAM,IAAI,MAAM,mCAAmC;EACxE,MAAM,kBAAkB,OAAO,QAAQ,iBAAiB;EACxD,MAAM,oBAAoB,OAAO,QAAQ,mBAAmB;EAC5D,MAAM,mBAAmB,OAAO,QAAQ,kBAAkB;EAC1D,QAAQ,OAAO,SAAf;GACE,KAAK;IACH,IACE,sBAAsB,cACtB,oBAAoB,cAEpB,MAAM,IAAI,MACR,sDACF;IACF,OAAO;KACL,MAAM;KACN;KACA;KACA;IACF;GACF,KAAK,uBAAuB;IAC1B,MAAM,uBAAuB,OAAO,QAAQ,sBAAsB;IAClE,MAAM,yBAAyB,OAAO,QAAQ,wBAAwB;IACtE,IACE,sBAAsB,kBAAkB,gBACxC,2BAA2B,SAE3B,MAAM,IAAI,MACR,sDACF;IACF,OAAO;KACL,MAAM;KACN;KACA;KACA;KACA;KACA;IACF;GACF;GACA,SACE,MAAM,IAAI,MAAM,uCAAuC;EAC3D;CACF,CAAC;CACD,MAAM,eAAe,MAAM;CAC3B,IAAI,CAAC,OAAO,YAAY,KAAK,OAAO,KAAK,YAAY,CAAC,CAAC,WAAW,GAChE,MAAM,IAAI,MAAM,0BAA0B;CAC5C,MAAM,UAA4D,CAAC;CACnE,KAAK,MAAM,CAAC,MAAM,WAAW,OAAO,QAAQ,YAAY,GAAG;EACzD,IAAI,CAAC,OAAO,MAAM,GAAG,MAAM,IAAI,MAAM,0BAA0B,MAAM;EACrE,MAAM,MAAM,OAAO,QAAQ,KAAK;EAChC,MAAM,gBAAgB,OAAO,QAAQ,SAAS;EAC9C,IAAI,CAAC,iBAAiB,KAAK,GAAG,KAAK,CAAC,mBAAmB,KAAK,aAAa,GACvE,MAAM,IAAI,MAAM,+BAA+B,MAAM;EACvD,QAAQ,QAAQ;GAAE;GAAK,SAAS;EAAc;CAChD;CACA,MAAM,kBAAkB,MAAM;CAC9B,IACE,CAAC,OAAO,eAAe,KACvB,CAAC,OAAO,gBAAgB,WAAW,KACnC,CAAC,OAAO,gBAAgB,WAAW,KACnC,CAAC,OAAO,gBAAgB,SAAS,GAEjC,MAAM,IAAI,MAAM,2BAA2B;CAC7C,MAAM,gBAAgB,gBAAgB;CACtC,MAAM,WAAW;EACf,UAAU,OAAO,eAAe,UAAU;EAC1C,KAAK,OAAO,eAAe,KAAK;EAChC,MAAM,OAAO,eAAe,MAAM;EAClC,UAAU,OAAO,eAAe,UAAU;CAC5C;CACA,MAAM,cAAc,gBAAgB,WAAW,CAAC;CAChD,IACE,OAAO,gBAAgB,YACvB,CAAC,OAAO,UAAU,WAAW,KAC7B,cAAc,GAEd,MAAM,IAAI,MAAM,gDAAgD;CAClE,MAAM,WAAW,UAA6B;EAC5C,IACE,CAAC,MAAM,QAAQ,KAAK,KACpB,CAAC,MAAM,OAAO,UAAmB,OAAO,UAAU,QAAQ,GAE1D,MAAM,IAAI,MAAM,+CAA+C;EACjE,OAAO;CACT;CAGA,MAAM,oBAAoB,gBAAgB;CAC1C,IAAI,CAAC,OAAO,iBAAiB,GAC3B,MAAM,IAAI,MAAM,kCAAkC;CACpD,MAAM,eAAuD,CAAC;CAC9D,KAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ,iBAAiB,GAAG;EAC7D,IAAI,CAAC,OAAO,KAAK,KAAK,OAAO,KAAK,KAAK,CAAC,CAAC,MAAM,QAAQ,QAAQ,UAAU,GACvE,MAAM,IAAI,MAAM,oCAAoC,MAAM;EAC5D,aAAa,QAAQ,EAAE,UAAU,QAAQ,MAAM,WAAW,EAAE;CAC9D;CACA,MAAM,SACJ,CAAC;CACH,KAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ,gBAAgB,SAAS,GAAG;EACrE,IAAI,CAAC,OAAO,KAAK,GAAG,MAAM,IAAI,MAAM,6BAA6B,MAAM;EACvE,OAAO,QAAQ;GACb,UAAU,QAAQ,MAAM,WAAW;GACnC,aAAa,QAAQ,MAAM,cAAc;EAC3C;CACF;CACA,OAAO;EACL;EACA,WAAW,qBAAqB,MAAM,YAAY;EAClD;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,0BAA0B;GAAE;GAAS;EAAa;EAClD,YAAY;GACV;GACA,UAAU,EAAE,YAAY;GACxB;GACA;GACA,iBAAiB,CACf,mBAAG,IAAI,IAAI;IACT,GAAG,OAAO,KAAK,QAAQ;IAGvB;IACA;IACA,GAAG,yBAAyB,SAAS,WACnC,OAAO,SAAS,WACZ,CAAC,OAAO,eAAe,IACvB,CAAC,OAAO,iBAAiB,OAAO,oBAAoB,CAC1D;IACA;IACA;GACF,CAAC,CACH;GACA,gBAAgB,OAAO,KAAK,OAAO;GACnC,eAAe;IAAC;IAAQ;IAAU;GAAU;EAC9C;CACF;AACF"}
|
|
1
|
+
{"version":3,"file":"toolchain-schema.cjs","names":["record","path","workspaceContains","parseToml","isFormatterConfigPath","githubAutomationFileKind","isLefthookConfigPath","parseDocument","isDockerDefinitionPath","isShellScript","valid","nodePolicyValid"],"sources":["../src/toolchain-formatter.ts","../src/toolchain-schema.ts"],"sourcesContent":["import path from \"node:path\";\nimport picomatch from \"picomatch\";\nimport { parse as parseToml } from \"smol-toml\";\nimport { parseDocument } from \"yaml\";\n\nimport {\n githubAutomationFileKind,\n isDockerDefinitionPath,\n isFormatterConfigPath,\n isLefthookConfigPath,\n isShellScript,\n} from \"./toolchain-inputs\";\nimport { workspaceContains } from \"./toolchain-workspaces\";\n\nexport const formatterRule = \"formatter-policy\" as const;\n\ntype Diagnostic = {\n rule: typeof formatterRule;\n path: string;\n line: number;\n message: string;\n};\n\nexport type FormatterStyle = Readonly<Record<string, unknown>>;\n\nexport type FormatterPolicy = {\n command: \"bun fmt\";\n style: FormatterStyle;\n /** Generated files every repository leaves to their generators. */\n ignorePatterns: readonly string[];\n};\n\n/** Repository-owned [fmt] keys: what to skip, and the Tailwind entry point. */\nexport const repositoryFormatKeys = [\n \"ignorePatterns\",\n \"sortTailwindcss\",\n] as const;\n\nconst record = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\n/** One style for every repository; only repository-owned keys may differ. */\nexport const parseFormatterPolicy = (input: unknown): FormatterPolicy => {\n if (\n !record(input) ||\n Object.keys(input).some(\n (key) => key !== \"command\" && key !== \"style\" && key !== \"ignorePatterns\",\n )\n )\n throw new Error(\n \"toolchain.json formatter accepts only command, style and ignorePatterns\",\n );\n if (input[\"command\"] !== \"bun fmt\")\n throw new Error(\"toolchain.json formatter command must be bun fmt\");\n const style = input[\"style\"];\n if (!record(style) || Object.keys(style).length === 0)\n throw new Error(\"toolchain.json formatter style must be a nonempty table\");\n for (const key of Object.keys(style))\n if (repositoryFormatKeys.some((owned) => owned === key))\n throw new Error(\n `toolchain.json formatter style cannot own the repository key ${key}`,\n );\n const ignorePatterns = input[\"ignorePatterns\"];\n if (\n !Array.isArray(ignorePatterns) ||\n !ignorePatterns.every(\n (pattern): pattern is string =>\n typeof pattern === \"string\" && pattern !== \"\",\n )\n )\n throw new Error(\n \"toolchain.json formatter ignorePatterns must be nonempty strings\",\n );\n return { command: \"bun fmt\", style, ignorePatterns };\n};\n\nconst tomlValue = (value: unknown): string => {\n if (Array.isArray(value)) return `[${value.map(tomlValue).join(\", \")}]`;\n if (record(value))\n return `{ ${Object.entries(value)\n .map(([key, entry]) => `${key} = ${tomlValue(entry)}`)\n .join(\", \")} }`;\n return JSON.stringify(value);\n};\n\nconst tomlLines = (entries: readonly (readonly [string, unknown])[]) =>\n entries.map(([key, value]) => `${key} = ${tomlValue(value)}\\n`).join(\"\");\n\n/** Render the shared bunfig.toml [fmt] tables. */\nexport const sharedFormatTables = (policy: FormatterPolicy) => {\n const entries = Object.entries(policy.style);\n let output = `[fmt]\\n${tomlLines(\n entries.filter(([, value]) => !record(value)),\n )}ignorePatterns = ${tomlValue(policy.ignorePatterns)}\\n`;\n for (const [name, table] of entries)\n if (record(table))\n output += `\\n[fmt.${name}]\\n${tomlLines(Object.entries(table))}`;\n return output;\n};\n\nconst stableJson = (value: unknown): string =>\n JSON.stringify(value, (_key, entry: unknown) =>\n record(entry)\n ? Object.fromEntries(\n Object.entries(entry).toSorted(([left], [right]) =>\n left.localeCompare(right),\n ),\n )\n : entry,\n );\n\n// Every alternative formatter is rejected, not only the one being replaced.\nconst formatterPackage = (name: string) =>\n name === \"oxfmt\" ||\n name === \"prettier\" ||\n name === \"dprint\" ||\n name === \"@biomejs/biome\" ||\n name.startsWith(\"@dprint/\") ||\n /^(?:@[^/]+\\/)?prettier-plugin-/.test(name);\n\nconst dependencyFields = [\n \"dependencies\",\n \"devDependencies\",\n \"optionalDependencies\",\n \"peerDependencies\",\n \"overrides\",\n \"resolutions\",\n \"catalog\",\n] as const;\n\nconst declaredPackages = (manifest: Record<string, unknown>) => {\n const tables: unknown[] = dependencyFields.map((field) => manifest[field]);\n const workspaces = manifest[\"workspaces\"];\n for (const owner of [manifest, record(workspaces) ? workspaces : {}]) {\n if (owner !== manifest) tables.push(owner[\"catalog\"]);\n const catalogs = owner[\"catalogs\"];\n if (record(catalogs)) tables.push(...Object.values(catalogs));\n }\n return tables.flatMap((table) => (record(table) ? Object.keys(table) : []));\n};\n\nconst shellWords = (command: string) =>\n command\n .split(/[\\s;&|()<>`]+/u)\n .map((word) => word.replace(/^[\"']+|[\"']+$/gu, \"\"))\n .filter((word) => word !== \"\");\n\n/** Over-approximate: any formatter executable named as a word is an invocation. */\nconst invokesFormatter = (command: string) => {\n const words = shellWords(command);\n return words.some((word, index) => {\n const name = path.posix.basename(word);\n if (name === \"oxfmt\" || name === \"prettier\" || name === \"dprint\")\n return true;\n return (\n name === \"biome\" &&\n [\"format\", \"check\", \"ci\"].includes(words.at(index + 1) ?? \"\")\n );\n });\n};\n\nconst lineOf = (text: string, needle: string) =>\n Math.max(\n 1,\n text.split(/\\r?\\n/u).findIndex((line) => line.includes(needle)) + 1,\n );\n\n/** Collect every `run` string of a workflow, composite action or hook config. */\nconst runValues = (value: unknown): string[] => {\n if (Array.isArray(value)) return value.flatMap(runValues);\n if (!record(value)) return [];\n return Object.entries(value).flatMap(([key, entry]) =>\n key === \"run\" && typeof entry === \"string\" ? [entry] : runValues(entry),\n );\n};\n\nconst commandLines = (commands: readonly string[]) =>\n commands.flatMap((command) =>\n command\n .replace(/\\\\\\r?\\n/gu, \" \")\n .split(/\\r?\\n|&&|;/u)\n .map((line) => line.trim()),\n );\n\nconst isBunFormat = (line: string, flag: \"--check\" | \"--staged\") => {\n const words = shellWords(line);\n // Only flags may follow: a path operand narrows the check below the repository.\n return (\n words[0] === \"bun\" &&\n words[1] === \"fmt\" &&\n words.slice(2).includes(flag) &&\n words.slice(2).every((word) => word.startsWith(\"-\"))\n );\n};\n\n/** Package directories that the root workspaces patterns select. */\nconst workspacePackageRoots = (files: Record<string, string>) => {\n let manifest: unknown;\n try {\n manifest = JSON.parse(files[\"package.json\"] ?? \"\");\n } catch {\n return [];\n }\n if (!record(manifest)) return [];\n const declared = manifest[\"workspaces\"];\n // Bun accepts the array form and the { packages } object form.\n const patterns = record(declared) ? declared[\"packages\"] : declared;\n return Object.keys(files)\n .filter(\n (file) =>\n file.endsWith(\"/package.json\") &&\n workspaceContains({\n directory: \".\",\n file,\n patterns,\n rootMembership: \"patterns\",\n }),\n )\n .map((file) => path.posix.dirname(file));\n};\n\n// Representative package files: the manifest and common source layouts and\n// extensions. An ignore that matches any of them drops package sources.\nconst packageSourceProbes = [\n \"package.json\",\n \"index.ts\",\n \"index.js\",\n \"src/index.ts\",\n \"src/index.tsx\",\n \"src/index.js\",\n \"src/index.mjs\",\n \"src/main.ts\",\n \"src/nested/module.ts\",\n \"src/nested/component.tsx\",\n \"lib/index.ts\",\n \"lib/index.js\",\n] as const;\n\n/**\n * Ignore-file matching at one path level: a trailing slash limits a pattern to\n * directories, and a leading or inner slash anchors it at the root; otherwise\n * it matches at any depth.\n */\nconst matchesLevel = (pattern: string, level: string, directory: boolean) => {\n if (pattern.endsWith(\"/\") && !directory) return false;\n const anchored = pattern.replace(/\\/+$/u, \"\").includes(\"/\");\n const body = pattern.replace(/^\\/+|\\/+$/gu, \"\");\n // An empty pattern (\"/\") matches nothing.\n if (body === \"\") return false;\n const globs = anchored ? [body] : [body, `**/${body}`];\n return globs.some((glob) => picomatch.isMatch(level, glob, { dot: true }));\n};\n\n/** The patterns that match a path or one of its directories. */\nconst ignoringPatterns = (patterns: readonly string[], file: string) => {\n const parts = file.split(\"/\");\n return patterns.filter((pattern) =>\n parts.some((_, index) =>\n matchesLevel(\n pattern,\n parts.slice(0, index + 1).join(\"/\"),\n index < parts.length - 1,\n ),\n ),\n );\n};\n\nconst checkFormatConfig = (\n bunfig: string,\n policy: FormatterPolicy,\n packageRoots: readonly string[],\n): string[] => {\n let parsed: Record<string, unknown>;\n try {\n parsed = parseToml(bunfig);\n } catch {\n return [\"bunfig.toml must be valid TOML\"];\n }\n const fmt = parsed[\"fmt\"];\n if (!record(fmt))\n return [\n `bunfig.toml requires a [fmt] table: bun fmt reads its configuration only from there; start from:\\n${sharedFormatTables(policy)}`,\n ];\n const errors: string[] = [];\n for (const key of Object.keys(fmt))\n if (\n !Object.hasOwn(policy.style, key) &&\n !repositoryFormatKeys.some((owned) => owned === key)\n )\n errors.push(\n `bunfig.toml [fmt] ${key} is not part of the shared style; every repository formats alike`,\n );\n const ignored = Array.isArray(fmt[\"ignorePatterns\"])\n ? fmt[\"ignorePatterns\"]\n : [];\n const missing = policy.ignorePatterns.filter(\n (pattern) => !ignored.includes(pattern),\n );\n if (missing.length > 0)\n errors.push(\n `bunfig.toml [fmt] ignorePatterns must include the shared generated files: ${missing.join(\", \")}`,\n );\n // Ignores are for generated or vendored paths; one that covers a workspace\n // package silently drops its sources from bun fmt --check. Negations are not\n // accepted, so every listed pattern only ever removes files.\n const patterns = ignored.filter(\n (pattern): pattern is string => typeof pattern === \"string\",\n );\n for (const pattern of patterns)\n if (pattern.startsWith(\"!\"))\n errors.push(\n `bunfig.toml [fmt] ignorePatterns entry ${pattern} re-includes files; list only generated or vendored paths`,\n );\n const positives = patterns.filter((pattern) => !pattern.startsWith(\"!\"));\n const covered = new Map<string, string[]>();\n for (const root of packageRoots)\n for (const probe of packageSourceProbes) {\n for (const pattern of ignoringPatterns(positives, `${root}/${probe}`)) {\n if (policy.ignorePatterns.includes(pattern)) continue;\n const roots = covered.get(pattern) ?? [];\n if (!roots.includes(root)) roots.push(root);\n covered.set(pattern, roots);\n }\n }\n for (const pattern of patterns) {\n const roots = covered.get(pattern);\n if (roots !== undefined)\n errors.push(\n `bunfig.toml [fmt] ignorePatterns entry ${pattern} covers workspace packages (${roots.join(\", \")}); ignore only their generated or vendored paths`,\n );\n }\n for (const [key, value] of Object.entries(policy.style))\n if (stableJson(fmt[key]) !== stableJson(value))\n errors.push(\n `bunfig.toml [fmt] ${key} must equal the shared style:\\n${sharedFormatTables(policy)}`,\n );\n return errors;\n};\n\ntype CheckFormatterOptions = {\n files: Record<string, string>;\n policy: FormatterPolicy;\n usesBun: boolean;\n};\n\n/** bun fmt is the only formatter: one config table, staged hooks and a full CI check. */\nexport const checkFormatter = ({\n files,\n policy,\n usesBun,\n}: CheckFormatterOptions): Diagnostic[] => {\n const diagnostics: Diagnostic[] = [];\n const add = (file: string, line: number, message: string) =>\n diagnostics.push({ rule: formatterRule, path: file, line, message });\n const workflowCommands: string[] = [];\n for (const [file, text] of Object.entries(files)) {\n const name = path.posix.basename(file);\n if (isFormatterConfigPath(file))\n add(\n file,\n 1,\n \"formatter configuration belongs in bunfig.toml [fmt]; remove this file\",\n );\n if (name === \"package.json\") {\n let manifest: unknown;\n try {\n manifest = JSON.parse(text);\n } catch {\n // Package diagnostics already reject malformed manifests.\n continue;\n }\n if (!record(manifest)) continue;\n for (const dependency of declaredPackages(manifest))\n if (formatterPackage(dependency))\n add(\n file,\n lineOf(text, JSON.stringify(dependency)),\n `${dependency} is not allowed: bun fmt is the only formatter`,\n );\n if (manifest[\"prettier\"] !== undefined)\n add(\n file,\n lineOf(text, '\"prettier\"'),\n \"package.json prettier configuration belongs in bunfig.toml [fmt]\",\n );\n const scripts = manifest[\"scripts\"];\n if (record(scripts))\n for (const [script, command] of Object.entries(scripts)) {\n if (script === \"fmt\")\n add(\n file,\n lineOf(text, '\"fmt\"'),\n \"a package script named fmt shadows bun fmt; remove it\",\n );\n if (typeof command === \"string\" && invokesFormatter(command))\n add(\n file,\n lineOf(text, JSON.stringify(script)),\n `script ${script} runs another formatter; use bun fmt`,\n );\n }\n continue;\n }\n if (file === \".changeset/config.json\") {\n try {\n const config: unknown = JSON.parse(text);\n if (record(config) && config[\"format\"] !== false)\n add(\n file,\n lineOf(text, '\"format\"'),\n \"changesets must not run a formatter (format: false); format releases with bun fmt\",\n );\n } catch {\n add(file, 1, \"changeset configuration must be valid JSON\");\n }\n continue;\n }\n const automation = githubAutomationFileKind(file);\n if (automation !== undefined || isLefthookConfigPath(file)) {\n const document = parseDocument(text);\n if (document.errors.length > 0) continue;\n const parsed: unknown = document.toJS();\n const commands = runValues(parsed);\n for (const command of commands)\n if (invokesFormatter(command))\n add(\n file,\n lineOf(text, command.split(/\\r?\\n/u)[0] ?? command),\n \"command runs another formatter; use bun fmt\",\n );\n if (automation === \"workflow\") workflowCommands.push(...commands);\n if (isLefthookConfigPath(file) && usesBun) {\n const preCommit = record(parsed) ? parsed[\"pre-commit\"] : undefined;\n if (\n !commandLines(runValues(preCommit)).some((line) =>\n isBunFormat(line, \"--staged\"),\n )\n )\n add(\n file,\n lineOf(text, \"pre-commit\"),\n \"lefthook pre-commit must run bun fmt --staged\",\n );\n }\n continue;\n }\n if (\n text !== \"\" &&\n (isDockerDefinitionPath(file) || isShellScript(file, text))\n )\n for (const [index, line] of text.split(/\\r?\\n/u).entries())\n if (!line.trimStart().startsWith(\"#\") && invokesFormatter(line))\n add(file, index + 1, \"command runs another formatter; use bun fmt\");\n }\n if (!usesBun) return diagnostics;\n const bunfig = files[\"bunfig.toml\"];\n if (bunfig !== undefined)\n for (const message of checkFormatConfig(\n bunfig,\n policy,\n workspacePackageRoots(files),\n ))\n add(\"bunfig.toml\", lineOf(bunfig, \"[fmt\"), message);\n const hasWorkflows = Object.keys(files).some(\n (file) => githubAutomationFileKind(file) === \"workflow\",\n );\n if (\n hasWorkflows &&\n !commandLines(workflowCommands).some((line) => isBunFormat(line, \"--check\"))\n )\n add(\n \".github/workflows\",\n 1,\n \"a workflow must run bun fmt --check over the whole repository\",\n );\n return diagnostics;\n};\n","import { valid } from \"semver\";\n\nimport { parseFormatterPolicy } from \"./toolchain-formatter\";\nimport { nodePolicyValid } from \"./toolchain-node\";\n\nexport const packagePinKeys = [\n \"oxlint\",\n \"oxlint-tsgolint\",\n \"@oxlint/plugins\",\n \"@stll/oxlint-plugin\",\n \"lefthook\",\n] as const;\n\nexport const valkeyArchitectures = [\"amd64\", \"arm64\"] as const;\nexport const valkeyArtifactPackages = {\n server: \"valkey-server\",\n tools: \"valkey-tools\",\n} as const;\n\nconst record = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nconst artifactRecord = (value: unknown, keys: readonly string[]) => {\n if (\n !record(value) ||\n Object.keys(value).some((key) => !keys.includes(key)) ||\n keys.some((key) => !Object.hasOwn(value, key))\n )\n throw new Error(\n \"valkeyArtifacts requires complete, closed artifact objects\",\n );\n return value;\n};\n\nconst parseValkeyArtifacts = (input: unknown, version: string) => {\n const architectures = artifactRecord(input, valkeyArchitectures);\n const line = version.split(\".\").slice(0, 2).join(\".\");\n const parseArchitecture = (\n architecture: (typeof valkeyArchitectures)[number],\n ) => {\n const packages = artifactRecord(\n architectures[architecture],\n Object.keys(valkeyArtifactPackages),\n );\n const parseArtifact = (kind: keyof typeof valkeyArtifactPackages) => {\n const artifact = artifactRecord(packages[kind], [\"url\", \"sha256\"]);\n const url = artifact[\"url\"];\n const sha256 = artifact[\"sha256\"];\n const expected = `https://download.valkey.io/packaging/valkey-${line}/deb/ubuntu2404/${architecture}/${valkeyArtifactPackages[kind]}_${version}-1.noble_${architecture}.deb`;\n if (typeof url !== \"string\" || url !== expected)\n throw new Error(\n \"valkeyArtifacts URL must select the exact official versioned Ubuntu artifact\",\n );\n if (typeof sha256 !== \"string\" || !/^[a-f0-9]{64}$/.test(sha256))\n throw new Error(\"valkeyArtifacts requires a lowercase SHA256 pin\");\n return { url, sha256 };\n };\n return {\n server: parseArtifact(\"server\"),\n tools: parseArtifact(\"tools\"),\n } satisfies Record<\n keyof typeof valkeyArtifactPackages,\n ReturnType<typeof parseArtifact>\n >;\n };\n return {\n amd64: parseArchitecture(\"amd64\"),\n arm64: parseArchitecture(\"arm64\"),\n } satisfies Record<\n (typeof valkeyArchitectures)[number],\n ReturnType<typeof parseArchitecture>\n >;\n};\n\n/** Reject unsupported or incomplete installed policies before inspecting a consumer. */\nexport const parseToolchainPolicy = (input: unknown) => {\n if (!record(input) || input[\"schemaVersion\"] !== 1)\n throw new Error(\"toolchain.json must use schemaVersion 1\");\n const string = (object: Record<string, unknown>, key: string) => {\n const value = object[key];\n if (typeof value !== \"string\" || value.trim() === \"\")\n throw new Error(`toolchain.json requires a nonempty ${key}`);\n return value;\n };\n const packages: Record<string, string> = {};\n for (const key of packagePinKeys) packages[key] = string(input, key);\n const bun = string(input, \"bun\");\n const typescript = string(input, \"typescript\");\n const node = string(input, \"node\");\n const consumerNode = string(input, \"consumerNode\");\n const consumerNpm = string(input, \"consumerNpm\");\n const consumerPnpm = string(input, \"consumerPnpm\");\n const consumerTypescript = string(input, \"consumerTypescript\");\n const python = string(input, \"python\");\n const postgres = string(input, \"postgres\");\n const valkey = string(input, \"valkey\");\n const rust = string(input, \"rust\");\n for (const [name, value] of Object.entries({\n ...packages,\n bun,\n typescript,\n consumerNpm,\n consumerPnpm,\n consumerTypescript,\n }))\n if (valid(value) !== value)\n throw new Error(`toolchain.json ${name} must be an exact release`);\n if (!/^[1-9]\\d*$/.test(postgres) || !Number.isSafeInteger(Number(postgres)))\n throw new Error(\"PostgreSQL must be a canonical positive major\");\n if (valid(valkey) !== valkey || !/^\\d+\\.\\d+\\.\\d+$/.test(valkey))\n throw new Error(\"Valkey must be an exact stable release\");\n const valkeyArtifacts = parseValkeyArtifacts(\n input[\"valkeyArtifacts\"],\n valkey,\n );\n if (!nodePolicyValid(node))\n throw new Error(\"Node must be a canonical major N.x series\");\n if (\n valid(consumerNode) !== consumerNode ||\n !consumerNode.startsWith(\"22.\") ||\n consumerNode.includes(\"-\") ||\n consumerNode.includes(\"+\")\n )\n throw new Error(\"consumerNode must be an exact stable Node 22 release\");\n if (!/^\\d+\\.\\d+(?:\\.\\d+)?$/.test(python))\n throw new Error(\"Python must be an exact minor or patch release\");\n if (!/^\\d+\\.\\d+\\.\\d+$/.test(rust))\n throw new Error(\"Rust must be an exact stable release\");\n if (\n !consumerTypescript.startsWith(\"6.\") ||\n consumerTypescript.includes(\"-\") ||\n consumerTypescript.includes(\"+\")\n )\n throw new Error(\n \"consumerTypescript must be an exact stable TypeScript 6 release\",\n );\n const actionsInput = input[\"actions\"];\n if (!record(actionsInput) || Object.keys(actionsInput).length === 0)\n throw new Error(\"missing approved actions\");\n const actions: Record<string, { sha: string; version: string }> = {};\n for (const [name, action] of Object.entries(actionsInput)) {\n if (!record(action)) throw new Error(`invalid action policy: ${name}`);\n const sha = string(action, \"sha\");\n const actionVersion = string(action, \"version\");\n if (!/^[a-f0-9]{40}$/.test(sha) || !/^v\\d+(?:\\.\\d+)*$/.test(actionVersion))\n throw new Error(`invalid action SHA/version: ${name}`);\n actions[name] = { sha, version: actionVersion };\n }\n const dependabotInput = input[\"dependabot\"];\n if (\n !record(dependabotInput) ||\n !record(dependabotInput[\"schedule\"]) ||\n !record(dependabotInput[\"cooldown\"]) ||\n !record(dependabotInput[\"groups\"])\n )\n throw new Error(\"missing Dependabot policy\");\n const scheduleInput = dependabotInput[\"schedule\"];\n const schedule = {\n interval: string(scheduleInput, \"interval\"),\n day: string(scheduleInput, \"day\"),\n time: string(scheduleInput, \"time\"),\n timezone: string(scheduleInput, \"timezone\"),\n };\n const defaultDays = dependabotInput[\"cooldown\"][\"defaultDays\"];\n if (\n typeof defaultDays !== \"number\" ||\n !Number.isInteger(defaultDays) ||\n defaultDays < 5\n )\n throw new Error(\"Dependabot cooldown must be at least five days\");\n const strings = (value: unknown): string[] => {\n if (\n !Array.isArray(value) ||\n !value.every((entry: unknown) => typeof entry === \"string\")\n )\n throw new Error(\"Dependabot group values must be string arrays\");\n return value;\n };\n // First-party reusable workflows move by commit, without a semver update\n // type, and must land together; they precede the shared semver groups.\n const actionGroupsInput = dependabotInput[\"actionGroups\"];\n if (!record(actionGroupsInput))\n throw new Error(\"missing Dependabot action groups\");\n const actionGroups: Record<string, { patterns: string[] }> = {};\n for (const [name, group] of Object.entries(actionGroupsInput)) {\n if (!record(group) || Object.keys(group).some((key) => key !== \"patterns\"))\n throw new Error(`invalid Dependabot action group: ${name}`);\n actionGroups[name] = { patterns: strings(group[\"patterns\"]) };\n }\n const groups: Record<string, { patterns: string[]; updateTypes: string[] }> =\n {};\n for (const [name, group] of Object.entries(dependabotInput[\"groups\"])) {\n if (!record(group)) throw new Error(`invalid Dependabot group: ${name}`);\n groups[name] = {\n patterns: strings(group[\"patterns\"]),\n updateTypes: strings(group[\"updateTypes\"]),\n };\n }\n return {\n bun,\n formatter: parseFormatterPolicy(input[\"formatter\"]),\n typescript,\n node,\n postgres,\n valkey,\n valkeyArtifacts,\n consumerNode,\n consumerNpm,\n consumerPnpm,\n consumerTypescript,\n python,\n rust,\n packages,\n actions,\n dependabot: {\n schedule,\n cooldown: { defaultDays },\n actionGroups,\n groups,\n ignoredPackages: [\n ...new Set([\n ...Object.keys(packages),\n // The consumer package managers move only with a reviewed\n // consumerNpm or consumerPnpm change.\n \"npm\",\n \"pnpm\",\n // A repository's TypeScript install moves only with a reviewed\n // typescriptAllowlist change in stll-toolchain.json.\n \"typescript\",\n \"@typescript/native\",\n \"bun-types\",\n ]),\n ],\n ignoredActions: Object.keys(actions),\n ignoredImages: [\"node\", \"python\", \"oven/bun\"],\n },\n };\n};\n"],"mappings":"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"}
|
|
@@ -310,43 +310,6 @@ const parseToolchainPolicy = (input) => {
|
|
|
310
310
|
if (!/^\d+\.\d+(?:\.\d+)?$/.test(python)) throw new Error("Python must be an exact minor or patch release");
|
|
311
311
|
if (!/^\d+\.\d+\.\d+$/.test(rust)) throw new Error("Rust must be an exact stable release");
|
|
312
312
|
if (!consumerTypescript.startsWith("6.") || consumerTypescript.includes("-") || consumerTypescript.includes("+")) throw new Error("consumerTypescript must be an exact stable TypeScript 6 release");
|
|
313
|
-
const compatibility = input["typescript6Compatibility"];
|
|
314
|
-
if (!record(compatibility)) throw new Error("missing TypeScript compatibility policy");
|
|
315
|
-
const version = string(compatibility, "version");
|
|
316
|
-
const packageAlias = string(compatibility, "packageAlias");
|
|
317
|
-
if (valid(version) !== version) throw new Error("TypeScript compatibility must be an exact release");
|
|
318
|
-
const layouts = input["typescriptInstallLayouts"];
|
|
319
|
-
if (!Array.isArray(layouts) || layouts.length === 0) throw new Error("missing TypeScript install layouts");
|
|
320
|
-
const typescriptInstallLayouts = layouts.map((layout) => {
|
|
321
|
-
if (!record(layout)) throw new Error("invalid TypeScript install layout");
|
|
322
|
-
const compilerPackage = string(layout, "compilerPackage");
|
|
323
|
-
const compilerSpecifier = string(layout, "compilerSpecifier");
|
|
324
|
-
const typecheckCommand = string(layout, "typecheckCommand");
|
|
325
|
-
switch (layout["type"]) {
|
|
326
|
-
case "direct":
|
|
327
|
-
if (compilerSpecifier !== typescript || compilerPackage !== "typescript") throw new Error("direct TypeScript layout differs from shared version");
|
|
328
|
-
return {
|
|
329
|
-
type: "direct",
|
|
330
|
-
compilerPackage,
|
|
331
|
-
compilerSpecifier,
|
|
332
|
-
typecheckCommand
|
|
333
|
-
};
|
|
334
|
-
case "split-compatibility": {
|
|
335
|
-
const compatibilityPackage = string(layout, "compatibilityPackage");
|
|
336
|
-
const compatibilitySpecifier = string(layout, "compatibilitySpecifier");
|
|
337
|
-
if (compilerSpecifier !== `npm:typescript@${typescript}` || compatibilitySpecifier !== version) throw new Error("split TypeScript layout differs from shared versions");
|
|
338
|
-
return {
|
|
339
|
-
type: "split-compatibility",
|
|
340
|
-
compilerPackage,
|
|
341
|
-
compilerSpecifier,
|
|
342
|
-
compatibilityPackage,
|
|
343
|
-
compatibilitySpecifier,
|
|
344
|
-
typecheckCommand
|
|
345
|
-
};
|
|
346
|
-
}
|
|
347
|
-
default: throw new Error("unsupported TypeScript install layout");
|
|
348
|
-
}
|
|
349
|
-
});
|
|
350
313
|
const actionsInput = input["actions"];
|
|
351
314
|
if (!record(actionsInput) || Object.keys(actionsInput).length === 0) throw new Error("missing approved actions");
|
|
352
315
|
const actions = {};
|
|
@@ -406,11 +369,6 @@ const parseToolchainPolicy = (input) => {
|
|
|
406
369
|
rust,
|
|
407
370
|
packages,
|
|
408
371
|
actions,
|
|
409
|
-
typescriptInstallLayouts,
|
|
410
|
-
typescript6Compatibility: {
|
|
411
|
-
version,
|
|
412
|
-
packageAlias
|
|
413
|
-
},
|
|
414
372
|
dependabot: {
|
|
415
373
|
schedule,
|
|
416
374
|
cooldown: { defaultDays },
|
|
@@ -420,8 +378,8 @@ const parseToolchainPolicy = (input) => {
|
|
|
420
378
|
...Object.keys(packages),
|
|
421
379
|
"npm",
|
|
422
380
|
"pnpm",
|
|
423
|
-
|
|
424
|
-
|
|
381
|
+
"typescript",
|
|
382
|
+
"@typescript/native",
|
|
425
383
|
"bun-types"
|
|
426
384
|
])],
|
|
427
385
|
ignoredActions: Object.keys(actions),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toolchain-schema.mjs","names":["record","parseToml"],"sources":["../src/toolchain-formatter.ts","../src/toolchain-schema.ts"],"sourcesContent":["import path from \"node:path\";\nimport picomatch from \"picomatch\";\nimport { parse as parseToml } from \"smol-toml\";\nimport { parseDocument } from \"yaml\";\n\nimport {\n githubAutomationFileKind,\n isDockerDefinitionPath,\n isFormatterConfigPath,\n isLefthookConfigPath,\n isShellScript,\n} from \"./toolchain-inputs\";\nimport { workspaceContains } from \"./toolchain-workspaces\";\n\nexport const formatterRule = \"formatter-policy\" as const;\n\ntype Diagnostic = {\n rule: typeof formatterRule;\n path: string;\n line: number;\n message: string;\n};\n\nexport type FormatterStyle = Readonly<Record<string, unknown>>;\n\nexport type FormatterPolicy = {\n command: \"bun fmt\";\n style: FormatterStyle;\n /** Generated files every repository leaves to their generators. */\n ignorePatterns: readonly string[];\n};\n\n/** Repository-owned [fmt] keys: what to skip, and the Tailwind entry point. */\nexport const repositoryFormatKeys = [\n \"ignorePatterns\",\n \"sortTailwindcss\",\n] as const;\n\nconst record = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\n/** One style for every repository; only repository-owned keys may differ. */\nexport const parseFormatterPolicy = (input: unknown): FormatterPolicy => {\n if (\n !record(input) ||\n Object.keys(input).some(\n (key) => key !== \"command\" && key !== \"style\" && key !== \"ignorePatterns\",\n )\n )\n throw new Error(\n \"toolchain.json formatter accepts only command, style and ignorePatterns\",\n );\n if (input[\"command\"] !== \"bun fmt\")\n throw new Error(\"toolchain.json formatter command must be bun fmt\");\n const style = input[\"style\"];\n if (!record(style) || Object.keys(style).length === 0)\n throw new Error(\"toolchain.json formatter style must be a nonempty table\");\n for (const key of Object.keys(style))\n if (repositoryFormatKeys.some((owned) => owned === key))\n throw new Error(\n `toolchain.json formatter style cannot own the repository key ${key}`,\n );\n const ignorePatterns = input[\"ignorePatterns\"];\n if (\n !Array.isArray(ignorePatterns) ||\n !ignorePatterns.every(\n (pattern): pattern is string =>\n typeof pattern === \"string\" && pattern !== \"\",\n )\n )\n throw new Error(\n \"toolchain.json formatter ignorePatterns must be nonempty strings\",\n );\n return { command: \"bun fmt\", style, ignorePatterns };\n};\n\nconst tomlValue = (value: unknown): string => {\n if (Array.isArray(value)) return `[${value.map(tomlValue).join(\", \")}]`;\n if (record(value))\n return `{ ${Object.entries(value)\n .map(([key, entry]) => `${key} = ${tomlValue(entry)}`)\n .join(\", \")} }`;\n return JSON.stringify(value);\n};\n\nconst tomlLines = (entries: readonly (readonly [string, unknown])[]) =>\n entries.map(([key, value]) => `${key} = ${tomlValue(value)}\\n`).join(\"\");\n\n/** Render the shared bunfig.toml [fmt] tables. */\nexport const sharedFormatTables = (policy: FormatterPolicy) => {\n const entries = Object.entries(policy.style);\n let output = `[fmt]\\n${tomlLines(\n entries.filter(([, value]) => !record(value)),\n )}ignorePatterns = ${tomlValue(policy.ignorePatterns)}\\n`;\n for (const [name, table] of entries)\n if (record(table))\n output += `\\n[fmt.${name}]\\n${tomlLines(Object.entries(table))}`;\n return output;\n};\n\nconst stableJson = (value: unknown): string =>\n JSON.stringify(value, (_key, entry: unknown) =>\n record(entry)\n ? Object.fromEntries(\n Object.entries(entry).toSorted(([left], [right]) =>\n left.localeCompare(right),\n ),\n )\n : entry,\n );\n\n// Every alternative formatter is rejected, not only the one being replaced.\nconst formatterPackage = (name: string) =>\n name === \"oxfmt\" ||\n name === \"prettier\" ||\n name === \"dprint\" ||\n name === \"@biomejs/biome\" ||\n name.startsWith(\"@dprint/\") ||\n /^(?:@[^/]+\\/)?prettier-plugin-/.test(name);\n\nconst dependencyFields = [\n \"dependencies\",\n \"devDependencies\",\n \"optionalDependencies\",\n \"peerDependencies\",\n \"overrides\",\n \"resolutions\",\n \"catalog\",\n] as const;\n\nconst declaredPackages = (manifest: Record<string, unknown>) => {\n const tables: unknown[] = dependencyFields.map((field) => manifest[field]);\n const workspaces = manifest[\"workspaces\"];\n for (const owner of [manifest, record(workspaces) ? workspaces : {}]) {\n if (owner !== manifest) tables.push(owner[\"catalog\"]);\n const catalogs = owner[\"catalogs\"];\n if (record(catalogs)) tables.push(...Object.values(catalogs));\n }\n return tables.flatMap((table) => (record(table) ? Object.keys(table) : []));\n};\n\nconst shellWords = (command: string) =>\n command\n .split(/[\\s;&|()<>`]+/u)\n .map((word) => word.replace(/^[\"']+|[\"']+$/gu, \"\"))\n .filter((word) => word !== \"\");\n\n/** Over-approximate: any formatter executable named as a word is an invocation. */\nconst invokesFormatter = (command: string) => {\n const words = shellWords(command);\n return words.some((word, index) => {\n const name = path.posix.basename(word);\n if (name === \"oxfmt\" || name === \"prettier\" || name === \"dprint\")\n return true;\n return (\n name === \"biome\" &&\n [\"format\", \"check\", \"ci\"].includes(words.at(index + 1) ?? \"\")\n );\n });\n};\n\nconst lineOf = (text: string, needle: string) =>\n Math.max(\n 1,\n text.split(/\\r?\\n/u).findIndex((line) => line.includes(needle)) + 1,\n );\n\n/** Collect every `run` string of a workflow, composite action or hook config. */\nconst runValues = (value: unknown): string[] => {\n if (Array.isArray(value)) return value.flatMap(runValues);\n if (!record(value)) return [];\n return Object.entries(value).flatMap(([key, entry]) =>\n key === \"run\" && typeof entry === \"string\" ? [entry] : runValues(entry),\n );\n};\n\nconst commandLines = (commands: readonly string[]) =>\n commands.flatMap((command) =>\n command\n .replace(/\\\\\\r?\\n/gu, \" \")\n .split(/\\r?\\n|&&|;/u)\n .map((line) => line.trim()),\n );\n\nconst isBunFormat = (line: string, flag: \"--check\" | \"--staged\") => {\n const words = shellWords(line);\n // Only flags may follow: a path operand narrows the check below the repository.\n return (\n words[0] === \"bun\" &&\n words[1] === \"fmt\" &&\n words.slice(2).includes(flag) &&\n words.slice(2).every((word) => word.startsWith(\"-\"))\n );\n};\n\n/** Package directories that the root workspaces patterns select. */\nconst workspacePackageRoots = (files: Record<string, string>) => {\n let manifest: unknown;\n try {\n manifest = JSON.parse(files[\"package.json\"] ?? \"\");\n } catch {\n return [];\n }\n if (!record(manifest)) return [];\n const declared = manifest[\"workspaces\"];\n // Bun accepts the array form and the { packages } object form.\n const patterns = record(declared) ? declared[\"packages\"] : declared;\n return Object.keys(files)\n .filter(\n (file) =>\n file.endsWith(\"/package.json\") &&\n workspaceContains({\n directory: \".\",\n file,\n patterns,\n rootMembership: \"patterns\",\n }),\n )\n .map((file) => path.posix.dirname(file));\n};\n\n// Representative package files: the manifest and common source layouts and\n// extensions. An ignore that matches any of them drops package sources.\nconst packageSourceProbes = [\n \"package.json\",\n \"index.ts\",\n \"index.js\",\n \"src/index.ts\",\n \"src/index.tsx\",\n \"src/index.js\",\n \"src/index.mjs\",\n \"src/main.ts\",\n \"src/nested/module.ts\",\n \"src/nested/component.tsx\",\n \"lib/index.ts\",\n \"lib/index.js\",\n] as const;\n\n/**\n * Ignore-file matching at one path level: a trailing slash limits a pattern to\n * directories, and a leading or inner slash anchors it at the root; otherwise\n * it matches at any depth.\n */\nconst matchesLevel = (pattern: string, level: string, directory: boolean) => {\n if (pattern.endsWith(\"/\") && !directory) return false;\n const anchored = pattern.replace(/\\/+$/u, \"\").includes(\"/\");\n const body = pattern.replace(/^\\/+|\\/+$/gu, \"\");\n // An empty pattern (\"/\") matches nothing.\n if (body === \"\") return false;\n const globs = anchored ? [body] : [body, `**/${body}`];\n return globs.some((glob) => picomatch.isMatch(level, glob, { dot: true }));\n};\n\n/** The patterns that match a path or one of its directories. */\nconst ignoringPatterns = (patterns: readonly string[], file: string) => {\n const parts = file.split(\"/\");\n return patterns.filter((pattern) =>\n parts.some((_, index) =>\n matchesLevel(\n pattern,\n parts.slice(0, index + 1).join(\"/\"),\n index < parts.length - 1,\n ),\n ),\n );\n};\n\nconst checkFormatConfig = (\n bunfig: string,\n policy: FormatterPolicy,\n packageRoots: readonly string[],\n): string[] => {\n let parsed: Record<string, unknown>;\n try {\n parsed = parseToml(bunfig);\n } catch {\n return [\"bunfig.toml must be valid TOML\"];\n }\n const fmt = parsed[\"fmt\"];\n if (!record(fmt))\n return [\n `bunfig.toml requires a [fmt] table: bun fmt reads its configuration only from there; start from:\\n${sharedFormatTables(policy)}`,\n ];\n const errors: string[] = [];\n for (const key of Object.keys(fmt))\n if (\n !Object.hasOwn(policy.style, key) &&\n !repositoryFormatKeys.some((owned) => owned === key)\n )\n errors.push(\n `bunfig.toml [fmt] ${key} is not part of the shared style; every repository formats alike`,\n );\n const ignored = Array.isArray(fmt[\"ignorePatterns\"])\n ? fmt[\"ignorePatterns\"]\n : [];\n const missing = policy.ignorePatterns.filter(\n (pattern) => !ignored.includes(pattern),\n );\n if (missing.length > 0)\n errors.push(\n `bunfig.toml [fmt] ignorePatterns must include the shared generated files: ${missing.join(\", \")}`,\n );\n // Ignores are for generated or vendored paths; one that covers a workspace\n // package silently drops its sources from bun fmt --check. Negations are not\n // accepted, so every listed pattern only ever removes files.\n const patterns = ignored.filter(\n (pattern): pattern is string => typeof pattern === \"string\",\n );\n for (const pattern of patterns)\n if (pattern.startsWith(\"!\"))\n errors.push(\n `bunfig.toml [fmt] ignorePatterns entry ${pattern} re-includes files; list only generated or vendored paths`,\n );\n const positives = patterns.filter((pattern) => !pattern.startsWith(\"!\"));\n const covered = new Map<string, string[]>();\n for (const root of packageRoots)\n for (const probe of packageSourceProbes) {\n for (const pattern of ignoringPatterns(positives, `${root}/${probe}`)) {\n if (policy.ignorePatterns.includes(pattern)) continue;\n const roots = covered.get(pattern) ?? [];\n if (!roots.includes(root)) roots.push(root);\n covered.set(pattern, roots);\n }\n }\n for (const pattern of patterns) {\n const roots = covered.get(pattern);\n if (roots !== undefined)\n errors.push(\n `bunfig.toml [fmt] ignorePatterns entry ${pattern} covers workspace packages (${roots.join(\", \")}); ignore only their generated or vendored paths`,\n );\n }\n for (const [key, value] of Object.entries(policy.style))\n if (stableJson(fmt[key]) !== stableJson(value))\n errors.push(\n `bunfig.toml [fmt] ${key} must equal the shared style:\\n${sharedFormatTables(policy)}`,\n );\n return errors;\n};\n\ntype CheckFormatterOptions = {\n files: Record<string, string>;\n policy: FormatterPolicy;\n usesBun: boolean;\n};\n\n/** bun fmt is the only formatter: one config table, staged hooks and a full CI check. */\nexport const checkFormatter = ({\n files,\n policy,\n usesBun,\n}: CheckFormatterOptions): Diagnostic[] => {\n const diagnostics: Diagnostic[] = [];\n const add = (file: string, line: number, message: string) =>\n diagnostics.push({ rule: formatterRule, path: file, line, message });\n const workflowCommands: string[] = [];\n for (const [file, text] of Object.entries(files)) {\n const name = path.posix.basename(file);\n if (isFormatterConfigPath(file))\n add(\n file,\n 1,\n \"formatter configuration belongs in bunfig.toml [fmt]; remove this file\",\n );\n if (name === \"package.json\") {\n let manifest: unknown;\n try {\n manifest = JSON.parse(text);\n } catch {\n // Package diagnostics already reject malformed manifests.\n continue;\n }\n if (!record(manifest)) continue;\n for (const dependency of declaredPackages(manifest))\n if (formatterPackage(dependency))\n add(\n file,\n lineOf(text, JSON.stringify(dependency)),\n `${dependency} is not allowed: bun fmt is the only formatter`,\n );\n if (manifest[\"prettier\"] !== undefined)\n add(\n file,\n lineOf(text, '\"prettier\"'),\n \"package.json prettier configuration belongs in bunfig.toml [fmt]\",\n );\n const scripts = manifest[\"scripts\"];\n if (record(scripts))\n for (const [script, command] of Object.entries(scripts)) {\n if (script === \"fmt\")\n add(\n file,\n lineOf(text, '\"fmt\"'),\n \"a package script named fmt shadows bun fmt; remove it\",\n );\n if (typeof command === \"string\" && invokesFormatter(command))\n add(\n file,\n lineOf(text, JSON.stringify(script)),\n `script ${script} runs another formatter; use bun fmt`,\n );\n }\n continue;\n }\n if (file === \".changeset/config.json\") {\n try {\n const config: unknown = JSON.parse(text);\n if (record(config) && config[\"format\"] !== false)\n add(\n file,\n lineOf(text, '\"format\"'),\n \"changesets must not run a formatter (format: false); format releases with bun fmt\",\n );\n } catch {\n add(file, 1, \"changeset configuration must be valid JSON\");\n }\n continue;\n }\n const automation = githubAutomationFileKind(file);\n if (automation !== undefined || isLefthookConfigPath(file)) {\n const document = parseDocument(text);\n if (document.errors.length > 0) continue;\n const parsed: unknown = document.toJS();\n const commands = runValues(parsed);\n for (const command of commands)\n if (invokesFormatter(command))\n add(\n file,\n lineOf(text, command.split(/\\r?\\n/u)[0] ?? command),\n \"command runs another formatter; use bun fmt\",\n );\n if (automation === \"workflow\") workflowCommands.push(...commands);\n if (isLefthookConfigPath(file) && usesBun) {\n const preCommit = record(parsed) ? parsed[\"pre-commit\"] : undefined;\n if (\n !commandLines(runValues(preCommit)).some((line) =>\n isBunFormat(line, \"--staged\"),\n )\n )\n add(\n file,\n lineOf(text, \"pre-commit\"),\n \"lefthook pre-commit must run bun fmt --staged\",\n );\n }\n continue;\n }\n if (\n text !== \"\" &&\n (isDockerDefinitionPath(file) || isShellScript(file, text))\n )\n for (const [index, line] of text.split(/\\r?\\n/u).entries())\n if (!line.trimStart().startsWith(\"#\") && invokesFormatter(line))\n add(file, index + 1, \"command runs another formatter; use bun fmt\");\n }\n if (!usesBun) return diagnostics;\n const bunfig = files[\"bunfig.toml\"];\n if (bunfig !== undefined)\n for (const message of checkFormatConfig(\n bunfig,\n policy,\n workspacePackageRoots(files),\n ))\n add(\"bunfig.toml\", lineOf(bunfig, \"[fmt\"), message);\n const hasWorkflows = Object.keys(files).some(\n (file) => githubAutomationFileKind(file) === \"workflow\",\n );\n if (\n hasWorkflows &&\n !commandLines(workflowCommands).some((line) => isBunFormat(line, \"--check\"))\n )\n add(\n \".github/workflows\",\n 1,\n \"a workflow must run bun fmt --check over the whole repository\",\n );\n return diagnostics;\n};\n","import { valid } from \"semver\";\n\nimport { parseFormatterPolicy } from \"./toolchain-formatter\";\nimport { nodePolicyValid } from \"./toolchain-node\";\n\nexport const packagePinKeys = [\n \"oxlint\",\n \"oxlint-tsgolint\",\n \"@oxlint/plugins\",\n \"@stll/oxlint-plugin\",\n \"lefthook\",\n] as const;\n\nexport const valkeyArchitectures = [\"amd64\", \"arm64\"] as const;\nexport const valkeyArtifactPackages = {\n server: \"valkey-server\",\n tools: \"valkey-tools\",\n} as const;\n\nconst record = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nconst artifactRecord = (value: unknown, keys: readonly string[]) => {\n if (\n !record(value) ||\n Object.keys(value).some((key) => !keys.includes(key)) ||\n keys.some((key) => !Object.hasOwn(value, key))\n )\n throw new Error(\n \"valkeyArtifacts requires complete, closed artifact objects\",\n );\n return value;\n};\n\nconst parseValkeyArtifacts = (input: unknown, version: string) => {\n const architectures = artifactRecord(input, valkeyArchitectures);\n const line = version.split(\".\").slice(0, 2).join(\".\");\n const parseArchitecture = (\n architecture: (typeof valkeyArchitectures)[number],\n ) => {\n const packages = artifactRecord(\n architectures[architecture],\n Object.keys(valkeyArtifactPackages),\n );\n const parseArtifact = (kind: keyof typeof valkeyArtifactPackages) => {\n const artifact = artifactRecord(packages[kind], [\"url\", \"sha256\"]);\n const url = artifact[\"url\"];\n const sha256 = artifact[\"sha256\"];\n const expected = `https://download.valkey.io/packaging/valkey-${line}/deb/ubuntu2404/${architecture}/${valkeyArtifactPackages[kind]}_${version}-1.noble_${architecture}.deb`;\n if (typeof url !== \"string\" || url !== expected)\n throw new Error(\n \"valkeyArtifacts URL must select the exact official versioned Ubuntu artifact\",\n );\n if (typeof sha256 !== \"string\" || !/^[a-f0-9]{64}$/.test(sha256))\n throw new Error(\"valkeyArtifacts requires a lowercase SHA256 pin\");\n return { url, sha256 };\n };\n return {\n server: parseArtifact(\"server\"),\n tools: parseArtifact(\"tools\"),\n } satisfies Record<\n keyof typeof valkeyArtifactPackages,\n ReturnType<typeof parseArtifact>\n >;\n };\n return {\n amd64: parseArchitecture(\"amd64\"),\n arm64: parseArchitecture(\"arm64\"),\n } satisfies Record<\n (typeof valkeyArchitectures)[number],\n ReturnType<typeof parseArchitecture>\n >;\n};\n\n/** Reject unsupported or incomplete installed policies before inspecting a consumer. */\nexport const parseToolchainPolicy = (input: unknown) => {\n if (!record(input) || input[\"schemaVersion\"] !== 1)\n throw new Error(\"toolchain.json must use schemaVersion 1\");\n const string = (object: Record<string, unknown>, key: string) => {\n const value = object[key];\n if (typeof value !== \"string\" || value.trim() === \"\")\n throw new Error(`toolchain.json requires a nonempty ${key}`);\n return value;\n };\n const packages: Record<string, string> = {};\n for (const key of packagePinKeys) packages[key] = string(input, key);\n const bun = string(input, \"bun\");\n const typescript = string(input, \"typescript\");\n const node = string(input, \"node\");\n const consumerNode = string(input, \"consumerNode\");\n const consumerNpm = string(input, \"consumerNpm\");\n const consumerPnpm = string(input, \"consumerPnpm\");\n const consumerTypescript = string(input, \"consumerTypescript\");\n const python = string(input, \"python\");\n const postgres = string(input, \"postgres\");\n const valkey = string(input, \"valkey\");\n const rust = string(input, \"rust\");\n for (const [name, value] of Object.entries({\n ...packages,\n bun,\n typescript,\n consumerNpm,\n consumerPnpm,\n consumerTypescript,\n }))\n if (valid(value) !== value)\n throw new Error(`toolchain.json ${name} must be an exact release`);\n if (!/^[1-9]\\d*$/.test(postgres) || !Number.isSafeInteger(Number(postgres)))\n throw new Error(\"PostgreSQL must be a canonical positive major\");\n if (valid(valkey) !== valkey || !/^\\d+\\.\\d+\\.\\d+$/.test(valkey))\n throw new Error(\"Valkey must be an exact stable release\");\n const valkeyArtifacts = parseValkeyArtifacts(\n input[\"valkeyArtifacts\"],\n valkey,\n );\n if (!nodePolicyValid(node))\n throw new Error(\"Node must be a canonical major N.x series\");\n if (\n valid(consumerNode) !== consumerNode ||\n !consumerNode.startsWith(\"22.\") ||\n consumerNode.includes(\"-\") ||\n consumerNode.includes(\"+\")\n )\n throw new Error(\"consumerNode must be an exact stable Node 22 release\");\n if (!/^\\d+\\.\\d+(?:\\.\\d+)?$/.test(python))\n throw new Error(\"Python must be an exact minor or patch release\");\n if (!/^\\d+\\.\\d+\\.\\d+$/.test(rust))\n throw new Error(\"Rust must be an exact stable release\");\n if (\n !consumerTypescript.startsWith(\"6.\") ||\n consumerTypescript.includes(\"-\") ||\n consumerTypescript.includes(\"+\")\n )\n throw new Error(\n \"consumerTypescript must be an exact stable TypeScript 6 release\",\n );\n const compatibility = input[\"typescript6Compatibility\"];\n if (!record(compatibility))\n throw new Error(\"missing TypeScript compatibility policy\");\n const version = string(compatibility, \"version\");\n const packageAlias = string(compatibility, \"packageAlias\");\n if (valid(version) !== version)\n throw new Error(\"TypeScript compatibility must be an exact release\");\n const layouts = input[\"typescriptInstallLayouts\"];\n if (!Array.isArray(layouts) || layouts.length === 0)\n throw new Error(\"missing TypeScript install layouts\");\n const typescriptInstallLayouts = layouts.map((layout: unknown) => {\n if (!record(layout)) throw new Error(\"invalid TypeScript install layout\");\n const compilerPackage = string(layout, \"compilerPackage\");\n const compilerSpecifier = string(layout, \"compilerSpecifier\");\n const typecheckCommand = string(layout, \"typecheckCommand\");\n switch (layout[\"type\"]) {\n case \"direct\":\n if (\n compilerSpecifier !== typescript ||\n compilerPackage !== \"typescript\"\n )\n throw new Error(\n \"direct TypeScript layout differs from shared version\",\n );\n return {\n type: \"direct\",\n compilerPackage,\n compilerSpecifier,\n typecheckCommand,\n } as const;\n case \"split-compatibility\": {\n const compatibilityPackage = string(layout, \"compatibilityPackage\");\n const compatibilitySpecifier = string(layout, \"compatibilitySpecifier\");\n if (\n compilerSpecifier !== `npm:typescript@${typescript}` ||\n compatibilitySpecifier !== version\n )\n throw new Error(\n \"split TypeScript layout differs from shared versions\",\n );\n return {\n type: \"split-compatibility\",\n compilerPackage,\n compilerSpecifier,\n compatibilityPackage,\n compatibilitySpecifier,\n typecheckCommand,\n } as const;\n }\n default:\n throw new Error(\"unsupported TypeScript install layout\");\n }\n });\n const actionsInput = input[\"actions\"];\n if (!record(actionsInput) || Object.keys(actionsInput).length === 0)\n throw new Error(\"missing approved actions\");\n const actions: Record<string, { sha: string; version: string }> = {};\n for (const [name, action] of Object.entries(actionsInput)) {\n if (!record(action)) throw new Error(`invalid action policy: ${name}`);\n const sha = string(action, \"sha\");\n const actionVersion = string(action, \"version\");\n if (!/^[a-f0-9]{40}$/.test(sha) || !/^v\\d+(?:\\.\\d+)*$/.test(actionVersion))\n throw new Error(`invalid action SHA/version: ${name}`);\n actions[name] = { sha, version: actionVersion };\n }\n const dependabotInput = input[\"dependabot\"];\n if (\n !record(dependabotInput) ||\n !record(dependabotInput[\"schedule\"]) ||\n !record(dependabotInput[\"cooldown\"]) ||\n !record(dependabotInput[\"groups\"])\n )\n throw new Error(\"missing Dependabot policy\");\n const scheduleInput = dependabotInput[\"schedule\"];\n const schedule = {\n interval: string(scheduleInput, \"interval\"),\n day: string(scheduleInput, \"day\"),\n time: string(scheduleInput, \"time\"),\n timezone: string(scheduleInput, \"timezone\"),\n };\n const defaultDays = dependabotInput[\"cooldown\"][\"defaultDays\"];\n if (\n typeof defaultDays !== \"number\" ||\n !Number.isInteger(defaultDays) ||\n defaultDays < 5\n )\n throw new Error(\"Dependabot cooldown must be at least five days\");\n const strings = (value: unknown): string[] => {\n if (\n !Array.isArray(value) ||\n !value.every((entry: unknown) => typeof entry === \"string\")\n )\n throw new Error(\"Dependabot group values must be string arrays\");\n return value;\n };\n // First-party reusable workflows move by commit, without a semver update\n // type, and must land together; they precede the shared semver groups.\n const actionGroupsInput = dependabotInput[\"actionGroups\"];\n if (!record(actionGroupsInput))\n throw new Error(\"missing Dependabot action groups\");\n const actionGroups: Record<string, { patterns: string[] }> = {};\n for (const [name, group] of Object.entries(actionGroupsInput)) {\n if (!record(group) || Object.keys(group).some((key) => key !== \"patterns\"))\n throw new Error(`invalid Dependabot action group: ${name}`);\n actionGroups[name] = { patterns: strings(group[\"patterns\"]) };\n }\n const groups: Record<string, { patterns: string[]; updateTypes: string[] }> =\n {};\n for (const [name, group] of Object.entries(dependabotInput[\"groups\"])) {\n if (!record(group)) throw new Error(`invalid Dependabot group: ${name}`);\n groups[name] = {\n patterns: strings(group[\"patterns\"]),\n updateTypes: strings(group[\"updateTypes\"]),\n };\n }\n return {\n bun,\n formatter: parseFormatterPolicy(input[\"formatter\"]),\n typescript,\n node,\n postgres,\n valkey,\n valkeyArtifacts,\n consumerNode,\n consumerNpm,\n consumerPnpm,\n consumerTypescript,\n python,\n rust,\n packages,\n actions,\n typescriptInstallLayouts,\n typescript6Compatibility: { version, packageAlias },\n dependabot: {\n schedule,\n cooldown: { defaultDays },\n actionGroups,\n groups,\n ignoredPackages: [\n ...new Set([\n ...Object.keys(packages),\n // The consumer package managers move only with a reviewed\n // consumerNpm or consumerPnpm change.\n \"npm\",\n \"pnpm\",\n ...typescriptInstallLayouts.flatMap((layout) =>\n layout.type === \"direct\"\n ? [layout.compilerPackage]\n : [layout.compilerPackage, layout.compatibilityPackage],\n ),\n packageAlias,\n \"bun-types\",\n ]),\n ],\n ignoredActions: Object.keys(actions),\n ignoredImages: [\"node\", \"python\", \"oven/bun\"],\n },\n };\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"toolchain-schema.mjs","names":["record","parseToml"],"sources":["../src/toolchain-formatter.ts","../src/toolchain-schema.ts"],"sourcesContent":["import path from \"node:path\";\nimport picomatch from \"picomatch\";\nimport { parse as parseToml } from \"smol-toml\";\nimport { parseDocument } from \"yaml\";\n\nimport {\n githubAutomationFileKind,\n isDockerDefinitionPath,\n isFormatterConfigPath,\n isLefthookConfigPath,\n isShellScript,\n} from \"./toolchain-inputs\";\nimport { workspaceContains } from \"./toolchain-workspaces\";\n\nexport const formatterRule = \"formatter-policy\" as const;\n\ntype Diagnostic = {\n rule: typeof formatterRule;\n path: string;\n line: number;\n message: string;\n};\n\nexport type FormatterStyle = Readonly<Record<string, unknown>>;\n\nexport type FormatterPolicy = {\n command: \"bun fmt\";\n style: FormatterStyle;\n /** Generated files every repository leaves to their generators. */\n ignorePatterns: readonly string[];\n};\n\n/** Repository-owned [fmt] keys: what to skip, and the Tailwind entry point. */\nexport const repositoryFormatKeys = [\n \"ignorePatterns\",\n \"sortTailwindcss\",\n] as const;\n\nconst record = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\n/** One style for every repository; only repository-owned keys may differ. */\nexport const parseFormatterPolicy = (input: unknown): FormatterPolicy => {\n if (\n !record(input) ||\n Object.keys(input).some(\n (key) => key !== \"command\" && key !== \"style\" && key !== \"ignorePatterns\",\n )\n )\n throw new Error(\n \"toolchain.json formatter accepts only command, style and ignorePatterns\",\n );\n if (input[\"command\"] !== \"bun fmt\")\n throw new Error(\"toolchain.json formatter command must be bun fmt\");\n const style = input[\"style\"];\n if (!record(style) || Object.keys(style).length === 0)\n throw new Error(\"toolchain.json formatter style must be a nonempty table\");\n for (const key of Object.keys(style))\n if (repositoryFormatKeys.some((owned) => owned === key))\n throw new Error(\n `toolchain.json formatter style cannot own the repository key ${key}`,\n );\n const ignorePatterns = input[\"ignorePatterns\"];\n if (\n !Array.isArray(ignorePatterns) ||\n !ignorePatterns.every(\n (pattern): pattern is string =>\n typeof pattern === \"string\" && pattern !== \"\",\n )\n )\n throw new Error(\n \"toolchain.json formatter ignorePatterns must be nonempty strings\",\n );\n return { command: \"bun fmt\", style, ignorePatterns };\n};\n\nconst tomlValue = (value: unknown): string => {\n if (Array.isArray(value)) return `[${value.map(tomlValue).join(\", \")}]`;\n if (record(value))\n return `{ ${Object.entries(value)\n .map(([key, entry]) => `${key} = ${tomlValue(entry)}`)\n .join(\", \")} }`;\n return JSON.stringify(value);\n};\n\nconst tomlLines = (entries: readonly (readonly [string, unknown])[]) =>\n entries.map(([key, value]) => `${key} = ${tomlValue(value)}\\n`).join(\"\");\n\n/** Render the shared bunfig.toml [fmt] tables. */\nexport const sharedFormatTables = (policy: FormatterPolicy) => {\n const entries = Object.entries(policy.style);\n let output = `[fmt]\\n${tomlLines(\n entries.filter(([, value]) => !record(value)),\n )}ignorePatterns = ${tomlValue(policy.ignorePatterns)}\\n`;\n for (const [name, table] of entries)\n if (record(table))\n output += `\\n[fmt.${name}]\\n${tomlLines(Object.entries(table))}`;\n return output;\n};\n\nconst stableJson = (value: unknown): string =>\n JSON.stringify(value, (_key, entry: unknown) =>\n record(entry)\n ? Object.fromEntries(\n Object.entries(entry).toSorted(([left], [right]) =>\n left.localeCompare(right),\n ),\n )\n : entry,\n );\n\n// Every alternative formatter is rejected, not only the one being replaced.\nconst formatterPackage = (name: string) =>\n name === \"oxfmt\" ||\n name === \"prettier\" ||\n name === \"dprint\" ||\n name === \"@biomejs/biome\" ||\n name.startsWith(\"@dprint/\") ||\n /^(?:@[^/]+\\/)?prettier-plugin-/.test(name);\n\nconst dependencyFields = [\n \"dependencies\",\n \"devDependencies\",\n \"optionalDependencies\",\n \"peerDependencies\",\n \"overrides\",\n \"resolutions\",\n \"catalog\",\n] as const;\n\nconst declaredPackages = (manifest: Record<string, unknown>) => {\n const tables: unknown[] = dependencyFields.map((field) => manifest[field]);\n const workspaces = manifest[\"workspaces\"];\n for (const owner of [manifest, record(workspaces) ? workspaces : {}]) {\n if (owner !== manifest) tables.push(owner[\"catalog\"]);\n const catalogs = owner[\"catalogs\"];\n if (record(catalogs)) tables.push(...Object.values(catalogs));\n }\n return tables.flatMap((table) => (record(table) ? Object.keys(table) : []));\n};\n\nconst shellWords = (command: string) =>\n command\n .split(/[\\s;&|()<>`]+/u)\n .map((word) => word.replace(/^[\"']+|[\"']+$/gu, \"\"))\n .filter((word) => word !== \"\");\n\n/** Over-approximate: any formatter executable named as a word is an invocation. */\nconst invokesFormatter = (command: string) => {\n const words = shellWords(command);\n return words.some((word, index) => {\n const name = path.posix.basename(word);\n if (name === \"oxfmt\" || name === \"prettier\" || name === \"dprint\")\n return true;\n return (\n name === \"biome\" &&\n [\"format\", \"check\", \"ci\"].includes(words.at(index + 1) ?? \"\")\n );\n });\n};\n\nconst lineOf = (text: string, needle: string) =>\n Math.max(\n 1,\n text.split(/\\r?\\n/u).findIndex((line) => line.includes(needle)) + 1,\n );\n\n/** Collect every `run` string of a workflow, composite action or hook config. */\nconst runValues = (value: unknown): string[] => {\n if (Array.isArray(value)) return value.flatMap(runValues);\n if (!record(value)) return [];\n return Object.entries(value).flatMap(([key, entry]) =>\n key === \"run\" && typeof entry === \"string\" ? [entry] : runValues(entry),\n );\n};\n\nconst commandLines = (commands: readonly string[]) =>\n commands.flatMap((command) =>\n command\n .replace(/\\\\\\r?\\n/gu, \" \")\n .split(/\\r?\\n|&&|;/u)\n .map((line) => line.trim()),\n );\n\nconst isBunFormat = (line: string, flag: \"--check\" | \"--staged\") => {\n const words = shellWords(line);\n // Only flags may follow: a path operand narrows the check below the repository.\n return (\n words[0] === \"bun\" &&\n words[1] === \"fmt\" &&\n words.slice(2).includes(flag) &&\n words.slice(2).every((word) => word.startsWith(\"-\"))\n );\n};\n\n/** Package directories that the root workspaces patterns select. */\nconst workspacePackageRoots = (files: Record<string, string>) => {\n let manifest: unknown;\n try {\n manifest = JSON.parse(files[\"package.json\"] ?? \"\");\n } catch {\n return [];\n }\n if (!record(manifest)) return [];\n const declared = manifest[\"workspaces\"];\n // Bun accepts the array form and the { packages } object form.\n const patterns = record(declared) ? declared[\"packages\"] : declared;\n return Object.keys(files)\n .filter(\n (file) =>\n file.endsWith(\"/package.json\") &&\n workspaceContains({\n directory: \".\",\n file,\n patterns,\n rootMembership: \"patterns\",\n }),\n )\n .map((file) => path.posix.dirname(file));\n};\n\n// Representative package files: the manifest and common source layouts and\n// extensions. An ignore that matches any of them drops package sources.\nconst packageSourceProbes = [\n \"package.json\",\n \"index.ts\",\n \"index.js\",\n \"src/index.ts\",\n \"src/index.tsx\",\n \"src/index.js\",\n \"src/index.mjs\",\n \"src/main.ts\",\n \"src/nested/module.ts\",\n \"src/nested/component.tsx\",\n \"lib/index.ts\",\n \"lib/index.js\",\n] as const;\n\n/**\n * Ignore-file matching at one path level: a trailing slash limits a pattern to\n * directories, and a leading or inner slash anchors it at the root; otherwise\n * it matches at any depth.\n */\nconst matchesLevel = (pattern: string, level: string, directory: boolean) => {\n if (pattern.endsWith(\"/\") && !directory) return false;\n const anchored = pattern.replace(/\\/+$/u, \"\").includes(\"/\");\n const body = pattern.replace(/^\\/+|\\/+$/gu, \"\");\n // An empty pattern (\"/\") matches nothing.\n if (body === \"\") return false;\n const globs = anchored ? [body] : [body, `**/${body}`];\n return globs.some((glob) => picomatch.isMatch(level, glob, { dot: true }));\n};\n\n/** The patterns that match a path or one of its directories. */\nconst ignoringPatterns = (patterns: readonly string[], file: string) => {\n const parts = file.split(\"/\");\n return patterns.filter((pattern) =>\n parts.some((_, index) =>\n matchesLevel(\n pattern,\n parts.slice(0, index + 1).join(\"/\"),\n index < parts.length - 1,\n ),\n ),\n );\n};\n\nconst checkFormatConfig = (\n bunfig: string,\n policy: FormatterPolicy,\n packageRoots: readonly string[],\n): string[] => {\n let parsed: Record<string, unknown>;\n try {\n parsed = parseToml(bunfig);\n } catch {\n return [\"bunfig.toml must be valid TOML\"];\n }\n const fmt = parsed[\"fmt\"];\n if (!record(fmt))\n return [\n `bunfig.toml requires a [fmt] table: bun fmt reads its configuration only from there; start from:\\n${sharedFormatTables(policy)}`,\n ];\n const errors: string[] = [];\n for (const key of Object.keys(fmt))\n if (\n !Object.hasOwn(policy.style, key) &&\n !repositoryFormatKeys.some((owned) => owned === key)\n )\n errors.push(\n `bunfig.toml [fmt] ${key} is not part of the shared style; every repository formats alike`,\n );\n const ignored = Array.isArray(fmt[\"ignorePatterns\"])\n ? fmt[\"ignorePatterns\"]\n : [];\n const missing = policy.ignorePatterns.filter(\n (pattern) => !ignored.includes(pattern),\n );\n if (missing.length > 0)\n errors.push(\n `bunfig.toml [fmt] ignorePatterns must include the shared generated files: ${missing.join(\", \")}`,\n );\n // Ignores are for generated or vendored paths; one that covers a workspace\n // package silently drops its sources from bun fmt --check. Negations are not\n // accepted, so every listed pattern only ever removes files.\n const patterns = ignored.filter(\n (pattern): pattern is string => typeof pattern === \"string\",\n );\n for (const pattern of patterns)\n if (pattern.startsWith(\"!\"))\n errors.push(\n `bunfig.toml [fmt] ignorePatterns entry ${pattern} re-includes files; list only generated or vendored paths`,\n );\n const positives = patterns.filter((pattern) => !pattern.startsWith(\"!\"));\n const covered = new Map<string, string[]>();\n for (const root of packageRoots)\n for (const probe of packageSourceProbes) {\n for (const pattern of ignoringPatterns(positives, `${root}/${probe}`)) {\n if (policy.ignorePatterns.includes(pattern)) continue;\n const roots = covered.get(pattern) ?? [];\n if (!roots.includes(root)) roots.push(root);\n covered.set(pattern, roots);\n }\n }\n for (const pattern of patterns) {\n const roots = covered.get(pattern);\n if (roots !== undefined)\n errors.push(\n `bunfig.toml [fmt] ignorePatterns entry ${pattern} covers workspace packages (${roots.join(\", \")}); ignore only their generated or vendored paths`,\n );\n }\n for (const [key, value] of Object.entries(policy.style))\n if (stableJson(fmt[key]) !== stableJson(value))\n errors.push(\n `bunfig.toml [fmt] ${key} must equal the shared style:\\n${sharedFormatTables(policy)}`,\n );\n return errors;\n};\n\ntype CheckFormatterOptions = {\n files: Record<string, string>;\n policy: FormatterPolicy;\n usesBun: boolean;\n};\n\n/** bun fmt is the only formatter: one config table, staged hooks and a full CI check. */\nexport const checkFormatter = ({\n files,\n policy,\n usesBun,\n}: CheckFormatterOptions): Diagnostic[] => {\n const diagnostics: Diagnostic[] = [];\n const add = (file: string, line: number, message: string) =>\n diagnostics.push({ rule: formatterRule, path: file, line, message });\n const workflowCommands: string[] = [];\n for (const [file, text] of Object.entries(files)) {\n const name = path.posix.basename(file);\n if (isFormatterConfigPath(file))\n add(\n file,\n 1,\n \"formatter configuration belongs in bunfig.toml [fmt]; remove this file\",\n );\n if (name === \"package.json\") {\n let manifest: unknown;\n try {\n manifest = JSON.parse(text);\n } catch {\n // Package diagnostics already reject malformed manifests.\n continue;\n }\n if (!record(manifest)) continue;\n for (const dependency of declaredPackages(manifest))\n if (formatterPackage(dependency))\n add(\n file,\n lineOf(text, JSON.stringify(dependency)),\n `${dependency} is not allowed: bun fmt is the only formatter`,\n );\n if (manifest[\"prettier\"] !== undefined)\n add(\n file,\n lineOf(text, '\"prettier\"'),\n \"package.json prettier configuration belongs in bunfig.toml [fmt]\",\n );\n const scripts = manifest[\"scripts\"];\n if (record(scripts))\n for (const [script, command] of Object.entries(scripts)) {\n if (script === \"fmt\")\n add(\n file,\n lineOf(text, '\"fmt\"'),\n \"a package script named fmt shadows bun fmt; remove it\",\n );\n if (typeof command === \"string\" && invokesFormatter(command))\n add(\n file,\n lineOf(text, JSON.stringify(script)),\n `script ${script} runs another formatter; use bun fmt`,\n );\n }\n continue;\n }\n if (file === \".changeset/config.json\") {\n try {\n const config: unknown = JSON.parse(text);\n if (record(config) && config[\"format\"] !== false)\n add(\n file,\n lineOf(text, '\"format\"'),\n \"changesets must not run a formatter (format: false); format releases with bun fmt\",\n );\n } catch {\n add(file, 1, \"changeset configuration must be valid JSON\");\n }\n continue;\n }\n const automation = githubAutomationFileKind(file);\n if (automation !== undefined || isLefthookConfigPath(file)) {\n const document = parseDocument(text);\n if (document.errors.length > 0) continue;\n const parsed: unknown = document.toJS();\n const commands = runValues(parsed);\n for (const command of commands)\n if (invokesFormatter(command))\n add(\n file,\n lineOf(text, command.split(/\\r?\\n/u)[0] ?? command),\n \"command runs another formatter; use bun fmt\",\n );\n if (automation === \"workflow\") workflowCommands.push(...commands);\n if (isLefthookConfigPath(file) && usesBun) {\n const preCommit = record(parsed) ? parsed[\"pre-commit\"] : undefined;\n if (\n !commandLines(runValues(preCommit)).some((line) =>\n isBunFormat(line, \"--staged\"),\n )\n )\n add(\n file,\n lineOf(text, \"pre-commit\"),\n \"lefthook pre-commit must run bun fmt --staged\",\n );\n }\n continue;\n }\n if (\n text !== \"\" &&\n (isDockerDefinitionPath(file) || isShellScript(file, text))\n )\n for (const [index, line] of text.split(/\\r?\\n/u).entries())\n if (!line.trimStart().startsWith(\"#\") && invokesFormatter(line))\n add(file, index + 1, \"command runs another formatter; use bun fmt\");\n }\n if (!usesBun) return diagnostics;\n const bunfig = files[\"bunfig.toml\"];\n if (bunfig !== undefined)\n for (const message of checkFormatConfig(\n bunfig,\n policy,\n workspacePackageRoots(files),\n ))\n add(\"bunfig.toml\", lineOf(bunfig, \"[fmt\"), message);\n const hasWorkflows = Object.keys(files).some(\n (file) => githubAutomationFileKind(file) === \"workflow\",\n );\n if (\n hasWorkflows &&\n !commandLines(workflowCommands).some((line) => isBunFormat(line, \"--check\"))\n )\n add(\n \".github/workflows\",\n 1,\n \"a workflow must run bun fmt --check over the whole repository\",\n );\n return diagnostics;\n};\n","import { valid } from \"semver\";\n\nimport { parseFormatterPolicy } from \"./toolchain-formatter\";\nimport { nodePolicyValid } from \"./toolchain-node\";\n\nexport const packagePinKeys = [\n \"oxlint\",\n \"oxlint-tsgolint\",\n \"@oxlint/plugins\",\n \"@stll/oxlint-plugin\",\n \"lefthook\",\n] as const;\n\nexport const valkeyArchitectures = [\"amd64\", \"arm64\"] as const;\nexport const valkeyArtifactPackages = {\n server: \"valkey-server\",\n tools: \"valkey-tools\",\n} as const;\n\nconst record = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nconst artifactRecord = (value: unknown, keys: readonly string[]) => {\n if (\n !record(value) ||\n Object.keys(value).some((key) => !keys.includes(key)) ||\n keys.some((key) => !Object.hasOwn(value, key))\n )\n throw new Error(\n \"valkeyArtifacts requires complete, closed artifact objects\",\n );\n return value;\n};\n\nconst parseValkeyArtifacts = (input: unknown, version: string) => {\n const architectures = artifactRecord(input, valkeyArchitectures);\n const line = version.split(\".\").slice(0, 2).join(\".\");\n const parseArchitecture = (\n architecture: (typeof valkeyArchitectures)[number],\n ) => {\n const packages = artifactRecord(\n architectures[architecture],\n Object.keys(valkeyArtifactPackages),\n );\n const parseArtifact = (kind: keyof typeof valkeyArtifactPackages) => {\n const artifact = artifactRecord(packages[kind], [\"url\", \"sha256\"]);\n const url = artifact[\"url\"];\n const sha256 = artifact[\"sha256\"];\n const expected = `https://download.valkey.io/packaging/valkey-${line}/deb/ubuntu2404/${architecture}/${valkeyArtifactPackages[kind]}_${version}-1.noble_${architecture}.deb`;\n if (typeof url !== \"string\" || url !== expected)\n throw new Error(\n \"valkeyArtifacts URL must select the exact official versioned Ubuntu artifact\",\n );\n if (typeof sha256 !== \"string\" || !/^[a-f0-9]{64}$/.test(sha256))\n throw new Error(\"valkeyArtifacts requires a lowercase SHA256 pin\");\n return { url, sha256 };\n };\n return {\n server: parseArtifact(\"server\"),\n tools: parseArtifact(\"tools\"),\n } satisfies Record<\n keyof typeof valkeyArtifactPackages,\n ReturnType<typeof parseArtifact>\n >;\n };\n return {\n amd64: parseArchitecture(\"amd64\"),\n arm64: parseArchitecture(\"arm64\"),\n } satisfies Record<\n (typeof valkeyArchitectures)[number],\n ReturnType<typeof parseArchitecture>\n >;\n};\n\n/** Reject unsupported or incomplete installed policies before inspecting a consumer. */\nexport const parseToolchainPolicy = (input: unknown) => {\n if (!record(input) || input[\"schemaVersion\"] !== 1)\n throw new Error(\"toolchain.json must use schemaVersion 1\");\n const string = (object: Record<string, unknown>, key: string) => {\n const value = object[key];\n if (typeof value !== \"string\" || value.trim() === \"\")\n throw new Error(`toolchain.json requires a nonempty ${key}`);\n return value;\n };\n const packages: Record<string, string> = {};\n for (const key of packagePinKeys) packages[key] = string(input, key);\n const bun = string(input, \"bun\");\n const typescript = string(input, \"typescript\");\n const node = string(input, \"node\");\n const consumerNode = string(input, \"consumerNode\");\n const consumerNpm = string(input, \"consumerNpm\");\n const consumerPnpm = string(input, \"consumerPnpm\");\n const consumerTypescript = string(input, \"consumerTypescript\");\n const python = string(input, \"python\");\n const postgres = string(input, \"postgres\");\n const valkey = string(input, \"valkey\");\n const rust = string(input, \"rust\");\n for (const [name, value] of Object.entries({\n ...packages,\n bun,\n typescript,\n consumerNpm,\n consumerPnpm,\n consumerTypescript,\n }))\n if (valid(value) !== value)\n throw new Error(`toolchain.json ${name} must be an exact release`);\n if (!/^[1-9]\\d*$/.test(postgres) || !Number.isSafeInteger(Number(postgres)))\n throw new Error(\"PostgreSQL must be a canonical positive major\");\n if (valid(valkey) !== valkey || !/^\\d+\\.\\d+\\.\\d+$/.test(valkey))\n throw new Error(\"Valkey must be an exact stable release\");\n const valkeyArtifacts = parseValkeyArtifacts(\n input[\"valkeyArtifacts\"],\n valkey,\n );\n if (!nodePolicyValid(node))\n throw new Error(\"Node must be a canonical major N.x series\");\n if (\n valid(consumerNode) !== consumerNode ||\n !consumerNode.startsWith(\"22.\") ||\n consumerNode.includes(\"-\") ||\n consumerNode.includes(\"+\")\n )\n throw new Error(\"consumerNode must be an exact stable Node 22 release\");\n if (!/^\\d+\\.\\d+(?:\\.\\d+)?$/.test(python))\n throw new Error(\"Python must be an exact minor or patch release\");\n if (!/^\\d+\\.\\d+\\.\\d+$/.test(rust))\n throw new Error(\"Rust must be an exact stable release\");\n if (\n !consumerTypescript.startsWith(\"6.\") ||\n consumerTypescript.includes(\"-\") ||\n consumerTypescript.includes(\"+\")\n )\n throw new Error(\n \"consumerTypescript must be an exact stable TypeScript 6 release\",\n );\n const actionsInput = input[\"actions\"];\n if (!record(actionsInput) || Object.keys(actionsInput).length === 0)\n throw new Error(\"missing approved actions\");\n const actions: Record<string, { sha: string; version: string }> = {};\n for (const [name, action] of Object.entries(actionsInput)) {\n if (!record(action)) throw new Error(`invalid action policy: ${name}`);\n const sha = string(action, \"sha\");\n const actionVersion = string(action, \"version\");\n if (!/^[a-f0-9]{40}$/.test(sha) || !/^v\\d+(?:\\.\\d+)*$/.test(actionVersion))\n throw new Error(`invalid action SHA/version: ${name}`);\n actions[name] = { sha, version: actionVersion };\n }\n const dependabotInput = input[\"dependabot\"];\n if (\n !record(dependabotInput) ||\n !record(dependabotInput[\"schedule\"]) ||\n !record(dependabotInput[\"cooldown\"]) ||\n !record(dependabotInput[\"groups\"])\n )\n throw new Error(\"missing Dependabot policy\");\n const scheduleInput = dependabotInput[\"schedule\"];\n const schedule = {\n interval: string(scheduleInput, \"interval\"),\n day: string(scheduleInput, \"day\"),\n time: string(scheduleInput, \"time\"),\n timezone: string(scheduleInput, \"timezone\"),\n };\n const defaultDays = dependabotInput[\"cooldown\"][\"defaultDays\"];\n if (\n typeof defaultDays !== \"number\" ||\n !Number.isInteger(defaultDays) ||\n defaultDays < 5\n )\n throw new Error(\"Dependabot cooldown must be at least five days\");\n const strings = (value: unknown): string[] => {\n if (\n !Array.isArray(value) ||\n !value.every((entry: unknown) => typeof entry === \"string\")\n )\n throw new Error(\"Dependabot group values must be string arrays\");\n return value;\n };\n // First-party reusable workflows move by commit, without a semver update\n // type, and must land together; they precede the shared semver groups.\n const actionGroupsInput = dependabotInput[\"actionGroups\"];\n if (!record(actionGroupsInput))\n throw new Error(\"missing Dependabot action groups\");\n const actionGroups: Record<string, { patterns: string[] }> = {};\n for (const [name, group] of Object.entries(actionGroupsInput)) {\n if (!record(group) || Object.keys(group).some((key) => key !== \"patterns\"))\n throw new Error(`invalid Dependabot action group: ${name}`);\n actionGroups[name] = { patterns: strings(group[\"patterns\"]) };\n }\n const groups: Record<string, { patterns: string[]; updateTypes: string[] }> =\n {};\n for (const [name, group] of Object.entries(dependabotInput[\"groups\"])) {\n if (!record(group)) throw new Error(`invalid Dependabot group: ${name}`);\n groups[name] = {\n patterns: strings(group[\"patterns\"]),\n updateTypes: strings(group[\"updateTypes\"]),\n };\n }\n return {\n bun,\n formatter: parseFormatterPolicy(input[\"formatter\"]),\n typescript,\n node,\n postgres,\n valkey,\n valkeyArtifacts,\n consumerNode,\n consumerNpm,\n consumerPnpm,\n consumerTypescript,\n python,\n rust,\n packages,\n actions,\n dependabot: {\n schedule,\n cooldown: { defaultDays },\n actionGroups,\n groups,\n ignoredPackages: [\n ...new Set([\n ...Object.keys(packages),\n // The consumer package managers move only with a reviewed\n // consumerNpm or consumerPnpm change.\n \"npm\",\n \"pnpm\",\n // A repository's TypeScript install moves only with a reviewed\n // typescriptAllowlist change in stll-toolchain.json.\n \"typescript\",\n \"@typescript/native\",\n \"bun-types\",\n ]),\n ],\n ignoredActions: Object.keys(actions),\n ignoredImages: [\"node\", \"python\", \"oven/bun\"],\n },\n };\n};\n"],"mappings":"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"}
|
|
@@ -1,13 +1,51 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const require_rolldown_runtime = require("./rolldown-runtime.cjs");
|
|
4
|
-
const require_typecheck_parity = require("./typecheck-parity.cjs");
|
|
5
4
|
let node_fs_promises = require("node:fs/promises");
|
|
6
5
|
let node_path = require("node:path");
|
|
7
6
|
node_path = require_rolldown_runtime.__toESM(node_path, 1);
|
|
8
7
|
let node_child_process = require("node:child_process");
|
|
9
8
|
let node_crypto = require("node:crypto");
|
|
9
|
+
let node_util = require("node:util");
|
|
10
10
|
//#region src/typecheck-probe.ts
|
|
11
|
+
const diagnosticLocation = (file, repo) => {
|
|
12
|
+
const normalized = file.replaceAll("\\", "/");
|
|
13
|
+
const bundled = /^bundled:\/\/\/libs\/(lib\.[^/]+\.d\.ts)$/.exec(normalized);
|
|
14
|
+
const installed = /(?:^|\/)node_modules\/(?:typescript|@typescript\/(?:native|typescript-[^/]+))\/(?:.*\/)?(lib\.[^/]+\.d\.ts)$/.exec(normalized);
|
|
15
|
+
const library = bundled?.at(1) ?? installed?.at(1);
|
|
16
|
+
return library === void 0 ? (0, node_path.relative)(repo, (0, node_path.resolve)(repo, file)).replaceAll("\\", "/") : `<lib>/${library}`;
|
|
17
|
+
};
|
|
18
|
+
const globalDiagnosticKey = (code, message) => `<config>:0:${code}:${message.trim().replaceAll(/\s+/g, " ")}`;
|
|
19
|
+
/** Normalizes checker output to sorted `file:line:code` keys. */
|
|
20
|
+
const diagnosticSet = (output, repo) => {
|
|
21
|
+
const clean = (0, node_util.stripVTControlCharacters)(output);
|
|
22
|
+
const diagnostics = /* @__PURE__ */ new Set();
|
|
23
|
+
for (const block of clean.matchAll(/<error\b([^>]*)>([\s\S]*?)<\/error>/g)) {
|
|
24
|
+
const attributes = new Map([...(block.at(1) ?? "").matchAll(/(\w+)="([^"]*)"/g)].map((match) => [match.at(1), match.at(2)]));
|
|
25
|
+
const file = attributes.get("file");
|
|
26
|
+
const row = attributes.get("line");
|
|
27
|
+
const code = attributes.get("code");
|
|
28
|
+
if (code === void 0 || !/^TS\d+$/.test(code)) continue;
|
|
29
|
+
if (file !== void 0 && row !== void 0 && row !== "0") diagnostics.add(`${diagnosticLocation(file, repo)}:${row}:${code.slice(2)}`);
|
|
30
|
+
else {
|
|
31
|
+
const message = (block.at(2) ?? "").split(/<(?:source|related)\b/).at(0) ?? "";
|
|
32
|
+
diagnostics.add(globalDiagnosticKey(code.slice(2), message));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
for (const rawLine of clean.split("\n")) {
|
|
36
|
+
const line = rawLine.replace(/^(?!(?:error|warning) TS\d+:)(?:@[a-z0-9][a-z0-9._-]*\/)?[a-z0-9][a-z0-9._-]* [a-zA-Z0-9_.:-]+: /, "");
|
|
37
|
+
if (line.startsWith("<error ")) continue;
|
|
38
|
+
const match = /^(.*?)\((\d+),\d+\):\s*(?:error|warning) TS(\d+)/.exec(line) ?? /^(.*?):(\d+):\d+:\s*(?:error|warning) (?:TS)?(\d+)/.exec(line);
|
|
39
|
+
if (match) {
|
|
40
|
+
const [, file = "", row = "", code = ""] = match;
|
|
41
|
+
diagnostics.add(`${diagnosticLocation(file, repo)}:${row}:${code}`);
|
|
42
|
+
} else {
|
|
43
|
+
const global = /^(?:error|warning) TS(\d+):\s*(.*)/.exec(line);
|
|
44
|
+
if (global) diagnostics.add(globalDiagnosticKey(global.at(1) ?? "", global.at(2) ?? ""));
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return [...diagnostics].sort();
|
|
48
|
+
};
|
|
11
49
|
const runProbeCommand = ({ command, cwd, signal }) => new Promise((done, reject) => {
|
|
12
50
|
const executable = command.at(0);
|
|
13
51
|
if (executable === void 0) {
|
|
@@ -120,7 +158,7 @@ const runTypecheckProbe = async ({ repo, project, seedDirectory, command, output
|
|
|
120
158
|
}
|
|
121
159
|
const seeded = await execute();
|
|
122
160
|
if (seeded.status === null || seeded.status === 0) throw new Error(`typecheck probe expected the seeded command to fail: ${seedLocation}`);
|
|
123
|
-
if (![.../* @__PURE__ */ new Set([root, (0, node_path.dirname)(config)])].some((origin) =>
|
|
161
|
+
if (![.../* @__PURE__ */ new Set([root, (0, node_path.dirname)(config)])].some((origin) => diagnosticSet(seeded.output, origin).includes(`${(0, node_path.relative)(origin, seed).replaceAll("\\", "/")}:1:2322`))) throw new Error(`typecheck probe expected TS2322 attributed to ${seedLocation}; the declared project may exclude the seed`);
|
|
124
162
|
await removeSeed();
|
|
125
163
|
const clean = await execute();
|
|
126
164
|
if (clean.status !== 0) throw new Error(`typecheck probe clean command failed with status ${clean.status ?? "unknown"}: ${project}`);
|