@hublo/sentinel 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin/sentinel.js
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
WORKSPACE_ROOT_MARKER,
|
|
10
10
|
availableTargets,
|
|
11
11
|
buildConfigFile,
|
|
12
|
+
correctingSignal,
|
|
12
13
|
declaredPresetFor,
|
|
13
14
|
describeFramework,
|
|
14
15
|
dispatch,
|
|
@@ -22,7 +23,7 @@ import {
|
|
|
22
23
|
registerAdapters,
|
|
23
24
|
resolve,
|
|
24
25
|
resolveBin
|
|
25
|
-
} from "../chunk-
|
|
26
|
+
} from "../chunk-676GBPMS.js";
|
|
26
27
|
|
|
27
28
|
// bin/sentinel.ts
|
|
28
29
|
import { program } from "commander";
|
|
@@ -235,6 +236,7 @@ async function analyse(params) {
|
|
|
235
236
|
) + "\n"
|
|
236
237
|
);
|
|
237
238
|
}
|
|
239
|
+
preset2 = correctingSignal(preset2, module.root)?.preset ?? preset2;
|
|
238
240
|
}
|
|
239
241
|
for (const target of params.targets) {
|
|
240
242
|
let adapter;
|
|
@@ -655,7 +657,10 @@ program.name("sentinel").description("One CLI that guards code health: presets,
|
|
|
655
657
|
" sentinel --run --json # from root \u2192 all types, machine output",
|
|
656
658
|
" sentinel --run --ci # from root \u2192 affected only",
|
|
657
659
|
" sentinel --inspect --typescript # from root \u2192 adoption + what is deferred",
|
|
658
|
-
|
|
660
|
+
// Deliberately not enumerated here. A hand-written list drifts, and this one did: it
|
|
661
|
+
// still said "lint, format, typescript" after the build role shipped, so the help told
|
|
662
|
+
// adopters the build was not covered when it was. "Available now", below, is derived.
|
|
663
|
+
" sentinel --init --preset react # adopt every available role (see below)",
|
|
659
664
|
" sentinel --init --typescript --preset react # set up the current module + workspace",
|
|
660
665
|
" sentinel --run --typescript -- --noImplicitAny # ask the tool a question of your own"
|
|
661
666
|
].join("\n")
|
|
@@ -1503,6 +1503,7 @@ var NATIVE_TS_ALIAS = "@typescript/native";
|
|
|
1503
1503
|
var WORKSPACE_YAML = "pnpm-workspace.yaml";
|
|
1504
1504
|
var RELEASE_AGE_KEY = "minimumReleaseAgeExclude";
|
|
1505
1505
|
var LIST_ITEM = /^(\s*)-\s+(.*?)\s*$/;
|
|
1506
|
+
var MAP_ENTRY = /^(\s+)(.*?):\s+(.*?)\s*$/;
|
|
1506
1507
|
function findWorkspaceRoot(startDir) {
|
|
1507
1508
|
let dir = startDir;
|
|
1508
1509
|
for (; ; ) {
|
|
@@ -1524,14 +1525,50 @@ function ensureI18nextSingleton(root, dryRun) {
|
|
|
1524
1525
|
const pkg = JSON.parse(readFileSync10(pkgPath, "utf8"));
|
|
1525
1526
|
const want = declaredNativeTs(pkg);
|
|
1526
1527
|
if (!want) return void 0;
|
|
1527
|
-
const
|
|
1528
|
-
if (
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1528
|
+
const yamlPath = join12(root, WORKSPACE_YAML);
|
|
1529
|
+
if (!existsSync12(yamlPath)) return void 0;
|
|
1530
|
+
const lines = readFileSync10(yamlPath, "utf8").split("\n");
|
|
1531
|
+
const entry = findOverrideEntry(lines);
|
|
1532
|
+
if (entry.valueIdx !== void 0 && entry.value === want) return void 0;
|
|
1533
|
+
if (dryRun) return `would pin ${OVERRIDE_KEY} to ${want} in ${WORKSPACE_YAML} (i18next singleton)`;
|
|
1534
|
+
applyOverride(lines, entry, want);
|
|
1535
|
+
writeFileSync(yamlPath, lines.join("\n"));
|
|
1536
|
+
return `pinned ${OVERRIDE_KEY} to ${want} in ${WORKSPACE_YAML} (i18next singleton)`;
|
|
1537
|
+
}
|
|
1538
|
+
function findOverrideEntry(lines) {
|
|
1539
|
+
const blockIdx = lines.findIndex((line) => line.replace(/\s+$/, "") === "overrides:");
|
|
1540
|
+
if (blockIdx === -1) return { indent: " " };
|
|
1541
|
+
let lastEntryIdx = blockIdx;
|
|
1542
|
+
let indent = " ";
|
|
1543
|
+
for (let i = blockIdx + 1; i < lines.length; i++) {
|
|
1544
|
+
const match = lines[i]?.match(MAP_ENTRY);
|
|
1545
|
+
if (!match) break;
|
|
1546
|
+
indent = match[1] ?? indent;
|
|
1547
|
+
lastEntryIdx = i;
|
|
1548
|
+
if ((match[2] ?? "").replace(/^['"]|['"]$/g, "") === OVERRIDE_KEY) {
|
|
1549
|
+
return {
|
|
1550
|
+
valueIdx: i,
|
|
1551
|
+
value: (match[3] ?? "").replace(/^['"]|['"]$/g, ""),
|
|
1552
|
+
blockIdx,
|
|
1553
|
+
lastEntryIdx,
|
|
1554
|
+
indent
|
|
1555
|
+
};
|
|
1556
|
+
}
|
|
1557
|
+
}
|
|
1558
|
+
return { blockIdx, lastEntryIdx, indent };
|
|
1559
|
+
}
|
|
1560
|
+
function applyOverride(lines, entry, want) {
|
|
1561
|
+
const line = `${entry.indent}'${OVERRIDE_KEY}': ${want}`;
|
|
1562
|
+
if (entry.valueIdx !== void 0) {
|
|
1563
|
+
lines[entry.valueIdx] = line;
|
|
1564
|
+
return;
|
|
1565
|
+
}
|
|
1566
|
+
if (entry.lastEntryIdx !== void 0) {
|
|
1567
|
+
lines.splice(entry.lastEntryIdx + 1, 0, line);
|
|
1568
|
+
return;
|
|
1569
|
+
}
|
|
1570
|
+
while (lines.length > 0 && lines[lines.length - 1] === "") lines.pop();
|
|
1571
|
+
lines.push("overrides:", line, "");
|
|
1535
1572
|
}
|
|
1536
1573
|
function ensureReleaseAgeAllowList(root, dryRun) {
|
|
1537
1574
|
const yamlPath = join12(root, WORKSPACE_YAML);
|
|
@@ -1620,18 +1657,25 @@ function inspectWorkspacePrep(root) {
|
|
|
1620
1657
|
pkg = {};
|
|
1621
1658
|
}
|
|
1622
1659
|
}
|
|
1623
|
-
const
|
|
1660
|
+
const yamlPath = join12(root, WORKSPACE_YAML);
|
|
1661
|
+
const yaml = existsSync12(yamlPath) ? readFileSync10(yamlPath, "utf8") : void 0;
|
|
1662
|
+
const pinned = yaml === void 0 ? void 0 : findOverrideEntry(yaml.split("\n")).value;
|
|
1624
1663
|
if (pinned !== void 0) {
|
|
1625
1664
|
const stillForks = declaredNativeTs(pkg);
|
|
1626
1665
|
entries.push({
|
|
1627
|
-
rule:
|
|
1666
|
+
rule: `${WORKSPACE_YAML} \u2192 overrides.${OVERRIDE_KEY}`,
|
|
1628
1667
|
reason: stillForks === void 0 ? `pinned to ${pinned}, but the root no longer declares ${NATIVE_TS_ALIAS}, so nothing forks any more. This override is now dead config and can be removed.` : `pinned to ${pinned}, matching the second TypeScript the root declares (${NATIVE_TS_ALIAS}). It re-resolves i18next for EVERY module that depends on it, not only adopted ones. It retires with the second TypeScript.`
|
|
1629
1668
|
});
|
|
1630
1669
|
}
|
|
1670
|
+
const legacy = pkg.pnpm?.overrides?.[OVERRIDE_KEY];
|
|
1671
|
+
if (legacy !== void 0) {
|
|
1672
|
+
entries.push({
|
|
1673
|
+
rule: `package.json \u2192 pnpm.overrides.${OVERRIDE_KEY}`,
|
|
1674
|
+
reason: `pinned to ${legacy}, but pnpm 11 no longer reads the \`pnpm\` field of package.json and says nothing about it, so this override is not applied. Move it to ${WORKSPACE_YAML} under \`overrides:\`, which pnpm 10 and 11 both read.`
|
|
1675
|
+
});
|
|
1676
|
+
}
|
|
1631
1677
|
const own = readOwnPackage().name;
|
|
1632
|
-
|
|
1633
|
-
if (existsSync12(yamlPath)) {
|
|
1634
|
-
const yaml = readFileSync10(yamlPath, "utf8");
|
|
1678
|
+
if (yaml !== void 0) {
|
|
1635
1679
|
const listed = new RegExp(`^\\s*-\\s*['"]?${own.replace("/", "\\/")}['"]?\\s*$`, "m").test(yaml);
|
|
1636
1680
|
if (listed) {
|
|
1637
1681
|
const gated = new RegExp(`^\\s*minimumReleaseAge\\s*:`, "m").test(yaml);
|
|
@@ -1951,6 +1995,7 @@ function toModulePattern(pattern) {
|
|
|
1951
1995
|
const trimmed = pattern.trim();
|
|
1952
1996
|
if (trimmed.startsWith("!")) return void 0;
|
|
1953
1997
|
if (trimmed.startsWith("/**/")) return trimmed.slice(1);
|
|
1998
|
+
if (trimmed.startsWith("**/")) return trimmed;
|
|
1954
1999
|
if (trimmed.startsWith("/")) return void 0;
|
|
1955
2000
|
return trimmed.replace(/\/$/, "").includes("/") ? void 0 : trimmed;
|
|
1956
2001
|
}
|
|
@@ -6475,7 +6520,11 @@ var PATH_SIGNALS = [
|
|
|
6475
6520
|
}
|
|
6476
6521
|
];
|
|
6477
6522
|
var DEPENDENCY_SIGNALS = [
|
|
6478
|
-
|
|
6523
|
+
// Runtime dependencies only. `eslint-plugin-react*` used to count here, but a lint plugin is
|
|
6524
|
+
// TOOLING: this very repo depends on `eslint-plugin-react-refresh` to ship React rules to
|
|
6525
|
+
// other projects, and was therefore read as a React app itself. No module in the monorepo
|
|
6526
|
+
// carries an `eslint-plugin-react*` without also carrying react, so nothing loses detection.
|
|
6527
|
+
{ preset: "react", pattern: /^(react|react-dom|@types\/react)$/ },
|
|
6479
6528
|
{ preset: "svelte", pattern: /^svelte$|^@sveltejs\// },
|
|
6480
6529
|
{ preset: "nest", pattern: /^@nestjs\// }
|
|
6481
6530
|
];
|
|
@@ -6534,6 +6583,10 @@ function presetSignals(cwd) {
|
|
|
6534
6583
|
}
|
|
6535
6584
|
return signals;
|
|
6536
6585
|
}
|
|
6586
|
+
function correctingSignal(detected, cwd) {
|
|
6587
|
+
const [signal] = presetSignals(cwd);
|
|
6588
|
+
return signal !== void 0 && signal.preset !== detected ? signal : void 0;
|
|
6589
|
+
}
|
|
6537
6590
|
function presetContradiction(declared, cwd) {
|
|
6538
6591
|
const signals = presetSignals(cwd);
|
|
6539
6592
|
if (signals.length === 0) return void 0;
|
|
@@ -6614,8 +6667,8 @@ async function dispatch(opts) {
|
|
|
6614
6667
|
}
|
|
6615
6668
|
let effective = preset;
|
|
6616
6669
|
if (opts.preset === void 0 && adapter.declaredPreset?.(opts.cwd) === void 0) {
|
|
6617
|
-
const
|
|
6618
|
-
if (signal !== void 0
|
|
6670
|
+
const signal = correctingSignal(preset, opts.cwd);
|
|
6671
|
+
if (signal !== void 0) {
|
|
6619
6672
|
effective = signal.preset;
|
|
6620
6673
|
process.stderr.write(
|
|
6621
6674
|
` detected "${preset}" from dependencies, but ${signal.evidence}, so adopting as "${signal.preset}". Pass --preset to override.
|
|
@@ -6683,8 +6736,9 @@ export {
|
|
|
6683
6736
|
PRESET_NAMES,
|
|
6684
6737
|
palette,
|
|
6685
6738
|
registerAdapters,
|
|
6739
|
+
correctingSignal,
|
|
6686
6740
|
describeFramework,
|
|
6687
6741
|
detectFramework,
|
|
6688
6742
|
dispatch
|
|
6689
6743
|
};
|
|
6690
|
-
//# sourceMappingURL=chunk-
|
|
6744
|
+
//# sourceMappingURL=chunk-676GBPMS.js.map
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hublo/sentinel",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
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",
|