@stll/oxlint-config 0.12.1 → 0.14.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/README.md +303 -6
  2. package/dist/cloud-setup-cli.cjs +6 -4
  3. package/dist/cloud-setup-cli.cjs.map +1 -1
  4. package/dist/cloud-setup-cli.mjs +3 -1
  5. package/dist/cloud-setup-cli.mjs.map +1 -1
  6. package/dist/compiler-packages.cjs +28 -0
  7. package/dist/compiler-packages.cjs.map +1 -0
  8. package/dist/compiler-packages.mjs +17 -0
  9. package/dist/compiler-packages.mjs.map +1 -0
  10. package/dist/consumer-compat-cli.cjs +1091 -0
  11. package/dist/consumer-compat-cli.cjs.map +1 -0
  12. package/dist/consumer-compat-cli.d.cts +1 -0
  13. package/dist/consumer-compat-cli.d.mts +1 -0
  14. package/dist/consumer-compat-cli.mjs +1089 -0
  15. package/dist/consumer-compat-cli.mjs.map +1 -0
  16. package/dist/publish-build-target-nuxt-helper.cjs +71 -0
  17. package/dist/publish-build-target-nuxt-helper.cjs.map +1 -0
  18. package/dist/publish-build-target-nuxt-helper.d.cts +10 -0
  19. package/dist/publish-build-target-nuxt-helper.d.mts +10 -0
  20. package/dist/publish-build-target-nuxt-helper.mjs +68 -0
  21. package/dist/publish-build-target-nuxt-helper.mjs.map +1 -0
  22. package/dist/publish-build-target-vite-dts-helper.cjs +3 -0
  23. package/dist/publish-build-target-vite-dts-helper.d.cts +24 -0
  24. package/dist/publish-build-target-vite-dts-helper.d.mts +24 -0
  25. package/dist/publish-build-target-vite-dts-helper.mjs +2 -0
  26. package/dist/publish-build-target-vite-dts-helper2.cjs +372 -0
  27. package/dist/publish-build-target-vite-dts-helper2.cjs.map +1 -0
  28. package/dist/publish-build-target-vite-dts-helper2.mjs +359 -0
  29. package/dist/publish-build-target-vite-dts-helper2.mjs.map +1 -0
  30. package/dist/publish-contract-cli.cjs +983 -0
  31. package/dist/publish-contract-cli.cjs.map +1 -0
  32. package/dist/publish-contract-cli.d.cts +1 -0
  33. package/dist/publish-contract-cli.d.mts +1 -0
  34. package/dist/publish-contract-cli.mjs +981 -0
  35. package/dist/publish-contract-cli.mjs.map +1 -0
  36. package/dist/publish-contract.cjs +431 -0
  37. package/dist/publish-contract.cjs.map +1 -0
  38. package/dist/publish-contract.mjs +396 -0
  39. package/dist/publish-contract.mjs.map +1 -0
  40. package/dist/rolldown-runtime.cjs +28 -0
  41. package/dist/toolchain-changed-cli.cjs +34 -0
  42. package/dist/toolchain-changed-cli.cjs.map +1 -0
  43. package/dist/toolchain-changed-cli.d.cts +1 -0
  44. package/dist/toolchain-changed-cli.d.mts +1 -0
  45. package/dist/toolchain-changed-cli.mjs +34 -0
  46. package/dist/toolchain-changed-cli.mjs.map +1 -0
  47. package/dist/toolchain-changed.cjs +1470 -0
  48. package/dist/toolchain-changed.cjs.map +1 -0
  49. package/dist/toolchain-changed.mjs +1463 -0
  50. package/dist/toolchain-changed.mjs.map +1 -0
  51. package/dist/toolchain-check-cli.cjs +2 -1
  52. package/dist/toolchain-check-cli.cjs.map +1 -1
  53. package/dist/toolchain-check-cli.mjs +2 -1
  54. package/dist/toolchain-check-cli.mjs.map +1 -1
  55. package/dist/toolchain-guard.cjs +551 -1166
  56. package/dist/toolchain-guard.cjs.map +1 -1
  57. package/dist/toolchain-guard.mjs +529 -1105
  58. package/dist/toolchain-guard.mjs.map +1 -1
  59. package/dist/toolchain-inputs.cjs +926 -0
  60. package/dist/toolchain-inputs.cjs.map +1 -0
  61. package/dist/toolchain-inputs.mjs +816 -0
  62. package/dist/toolchain-inputs.mjs.map +1 -0
  63. package/dist/toolchain-schema.cjs +702 -0
  64. package/dist/toolchain-schema.cjs.map +1 -0
  65. package/dist/toolchain-schema.mjs +580 -0
  66. package/dist/toolchain-schema.mjs.map +1 -0
  67. package/dist/typecheck-parity-cli.cjs +38 -898
  68. package/dist/typecheck-parity-cli.cjs.map +1 -1
  69. package/dist/typecheck-parity-cli.mjs +39 -899
  70. package/dist/typecheck-parity-cli.mjs.map +1 -1
  71. package/dist/typecheck-parity.cjs +905 -0
  72. package/dist/typecheck-parity.cjs.map +1 -0
  73. package/dist/typecheck-parity.mjs +894 -0
  74. package/dist/typecheck-parity.mjs.map +1 -0
  75. package/dist/typecheck-probe-cli.cjs +176 -0
  76. package/dist/typecheck-probe-cli.cjs.map +1 -0
  77. package/dist/typecheck-probe-cli.d.cts +1 -0
  78. package/dist/typecheck-probe-cli.d.mts +1 -0
  79. package/dist/typecheck-probe-cli.mjs +174 -0
  80. package/dist/typecheck-probe-cli.mjs.map +1 -0
  81. package/package.json +43 -5
  82. package/toolchain.json +9 -1
package/README.md CHANGED
@@ -64,15 +64,41 @@ The checkout must omit both `if` and `continue-on-error`, and its normalized
64
64
  path must be unique among every checkout in that job, including later steps.
65
65
  Unknown checkout destinations prevent mapped selectors from proving provenance.
66
66
  Sparse checkouts must explicitly list the selected repository-relative file,
67
- without the checkout prefix, in `sparse-checkout`. This applies in either cone
68
- mode and to delegated sources. Dynamic, empty, glob, negation, or unsupported
69
- sparse configurations fail; a cone-mode input alone is insufficient. Directory
70
- entries cannot substitute for the selected file.
67
+ without the checkout prefix, in `sparse-checkout`; a root-anchored entry such as
68
+ `/package.json` is accepted. This applies in either cone mode and to delegated
69
+ sources. Empty, glob, negation, or unsupported sparse configurations fail; a
70
+ cone-mode input alone is insufficient. Directory entries cannot substitute for
71
+ the selected file. A scoped Bun-source declaration can acknowledge a dynamic
72
+ sparse expression, but cannot waive a literal omission or invalid pattern,
73
+ including literal patterns mixed with expression lines or literal fragments
74
+ adjoining an expression. The deepest checkout destination containing a static selected file supplies that
75
+ file. Sparse validation checks that provider, including every writer at the same
76
+ destination, before expression acknowledgement; ancestor sparse settings do not
77
+ constrain an independent nested checkout. Checkout writes are processed in step
78
+ order: any later ancestor checkout invalidates earlier descendants, regardless of
79
+ its clean input. Checkout may clear a destination without a matching Git repository
80
+ even when clean is false. Unresolved clean values remain untrusted. Unknown
81
+ selectors remain fail closed. Mixed literal/expression sparse
82
+ configurations retain their literal paths: those paths must explicitly include a
83
+ static selected manifest. A declaration acknowledges only expression additions.
84
+ For every static manifest selector from the inspected source, the manifest pin
85
+ is validated after sparse acknowledgement, including fully dynamic sparse inputs.
71
86
  Other nonempty, nonconstant GitHub expression refs on same-repository checkouts
72
87
  (including `${{ job.workflow_repository }}`) delegate a safe static version-file selector
73
88
  to that checkout. The CLI reports delegation on stdout without validating the
74
- current source's version file. Literal refs and unpaired `${{ github.sha }}` /
75
- `${{ job.workflow_sha }}` remain rejected.
89
+ current source's version file. Current-source checkouts also accept
90
+ `${{ github.sha }}` on the same repository, except reusable `workflow_call`
91
+ workflows whose GitHub context belongs to the caller. Reusable workflows must
92
+ use the exact workflow repository/SHA pair to authorize local actions. A default
93
+ reusable-workflow checkout delegates the caller manifest just like an explicit
94
+ caller repository/SHA binding. This default applies only when the repository is
95
+ omitted or exactly `${{ github.repository }}`; a literal workflow-repository
96
+ checkout without a ref does not identify the caller snapshot. Mutable `${{ github.ref }}` bindings delegate
97
+ on every event; only the event SHA establishes the inspected snapshot. PR-head
98
+ SHA/ref expressions and their fallbacks are delegated: they cannot establish
99
+ local-action provenance or validate the inspected source's manifest. Local
100
+ actions require current-source bindings. Literal refs, foreign repositories and
101
+ unpaired `${{ job.workflow_sha }}` remain rejected.
76
102
  For snapshot-bound sources, the guard maps the selector to its tracked source
77
103
  file. Literal commit SHAs,
78
104
  branches, tags, unpaired snapshot contexts, foreign repositories, and traversal
@@ -128,6 +154,44 @@ Missing packages or jobs, private packages, absent setup-node selectors and
128
154
  floor mismatches fail configuration validation. `optOuts` is optional when
129
155
  only `engineFloors` is declared.
130
156
 
157
+ A runtime image or Bun source selected by an expression can have a scoped,
158
+ reviewed `dynamicSelectors` declaration instead of a whole-rule opt-out:
159
+
160
+ ```json
161
+ {
162
+ "dynamicSelectors": [
163
+ {
164
+ "path": ".github/workflows/example.yml",
165
+ "at": "jobs.example.services.database",
166
+ "kind": "image",
167
+ "reason": "The scoped image producer validates the selected image."
168
+ },
169
+ {
170
+ "path": ".github/workflows/example.yml",
171
+ "at": "jobs.example.steps.setup",
172
+ "kind": "bun-source",
173
+ "reason": "The manifest producer selects the owned source snapshot."
174
+ }
175
+ ]
176
+ }
177
+ ```
178
+
179
+ `at` identifies a job container (`jobs.<job>.container`), job service
180
+ (`jobs.<job>.services.<service>`), Compose image (`services.<service>.image`),
181
+ or setup step ID (`jobs.<job>.steps.<id>`; `runs.steps.<id>` in a composite
182
+ action). If a step has no ID, replace `at` with a positive `line` number
183
+ pointing at its version-file selector. Images without an ID locator (including
184
+ unresolved Dockerfile `FROM` arguments) can also use a line number. Prefer IDs so unrelated edits do not
185
+ move the declaration. Each declaration requires an exact tracked path, one
186
+ locator, a known kind and a nonempty reason. It must match exactly one unresolved
187
+ selector; missing, static or ambiguous locations fail configuration validation.
188
+ An image declaration applies only to an expression, never a literal runtime pin.
189
+ A Bun declaration acknowledges an unresolved manifest expression or same-source
190
+ dynamic checkout ambiguity; it does not verify the selected version. Foreign or
191
+ literal-ref checkouts, incorrect action pins and conditional/error-tolerant
192
+ checkouts still fail. Local-action provenance is independent of these declarations.
193
+ Review the producer named in the reason whenever the selector changes.
194
+
131
195
  Run the installed checker from the repository root in CI:
132
196
 
133
197
  ```sh
@@ -256,3 +320,236 @@ commands and repository adoption are separate configuration steps.
256
320
  Environments may cache filesystems without preserving service processes.
257
321
  Run `start` at every session start, including sessions that reuse installed files.
258
322
  The supported OS, privileges, and pinned runtime requirements are checked explicitly.
323
+
324
+ ## Published package contracts
325
+
326
+ Run `stll-publish-contract` in PR CI. Every published root or declared workspace
327
+ package commits `publish-contract.json`, recording engines, peer support ranges,
328
+ resolved JavaScript targets, and entry points. `stll-publish-contract --write`
329
+ records an explicit contract decision as a reviewable diff; it also validates
330
+ consumer support and cannot accept development-only requirements.
331
+
332
+ The consumer policy pins Node 22.23.3, npm 12.2.0, pnpm 12.9.1, and TypeScript
333
+ 6.0.3 independently of the development toolchain. Published engines and TypeScript
334
+ peers must support the consumer versions; ranges may include newer versions.
335
+ Bun runtime/compiler requirements are rejected. JSON and declaration-only packages
336
+ record `{"type":"types-only"}` explicitly.
337
+
338
+ The static guard follows the packer declared in the tracked release workflow.
339
+ With pnpm, it models `publishConfig` overrides for `exports`, `main`, `module`,
340
+ `types`, `typings`, `bin`, and `typesVersions`. npm does not apply these overrides,
341
+ so differing values fail; move the published entry into the source manifest.
342
+ `access` and `registry` are allowed publication metadata. Other overrides,
343
+ including `engines`, are rejected. Real npm and pnpm pack tests compare the
344
+ modeled contract with each tarball manifest.
345
+
346
+ Build adapters use the installed configuration loaders and bind their behavior to
347
+ tsdown 0.22.9, Vite 8.1.5, or @nuxt/module-builder 1.0.3 (unbuild 3.6.1 and
348
+ mkdist 2.4.1). They record final transform targets, including separate Nuxt module
349
+ and runtime entries. No syntax lowering records `esnext`.
350
+ Only exact single build invocations (`tsdown`, `vite build`, or
351
+ `nuxt-module-build build`) are supported. Shell composition, environment prefixes,
352
+ launchers, directory changes, workspace filters, CLI overrides, and pre/post build
353
+ lifecycle scripts fail.
354
+ Vite accepts its version-bound default plugin pipeline and the default
355
+ `@vitejs/plugin-vue` 6.0.8 factory; custom Vue compiler, template, script, and feature
356
+ options are unsupported. Nuxt accepts the version-bound builder and immutable target
357
+ marker; foreign branded callbacks are replaced with the installed canonical hook before execution. Unapproved plugins, output transforms, and execution-order changes fail. The static guard validates the supported configuration; the nightly runner validates the actual packed JavaScript. Add a reviewed adapter when adopting another build tool.
358
+
359
+ Vite libraries can generate declarations through the reviewed helper:
360
+
361
+ ```ts
362
+ import { declarationOnlyDts } from "@stll/oxlint-config/declaration-only-dts";
363
+
364
+ export default {
365
+ plugins: [
366
+ declarationOnlyDts({
367
+ directory: import.meta.dirname,
368
+ include: ["src/**/*"],
369
+ entryRoot: "src",
370
+ }),
371
+ ],
372
+ build: { target: "es2022", lib: { entry: "src/index.ts", formats: ["es"] } },
373
+ };
374
+ ```
375
+
376
+ This adapter requires consumer-installed `vite-plugin-dts` 5.0.3 and its
377
+ `unplugin-dts` 1.0.3 implementation. Its dependency scope must provide TypeScript
378
+ 6.0.3 as `typescript` or the plugin's `@typescript/typescript6` fallback.
379
+ Unsupported versions fail explicitly.
380
+ The resolver proves a direct helper import and call in a literal plugin array;
381
+ raw declaration plugins, opaque plugin arrays, and additional emitters fail.
382
+ Options are closed and static: include/exclude, entryRoot, pathsToAliases,
383
+ compilerOptions.declarationMap=false, strictOutput=true, and declarationOnly=false. Hooks may
384
+ emit only `.d.ts`, `.d.mts`, `.d.cts`, and their maps. Bundle and on-disk non-declaration
385
+ bytes must remain unchanged across each declaration hook; this is checked during
386
+ the actual build, without a comparison build.
387
+
388
+ Nuxt modules can set both emitted targets without replacing the builder's entries:
389
+
390
+ ```ts
391
+ import { nuxtModuleTarget } from "@stll/oxlint-config/build-target";
392
+
393
+ export default { hooks: { "build:before": nuxtModuleTarget("es2022") } };
394
+ ```
395
+
396
+ The Nuxt adapter recognizes the immutable marker across module formats without executing a foreign callback. It captures the normalized configuration before cleanup or output writes. The built
397
+ publish-contract CLI is also checked against a TypeScript configuration and relative
398
+ TypeScript import on the package's minimum supported Node release.
399
+
400
+ Packed-artifact checks run nightly, while the static contract check runs per PR.
401
+ Every packed `.js`, `.mjs`, and `.cjs` file is checked, including non-entry chunks
402
+ and executables. The actual packed manifest must match the committed contract.
403
+ Acorn 8.15.0 applies the strictest declared ECMAScript target (`es5`, `es2015`
404
+ through `es2025`); the provisioned consumer Node also parses every file with
405
+ `--check`, without executing artifact code. `esnext` and supported Node targets use the native consumer Node bound.
406
+ Node target identifiers follow the same grammar and compatibility rule as the
407
+ static contract; no older Node-to-ECMAScript mapping is inferred. Browser targets
408
+ are unsupported here: declare an explicit ECMAScript year. Types-only contracts reject any packed JavaScript. Nested
409
+ package manifests and explicit module extensions determine parsing mode.
410
+ Linked syntax inputs and unsafe archive paths fail before staging.
411
+
412
+ The reusable consumer job declares its exact scope in `stll-toolchain.json`:
413
+
414
+ ```json
415
+ {
416
+ "consumerChecks": [
417
+ {
418
+ "workflow": ".github/workflows/consumer-compat.yml",
419
+ "job": "consumer",
420
+ "packages": ["packages/library"],
421
+ "toolingVersion": "<installed tooling version>",
422
+ "fixturePath": "tests/consumer"
423
+ }
424
+ ]
425
+ }
426
+ ```
427
+
428
+ The reusable consumer job must be stand-alone and unconditional (no `needs`, `if`, or `strategy`), so a job condition
429
+ cannot skip its scheduled execution.
430
+ The declared workflow requires a nonempty `on.schedule` with validated five-field cron (field bounds, lists, ranges, and positive steps);
431
+ Day of week is 0–6 (SUN–SAT), matching the [GitHub Actions schedule contract](https://docs.github.com/en/actions/reference/workflows-and-actions/events-that-trigger-workflows#schedule); numeric 7 is unsupported. The combined schedules must cover every weekday with unrestricted month and date fields, so weekly or seasonal schedules cannot satisfy the daily contract. Public packages require a semver-valid version. Published workspace packages under a `vendor` directory are unsupported; the contract CLI reports them rather than omitting them. `bundleDependencies` and `bundledDependencies` are unsupported because artifact staging does not install a bundled dependency tree; remove these fields before declaring consumer checks.
432
+ `workflow_dispatch` may also be enabled. That job calls the shared
433
+ `package-consumer-compat.yml` workflow at its approved immutable policy pin, with
434
+ `packages` as the same JSON array and `consumer-node` equal to the consumer policy
435
+ pin. Required `tooling-version` and `fixture-path` inputs equal the declared exact
436
+ `toolingVersion` and repository-relative `fixturePath`; its `consumer-compat.json` must
437
+ be tracked, parse with the runner’s fixture schema, and select exactly the declared package set. Replace `<installed tooling version>` with the exact installed
438
+ `@stll/oxlint-config` release that provides the consumer runner; the guard binds the
439
+ declaration to that package version. Every named package and its transitive workspace closure must be tracked,
440
+ published, and have valid manifests. Each selected package must support that Node version.
441
+ Unknown jobs, stale entries, undeclared consumer calls, and inconsistent inputs fail.
442
+ This declaration applies to consumer checks; `engineFloors` retains its separate
443
+ minimum-supported-major contract.
444
+
445
+ `stll-consumer-compat --packages '["packages/library"]' --consumer-node 22.23.3
446
+ --fixture-path tests/consumer` tests final tarballs in isolated projects with both
447
+ npm and pnpm. The repository builds once with its development toolchain first.
448
+ The runner reads the exact packer version and pack flags from a single tracked
449
+ release workflow and packs directly with that manager. Missing, ambiguous, or
450
+ unsupported pack configuration fails. Both consumers install the same release
451
+ artifacts; the runner does not rewrite workspace or catalog protocols through a
452
+ different manager. Fixture installs disable scripts, reject reserved runtime/manager bins throughout nested lifecycle paths, then approve only directly declared dependencies at their resolved lock identities. npm rebuilds those identities; pnpm runs its built-in pending rebuild. Both use the pinned consumer runtime before typecheck, build and smoke. Undeclared transitive build scripts receive no approval. Catalog entries that resolve to a local workspace
453
+ package are unsupported: use `workspace:` for that dependency. Registry catalog declarations are staged intact; the release packer must resolve
454
+ publication protocols. pnpm workspace owners require an adjacent tracked
455
+ `package.json`; manifestless owners are unsupported. Public package names must be
456
+ canonical lowercase, URL-safe npm names (at most 214 characters), with no traversal components. The runner verifies
457
+ the official Node archive checksum and exact runtime/package-manager versions,
458
+ uses the oldest published React satisfying the package peer range and, when ReactDOM is required, its compatible renderer peer range, typechecks with
459
+ the consumer TypeScript, and runs each fixture's build and usage smoke.
460
+
461
+ The fixture directory contains `consumer-compat.json`:
462
+
463
+ ```json
464
+ {
465
+ "packages": [
466
+ {
467
+ "package": "packages/library",
468
+ "fixture": "library",
469
+ "kind": "node",
470
+ "build": ["npm", "run", "build"],
471
+ "smoke": ["npm", "run", "smoke"]
472
+ }
473
+ ]
474
+ }
475
+ ```
476
+
477
+ Each fixture is a standalone project with its own source, package manifest, and
478
+ TypeScript configuration. Use `react` for a React peer and a render smoke; use
479
+ `node` for an import and representative call. Dependency bindings, runtime tools,
480
+ and caches belong to the runner. A nightly failure must open or update one issue
481
+ in the consuming repository and use its existing failure notification.
482
+
483
+ ## Toolchain changes and typecheck probes
484
+
485
+ `stll-toolchain-changed --since <git-ref>` compares committed snapshots at the
486
+ reference and `HEAD`. Fetch the reference and its history before running it.
487
+ It prints one JSON object with `changed`, `tools`, and `status`; the detector
488
+ exits successfully even when history is unreadable, reporting `changed: true`
489
+ and `status: "unreadable"`. Use `changed` to force the full CI depth on both
490
+ pull requests and merge-queue runs. An unreadable snapshot never skips checks.
491
+
492
+ The comparison includes Bun declarations, Node selectors and support ranges,
493
+ resolved TypeScript compiler versions (including workspace and compatibility
494
+ aliases), oxlint, oxlint-tsgolint, oxfmt, and shared tooling pins. Lockfile
495
+ resolutions determine installed package versions; manifest ranges alone do not.
496
+ Resolution locations and importer bindings are retained: swapping compiler
497
+ versions between workspaces cannot look unchanged. Compiler specifier changes
498
+ run parity even when the resolved release version is unchanged. Unknown lock
499
+ shapes and ambiguous resolutions report an unreadable snapshot. Supported text
500
+ locks include Bun JSONC (schema 0/1), pnpm YAML (5.4/6/9), npm package-lock/
501
+ shrinkwrap (1/2/3), and bounded Yarn Classic/Berry shapes; a binary-only Bun lock
502
+ cannot be compared without executing Bun.
503
+ Workflow/action and Docker definition edits conservatively force full CI.
504
+ Unrelated application dependency changes do not force compiler parity.
505
+ Setup-action runtime selectors and their tracked version-file contents must
506
+ identify an exact stable release (or a dated Rust nightly). Floating selectors,
507
+ ranges, expressions, empty
508
+ values, or omitted runtime versions report an unreadable snapshot and run parity
509
+ even when their committed text is unchanged.
510
+
511
+ On pull requests, run the repository's ordinary Bun typecheck and the probe,
512
+ then select parity using the same detector:
513
+
514
+ ```sh
515
+ stll-typecheck-probe --project packages/api/tsconfig.json --seed-dir packages/api/src -- bun run typecheck
516
+ stll-typecheck-parity --changed-since origin/main --project packages/api/tsconfig.json
517
+ ```
518
+
519
+ The probe writes an exclusive temporary TypeScript file in the declared
520
+ project, requires the command to fail with TS2322 attributed to that file, removes
521
+ it, and requires the clean command to pass. Use `--seed-dir` to select a repository-relative directory inside the project;
522
+ the default is the config directory. The config must include the seed directory;
523
+ excluded seeds fail instead of producing a vacuous pass. Commands are argv,
524
+ not shell expressions. Cleanup also runs on failure and handled termination.
525
+ Repeat the probe for independently checked projects as needed.
526
+
527
+ Conditional parity runs when Bun, TypeScript, or shared declarations change;
528
+ otherwise it prints `parity skipped: toolchain unchanged since ...`. An unreadable
529
+ reference runs full parity. Nightly jobs omit `--changed-since` to run full parity.
530
+ Node and lint-tool changes still force full CI through the shared detector.
531
+
532
+ Workflow, composite-action, Docker, mise, and tool-version declarations are
533
+ conservatively fingerprinted for compiler parity, including referenced tracked
534
+ setup-action version files (Node, Bun, Python, Go, Java and other runtimes).
535
+ Rust toolchain-file selectors and conventional runtime files are included;
536
+ cache-dependency-path is not a runtime selector. Compose and Kubernetes image
537
+ definitions are conservatively fingerprinted alongside Dockerfiles. Catalog and unresolved declaration changes also force parity;
538
+ an unclassifiable reference runs full parity. This may run parity for unrelated
539
+ edits to these declaration files. Active installed compiler comparisons still
540
+ use the owning lockfile resolutions.
541
+
542
+ Compiler patch declarations, lockfile patch hashes, and their tracked patch files
543
+ are included even when the compiler version is unchanged. Compiler patch-package
544
+ files are included too. Missing referenced compiler patches fail closed; unrelated
545
+ package patches do not trigger compiler parity.
546
+
547
+ Compiler manifest specifiers and complete compiler lock entries form part of the
548
+ change identity, including resolved URLs, integrity, commits, checksums and patch
549
+ hashes. Changing a source at the same release version runs parity. Local compiler
550
+ sources without an immutable byte identity fail closed; a version alone does not
551
+ identify a local directory. Git compiler sources require a full commit identity.
552
+ Supported text locks include Bun, npm, pnpm and bounded
553
+ Yarn Classic/Berry shapes; unrecognized lock shapes run parity. Yarn compiler
554
+ `patch:` protocols are unsupported and run parity because their patch bytes are
555
+ not represented by the lock checksum alone.
@@ -1,6 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const require_toolchain_inputs = require("./toolchain-inputs.cjs");
3
4
  const require_toolchain_guard = require("./toolchain-guard.cjs");
5
+ const require_toolchain_schema = require("./toolchain-schema.cjs");
4
6
  let node_fs = require("node:fs");
5
7
  let node_path = require("node:path");
6
8
  let node_fs_promises = require("node:fs/promises");
@@ -30,12 +32,12 @@ const main = async () => {
30
32
  if (cloud === void 0) throw new Error("requires an explicit cloud declaration");
31
33
  const nodeVersion = files[".node-version"];
32
34
  if (nodeVersion === void 0) throw new Error("requires tracked root .node-version");
33
- const script = require_toolchain_guard.generateCloudSetup({
34
- policy: require_toolchain_guard.parseToolchainPolicy(JSON.parse(await (0, node_fs_promises.readFile)(new URL("../toolchain.json", require("url").pathToFileURL(__filename).href), "utf8"))),
35
+ const script = require_toolchain_inputs.generateCloudSetup({
36
+ policy: require_toolchain_schema.parseToolchainPolicy(JSON.parse(await (0, node_fs_promises.readFile)(new URL("../toolchain.json", require("url").pathToFileURL(__filename).href), "utf8"))),
35
37
  cloud,
36
38
  nodeVersion: nodeVersion.trim()
37
39
  });
38
- const destination = (0, node_path.join)(root, require_toolchain_guard.cloudSetupPath);
40
+ const destination = (0, node_path.join)(root, require_toolchain_inputs.cloudSetupPath);
39
41
  const parent = (0, node_path.dirname)(destination);
40
42
  const parentStat = await optionalStat(parent);
41
43
  if (parentStat === void 0) await (0, node_fs_promises.mkdir)(parent);
@@ -52,7 +54,7 @@ const main = async () => {
52
54
  } finally {
53
55
  await output.close();
54
56
  }
55
- process.stdout.write(`Generated ${require_toolchain_guard.cloudSetupPath}\n`);
57
+ process.stdout.write(`Generated ${require_toolchain_inputs.cloudSetupPath}\n`);
56
58
  };
57
59
  main().catch((error) => {
58
60
  process.stderr.write(`cloud-setup: ${error instanceof Error ? error.message : String(error)}\n`);
@@ -1 +1 @@
1
- {"version":3,"file":"cloud-setup-cli.cjs","names":["readToolchainInputs","parseToolchainConfiguration","generateCloudSetup","parseToolchainPolicy","cloudSetupPath","constants"],"sources":["../src/cloud-setup-cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { constants } from \"node:fs\";\nimport { lstat, mkdir, open, readFile, realpath } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\n\nimport { cloudSetupPath, generateCloudSetup } from \"./cloud-setup\";\nimport {\n parseToolchainConfiguration,\n readToolchainInputs,\n} from \"./toolchain-guard\";\nimport { parseToolchainPolicy } from \"./toolchain-schema\";\n\nconst usage =\n \"Usage: stll-cloud-setup (run from repository root)\\n stll-cloud-setup --help\";\nconst optionalStat = async (path: string) => {\n try {\n return await lstat(path);\n } catch (error) {\n if (error instanceof Error && \"code\" in error && error.code === \"ENOENT\")\n return undefined;\n throw error;\n }\n};\n\nconst main = async () => {\n const args = process.argv.slice(2);\n if (args.length === 1 && args.at(0) === \"--help\") {\n process.stdout.write(`${usage}\\n`);\n return;\n }\n if (args.length !== 0) throw new Error(usage);\n const root = await realpath(process.cwd());\n const { files, diagnostics } = readToolchainInputs(root);\n if (diagnostics.length > 0)\n throw new Error(\n diagnostics.map(({ path, message }) => `${path}: ${message}`).join(\"\\n\"),\n );\n const text = files[\"stll-toolchain.json\"];\n if (text === undefined)\n throw new Error(\"requires tracked stll-toolchain.json\");\n const { cloud } = parseToolchainConfiguration(JSON.parse(text));\n if (cloud === undefined)\n throw new Error(\"requires an explicit cloud declaration\");\n const nodeVersion = files[\".node-version\"];\n if (nodeVersion === undefined)\n throw new Error(\"requires tracked root .node-version\");\n const policy = parseToolchainPolicy(\n JSON.parse(\n await readFile(new URL(\"../toolchain.json\", import.meta.url), \"utf8\"),\n ),\n );\n const script = generateCloudSetup({\n policy,\n cloud,\n nodeVersion: nodeVersion.trim(),\n });\n const destination = join(root, cloudSetupPath);\n const parent = dirname(destination);\n const parentStat = await optionalStat(parent);\n if (parentStat === undefined) await mkdir(parent);\n else if (parentStat.isSymbolicLink() || !parentStat.isDirectory())\n throw new Error(\"cloud setup parent must be a real repository directory\");\n const destinationStat = await optionalStat(destination);\n if (\n destinationStat !== undefined &&\n (destinationStat.isSymbolicLink() ||\n !destinationStat.isFile() ||\n destinationStat.nlink !== 1)\n )\n throw new Error(\n \"cloud setup destination must be a single-link regular repository file\",\n );\n const output = await open(\n destination,\n constants.O_WRONLY | constants.O_CREAT | constants.O_NOFOLLOW,\n 0o755,\n );\n try {\n const opened = await output.stat();\n if (!opened.isFile() || opened.nlink !== 1)\n throw new Error(\n \"cloud setup destination must be a single-link regular repository file\",\n );\n await output.truncate(0);\n await output.writeFile(script, \"utf8\");\n await output.chmod(0o755);\n } finally {\n await output.close();\n }\n process.stdout.write(`Generated ${cloudSetupPath}\\n`);\n};\n\nmain().catch((error: unknown) => {\n process.stderr.write(\n `cloud-setup: ${error instanceof Error ? error.message : String(error)}\\n`,\n );\n process.exitCode = 1;\n});\n"],"mappings":";;;;;;;AAYA,MAAM,QACJ;AACF,MAAM,eAAe,OAAO,SAAiB;CAC3C,IAAI;EACF,OAAO,OAAA,GAAA,iBAAA,MAAA,CAAY,IAAI;CACzB,SAAS,OAAO;EACd,IAAI,iBAAiB,SAAS,UAAU,SAAS,MAAM,SAAS,UAC9D,OAAO,KAAA;EACT,MAAM;CACR;AACF;AAEA,MAAM,OAAO,YAAY;CACvB,MAAM,OAAO,QAAQ,KAAK,MAAM,CAAC;CACjC,IAAI,KAAK,WAAW,KAAK,KAAK,GAAG,CAAC,MAAM,UAAU;EAChD,QAAQ,OAAO,MAAM,GAAG,MAAM,GAAG;EACjC;CACF;CACA,IAAI,KAAK,WAAW,GAAG,MAAM,IAAI,MAAM,KAAK;CAC5C,MAAM,OAAO,OAAA,GAAA,iBAAA,SAAA,CAAe,QAAQ,IAAI,CAAC;CACzC,MAAM,EAAE,OAAO,gBAAgBA,wBAAAA,oBAAoB,IAAI;CACvD,IAAI,YAAY,SAAS,GACvB,MAAM,IAAI,MACR,YAAY,KAAK,EAAE,MAAM,cAAc,GAAG,KAAK,IAAI,SAAS,CAAC,CAAC,KAAK,IAAI,CACzE;CACF,MAAM,OAAO,MAAM;CACnB,IAAI,SAAS,KAAA,GACX,MAAM,IAAI,MAAM,sCAAsC;CACxD,MAAM,EAAE,UAAUC,wBAAAA,4BAA4B,KAAK,MAAM,IAAI,CAAC;CAC9D,IAAI,UAAU,KAAA,GACZ,MAAM,IAAI,MAAM,wCAAwC;CAC1D,MAAM,cAAc,MAAM;CAC1B,IAAI,gBAAgB,KAAA,GAClB,MAAM,IAAI,MAAM,qCAAqC;CAMvD,MAAM,SAASC,wBAAAA,mBAAmB;EAChC,QANaC,wBAAAA,qBACb,KAAK,MACH,OAAA,GAAA,iBAAA,SAAA,CAAe,IAAI,IAAI,qBAAA,QAAA,KAAA,CAAA,CAAA,cAAA,UAAA,CAAA,CAAA,IAAoC,GAAG,MAAM,CACtE,CAGK;EACL;EACA,aAAa,YAAY,KAAK;CAChC,CAAC;CACD,MAAM,eAAA,GAAA,UAAA,KAAA,CAAmB,MAAMC,wBAAAA,cAAc;CAC7C,MAAM,UAAA,GAAA,UAAA,QAAA,CAAiB,WAAW;CAClC,MAAM,aAAa,MAAM,aAAa,MAAM;CAC5C,IAAI,eAAe,KAAA,GAAW,OAAA,GAAA,iBAAA,MAAA,CAAY,MAAM;MAC3C,IAAI,WAAW,eAAe,KAAK,CAAC,WAAW,YAAY,GAC9D,MAAM,IAAI,MAAM,wDAAwD;CAC1E,MAAM,kBAAkB,MAAM,aAAa,WAAW;CACtD,IACE,oBAAoB,KAAA,MACnB,gBAAgB,eAAe,KAC9B,CAAC,gBAAgB,OAAO,KACxB,gBAAgB,UAAU,IAE5B,MAAM,IAAI,MACR,uEACF;CACF,MAAM,SAAS,OAAA,GAAA,iBAAA,KAAA,CACb,aACAC,QAAAA,UAAU,WAAWA,QAAAA,UAAU,UAAUA,QAAAA,UAAU,YACnD,GACF;CACA,IAAI;EACF,MAAM,SAAS,MAAM,OAAO,KAAK;EACjC,IAAI,CAAC,OAAO,OAAO,KAAK,OAAO,UAAU,GACvC,MAAM,IAAI,MACR,uEACF;EACF,MAAM,OAAO,SAAS,CAAC;EACvB,MAAM,OAAO,UAAU,QAAQ,MAAM;EACrC,MAAM,OAAO,MAAM,GAAK;CAC1B,UAAU;EACR,MAAM,OAAO,MAAM;CACrB;CACA,QAAQ,OAAO,MAAM,aAAaD,wBAAAA,eAAe,GAAG;AACtD;AAEA,KAAK,CAAC,CAAC,OAAO,UAAmB;CAC/B,QAAQ,OAAO,MACb,gBAAgB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,EAAE,GACzE;CACA,QAAQ,WAAW;AACrB,CAAC"}
1
+ {"version":3,"file":"cloud-setup-cli.cjs","names":["readToolchainInputs","parseToolchainConfiguration","generateCloudSetup","parseToolchainPolicy","cloudSetupPath","constants"],"sources":["../src/cloud-setup-cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { constants } from \"node:fs\";\nimport { lstat, mkdir, open, readFile, realpath } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\n\nimport { cloudSetupPath, generateCloudSetup } from \"./cloud-setup\";\nimport {\n parseToolchainConfiguration,\n readToolchainInputs,\n} from \"./toolchain-guard\";\nimport { parseToolchainPolicy } from \"./toolchain-schema\";\n\nconst usage =\n \"Usage: stll-cloud-setup (run from repository root)\\n stll-cloud-setup --help\";\nconst optionalStat = async (path: string) => {\n try {\n return await lstat(path);\n } catch (error) {\n if (error instanceof Error && \"code\" in error && error.code === \"ENOENT\")\n return undefined;\n throw error;\n }\n};\n\nconst main = async () => {\n const args = process.argv.slice(2);\n if (args.length === 1 && args.at(0) === \"--help\") {\n process.stdout.write(`${usage}\\n`);\n return;\n }\n if (args.length !== 0) throw new Error(usage);\n const root = await realpath(process.cwd());\n const { files, diagnostics } = readToolchainInputs(root);\n if (diagnostics.length > 0)\n throw new Error(\n diagnostics.map(({ path, message }) => `${path}: ${message}`).join(\"\\n\"),\n );\n const text = files[\"stll-toolchain.json\"];\n if (text === undefined)\n throw new Error(\"requires tracked stll-toolchain.json\");\n const { cloud } = parseToolchainConfiguration(JSON.parse(text));\n if (cloud === undefined)\n throw new Error(\"requires an explicit cloud declaration\");\n const nodeVersion = files[\".node-version\"];\n if (nodeVersion === undefined)\n throw new Error(\"requires tracked root .node-version\");\n const policy = parseToolchainPolicy(\n JSON.parse(\n await readFile(new URL(\"../toolchain.json\", import.meta.url), \"utf8\"),\n ),\n );\n const script = generateCloudSetup({\n policy,\n cloud,\n nodeVersion: nodeVersion.trim(),\n });\n const destination = join(root, cloudSetupPath);\n const parent = dirname(destination);\n const parentStat = await optionalStat(parent);\n if (parentStat === undefined) await mkdir(parent);\n else if (parentStat.isSymbolicLink() || !parentStat.isDirectory())\n throw new Error(\"cloud setup parent must be a real repository directory\");\n const destinationStat = await optionalStat(destination);\n if (\n destinationStat !== undefined &&\n (destinationStat.isSymbolicLink() ||\n !destinationStat.isFile() ||\n destinationStat.nlink !== 1)\n )\n throw new Error(\n \"cloud setup destination must be a single-link regular repository file\",\n );\n const output = await open(\n destination,\n constants.O_WRONLY | constants.O_CREAT | constants.O_NOFOLLOW,\n 0o755,\n );\n try {\n const opened = await output.stat();\n if (!opened.isFile() || opened.nlink !== 1)\n throw new Error(\n \"cloud setup destination must be a single-link regular repository file\",\n );\n await output.truncate(0);\n await output.writeFile(script, \"utf8\");\n await output.chmod(0o755);\n } finally {\n await output.close();\n }\n process.stdout.write(`Generated ${cloudSetupPath}\\n`);\n};\n\nmain().catch((error: unknown) => {\n process.stderr.write(\n `cloud-setup: ${error instanceof Error ? error.message : String(error)}\\n`,\n );\n process.exitCode = 1;\n});\n"],"mappings":";;;;;;;;;AAYA,MAAM,QACJ;AACF,MAAM,eAAe,OAAO,SAAiB;CAC3C,IAAI;EACF,OAAO,OAAA,GAAA,iBAAA,MAAA,CAAY,IAAI;CACzB,SAAS,OAAO;EACd,IAAI,iBAAiB,SAAS,UAAU,SAAS,MAAM,SAAS,UAC9D,OAAO,KAAA;EACT,MAAM;CACR;AACF;AAEA,MAAM,OAAO,YAAY;CACvB,MAAM,OAAO,QAAQ,KAAK,MAAM,CAAC;CACjC,IAAI,KAAK,WAAW,KAAK,KAAK,GAAG,CAAC,MAAM,UAAU;EAChD,QAAQ,OAAO,MAAM,GAAG,MAAM,GAAG;EACjC;CACF;CACA,IAAI,KAAK,WAAW,GAAG,MAAM,IAAI,MAAM,KAAK;CAC5C,MAAM,OAAO,OAAA,GAAA,iBAAA,SAAA,CAAe,QAAQ,IAAI,CAAC;CACzC,MAAM,EAAE,OAAO,gBAAgBA,wBAAAA,oBAAoB,IAAI;CACvD,IAAI,YAAY,SAAS,GACvB,MAAM,IAAI,MACR,YAAY,KAAK,EAAE,MAAM,cAAc,GAAG,KAAK,IAAI,SAAS,CAAC,CAAC,KAAK,IAAI,CACzE;CACF,MAAM,OAAO,MAAM;CACnB,IAAI,SAAS,KAAA,GACX,MAAM,IAAI,MAAM,sCAAsC;CACxD,MAAM,EAAE,UAAUC,wBAAAA,4BAA4B,KAAK,MAAM,IAAI,CAAC;CAC9D,IAAI,UAAU,KAAA,GACZ,MAAM,IAAI,MAAM,wCAAwC;CAC1D,MAAM,cAAc,MAAM;CAC1B,IAAI,gBAAgB,KAAA,GAClB,MAAM,IAAI,MAAM,qCAAqC;CAMvD,MAAM,SAASC,yBAAAA,mBAAmB;EAChC,QANaC,yBAAAA,qBACb,KAAK,MACH,OAAA,GAAA,iBAAA,SAAA,CAAe,IAAI,IAAI,qBAAA,QAAA,KAAA,CAAA,CAAA,cAAA,UAAA,CAAA,CAAA,IAAoC,GAAG,MAAM,CACtE,CAGK;EACL;EACA,aAAa,YAAY,KAAK;CAChC,CAAC;CACD,MAAM,eAAA,GAAA,UAAA,KAAA,CAAmB,MAAMC,yBAAAA,cAAc;CAC7C,MAAM,UAAA,GAAA,UAAA,QAAA,CAAiB,WAAW;CAClC,MAAM,aAAa,MAAM,aAAa,MAAM;CAC5C,IAAI,eAAe,KAAA,GAAW,OAAA,GAAA,iBAAA,MAAA,CAAY,MAAM;MAC3C,IAAI,WAAW,eAAe,KAAK,CAAC,WAAW,YAAY,GAC9D,MAAM,IAAI,MAAM,wDAAwD;CAC1E,MAAM,kBAAkB,MAAM,aAAa,WAAW;CACtD,IACE,oBAAoB,KAAA,MACnB,gBAAgB,eAAe,KAC9B,CAAC,gBAAgB,OAAO,KACxB,gBAAgB,UAAU,IAE5B,MAAM,IAAI,MACR,uEACF;CACF,MAAM,SAAS,OAAA,GAAA,iBAAA,KAAA,CACb,aACAC,QAAAA,UAAU,WAAWA,QAAAA,UAAU,UAAUA,QAAAA,UAAU,YACnD,GACF;CACA,IAAI;EACF,MAAM,SAAS,MAAM,OAAO,KAAK;EACjC,IAAI,CAAC,OAAO,OAAO,KAAK,OAAO,UAAU,GACvC,MAAM,IAAI,MACR,uEACF;EACF,MAAM,OAAO,SAAS,CAAC;EACvB,MAAM,OAAO,UAAU,QAAQ,MAAM;EACrC,MAAM,OAAO,MAAM,GAAK;CAC1B,UAAU;EACR,MAAM,OAAO,MAAM;CACrB;CACA,QAAQ,OAAO,MAAM,aAAaD,yBAAAA,eAAe,GAAG;AACtD;AAEA,KAAK,CAAC,CAAC,OAAO,UAAmB;CAC/B,QAAQ,OAAO,MACb,gBAAgB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,EAAE,GACzE;CACA,QAAQ,WAAW;AACrB,CAAC"}
@@ -1,5 +1,7 @@
1
1
  #!/usr/bin/env node
2
- import { a as cloudSetupPath, i as parseToolchainPolicy, n as parseToolchainConfiguration, o as generateCloudSetup, r as readToolchainInputs } from "./toolchain-guard.mjs";
2
+ import { m as generateCloudSetup, p as cloudSetupPath } from "./toolchain-inputs.mjs";
3
+ import { n as parseToolchainConfiguration, r as readToolchainInputs } from "./toolchain-guard.mjs";
4
+ import { t as parseToolchainPolicy } from "./toolchain-schema.mjs";
3
5
  import { constants } from "node:fs";
4
6
  import { dirname, join } from "node:path";
5
7
  import { lstat, mkdir, open, readFile, realpath } from "node:fs/promises";
@@ -1 +1 @@
1
- {"version":3,"file":"cloud-setup-cli.mjs","names":[],"sources":["../src/cloud-setup-cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { constants } from \"node:fs\";\nimport { lstat, mkdir, open, readFile, realpath } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\n\nimport { cloudSetupPath, generateCloudSetup } from \"./cloud-setup\";\nimport {\n parseToolchainConfiguration,\n readToolchainInputs,\n} from \"./toolchain-guard\";\nimport { parseToolchainPolicy } from \"./toolchain-schema\";\n\nconst usage =\n \"Usage: stll-cloud-setup (run from repository root)\\n stll-cloud-setup --help\";\nconst optionalStat = async (path: string) => {\n try {\n return await lstat(path);\n } catch (error) {\n if (error instanceof Error && \"code\" in error && error.code === \"ENOENT\")\n return undefined;\n throw error;\n }\n};\n\nconst main = async () => {\n const args = process.argv.slice(2);\n if (args.length === 1 && args.at(0) === \"--help\") {\n process.stdout.write(`${usage}\\n`);\n return;\n }\n if (args.length !== 0) throw new Error(usage);\n const root = await realpath(process.cwd());\n const { files, diagnostics } = readToolchainInputs(root);\n if (diagnostics.length > 0)\n throw new Error(\n diagnostics.map(({ path, message }) => `${path}: ${message}`).join(\"\\n\"),\n );\n const text = files[\"stll-toolchain.json\"];\n if (text === undefined)\n throw new Error(\"requires tracked stll-toolchain.json\");\n const { cloud } = parseToolchainConfiguration(JSON.parse(text));\n if (cloud === undefined)\n throw new Error(\"requires an explicit cloud declaration\");\n const nodeVersion = files[\".node-version\"];\n if (nodeVersion === undefined)\n throw new Error(\"requires tracked root .node-version\");\n const policy = parseToolchainPolicy(\n JSON.parse(\n await readFile(new URL(\"../toolchain.json\", import.meta.url), \"utf8\"),\n ),\n );\n const script = generateCloudSetup({\n policy,\n cloud,\n nodeVersion: nodeVersion.trim(),\n });\n const destination = join(root, cloudSetupPath);\n const parent = dirname(destination);\n const parentStat = await optionalStat(parent);\n if (parentStat === undefined) await mkdir(parent);\n else if (parentStat.isSymbolicLink() || !parentStat.isDirectory())\n throw new Error(\"cloud setup parent must be a real repository directory\");\n const destinationStat = await optionalStat(destination);\n if (\n destinationStat !== undefined &&\n (destinationStat.isSymbolicLink() ||\n !destinationStat.isFile() ||\n destinationStat.nlink !== 1)\n )\n throw new Error(\n \"cloud setup destination must be a single-link regular repository file\",\n );\n const output = await open(\n destination,\n constants.O_WRONLY | constants.O_CREAT | constants.O_NOFOLLOW,\n 0o755,\n );\n try {\n const opened = await output.stat();\n if (!opened.isFile() || opened.nlink !== 1)\n throw new Error(\n \"cloud setup destination must be a single-link regular repository file\",\n );\n await output.truncate(0);\n await output.writeFile(script, \"utf8\");\n await output.chmod(0o755);\n } finally {\n await output.close();\n }\n process.stdout.write(`Generated ${cloudSetupPath}\\n`);\n};\n\nmain().catch((error: unknown) => {\n process.stderr.write(\n `cloud-setup: ${error instanceof Error ? error.message : String(error)}\\n`,\n );\n process.exitCode = 1;\n});\n"],"mappings":";;;;;;AAYA,MAAM,QACJ;AACF,MAAM,eAAe,OAAO,SAAiB;CAC3C,IAAI;EACF,OAAO,MAAM,MAAM,IAAI;CACzB,SAAS,OAAO;EACd,IAAI,iBAAiB,SAAS,UAAU,SAAS,MAAM,SAAS,UAC9D,OAAO,KAAA;EACT,MAAM;CACR;AACF;AAEA,MAAM,OAAO,YAAY;CACvB,MAAM,OAAO,QAAQ,KAAK,MAAM,CAAC;CACjC,IAAI,KAAK,WAAW,KAAK,KAAK,GAAG,CAAC,MAAM,UAAU;EAChD,QAAQ,OAAO,MAAM,GAAG,MAAM,GAAG;EACjC;CACF;CACA,IAAI,KAAK,WAAW,GAAG,MAAM,IAAI,MAAM,KAAK;CAC5C,MAAM,OAAO,MAAM,SAAS,QAAQ,IAAI,CAAC;CACzC,MAAM,EAAE,OAAO,gBAAgB,oBAAoB,IAAI;CACvD,IAAI,YAAY,SAAS,GACvB,MAAM,IAAI,MACR,YAAY,KAAK,EAAE,MAAM,cAAc,GAAG,KAAK,IAAI,SAAS,CAAC,CAAC,KAAK,IAAI,CACzE;CACF,MAAM,OAAO,MAAM;CACnB,IAAI,SAAS,KAAA,GACX,MAAM,IAAI,MAAM,sCAAsC;CACxD,MAAM,EAAE,UAAU,4BAA4B,KAAK,MAAM,IAAI,CAAC;CAC9D,IAAI,UAAU,KAAA,GACZ,MAAM,IAAI,MAAM,wCAAwC;CAC1D,MAAM,cAAc,MAAM;CAC1B,IAAI,gBAAgB,KAAA,GAClB,MAAM,IAAI,MAAM,qCAAqC;CAMvD,MAAM,SAAS,mBAAmB;EAChC,QANa,qBACb,KAAK,MACH,MAAM,SAAS,IAAI,IAAI,qBAAqB,OAAO,KAAK,GAAG,GAAG,MAAM,CACtE,CAGK;EACL;EACA,aAAa,YAAY,KAAK;CAChC,CAAC;CACD,MAAM,cAAc,KAAK,MAAM,cAAc;CAC7C,MAAM,SAAS,QAAQ,WAAW;CAClC,MAAM,aAAa,MAAM,aAAa,MAAM;CAC5C,IAAI,eAAe,KAAA,GAAW,MAAM,MAAM,MAAM;MAC3C,IAAI,WAAW,eAAe,KAAK,CAAC,WAAW,YAAY,GAC9D,MAAM,IAAI,MAAM,wDAAwD;CAC1E,MAAM,kBAAkB,MAAM,aAAa,WAAW;CACtD,IACE,oBAAoB,KAAA,MACnB,gBAAgB,eAAe,KAC9B,CAAC,gBAAgB,OAAO,KACxB,gBAAgB,UAAU,IAE5B,MAAM,IAAI,MACR,uEACF;CACF,MAAM,SAAS,MAAM,KACnB,aACA,UAAU,WAAW,UAAU,UAAU,UAAU,YACnD,GACF;CACA,IAAI;EACF,MAAM,SAAS,MAAM,OAAO,KAAK;EACjC,IAAI,CAAC,OAAO,OAAO,KAAK,OAAO,UAAU,GACvC,MAAM,IAAI,MACR,uEACF;EACF,MAAM,OAAO,SAAS,CAAC;EACvB,MAAM,OAAO,UAAU,QAAQ,MAAM;EACrC,MAAM,OAAO,MAAM,GAAK;CAC1B,UAAU;EACR,MAAM,OAAO,MAAM;CACrB;CACA,QAAQ,OAAO,MAAM,aAAa,eAAe,GAAG;AACtD;AAEA,KAAK,CAAC,CAAC,OAAO,UAAmB;CAC/B,QAAQ,OAAO,MACb,gBAAgB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,EAAE,GACzE;CACA,QAAQ,WAAW;AACrB,CAAC"}
1
+ {"version":3,"file":"cloud-setup-cli.mjs","names":[],"sources":["../src/cloud-setup-cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { constants } from \"node:fs\";\nimport { lstat, mkdir, open, readFile, realpath } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\n\nimport { cloudSetupPath, generateCloudSetup } from \"./cloud-setup\";\nimport {\n parseToolchainConfiguration,\n readToolchainInputs,\n} from \"./toolchain-guard\";\nimport { parseToolchainPolicy } from \"./toolchain-schema\";\n\nconst usage =\n \"Usage: stll-cloud-setup (run from repository root)\\n stll-cloud-setup --help\";\nconst optionalStat = async (path: string) => {\n try {\n return await lstat(path);\n } catch (error) {\n if (error instanceof Error && \"code\" in error && error.code === \"ENOENT\")\n return undefined;\n throw error;\n }\n};\n\nconst main = async () => {\n const args = process.argv.slice(2);\n if (args.length === 1 && args.at(0) === \"--help\") {\n process.stdout.write(`${usage}\\n`);\n return;\n }\n if (args.length !== 0) throw new Error(usage);\n const root = await realpath(process.cwd());\n const { files, diagnostics } = readToolchainInputs(root);\n if (diagnostics.length > 0)\n throw new Error(\n diagnostics.map(({ path, message }) => `${path}: ${message}`).join(\"\\n\"),\n );\n const text = files[\"stll-toolchain.json\"];\n if (text === undefined)\n throw new Error(\"requires tracked stll-toolchain.json\");\n const { cloud } = parseToolchainConfiguration(JSON.parse(text));\n if (cloud === undefined)\n throw new Error(\"requires an explicit cloud declaration\");\n const nodeVersion = files[\".node-version\"];\n if (nodeVersion === undefined)\n throw new Error(\"requires tracked root .node-version\");\n const policy = parseToolchainPolicy(\n JSON.parse(\n await readFile(new URL(\"../toolchain.json\", import.meta.url), \"utf8\"),\n ),\n );\n const script = generateCloudSetup({\n policy,\n cloud,\n nodeVersion: nodeVersion.trim(),\n });\n const destination = join(root, cloudSetupPath);\n const parent = dirname(destination);\n const parentStat = await optionalStat(parent);\n if (parentStat === undefined) await mkdir(parent);\n else if (parentStat.isSymbolicLink() || !parentStat.isDirectory())\n throw new Error(\"cloud setup parent must be a real repository directory\");\n const destinationStat = await optionalStat(destination);\n if (\n destinationStat !== undefined &&\n (destinationStat.isSymbolicLink() ||\n !destinationStat.isFile() ||\n destinationStat.nlink !== 1)\n )\n throw new Error(\n \"cloud setup destination must be a single-link regular repository file\",\n );\n const output = await open(\n destination,\n constants.O_WRONLY | constants.O_CREAT | constants.O_NOFOLLOW,\n 0o755,\n );\n try {\n const opened = await output.stat();\n if (!opened.isFile() || opened.nlink !== 1)\n throw new Error(\n \"cloud setup destination must be a single-link regular repository file\",\n );\n await output.truncate(0);\n await output.writeFile(script, \"utf8\");\n await output.chmod(0o755);\n } finally {\n await output.close();\n }\n process.stdout.write(`Generated ${cloudSetupPath}\\n`);\n};\n\nmain().catch((error: unknown) => {\n process.stderr.write(\n `cloud-setup: ${error instanceof Error ? error.message : String(error)}\\n`,\n );\n process.exitCode = 1;\n});\n"],"mappings":";;;;;;;;AAYA,MAAM,QACJ;AACF,MAAM,eAAe,OAAO,SAAiB;CAC3C,IAAI;EACF,OAAO,MAAM,MAAM,IAAI;CACzB,SAAS,OAAO;EACd,IAAI,iBAAiB,SAAS,UAAU,SAAS,MAAM,SAAS,UAC9D,OAAO,KAAA;EACT,MAAM;CACR;AACF;AAEA,MAAM,OAAO,YAAY;CACvB,MAAM,OAAO,QAAQ,KAAK,MAAM,CAAC;CACjC,IAAI,KAAK,WAAW,KAAK,KAAK,GAAG,CAAC,MAAM,UAAU;EAChD,QAAQ,OAAO,MAAM,GAAG,MAAM,GAAG;EACjC;CACF;CACA,IAAI,KAAK,WAAW,GAAG,MAAM,IAAI,MAAM,KAAK;CAC5C,MAAM,OAAO,MAAM,SAAS,QAAQ,IAAI,CAAC;CACzC,MAAM,EAAE,OAAO,gBAAgB,oBAAoB,IAAI;CACvD,IAAI,YAAY,SAAS,GACvB,MAAM,IAAI,MACR,YAAY,KAAK,EAAE,MAAM,cAAc,GAAG,KAAK,IAAI,SAAS,CAAC,CAAC,KAAK,IAAI,CACzE;CACF,MAAM,OAAO,MAAM;CACnB,IAAI,SAAS,KAAA,GACX,MAAM,IAAI,MAAM,sCAAsC;CACxD,MAAM,EAAE,UAAU,4BAA4B,KAAK,MAAM,IAAI,CAAC;CAC9D,IAAI,UAAU,KAAA,GACZ,MAAM,IAAI,MAAM,wCAAwC;CAC1D,MAAM,cAAc,MAAM;CAC1B,IAAI,gBAAgB,KAAA,GAClB,MAAM,IAAI,MAAM,qCAAqC;CAMvD,MAAM,SAAS,mBAAmB;EAChC,QANa,qBACb,KAAK,MACH,MAAM,SAAS,IAAI,IAAI,qBAAqB,OAAO,KAAK,GAAG,GAAG,MAAM,CACtE,CAGK;EACL;EACA,aAAa,YAAY,KAAK;CAChC,CAAC;CACD,MAAM,cAAc,KAAK,MAAM,cAAc;CAC7C,MAAM,SAAS,QAAQ,WAAW;CAClC,MAAM,aAAa,MAAM,aAAa,MAAM;CAC5C,IAAI,eAAe,KAAA,GAAW,MAAM,MAAM,MAAM;MAC3C,IAAI,WAAW,eAAe,KAAK,CAAC,WAAW,YAAY,GAC9D,MAAM,IAAI,MAAM,wDAAwD;CAC1E,MAAM,kBAAkB,MAAM,aAAa,WAAW;CACtD,IACE,oBAAoB,KAAA,MACnB,gBAAgB,eAAe,KAC9B,CAAC,gBAAgB,OAAO,KACxB,gBAAgB,UAAU,IAE5B,MAAM,IAAI,MACR,uEACF;CACF,MAAM,SAAS,MAAM,KACnB,aACA,UAAU,WAAW,UAAU,UAAU,UAAU,YACnD,GACF;CACA,IAAI;EACF,MAAM,SAAS,MAAM,OAAO,KAAK;EACjC,IAAI,CAAC,OAAO,OAAO,KAAK,OAAO,UAAU,GACvC,MAAM,IAAI,MACR,uEACF;EACF,MAAM,OAAO,SAAS,CAAC;EACvB,MAAM,OAAO,UAAU,QAAQ,MAAM;EACrC,MAAM,OAAO,MAAM,GAAK;CAC1B,UAAU;EACR,MAAM,OAAO,MAAM;CACrB;CACA,QAAQ,OAAO,MAAM,aAAa,eAAe,GAAG;AACtD;AAEA,KAAK,CAAC,CAAC,OAAO,UAAmB;CAC/B,QAAQ,OAAO,MACb,gBAAgB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,EAAE,GACzE;CACA,QAAQ,WAAW;AACrB,CAAC"}
@@ -0,0 +1,28 @@
1
+ //#region src/compiler-packages.ts
2
+ const compilerPackages = {
3
+ typescript: "typescript",
4
+ typescriptCompatibility: "@typescript/typescript6",
5
+ native: "@typescript/native",
6
+ nativePreview: "@typescript/native-preview",
7
+ typescriptCompatibilityAlias: "typescript-compat",
8
+ bunTypes: "bun-types",
9
+ typesBun: "@types/bun",
10
+ tsgo: "tsgo",
11
+ typescriptTsgo: "@typescript/tsgo"
12
+ };
13
+ const isCompilerPackage = (name) => Object.values(compilerPackages).some((identifier) => identifier === name) || name.startsWith("@typescript/native-");
14
+ //#endregion
15
+ Object.defineProperty(exports, "compilerPackages", {
16
+ enumerable: true,
17
+ get: function() {
18
+ return compilerPackages;
19
+ }
20
+ });
21
+ Object.defineProperty(exports, "isCompilerPackage", {
22
+ enumerable: true,
23
+ get: function() {
24
+ return isCompilerPackage;
25
+ }
26
+ });
27
+
28
+ //# sourceMappingURL=compiler-packages.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compiler-packages.cjs","names":[],"sources":["../src/compiler-packages.ts"],"sourcesContent":["export const compilerPackages = {\n typescript: \"typescript\",\n typescriptCompatibility: \"@typescript/typescript6\",\n native: \"@typescript/native\",\n nativePreview: \"@typescript/native-preview\",\n typescriptCompatibilityAlias: \"typescript-compat\",\n bunTypes: \"bun-types\",\n typesBun: \"@types/bun\",\n tsgo: \"tsgo\",\n typescriptTsgo: \"@typescript/tsgo\",\n} as const;\n\nexport const isCompilerPackage = (name: string) =>\n Object.values(compilerPackages).some((identifier) => identifier === name) ||\n name.startsWith(\"@typescript/native-\");\n"],"mappings":";AAAA,MAAa,mBAAmB;CAC9B,YAAY;CACZ,yBAAyB;CACzB,QAAQ;CACR,eAAe;CACf,8BAA8B;CAC9B,UAAU;CACV,UAAU;CACV,MAAM;CACN,gBAAgB;AAClB;AAEA,MAAa,qBAAqB,SAChC,OAAO,OAAO,gBAAgB,CAAC,CAAC,MAAM,eAAe,eAAe,IAAI,KACxE,KAAK,WAAW,qBAAqB"}
@@ -0,0 +1,17 @@
1
+ //#region src/compiler-packages.ts
2
+ const compilerPackages = {
3
+ typescript: "typescript",
4
+ typescriptCompatibility: "@typescript/typescript6",
5
+ native: "@typescript/native",
6
+ nativePreview: "@typescript/native-preview",
7
+ typescriptCompatibilityAlias: "typescript-compat",
8
+ bunTypes: "bun-types",
9
+ typesBun: "@types/bun",
10
+ tsgo: "tsgo",
11
+ typescriptTsgo: "@typescript/tsgo"
12
+ };
13
+ const isCompilerPackage = (name) => Object.values(compilerPackages).some((identifier) => identifier === name) || name.startsWith("@typescript/native-");
14
+ //#endregion
15
+ export { isCompilerPackage as n, compilerPackages as t };
16
+
17
+ //# sourceMappingURL=compiler-packages.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compiler-packages.mjs","names":[],"sources":["../src/compiler-packages.ts"],"sourcesContent":["export const compilerPackages = {\n typescript: \"typescript\",\n typescriptCompatibility: \"@typescript/typescript6\",\n native: \"@typescript/native\",\n nativePreview: \"@typescript/native-preview\",\n typescriptCompatibilityAlias: \"typescript-compat\",\n bunTypes: \"bun-types\",\n typesBun: \"@types/bun\",\n tsgo: \"tsgo\",\n typescriptTsgo: \"@typescript/tsgo\",\n} as const;\n\nexport const isCompilerPackage = (name: string) =>\n Object.values(compilerPackages).some((identifier) => identifier === name) ||\n name.startsWith(\"@typescript/native-\");\n"],"mappings":";AAAA,MAAa,mBAAmB;CAC9B,YAAY;CACZ,yBAAyB;CACzB,QAAQ;CACR,eAAe;CACf,8BAA8B;CAC9B,UAAU;CACV,UAAU;CACV,MAAM;CACN,gBAAgB;AAClB;AAEA,MAAa,qBAAqB,SAChC,OAAO,OAAO,gBAAgB,CAAC,CAAC,MAAM,eAAe,eAAe,IAAI,KACxE,KAAK,WAAW,qBAAqB"}