@hublo/sentinel 1.4.0-alpha.11 → 1.4.0-alpha.12

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.
@@ -16,7 +16,7 @@ import {
16
16
  registerAdapters,
17
17
  resolve,
18
18
  resolveBin
19
- } from "../chunk-2S2VYRUM.js";
19
+ } from "../chunk-KGI2F2QK.js";
20
20
  import {
21
21
  WORKSPACE_ROOT_MARKER,
22
22
  ensureWorkspacePrep,
@@ -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 relative7 = typeof bin === "string" ? bin : bin?.[binName];
565
- if (!relative7) return void 0;
566
- const executable = join5(dirname(manifest), relative7);
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 { join as join35 } from "path";
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(relative7) {
5618
- const cut = relative7.lastIndexOf("/");
5619
- const directory = cut === -1 ? "" : relative7.slice(0, cut + 1);
5620
- const base = relative7.slice(cut + 1);
5621
- if (!base.startsWith(JEST_PREFIX)) return relative7;
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 relative7 of listTestSupportFiles(cwd, setupFiles)) {
7587
- const source = read2(join31(cwd, relative7));
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: relative7, reason: "this file could not be read" });
7590
+ blockers.push({ file: relative8, reason: "this file could not be read" });
7590
7591
  continue;
7591
7592
  }
7592
- const migrated = migrateTestFile(join31(cwd, relative7), source, defaultImported);
7593
- const renamedTo = vitestSupportName(relative7);
7594
- if (!migrated.changed && renamedTo === relative7) continue;
7595
- if (renamedTo !== relative7) operations.push({ kind: "delete", path: relative7 });
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 relative7 of listTestFiles(cwd)) {
7609
- const source = read2(join31(cwd, relative7));
7609
+ for (const relative8 of listTestFiles(cwd)) {
7610
+ const source = read2(join31(cwd, relative8));
7610
7611
  if (source === void 0) {
7611
- blockers.push({ file: relative7, reason: "this file could not be read" });
7612
+ blockers.push({ file: relative8, reason: "this file could not be read" });
7612
7613
  continue;
7613
7614
  }
7614
- const migrated = migrateTestFile(join31(cwd, relative7), source, defaultImported, asyncHelpers);
7615
+ const migrated = migrateTestFile(join31(cwd, relative8), source, defaultImported, asyncHelpers);
7615
7616
  for (const member of migrated.unhandled) {
7616
7617
  blockers.push({
7617
- file: `${relative7}:${member.line}`,
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: relative7, reason: refusal.reason });
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: relative7, contents: migrated.source });
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,17 @@ 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), "types", "mock-extended.d.ts");
8215
+ if (!existsSync29(file)) return void 0;
8216
+ const path = relative7(cwd, file);
8217
+ return path.startsWith(".") ? path : `./${path}`;
8218
+ } catch {
8219
+ return void 0;
8220
+ }
8221
+ }
8210
8222
  function tsconfigFileListOperations(cwd) {
8211
8223
  const operations = [];
8212
8224
  let names;
@@ -8227,12 +8239,13 @@ function tsconfigFileListOperations(cwd) {
8227
8239
  }
8228
8240
  const include = Array.isArray(config?.include) ? rewriteFileList(config.include) : void 0;
8229
8241
  const exclude = Array.isArray(config?.exclude) ? rewriteFileList(config.exclude) : void 0;
8230
- if (include === void 0 && exclude === void 0) continue;
8242
+ const withTypes = name === SPEC_TSCONFIG ? withMockExtendedTypes(cwd, include ?? config?.include) : void 0;
8243
+ if (include === void 0 && exclude === void 0 && withTypes === void 0) continue;
8231
8244
  operations.push({
8232
8245
  kind: "merge-json",
8233
8246
  path: name,
8234
8247
  value: {
8235
- ...include === void 0 ? {} : { include },
8248
+ ...withTypes === void 0 ? include === void 0 ? {} : { include } : { include: withTypes },
8236
8249
  ...exclude === void 0 ? {} : { exclude }
8237
8250
  }
8238
8251
  });
@@ -8244,6 +8257,13 @@ function rewriteFileList(entries) {
8244
8257
  const unchanged = rewritten.length === entries.length && rewritten.every((entry, index) => entry === entries[index]);
8245
8258
  return unchanged ? void 0 : rewritten;
8246
8259
  }
8260
+ function withMockExtendedTypes(cwd, include) {
8261
+ const path = mockExtendedTypesPath(cwd);
8262
+ if (path === void 0 || !Array.isArray(include)) return void 0;
8263
+ const entries = include;
8264
+ if (entries.some((entry) => entry.endsWith("types/mock-extended.d.ts"))) return void 0;
8265
+ return [...entries, path];
8266
+ }
8247
8267
  var JEST_CONFIG_ENTRY = /(^|\/)jest\.[\w.-]*config\.[cm]?[jt]s$/;
8248
8268
  var TSCONFIG_FILE = /^tsconfig[\w.-]*\.json$/;
8249
8269
  function siblingScriptRewrites(cwd) {
@@ -8991,7 +9011,7 @@ function registerTest() {
8991
9011
  // src/roles/typescript/adapters/tsc/tsc.adapter.ts
8992
9012
  import { spawnSync as spawnSync6 } from "child_process";
8993
9013
  import { existsSync as existsSync31, readFileSync as readFileSync32 } from "fs";
8994
- import { createRequire as createRequire6 } from "module";
9014
+ import { createRequire as createRequire7 } from "module";
8995
9015
  import { join as join39 } from "path";
8996
9016
 
8997
9017
  // src/roles/typescript/presets/nest.json
@@ -9418,7 +9438,7 @@ var TscAdapter = class _TscAdapter extends BaseAdapter {
9418
9438
  );
9419
9439
  if (preset === void 0) return void 0;
9420
9440
  try {
9421
- createRequire6(join39(cwd, "noop.js")).resolve(preset);
9441
+ createRequire7(join39(cwd, "noop.js")).resolve(preset);
9422
9442
  return void 0;
9423
9443
  } catch {
9424
9444
  return preset;
package/dist/index.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  registerAdapters,
8
8
  resolve,
9
9
  setDefaultRunner
10
- } from "./chunk-2S2VYRUM.js";
10
+ } from "./chunk-KGI2F2QK.js";
11
11
  import "./chunk-WLFE5RUU.js";
12
12
  export {
13
13
  BaseAdapter,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hublo/sentinel",
3
- "version": "1.4.0-alpha.11",
3
+ "version": "1.4.0-alpha.12",
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
+ }