@stll/oxlint-config 1.2.0 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -586,27 +586,93 @@ const snapshotText = ({ snapshot, file, visited = /* @__PURE__ */ new Set() }) =
586
586
  visited
587
587
  });
588
588
  };
589
- /** Read declared selector files too, without executing workflows or inspecting installed tools. */
589
+ /**
590
+ * What one `actions/checkout` step puts where, or `undefined` for any other step.
591
+ *
592
+ * A selector such as `base/package.json` after a checkout of this repository
593
+ * with `path: base` names the repository's own `package.json` at another ref,
594
+ * so it is read as that tracked file. A path built from an expression could
595
+ * replace any directory, so it is `unknown`.
596
+ */
597
+ const checkoutStep = (step) => {
598
+ if (!changedRecord(step)) return void 0;
599
+ const uses = step["uses"];
600
+ if (typeof uses !== "string" || !uses.startsWith("actions/checkout@")) return void 0;
601
+ const options = changedRecord(step["with"]) ? step["with"] : {};
602
+ const repository = options["repository"];
603
+ const sameRepository = repository === void 0 || repository === "${{ github.repository }}";
604
+ const checkoutPath = options["path"];
605
+ if (checkoutPath === void 0) return {
606
+ kind: "root",
607
+ sameRepository
608
+ };
609
+ if (typeof checkoutPath !== "string" || checkoutPath.includes("${{") || node_path.default.posix.isAbsolute(checkoutPath)) return { kind: "unknown" };
610
+ const normalized = node_path.default.posix.normalize(checkoutPath).replace(/\/+$/, "");
611
+ if (normalized === "" || normalized === ".") return {
612
+ kind: "root",
613
+ sameRepository
614
+ };
615
+ if (normalized.split("/").includes("..")) return { kind: "unknown" };
616
+ return {
617
+ kind: "path",
618
+ path: normalized,
619
+ sameRepository
620
+ };
621
+ };
622
+ /**
623
+ * The tracked file a declared selector names under the checkouts preceding
624
+ * its step. The most specific checkout directory decides; a selector inside
625
+ * another repository's checkout is not a tracked file, whatever this
626
+ * repository tracks at the same path.
627
+ */
628
+ const resolveCheckoutSelector = (declared, checkouts) => {
629
+ const file = node_path.default.posix.normalize(declared);
630
+ let owner;
631
+ for (const directory of checkouts.keys()) if ((directory === "" || file.startsWith(`${directory}/`)) && (owner === void 0 || directory.length > owner.length)) owner = directory;
632
+ if (owner === void 0) return file;
633
+ if (checkouts.get(owner) !== true) throw new Error(`Setup version-file names a file outside this repository: ${declared}`);
634
+ return owner === "" ? file : file.slice(owner.length + 1);
635
+ };
636
+ /** Visit each step with only the checkouts that precede it. */
637
+ const visitStepsInOrder = (steps, checkouts, visitStep) => {
638
+ const scope = new Map(checkouts);
639
+ for (const step of steps) {
640
+ visitStep(step, scope);
641
+ const checkout = checkoutStep(step);
642
+ if (checkout === void 0) continue;
643
+ if (checkout.kind !== "path") {
644
+ scope.clear();
645
+ scope.set("", checkout.kind === "root" && checkout.sameRepository);
646
+ continue;
647
+ }
648
+ for (const directory of scope.keys()) if (directory === checkout.path || directory.startsWith(`${checkout.path}/`)) scope.delete(directory);
649
+ scope.set(checkout.path, checkout.sameRepository);
650
+ }
651
+ };
590
652
  const selectorFiles = (snapshot) => {
591
653
  const files = /* @__PURE__ */ new Map();
592
- const visit = (value) => {
654
+ const visit = (value, checkouts = /* @__PURE__ */ new Map()) => {
593
655
  if (Array.isArray(value)) {
594
- for (const entry of value) visit(entry);
656
+ for (const entry of value) visit(entry, checkouts);
595
657
  return;
596
658
  }
597
659
  if (!changedRecord(value)) return;
598
660
  for (const [key, entry] of Object.entries(value)) {
661
+ if (key === "steps" && Array.isArray(entry)) {
662
+ visitStepsInOrder(entry, checkouts, visit);
663
+ continue;
664
+ }
599
665
  const input = key.toLowerCase();
600
666
  if (!/(?:^|-)version-file$/.test(input) && ![
601
667
  "toolchain-file",
602
668
  "rust-toolchain-file",
603
669
  "global-json-file"
604
670
  ].includes(input)) {
605
- visit(entry);
671
+ visit(entry, checkouts);
606
672
  continue;
607
673
  }
608
674
  if (typeof entry !== "string" || entry.trim() === "" || entry.includes("${{") || node_path.default.posix.isAbsolute(entry) || entry.split("/").includes("..")) throw new Error("Unclassifiable setup version-file declaration");
609
- const file = node_path.default.posix.normalize(entry);
675
+ const file = resolveCheckoutSelector(entry, checkouts);
610
676
  if (file === "." || file.split("/").some((part) => part === "vendor" || part === "node_modules")) throw new Error("Setup version-file leaves the tracked toolchain scope");
611
677
  let tool = "shared";
612
678
  if (input === "node-version-file") tool = "node";
@@ -962,10 +1028,18 @@ const setupRuntimeFileVersion = ({ snapshot, file, runtime }) => {
962
1028
  };
963
1029
  const setupRuntimeVersions = (snapshot) => {
964
1030
  const versions = [];
965
- const step = (value, file) => {
1031
+ const step = (value, file, checkouts) => {
966
1032
  if (!changedRecord(value) || typeof value["uses"] !== "string") return;
967
1033
  const action = value["uses"].split("@").at(0)?.toLowerCase();
968
1034
  let runtime = /(?:^|\/)setup-([^/]+)$/.exec(action ?? "")?.[1];
1035
+ const wrapped = [
1036
+ "bun",
1037
+ "node",
1038
+ "python",
1039
+ "go",
1040
+ "java"
1041
+ ].find((candidate) => runtime?.startsWith(`${candidate}-`));
1042
+ if (wrapped !== void 0) runtime = wrapped;
969
1043
  if (action === "dtolnay/rust-toolchain") runtime = "rust";
970
1044
  if (runtime === void 0) return;
971
1045
  const raw = value["with"];
@@ -1013,7 +1087,7 @@ const setupRuntimeVersions = (snapshot) => {
1013
1087
  if (typeof input !== "string" || input.trim() === "" || input.includes("${{")) throw new Error("Unclassifiable setup version-file declaration");
1014
1088
  version = setupRuntimeFileVersion({
1015
1089
  snapshot,
1016
- file: node_path.default.posix.normalize(input),
1090
+ file: resolveCheckoutSelector(input, checkouts),
1017
1091
  runtime: inputRuntime
1018
1092
  });
1019
1093
  } else version = setupRuntimeVersion(input);
@@ -1031,7 +1105,7 @@ const setupRuntimeVersions = (snapshot) => {
1031
1105
  return;
1032
1106
  }
1033
1107
  if (!changedRecord(value)) return;
1034
- for (const [key, entry] of Object.entries(value)) if (key === "steps" && Array.isArray(entry)) for (const child of entry) step(child, file);
1108
+ for (const [key, entry] of Object.entries(value)) if (key === "steps" && Array.isArray(entry)) visitStepsInOrder(entry, /* @__PURE__ */ new Map(), (child, checkouts) => step(child, file, checkouts));
1035
1109
  else visit(entry, file);
1036
1110
  };
1037
1111
  for (const file of snapshot.entries.keys()) {