@hublo/sentinel 1.2.0-alpha.25 → 1.2.0-alpha.26

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.
@@ -22,7 +22,7 @@ import {
22
22
  registerAdapters,
23
23
  resolve,
24
24
  resolveBin
25
- } from "../chunk-C4BWV6SU.js";
25
+ } from "../chunk-O7OXACCN.js";
26
26
 
27
27
  // bin/sentinel.ts
28
28
  import { program } from "commander";
@@ -591,8 +591,8 @@ function binSearchPath(cwd) {
591
591
  }
592
592
 
593
593
  // src/roles/build/plan.ts
594
- import { existsSync as existsSync10, readFileSync as readFileSync8 } from "fs";
595
- import { join as join10 } from "path";
594
+ import { existsSync as existsSync11, readFileSync as readFileSync9 } from "fs";
595
+ import { join as join11 } from "path";
596
596
 
597
597
  // src/core/config/existing-command.ts
598
598
  import { readFileSync as readFileSync6 } from "fs";
@@ -711,6 +711,161 @@ function keepsOtherCommands(script, sentinelCommand) {
711
711
  return script.split(SEGMENT_SEPARATOR).filter((_, index) => !isSeparatorAt(index)).some((segment) => segment.trim() !== "" && segment.trim() !== sentinelCommand);
712
712
  }
713
713
 
714
+ // src/roles/format/read-adoption.ts
715
+ import { existsSync as existsSync9, readFileSync as readFileSync7 } from "fs";
716
+ import { join as join9 } from "path";
717
+
718
+ // src/roles/format/config-policy.ts
719
+ var FORMAT_CONFIG_FILE = ".oxfmtrc.json";
720
+ var FORMAT_SCRIPT_NAME = "format";
721
+ var PROVENANCE_KEY = "$sentinel";
722
+ var PERMITTED_LOCAL_KEYS = [
723
+ "useTabs",
724
+ "tabWidth",
725
+ "printWidth",
726
+ "semi",
727
+ "singleQuote",
728
+ "jsxSingleQuote",
729
+ "trailingComma",
730
+ "quoteProps",
731
+ "bracketSpacing",
732
+ "bracketSameLine",
733
+ "arrowParens",
734
+ "endOfLine",
735
+ "objectWrap",
736
+ "proseWrap",
737
+ "experimentalOperatorPosition"
738
+ ];
739
+ var ALWAYS_LOCAL_KEYS = ["ignorePatterns", "overrides"];
740
+ var FORMAT_DEFAULT_IGNORES = ["**/*.toml"];
741
+ var PRETTIER_CONFIG_FILES = [
742
+ ".prettierrc",
743
+ ".prettierrc.json",
744
+ ".prettierrc.json5",
745
+ ".prettierrc.yml",
746
+ ".prettierrc.yaml",
747
+ ".prettierrc.js",
748
+ ".prettierrc.cjs",
749
+ ".prettierrc.mjs",
750
+ "prettier.config.js",
751
+ "prettier.config.cjs",
752
+ "prettier.config.mjs"
753
+ ];
754
+ function formatTargets() {
755
+ return {
756
+ [FORMAT_SCRIPT_NAME]: {
757
+ cache: true,
758
+ inputs: ["default", `{projectRoot}/${FORMAT_CONFIG_FILE}`]
759
+ },
760
+ [`${FORMAT_SCRIPT_NAME}:fix`]: { cache: false }
761
+ };
762
+ }
763
+
764
+ // src/roles/format/presets/base.json
765
+ var base_default = {
766
+ printWidth: 80,
767
+ semi: false,
768
+ singleQuote: true,
769
+ trailingComma: "all",
770
+ sortPackageJson: false,
771
+ sortImports: false
772
+ };
773
+
774
+ // src/roles/format/presets/nest-imports.json
775
+ var nest_imports_default = {
776
+ customGroups: [
777
+ {
778
+ groupName: "workspace",
779
+ elementNamePattern: ["@hublo/**", "@shared/**", "@front/**", "@network/**"]
780
+ }
781
+ ],
782
+ groups: ["builtin", "external", "workspace", ["parent", "index"], "sibling"],
783
+ newlinesBetween: true,
784
+ order: "asc",
785
+ ignoreCase: false
786
+ };
787
+
788
+ // src/roles/format/preset-data.ts
789
+ var FORMAT_PRESETS = ["base", "svelte", "nest"];
790
+ function hasFormatPreset(name) {
791
+ return FORMAT_PRESETS.includes(name);
792
+ }
793
+ function formatPresetName(declared) {
794
+ if (declared === "svelte") return "svelte";
795
+ if (declared === "nest") return "nest";
796
+ return "base";
797
+ }
798
+ function formatPresetFor(preset) {
799
+ const base = base_default;
800
+ const name = formatPresetName(preset);
801
+ if (name === "svelte") return { ...base, svelte: true };
802
+ if (name === "nest") return { ...base, sortImports: nest_imports_default };
803
+ return base;
804
+ }
805
+
806
+ // src/roles/format/read-adoption.ts
807
+ var NOT_ADOPTED2 = (configFile, unreadable = null) => ({
808
+ configFile,
809
+ preset: null,
810
+ adopted: false,
811
+ conformant: false,
812
+ drift: [],
813
+ local: {},
814
+ presetVersion: null,
815
+ effective: {},
816
+ unreadable
817
+ });
818
+ function sameValue(a, b) {
819
+ return JSON.stringify(a) === JSON.stringify(b);
820
+ }
821
+ function readFormatAdoption(cwd) {
822
+ const path = join9(cwd, FORMAT_CONFIG_FILE);
823
+ if (!existsSync9(path)) return NOT_ADOPTED2(null);
824
+ let parsed;
825
+ try {
826
+ parsed = parseJsonc(readFileSync7(path, "utf8"), FORMAT_CONFIG_FILE);
827
+ } catch (error) {
828
+ const reason = error instanceof Error ? error.message : String(error);
829
+ return NOT_ADOPTED2(FORMAT_CONFIG_FILE, `${FORMAT_CONFIG_FILE} could not be parsed (${reason})`);
830
+ }
831
+ const provenance = parsed[PROVENANCE_KEY];
832
+ if (!provenance || typeof provenance.preset !== "string") return NOT_ADOPTED2(FORMAT_CONFIG_FILE);
833
+ if (!hasFormatPreset(provenance.preset)) {
834
+ return NOT_ADOPTED2(
835
+ FORMAT_CONFIG_FILE,
836
+ `${FORMAT_CONFIG_FILE} declares the format preset "${provenance.preset}", which sentinel does not ship (shipped: ${FORMAT_PRESETS.join(", ")}). Re-run \`sentinel --init --format\`.`
837
+ );
838
+ }
839
+ const declaredLocal = Array.isArray(provenance.local) ? provenance.local : [];
840
+ const preset = formatPresetFor(provenance.preset);
841
+ const drift = [];
842
+ const local = {};
843
+ for (const [key, expected] of Object.entries(preset)) {
844
+ if (declaredLocal.includes(key)) {
845
+ local[key] = parsed[key];
846
+ continue;
847
+ }
848
+ if (!(key in parsed) || !sameValue(parsed[key], expected)) drift.push(key);
849
+ }
850
+ for (const key of declaredLocal) {
851
+ if (!(key in preset)) local[key] = parsed[key];
852
+ }
853
+ for (const key of ALWAYS_LOCAL_KEYS) {
854
+ if (key in parsed) local[key] = parsed[key];
855
+ }
856
+ return {
857
+ configFile: FORMAT_CONFIG_FILE,
858
+ preset: provenance.preset,
859
+ adopted: true,
860
+ conformant: drift.length === 0,
861
+ drift,
862
+ local,
863
+ presetVersion: typeof provenance.version === "string" ? provenance.version : null,
864
+ effective: parsed,
865
+ unreadable: null
866
+ };
867
+ }
868
+
714
869
  // src/roles/build/dev-script.ts
715
870
  var CHAIN = " -- ";
716
871
  var VITE_TOKEN = /(^|\s|\/)vite(\s|$)/;
@@ -732,13 +887,38 @@ function composeDevScript(existing, command) {
732
887
  }
733
888
 
734
889
  // src/roles/build/nest/adopt.ts
735
- import { existsSync as existsSync9, readFileSync as readFileSync7 } from "fs";
736
- import { join as join9 } from "path";
890
+ import { existsSync as existsSync10, readFileSync as readFileSync8 } from "fs";
891
+ import { join as join10 } from "path";
737
892
  var NEST_CONFIG_FILE = "vite.config.mts";
893
+ function asSource(value, depth) {
894
+ const pad = " ".repeat(depth);
895
+ const inner = " ".repeat(depth + 1);
896
+ if (Array.isArray(value)) {
897
+ if (value.length === 0) return "[]";
898
+ return `[
899
+ ${value.map((item) => `${inner}${asSource(item, depth + 1)}`).join(",\n")},
900
+ ${pad}]`;
901
+ }
902
+ if (value !== null && typeof value === "object") {
903
+ const entries = Object.entries(value);
904
+ if (entries.length === 0) return "{}";
905
+ return `{
906
+ ${entries.map(([key, item]) => `${inner}${asKey(key)}: ${asSource(item, depth + 1)}`).join(",\n")},
907
+ ${pad}}`;
908
+ }
909
+ if (typeof value === "string") return `'${value.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
910
+ if (typeof value === "number" || typeof value === "boolean") return String(value);
911
+ throw new Error(
912
+ `sentinel build(nest): cannot write ${typeof value} into the generated config. The build target carries a shape this translation was not written for, and it should refuse rather than emit something nobody has read.`
913
+ );
914
+ }
915
+ function asKey(key) {
916
+ return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key) ? key : `'${key}'`;
917
+ }
738
918
  function nestConfigSource(cwd, target) {
739
919
  const hops = workspaceRootHops(cwd, target);
740
920
  const up = Array.from({ length: hops }, () => "..").join("/");
741
- const carried = (name, value) => value === void 0 || value.length === 0 ? "" : ` ${name}: ${JSON.stringify(value)},
921
+ const carried = (name, value) => value === void 0 || value.length === 0 ? "" : ` ${name}: ${asSource(value, 1)},
742
922
  `;
743
923
  return `import path from 'node:path'
744
924
 
@@ -757,9 +937,9 @@ function nestBuildOutputs(target) {
757
937
  }
758
938
  var OUT_DIR_IN_CONFIG = /^\s*outDir:\s*'([^']+)'/m;
759
939
  function nestOutputsFromConfig(cwd) {
760
- const configPath = join9(cwd, NEST_CONFIG_FILE);
761
- if (!existsSync9(configPath)) return void 0;
762
- const outDir = OUT_DIR_IN_CONFIG.exec(readFileSync7(configPath, "utf8"))?.[1];
940
+ const configPath = join10(cwd, NEST_CONFIG_FILE);
941
+ if (!existsSync10(configPath)) return void 0;
942
+ const outDir = OUT_DIR_IN_CONFIG.exec(readFileSync8(configPath, "utf8"))?.[1];
763
943
  return outDir === void 0 ? void 0 : [`{workspaceRoot}/${outDir}`];
764
944
  }
765
945
  function nestAdoptionOperations(cwd, target) {
@@ -1019,6 +1199,10 @@ function planReactApp(context, configFile) {
1019
1199
  `removed ${owned.map(([, name]) => name).join(", ")} from this module: sentinel owns them now, and two copies of Vite in one build give the plugins a different Vite than the one running them.`
1020
1200
  );
1021
1201
  }
1202
+ const formatted = readFormatAdoption(context.cwd).adopted;
1203
+ notes.push(
1204
+ formatted ? `run \`sentinel --run --format --fix\` on this module: adoption rewrote ${configFile}, and a rewritten import can be longer than your formatter wraps at.` : `this module is formatted by the workspace, not by sentinel, so format ${configFile} with whatever owns it before committing: a rewritten import can be longer than that formatter wraps at, and the check would fail on a file nobody typed.`
1205
+ );
1022
1206
  notes.push(
1023
1207
  `this config is code, and it runs before the build does: any environment variable it reads has to be present wherever you build, including a fresh clone, another CI job or an image. Adoption does not change what it reads, but a failure there arrives early and names this role rather than the variable.`
1024
1208
  );
@@ -1059,9 +1243,9 @@ function planNestService(context, webpackTarget) {
1059
1243
  };
1060
1244
  }
1061
1245
  function readConfigSource(cwd, configFile) {
1062
- if (!existsSync10(join10(cwd, configFile))) return "";
1246
+ if (!existsSync11(join11(cwd, configFile))) return "";
1063
1247
  try {
1064
- return readFileSync8(join10(cwd, configFile), "utf8");
1248
+ return readFileSync9(join11(cwd, configFile), "utf8");
1065
1249
  } catch {
1066
1250
  return "";
1067
1251
  }
@@ -1246,12 +1430,12 @@ var ViteDevAdapter = class extends ViteRoleAdapter {
1246
1430
  };
1247
1431
 
1248
1432
  // src/roles/build/declared-outputs.ts
1249
- import { existsSync as existsSync12, rmSync, statSync, writeFileSync as writeFileSync2 } from "fs";
1250
- import { join as join12 } from "path";
1433
+ import { existsSync as existsSync13, rmSync, statSync, writeFileSync as writeFileSync2 } from "fs";
1434
+ import { join as join13 } from "path";
1251
1435
 
1252
1436
  // src/core/workspace-prep.ts
1253
- import { existsSync as existsSync11, readFileSync as readFileSync9, writeFileSync } from "fs";
1254
- import { dirname as dirname3, join as join11, relative as relative2 } from "path";
1437
+ import { existsSync as existsSync12, readFileSync as readFileSync10, writeFileSync } from "fs";
1438
+ import { dirname as dirname3, join as join12, relative as relative2 } from "path";
1255
1439
 
1256
1440
  // src/core/settings.ts
1257
1441
  var WORKSPACE_ROOT_MARKER = "nx.json";
@@ -1266,7 +1450,7 @@ var LIST_ITEM = /^(\s*)-\s+(.*?)\s*$/;
1266
1450
  function findWorkspaceRoot(startDir) {
1267
1451
  let dir = startDir;
1268
1452
  for (; ; ) {
1269
- if (existsSync11(join11(dir, WORKSPACE_ROOT_MARKER))) return dir;
1453
+ if (existsSync12(join12(dir, WORKSPACE_ROOT_MARKER))) return dir;
1270
1454
  const parent = dirname3(dir);
1271
1455
  if (parent === dir) return void 0;
1272
1456
  dir = parent;
@@ -1279,9 +1463,9 @@ function declaredNativeTs(pkg) {
1279
1463
  return version || void 0;
1280
1464
  }
1281
1465
  function ensureI18nextSingleton(root, dryRun) {
1282
- const pkgPath = join11(root, "package.json");
1283
- if (!existsSync11(pkgPath)) return void 0;
1284
- const pkg = JSON.parse(readFileSync9(pkgPath, "utf8"));
1466
+ const pkgPath = join12(root, "package.json");
1467
+ if (!existsSync12(pkgPath)) return void 0;
1468
+ const pkg = JSON.parse(readFileSync10(pkgPath, "utf8"));
1285
1469
  const want = declaredNativeTs(pkg);
1286
1470
  if (!want) return void 0;
1287
1471
  const have = pkg.pnpm?.overrides?.[OVERRIDE_KEY];
@@ -1294,10 +1478,10 @@ function ensureI18nextSingleton(root, dryRun) {
1294
1478
  return `pinned ${OVERRIDE_KEY} to ${want} in package.json (i18next singleton)`;
1295
1479
  }
1296
1480
  function ensureReleaseAgeAllowList(root, dryRun) {
1297
- const yamlPath = join11(root, WORKSPACE_YAML);
1298
- if (!existsSync11(yamlPath)) return void 0;
1481
+ const yamlPath = join12(root, WORKSPACE_YAML);
1482
+ if (!existsSync12(yamlPath)) return void 0;
1299
1483
  const own = readOwnPackage().name;
1300
- const lines = readFileSync9(yamlPath, "utf8").split("\n");
1484
+ const lines = readFileSync10(yamlPath, "utf8").split("\n");
1301
1485
  const keyIdx = lines.findIndex((line) => line.replace(/\s+$/, "") === `${RELEASE_AGE_KEY}:`);
1302
1486
  if (keyIdx === -1) return void 0;
1303
1487
  let lastItemIdx = keyIdx;
@@ -1332,11 +1516,11 @@ var ROOT_PRETTIER_CONFIGS = [
1332
1516
  function ensureFormatterExclusion(root, moduleDir, dryRun) {
1333
1517
  const rel = relative2(root, moduleDir).replaceAll("\\", "/");
1334
1518
  if (rel === "" || rel.startsWith("..")) return void 0;
1335
- const ignorePath = join11(root, PRETTIER_IGNORE);
1336
- const hasPrettier = existsSync11(ignorePath) || ROOT_PRETTIER_CONFIGS.some((name) => existsSync11(join11(root, name)));
1519
+ const ignorePath = join12(root, PRETTIER_IGNORE);
1520
+ const hasPrettier = existsSync12(ignorePath) || ROOT_PRETTIER_CONFIGS.some((name) => existsSync12(join12(root, name)));
1337
1521
  if (!hasPrettier) return void 0;
1338
1522
  const pattern = `/${rel}/`;
1339
- const existing = existsSync11(ignorePath) ? readFileSync9(ignorePath, "utf8") : "";
1523
+ const existing = existsSync12(ignorePath) ? readFileSync10(ignorePath, "utf8") : "";
1340
1524
  const lines = existing.split("\n");
1341
1525
  if (lines.some((line) => line.trim().replace(/\/$/, "") === pattern.replace(/\/$/, ""))) {
1342
1526
  return void 0;
@@ -1372,10 +1556,10 @@ function ensureWorkspacePrep(opts) {
1372
1556
  function inspectWorkspacePrep(root) {
1373
1557
  const entries = [];
1374
1558
  let pkg = {};
1375
- const pkgPath = join11(root, "package.json");
1376
- if (existsSync11(pkgPath)) {
1559
+ const pkgPath = join12(root, "package.json");
1560
+ if (existsSync12(pkgPath)) {
1377
1561
  try {
1378
- pkg = JSON.parse(readFileSync9(pkgPath, "utf8"));
1562
+ pkg = JSON.parse(readFileSync10(pkgPath, "utf8"));
1379
1563
  } catch {
1380
1564
  pkg = {};
1381
1565
  }
@@ -1389,9 +1573,9 @@ function inspectWorkspacePrep(root) {
1389
1573
  });
1390
1574
  }
1391
1575
  const own = readOwnPackage().name;
1392
- const yamlPath = join11(root, WORKSPACE_YAML);
1393
- if (existsSync11(yamlPath)) {
1394
- const yaml = readFileSync9(yamlPath, "utf8");
1576
+ const yamlPath = join12(root, WORKSPACE_YAML);
1577
+ if (existsSync12(yamlPath)) {
1578
+ const yaml = readFileSync10(yamlPath, "utf8");
1395
1579
  const listed = new RegExp(`^\\s*-\\s*['"]?${own.replace("/", "\\/")}['"]?\\s*$`, "m").test(yaml);
1396
1580
  if (listed) {
1397
1581
  const gated = new RegExp(`^\\s*minimumReleaseAge\\s*:`, "m").test(yaml);
@@ -1409,15 +1593,15 @@ function declaredBuildTarget(cwd) {
1409
1593
  return readProjectPackageJson(cwd).nx?.targets?.[BUILD_SCRIPT_NAME];
1410
1594
  }
1411
1595
  function resolveOutputToken(token, cwd) {
1412
- if (token.startsWith("{projectRoot}/")) return join12(cwd, token.slice("{projectRoot}/".length));
1596
+ if (token.startsWith("{projectRoot}/")) return join13(cwd, token.slice("{projectRoot}/".length));
1413
1597
  if (token.startsWith("{workspaceRoot}/")) {
1414
1598
  const root = findWorkspaceRoot(cwd);
1415
- return root === void 0 ? void 0 : join12(root, token.slice("{workspaceRoot}/".length));
1599
+ return root === void 0 ? void 0 : join13(root, token.slice("{workspaceRoot}/".length));
1416
1600
  }
1417
- return join12(cwd, token);
1601
+ return join13(cwd, token);
1418
1602
  }
1419
1603
  function buildStamp(cwd) {
1420
- const marker = join12(cwd, `.sentinel-build-stamp-${process.pid}`);
1604
+ const marker = join13(cwd, `.sentinel-build-stamp-${process.pid}`);
1421
1605
  try {
1422
1606
  writeFileSync2(marker, "");
1423
1607
  const stamp = statSync(marker).mtimeMs;
@@ -1428,7 +1612,7 @@ function buildStamp(cwd) {
1428
1612
  }
1429
1613
  }
1430
1614
  function writtenSince(path, startedAt) {
1431
- if (!existsSync12(path)) return false;
1615
+ if (!existsSync13(path)) return false;
1432
1616
  try {
1433
1617
  return statSync(path).mtimeMs >= startedAt;
1434
1618
  } catch {
@@ -1582,7 +1766,7 @@ import { join as join18 } from "path";
1582
1766
 
1583
1767
  // src/core/config/has-source.ts
1584
1768
  import { readdirSync } from "fs";
1585
- import { extname, join as join13, relative as relative3 } from "path";
1769
+ import { extname, join as join14, relative as relative3 } from "path";
1586
1770
  var SKIP_DIRECTORIES = /* @__PURE__ */ new Set([
1587
1771
  "node_modules",
1588
1772
  "dist",
@@ -1633,7 +1817,7 @@ function hasSourceFiles(cwd, extensions) {
1633
1817
  }
1634
1818
  for (const entry of entries) {
1635
1819
  if (entry.isDirectory()) {
1636
- if (!SKIP_DIRECTORIES.has(entry.name)) queue.push(join13(dir, entry.name));
1820
+ if (!SKIP_DIRECTORIES.has(entry.name)) queue.push(join14(dir, entry.name));
1637
1821
  continue;
1638
1822
  }
1639
1823
  if (wanted.has(extname(entry.name))) return true;
@@ -1654,7 +1838,7 @@ function listSourceFiles(cwd, extensions) {
1654
1838
  continue;
1655
1839
  }
1656
1840
  for (const entry of entries) {
1657
- const full = join13(dir, entry.name);
1841
+ const full = join14(dir, entry.name);
1658
1842
  if (entry.isDirectory()) {
1659
1843
  if (!SKIP_DIRECTORIES.has(entry.name)) queue.push(full);
1660
1844
  continue;
@@ -1672,52 +1856,6 @@ function scopeFlags(paths, options = []) {
1672
1856
  return [TOLERATE_EMPTY_FLAG];
1673
1857
  }
1674
1858
 
1675
- // src/roles/format/config-policy.ts
1676
- var FORMAT_CONFIG_FILE = ".oxfmtrc.json";
1677
- var FORMAT_SCRIPT_NAME = "format";
1678
- var PROVENANCE_KEY = "$sentinel";
1679
- var PERMITTED_LOCAL_KEYS = [
1680
- "useTabs",
1681
- "tabWidth",
1682
- "printWidth",
1683
- "semi",
1684
- "singleQuote",
1685
- "jsxSingleQuote",
1686
- "trailingComma",
1687
- "quoteProps",
1688
- "bracketSpacing",
1689
- "bracketSameLine",
1690
- "arrowParens",
1691
- "endOfLine",
1692
- "objectWrap",
1693
- "proseWrap",
1694
- "experimentalOperatorPosition"
1695
- ];
1696
- var ALWAYS_LOCAL_KEYS = ["ignorePatterns", "overrides"];
1697
- var FORMAT_DEFAULT_IGNORES = ["**/*.toml"];
1698
- var PRETTIER_CONFIG_FILES = [
1699
- ".prettierrc",
1700
- ".prettierrc.json",
1701
- ".prettierrc.json5",
1702
- ".prettierrc.yml",
1703
- ".prettierrc.yaml",
1704
- ".prettierrc.js",
1705
- ".prettierrc.cjs",
1706
- ".prettierrc.mjs",
1707
- "prettier.config.js",
1708
- "prettier.config.cjs",
1709
- "prettier.config.mjs"
1710
- ];
1711
- function formatTargets() {
1712
- return {
1713
- [FORMAT_SCRIPT_NAME]: {
1714
- cache: true,
1715
- inputs: ["default", `{projectRoot}/${FORMAT_CONFIG_FILE}`]
1716
- },
1717
- [`${FORMAT_SCRIPT_NAME}:fix`]: { cache: false }
1718
- };
1719
- }
1720
-
1721
1859
  // src/roles/format/format-script.ts
1722
1860
  var SENTINEL_FORMAT_COMMAND = "sentinel --run --format";
1723
1861
  function isPrettierSegment(segment) {
@@ -1746,8 +1884,8 @@ function writesWhenRewritten(name, command) {
1746
1884
  var CHECK_SCRIPT_NAMES = /* @__PURE__ */ new Set(["lint", "format", "check", "test", "typecheck", "verify"]);
1747
1885
 
1748
1886
  // src/roles/format/inherited-ignores.ts
1749
- import { existsSync as existsSync13, readFileSync as readFileSync10 } from "fs";
1750
- import { join as join14 } from "path";
1887
+ import { existsSync as existsSync14, readFileSync as readFileSync11 } from "fs";
1888
+ import { join as join15 } from "path";
1751
1889
  var ROOT_IGNORE_FILE = ".prettierignore";
1752
1890
  function isPattern(line) {
1753
1891
  const trimmed = line.trim();
@@ -1762,11 +1900,11 @@ function toModulePattern(pattern) {
1762
1900
  }
1763
1901
  function inheritedIgnorePatterns(workspaceRoot) {
1764
1902
  if (!workspaceRoot) return [];
1765
- const path = join14(workspaceRoot, ROOT_IGNORE_FILE);
1766
- if (!existsSync13(path)) return [];
1903
+ const path = join15(workspaceRoot, ROOT_IGNORE_FILE);
1904
+ if (!existsSync14(path)) return [];
1767
1905
  let contents;
1768
1906
  try {
1769
- contents = readFileSync10(path, "utf8");
1907
+ contents = readFileSync11(path, "utf8");
1770
1908
  } catch {
1771
1909
  return [];
1772
1910
  }
@@ -1810,56 +1948,14 @@ function needsSvelteCompiler(output) {
1810
1948
  return /svelte\/compiler/.test(output);
1811
1949
  }
1812
1950
 
1813
- // src/roles/format/presets/base.json
1814
- var base_default = {
1815
- printWidth: 80,
1816
- semi: false,
1817
- singleQuote: true,
1818
- trailingComma: "all",
1819
- sortPackageJson: false,
1820
- sortImports: false
1821
- };
1822
-
1823
- // src/roles/format/presets/nest-imports.json
1824
- var nest_imports_default = {
1825
- customGroups: [
1826
- {
1827
- groupName: "workspace",
1828
- elementNamePattern: ["@hublo/**", "@shared/**", "@front/**", "@network/**"]
1829
- }
1830
- ],
1831
- groups: ["builtin", "external", "workspace", ["parent", "index"], "sibling"],
1832
- newlinesBetween: true,
1833
- order: "asc",
1834
- ignoreCase: false
1835
- };
1836
-
1837
- // src/roles/format/preset-data.ts
1838
- var FORMAT_PRESETS = ["base", "svelte", "nest"];
1839
- function hasFormatPreset(name) {
1840
- return FORMAT_PRESETS.includes(name);
1841
- }
1842
- function formatPresetName(declared) {
1843
- if (declared === "svelte") return "svelte";
1844
- if (declared === "nest") return "nest";
1845
- return "base";
1846
- }
1847
- function formatPresetFor(preset) {
1848
- const base = base_default;
1849
- const name = formatPresetName(preset);
1850
- if (name === "svelte") return { ...base, svelte: true };
1851
- if (name === "nest") return { ...base, sortImports: nest_imports_default };
1852
- return base;
1853
- }
1854
-
1855
1951
  // src/roles/format/prettier-config.ts
1856
- import { existsSync as existsSync14, readFileSync as readFileSync12 } from "fs";
1857
- import { join as join16 } from "path";
1952
+ import { existsSync as existsSync15, readFileSync as readFileSync13 } from "fs";
1953
+ import { join as join17 } from "path";
1858
1954
 
1859
1955
  // src/roles/format/resolve-oxfmt.ts
1860
- import { readFileSync as readFileSync11 } from "fs";
1956
+ import { readFileSync as readFileSync12 } from "fs";
1861
1957
  import { createRequire as createRequire2 } from "module";
1862
- import { dirname as dirname4, join as join15 } from "path";
1958
+ import { dirname as dirname4, join as join16 } from "path";
1863
1959
  function resolveOxfmt(cwd) {
1864
1960
  return resolveBin(cwd, "oxfmt") ?? binFromOwnInstall("oxfmt", "oxfmt");
1865
1961
  }
@@ -1888,8 +1984,8 @@ function configSchema() {
1888
1984
  function readConfigSchema() {
1889
1985
  try {
1890
1986
  const manifest = createRequire2(import.meta.url).resolve("oxfmt/package.json");
1891
- const schemaPath = join15(dirname4(manifest), "configuration_schema.json");
1892
- return JSON.parse(readFileSync11(schemaPath, "utf8"));
1987
+ const schemaPath = join16(dirname4(manifest), "configuration_schema.json");
1988
+ return JSON.parse(readFileSync12(schemaPath, "utf8"));
1893
1989
  } catch {
1894
1990
  return void 0;
1895
1991
  }
@@ -1920,14 +2016,14 @@ function toOxfmtOverrides(value) {
1920
2016
  return { overrides, unresolved };
1921
2017
  }
1922
2018
  function readPrettierSettings(cwd) {
1923
- const file = PRETTIER_CONFIG_FILES.find((name) => existsSync14(join16(cwd, name)));
2019
+ const file = PRETTIER_CONFIG_FILES.find((name) => existsSync15(join17(cwd, name)));
1924
2020
  if (!file) return { options: {}, unresolved: [] };
1925
2021
  if (/\.(js|cjs|mjs)$/.test(file)) {
1926
2022
  return { options: {}, file, unresolved: [`${file} is JavaScript, so it was not executed`] };
1927
2023
  }
1928
2024
  let parsed;
1929
2025
  try {
1930
- parsed = parseJsonc(readFileSync12(join16(cwd, file), "utf8"), file);
2026
+ parsed = parseJsonc(readFileSync13(join17(cwd, file), "utf8"), file);
1931
2027
  } catch {
1932
2028
  return { options: {}, file, unresolved: [`${file} could not be parsed`] };
1933
2029
  }
@@ -1956,71 +2052,6 @@ function readPrettierSettings(cwd) {
1956
2052
  return { options, file, unresolved };
1957
2053
  }
1958
2054
 
1959
- // src/roles/format/read-adoption.ts
1960
- import { existsSync as existsSync15, readFileSync as readFileSync13 } from "fs";
1961
- import { join as join17 } from "path";
1962
- var NOT_ADOPTED2 = (configFile, unreadable = null) => ({
1963
- configFile,
1964
- preset: null,
1965
- adopted: false,
1966
- conformant: false,
1967
- drift: [],
1968
- local: {},
1969
- presetVersion: null,
1970
- effective: {},
1971
- unreadable
1972
- });
1973
- function sameValue(a, b) {
1974
- return JSON.stringify(a) === JSON.stringify(b);
1975
- }
1976
- function readFormatAdoption(cwd) {
1977
- const path = join17(cwd, FORMAT_CONFIG_FILE);
1978
- if (!existsSync15(path)) return NOT_ADOPTED2(null);
1979
- let parsed;
1980
- try {
1981
- parsed = parseJsonc(readFileSync13(path, "utf8"), FORMAT_CONFIG_FILE);
1982
- } catch (error) {
1983
- const reason = error instanceof Error ? error.message : String(error);
1984
- return NOT_ADOPTED2(FORMAT_CONFIG_FILE, `${FORMAT_CONFIG_FILE} could not be parsed (${reason})`);
1985
- }
1986
- const provenance = parsed[PROVENANCE_KEY];
1987
- if (!provenance || typeof provenance.preset !== "string") return NOT_ADOPTED2(FORMAT_CONFIG_FILE);
1988
- if (!hasFormatPreset(provenance.preset)) {
1989
- return NOT_ADOPTED2(
1990
- FORMAT_CONFIG_FILE,
1991
- `${FORMAT_CONFIG_FILE} declares the format preset "${provenance.preset}", which sentinel does not ship (shipped: ${FORMAT_PRESETS.join(", ")}). Re-run \`sentinel --init --format\`.`
1992
- );
1993
- }
1994
- const declaredLocal = Array.isArray(provenance.local) ? provenance.local : [];
1995
- const preset = formatPresetFor(provenance.preset);
1996
- const drift = [];
1997
- const local = {};
1998
- for (const [key, expected] of Object.entries(preset)) {
1999
- if (declaredLocal.includes(key)) {
2000
- local[key] = parsed[key];
2001
- continue;
2002
- }
2003
- if (!(key in parsed) || !sameValue(parsed[key], expected)) drift.push(key);
2004
- }
2005
- for (const key of declaredLocal) {
2006
- if (!(key in preset)) local[key] = parsed[key];
2007
- }
2008
- for (const key of ALWAYS_LOCAL_KEYS) {
2009
- if (key in parsed) local[key] = parsed[key];
2010
- }
2011
- return {
2012
- configFile: FORMAT_CONFIG_FILE,
2013
- preset: provenance.preset,
2014
- adopted: true,
2015
- conformant: drift.length === 0,
2016
- drift,
2017
- local,
2018
- presetVersion: typeof provenance.version === "string" ? provenance.version : null,
2019
- effective: parsed,
2020
- unreadable: null
2021
- };
2022
- }
2023
-
2024
2055
  // src/roles/format/unenforced.ts
2025
2056
  function unenforcedFormatOptions(options) {
2026
2057
  const gaps = [];
@@ -6600,4 +6631,4 @@ export {
6600
6631
  detectFramework,
6601
6632
  dispatch
6602
6633
  };
6603
- //# sourceMappingURL=chunk-C4BWV6SU.js.map
6634
+ //# sourceMappingURL=chunk-O7OXACCN.js.map
package/dist/index.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  registerAdapters,
8
8
  resolve,
9
9
  setDefaultRunner
10
- } from "./chunk-C4BWV6SU.js";
10
+ } from "./chunk-O7OXACCN.js";
11
11
  export {
12
12
  BaseAdapter,
13
13
  all,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hublo/sentinel",
3
- "version": "1.2.0-alpha.25",
3
+ "version": "1.2.0-alpha.26",
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",