@hublo/sentinel 1.4.0-alpha.18 → 1.4.0-alpha.19
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
|
@@ -5404,7 +5404,7 @@ function registerLint() {
|
|
|
5404
5404
|
import { spawnSync as spawnSync5 } from "child_process";
|
|
5405
5405
|
import { mkdtempSync as mkdtempSync2, readFileSync as readFileSync30 } from "fs";
|
|
5406
5406
|
import { tmpdir as tmpdir2 } from "os";
|
|
5407
|
-
import { isAbsolute as isAbsolute3, join as
|
|
5407
|
+
import { isAbsolute as isAbsolute3, join as join38, resolve as resolve6 } from "path";
|
|
5408
5408
|
|
|
5409
5409
|
// src/roles/test/presets/toolchain.json
|
|
5410
5410
|
var toolchain_default2 = {
|
|
@@ -5481,9 +5481,9 @@ function testTarget(options) {
|
|
|
5481
5481
|
}
|
|
5482
5482
|
|
|
5483
5483
|
// src/roles/test/jest-migration.ts
|
|
5484
|
-
import { existsSync as
|
|
5484
|
+
import { existsSync as existsSync30, readFileSync as readFileSync28, readdirSync as readdirSync8 } from "fs";
|
|
5485
5485
|
import { createRequire as createRequire6 } from "module";
|
|
5486
|
-
import { dirname as
|
|
5486
|
+
import { dirname as dirname8, join as join36, relative as relative7 } from "path";
|
|
5487
5487
|
|
|
5488
5488
|
// src/roles/test/codemod/migrate-module.ts
|
|
5489
5489
|
import { readdirSync as readdirSync6, readFileSync as readFileSync25, statSync as statSync6 } from "fs";
|
|
@@ -8262,12 +8262,59 @@ function runModes(cwd, fallback) {
|
|
|
8262
8262
|
);
|
|
8263
8263
|
}
|
|
8264
8264
|
|
|
8265
|
+
// src/roles/test/written-file-formatter.ts
|
|
8266
|
+
import { existsSync as existsSync29 } from "fs";
|
|
8267
|
+
import { dirname as dirname7, join as join35 } from "path";
|
|
8268
|
+
var PRETTIER_CONFIGS = [
|
|
8269
|
+
".prettierrc",
|
|
8270
|
+
".prettierrc.json",
|
|
8271
|
+
".prettierrc.json5",
|
|
8272
|
+
".prettierrc.yaml",
|
|
8273
|
+
".prettierrc.yml",
|
|
8274
|
+
".prettierrc.js",
|
|
8275
|
+
".prettierrc.cjs",
|
|
8276
|
+
".prettierrc.mjs",
|
|
8277
|
+
".prettierrc.toml",
|
|
8278
|
+
"prettier.config.js",
|
|
8279
|
+
"prettier.config.cjs",
|
|
8280
|
+
"prettier.config.mjs"
|
|
8281
|
+
];
|
|
8282
|
+
function prettierConfigFrom(cwd) {
|
|
8283
|
+
let dir = cwd;
|
|
8284
|
+
for (; ; ) {
|
|
8285
|
+
for (const name of PRETTIER_CONFIGS) {
|
|
8286
|
+
if (existsSync29(join35(dir, name))) return join35(dir, name);
|
|
8287
|
+
}
|
|
8288
|
+
const parent = dirname7(dir);
|
|
8289
|
+
if (parent === dir) return void 0;
|
|
8290
|
+
dir = parent;
|
|
8291
|
+
}
|
|
8292
|
+
}
|
|
8293
|
+
function writtenFileFormatter(cwd) {
|
|
8294
|
+
if (readFormatAdoption(cwd).configFile !== null) {
|
|
8295
|
+
const oxfmt = resolveOxfmt(cwd);
|
|
8296
|
+
if (oxfmt !== void 0) {
|
|
8297
|
+
return { bin: oxfmt, args: ["--write"], origin: "this module's own oxfmt config" };
|
|
8298
|
+
}
|
|
8299
|
+
}
|
|
8300
|
+
const config = prettierConfigFrom(cwd);
|
|
8301
|
+
const prettier = resolveBin(cwd, "prettier");
|
|
8302
|
+
if (config !== void 0 && prettier !== void 0) {
|
|
8303
|
+
return {
|
|
8304
|
+
bin: prettier,
|
|
8305
|
+
args: ["--write", "--log-level", "warn"],
|
|
8306
|
+
origin: `the workspace's Prettier`
|
|
8307
|
+
};
|
|
8308
|
+
}
|
|
8309
|
+
return void 0;
|
|
8310
|
+
}
|
|
8311
|
+
|
|
8265
8312
|
// src/roles/test/jest-migration.ts
|
|
8266
8313
|
var SPEC_TSCONFIG = "tsconfig.spec.json";
|
|
8267
8314
|
var VITEST_GLOBAL_TYPES = "vitest/globals";
|
|
8268
8315
|
function specTypesOperation(cwd) {
|
|
8269
|
-
const path =
|
|
8270
|
-
if (!
|
|
8316
|
+
const path = join36(cwd, SPEC_TSCONFIG);
|
|
8317
|
+
if (!existsSync30(path)) return void 0;
|
|
8271
8318
|
let config;
|
|
8272
8319
|
try {
|
|
8273
8320
|
config = parseJsonc(
|
|
@@ -8291,9 +8338,9 @@ function specTypesOperation(cwd) {
|
|
|
8291
8338
|
}
|
|
8292
8339
|
function shippedTypesPath(cwd, declaration) {
|
|
8293
8340
|
try {
|
|
8294
|
-
const manifest = createRequire6(
|
|
8295
|
-
const file =
|
|
8296
|
-
if (
|
|
8341
|
+
const manifest = createRequire6(join36(cwd, "noop.cjs")).resolve("@hublo/sentinel/package.json");
|
|
8342
|
+
const file = join36(dirname8(manifest), declaration);
|
|
8343
|
+
if (existsSync30(file)) {
|
|
8297
8344
|
const path = relative7(cwd, file);
|
|
8298
8345
|
return path.startsWith(".") ? path : `./${path}`;
|
|
8299
8346
|
}
|
|
@@ -8313,7 +8360,7 @@ function tsconfigFileListOperations(cwd) {
|
|
|
8313
8360
|
let config;
|
|
8314
8361
|
try {
|
|
8315
8362
|
config = parseJsonc(
|
|
8316
|
-
readFileSync28(
|
|
8363
|
+
readFileSync28(join36(cwd, name), "utf8"),
|
|
8317
8364
|
name
|
|
8318
8365
|
);
|
|
8319
8366
|
} catch {
|
|
@@ -8446,13 +8493,14 @@ function planJestMigration(context, adoption) {
|
|
|
8446
8493
|
`${SPEC_TSCONFIG} now declares \`${VITEST_GLOBAL_TYPES}\` instead of \`jest\`. Without it the module keeps depending on @types/jest and \`jest.Mock\` still resolves, so the migration would look finished while the dependency it cuts is still declared.`
|
|
8447
8494
|
);
|
|
8448
8495
|
}
|
|
8449
|
-
|
|
8496
|
+
const formatter = writtenFileFormatter(context.cwd);
|
|
8497
|
+
if (formatter !== void 0) {
|
|
8450
8498
|
notes.push(
|
|
8451
|
-
`the files this rewrote were run through
|
|
8499
|
+
`the files this rewrote were run through ${formatter.origin} afterwards. Two things needed it: the Vitest type imports land beside the existing ones, and a rewritten call is often SHORTER than the one it replaced, so the line breaks around it are no longer the ones your config would pick. Neither is a defect, and both would have failed your format check. What no formatter does is ORDER imports, so if your lint enforces \`import/order\`, run its fixer too.`
|
|
8452
8500
|
);
|
|
8453
8501
|
} else {
|
|
8454
8502
|
notes.push(
|
|
8455
|
-
`this module
|
|
8503
|
+
`no style is declared here, by this module or its workspace, so what was written keeps the shape it was written in, and the Vitest type imports sit beside the existing ones rather than where your \`import/order\` wants them. That rule is classified by a prefix list this package cannot read, so it is left to the tool that owns it: run your module's own lint fixer (\`nx run <module>:lint --fix\` here) and its formatter before committing.`
|
|
8456
8504
|
);
|
|
8457
8505
|
}
|
|
8458
8506
|
notes.push(
|
|
@@ -8601,9 +8649,9 @@ function plan3(context) {
|
|
|
8601
8649
|
// src/roles/test/reference.ts
|
|
8602
8650
|
import { execFileSync } from "child_process";
|
|
8603
8651
|
import { createHash } from "crypto";
|
|
8604
|
-
import { existsSync as
|
|
8652
|
+
import { existsSync as existsSync31, mkdirSync, mkdtempSync, readFileSync as readFileSync29, rmSync as rmSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
8605
8653
|
import { tmpdir } from "os";
|
|
8606
|
-
import { join as
|
|
8654
|
+
import { join as join37, resolve as resolve5 } from "path";
|
|
8607
8655
|
|
|
8608
8656
|
// src/roles/test/baseline.ts
|
|
8609
8657
|
function readSnapshot(report) {
|
|
@@ -8847,22 +8895,22 @@ function describeComparison(comparison) {
|
|
|
8847
8895
|
// src/roles/test/reference.ts
|
|
8848
8896
|
function referencePath(cwd) {
|
|
8849
8897
|
const key = createHash("sha256").update(resolve5(cwd)).digest("hex").slice(0, 16);
|
|
8850
|
-
return
|
|
8898
|
+
return join37(tmpdir(), "sentinel-test-reference", `${key}.json`);
|
|
8851
8899
|
}
|
|
8852
8900
|
function runJest(cwd, config) {
|
|
8853
8901
|
const bin = resolveBin(cwd, "jest");
|
|
8854
8902
|
if (bin === void 0) return void 0;
|
|
8855
8903
|
const root = findWorkspaceRoot(cwd) ?? cwd;
|
|
8856
|
-
const out =
|
|
8904
|
+
const out = join37(mkdtempSync(join37(tmpdir(), "sentinel-reference-")), "jest.json");
|
|
8857
8905
|
try {
|
|
8858
|
-
execFileSync(bin, ["-c",
|
|
8906
|
+
execFileSync(bin, ["-c", join37(cwd, config), "--json", `--outputFile=${out}`, "--silent"], {
|
|
8859
8907
|
cwd: root,
|
|
8860
8908
|
stdio: ["ignore", "ignore", "ignore"],
|
|
8861
8909
|
maxBuffer: 1 << 28
|
|
8862
8910
|
});
|
|
8863
8911
|
} catch {
|
|
8864
8912
|
}
|
|
8865
|
-
if (!
|
|
8913
|
+
if (!existsSync31(out)) return void 0;
|
|
8866
8914
|
try {
|
|
8867
8915
|
return JSON.parse(readFileSync29(out, "utf8"));
|
|
8868
8916
|
} catch {
|
|
@@ -8892,7 +8940,7 @@ function captureReference(cwd, config) {
|
|
|
8892
8940
|
snapshot
|
|
8893
8941
|
};
|
|
8894
8942
|
const path = referencePath(cwd);
|
|
8895
|
-
mkdirSync(
|
|
8943
|
+
mkdirSync(join37(path, ".."), { recursive: true });
|
|
8896
8944
|
writeFileSync3(path, `${JSON.stringify(stored, void 0, 2)}
|
|
8897
8945
|
`);
|
|
8898
8946
|
return {
|
|
@@ -8901,7 +8949,7 @@ function captureReference(cwd, config) {
|
|
|
8901
8949
|
};
|
|
8902
8950
|
}
|
|
8903
8951
|
function hasReference(cwd) {
|
|
8904
|
-
return
|
|
8952
|
+
return existsSync31(referencePath(cwd));
|
|
8905
8953
|
}
|
|
8906
8954
|
function compareAgainstReference(cwd, report) {
|
|
8907
8955
|
const path = referencePath(cwd);
|
|
@@ -8929,6 +8977,7 @@ function resolveVitest(cwd) {
|
|
|
8929
8977
|
return fromModule !== void 0 ? { bin: fromModule, origin: "module" } : { bin: void 0, origin: "module" };
|
|
8930
8978
|
}
|
|
8931
8979
|
var FORMATTABLE = /\.(m|c)?(j|t)sx?$|\.json$/;
|
|
8980
|
+
var FORMAT_BATCH = 25;
|
|
8932
8981
|
var VitestAdapter = class extends BaseAdapter {
|
|
8933
8982
|
target = "test";
|
|
8934
8983
|
runner = "vitest";
|
|
@@ -8998,20 +9047,27 @@ var VitestAdapter = class extends BaseAdapter {
|
|
|
8998
9047
|
async afterInit(ctx) {
|
|
8999
9048
|
const written = (ctx.written ?? []).filter((file) => FORMATTABLE.test(file));
|
|
9000
9049
|
if (written.length === 0) return Promise.resolve();
|
|
9001
|
-
|
|
9050
|
+
const formatter = writtenFileFormatter(ctx.cwd);
|
|
9051
|
+
if (formatter === void 0) {
|
|
9002
9052
|
this.say(
|
|
9003
|
-
`no
|
|
9053
|
+
`no style is declared here, by this module or its workspace, so the ${written.length} file(s) this wrote keep the shape they were written in. Run your own formatter over them before committing.`
|
|
9004
9054
|
);
|
|
9005
9055
|
return Promise.resolve();
|
|
9006
9056
|
}
|
|
9007
|
-
|
|
9008
|
-
|
|
9009
|
-
|
|
9057
|
+
let failed = 0;
|
|
9058
|
+
for (let at = 0; at < written.length; at += FORMAT_BATCH) {
|
|
9059
|
+
const batch = written.slice(at, at + FORMAT_BATCH);
|
|
9060
|
+
const pass = spawnSync5(formatter.bin, [...formatter.args, ...batch], {
|
|
9061
|
+
cwd: ctx.cwd,
|
|
9062
|
+
encoding: "utf8"
|
|
9063
|
+
});
|
|
9064
|
+
if (pass.status !== 0) failed += batch.length;
|
|
9065
|
+
}
|
|
9010
9066
|
this.say(
|
|
9011
|
-
|
|
9067
|
+
failed === 0 ? `formatted the ${written.length} file(s) this wrote with ${formatter.origin}, so a format check passes on files it did not write itself.` : (
|
|
9012
9068
|
// Adoption SUCCEEDED; only the tidy-up did not. Failing here would revert a migration
|
|
9013
9069
|
// over a formatting pass, which is the wrong trade.
|
|
9014
|
-
|
|
9070
|
+
`${formatter.origin} could not run over ${failed} of the ${written.length} file(s) this wrote. Adoption itself is applied; run your formatter before committing.`
|
|
9015
9071
|
)
|
|
9016
9072
|
);
|
|
9017
9073
|
return Promise.resolve();
|
|
@@ -9066,7 +9122,7 @@ var VitestAdapter = class extends BaseAdapter {
|
|
|
9066
9122
|
const { cwd: runFrom, options, paths } = fromWorkspaceRoot(ctx.cwd, typedOptions, typedPaths);
|
|
9067
9123
|
const watching = options.includes("--watch") || options.includes("-w");
|
|
9068
9124
|
const proving = !watching && hasReference(ctx.cwd);
|
|
9069
|
-
const reportFile = proving ?
|
|
9125
|
+
const reportFile = proving ? join38(mkdtempSync2(join38(tmpdir2(), "sentinel-run-")), "vitest.json") : void 0;
|
|
9070
9126
|
const reporters = reportFile === void 0 ? [] : ["--reporter=default", "--reporter=json", `--outputFile=${reportFile}`];
|
|
9071
9127
|
const argv = watching ? [...options, ...paths] : ["run", ...reporters, ...options, ...paths];
|
|
9072
9128
|
const result = spawnSync5(bin, argv, { cwd: runFrom, stdio: "inherit" });
|
|
@@ -9131,9 +9187,9 @@ function registerTest() {
|
|
|
9131
9187
|
|
|
9132
9188
|
// src/roles/typescript/adapters/tsc/tsc.adapter.ts
|
|
9133
9189
|
import { spawnSync as spawnSync6 } from "child_process";
|
|
9134
|
-
import { existsSync as
|
|
9190
|
+
import { existsSync as existsSync32, readFileSync as readFileSync32 } from "fs";
|
|
9135
9191
|
import { createRequire as createRequire7 } from "module";
|
|
9136
|
-
import { join as
|
|
9192
|
+
import { join as join40 } from "path";
|
|
9137
9193
|
|
|
9138
9194
|
// src/roles/typescript/presets/nest.json
|
|
9139
9195
|
var nest_default2 = {
|
|
@@ -9315,7 +9371,7 @@ function readTsconfigAdoption(cwd) {
|
|
|
9315
9371
|
|
|
9316
9372
|
// src/roles/typescript/adapters/tsc/plan.ts
|
|
9317
9373
|
import { readFileSync as readFileSync31 } from "fs";
|
|
9318
|
-
import { join as
|
|
9374
|
+
import { join as join39 } from "path";
|
|
9319
9375
|
|
|
9320
9376
|
// src/roles/typescript/typecheck-script.ts
|
|
9321
9377
|
var SENTINEL_TYPECHECK_COMMAND = "sentinel --run --typescript";
|
|
@@ -9408,7 +9464,7 @@ function planAdoption(context) {
|
|
|
9408
9464
|
};
|
|
9409
9465
|
}
|
|
9410
9466
|
const existing = parseJsonc(
|
|
9411
|
-
readFileSync31(
|
|
9467
|
+
readFileSync31(join39(context.cwd, target.path), "utf8"),
|
|
9412
9468
|
target.path
|
|
9413
9469
|
);
|
|
9414
9470
|
const extendsChain = composeExtends(existing.extends, preset);
|
|
@@ -9546,7 +9602,7 @@ var TscAdapter = class _TscAdapter extends BaseAdapter {
|
|
|
9546
9602
|
let chain;
|
|
9547
9603
|
try {
|
|
9548
9604
|
const parsed = parseJsonc(
|
|
9549
|
-
readFileSync32(
|
|
9605
|
+
readFileSync32(join40(cwd, target.path), "utf8"),
|
|
9550
9606
|
target.path
|
|
9551
9607
|
);
|
|
9552
9608
|
chain = parsed.extends;
|
|
@@ -9559,7 +9615,7 @@ var TscAdapter = class _TscAdapter extends BaseAdapter {
|
|
|
9559
9615
|
);
|
|
9560
9616
|
if (preset === void 0) return void 0;
|
|
9561
9617
|
try {
|
|
9562
|
-
createRequire7(
|
|
9618
|
+
createRequire7(join40(cwd, "noop.js")).resolve(preset);
|
|
9563
9619
|
return void 0;
|
|
9564
9620
|
} catch {
|
|
9565
9621
|
return preset;
|
|
@@ -9655,7 +9711,7 @@ var TscAdapter = class _TscAdapter extends BaseAdapter {
|
|
|
9655
9711
|
referencedProjects(cwd, config) {
|
|
9656
9712
|
try {
|
|
9657
9713
|
const parsed = parseJsonc(
|
|
9658
|
-
readFileSync32(
|
|
9714
|
+
readFileSync32(join40(cwd, config), "utf8"),
|
|
9659
9715
|
config
|
|
9660
9716
|
);
|
|
9661
9717
|
const referenced = (parsed.references ?? []).map((reference) => reference.path).filter((path) => typeof path === "string" && path.length > 0);
|
|
@@ -9671,7 +9727,7 @@ var TscAdapter = class _TscAdapter extends BaseAdapter {
|
|
|
9671
9727
|
* check.
|
|
9672
9728
|
*/
|
|
9673
9729
|
typecheckTarget(cwd) {
|
|
9674
|
-
if (
|
|
9730
|
+
if (existsSync32(join40(cwd, "tsconfig.json"))) return "tsconfig.json";
|
|
9675
9731
|
const target = resolveTsconfigTarget(cwd);
|
|
9676
9732
|
return target.reason === "none" ? null : target.path;
|
|
9677
9733
|
}
|
|
@@ -9876,7 +9932,7 @@ function replaceLines(current, replacements) {
|
|
|
9876
9932
|
}
|
|
9877
9933
|
|
|
9878
9934
|
// src/core/apply-plan.ts
|
|
9879
|
-
import { existsSync as
|
|
9935
|
+
import { existsSync as existsSync33, readFileSync as readFileSync33, renameSync, rmSync as rmSync4, writeFileSync as writeFileSync4 } from "fs";
|
|
9880
9936
|
import { resolve as resolve7, sep } from "path";
|
|
9881
9937
|
import { applyEdits as applyEdits3, findNodeAtLocation, modify, parseTree } from "jsonc-parser";
|
|
9882
9938
|
|
|
@@ -9895,7 +9951,7 @@ function resolveWithinRoot(cwd, relativePath) {
|
|
|
9895
9951
|
return absolutePath;
|
|
9896
9952
|
}
|
|
9897
9953
|
function readIfExists(absolutePath) {
|
|
9898
|
-
return
|
|
9954
|
+
return existsSync33(absolutePath) ? readFileSync33(absolutePath, "utf8") : void 0;
|
|
9899
9955
|
}
|
|
9900
9956
|
function* leaves(value, prefix = []) {
|
|
9901
9957
|
for (const [key, keyValue] of Object.entries(value)) {
|
|
@@ -10013,8 +10069,8 @@ function applyPlan(cwd, plan4) {
|
|
|
10013
10069
|
}
|
|
10014
10070
|
|
|
10015
10071
|
// src/core/config/preset-evidence.ts
|
|
10016
|
-
import { existsSync as
|
|
10017
|
-
import { join as
|
|
10072
|
+
import { existsSync as existsSync34, readdirSync as readdirSync9, readFileSync as readFileSync34 } from "fs";
|
|
10073
|
+
import { join as join41 } from "path";
|
|
10018
10074
|
var PATH_SIGNALS = [
|
|
10019
10075
|
{
|
|
10020
10076
|
preset: "nest",
|
|
@@ -10048,12 +10104,12 @@ function sourceImports(cwd, pattern) {
|
|
|
10048
10104
|
}
|
|
10049
10105
|
for (const entry of entries) {
|
|
10050
10106
|
if (entry.isDirectory()) {
|
|
10051
|
-
if (!NOT_SCANNED.has(entry.name)) stack.push(
|
|
10107
|
+
if (!NOT_SCANNED.has(entry.name)) stack.push(join41(dir, entry.name));
|
|
10052
10108
|
continue;
|
|
10053
10109
|
}
|
|
10054
10110
|
if (!SOURCE_FILE2.test(entry.name)) continue;
|
|
10055
10111
|
try {
|
|
10056
|
-
if (pattern.test(readFileSync34(
|
|
10112
|
+
if (pattern.test(readFileSync34(join41(dir, entry.name), "utf8"))) return true;
|
|
10057
10113
|
} catch {
|
|
10058
10114
|
continue;
|
|
10059
10115
|
}
|
|
@@ -10062,8 +10118,8 @@ function sourceImports(cwd, pattern) {
|
|
|
10062
10118
|
return false;
|
|
10063
10119
|
}
|
|
10064
10120
|
function dependencyNames(cwd) {
|
|
10065
|
-
const path =
|
|
10066
|
-
if (!
|
|
10121
|
+
const path = join41(cwd, "package.json");
|
|
10122
|
+
if (!existsSync34(path)) return [];
|
|
10067
10123
|
try {
|
|
10068
10124
|
const manifest = parseJsonc(
|
|
10069
10125
|
readFileSync34(path, "utf8"),
|
|
@@ -10089,7 +10145,7 @@ function declaresJsx(cwd) {
|
|
|
10089
10145
|
for (const name of entries) {
|
|
10090
10146
|
try {
|
|
10091
10147
|
const config = parseJsonc(
|
|
10092
|
-
readFileSync34(
|
|
10148
|
+
readFileSync34(join41(cwd, name), "utf8"),
|
|
10093
10149
|
name
|
|
10094
10150
|
);
|
|
10095
10151
|
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.19",
|
|
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",
|