@hublo/sentinel 1.4.0-alpha.21 → 1.4.0-alpha.23
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
|
@@ -5406,9 +5406,7 @@ function registerLint() {
|
|
|
5406
5406
|
|
|
5407
5407
|
// src/roles/test/adapters/vitest/vitest.adapter.ts
|
|
5408
5408
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
5409
|
-
import {
|
|
5410
|
-
import { tmpdir as tmpdir2 } from "node:os";
|
|
5411
|
-
import { isAbsolute as isAbsolute3, join as join39, resolve as resolve6 } from "node:path";
|
|
5409
|
+
import { isAbsolute as isAbsolute3, resolve as resolve6 } from "node:path";
|
|
5412
5410
|
|
|
5413
5411
|
// src/roles/test/presets/toolchain.json
|
|
5414
5412
|
var toolchain_default2 = {
|
|
@@ -7848,11 +7846,13 @@ function concurrencyBlock(cwd, reading, target) {
|
|
|
7848
7846
|
if (declared !== void 0) {
|
|
7849
7847
|
return declared === "1" ? ` fileParallelism: false,` : ` maxWorkers: ${declared},`;
|
|
7850
7848
|
}
|
|
7851
|
-
const
|
|
7852
|
-
|
|
7853
|
-
|
|
7854
|
-
|
|
7855
|
-
|
|
7849
|
+
const nxTarget = projectTargets(cwd)?.[target];
|
|
7850
|
+
for (const level of [nxTarget?.options, nxTarget?.configurations?.ci]) {
|
|
7851
|
+
if (level === void 0) continue;
|
|
7852
|
+
if (level.runInBand === true) return ` fileParallelism: false,`;
|
|
7853
|
+
if (typeof level.maxWorkers === "number") {
|
|
7854
|
+
return level.maxWorkers === 1 ? ` fileParallelism: false,` : ` maxWorkers: ${level.maxWorkers},`;
|
|
7855
|
+
}
|
|
7856
7856
|
}
|
|
7857
7857
|
return "";
|
|
7858
7858
|
}
|
|
@@ -8703,166 +8703,6 @@ function readSnapshot(report) {
|
|
|
8703
8703
|
claimedFailing: typeof claimed === "number" ? claimed : failing.length
|
|
8704
8704
|
};
|
|
8705
8705
|
}
|
|
8706
|
-
function difference(left, right) {
|
|
8707
|
-
const remaining = /* @__PURE__ */ new Map();
|
|
8708
|
-
for (const name of right) remaining.set(name, (remaining.get(name) ?? 0) + 1);
|
|
8709
|
-
const missing = [];
|
|
8710
|
-
for (const name of left) {
|
|
8711
|
-
const left_ = remaining.get(name) ?? 0;
|
|
8712
|
-
if (left_ === 0) {
|
|
8713
|
-
missing.push(name);
|
|
8714
|
-
continue;
|
|
8715
|
-
}
|
|
8716
|
-
remaining.set(name, left_ - 1);
|
|
8717
|
-
}
|
|
8718
|
-
return missing.sort();
|
|
8719
|
-
}
|
|
8720
|
-
var withoutRenderingQuotes = (name) => name.replaceAll(String.raw`\'`, "'").replaceAll(String.raw`\"`, '"').replaceAll(/['"`]\s*\+\s*['"`]/g, "").replaceAll(/(^|[\s:,[{(])(''|"")($|[\s,)\]}])/g, "$1<empty-string>$3").replaceAll(/['"`]/g, "");
|
|
8721
|
-
function withoutRenderingNoise(name) {
|
|
8722
|
-
const spelled = withSortedKeys(
|
|
8723
|
-
withoutUndefinedEntries(
|
|
8724
|
-
withoutErrorRendering(
|
|
8725
|
-
withoutNaN(
|
|
8726
|
-
withoutTimestamps(withoutRenderingQuotes(withoutClassBodies(withoutStackFrames(name))))
|
|
8727
|
-
)
|
|
8728
|
-
)
|
|
8729
|
-
)
|
|
8730
|
-
);
|
|
8731
|
-
return withoutArrayBrackets(
|
|
8732
|
-
spelled.replaceAll(/\[\s+/g, "[").replaceAll(/\s+\]/g, "]").replaceAll(/\{\s+/g, "{").replaceAll(/\s+\}/g, "}").replaceAll(/(?<=[[{,\s])\+0\b/g, "0").replaceAll(/:\s+/g, ":").replaceAll(/,\s+/g, ",")
|
|
8733
|
-
);
|
|
8734
|
-
}
|
|
8735
|
-
function withoutArrayBrackets(name) {
|
|
8736
|
-
return name.replaceAll(
|
|
8737
|
-
/\[([^[\]]*)\]/g,
|
|
8738
|
-
(match, inner) => (
|
|
8739
|
-
// `[Object]` and `[Array]` are the formatter saying it STOPPED, not an array literal.
|
|
8740
|
-
// Stripping their brackets would erase the marker `collapsedOf` pairs on.
|
|
8741
|
-
/^(?:Object|Array)$/.test(inner) ? match : inner.replaceAll(/,\s+/g, ",")
|
|
8742
|
-
)
|
|
8743
|
-
);
|
|
8744
|
-
}
|
|
8745
|
-
var withoutClassBodies = (name) => name.replaceAll(
|
|
8746
|
-
/class\s+([A-Za-z_$][\w$]*)\s*\{\s*\}/g,
|
|
8747
|
-
(_match, className) => `class ${className}`
|
|
8748
|
-
).replaceAll(
|
|
8749
|
-
/class\s+([A-Za-z_$][\w$]*)[\s\S]*?\n\}/g,
|
|
8750
|
-
(_match, className) => `class ${className}`
|
|
8751
|
-
);
|
|
8752
|
-
var withoutTimestamps = (name) => name.replaceAll(/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z/g, "<instant>");
|
|
8753
|
-
var withoutNaN = (name) => name.replaceAll(/\bNaN\b/g, "null");
|
|
8754
|
-
function entriesOf(inner) {
|
|
8755
|
-
const parts = [];
|
|
8756
|
-
let depth = 0;
|
|
8757
|
-
let start = 0;
|
|
8758
|
-
for (let index = 0; index < inner.length; index += 1) {
|
|
8759
|
-
const character = inner[index];
|
|
8760
|
-
if (character === "[" || character === "(") depth += 1;
|
|
8761
|
-
else if (character === "]" || character === ")") depth -= 1;
|
|
8762
|
-
else if (character === "," && depth === 0) {
|
|
8763
|
-
parts.push(inner.slice(start, index));
|
|
8764
|
-
start = index + 1;
|
|
8765
|
-
}
|
|
8766
|
-
if (depth < 0) return void 0;
|
|
8767
|
-
}
|
|
8768
|
-
if (depth !== 0) return void 0;
|
|
8769
|
-
parts.push(inner.slice(start));
|
|
8770
|
-
return parts.map((part) => part.trim()).filter(Boolean);
|
|
8771
|
-
}
|
|
8772
|
-
var sortedGroup = (match, inner) => {
|
|
8773
|
-
if (!inner.includes(":")) return match;
|
|
8774
|
-
const parts = entriesOf(inner);
|
|
8775
|
-
if (parts === void 0) return match;
|
|
8776
|
-
if (parts.length < 2 || !parts.every((part) => part.includes(":"))) return match;
|
|
8777
|
-
return `{${[...parts].sort().join(",")}}`;
|
|
8778
|
-
};
|
|
8779
|
-
var HELD = "\u241F";
|
|
8780
|
-
var withSortedKeys = (name) => {
|
|
8781
|
-
const held = [];
|
|
8782
|
-
let current = name;
|
|
8783
|
-
for (let depth = 0; depth < 24; depth += 1) {
|
|
8784
|
-
const next = current.replaceAll(/\{([^{}]*)\}/g, (match, inner) => {
|
|
8785
|
-
held.push(sortedGroup(match, inner));
|
|
8786
|
-
return `${HELD}${held.length - 1}${HELD}`;
|
|
8787
|
-
});
|
|
8788
|
-
if (next === current) break;
|
|
8789
|
-
current = next;
|
|
8790
|
-
}
|
|
8791
|
-
for (let depth = 0; depth < 24 && current.includes(HELD); depth += 1) {
|
|
8792
|
-
current = current.replaceAll(
|
|
8793
|
-
new RegExp(`${HELD}(\\d+)${HELD}`, "g"),
|
|
8794
|
-
(_match, index) => held[Number(index)]
|
|
8795
|
-
);
|
|
8796
|
-
}
|
|
8797
|
-
return current;
|
|
8798
|
-
};
|
|
8799
|
-
var withoutStackFrames = (name) => {
|
|
8800
|
-
const frame = name.search(/\n\s+at\s/);
|
|
8801
|
-
return frame === -1 ? name : name.slice(0, frame);
|
|
8802
|
-
};
|
|
8803
|
-
var withoutErrorRendering = (name) => name.replaceAll(/\[[A-Za-z]*(?:Error|Exception):[^\][]*\]/g, "{}");
|
|
8804
|
-
var withoutUndefinedEntries = (name) => name.replaceAll(/([{,])\s*[A-Za-z_$][\w$]*\s*:\s*undefined\s*(?=[,}])/g, "$1").replaceAll(/\{\s*,/g, "{").replaceAll(/,\s*\}/g, "}").replaceAll(/\{\s*\}/g, "{}");
|
|
8805
|
-
function collapsedOf(candidate, name) {
|
|
8806
|
-
if (!/\[(?:Object|Array)\]/.test(candidate)) return false;
|
|
8807
|
-
const pattern = candidate.split(/\[(?:Object|Array)\]/).map((part) => part.replaceAll(/[.*+?^${}()|[\]\\]/g, "\\$&")).join(".*");
|
|
8808
|
-
return new RegExp(`^${pattern}$`, "s").test(name);
|
|
8809
|
-
}
|
|
8810
|
-
function truncationOf(candidate, name) {
|
|
8811
|
-
const cut = candidate.indexOf("\u2026");
|
|
8812
|
-
if (cut === -1) return false;
|
|
8813
|
-
const head = candidate.slice(0, cut);
|
|
8814
|
-
const tail = candidate.slice(cut + 1);
|
|
8815
|
-
return name.startsWith(head) && name.endsWith(tail);
|
|
8816
|
-
}
|
|
8817
|
-
function pairRenamed(missing, added) {
|
|
8818
|
-
const remaining = [...added];
|
|
8819
|
-
const renamed = [];
|
|
8820
|
-
const unmatched = [];
|
|
8821
|
-
for (const name of missing) {
|
|
8822
|
-
const normalised = withoutRenderingNoise(name);
|
|
8823
|
-
const at = remaining.findIndex((candidate) => withoutRenderingNoise(candidate) === normalised);
|
|
8824
|
-
if (at === -1) {
|
|
8825
|
-
unmatched.push(name);
|
|
8826
|
-
continue;
|
|
8827
|
-
}
|
|
8828
|
-
renamed.push({ before: name, after: remaining[at] });
|
|
8829
|
-
remaining.splice(at, 1);
|
|
8830
|
-
}
|
|
8831
|
-
const lost = [];
|
|
8832
|
-
for (const name of unmatched) {
|
|
8833
|
-
const normalised = withoutRenderingNoise(name);
|
|
8834
|
-
const at = remaining.findIndex(
|
|
8835
|
-
(candidate) => truncationOf(withoutRenderingNoise(candidate), normalised) || collapsedOf(normalised, withoutRenderingNoise(candidate))
|
|
8836
|
-
);
|
|
8837
|
-
if (at === -1) {
|
|
8838
|
-
lost.push(name);
|
|
8839
|
-
continue;
|
|
8840
|
-
}
|
|
8841
|
-
renamed.push({ before: name, after: remaining[at] });
|
|
8842
|
-
remaining.splice(at, 1);
|
|
8843
|
-
}
|
|
8844
|
-
return { renamed, missing: lost, added: remaining };
|
|
8845
|
-
}
|
|
8846
|
-
function compareSnapshots(before, after) {
|
|
8847
|
-
const beforeAll = [...before.passing, ...before.failing];
|
|
8848
|
-
const afterAll = [...after.passing, ...after.failing];
|
|
8849
|
-
const paired = pairRenamed(difference(beforeAll, afterAll), difference(afterAll, beforeAll));
|
|
8850
|
-
const renamedBefore = new Set(paired.renamed.map((pair) => pair.before));
|
|
8851
|
-
const regressed = difference(before.passing, after.passing).filter(
|
|
8852
|
-
(name) => !paired.missing.includes(name) && !renamedBefore.has(name)
|
|
8853
|
-
);
|
|
8854
|
-
const failedBefore = new Set(before.failing);
|
|
8855
|
-
const recovered = after.passing.filter((name) => failedBefore.has(name));
|
|
8856
|
-
return {
|
|
8857
|
-
identical: paired.missing.length === 0 && paired.added.length === 0 && regressed.length === 0,
|
|
8858
|
-
missing: paired.missing,
|
|
8859
|
-
added: paired.added,
|
|
8860
|
-
regressed,
|
|
8861
|
-
renamed: paired.renamed,
|
|
8862
|
-
recovered,
|
|
8863
|
-
alreadyFailing: before.failing.length
|
|
8864
|
-
};
|
|
8865
|
-
}
|
|
8866
8706
|
function unusableAsBaseline(snapshot) {
|
|
8867
8707
|
if (snapshot.unloadable.length > 0) {
|
|
8868
8708
|
return `${snapshot.unloadable.length} file(s) in the reference run did not load, so they reported no test at all and the run is short by however many they hold: ${snapshot.unloadable.slice(0, 3).join(", ")}. A reference that quietly lost tests cannot prove anything about the run after it`;
|
|
@@ -8875,45 +8715,6 @@ function unusableAsBaseline(snapshot) {
|
|
|
8875
8715
|
}
|
|
8876
8716
|
return void 0;
|
|
8877
8717
|
}
|
|
8878
|
-
function renamedExample(before, after) {
|
|
8879
|
-
let shared = 0;
|
|
8880
|
-
while (shared < before.length && shared < after.length && before[shared] === after[shared]) {
|
|
8881
|
-
shared += 1;
|
|
8882
|
-
}
|
|
8883
|
-
const boundary = before.lastIndexOf(" ", shared);
|
|
8884
|
-
const from = boundary > 0 ? boundary + 1 : 0;
|
|
8885
|
-
const ellipsis = from > 0 ? "\u2026" : "";
|
|
8886
|
-
return `"${ellipsis}${before.slice(from)}" -> "${ellipsis}${after.slice(from)}"`;
|
|
8887
|
-
}
|
|
8888
|
-
function describeComparison(comparison) {
|
|
8889
|
-
const firstRename = comparison.renamed[0];
|
|
8890
|
-
const renamedNote = firstRename === void 0 ? "" : ` ${comparison.renamed.length} test(s) kept their identity and changed name, because the runners render an each title's interpolated value differently (e.g. ${renamedExample(firstRename.before, firstRename.after)}).`;
|
|
8891
|
-
const alreadyRedNote = comparison.alreadyFailing > 0 ? ` ${comparison.alreadyFailing} test(s) were already failing before the migration and are outside this comparison, which covers only what passed.` : "";
|
|
8892
|
-
const recoveredNote = comparison.recovered.length > 0 ? ` ${comparison.recovered.length} test(s) were failing before and pass now.` : "";
|
|
8893
|
-
if (comparison.identical) {
|
|
8894
|
-
return `every test that ran before runs and passes now.${recoveredNote}${renamedNote}${alreadyRedNote}`;
|
|
8895
|
-
}
|
|
8896
|
-
const parts = [];
|
|
8897
|
-
if (comparison.recovered.length > 0) {
|
|
8898
|
-
parts.push(`${comparison.recovered.length} test(s) were failing before and pass now`);
|
|
8899
|
-
}
|
|
8900
|
-
if (comparison.missing.length > 0) {
|
|
8901
|
-
parts.push(
|
|
8902
|
-
`${comparison.missing.length} test(s) no longer exist: ${comparison.missing.slice(0, 3).join(", ")}`
|
|
8903
|
-
);
|
|
8904
|
-
}
|
|
8905
|
-
if (comparison.added.length > 0) {
|
|
8906
|
-
parts.push(
|
|
8907
|
-
`${comparison.added.length} test(s) appeared, which a migration should not do: ${comparison.added.slice(0, 3).join(", ")}`
|
|
8908
|
-
);
|
|
8909
|
-
}
|
|
8910
|
-
if (comparison.regressed.length > 0) {
|
|
8911
|
-
parts.push(
|
|
8912
|
-
`${comparison.regressed.length} test(s) passed before and do not now: ${comparison.regressed.slice(0, 3).join(", ")}`
|
|
8913
|
-
);
|
|
8914
|
-
}
|
|
8915
|
-
return `${parts.join("; ")}.${renamedNote}${alreadyRedNote}`;
|
|
8916
|
-
}
|
|
8917
8718
|
|
|
8918
8719
|
// src/roles/test/reference.ts
|
|
8919
8720
|
function referencePath(cwd) {
|
|
@@ -8971,26 +8772,6 @@ function captureReference(cwd, config) {
|
|
|
8971
8772
|
message: `recorded ${snapshot.passing.length} passing test name(s) from ${config} as the reference. The next \`sentinel --run --test\` compares against it.`
|
|
8972
8773
|
};
|
|
8973
8774
|
}
|
|
8974
|
-
function hasReference(cwd) {
|
|
8975
|
-
return existsSync31(referencePath(cwd));
|
|
8976
|
-
}
|
|
8977
|
-
function compareAgainstReference(cwd, report) {
|
|
8978
|
-
const path = referencePath(cwd);
|
|
8979
|
-
let stored;
|
|
8980
|
-
try {
|
|
8981
|
-
stored = JSON.parse(readFileSync30(path, "utf8"));
|
|
8982
|
-
} catch {
|
|
8983
|
-
rmSync3(path, { force: true });
|
|
8984
|
-
return { ok: true, message: `the recorded reference could not be read, so nothing was proved.` };
|
|
8985
|
-
}
|
|
8986
|
-
const comparison = compareSnapshots(stored.snapshot, readSnapshot(report));
|
|
8987
|
-
if (comparison.identical) rmSync3(path, { force: true });
|
|
8988
|
-
const kept = comparison.identical ? "" : ` The reference is KEPT until a run passes it, so this does not go green by running again. Fix the suite and re-run, or delete ${path} to abandon the proof on purpose.`;
|
|
8989
|
-
return {
|
|
8990
|
-
ok: comparison.identical,
|
|
8991
|
-
message: `${describeComparison(comparison)} (reference: ${stored.config}, ${stored.takenAt})${kept}`
|
|
8992
|
-
};
|
|
8993
|
-
}
|
|
8994
8775
|
|
|
8995
8776
|
// src/roles/test/adapters/vitest/vitest.adapter.ts
|
|
8996
8777
|
function resolveVitest(cwd) {
|
|
@@ -9144,31 +8925,13 @@ var VitestAdapter = class extends BaseAdapter {
|
|
|
9144
8925
|
});
|
|
9145
8926
|
const { cwd: runFrom, options, paths } = fromWorkspaceRoot(ctx.cwd, typedOptions, typedPaths);
|
|
9146
8927
|
const watching = options.includes("--watch") || options.includes("-w");
|
|
9147
|
-
const
|
|
9148
|
-
const reportFile = proving ? join39(mkdtempSync2(join39(tmpdir2(), "sentinel-run-")), "vitest.json") : void 0;
|
|
9149
|
-
const reporters = reportFile === void 0 ? [] : ["--reporter=default", "--reporter=json", `--outputFile=${reportFile}`];
|
|
9150
|
-
const argv = watching ? [...options, ...paths] : ["run", ...reporters, ...options, ...paths];
|
|
8928
|
+
const argv = watching ? [...options, ...paths] : ["run", ...options, ...paths];
|
|
9151
8929
|
const result = spawnSync5(bin, argv, { cwd: runFrom, stdio: "inherit" });
|
|
9152
8930
|
if (result.error) {
|
|
9153
8931
|
this.say(`could not run vitest (${result.error.message})`);
|
|
9154
8932
|
return Promise.resolve({ ok: false, code: 1 });
|
|
9155
8933
|
}
|
|
9156
8934
|
const code = result.status ?? 1;
|
|
9157
|
-
if (reportFile !== void 0) {
|
|
9158
|
-
let report;
|
|
9159
|
-
try {
|
|
9160
|
-
report = JSON.parse(readFileSync31(reportFile, "utf8"));
|
|
9161
|
-
} catch {
|
|
9162
|
-
report = void 0;
|
|
9163
|
-
}
|
|
9164
|
-
if (report === void 0) {
|
|
9165
|
-
this.say(`vitest wrote no report, so this run proved nothing against the reference.`);
|
|
9166
|
-
} else {
|
|
9167
|
-
const outcome = compareAgainstReference(ctx.cwd, report);
|
|
9168
|
-
this.say(outcome.message);
|
|
9169
|
-
if (!outcome.ok) return Promise.resolve({ ok: false, code: code === 0 ? 1 : code });
|
|
9170
|
-
}
|
|
9171
|
-
}
|
|
9172
8935
|
return Promise.resolve({ ok: code === 0, code });
|
|
9173
8936
|
}
|
|
9174
8937
|
say(message) {
|
|
@@ -9210,9 +8973,9 @@ function registerTest() {
|
|
|
9210
8973
|
|
|
9211
8974
|
// src/roles/typescript/adapters/tsc/tsc.adapter.ts
|
|
9212
8975
|
import { spawnSync as spawnSync6 } from "node:child_process";
|
|
9213
|
-
import { existsSync as existsSync32, readFileSync as
|
|
8976
|
+
import { existsSync as existsSync32, readFileSync as readFileSync32 } from "node:fs";
|
|
9214
8977
|
import { createRequire as createRequire7 } from "node:module";
|
|
9215
|
-
import { join as
|
|
8978
|
+
import { join as join40 } from "node:path";
|
|
9216
8979
|
|
|
9217
8980
|
// src/roles/typescript/presets/nest.json
|
|
9218
8981
|
var nest_default2 = {
|
|
@@ -9393,8 +9156,8 @@ function readTsconfigAdoption(cwd) {
|
|
|
9393
9156
|
}
|
|
9394
9157
|
|
|
9395
9158
|
// src/roles/typescript/adapters/tsc/plan.ts
|
|
9396
|
-
import { readFileSync as
|
|
9397
|
-
import { join as
|
|
9159
|
+
import { readFileSync as readFileSync31 } from "node:fs";
|
|
9160
|
+
import { join as join39 } from "node:path";
|
|
9398
9161
|
|
|
9399
9162
|
// src/roles/typescript/typecheck-script.ts
|
|
9400
9163
|
var SENTINEL_TYPECHECK_COMMAND = "sentinel --run --typescript";
|
|
@@ -9487,7 +9250,7 @@ function planAdoption(context) {
|
|
|
9487
9250
|
};
|
|
9488
9251
|
}
|
|
9489
9252
|
const existing = parseJsonc(
|
|
9490
|
-
|
|
9253
|
+
readFileSync31(join39(context.cwd, target.path), "utf8"),
|
|
9491
9254
|
target.path
|
|
9492
9255
|
);
|
|
9493
9256
|
const extendsChain = composeExtends(existing.extends, preset);
|
|
@@ -9625,7 +9388,7 @@ var TscAdapter = class _TscAdapter extends BaseAdapter {
|
|
|
9625
9388
|
let chain;
|
|
9626
9389
|
try {
|
|
9627
9390
|
const parsed = parseJsonc(
|
|
9628
|
-
|
|
9391
|
+
readFileSync32(join40(cwd, target.path), "utf8"),
|
|
9629
9392
|
target.path
|
|
9630
9393
|
);
|
|
9631
9394
|
chain = parsed.extends;
|
|
@@ -9638,7 +9401,7 @@ var TscAdapter = class _TscAdapter extends BaseAdapter {
|
|
|
9638
9401
|
);
|
|
9639
9402
|
if (preset === void 0) return void 0;
|
|
9640
9403
|
try {
|
|
9641
|
-
createRequire7(
|
|
9404
|
+
createRequire7(join40(cwd, "noop.js")).resolve(preset);
|
|
9642
9405
|
return void 0;
|
|
9643
9406
|
} catch {
|
|
9644
9407
|
return preset;
|
|
@@ -9734,7 +9497,7 @@ var TscAdapter = class _TscAdapter extends BaseAdapter {
|
|
|
9734
9497
|
referencedProjects(cwd, config) {
|
|
9735
9498
|
try {
|
|
9736
9499
|
const parsed = parseJsonc(
|
|
9737
|
-
|
|
9500
|
+
readFileSync32(join40(cwd, config), "utf8"),
|
|
9738
9501
|
config
|
|
9739
9502
|
);
|
|
9740
9503
|
const referenced = (parsed.references ?? []).map((reference) => reference.path).filter((path) => typeof path === "string" && path.length > 0);
|
|
@@ -9750,7 +9513,7 @@ var TscAdapter = class _TscAdapter extends BaseAdapter {
|
|
|
9750
9513
|
* check.
|
|
9751
9514
|
*/
|
|
9752
9515
|
typecheckTarget(cwd) {
|
|
9753
|
-
if (existsSync32(
|
|
9516
|
+
if (existsSync32(join40(cwd, "tsconfig.json"))) return "tsconfig.json";
|
|
9754
9517
|
const target = resolveTsconfigTarget(cwd);
|
|
9755
9518
|
return target.reason === "none" ? null : target.path;
|
|
9756
9519
|
}
|
|
@@ -9955,7 +9718,7 @@ function replaceLines(current, replacements) {
|
|
|
9955
9718
|
}
|
|
9956
9719
|
|
|
9957
9720
|
// src/core/apply-plan.ts
|
|
9958
|
-
import { existsSync as existsSync33, readFileSync as
|
|
9721
|
+
import { existsSync as existsSync33, readFileSync as readFileSync33, renameSync, rmSync as rmSync4, writeFileSync as writeFileSync4 } from "node:fs";
|
|
9959
9722
|
import { resolve as resolve7, sep } from "node:path";
|
|
9960
9723
|
import { applyEdits as applyEdits3, findNodeAtLocation, modify, parseTree } from "jsonc-parser";
|
|
9961
9724
|
|
|
@@ -9974,7 +9737,7 @@ function resolveWithinRoot(cwd, relativePath) {
|
|
|
9974
9737
|
return absolutePath;
|
|
9975
9738
|
}
|
|
9976
9739
|
function readIfExists(absolutePath) {
|
|
9977
|
-
return existsSync33(absolutePath) ?
|
|
9740
|
+
return existsSync33(absolutePath) ? readFileSync33(absolutePath, "utf8") : void 0;
|
|
9978
9741
|
}
|
|
9979
9742
|
function* leaves(value, prefix = []) {
|
|
9980
9743
|
for (const [key, keyValue] of Object.entries(value)) {
|
|
@@ -10092,8 +9855,8 @@ function applyPlan(cwd, plan4) {
|
|
|
10092
9855
|
}
|
|
10093
9856
|
|
|
10094
9857
|
// src/core/config/preset-evidence.ts
|
|
10095
|
-
import { existsSync as existsSync34, readdirSync as readdirSync9, readFileSync as
|
|
10096
|
-
import { join as
|
|
9858
|
+
import { existsSync as existsSync34, readdirSync as readdirSync9, readFileSync as readFileSync34 } from "node:fs";
|
|
9859
|
+
import { join as join41 } from "node:path";
|
|
10097
9860
|
var PATH_SIGNALS = [
|
|
10098
9861
|
{
|
|
10099
9862
|
preset: "nest",
|
|
@@ -10127,12 +9890,12 @@ function sourceImports(cwd, pattern) {
|
|
|
10127
9890
|
}
|
|
10128
9891
|
for (const entry of entries) {
|
|
10129
9892
|
if (entry.isDirectory()) {
|
|
10130
|
-
if (!NOT_SCANNED.has(entry.name)) stack.push(
|
|
9893
|
+
if (!NOT_SCANNED.has(entry.name)) stack.push(join41(dir, entry.name));
|
|
10131
9894
|
continue;
|
|
10132
9895
|
}
|
|
10133
9896
|
if (!SOURCE_FILE2.test(entry.name)) continue;
|
|
10134
9897
|
try {
|
|
10135
|
-
if (pattern.test(
|
|
9898
|
+
if (pattern.test(readFileSync34(join41(dir, entry.name), "utf8"))) return true;
|
|
10136
9899
|
} catch {
|
|
10137
9900
|
continue;
|
|
10138
9901
|
}
|
|
@@ -10141,11 +9904,11 @@ function sourceImports(cwd, pattern) {
|
|
|
10141
9904
|
return false;
|
|
10142
9905
|
}
|
|
10143
9906
|
function dependencyNames(cwd) {
|
|
10144
|
-
const path =
|
|
9907
|
+
const path = join41(cwd, "package.json");
|
|
10145
9908
|
if (!existsSync34(path)) return [];
|
|
10146
9909
|
try {
|
|
10147
9910
|
const manifest = parseJsonc(
|
|
10148
|
-
|
|
9911
|
+
readFileSync34(path, "utf8"),
|
|
10149
9912
|
path
|
|
10150
9913
|
);
|
|
10151
9914
|
return [
|
|
@@ -10168,7 +9931,7 @@ function declaresJsx(cwd) {
|
|
|
10168
9931
|
for (const name of entries) {
|
|
10169
9932
|
try {
|
|
10170
9933
|
const config = parseJsonc(
|
|
10171
|
-
|
|
9934
|
+
readFileSync34(join41(cwd, name), "utf8"),
|
|
10172
9935
|
name
|
|
10173
9936
|
);
|
|
10174
9937
|
if (config.compilerOptions?.jsx !== void 0) return true;
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hublo/sentinel",
|
|
3
|
-
"version": "1.4.0-alpha.
|
|
3
|
+
"version": "1.4.0-alpha.23",
|
|
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",
|