@hublo/sentinel 1.4.0-alpha.11 → 1.4.0-alpha.13
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
|
@@ -561,9 +561,9 @@ function binFromOwnInstall(packageName, binName) {
|
|
|
561
561
|
try {
|
|
562
562
|
const manifest = require2.resolve(`${packageName}/package.json`);
|
|
563
563
|
const bin = require2(manifest).bin;
|
|
564
|
-
const
|
|
565
|
-
if (!
|
|
566
|
-
const executable = join5(dirname(manifest),
|
|
564
|
+
const relative8 = typeof bin === "string" ? bin : bin?.[binName];
|
|
565
|
+
if (!relative8) return void 0;
|
|
566
|
+
const executable = join5(dirname(manifest), relative8);
|
|
567
567
|
return existsSync6(executable) ? executable : void 0;
|
|
568
568
|
} catch {
|
|
569
569
|
return void 0;
|
|
@@ -5482,7 +5482,8 @@ function testTarget(options) {
|
|
|
5482
5482
|
|
|
5483
5483
|
// src/roles/test/jest-migration.ts
|
|
5484
5484
|
import { existsSync as existsSync29, readFileSync as readFileSync28, readdirSync as readdirSync8 } from "fs";
|
|
5485
|
-
import {
|
|
5485
|
+
import { createRequire as createRequire6 } from "module";
|
|
5486
|
+
import { dirname as dirname7, join as join35, relative as relative7 } from "path";
|
|
5486
5487
|
|
|
5487
5488
|
// src/roles/test/codemod/migrate-module.ts
|
|
5488
5489
|
import { readdirSync as readdirSync6, readFileSync as readFileSync25, statSync as statSync6 } from "fs";
|
|
@@ -5614,11 +5615,11 @@ function readTestAdoption(cwd) {
|
|
|
5614
5615
|
// src/roles/test/support-file-name.ts
|
|
5615
5616
|
var JEST_PREFIX = "jest.";
|
|
5616
5617
|
var VITEST_PREFIX = "vitest.";
|
|
5617
|
-
function vitestSupportName(
|
|
5618
|
-
const cut =
|
|
5619
|
-
const directory = cut === -1 ? "" :
|
|
5620
|
-
const base =
|
|
5621
|
-
if (!base.startsWith(JEST_PREFIX)) return
|
|
5618
|
+
function vitestSupportName(relative8) {
|
|
5619
|
+
const cut = relative8.lastIndexOf("/");
|
|
5620
|
+
const directory = cut === -1 ? "" : relative8.slice(0, cut + 1);
|
|
5621
|
+
const base = relative8.slice(cut + 1);
|
|
5622
|
+
if (!base.startsWith(JEST_PREFIX)) return relative8;
|
|
5622
5623
|
return `${directory}${VITEST_PREFIX}${base.slice(JEST_PREFIX.length)}`;
|
|
5623
5624
|
}
|
|
5624
5625
|
|
|
@@ -7583,16 +7584,16 @@ function migrateModuleTests(cwd, setupFiles = []) {
|
|
|
7583
7584
|
let hoisted = 0;
|
|
7584
7585
|
const defaultImported = defaultImportedSpecifiers(cwd);
|
|
7585
7586
|
const asyncHelpers = /* @__PURE__ */ new Set();
|
|
7586
|
-
for (const
|
|
7587
|
-
const source = read2(join31(cwd,
|
|
7587
|
+
for (const relative8 of listTestSupportFiles(cwd, setupFiles)) {
|
|
7588
|
+
const source = read2(join31(cwd, relative8));
|
|
7588
7589
|
if (source === void 0) {
|
|
7589
|
-
blockers.push({ file:
|
|
7590
|
+
blockers.push({ file: relative8, reason: "this file could not be read" });
|
|
7590
7591
|
continue;
|
|
7591
7592
|
}
|
|
7592
|
-
const migrated = migrateTestFile(join31(cwd,
|
|
7593
|
-
const renamedTo = vitestSupportName(
|
|
7594
|
-
if (!migrated.changed && renamedTo ===
|
|
7595
|
-
if (renamedTo !==
|
|
7593
|
+
const migrated = migrateTestFile(join31(cwd, relative8), source, defaultImported);
|
|
7594
|
+
const renamedTo = vitestSupportName(relative8);
|
|
7595
|
+
if (!migrated.changed && renamedTo === relative8) continue;
|
|
7596
|
+
if (renamedTo !== relative8) operations.push({ kind: "delete", path: relative8 });
|
|
7596
7597
|
const before = parse3(source);
|
|
7597
7598
|
const after = parse3(migrated.source);
|
|
7598
7599
|
if (before !== void 0 && after !== void 0) {
|
|
@@ -7605,27 +7606,27 @@ function migrateModuleTests(cwd, setupFiles = []) {
|
|
|
7605
7606
|
renamed += migrated.renamed;
|
|
7606
7607
|
operations.push({ kind: "write", path: renamedTo, contents: migrated.source });
|
|
7607
7608
|
}
|
|
7608
|
-
for (const
|
|
7609
|
-
const source = read2(join31(cwd,
|
|
7609
|
+
for (const relative8 of listTestFiles(cwd)) {
|
|
7610
|
+
const source = read2(join31(cwd, relative8));
|
|
7610
7611
|
if (source === void 0) {
|
|
7611
|
-
blockers.push({ file:
|
|
7612
|
+
blockers.push({ file: relative8, reason: "this file could not be read" });
|
|
7612
7613
|
continue;
|
|
7613
7614
|
}
|
|
7614
|
-
const migrated = migrateTestFile(join31(cwd,
|
|
7615
|
+
const migrated = migrateTestFile(join31(cwd, relative8), source, defaultImported, asyncHelpers);
|
|
7615
7616
|
for (const member of migrated.unhandled) {
|
|
7616
7617
|
blockers.push({
|
|
7617
|
-
file: `${
|
|
7618
|
+
file: `${relative8}:${member.line}`,
|
|
7618
7619
|
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}`
|
|
7619
7620
|
});
|
|
7620
7621
|
}
|
|
7621
7622
|
for (const refusal of migrated.refusals) {
|
|
7622
|
-
blockers.push({ file:
|
|
7623
|
+
blockers.push({ file: relative8, reason: refusal.reason });
|
|
7623
7624
|
}
|
|
7624
7625
|
if (!migrated.changed) continue;
|
|
7625
7626
|
files++;
|
|
7626
7627
|
renamed += migrated.renamed;
|
|
7627
7628
|
if (migrated.hoisted.length > 0) hoisted++;
|
|
7628
|
-
operations.push({ kind: "write", path:
|
|
7629
|
+
operations.push({ kind: "write", path: relative8, contents: migrated.source });
|
|
7629
7630
|
}
|
|
7630
7631
|
return blockers.length > 0 ? { operations: [], files, renamed, hoisted, blockers } : { operations, files, renamed, hoisted, blockers: [] };
|
|
7631
7632
|
}
|
|
@@ -8207,6 +8208,18 @@ function specTypesOperation(cwd) {
|
|
|
8207
8208
|
}
|
|
8208
8209
|
};
|
|
8209
8210
|
}
|
|
8211
|
+
function mockExtendedTypesPath(cwd) {
|
|
8212
|
+
try {
|
|
8213
|
+
const manifest = createRequire6(join35(cwd, "noop.cjs")).resolve("@hublo/sentinel/package.json");
|
|
8214
|
+
const file = join35(dirname7(manifest), MOCK_EXTENDED_TYPES);
|
|
8215
|
+
if (existsSync29(file)) {
|
|
8216
|
+
const path = relative7(cwd, file);
|
|
8217
|
+
return path.startsWith(".") ? path : `./${path}`;
|
|
8218
|
+
}
|
|
8219
|
+
} catch {
|
|
8220
|
+
}
|
|
8221
|
+
return `./node_modules/@hublo/sentinel/${MOCK_EXTENDED_TYPES}`;
|
|
8222
|
+
}
|
|
8210
8223
|
function tsconfigFileListOperations(cwd) {
|
|
8211
8224
|
const operations = [];
|
|
8212
8225
|
let names;
|
|
@@ -8227,13 +8240,17 @@ function tsconfigFileListOperations(cwd) {
|
|
|
8227
8240
|
}
|
|
8228
8241
|
const include = Array.isArray(config?.include) ? rewriteFileList(config.include) : void 0;
|
|
8229
8242
|
const exclude = Array.isArray(config?.exclude) ? rewriteFileList(config.exclude) : void 0;
|
|
8230
|
-
|
|
8243
|
+
const files = Array.isArray(config?.files) ? rewriteFileList(config.files) : void 0;
|
|
8244
|
+
const withTypes = name === SPEC_TSCONFIG ? withMockExtendedTypes(cwd, files ?? config?.files) : void 0;
|
|
8245
|
+
if (include === void 0 && exclude === void 0 && files === void 0 && withTypes === void 0)
|
|
8246
|
+
continue;
|
|
8231
8247
|
operations.push({
|
|
8232
8248
|
kind: "merge-json",
|
|
8233
8249
|
path: name,
|
|
8234
8250
|
value: {
|
|
8235
8251
|
...include === void 0 ? {} : { include },
|
|
8236
|
-
...exclude === void 0 ? {} : { exclude }
|
|
8252
|
+
...exclude === void 0 ? {} : { exclude },
|
|
8253
|
+
...withTypes === void 0 ? files === void 0 ? {} : { files } : { files: withTypes }
|
|
8237
8254
|
}
|
|
8238
8255
|
});
|
|
8239
8256
|
}
|
|
@@ -8244,6 +8261,12 @@ function rewriteFileList(entries) {
|
|
|
8244
8261
|
const unchanged = rewritten.length === entries.length && rewritten.every((entry, index) => entry === entries[index]);
|
|
8245
8262
|
return unchanged ? void 0 : rewritten;
|
|
8246
8263
|
}
|
|
8264
|
+
function withMockExtendedTypes(cwd, files) {
|
|
8265
|
+
const entries = Array.isArray(files) ? files : [];
|
|
8266
|
+
if (entries.some((entry) => entry.endsWith(MOCK_EXTENDED_TYPES))) return void 0;
|
|
8267
|
+
return [...entries, mockExtendedTypesPath(cwd)];
|
|
8268
|
+
}
|
|
8269
|
+
var MOCK_EXTENDED_TYPES = "types/mock-extended.d.ts";
|
|
8247
8270
|
var JEST_CONFIG_ENTRY = /(^|\/)jest\.[\w.-]*config\.[cm]?[jt]s$/;
|
|
8248
8271
|
var TSCONFIG_FILE = /^tsconfig[\w.-]*\.json$/;
|
|
8249
8272
|
function siblingScriptRewrites(cwd) {
|
|
@@ -8991,7 +9014,7 @@ function registerTest() {
|
|
|
8991
9014
|
// src/roles/typescript/adapters/tsc/tsc.adapter.ts
|
|
8992
9015
|
import { spawnSync as spawnSync6 } from "child_process";
|
|
8993
9016
|
import { existsSync as existsSync31, readFileSync as readFileSync32 } from "fs";
|
|
8994
|
-
import { createRequire as
|
|
9017
|
+
import { createRequire as createRequire7 } from "module";
|
|
8995
9018
|
import { join as join39 } from "path";
|
|
8996
9019
|
|
|
8997
9020
|
// src/roles/typescript/presets/nest.json
|
|
@@ -9418,7 +9441,7 @@ var TscAdapter = class _TscAdapter extends BaseAdapter {
|
|
|
9418
9441
|
);
|
|
9419
9442
|
if (preset === void 0) return void 0;
|
|
9420
9443
|
try {
|
|
9421
|
-
|
|
9444
|
+
createRequire7(join39(cwd, "noop.js")).resolve(preset);
|
|
9422
9445
|
return void 0;
|
|
9423
9446
|
} catch {
|
|
9424
9447
|
return preset;
|
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.13",
|
|
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",
|
|
@@ -77,6 +77,7 @@
|
|
|
77
77
|
},
|
|
78
78
|
"files": [
|
|
79
79
|
"dist",
|
|
80
|
+
"types",
|
|
80
81
|
"docs",
|
|
81
82
|
"lint",
|
|
82
83
|
"oxlint",
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The type-level half of the `jest-mock-extended` alias.
|
|
3
|
+
*
|
|
4
|
+
* The generated Vitest config aliases `jest-mock-extended` to the fork sentinel ships, so at RUN
|
|
5
|
+
* time a migrated module has ONE copy. TypeScript does not read Vite's aliases, so it keeps
|
|
6
|
+
* resolving the jest package and a migrated spec ends up compiling two worlds at once:
|
|
7
|
+
*
|
|
8
|
+
* the value typeof mockDeep<Db>() -> CalledWithMock<…> extends jest.Mock
|
|
9
|
+
* the spec let spy: MockInstance -> vitest's own type
|
|
10
|
+
* TS2322 not assignable
|
|
11
|
+
*
|
|
12
|
+
* Measured on `apps/nest/microservices/agency`: one error, on a module whose typecheck was clean
|
|
13
|
+
* before it migrated. 34 files under `libs/` export a type built this way.
|
|
14
|
+
*
|
|
15
|
+
* ## Why here, and not in the module
|
|
16
|
+
*
|
|
17
|
+
* The declaration REPLACES the module's types with whatever it re-exports, so it has to name a
|
|
18
|
+
* package that resolves from wherever the file sits. `vitest-mock-extended` is sentinel's
|
|
19
|
+
* dependency, so a copy of this file placed in an adopting module would resolve nothing and empty
|
|
20
|
+
* the module out: measured, `Module '"jest-mock-extended"' has no exported member 'mockDeep'`.
|
|
21
|
+
*
|
|
22
|
+
* ## Why it does not couple modules to each other
|
|
23
|
+
*
|
|
24
|
+
* An ambient declaration applies to the PROGRAM that includes it, and nothing else. A module that
|
|
25
|
+
* includes it compiles against the Vitest types; a module still on jest, consuming the very same
|
|
26
|
+
* shared helper, keeps compiling against the jest ones. Proved on an isolated fixture: both
|
|
27
|
+
* programs green, over one unmodified shared lib.
|
|
28
|
+
*
|
|
29
|
+
* That is the whole point. Héla, 2026-09-24, on tying a module's migration to a library's:
|
|
30
|
+
* "ça crée des couplages et bloquent les migrations". lint, format and typescript each migrate one
|
|
31
|
+
* module at a time; this keeps the test role the same.
|
|
32
|
+
*/
|
|
33
|
+
declare module 'jest-mock-extended' {
|
|
34
|
+
export * from 'vitest-mock-extended'
|
|
35
|
+
}
|