@hublo/sentinel 1.4.0-alpha.32 → 1.4.0-alpha.33

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.
@@ -15,10 +15,10 @@ import {
15
15
  palette,
16
16
  registerAdapters,
17
17
  resolve
18
- } from "../chunk-SPW4KIQX.js";
18
+ } from "../chunk-63NQP75B.js";
19
19
  import {
20
20
  resolveContext
21
- } from "../chunk-ORESQJAU.js";
21
+ } from "../chunk-UBXL567Z.js";
22
22
  import "../chunk-O7REVMOC.js";
23
23
  import {
24
24
  ensureWorkspacePrep,
@@ -144,7 +144,7 @@ async function runValidate(ctx) {
144
144
  );
145
145
  }
146
146
  if (!ctx.targets.includes("test")) return 1;
147
- const { validateModuleTests } = await import("../validate-5GABSOYH.js");
147
+ const { validateModuleTests } = await import("../validate-JUNITP37.js");
148
148
  const outcomes = modules.flatMap(
149
149
  (module) => validateModuleTests(module.name, module.root)
150
150
  );
@@ -27,7 +27,7 @@ import {
27
27
  selfCommand,
28
28
  splitToolArgs,
29
29
  walk
30
- } from "./chunk-ORESQJAU.js";
30
+ } from "./chunk-UBXL567Z.js";
31
31
  import {
32
32
  DEFAULT_MAX_DIAGNOSTICS,
33
33
  findWorkspaceRoot,
@@ -723,7 +723,7 @@ function resolveVitest(cwd) {
723
723
 
724
724
  // src/roles/test/adapters/vitest/vitest.adapter.ts
725
725
  import { spawnSync } from "node:child_process";
726
- import { isAbsolute as isAbsolute2, resolve as resolve7 } from "node:path";
726
+ import { isAbsolute as isAbsolute2, resolve as resolve8 } from "node:path";
727
727
 
728
728
  // src/core/config/tool-args.ts
729
729
  import { existsSync as existsSync6 } from "node:fs";
@@ -873,9 +873,9 @@ function rewriteToolchainImports(toolchain, source, fileName) {
873
873
  }
874
874
 
875
875
  // src/roles/test/jest-migration.ts
876
- import { existsSync as existsSync18, readFileSync as readFileSync17, readdirSync as readdirSync6 } from "node:fs";
876
+ import { existsSync as existsSync19, readFileSync as readFileSync18, readdirSync as readdirSync6 } from "node:fs";
877
877
  import { createRequire as createRequire5 } from "node:module";
878
- import { dirname as dirname10, join as join22, relative as relative5 } from "node:path";
878
+ import { dirname as dirname11, join as join23, relative as relative5 } from "node:path";
879
879
 
880
880
  // src/shared/jsonc.ts
881
881
  import { parse as parse2, printParseErrorCode } from "jsonc-parser";
@@ -890,9 +890,9 @@ function parseJsonc(text, source = "config") {
890
890
  }
891
891
 
892
892
  // src/roles/test/codemod/migrate-module.ts
893
- import { readdirSync as readdirSync4, readFileSync as readFileSync12, statSync as statSync3 } from "node:fs";
894
- import { join as join15 } from "node:path";
895
- import { parseSync as parseSync7 } from "oxc-parser";
893
+ import { readdirSync as readdirSync4, readFileSync as readFileSync13, statSync as statSync4 } from "node:fs";
894
+ import { join as join16 } from "node:path";
895
+ import { parseSync as parseSync8 } from "oxc-parser";
896
896
 
897
897
  // src/roles/test/msw-lifecycle.ts
898
898
  import { existsSync as existsSync9, readFileSync as readFileSync6 } from "node:fs";
@@ -1121,8 +1121,8 @@ ${source}`;
1121
1121
  }
1122
1122
 
1123
1123
  // src/roles/test/codemod/migrate-file.ts
1124
- import { dirname as dirname6 } from "node:path";
1125
- import { parseSync as parseSync6 } from "oxc-parser";
1124
+ import { dirname as dirname7 } from "node:path";
1125
+ import { parseSync as parseSync7 } from "oxc-parser";
1126
1126
 
1127
1127
  // src/roles/test/codemod/assertion-return-value.ts
1128
1128
  var MEMBER_TYPES = /* @__PURE__ */ new Set(["MemberExpression", "StaticMemberExpression"]);
@@ -1881,9 +1881,165 @@ function rewriteHookReturnValue(source, program) {
1881
1881
  }
1882
1882
 
1883
1883
  // src/roles/test/codemod/named-rules.ts
1884
- import { existsSync as existsSync10, readFileSync as readFileSync7 } from "node:fs";
1884
+ import { existsSync as existsSync11, readFileSync as readFileSync8 } from "node:fs";
1885
1885
  import { createRequire as createRequire2 } from "node:module";
1886
- import { dirname as dirname2, join as join9 } from "node:path";
1886
+ import { dirname as dirname3, join as join10 } from "node:path";
1887
+
1888
+ // src/roles/test/codemod/static-import-for-require.ts
1889
+ import { existsSync as existsSync10, readFileSync as readFileSync7, statSync } from "node:fs";
1890
+ import { dirname as dirname2, join as join9, resolve as resolve3 } from "node:path";
1891
+ import { parseSync as parseSync4 } from "oxc-parser";
1892
+ var EXTENSIONS = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"];
1893
+ function resolveRelative(fromFile, specifier) {
1894
+ const base = resolve3(dirname2(fromFile), specifier);
1895
+ const candidates = [
1896
+ base,
1897
+ ...EXTENSIONS.map((extension) => `${base}${extension}`),
1898
+ ...EXTENSIONS.map((extension) => join9(base, `index${extension}`))
1899
+ ];
1900
+ for (const candidate of candidates) {
1901
+ try {
1902
+ if (statSync(candidate).isFile()) return candidate;
1903
+ } catch {
1904
+ }
1905
+ }
1906
+ return void 0;
1907
+ }
1908
+ function relativeSpecifiers(source) {
1909
+ const found = [];
1910
+ const patterns = [
1911
+ /\bfrom\s+['"](\.[^'"]*)['"]/g,
1912
+ /\bimport\s+['"](\.[^'"]*)['"]/g,
1913
+ /\bimport\s*\(\s*['"](\.[^'"]*)['"]\s*\)/g,
1914
+ /\brequire\s*\(\s*['"](\.[^'"]*)['"]\s*\)/g
1915
+ ];
1916
+ for (const pattern of patterns) {
1917
+ for (const match of source.matchAll(pattern)) found.push(match[1]);
1918
+ }
1919
+ return found;
1920
+ }
1921
+ function reachesBack(fromFile, specifier) {
1922
+ const entry = resolveRelative(fromFile, specifier);
1923
+ if (entry === void 0) return true;
1924
+ const target = resolve3(fromFile);
1925
+ const seen = /* @__PURE__ */ new Set();
1926
+ const stack = [entry];
1927
+ while (stack.length > 0 && seen.size < 200) {
1928
+ const file = stack.pop();
1929
+ if (seen.has(file)) continue;
1930
+ seen.add(file);
1931
+ if (resolve3(file) === target) return true;
1932
+ let source;
1933
+ try {
1934
+ source = readFileSync7(file, "utf8");
1935
+ } catch {
1936
+ continue;
1937
+ }
1938
+ for (const relative6 of relativeSpecifiers(source)) {
1939
+ const next = resolveRelative(file, relative6);
1940
+ if (next !== void 0) stack.push(next);
1941
+ }
1942
+ }
1943
+ return seen.size >= 200;
1944
+ }
1945
+ function namedRequireDeclarations(program) {
1946
+ const found = /* @__PURE__ */ new Map();
1947
+ walk(program, (node) => {
1948
+ if (node.type !== "VariableDeclaration") return;
1949
+ const declarators = node.declarations ?? [];
1950
+ if (declarators.length !== 1) return;
1951
+ const declarator = declarators[0];
1952
+ const init = declarator.init;
1953
+ if (init?.type !== "CallExpression") return;
1954
+ const callee = init.callee;
1955
+ if (callee?.type !== "Identifier" || callee.name !== "require") return;
1956
+ const [argument] = init.arguments ?? [];
1957
+ if (argument?.type !== "StringLiteral" && argument?.type !== "Literal") return;
1958
+ const specifier = String(argument.value);
1959
+ if (!specifier.startsWith(".")) return;
1960
+ const id = declarator.id;
1961
+ if (id?.type !== "ObjectPattern") return;
1962
+ const names = [];
1963
+ for (const property of id.properties ?? []) {
1964
+ if (property.type !== "Property" && property.type !== "ObjectProperty") return;
1965
+ if (property.computed === true || property.shorthand !== true) return;
1966
+ const key = property.key;
1967
+ const value = property.value;
1968
+ if (key?.type !== "Identifier" || value?.type !== "Identifier") return;
1969
+ if (key.name !== value.name) return;
1970
+ names.push(key.name);
1971
+ }
1972
+ if (names.length === 0) return;
1973
+ found.set(init, { names, specifier, start: node.start, end: node.end });
1974
+ });
1975
+ return found;
1976
+ }
1977
+ function topLevelNames(program) {
1978
+ const names = /* @__PURE__ */ new Set();
1979
+ for (const node of program.body ?? []) {
1980
+ if (node.type === "ImportDeclaration") {
1981
+ for (const specifier of node.specifiers ?? []) {
1982
+ const local = specifier.local;
1983
+ if (local?.type === "Identifier") names.add(local.name);
1984
+ }
1985
+ continue;
1986
+ }
1987
+ if (node.type === "VariableDeclaration") {
1988
+ for (const declarator of node.declarations ?? []) {
1989
+ const id = declarator.id;
1990
+ if (id?.type === "Identifier") names.add(id.name);
1991
+ }
1992
+ continue;
1993
+ }
1994
+ if ((node.type === "FunctionDeclaration" || node.type === "ClassDeclaration") && node.id?.type === "Identifier") {
1995
+ names.add(node.id.name);
1996
+ }
1997
+ }
1998
+ return names;
1999
+ }
2000
+ function withLeadingComments(source, comments, start) {
2001
+ let from = start;
2002
+ for (; ; ) {
2003
+ const before = source.slice(0, from);
2004
+ const blank = before.length - before.trimEnd().length;
2005
+ const candidate = comments.find((comment) => comment.end === from - blank);
2006
+ if (candidate === void 0) break;
2007
+ const lineStart = source.lastIndexOf("\n", candidate.start) + 1;
2008
+ if (source.slice(lineStart, candidate.start).trim() !== "") break;
2009
+ from = lineStart;
2010
+ }
2011
+ return from;
2012
+ }
2013
+ function planStaticImport(fileName, source, program, requireCall2, semi) {
2014
+ const declaration = namedRequireDeclarations(program).get(requireCall2);
2015
+ if (declaration === void 0) return void 0;
2016
+ const bound = topLevelNames(program);
2017
+ if (declaration.names.some((name) => bound.has(name))) return void 0;
2018
+ if (reachesBack(fileName, declaration.specifier)) return void 0;
2019
+ const { comments } = parseSync4(fileName, source, { sourceType: "module" });
2020
+ const lineStart = source.lastIndexOf("\n", declaration.start - 1) + 1;
2021
+ const ownsItsLine = source.slice(lineStart, declaration.start).trim() === "";
2022
+ const start = withLeadingComments(
2023
+ source,
2024
+ comments,
2025
+ ownsItsLine ? lineStart : declaration.start
2026
+ );
2027
+ return {
2028
+ line: `import { ${declaration.names.join(", ")} } from '${declaration.specifier}'${semi ? ";" : ""}`,
2029
+ // To the end of the line, so the statement does not leave an empty one behind.
2030
+ remove: { start, end: endOfLine(source, declaration.end) }
2031
+ };
2032
+ }
2033
+ function endOfLine(source, end) {
2034
+ let at = end;
2035
+ if (source[at] === ";") at += 1;
2036
+ while (source[at] === " " || source[at] === " ") at += 1;
2037
+ if (source[at] === "\r") at += 1;
2038
+ if (source[at] === "\n") at += 1;
2039
+ return at;
2040
+ }
2041
+
2042
+ // src/roles/test/codemod/named-rules.ts
1887
2043
  function isCommonJsPackage(fromFile, specifier) {
1888
2044
  if (specifier.startsWith(".") || specifier.startsWith("/")) return false;
1889
2045
  let resolved;
@@ -1895,23 +2051,27 @@ function isCommonJsPackage(fromFile, specifier) {
1895
2051
  if (!resolved.includes(`${"/"}node_modules${"/"}`)) return false;
1896
2052
  if (resolved.endsWith(".mjs")) return false;
1897
2053
  if (resolved.endsWith(".cjs")) return true;
1898
- let dir = dirname2(resolved);
2054
+ let dir = dirname3(resolved);
1899
2055
  for (let depth = 0; depth < 12; depth += 1) {
1900
- const manifest = join9(dir, "package.json");
1901
- if (existsSync10(manifest)) {
2056
+ const manifest = join10(dir, "package.json");
2057
+ if (existsSync11(manifest)) {
1902
2058
  try {
1903
- return JSON.parse(readFileSync7(manifest, "utf8")).type !== "module";
2059
+ return JSON.parse(readFileSync8(manifest, "utf8")).type !== "module";
1904
2060
  } catch {
1905
2061
  return false;
1906
2062
  }
1907
2063
  }
1908
- const parent = dirname2(dir);
2064
+ const parent = dirname3(dir);
1909
2065
  if (parent === dir) break;
1910
2066
  dir = parent;
1911
2067
  }
1912
2068
  return false;
1913
2069
  }
1914
2070
  var MEMBER_TYPES9 = /* @__PURE__ */ new Set(["MemberExpression", "StaticMemberExpression"]);
2071
+ function fileUsesSemicolons(source) {
2072
+ const first = /^import\s[^\n]*$/m.exec(source);
2073
+ return first !== null && first[0].trimEnd().endsWith(";");
2074
+ }
1915
2075
  var ASYNC_REPLACEMENTS = {
1916
2076
  requireActual: "importActual",
1917
2077
  requireMock: "importMock"
@@ -1934,6 +2094,16 @@ function mockedSpecifiers(program) {
1934
2094
  });
1935
2095
  return found;
1936
2096
  }
2097
+ function methodValues(program) {
2098
+ const found = /* @__PURE__ */ new Set();
2099
+ walk(program, (node) => {
2100
+ const isMethod = node.type === "MethodDefinition" || node.type === "ClassMethod" || node.type === "ObjectMethod" || (node.type === "Property" || node.type === "ObjectProperty") && (node.kind === "get" || node.kind === "set" || node.method === true);
2101
+ if (!isMethod) return;
2102
+ const value = node.value ?? node.body;
2103
+ if (value !== void 0) found.add(value);
2104
+ });
2105
+ return found;
2106
+ }
1937
2107
  var FUNCTIONS = /* @__PURE__ */ new Set(["ArrowFunctionExpression", "FunctionExpression", "FunctionDeclaration"]);
1938
2108
  function walkWithEnclosingFunction(node, enclosing, visit) {
1939
2109
  if (node === null || typeof node !== "object") return;
@@ -2016,7 +2186,25 @@ function applyNamedRules(source, program, fileName = "") {
2016
2186
  const edits = [];
2017
2187
  const applied = /* @__PURE__ */ new Set();
2018
2188
  const asyncify = /* @__PURE__ */ new Set();
2189
+ const refusals = [];
2190
+ const staticImports = [];
2019
2191
  const mocked = mockedSpecifiers(program);
2192
+ const methods = methodValues(program);
2193
+ const cannotAwaitHere = (enclosing, what, call) => {
2194
+ if (enclosing === void 0 || !methods.has(enclosing)) return false;
2195
+ const plan2 = planStaticImport(fileName, source, program, call, fileUsesSemicolons(source));
2196
+ if (plan2 !== void 0) {
2197
+ edits.push({ start: plan2.remove.start, end: plan2.remove.end, text: "" });
2198
+ staticImports.push(plan2.line);
2199
+ applied.add(`${what} as a static import`);
2200
+ return true;
2201
+ }
2202
+ refusals.push({
2203
+ binding: what,
2204
+ reason: `\`${what}\` sits inside a class or object METHOD, which cannot become async here: \`async get\` is not valid, and making a method that returns void return a promise changes what every caller gets. Left as it was. Under Vitest \`require\` is Node's own resolver, which knows nothing of \`.ts\`, so this one needs a person: a static import, or the dynamic one kept on purpose.`
2205
+ });
2206
+ return true;
2207
+ };
2020
2208
  const wholeStatement = /* @__PURE__ */ new Map();
2021
2209
  walk(program, (node) => {
2022
2210
  if (node.type !== "ExpressionStatement") return;
@@ -2084,6 +2272,7 @@ function applyNamedRules(source, program, fileName = "") {
2084
2272
  const [specifier] = node.arguments ?? [];
2085
2273
  const literal = specifier?.type === "StringLiteral" || specifier?.type === "Literal" ? String(specifier.value) : void 0;
2086
2274
  if (literal !== void 0 && mocked.has(literal)) {
2275
+ if (cannotAwaitHere(enclosing, "jest.requireMock", node)) return;
2087
2276
  edits.push({
2088
2277
  start: node.start,
2089
2278
  end: node.end,
@@ -2096,6 +2285,7 @@ function applyNamedRules(source, program, fileName = "") {
2096
2285
  }
2097
2286
  const asyncReplacement = member === void 0 ? void 0 : ASYNC_REPLACEMENTS[member];
2098
2287
  if (asyncReplacement !== void 0) {
2288
+ if (cannotAwaitHere(enclosing, `jest.${member}`, node)) return;
2099
2289
  edits.push({
2100
2290
  start: node.start,
2101
2291
  end: node.end,
@@ -2109,6 +2299,7 @@ function applyNamedRules(source, program, fileName = "") {
2109
2299
  return;
2110
2300
  }
2111
2301
  if (bareRequire(node)) {
2302
+ if (cannotAwaitHere(enclosing, "require", node)) return;
2112
2303
  const [specifier] = node.arguments ?? [];
2113
2304
  const literal = specifier?.type === "StringLiteral" || specifier?.type === "Literal" ? String(specifier.value) : void 0;
2114
2305
  const interop = literal !== void 0 && !readsANameOffIt.has(node) && !handedToTheRunnerAsAModule.has(node) && !wholeStatement.has(node) && isCommonJsPackage(fileName, literal) ? ".default" : "";
@@ -2143,7 +2334,27 @@ function applyNamedRules(source, program, fileName = "") {
2143
2334
  for (const fn of asyncify) {
2144
2335
  edits.push({ start: fn.start, end: fn.start, text: "async " });
2145
2336
  }
2146
- return { source: applyEdits(source, edits), applied: [...applied].sort() };
2337
+ if (staticImports.length > 0) {
2338
+ const first = (program.body ?? []).find(
2339
+ (node) => node.type === "ImportDeclaration"
2340
+ );
2341
+ const byModule = /* @__PURE__ */ new Map();
2342
+ for (const line of staticImports) {
2343
+ const parsed = /^import \{ (.+) \} from '(.+)'(;?)$/.exec(line);
2344
+ if (parsed === null) continue;
2345
+ const names = byModule.get(parsed[2]) ?? /* @__PURE__ */ new Set();
2346
+ for (const name of parsed[1].split(", ")) names.add(name);
2347
+ byModule.set(parsed[2], names);
2348
+ }
2349
+ const semi = staticImports[0]?.endsWith(";") === true ? ";" : "";
2350
+ const block = `${[...byModule].map(([specifier, names]) => `import { ${[...names].join(", ")} } from '${specifier}'${semi}`).join("\n")}
2351
+ `;
2352
+ edits.push(
2353
+ first === void 0 ? { start: 0, end: 0, text: `${block}
2354
+ ` } : { start: first.start, end: first.start, text: block }
2355
+ );
2356
+ }
2357
+ return { source: applyEdits(source, edits), applied: [...applied].sort(), refusals };
2147
2358
  }
2148
2359
 
2149
2360
  // src/roles/test/codemod/isolate-modules.ts
@@ -2539,7 +2750,7 @@ function annotateMockedBindings(source, program) {
2539
2750
  }
2540
2751
 
2541
2752
  // src/roles/test/codemod/propagate-await.ts
2542
- import { parseSync as parseSync4 } from "oxc-parser";
2753
+ import { parseSync as parseSync5 } from "oxc-parser";
2543
2754
  var FUNCTIONS3 = /* @__PURE__ */ new Set(["ArrowFunctionExpression", "FunctionExpression", "FunctionDeclaration"]);
2544
2755
  var MEMBER_TYPES14 = /* @__PURE__ */ new Set(["MemberExpression", "StaticMemberExpression"]);
2545
2756
  var ALREADY_A_PROMISE = /* @__PURE__ */ new Set(["then", "catch", "finally"]);
@@ -2635,7 +2846,7 @@ function propagateAwait(fileName, source, original, elsewhere = /* @__PURE__ */
2635
2846
  for (let round = 0; round < 12; round += 1) {
2636
2847
  let parsed;
2637
2848
  try {
2638
- parsed = parseSync4(fileName, current);
2849
+ parsed = parseSync5(fileName, current);
2639
2850
  } catch {
2640
2851
  return { source: current, rewritten };
2641
2852
  }
@@ -2665,9 +2876,9 @@ function propagateAwait(fileName, source, original, elsewhere = /* @__PURE__ */
2665
2876
  }
2666
2877
 
2667
2878
  // src/roles/test/codemod/reexport-barrel-mock.ts
2668
- import { readFileSync as readFileSync8, readdirSync as readdirSync2, statSync } from "node:fs";
2879
+ import { readFileSync as readFileSync9, readdirSync as readdirSync2, statSync as statSync2 } from "node:fs";
2669
2880
  import { createRequire as createRequire3 } from "node:module";
2670
- import { dirname as dirname3, join as join10 } from "node:path";
2881
+ import { dirname as dirname4, join as join11 } from "node:path";
2671
2882
  var MEMBER_TYPES15 = /* @__PURE__ */ new Set(["MemberExpression", "StaticMemberExpression"]);
2672
2883
  var PACKAGE_SUBPATH = /^(@[^/]+\/[^/]+|[^@.][^/]*)\/(.+)$/;
2673
2884
  var PURE_REEXPORT = /^module\.exports\s*=\s*require\(\s*(['"])([^'"]+)\1\s*\)\s*;?$/;
@@ -2696,7 +2907,7 @@ function mockCalls(program) {
2696
2907
  }
2697
2908
  function packageRoot(fromFile, name) {
2698
2909
  try {
2699
- return dirname3(createRequire3(fromFile).resolve(`${name}/package.json`));
2910
+ return dirname4(createRequire3(fromFile).resolve(`${name}/package.json`));
2700
2911
  } catch {
2701
2912
  return void 0;
2702
2913
  }
@@ -2720,11 +2931,11 @@ function barrelsFor(fromFile, name, target) {
2720
2931
  const aliases = [];
2721
2932
  for (const entry of entries) {
2722
2933
  if (!entry.endsWith(".js")) continue;
2723
- const path = join10(root, entry);
2934
+ const path = join11(root, entry);
2724
2935
  let body;
2725
2936
  try {
2726
- if (!statSync(path).isFile()) continue;
2727
- body = readFileSync8(path, "utf8");
2937
+ if (!statSync2(path).isFile()) continue;
2938
+ body = readFileSync9(path, "utf8");
2728
2939
  } catch {
2729
2940
  continue;
2730
2941
  }
@@ -2764,7 +2975,7 @@ ${text}` });
2764
2975
  }
2765
2976
 
2766
2977
  // src/roles/test/codemod/repoint-msw.ts
2767
- import { parseSync as parseSync5 } from "oxc-parser";
2978
+ import { parseSync as parseSync6 } from "oxc-parser";
2768
2979
  var SENTINEL_MSW_SERVER = "@hublo/sentinel/test/msw";
2769
2980
  var SENTINEL_MSW_API = "@hublo/sentinel/test/tools/msw";
2770
2981
  var MSW_PACKAGE = /^msw$/;
@@ -2777,7 +2988,7 @@ function importsServer(declaration) {
2777
2988
  });
2778
2989
  }
2779
2990
  function repointMswServer(fileName, source) {
2780
- const { program, errors } = parseSync5(fileName, source, { sourceType: "module" });
2991
+ const { program, errors } = parseSync6(fileName, source, { sourceType: "module" });
2781
2992
  if (errors.length > 0) return { source, repointed: false };
2782
2993
  const edits = [];
2783
2994
  walk(program, (node) => {
@@ -2803,17 +3014,17 @@ function repointMswServer(fileName, source) {
2803
3014
  }
2804
3015
 
2805
3016
  // src/roles/test/codemod/setup-static-imports.ts
2806
- import { dirname as dirname5, resolve as resolve5 } from "node:path";
3017
+ import { dirname as dirname6, resolve as resolve6 } from "node:path";
2807
3018
 
2808
3019
  // src/core/context.ts
2809
- import { existsSync as existsSync11 } from "node:fs";
2810
- import { dirname as dirname4, join as join12, resolve as resolve3 } from "node:path";
3020
+ import { existsSync as existsSync12 } from "node:fs";
3021
+ import { dirname as dirname5, join as join13, resolve as resolve4 } from "node:path";
2811
3022
 
2812
3023
  // src/core/discover-modules.ts
2813
3024
  import { execFileSync as execFileSync2 } from "node:child_process";
2814
- import { mkdtempSync as mkdtempSync2, readFileSync as readFileSync9, rmSync as rmSync2 } from "node:fs";
3025
+ import { mkdtempSync as mkdtempSync2, readFileSync as readFileSync10, rmSync as rmSync2 } from "node:fs";
2815
3026
  import { tmpdir as tmpdir2 } from "node:os";
2816
- import { join as join11 } from "node:path";
3027
+ import { join as join12 } from "node:path";
2817
3028
  function runNx(cwd, args) {
2818
3029
  const nx = resolveBin(cwd, "nx") ?? "nx";
2819
3030
  try {
@@ -2831,11 +3042,11 @@ function runNx(cwd, args) {
2831
3042
  }
2832
3043
  }
2833
3044
  function readGraph(cwd) {
2834
- const dir = mkdtempSync2(join11(tmpdir2(), "sentinel-nx-"));
2835
- const file = join11(dir, "graph.json");
3045
+ const dir = mkdtempSync2(join12(tmpdir2(), "sentinel-nx-"));
3046
+ const file = join12(dir, "graph.json");
2836
3047
  try {
2837
3048
  runNx(cwd, ["graph", "--file", file]);
2838
- const parsed = JSON.parse(readFileSync9(file, "utf8"));
3049
+ const parsed = JSON.parse(readFileSync10(file, "utf8"));
2839
3050
  const nodes = parsed.graph?.nodes;
2840
3051
  if (!nodes || typeof nodes !== "object") {
2841
3052
  throw new Error(
@@ -2844,7 +3055,7 @@ function readGraph(cwd) {
2844
3055
  }
2845
3056
  return Object.entries(nodes).map(([name, node]) => ({
2846
3057
  name,
2847
- root: join11(cwd, node.data.root)
3058
+ root: join12(cwd, node.data.root)
2848
3059
  }));
2849
3060
  } finally {
2850
3061
  rmSync2(dir, { recursive: true, force: true });
@@ -2862,20 +3073,20 @@ function discoverModules(cwd, options = {}) {
2862
3073
  // src/core/context.ts
2863
3074
  var MODULE_MARKERS = ["package.json", "project.json"];
2864
3075
  function isModuleDir(cwd) {
2865
- return MODULE_MARKERS.some((marker) => existsSync11(join12(cwd, marker)));
3076
+ return MODULE_MARKERS.some((marker) => existsSync12(join13(cwd, marker)));
2866
3077
  }
2867
3078
  function findModuleRoot(startDir, workspaceRoot) {
2868
- let dir = resolve3(startDir);
3079
+ let dir = resolve4(startDir);
2869
3080
  for (; ; ) {
2870
- if (workspaceRoot !== void 0 && dir === resolve3(workspaceRoot)) return void 0;
3081
+ if (workspaceRoot !== void 0 && dir === resolve4(workspaceRoot)) return void 0;
2871
3082
  if (isModuleDir(dir)) return dir;
2872
- const parent = dirname4(dir);
3083
+ const parent = dirname5(dir);
2873
3084
  if (parent === dir) return void 0;
2874
3085
  dir = parent;
2875
3086
  }
2876
3087
  }
2877
3088
  function resolveContext(cwd, opts) {
2878
- const atRoot = existsSync11(join12(cwd, WORKSPACE_ROOT_MARKER));
3089
+ const atRoot = existsSync12(join13(cwd, WORKSPACE_ROOT_MARKER));
2879
3090
  if (!atRoot && isModuleDir(cwd)) {
2880
3091
  if (opts.module) {
2881
3092
  throw new Error(
@@ -2903,16 +3114,16 @@ function resolveContext(cwd, opts) {
2903
3114
  }
2904
3115
 
2905
3116
  // src/roles/test/codemod/workspace-specifier.ts
2906
- import { existsSync as existsSync12, readFileSync as readFileSync10 } from "node:fs";
2907
- import { join as join13, relative as relative2, resolve as resolve4 } from "node:path";
2908
- var EXTENSIONS = ["", ".ts", ".tsx", ".js", ".jsx", ".mts", ".cts", "/index.ts", "/index.js"];
3117
+ import { existsSync as existsSync13, readFileSync as readFileSync11 } from "node:fs";
3118
+ import { join as join14, relative as relative2, resolve as resolve5 } from "node:path";
3119
+ var EXTENSIONS2 = ["", ".ts", ".tsx", ".js", ".jsx", ".mts", ".cts", "/index.ts", "/index.js"];
2909
3120
  function pathEntries(workspaceRoot) {
2910
- const file = join13(workspaceRoot, "tsconfig.base.json");
2911
- if (!existsSync12(file)) return [];
3121
+ const file = join14(workspaceRoot, "tsconfig.base.json");
3122
+ if (!existsSync13(file)) return [];
2912
3123
  let paths;
2913
3124
  try {
2914
3125
  paths = parseJsonc(
2915
- readFileSync10(file, "utf8"),
3126
+ readFileSync11(file, "utf8"),
2916
3127
  "tsconfig.base.json"
2917
3128
  )?.compilerOptions?.paths;
2918
3129
  } catch {
@@ -2925,17 +3136,17 @@ function pathEntries(workspaceRoot) {
2925
3136
  const wildcard = key.endsWith("/*") && target.endsWith("/*");
2926
3137
  entries.push({
2927
3138
  key: wildcard ? key.slice(0, -2) : key,
2928
- target: resolve4(workspaceRoot, wildcard ? target.slice(0, -2) : target),
3139
+ target: resolve5(workspaceRoot, wildcard ? target.slice(0, -2) : target),
2929
3140
  wildcard
2930
3141
  });
2931
3142
  }
2932
3143
  return entries.sort((left, right) => right.target.length - left.target.length);
2933
3144
  }
2934
3145
  function workspaceSpecifier(workspaceRoot, file) {
2935
- const absolute = resolve4(file);
3146
+ const absolute = resolve5(file);
2936
3147
  for (const entry of pathEntries(workspaceRoot)) {
2937
3148
  if (!entry.wildcard) {
2938
- if (EXTENSIONS.some((extension) => `${entry.target}${extension}` === absolute)) {
3149
+ if (EXTENSIONS2.some((extension) => `${entry.target}${extension}` === absolute)) {
2939
3150
  return entry.key;
2940
3151
  }
2941
3152
  continue;
@@ -2961,9 +3172,9 @@ function requireCall(source, node) {
2961
3172
  }
2962
3173
  function importable(written, fileName, workspaceRoot) {
2963
3174
  if (!written.startsWith(".")) return written;
2964
- const fileDir = dirname5(fileName);
3175
+ const fileDir = dirname6(fileName);
2965
3176
  const moduleRoot = findModuleRoot(fileDir, workspaceRoot) ?? fileDir;
2966
- const target = resolve5(fileDir, written);
3177
+ const target = resolve6(fileDir, written);
2967
3178
  if (target.startsWith(`${moduleRoot}/`)) return written;
2968
3179
  if (workspaceRoot === void 0) return void 0;
2969
3180
  return workspaceSpecifier(workspaceRoot, target);
@@ -3104,7 +3315,7 @@ function mockFactories(program) {
3104
3315
  return factories;
3105
3316
  }
3106
3317
  function parse3(fileName, source) {
3107
- const { program, errors } = parseSync6(fileName, source, { sourceType: "module" });
3318
+ const { program, errors } = parseSync7(fileName, source, { sourceType: "module" });
3108
3319
  return errors.length > 0 ? void 0 : program;
3109
3320
  }
3110
3321
  function migrateTestFile(fileName, source, defaultImported = /* @__PURE__ */ new Set(), asyncHelpers = /* @__PURE__ */ new Set(), modulesOwnMsw = false) {
@@ -3134,7 +3345,7 @@ function migrateTestFile(fileName, source, defaultImported = /* @__PURE__ */ new
3134
3345
  fileName,
3135
3346
  source,
3136
3347
  beforeStatic,
3137
- findWorkspaceRoot(dirname6(fileName))
3348
+ findWorkspaceRoot(dirname7(fileName))
3138
3349
  );
3139
3350
  source = statics.source;
3140
3351
  const original = statics.rewritten === 0 ? beforeStatic : parse3(fileName, source);
@@ -3249,7 +3460,8 @@ function migrateTestFile(fileName, source, defaultImported = /* @__PURE__ */ new
3249
3460
  ...hoist.refusals,
3250
3461
  ...mocks.refusals.map((refusal) => ({ binding: refusal.binding, reason: refusal.reason })),
3251
3462
  ...constructible.refusals,
3252
- ...isolated.refusals
3463
+ ...isolated.refusals,
3464
+ ...ruled.refusals
3253
3465
  ],
3254
3466
  warnings: fakeTimers.warnings,
3255
3467
  mswRepointed: repointed.repointed
@@ -3257,13 +3469,13 @@ function migrateTestFile(fileName, source, defaultImported = /* @__PURE__ */ new
3257
3469
  }
3258
3470
 
3259
3471
  // src/roles/test/codemod/test-support-files.ts
3260
- import { existsSync as existsSync13, readFileSync as readFileSync11, readdirSync as readdirSync3, statSync as statSync2 } from "node:fs";
3261
- import { dirname as dirname7, join as join14, relative as relative3, resolve as resolve6 } from "node:path";
3472
+ import { existsSync as existsSync14, readFileSync as readFileSync12, readdirSync as readdirSync3, statSync as statSync3 } from "node:fs";
3473
+ import { dirname as dirname8, join as join15, relative as relative3, resolve as resolve7 } from "node:path";
3262
3474
  var SKIPPED = /* @__PURE__ */ new Set(["node_modules", "dist", "coverage", ".git", ".vite"]);
3263
3475
  var TEST_FILE2 = /\.(spec|test)\.[cm]?[jt]sx?$/;
3264
3476
  var SOURCE_FILE = /\.[cm]?[jt]sx?$/;
3265
- var EXTENSIONS2 = [".ts", ".tsx", ".js", ".jsx", ".mts", ".cts"];
3266
- function relativeSpecifiers(source) {
3477
+ var EXTENSIONS3 = [".ts", ".tsx", ".js", ".jsx", ".mts", ".cts"];
3478
+ function relativeSpecifiers2(source) {
3267
3479
  const found = [];
3268
3480
  const patterns = [
3269
3481
  /\bfrom\s+['"](\.[^'"]*)['"]/g,
@@ -3277,14 +3489,14 @@ function relativeSpecifiers(source) {
3277
3489
  return found;
3278
3490
  }
3279
3491
  function resolveSpecifier(fromFile, specifier) {
3280
- const base = resolve6(dirname7(fromFile), specifier);
3281
- if (existsSync13(base) && statSync2(base).isFile()) return base;
3282
- for (const extension of EXTENSIONS2) {
3283
- if (existsSync13(`${base}${extension}`)) return `${base}${extension}`;
3492
+ const base = resolve7(dirname8(fromFile), specifier);
3493
+ if (existsSync14(base) && statSync3(base).isFile()) return base;
3494
+ for (const extension of EXTENSIONS3) {
3495
+ if (existsSync14(`${base}${extension}`)) return `${base}${extension}`;
3284
3496
  }
3285
- for (const extension of EXTENSIONS2) {
3286
- const index = join14(base, `index${extension}`);
3287
- if (existsSync13(index)) return index;
3497
+ for (const extension of EXTENSIONS3) {
3498
+ const index = join15(base, `index${extension}`);
3499
+ if (existsSync14(index)) return index;
3288
3500
  }
3289
3501
  return void 0;
3290
3502
  }
@@ -3301,9 +3513,9 @@ function moduleSources(cwd) {
3301
3513
  }
3302
3514
  for (const entry of entries) {
3303
3515
  if (entry.isDirectory()) {
3304
- if (!SKIPPED.has(entry.name)) stack.push(join14(dir, entry.name));
3516
+ if (!SKIPPED.has(entry.name)) stack.push(join15(dir, entry.name));
3305
3517
  } else if (SOURCE_FILE.test(entry.name)) {
3306
- found.push(join14(dir, entry.name));
3518
+ found.push(join15(dir, entry.name));
3307
3519
  }
3308
3520
  }
3309
3521
  }
@@ -3311,7 +3523,7 @@ function moduleSources(cwd) {
3311
3523
  }
3312
3524
  function read(path) {
3313
3525
  try {
3314
- return readFileSync11(path, "utf8");
3526
+ return readFileSync12(path, "utf8");
3315
3527
  } catch {
3316
3528
  return void 0;
3317
3529
  }
@@ -3320,10 +3532,10 @@ function setupFilesInside(cwd, named) {
3320
3532
  const kept = [];
3321
3533
  for (const raw of named) {
3322
3534
  const withoutToken = raw.replaceAll("<rootDir>/", "").replaceAll("<rootDir>", ".");
3323
- const full = resolve6(cwd, withoutToken);
3535
+ const full = resolve7(cwd, withoutToken);
3324
3536
  const inside = relative3(cwd, full);
3325
3537
  if (inside.startsWith("..") || inside === "") continue;
3326
- if (!existsSync13(full)) continue;
3538
+ if (!existsSync14(full)) continue;
3327
3539
  kept.push(inside.replaceAll("\\", "/"));
3328
3540
  }
3329
3541
  return kept;
@@ -3337,7 +3549,7 @@ function listTestSupportFiles(cwd, setupFiles = []) {
3337
3549
  }
3338
3550
  const importedBy = /* @__PURE__ */ new Map();
3339
3551
  for (const [file, source] of contents) {
3340
- for (const specifier of relativeSpecifiers(source)) {
3552
+ for (const specifier of relativeSpecifiers2(source)) {
3341
3553
  const target = resolveSpecifier(file, specifier);
3342
3554
  if (target === void 0 || !contents.has(target)) continue;
3343
3555
  importedBy.set(target, [...importedBy.get(target) ?? [], file]);
@@ -3350,7 +3562,7 @@ function listTestSupportFiles(cwd, setupFiles = []) {
3350
3562
  );
3351
3563
  while (queue.length > 0) {
3352
3564
  const file = queue.shift();
3353
- for (const specifier of relativeSpecifiers(contents.get(file) ?? "")) {
3565
+ for (const specifier of relativeSpecifiers2(contents.get(file) ?? "")) {
3354
3566
  const target = resolveSpecifier(file, specifier);
3355
3567
  if (target === void 0 || TEST_FILE2.test(target) || testOnly.has(target)) continue;
3356
3568
  if (!isTestOnly(target)) continue;
@@ -3364,12 +3576,12 @@ function listTestSupportFiles(cwd, setupFiles = []) {
3364
3576
 
3365
3577
  // src/roles/test/codemod/migrate-module.ts
3366
3578
  function parse4(source) {
3367
- const { program, errors } = parseSync7("file.ts", source, { sourceType: "module" });
3579
+ const { program, errors } = parseSync8("file.ts", source, { sourceType: "module" });
3368
3580
  return errors.length > 0 ? void 0 : program;
3369
3581
  }
3370
3582
  function read2(path) {
3371
3583
  try {
3372
- return readFileSync12(path, "utf8");
3584
+ return readFileSync13(path, "utf8");
3373
3585
  } catch {
3374
3586
  return void 0;
3375
3587
  }
@@ -3387,10 +3599,10 @@ function defaultImportedSpecifiers(cwd) {
3387
3599
  }
3388
3600
  for (const entry of entries) {
3389
3601
  if (SKIPPED2.has(entry)) continue;
3390
- const path = join15(dir, entry);
3602
+ const path = join16(dir, entry);
3391
3603
  let directory;
3392
3604
  try {
3393
- directory = statSync3(path).isDirectory();
3605
+ directory = statSync4(path).isDirectory();
3394
3606
  } catch {
3395
3607
  continue;
3396
3608
  }
@@ -3418,18 +3630,28 @@ function migrateModuleTests(cwd, setupFiles = []) {
3418
3630
  const defaultImported = defaultImportedSpecifiers(cwd);
3419
3631
  const asyncHelpers = /* @__PURE__ */ new Set();
3420
3632
  for (const relative6 of listTestSupportFiles(cwd, setupFiles)) {
3421
- const source = read2(join15(cwd, relative6));
3633
+ const source = read2(join16(cwd, relative6));
3422
3634
  if (source === void 0) {
3423
3635
  blockers.push({ file: relative6, reason: "this file could not be read" });
3424
3636
  continue;
3425
3637
  }
3426
3638
  const migrated = migrateTestFile(
3427
- join15(cwd, relative6),
3639
+ join16(cwd, relative6),
3428
3640
  source,
3429
3641
  defaultImported,
3430
3642
  /* @__PURE__ */ new Set(),
3431
3643
  modulesOwnMsw
3432
3644
  );
3645
+ for (const member of migrated.unhandled) {
3646
+ blockers.push({
3647
+ file: `${relative6}:${member.line}`,
3648
+ reason: member.rule === void 0 ? `${member.member} has no rule, and guessing one is how a suite goes green for the wrong reason` : `${member.member} needs ${member.rule}`
3649
+ });
3650
+ }
3651
+ for (const refusal of migrated.refusals) {
3652
+ blockers.push({ file: relative6, reason: refusal.reason });
3653
+ }
3654
+ collected.push(...migrated.warnings);
3433
3655
  const renamedTo = vitestSupportName(relative6);
3434
3656
  if (!migrated.changed && renamedTo === relative6) continue;
3435
3657
  if (renamedTo !== relative6) operations.push({ kind: "delete", path: relative6 });
@@ -3443,17 +3665,17 @@ function migrateModuleTests(cwd, setupFiles = []) {
3443
3665
  }
3444
3666
  files++;
3445
3667
  renamed += migrated.renamed;
3446
- const contents = /\bvi\./.test(migrated.source) ? injectViImport(join15(cwd, renamedTo), migrated.source) : migrated.source;
3668
+ const contents = /\bvi\./.test(migrated.source) ? injectViImport(join16(cwd, renamedTo), migrated.source) : migrated.source;
3447
3669
  operations.push({ kind: "write", path: renamedTo, contents });
3448
3670
  }
3449
3671
  for (const relative6 of listTestFiles(cwd)) {
3450
- const source = read2(join15(cwd, relative6));
3672
+ const source = read2(join16(cwd, relative6));
3451
3673
  if (source === void 0) {
3452
3674
  blockers.push({ file: relative6, reason: "this file could not be read" });
3453
3675
  continue;
3454
3676
  }
3455
3677
  const migrated = migrateTestFile(
3456
- join15(cwd, relative6),
3678
+ join16(cwd, relative6),
3457
3679
  source,
3458
3680
  defaultImported,
3459
3681
  asyncHelpers,
@@ -3480,8 +3702,8 @@ function migrateModuleTests(cwd, setupFiles = []) {
3480
3702
  }
3481
3703
 
3482
3704
  // src/roles/test/nest/generate-config.ts
3483
- import { readdirSync as readdirSync5, readFileSync as readFileSync13, statSync as statSync4 } from "node:fs";
3484
- import { join as join16, relative as relative4 } from "node:path";
3705
+ import { readdirSync as readdirSync5, readFileSync as readFileSync14, statSync as statSync5 } from "node:fs";
3706
+ import { join as join17, relative as relative4 } from "node:path";
3485
3707
  var NEST_TEST_PRESET_SPECIFIER = "@hublo/sentinel/test/nest";
3486
3708
  var REACT_TEST_PRESET_SPECIFIER = "@hublo/sentinel/test/react";
3487
3709
  function flavourOf(reading) {
@@ -3527,10 +3749,10 @@ function readModuleTraits(cwd) {
3527
3749
  }
3528
3750
  for (const entry of entries) {
3529
3751
  if (SKIPPED3.has(entry)) continue;
3530
- const path = join16(dir, entry);
3752
+ const path = join17(dir, entry);
3531
3753
  let directory;
3532
3754
  try {
3533
- directory = statSync4(path).isDirectory();
3755
+ directory = statSync5(path).isDirectory();
3534
3756
  } catch {
3535
3757
  continue;
3536
3758
  }
@@ -3541,7 +3763,7 @@ function readModuleTraits(cwd) {
3541
3763
  if (!/\.tsx?$/.test(entry)) continue;
3542
3764
  let source;
3543
3765
  try {
3544
- source = readFileSync13(path, "utf8");
3766
+ source = readFileSync14(path, "utf8");
3545
3767
  } catch {
3546
3768
  continue;
3547
3769
  }
@@ -3674,8 +3896,8 @@ ${overrides.join("\n")}
3674
3896
  }
3675
3897
 
3676
3898
  // src/roles/test/nest/read-jest-config.ts
3677
- import { existsSync as existsSync14, readFileSync as readFileSync14 } from "node:fs";
3678
- import { join as join17 } from "node:path";
3899
+ import { existsSync as existsSync15, readFileSync as readFileSync15 } from "node:fs";
3900
+ import { join as join18 } from "node:path";
3679
3901
  var CARRIED = [
3680
3902
  "testEnvironment",
3681
3903
  "coverageDirectory",
@@ -3865,7 +4087,7 @@ function extendedConfig(source, cwd) {
3865
4087
  (name) => name.replace(/^\.\//, "")
3866
4088
  );
3867
4089
  const file = candidates.find(
3868
- (name) => /^jest[\w.-]*\.(ts|js)$/.test(name) && existsSync14(join17(cwd, name))
4090
+ (name) => /^jest[\w.-]*\.(ts|js)$/.test(name) && existsSync15(join18(cwd, name))
3869
4091
  );
3870
4092
  if (file === void 0) continue;
3871
4093
  if (!new RegExp(String.raw`\{\s*\.\.\.${binding}\b`).test(source)) continue;
@@ -3892,11 +4114,11 @@ function sideEffects(source, extended) {
3892
4114
  return found;
3893
4115
  }
3894
4116
  function readJestConfig(cwd, named) {
3895
- const file = named ?? JEST_CONFIG_FILES.find((name) => existsSync14(join17(cwd, name)));
3896
- if (file === void 0 || !existsSync14(join17(cwd, file))) return void 0;
4117
+ const file = named ?? JEST_CONFIG_FILES.find((name) => existsSync15(join18(cwd, name)));
4118
+ if (file === void 0 || !existsSync15(join18(cwd, file))) return void 0;
3897
4119
  let source;
3898
4120
  try {
3899
- source = readFileSync14(join17(cwd, file), "utf8");
4121
+ source = readFileSync15(join18(cwd, file), "utf8");
3900
4122
  } catch {
3901
4123
  return { file, refusals: [`${file} could not be read`], notes: [] };
3902
4124
  }
@@ -3977,8 +4199,8 @@ function readJestConfig(cwd, named) {
3977
4199
  }
3978
4200
 
3979
4201
  // src/roles/test/nest/run-modes.ts
3980
- import { existsSync as existsSync15 } from "node:fs";
3981
- import { basename as basename2, join as join18 } from "node:path";
4202
+ import { existsSync as existsSync16 } from "node:fs";
4203
+ import { basename as basename2, join as join19 } from "node:path";
3982
4204
  var JEST_EXECUTOR = "@nx/jest:jest";
3983
4205
  var PRIMARY_CONFIG_FILE = "vitest.config.mts";
3984
4206
  var PRIMARY_TARGET = "test";
@@ -3999,7 +4221,7 @@ function runModes(cwd, fallback) {
3999
4221
  const jestConfig = entry.options?.jestConfig;
4000
4222
  if (jestConfig === void 0) continue;
4001
4223
  const name = configName(jestConfig);
4002
- if (!existsSync15(join18(cwd, name))) continue;
4224
+ if (!existsSync16(join19(cwd, name))) continue;
4003
4225
  declared.push({
4004
4226
  target,
4005
4227
  jestConfig: name,
@@ -4024,12 +4246,12 @@ function runModes(cwd, fallback) {
4024
4246
  }
4025
4247
 
4026
4248
  // src/roles/test/written-file-formatter.ts
4027
- import { existsSync as existsSync17 } from "node:fs";
4028
- import { dirname as dirname9, join as join21 } from "node:path";
4249
+ import { existsSync as existsSync18 } from "node:fs";
4250
+ import { dirname as dirname10, join as join22 } from "node:path";
4029
4251
 
4030
4252
  // src/roles/format/read-adoption.ts
4031
- import { existsSync as existsSync16, readFileSync as readFileSync15 } from "node:fs";
4032
- import { join as join19 } from "node:path";
4253
+ import { existsSync as existsSync17, readFileSync as readFileSync16 } from "node:fs";
4254
+ import { join as join20 } from "node:path";
4033
4255
 
4034
4256
  // src/roles/format/config-policy.ts
4035
4257
  var FORMAT_CONFIG_FILE = ".oxfmtrc.json";
@@ -4135,11 +4357,11 @@ function sameValue(a, b) {
4135
4357
  return JSON.stringify(a) === JSON.stringify(b);
4136
4358
  }
4137
4359
  function readFormatAdoption(cwd) {
4138
- const path = join19(cwd, FORMAT_CONFIG_FILE);
4139
- if (!existsSync16(path)) return NOT_ADOPTED(null);
4360
+ const path = join20(cwd, FORMAT_CONFIG_FILE);
4361
+ if (!existsSync17(path)) return NOT_ADOPTED(null);
4140
4362
  let parsed;
4141
4363
  try {
4142
- parsed = parseJsonc(readFileSync15(path, "utf8"), FORMAT_CONFIG_FILE);
4364
+ parsed = parseJsonc(readFileSync16(path, "utf8"), FORMAT_CONFIG_FILE);
4143
4365
  } catch (error) {
4144
4366
  const reason = error instanceof Error ? error.message : String(error);
4145
4367
  return NOT_ADOPTED(FORMAT_CONFIG_FILE, `${FORMAT_CONFIG_FILE} could not be parsed (${reason})`);
@@ -4183,9 +4405,9 @@ function readFormatAdoption(cwd) {
4183
4405
  }
4184
4406
 
4185
4407
  // src/roles/format/resolve-oxfmt.ts
4186
- import { readFileSync as readFileSync16 } from "node:fs";
4408
+ import { readFileSync as readFileSync17 } from "node:fs";
4187
4409
  import { createRequire as createRequire4 } from "node:module";
4188
- import { dirname as dirname8, join as join20 } from "node:path";
4410
+ import { dirname as dirname9, join as join21 } from "node:path";
4189
4411
  function resolveOxfmt(cwd) {
4190
4412
  return resolveBin(cwd, "oxfmt") ?? binFromOwnInstall("oxfmt", "oxfmt");
4191
4413
  }
@@ -4214,8 +4436,8 @@ function configSchema() {
4214
4436
  function readConfigSchema() {
4215
4437
  try {
4216
4438
  const manifest = createRequire4(import.meta.url).resolve("oxfmt/package.json");
4217
- const schemaPath = join20(dirname8(manifest), "configuration_schema.json");
4218
- return JSON.parse(readFileSync16(schemaPath, "utf8"));
4439
+ const schemaPath = join21(dirname9(manifest), "configuration_schema.json");
4440
+ return JSON.parse(readFileSync17(schemaPath, "utf8"));
4219
4441
  } catch {
4220
4442
  return void 0;
4221
4443
  }
@@ -4240,9 +4462,9 @@ function prettierConfigFrom(cwd) {
4240
4462
  let dir = cwd;
4241
4463
  for (; ; ) {
4242
4464
  for (const name of PRETTIER_CONFIGS) {
4243
- if (existsSync17(join21(dir, name))) return join21(dir, name);
4465
+ if (existsSync18(join22(dir, name))) return join22(dir, name);
4244
4466
  }
4245
- const parent = dirname9(dir);
4467
+ const parent = dirname10(dir);
4246
4468
  if (parent === dir) return void 0;
4247
4469
  dir = parent;
4248
4470
  }
@@ -4270,12 +4492,12 @@ function writtenFileFormatter(cwd) {
4270
4492
  var SPEC_TSCONFIG = "tsconfig.spec.json";
4271
4493
  var VITEST_GLOBAL_TYPES = "vitest/globals";
4272
4494
  function specTypesOperation(cwd) {
4273
- const path = join22(cwd, SPEC_TSCONFIG);
4274
- if (!existsSync18(path)) return void 0;
4495
+ const path = join23(cwd, SPEC_TSCONFIG);
4496
+ if (!existsSync19(path)) return void 0;
4275
4497
  let config;
4276
4498
  try {
4277
4499
  config = parseJsonc(
4278
- readFileSync17(path, "utf8"),
4500
+ readFileSync18(path, "utf8"),
4279
4501
  SPEC_TSCONFIG
4280
4502
  );
4281
4503
  } catch {
@@ -4295,9 +4517,9 @@ function specTypesOperation(cwd) {
4295
4517
  }
4296
4518
  function shippedTypesPath(cwd, declaration) {
4297
4519
  try {
4298
- const manifest = createRequire5(join22(cwd, "noop.cjs")).resolve("@hublo/sentinel/package.json");
4299
- const file = join22(dirname10(manifest), declaration);
4300
- if (existsSync18(file)) {
4520
+ const manifest = createRequire5(join23(cwd, "noop.cjs")).resolve("@hublo/sentinel/package.json");
4521
+ const file = join23(dirname11(manifest), declaration);
4522
+ if (existsSync19(file)) {
4301
4523
  const path = relative5(cwd, file);
4302
4524
  return path.startsWith(".") ? path : `./${path}`;
4303
4525
  }
@@ -4316,7 +4538,7 @@ function helpersStillCallingJest(cwd) {
4316
4538
  return;
4317
4539
  }
4318
4540
  for (const entry of entries) {
4319
- const path = join22(dir, entry.name);
4541
+ const path = join23(dir, entry.name);
4320
4542
  if (entry.isDirectory()) {
4321
4543
  if (!skip.has(entry.name)) walk2(path);
4322
4544
  continue;
@@ -4326,7 +4548,7 @@ function helpersStillCallingJest(cwd) {
4326
4548
  if (/^(jest|vitest)\./.test(entry.name)) continue;
4327
4549
  let source;
4328
4550
  try {
4329
- source = readFileSync17(path, "utf8");
4551
+ source = readFileSync18(path, "utf8");
4330
4552
  } catch {
4331
4553
  continue;
4332
4554
  }
@@ -4362,7 +4584,7 @@ function tsconfigFileListOperations(cwd) {
4362
4584
  let config;
4363
4585
  try {
4364
4586
  config = parseJsonc(
4365
- readFileSync17(join22(cwd, name), "utf8"),
4587
+ readFileSync18(join23(cwd, name), "utf8"),
4366
4588
  name
4367
4589
  );
4368
4590
  } catch {
@@ -4830,7 +5052,7 @@ function fromWorkspaceRoot(moduleDir, options, paths) {
4830
5052
  if (root === void 0 || root === moduleDir) {
4831
5053
  return { cwd: moduleDir, options: [...options], paths: [...paths] };
4832
5054
  }
4833
- const absolute = (value) => isAbsolute2(value) ? value : resolve7(moduleDir, value);
5055
+ const absolute = (value) => isAbsolute2(value) ? value : resolve8(moduleDir, value);
4834
5056
  const moved = [];
4835
5057
  let previousWasConfig = false;
4836
5058
  for (const option of options) {
package/dist/index.js CHANGED
@@ -6,10 +6,10 @@ import {
6
6
  registerAdapters,
7
7
  resolve,
8
8
  setDefaultRunner
9
- } from "./chunk-SPW4KIQX.js";
9
+ } from "./chunk-63NQP75B.js";
10
10
  import {
11
11
  BaseAdapter
12
- } from "./chunk-ORESQJAU.js";
12
+ } from "./chunk-UBXL567Z.js";
13
13
  import "./chunk-O7REVMOC.js";
14
14
  import "./chunk-NW6UHNYX.js";
15
15
  export {
@@ -7,7 +7,7 @@ import {
7
7
  readTestAdoption,
8
8
  resolveVitest,
9
9
  suiteOf
10
- } from "./chunk-ORESQJAU.js";
10
+ } from "./chunk-UBXL567Z.js";
11
11
  import "./chunk-O7REVMOC.js";
12
12
  import "./chunk-NW6UHNYX.js";
13
13
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hublo/sentinel",
3
- "version": "1.4.0-alpha.32",
3
+ "version": "1.4.0-alpha.33",
4
4
  "description": "One CLI that guards code health across Hublo repos: shared lint/typescript/build/test presets, static & dynamic analysis, and architecture checks.",
5
5
  "type": "module",
6
6
  "license": "MIT",