@hublo/sentinel 1.4.0-alpha.26 → 1.4.0-alpha.28
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 +32 -4
- package/dist/{chunk-ATDETQX5.js → chunk-J3MDCYSX.js} +380 -711
- package/dist/chunk-WYWE4VIL.js +711 -0
- package/dist/index.d.ts +18 -5
- package/dist/index.js +2 -1
- package/dist/validate-B5MYLIG4.js +127 -0
- package/docs/test-adoption.md +85 -0
- package/package.json +1 -1
|
@@ -1,9 +1,32 @@
|
|
|
1
|
+
import {
|
|
2
|
+
JEST_CONFIG_FILES,
|
|
3
|
+
SENTINEL_OWNED_TEST_PACKAGES,
|
|
4
|
+
SENTINEL_TEST_COMMAND,
|
|
5
|
+
TEST_SCRIPT_NAME,
|
|
6
|
+
adoptedPackageName,
|
|
7
|
+
binFromOwnInstall,
|
|
8
|
+
binSearchPath,
|
|
9
|
+
hasReference,
|
|
10
|
+
listTestFiles,
|
|
11
|
+
manifestOperation,
|
|
12
|
+
manifestTargets,
|
|
13
|
+
moduleScripts,
|
|
14
|
+
readTestAdoption,
|
|
15
|
+
readTestConfigSource,
|
|
16
|
+
resolveBin,
|
|
17
|
+
resolveVitest,
|
|
18
|
+
rewriteVitestScript,
|
|
19
|
+
selfCommand,
|
|
20
|
+
suiteOf,
|
|
21
|
+
testConfigFile,
|
|
22
|
+
testTarget,
|
|
23
|
+
testToolchain
|
|
24
|
+
} from "./chunk-WYWE4VIL.js";
|
|
1
25
|
import {
|
|
2
26
|
DEFAULT_MAX_DIAGNOSTICS,
|
|
3
27
|
WORKSPACE_ROOT_MARKER,
|
|
4
28
|
findWorkspaceRoot,
|
|
5
29
|
moduleName,
|
|
6
|
-
readNxProjectName,
|
|
7
30
|
readOwnPackage,
|
|
8
31
|
readProjectPackageJson
|
|
9
32
|
} from "./chunk-NW6UHNYX.js";
|
|
@@ -91,7 +114,7 @@ var BaseAdapter = class {
|
|
|
91
114
|
};
|
|
92
115
|
|
|
93
116
|
// src/core/domain.ts
|
|
94
|
-
var VERBS = ["run", "inspect", "init", "migrate", "report", "status"];
|
|
117
|
+
var VERBS = ["run", "inspect", "init", "migrate", "validate", "report", "status"];
|
|
95
118
|
var TARGETS = [
|
|
96
119
|
"lint",
|
|
97
120
|
"format",
|
|
@@ -196,8 +219,8 @@ function workspaceRootHops(cwd, target) {
|
|
|
196
219
|
}
|
|
197
220
|
|
|
198
221
|
// src/roles/build/read-adoption.ts
|
|
199
|
-
import { existsSync as
|
|
200
|
-
import { join as
|
|
222
|
+
import { existsSync as existsSync3, readFileSync as readFileSync3 } from "node:fs";
|
|
223
|
+
import { join as join3 } from "node:path";
|
|
201
224
|
|
|
202
225
|
// src/core/config/module-type.ts
|
|
203
226
|
function esmReadiness(fileName, packageType) {
|
|
@@ -210,68 +233,14 @@ function esmReadiness(fileName, packageType) {
|
|
|
210
233
|
};
|
|
211
234
|
}
|
|
212
235
|
|
|
213
|
-
// src/core/config/manifest.ts
|
|
214
|
-
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
|
|
215
|
-
import { basename, join as join2 } from "node:path";
|
|
216
|
-
function moduleScripts(cwd) {
|
|
217
|
-
try {
|
|
218
|
-
const pkg = JSON.parse(readFileSync2(join2(cwd, "package.json"), "utf8"));
|
|
219
|
-
return pkg.scripts ?? {};
|
|
220
|
-
} catch {
|
|
221
|
-
return {};
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
function manifestTargets(cwd) {
|
|
225
|
-
try {
|
|
226
|
-
const pkg = JSON.parse(readFileSync2(join2(cwd, "package.json"), "utf8"));
|
|
227
|
-
return pkg.nx?.targets ?? {};
|
|
228
|
-
} catch {
|
|
229
|
-
return {};
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
function moduleName2(cwd) {
|
|
233
|
-
try {
|
|
234
|
-
const pkg = JSON.parse(readFileSync2(join2(cwd, "package.json"), "utf8"));
|
|
235
|
-
return pkg.name;
|
|
236
|
-
} catch {
|
|
237
|
-
return void 0;
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
function isSelfAdoption(cwd) {
|
|
241
|
-
return moduleName2(cwd) === readOwnPackage().name;
|
|
242
|
-
}
|
|
243
|
-
function selfCommand(cwd, flags) {
|
|
244
|
-
const own = readOwnPackage();
|
|
245
|
-
if (!isSelfAdoption(cwd) || !own.bin) return void 0;
|
|
246
|
-
return `node ${own.bin.replace(/^\.\//, "")} ${flags}`;
|
|
247
|
-
}
|
|
248
|
-
function adoptedPackageName(cwd) {
|
|
249
|
-
return readProjectPackageJson(cwd).name ?? readNxProjectName(cwd) ?? basename(cwd);
|
|
250
|
-
}
|
|
251
|
-
function manifestOperation(cwd, scripts) {
|
|
252
|
-
const own = readOwnPackage();
|
|
253
|
-
const value = {
|
|
254
|
-
scripts,
|
|
255
|
-
devDependencies: { [own.name]: isSelfAdoption(cwd) ? "link:." : own.version }
|
|
256
|
-
};
|
|
257
|
-
if (existsSync2(join2(cwd, "package.json"))) {
|
|
258
|
-
return { kind: "merge-json", path: "package.json", value };
|
|
259
|
-
}
|
|
260
|
-
return {
|
|
261
|
-
kind: "merge-json",
|
|
262
|
-
path: "package.json",
|
|
263
|
-
value: { name: adoptedPackageName(cwd), private: true, ...value }
|
|
264
|
-
};
|
|
265
|
-
}
|
|
266
|
-
|
|
267
236
|
// src/core/config/project-json.ts
|
|
268
|
-
import { existsSync as
|
|
269
|
-
import { join as
|
|
237
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
|
|
238
|
+
import { join as join2 } from "node:path";
|
|
270
239
|
function projectTargets(cwd) {
|
|
271
|
-
const path =
|
|
272
|
-
if (!
|
|
240
|
+
const path = join2(cwd, "project.json");
|
|
241
|
+
if (!existsSync2(path)) return void 0;
|
|
273
242
|
try {
|
|
274
|
-
return JSON.parse(
|
|
243
|
+
return JSON.parse(readFileSync2(path, "utf8")).targets;
|
|
275
244
|
} catch {
|
|
276
245
|
return void 0;
|
|
277
246
|
}
|
|
@@ -374,12 +343,12 @@ var DEV_SCRIPT_NAME = "serve";
|
|
|
374
343
|
var SENTINEL_DEV_COMMAND = "sentinel --run --dev";
|
|
375
344
|
var BUILD_OUTPUT_CANDIDATES = ["dist", ".output", "build"];
|
|
376
345
|
function buildTarget(options) {
|
|
377
|
-
const { moduleName:
|
|
346
|
+
const { moduleName: moduleName2, configFiles = BUILD_CONFIG_FILES, outputs } = options;
|
|
378
347
|
return {
|
|
379
348
|
[BUILD_SCRIPT_NAME]: {
|
|
380
349
|
executor: "nx:run-commands",
|
|
381
350
|
options: {
|
|
382
|
-
command: `pnpm --filter ${
|
|
351
|
+
command: `pnpm --filter ${moduleName2} run ${BUILD_SCRIPT_NAME}`,
|
|
383
352
|
forwardAllArgs: false
|
|
384
353
|
},
|
|
385
354
|
cache: true,
|
|
@@ -454,7 +423,7 @@ var NOT_ADOPTED = (configFile, unreadable = null) => ({
|
|
|
454
423
|
unreadable
|
|
455
424
|
});
|
|
456
425
|
function buildConfigFile(cwd) {
|
|
457
|
-
return BUILD_CONFIG_FILES.find((name) =>
|
|
426
|
+
return BUILD_CONFIG_FILES.find((name) => existsSync3(join3(cwd, name)));
|
|
458
427
|
}
|
|
459
428
|
function importsSpecifier(source, specifier) {
|
|
460
429
|
const escaped = specifier.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -480,7 +449,7 @@ function readBuildConfigSource(cwd) {
|
|
|
480
449
|
const configFile = buildConfigFile(cwd);
|
|
481
450
|
if (!configFile) return void 0;
|
|
482
451
|
try {
|
|
483
|
-
return
|
|
452
|
+
return readFileSync3(join3(cwd, configFile), "utf8");
|
|
484
453
|
} catch {
|
|
485
454
|
return void 0;
|
|
486
455
|
}
|
|
@@ -490,7 +459,7 @@ function readBuildAdoption(cwd) {
|
|
|
490
459
|
if (!configFile) return NOT_ADOPTED(null);
|
|
491
460
|
let source;
|
|
492
461
|
try {
|
|
493
|
-
source =
|
|
462
|
+
source = readFileSync3(join3(cwd, configFile), "utf8");
|
|
494
463
|
} catch (error) {
|
|
495
464
|
return NOT_ADOPTED(configFile, error instanceof Error ? error.message : String(error));
|
|
496
465
|
}
|
|
@@ -526,7 +495,7 @@ function readBuildAdoption(cwd) {
|
|
|
526
495
|
import { spawnSync } from "node:child_process";
|
|
527
496
|
|
|
528
497
|
// src/core/config/tool-args.ts
|
|
529
|
-
import { existsSync as
|
|
498
|
+
import { existsSync as existsSync4 } from "node:fs";
|
|
530
499
|
import { isAbsolute, resolve as resolve2 } from "node:path";
|
|
531
500
|
function splitToolArgs(cwd, toolArgs = [], { valueFlags = [] } = {}) {
|
|
532
501
|
const takesValue = new Set(valueFlags);
|
|
@@ -536,53 +505,20 @@ function splitToolArgs(cwd, toolArgs = [], { valueFlags = [] } = {}) {
|
|
|
536
505
|
for (const arg of toolArgs) {
|
|
537
506
|
const looksLikeOption = arg.startsWith("-");
|
|
538
507
|
const target = isAbsolute(arg) ? arg : resolve2(cwd, arg);
|
|
539
|
-
if (!previousTakesValue && !looksLikeOption &&
|
|
508
|
+
if (!previousTakesValue && !looksLikeOption && existsSync4(target)) paths.push(arg);
|
|
540
509
|
else options.push(arg);
|
|
541
510
|
previousTakesValue = !arg.includes("=") && takesValue.has(arg);
|
|
542
511
|
}
|
|
543
512
|
return { options, paths };
|
|
544
513
|
}
|
|
545
514
|
|
|
546
|
-
// src/shared/resolve-bin.ts
|
|
547
|
-
import { existsSync as existsSync6 } from "node:fs";
|
|
548
|
-
import { createRequire } from "node:module";
|
|
549
|
-
import { delimiter, dirname, join as join5 } from "node:path";
|
|
550
|
-
var require2 = createRequire(import.meta.url);
|
|
551
|
-
function resolveBin(fromDir, name) {
|
|
552
|
-
let dir = fromDir;
|
|
553
|
-
for (; ; ) {
|
|
554
|
-
const candidate = join5(dir, "node_modules", ".bin", name);
|
|
555
|
-
if (existsSync6(candidate)) return candidate;
|
|
556
|
-
const parent = dirname(dir);
|
|
557
|
-
if (parent === dir) return void 0;
|
|
558
|
-
dir = parent;
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
function binFromOwnInstall(packageName, binName) {
|
|
562
|
-
try {
|
|
563
|
-
const manifest = require2.resolve(`${packageName}/package.json`);
|
|
564
|
-
const bin = require2(manifest).bin;
|
|
565
|
-
const relative9 = typeof bin === "string" ? bin : bin?.[binName];
|
|
566
|
-
if (!relative9) return void 0;
|
|
567
|
-
const executable = join5(dirname(manifest), relative9);
|
|
568
|
-
return existsSync6(executable) ? executable : void 0;
|
|
569
|
-
} catch {
|
|
570
|
-
return void 0;
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
function binSearchPath(cwd) {
|
|
574
|
-
return [`${cwd}${delimiter}node_modules/.bin (and parents)`, "sentinel's own install"].join(
|
|
575
|
-
" then "
|
|
576
|
-
);
|
|
577
|
-
}
|
|
578
|
-
|
|
579
515
|
// src/roles/build/plan.ts
|
|
580
|
-
import { existsSync as
|
|
581
|
-
import { join as
|
|
516
|
+
import { existsSync as existsSync8, readFileSync as readFileSync7 } from "node:fs";
|
|
517
|
+
import { join as join8 } from "node:path";
|
|
582
518
|
|
|
583
519
|
// src/core/config/existing-command.ts
|
|
584
|
-
import { readFileSync as
|
|
585
|
-
import { join as
|
|
520
|
+
import { readFileSync as readFileSync4 } from "node:fs";
|
|
521
|
+
import { join as join4 } from "node:path";
|
|
586
522
|
|
|
587
523
|
// src/shared/jsonc.ts
|
|
588
524
|
import { parse, printParseErrorCode } from "jsonc-parser";
|
|
@@ -601,7 +537,7 @@ function nxTargetCommand(cwd, target) {
|
|
|
601
537
|
let project;
|
|
602
538
|
try {
|
|
603
539
|
project = parseJsonc(
|
|
604
|
-
|
|
540
|
+
readFileSync4(join4(cwd, "project.json"), "utf8"),
|
|
605
541
|
"project.json"
|
|
606
542
|
);
|
|
607
543
|
} catch {
|
|
@@ -632,8 +568,8 @@ function existingCommand(cwd, target) {
|
|
|
632
568
|
}
|
|
633
569
|
|
|
634
570
|
// src/core/config/nx-target.ts
|
|
635
|
-
import { existsSync as
|
|
636
|
-
import { join as
|
|
571
|
+
import { existsSync as existsSync5 } from "node:fs";
|
|
572
|
+
import { join as join5 } from "node:path";
|
|
637
573
|
function nxTargetMetadataOperations(options) {
|
|
638
574
|
const { targets } = options;
|
|
639
575
|
if (Object.keys(targets).length === 0) return [];
|
|
@@ -644,7 +580,7 @@ function nxTargetOperations(options) {
|
|
|
644
580
|
const names = Object.keys(targets);
|
|
645
581
|
if (names.length === 0) return [];
|
|
646
582
|
const operations = [];
|
|
647
|
-
if (
|
|
583
|
+
if (existsSync5(join5(cwd, "project.json"))) {
|
|
648
584
|
operations.push({
|
|
649
585
|
kind: "remove-json-keys",
|
|
650
586
|
path: "project.json",
|
|
@@ -698,8 +634,8 @@ function keepsOtherCommands(script, sentinelCommand) {
|
|
|
698
634
|
}
|
|
699
635
|
|
|
700
636
|
// src/roles/format/read-adoption.ts
|
|
701
|
-
import { existsSync as
|
|
702
|
-
import { join as
|
|
637
|
+
import { existsSync as existsSync6, readFileSync as readFileSync5 } from "node:fs";
|
|
638
|
+
import { join as join6 } from "node:path";
|
|
703
639
|
|
|
704
640
|
// src/roles/format/config-policy.ts
|
|
705
641
|
var FORMAT_CONFIG_FILE = ".oxfmtrc.json";
|
|
@@ -805,11 +741,11 @@ function sameValue(a, b) {
|
|
|
805
741
|
return JSON.stringify(a) === JSON.stringify(b);
|
|
806
742
|
}
|
|
807
743
|
function readFormatAdoption(cwd) {
|
|
808
|
-
const path =
|
|
809
|
-
if (!
|
|
744
|
+
const path = join6(cwd, FORMAT_CONFIG_FILE);
|
|
745
|
+
if (!existsSync6(path)) return NOT_ADOPTED2(null);
|
|
810
746
|
let parsed;
|
|
811
747
|
try {
|
|
812
|
-
parsed = parseJsonc(
|
|
748
|
+
parsed = parseJsonc(readFileSync5(path, "utf8"), FORMAT_CONFIG_FILE);
|
|
813
749
|
} catch (error) {
|
|
814
750
|
const reason = error instanceof Error ? error.message : String(error);
|
|
815
751
|
return NOT_ADOPTED2(FORMAT_CONFIG_FILE, `${FORMAT_CONFIG_FILE} could not be parsed (${reason})`);
|
|
@@ -910,8 +846,8 @@ function devTargetOperations(cwd, devScript) {
|
|
|
910
846
|
}
|
|
911
847
|
|
|
912
848
|
// src/roles/build/nest/adopt.ts
|
|
913
|
-
import { existsSync as
|
|
914
|
-
import { join as
|
|
849
|
+
import { existsSync as existsSync7, readFileSync as readFileSync6 } from "node:fs";
|
|
850
|
+
import { join as join7 } from "node:path";
|
|
915
851
|
var NEST_CONFIG_FILE = "vite.config.mts";
|
|
916
852
|
function asSource(value, depth) {
|
|
917
853
|
const pad = " ".repeat(depth);
|
|
@@ -960,9 +896,9 @@ function nestBuildOutputs(target) {
|
|
|
960
896
|
}
|
|
961
897
|
var OUT_DIR_IN_CONFIG = /^\s*outDir:\s*'([^']+)'/m;
|
|
962
898
|
function nestOutputsFromConfig(cwd) {
|
|
963
|
-
const configPath =
|
|
964
|
-
if (!
|
|
965
|
-
const outDir = OUT_DIR_IN_CONFIG.exec(
|
|
899
|
+
const configPath = join7(cwd, NEST_CONFIG_FILE);
|
|
900
|
+
if (!existsSync7(configPath)) return void 0;
|
|
901
|
+
const outDir = OUT_DIR_IN_CONFIG.exec(readFileSync6(configPath, "utf8"))?.[1];
|
|
966
902
|
return outDir === void 0 ? void 0 : [`{workspaceRoot}/${outDir}`];
|
|
967
903
|
}
|
|
968
904
|
function nestAdoptionOperations(cwd, target) {
|
|
@@ -1267,9 +1203,9 @@ function planNestService(context, webpackTarget) {
|
|
|
1267
1203
|
};
|
|
1268
1204
|
}
|
|
1269
1205
|
function readConfigSource(cwd, configFile) {
|
|
1270
|
-
if (!
|
|
1206
|
+
if (!existsSync8(join8(cwd, configFile))) return "";
|
|
1271
1207
|
try {
|
|
1272
|
-
return
|
|
1208
|
+
return readFileSync7(join8(cwd, configFile), "utf8");
|
|
1273
1209
|
} catch {
|
|
1274
1210
|
return "";
|
|
1275
1211
|
}
|
|
@@ -1454,21 +1390,21 @@ var ViteDevAdapter = class extends ViteRoleAdapter {
|
|
|
1454
1390
|
};
|
|
1455
1391
|
|
|
1456
1392
|
// src/roles/build/declared-outputs.ts
|
|
1457
|
-
import { existsSync as
|
|
1458
|
-
import { join as
|
|
1393
|
+
import { existsSync as existsSync9, rmSync, statSync, writeFileSync } from "node:fs";
|
|
1394
|
+
import { join as join9 } from "node:path";
|
|
1459
1395
|
function declaredBuildTarget(cwd) {
|
|
1460
1396
|
return readProjectPackageJson(cwd).nx?.targets?.[BUILD_SCRIPT_NAME];
|
|
1461
1397
|
}
|
|
1462
1398
|
function resolveOutputToken(token, cwd) {
|
|
1463
|
-
if (token.startsWith("{projectRoot}/")) return
|
|
1399
|
+
if (token.startsWith("{projectRoot}/")) return join9(cwd, token.slice("{projectRoot}/".length));
|
|
1464
1400
|
if (token.startsWith("{workspaceRoot}/")) {
|
|
1465
1401
|
const root = findWorkspaceRoot(cwd);
|
|
1466
|
-
return root === void 0 ? void 0 :
|
|
1402
|
+
return root === void 0 ? void 0 : join9(root, token.slice("{workspaceRoot}/".length));
|
|
1467
1403
|
}
|
|
1468
|
-
return
|
|
1404
|
+
return join9(cwd, token);
|
|
1469
1405
|
}
|
|
1470
1406
|
function buildStamp(cwd) {
|
|
1471
|
-
const marker =
|
|
1407
|
+
const marker = join9(cwd, `.sentinel-build-stamp-${process.pid}`);
|
|
1472
1408
|
try {
|
|
1473
1409
|
writeFileSync(marker, "");
|
|
1474
1410
|
const stamp = statSync(marker).mtimeMs;
|
|
@@ -1479,7 +1415,7 @@ function buildStamp(cwd) {
|
|
|
1479
1415
|
}
|
|
1480
1416
|
}
|
|
1481
1417
|
function writtenSince(path, startedAt) {
|
|
1482
|
-
if (!
|
|
1418
|
+
if (!existsSync9(path)) return false;
|
|
1483
1419
|
try {
|
|
1484
1420
|
return statSync(path).mtimeMs >= startedAt;
|
|
1485
1421
|
} catch {
|
|
@@ -1628,12 +1564,12 @@ function registerBuild() {
|
|
|
1628
1564
|
|
|
1629
1565
|
// src/roles/format/adapters/oxfmt/oxfmt.adapter.ts
|
|
1630
1566
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
1631
|
-
import { existsSync as
|
|
1632
|
-
import { join as
|
|
1567
|
+
import { existsSync as existsSync12, readFileSync as readFileSync11 } from "node:fs";
|
|
1568
|
+
import { join as join14 } from "node:path";
|
|
1633
1569
|
|
|
1634
1570
|
// src/core/config/has-source.ts
|
|
1635
1571
|
import { readdirSync } from "node:fs";
|
|
1636
|
-
import { extname, join as
|
|
1572
|
+
import { extname, join as join10, relative as relative2 } from "node:path";
|
|
1637
1573
|
var SKIP_DIRECTORIES = /* @__PURE__ */ new Set([
|
|
1638
1574
|
"node_modules",
|
|
1639
1575
|
"dist",
|
|
@@ -1684,7 +1620,7 @@ function hasSourceFiles(cwd, extensions) {
|
|
|
1684
1620
|
}
|
|
1685
1621
|
for (const entry of entries) {
|
|
1686
1622
|
if (entry.isDirectory()) {
|
|
1687
|
-
if (!SKIP_DIRECTORIES.has(entry.name)) queue.push(
|
|
1623
|
+
if (!SKIP_DIRECTORIES.has(entry.name)) queue.push(join10(dir, entry.name));
|
|
1688
1624
|
continue;
|
|
1689
1625
|
}
|
|
1690
1626
|
if (wanted.has(extname(entry.name))) return true;
|
|
@@ -1705,7 +1641,7 @@ function listSourceFiles(cwd, extensions) {
|
|
|
1705
1641
|
continue;
|
|
1706
1642
|
}
|
|
1707
1643
|
for (const entry of entries) {
|
|
1708
|
-
const full =
|
|
1644
|
+
const full = join10(dir, entry.name);
|
|
1709
1645
|
if (entry.isDirectory()) {
|
|
1710
1646
|
if (!SKIP_DIRECTORIES.has(entry.name)) queue.push(full);
|
|
1711
1647
|
continue;
|
|
@@ -1751,8 +1687,8 @@ function writesWhenRewritten(name, command) {
|
|
|
1751
1687
|
var CHECK_SCRIPT_NAMES = /* @__PURE__ */ new Set(["lint", "format", "check", "test", "typecheck", "verify"]);
|
|
1752
1688
|
|
|
1753
1689
|
// src/roles/format/inherited-ignores.ts
|
|
1754
|
-
import { existsSync as
|
|
1755
|
-
import { join as
|
|
1690
|
+
import { existsSync as existsSync10, readFileSync as readFileSync8 } from "node:fs";
|
|
1691
|
+
import { join as join11 } from "node:path";
|
|
1756
1692
|
var ROOT_IGNORE_FILE = ".prettierignore";
|
|
1757
1693
|
function isPattern(line) {
|
|
1758
1694
|
const trimmed = line.trim();
|
|
@@ -1768,11 +1704,11 @@ function toModulePattern(pattern) {
|
|
|
1768
1704
|
}
|
|
1769
1705
|
function inheritedIgnorePatterns(workspaceRoot) {
|
|
1770
1706
|
if (!workspaceRoot) return [];
|
|
1771
|
-
const path =
|
|
1772
|
-
if (!
|
|
1707
|
+
const path = join11(workspaceRoot, ROOT_IGNORE_FILE);
|
|
1708
|
+
if (!existsSync10(path)) return [];
|
|
1773
1709
|
let contents;
|
|
1774
1710
|
try {
|
|
1775
|
-
contents =
|
|
1711
|
+
contents = readFileSync8(path, "utf8");
|
|
1776
1712
|
} catch {
|
|
1777
1713
|
return [];
|
|
1778
1714
|
}
|
|
@@ -1817,13 +1753,13 @@ function needsSvelteCompiler(output) {
|
|
|
1817
1753
|
}
|
|
1818
1754
|
|
|
1819
1755
|
// src/roles/format/prettier-config.ts
|
|
1820
|
-
import { existsSync as
|
|
1821
|
-
import { join as
|
|
1756
|
+
import { existsSync as existsSync11, readFileSync as readFileSync10 } from "node:fs";
|
|
1757
|
+
import { join as join13 } from "node:path";
|
|
1822
1758
|
|
|
1823
1759
|
// src/roles/format/resolve-oxfmt.ts
|
|
1824
|
-
import { readFileSync as
|
|
1825
|
-
import { createRequire
|
|
1826
|
-
import { dirname
|
|
1760
|
+
import { readFileSync as readFileSync9 } from "node:fs";
|
|
1761
|
+
import { createRequire } from "node:module";
|
|
1762
|
+
import { dirname, join as join12 } from "node:path";
|
|
1827
1763
|
function resolveOxfmt(cwd) {
|
|
1828
1764
|
return resolveBin(cwd, "oxfmt") ?? binFromOwnInstall("oxfmt", "oxfmt");
|
|
1829
1765
|
}
|
|
@@ -1851,9 +1787,9 @@ function configSchema() {
|
|
|
1851
1787
|
}
|
|
1852
1788
|
function readConfigSchema() {
|
|
1853
1789
|
try {
|
|
1854
|
-
const manifest =
|
|
1855
|
-
const schemaPath =
|
|
1856
|
-
return JSON.parse(
|
|
1790
|
+
const manifest = createRequire(import.meta.url).resolve("oxfmt/package.json");
|
|
1791
|
+
const schemaPath = join12(dirname(manifest), "configuration_schema.json");
|
|
1792
|
+
return JSON.parse(readFileSync9(schemaPath, "utf8"));
|
|
1857
1793
|
} catch {
|
|
1858
1794
|
return void 0;
|
|
1859
1795
|
}
|
|
@@ -1884,14 +1820,14 @@ function toOxfmtOverrides(value) {
|
|
|
1884
1820
|
return { overrides, unresolved };
|
|
1885
1821
|
}
|
|
1886
1822
|
function readPrettierSettings(cwd) {
|
|
1887
|
-
const file = PRETTIER_CONFIG_FILES.find((name) =>
|
|
1823
|
+
const file = PRETTIER_CONFIG_FILES.find((name) => existsSync11(join13(cwd, name)));
|
|
1888
1824
|
if (!file) return { options: {}, unresolved: [] };
|
|
1889
1825
|
if (/\.(js|cjs|mjs)$/.test(file)) {
|
|
1890
1826
|
return { options: {}, file, unresolved: [`${file} is JavaScript, so it was not executed`] };
|
|
1891
1827
|
}
|
|
1892
1828
|
let parsed;
|
|
1893
1829
|
try {
|
|
1894
|
-
parsed = parseJsonc(
|
|
1830
|
+
parsed = parseJsonc(readFileSync10(join13(cwd, file), "utf8"), file);
|
|
1895
1831
|
} catch {
|
|
1896
1832
|
return { options: {}, file, unresolved: [`${file} could not be parsed`] };
|
|
1897
1833
|
}
|
|
@@ -2002,7 +1938,7 @@ var OxfmtAdapter = class extends BaseAdapter {
|
|
|
2002
1938
|
manifestOperation(context.cwd, this.formatScripts(context.cwd))
|
|
2003
1939
|
];
|
|
2004
1940
|
const prettierConfigs = PRETTIER_CONFIG_FILES.filter(
|
|
2005
|
-
(name) =>
|
|
1941
|
+
(name) => existsSync12(join14(context.cwd, name))
|
|
2006
1942
|
);
|
|
2007
1943
|
for (const name of prettierConfigs) operations.push({ kind: "delete", path: name });
|
|
2008
1944
|
const removableDeps = this.modulePrettierDependencies(context.cwd);
|
|
@@ -2242,7 +2178,7 @@ var OxfmtAdapter = class extends BaseAdapter {
|
|
|
2242
2178
|
modulePrettierDependencies(cwd) {
|
|
2243
2179
|
const isPrettierPackage = (name) => name === "prettier" || name.startsWith("prettier-plugin-") || name.startsWith("@prettier/");
|
|
2244
2180
|
try {
|
|
2245
|
-
const manifest = JSON.parse(
|
|
2181
|
+
const manifest = JSON.parse(readFileSync11(join14(cwd, "package.json"), "utf8"));
|
|
2246
2182
|
return Object.keys(manifest.devDependencies ?? {}).filter(isPrettierPackage).map((name) => ["devDependencies", name]);
|
|
2247
2183
|
} catch {
|
|
2248
2184
|
return [];
|
|
@@ -2324,8 +2260,8 @@ function registerFormat() {
|
|
|
2324
2260
|
|
|
2325
2261
|
// src/roles/lint/adapters/oxlint/oxlint.adapter.ts
|
|
2326
2262
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
2327
|
-
import { existsSync as
|
|
2328
|
-
import { join as
|
|
2263
|
+
import { existsSync as existsSync20, readFileSync as readFileSync19, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
2264
|
+
import { join as join24 } from "node:path";
|
|
2329
2265
|
|
|
2330
2266
|
// src/core/config/deferred-rules.ts
|
|
2331
2267
|
function deferredRuleNames(rules) {
|
|
@@ -2334,7 +2270,7 @@ function deferredRuleNames(rules) {
|
|
|
2334
2270
|
|
|
2335
2271
|
// src/core/fix-report.ts
|
|
2336
2272
|
import { statSync as statSync2 } from "node:fs";
|
|
2337
|
-
import { join as
|
|
2273
|
+
import { join as join15 } from "node:path";
|
|
2338
2274
|
var CONFIG_REFUSED = /failed to parse .*config|invalid config file/i;
|
|
2339
2275
|
function readFailure(output) {
|
|
2340
2276
|
const lines = output.split("\n").map((line2) => line2.trim());
|
|
@@ -2354,7 +2290,7 @@ function fingerprint(path) {
|
|
|
2354
2290
|
function snapshotFiles(cwd, extensions) {
|
|
2355
2291
|
const snapshot = /* @__PURE__ */ new Map();
|
|
2356
2292
|
for (const file of listSourceFiles(cwd, extensions)) {
|
|
2357
|
-
const mark = fingerprint(
|
|
2293
|
+
const mark = fingerprint(join15(cwd, file));
|
|
2358
2294
|
if (mark !== void 0) snapshot.set(file, mark);
|
|
2359
2295
|
}
|
|
2360
2296
|
return snapshot;
|
|
@@ -2362,7 +2298,7 @@ function snapshotFiles(cwd, extensions) {
|
|
|
2362
2298
|
function changedSince(cwd, before, extensions) {
|
|
2363
2299
|
const changed = [];
|
|
2364
2300
|
for (const file of listSourceFiles(cwd, extensions)) {
|
|
2365
|
-
const now = fingerprint(
|
|
2301
|
+
const now = fingerprint(join15(cwd, file));
|
|
2366
2302
|
if (now === void 0) continue;
|
|
2367
2303
|
if (before.get(file) !== now) changed.push(file);
|
|
2368
2304
|
}
|
|
@@ -2385,8 +2321,8 @@ function describeFixOutcome(outcome, toolLabel) {
|
|
|
2385
2321
|
}
|
|
2386
2322
|
|
|
2387
2323
|
// src/roles/lint/module-baseline.ts
|
|
2388
|
-
import { existsSync as
|
|
2389
|
-
import { join as
|
|
2324
|
+
import { existsSync as existsSync13, readFileSync as readFileSync12 } from "node:fs";
|
|
2325
|
+
import { join as join16 } from "node:path";
|
|
2390
2326
|
var LINT_BASELINE_FILE = ".oxlintrc.baseline.json";
|
|
2391
2327
|
var LINT_MEASURE_FILE = ".oxlintrc.measure.json";
|
|
2392
2328
|
var LINT_BASELINE_SPECIFIER = `./${LINT_BASELINE_FILE}`;
|
|
@@ -2430,11 +2366,11 @@ function describeHolds(holds) {
|
|
|
2430
2366
|
return `held ${holds.length} rule(s) at \`warn\` for this module, covering ${total} violation(s) that were already there: ${listed}${rest}. They are written to ${LINT_BASELINE_FILE}, they still report, and they return to \`error\` once fixed and re-initialized`;
|
|
2431
2367
|
}
|
|
2432
2368
|
function heldRules(cwd) {
|
|
2433
|
-
const path =
|
|
2434
|
-
if (!
|
|
2369
|
+
const path = join16(cwd, LINT_BASELINE_FILE);
|
|
2370
|
+
if (!existsSync13(path)) return [];
|
|
2435
2371
|
try {
|
|
2436
2372
|
const parsed = parseJsonc(
|
|
2437
|
-
|
|
2373
|
+
readFileSync12(path, "utf8"),
|
|
2438
2374
|
LINT_BASELINE_FILE
|
|
2439
2375
|
);
|
|
2440
2376
|
return Object.keys(parsed.rules ?? {});
|
|
@@ -4260,14 +4196,14 @@ function downgradedRulesFor(preset) {
|
|
|
4260
4196
|
}
|
|
4261
4197
|
|
|
4262
4198
|
// src/roles/lint/extra-layers.ts
|
|
4263
|
-
import { existsSync as
|
|
4264
|
-
import { isAbsolute as isAbsolute2, join as
|
|
4199
|
+
import { existsSync as existsSync14, readFileSync as readFileSync13 } from "node:fs";
|
|
4200
|
+
import { isAbsolute as isAbsolute2, join as join17, resolve as resolve3 } from "node:path";
|
|
4265
4201
|
function ruleCount(cwd, specifier) {
|
|
4266
4202
|
const path = isAbsolute2(specifier) ? specifier : resolve3(cwd, specifier);
|
|
4267
|
-
if (!
|
|
4203
|
+
if (!existsSync14(path)) return void 0;
|
|
4268
4204
|
try {
|
|
4269
4205
|
const parsed = parseJsonc(
|
|
4270
|
-
|
|
4206
|
+
readFileSync13(path, "utf8"),
|
|
4271
4207
|
specifier
|
|
4272
4208
|
);
|
|
4273
4209
|
return Object.keys(parsed.rules ?? {}).length;
|
|
@@ -4287,7 +4223,7 @@ function extraLayers(cwd, extendsList) {
|
|
|
4287
4223
|
function committedExtendsList(cwd, configFile) {
|
|
4288
4224
|
try {
|
|
4289
4225
|
const parsed = parseJsonc(
|
|
4290
|
-
|
|
4226
|
+
readFileSync13(join17(cwd, configFile), "utf8"),
|
|
4291
4227
|
configFile
|
|
4292
4228
|
);
|
|
4293
4229
|
return Array.isArray(parsed.extends) ? parsed.extends.filter((entry) => typeof entry === "string") : [];
|
|
@@ -4346,8 +4282,8 @@ function errorCountsByConfigRule(stdout) {
|
|
|
4346
4282
|
}
|
|
4347
4283
|
|
|
4348
4284
|
// src/core/config/read-adoption.ts
|
|
4349
|
-
import { existsSync as
|
|
4350
|
-
import { join as
|
|
4285
|
+
import { existsSync as existsSync16, readFileSync as readFileSync15 } from "node:fs";
|
|
4286
|
+
import { join as join19 } from "node:path";
|
|
4351
4287
|
|
|
4352
4288
|
// src/core/config/owned-keys.ts
|
|
4353
4289
|
function presetOwnedKeys(config, permitted, presetSets) {
|
|
@@ -4362,12 +4298,12 @@ function localOnlyKeys(config, permitted, presetSets) {
|
|
|
4362
4298
|
}
|
|
4363
4299
|
|
|
4364
4300
|
// src/core/config/resolve-config-target.ts
|
|
4365
|
-
import { existsSync as
|
|
4366
|
-
import { join as
|
|
4301
|
+
import { existsSync as existsSync15, readFileSync as readFileSync14 } from "node:fs";
|
|
4302
|
+
import { join as join18 } from "node:path";
|
|
4367
4303
|
function readExtends(absolutePath) {
|
|
4368
4304
|
let parsed;
|
|
4369
4305
|
try {
|
|
4370
|
-
parsed = parseJsonc(
|
|
4306
|
+
parsed = parseJsonc(readFileSync14(absolutePath, "utf8"), absolutePath);
|
|
4371
4307
|
} catch {
|
|
4372
4308
|
return [];
|
|
4373
4309
|
}
|
|
@@ -4381,8 +4317,8 @@ function resolveConfigTarget(moduleDir, { candidates, markers, fallback }) {
|
|
|
4381
4317
|
let existing;
|
|
4382
4318
|
let existingExtendsSomething = false;
|
|
4383
4319
|
for (const candidate of candidates) {
|
|
4384
|
-
const absolutePath =
|
|
4385
|
-
if (!
|
|
4320
|
+
const absolutePath = join18(moduleDir, candidate);
|
|
4321
|
+
if (!existsSync15(absolutePath)) continue;
|
|
4386
4322
|
const chain = readExtends(absolutePath);
|
|
4387
4323
|
if (existing === void 0) {
|
|
4388
4324
|
existing = candidate;
|
|
@@ -4415,12 +4351,12 @@ var NOT_ADOPTED3 = (configFile, unreadable = null) => ({
|
|
|
4415
4351
|
});
|
|
4416
4352
|
function readAdoption(cwd, options) {
|
|
4417
4353
|
const target = resolveConfigTarget(cwd, options);
|
|
4418
|
-
if (target.reason === "none" || !
|
|
4354
|
+
if (target.reason === "none" || !existsSync16(join19(cwd, target.path))) {
|
|
4419
4355
|
return NOT_ADOPTED3(target.reason === "none" ? null : target.path);
|
|
4420
4356
|
}
|
|
4421
4357
|
let parsed;
|
|
4422
4358
|
try {
|
|
4423
|
-
parsed = parseJsonc(
|
|
4359
|
+
parsed = parseJsonc(readFileSync15(join19(cwd, target.path), "utf8"), target.path);
|
|
4424
4360
|
} catch (error) {
|
|
4425
4361
|
const reason = error instanceof Error ? error.message : String(error);
|
|
4426
4362
|
return NOT_ADOPTED3(target.path, `${target.path} could not be parsed (${reason})`);
|
|
@@ -4454,15 +4390,15 @@ function readLintAdoption(cwd) {
|
|
|
4454
4390
|
}
|
|
4455
4391
|
|
|
4456
4392
|
// src/roles/lint/resolve-oxlint.ts
|
|
4457
|
-
import { existsSync as
|
|
4458
|
-
import { createRequire as
|
|
4459
|
-
import { delimiter
|
|
4393
|
+
import { existsSync as existsSync17 } from "node:fs";
|
|
4394
|
+
import { createRequire as createRequire2 } from "node:module";
|
|
4395
|
+
import { delimiter, dirname as dirname2, join as join20 } from "node:path";
|
|
4460
4396
|
import { fileURLToPath } from "node:url";
|
|
4461
4397
|
var PACKAGE_OF = {
|
|
4462
4398
|
oxlint: "oxlint",
|
|
4463
4399
|
tsgolint: "oxlint-tsgolint"
|
|
4464
4400
|
};
|
|
4465
|
-
var
|
|
4401
|
+
var require2 = createRequire2(import.meta.url);
|
|
4466
4402
|
function resolveOxlint(cwd, name = "oxlint") {
|
|
4467
4403
|
return resolveBin(cwd, name) ?? binFromOwnInstall(PACKAGE_OF[name], name);
|
|
4468
4404
|
}
|
|
@@ -4472,7 +4408,7 @@ function canRunTypeAware(cwd) {
|
|
|
4472
4408
|
function oxlintPath(cwd, env) {
|
|
4473
4409
|
const shim = tsgolintShim(cwd);
|
|
4474
4410
|
if (!shim) return env.PATH;
|
|
4475
|
-
return [
|
|
4411
|
+
return [dirname2(shim), env.PATH].filter(Boolean).join(delimiter);
|
|
4476
4412
|
}
|
|
4477
4413
|
function tsgolintShim(cwd) {
|
|
4478
4414
|
const fromModule = resolveBin(cwd, "tsgolint");
|
|
@@ -4480,31 +4416,31 @@ function tsgolintShim(cwd) {
|
|
|
4480
4416
|
const candidates = [];
|
|
4481
4417
|
for (const owner of ["oxlint-tsgolint", "oxlint"]) {
|
|
4482
4418
|
try {
|
|
4483
|
-
const packageDir =
|
|
4484
|
-
candidates.push(
|
|
4485
|
-
candidates.push(
|
|
4419
|
+
const packageDir = dirname2(require2.resolve(`${owner}/package.json`));
|
|
4420
|
+
candidates.push(join20(packageDir, "node_modules", ".bin", "tsgolint"));
|
|
4421
|
+
candidates.push(join20(packageDir, "..", ".bin", "tsgolint"));
|
|
4486
4422
|
} catch {
|
|
4487
4423
|
}
|
|
4488
4424
|
}
|
|
4489
4425
|
try {
|
|
4490
|
-
const ownRoot =
|
|
4491
|
-
candidates.push(
|
|
4426
|
+
const ownRoot = dirname2(require2.resolve("@hublo/sentinel/package.json"));
|
|
4427
|
+
candidates.push(join20(ownRoot, "node_modules", ".bin", "tsgolint"));
|
|
4492
4428
|
} catch {
|
|
4493
|
-
candidates.push(resolveBin(
|
|
4429
|
+
candidates.push(resolveBin(dirname2(fileURLToPath(import.meta.url)), "tsgolint") ?? "");
|
|
4494
4430
|
}
|
|
4495
|
-
return candidates.find((candidate) => candidate !== "" &&
|
|
4431
|
+
return candidates.find((candidate) => candidate !== "" && existsSync17(candidate));
|
|
4496
4432
|
}
|
|
4497
4433
|
function oxlintSearchPath(cwd) {
|
|
4498
4434
|
return binSearchPath(cwd);
|
|
4499
4435
|
}
|
|
4500
4436
|
|
|
4501
4437
|
// src/roles/lint/adapters/oxlint/plan.ts
|
|
4502
|
-
import { existsSync as
|
|
4503
|
-
import { join as
|
|
4438
|
+
import { existsSync as existsSync19, readFileSync as readFileSync18 } from "node:fs";
|
|
4439
|
+
import { join as join23 } from "node:path";
|
|
4504
4440
|
|
|
4505
4441
|
// src/roles/lint/eslint-ignores.ts
|
|
4506
|
-
import { existsSync as
|
|
4507
|
-
import { join as
|
|
4442
|
+
import { existsSync as existsSync18, readFileSync as readFileSync16 } from "node:fs";
|
|
4443
|
+
import { join as join21 } from "node:path";
|
|
4508
4444
|
import { parseSync as parseSync2 } from "oxc-parser";
|
|
4509
4445
|
|
|
4510
4446
|
// src/shared/ast.ts
|
|
@@ -4533,11 +4469,11 @@ function readRootEslintIgnores(root) {
|
|
|
4533
4469
|
return { patterns: patterns.filter((pattern) => pattern.startsWith("**/")), unresolved };
|
|
4534
4470
|
}
|
|
4535
4471
|
function readEslintIgnores(cwd) {
|
|
4536
|
-
const config = ESLINT_CONFIG_FILES.map((name) =>
|
|
4472
|
+
const config = ESLINT_CONFIG_FILES.map((name) => join21(cwd, name)).find((path) => existsSync18(path));
|
|
4537
4473
|
if (!config) return { patterns: [], unresolved: [] };
|
|
4538
4474
|
let source;
|
|
4539
4475
|
try {
|
|
4540
|
-
source =
|
|
4476
|
+
source = readFileSync16(config, "utf8");
|
|
4541
4477
|
} catch {
|
|
4542
4478
|
return { patterns: [], unresolved: [] };
|
|
4543
4479
|
}
|
|
@@ -4628,8 +4564,8 @@ function lintPresetFor(preset) {
|
|
|
4628
4564
|
}
|
|
4629
4565
|
|
|
4630
4566
|
// src/roles/lint/rename-suppressions.ts
|
|
4631
|
-
import { readdirSync as readdirSync2, readFileSync as
|
|
4632
|
-
import { join as
|
|
4567
|
+
import { readdirSync as readdirSync2, readFileSync as readFileSync17, statSync as statSync3 } from "node:fs";
|
|
4568
|
+
import { join as join22, relative as relative3 } from "node:path";
|
|
4633
4569
|
var SOURCE_EXTENSIONS = [
|
|
4634
4570
|
".ts",
|
|
4635
4571
|
".tsx",
|
|
@@ -4676,7 +4612,7 @@ function* sourceFiles(dir) {
|
|
|
4676
4612
|
return;
|
|
4677
4613
|
}
|
|
4678
4614
|
for (const entry of entries) {
|
|
4679
|
-
const full =
|
|
4615
|
+
const full = join22(dir, entry);
|
|
4680
4616
|
let isDirectory;
|
|
4681
4617
|
try {
|
|
4682
4618
|
isDirectory = statSync3(full).isDirectory();
|
|
@@ -4696,7 +4632,7 @@ function findSuppressionRenames(cwd, renames) {
|
|
|
4696
4632
|
for (const file of sourceFiles(cwd)) {
|
|
4697
4633
|
let content;
|
|
4698
4634
|
try {
|
|
4699
|
-
content =
|
|
4635
|
+
content = readFileSync17(file, "utf8");
|
|
4700
4636
|
} catch {
|
|
4701
4637
|
continue;
|
|
4702
4638
|
}
|
|
@@ -4824,7 +4760,7 @@ function plan2(context) {
|
|
|
4824
4760
|
keys: removableDeps
|
|
4825
4761
|
});
|
|
4826
4762
|
}
|
|
4827
|
-
const eslintConfigs = ESLINT_CONFIG_FILES.filter((name) =>
|
|
4763
|
+
const eslintConfigs = ESLINT_CONFIG_FILES.filter((name) => existsSync19(join23(context.cwd, name)));
|
|
4828
4764
|
for (const name of eslintConfigs) operations.push({ kind: "delete", path: name });
|
|
4829
4765
|
operations.push(
|
|
4830
4766
|
...nxTargetOperations({
|
|
@@ -4922,7 +4858,7 @@ function lintScripts(cwd) {
|
|
|
4922
4858
|
function committedExtends(cwd) {
|
|
4923
4859
|
try {
|
|
4924
4860
|
const parsed = parseJsonc(
|
|
4925
|
-
|
|
4861
|
+
readFileSync18(join23(cwd, LINT_CONFIG_FILE), "utf8"),
|
|
4926
4862
|
LINT_CONFIG_FILE
|
|
4927
4863
|
);
|
|
4928
4864
|
return Array.isArray(parsed.extends) ? parsed.extends.filter((entry) => typeof entry === "string") : [];
|
|
@@ -4933,7 +4869,7 @@ function committedExtends(cwd) {
|
|
|
4933
4869
|
function committedIgnorePatterns(cwd) {
|
|
4934
4870
|
try {
|
|
4935
4871
|
const parsed = parseJsonc(
|
|
4936
|
-
|
|
4872
|
+
readFileSync18(join23(cwd, LINT_CONFIG_FILE), "utf8"),
|
|
4937
4873
|
LINT_CONFIG_FILE
|
|
4938
4874
|
);
|
|
4939
4875
|
return Array.isArray(parsed.ignorePatterns) ? parsed.ignorePatterns.filter((entry) => typeof entry === "string") : [];
|
|
@@ -4945,7 +4881,7 @@ function moduleEslintDependencies(cwd) {
|
|
|
4945
4881
|
const isEslintPackage = (name) => name === "eslint" || name === "@types/eslint" || name === "typescript-eslint" || name.startsWith("@typescript-eslint/") || name.startsWith("eslint-plugin-") || name.startsWith("eslint-config-") || name.startsWith("@eslint/");
|
|
4946
4882
|
let manifest;
|
|
4947
4883
|
try {
|
|
4948
|
-
manifest = JSON.parse(
|
|
4884
|
+
manifest = JSON.parse(readFileSync18(join23(cwd, "package.json"), "utf8"));
|
|
4949
4885
|
} catch {
|
|
4950
4886
|
return [];
|
|
4951
4887
|
}
|
|
@@ -5079,20 +5015,20 @@ ${result.stderr ?? ""}`);
|
|
|
5079
5015
|
* build the developer can see, rather than a silent half-adoption they cannot.
|
|
5080
5016
|
*/
|
|
5081
5017
|
writeModuleBaseline(ctx, oxlint, env) {
|
|
5082
|
-
const configPath =
|
|
5083
|
-
const baselinePath =
|
|
5084
|
-
if (!
|
|
5018
|
+
const configPath = join24(ctx.cwd, LINT_CONFIG_FILE);
|
|
5019
|
+
const baselinePath = join24(ctx.cwd, LINT_BASELINE_FILE);
|
|
5020
|
+
if (!existsSync20(configPath)) return;
|
|
5085
5021
|
let config;
|
|
5086
5022
|
try {
|
|
5087
5023
|
config = parseJsonc(
|
|
5088
|
-
|
|
5024
|
+
readFileSync19(configPath, "utf8"),
|
|
5089
5025
|
LINT_CONFIG_FILE
|
|
5090
5026
|
);
|
|
5091
5027
|
} catch {
|
|
5092
5028
|
return;
|
|
5093
5029
|
}
|
|
5094
5030
|
const current = Array.isArray(config.extends) ? config.extends : [];
|
|
5095
|
-
const measurePath =
|
|
5031
|
+
const measurePath = join24(ctx.cwd, LINT_MEASURE_FILE);
|
|
5096
5032
|
let measured;
|
|
5097
5033
|
try {
|
|
5098
5034
|
writeFileSync2(
|
|
@@ -5140,7 +5076,7 @@ ${result.stderr ?? ""}`);
|
|
|
5140
5076
|
}
|
|
5141
5077
|
}
|
|
5142
5078
|
async run(ctx) {
|
|
5143
|
-
if (!
|
|
5079
|
+
if (!existsSync20(join24(ctx.cwd, LINT_CONFIG_FILE))) {
|
|
5144
5080
|
process.stderr.write(
|
|
5145
5081
|
`sentinel lint(oxlint): no ${LINT_CONFIG_FILE} in this module; run \`sentinel --init --lint\` to adopt.
|
|
5146
5082
|
`
|
|
@@ -5288,7 +5224,7 @@ ${result.stderr ?? ""}`);
|
|
|
5288
5224
|
let stub;
|
|
5289
5225
|
try {
|
|
5290
5226
|
stub = parseJsonc(
|
|
5291
|
-
|
|
5227
|
+
readFileSync19(join24(cwd, LINT_CONFIG_FILE), "utf8"),
|
|
5292
5228
|
LINT_CONFIG_FILE
|
|
5293
5229
|
);
|
|
5294
5230
|
} catch {
|
|
@@ -5298,7 +5234,7 @@ ${result.stderr ?? ""}`);
|
|
|
5298
5234
|
for (const entry of stub.extends ?? []) {
|
|
5299
5235
|
try {
|
|
5300
5236
|
const preset = parseJsonc(
|
|
5301
|
-
|
|
5237
|
+
readFileSync19(join24(cwd, entry), "utf8"),
|
|
5302
5238
|
entry
|
|
5303
5239
|
);
|
|
5304
5240
|
for (const rule of Object.keys(preset.rules ?? {})) names.add(rule);
|
|
@@ -5368,14 +5304,14 @@ ${result.stderr ?? ""}`);
|
|
|
5368
5304
|
let parsed;
|
|
5369
5305
|
try {
|
|
5370
5306
|
parsed = parseJsonc(
|
|
5371
|
-
|
|
5307
|
+
readFileSync19(join24(cwd, LINT_CONFIG_FILE), "utf8"),
|
|
5372
5308
|
LINT_CONFIG_FILE
|
|
5373
5309
|
);
|
|
5374
5310
|
} catch {
|
|
5375
5311
|
return void 0;
|
|
5376
5312
|
}
|
|
5377
5313
|
const targets = Array.isArray(parsed.extends) ? parsed.extends.filter((entry) => typeof entry === "string") : typeof parsed.extends === "string" ? [parsed.extends] : [];
|
|
5378
|
-
return targets.find((target) => !
|
|
5314
|
+
return targets.find((target) => !existsSync20(join24(cwd, target)));
|
|
5379
5315
|
}
|
|
5380
5316
|
/** Announce what is not enforced, so reduced coverage is never silent. */
|
|
5381
5317
|
announceDisabled(preset) {
|
|
@@ -5407,103 +5343,29 @@ function registerLint() {
|
|
|
5407
5343
|
|
|
5408
5344
|
// src/roles/test/adapters/vitest/vitest.adapter.ts
|
|
5409
5345
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
5410
|
-
import { isAbsolute as isAbsolute3, resolve as
|
|
5411
|
-
|
|
5412
|
-
// src/roles/test/presets/toolchain.json
|
|
5413
|
-
var toolchain_default2 = {
|
|
5414
|
-
$comment: "The test toolchain sentinel owns. Same shape and same rule as the build one: a single table drives what `--init` removes from a module's package.json, which import specifiers move, and the name each default import is re-exported under, so the three cannot disagree.",
|
|
5415
|
-
owned: [
|
|
5416
|
-
{
|
|
5417
|
-
package: "vitest",
|
|
5418
|
-
specifier: "vitest/config",
|
|
5419
|
-
named: ["defineConfig", "mergeConfig"],
|
|
5420
|
-
types: ["ConfigEnv", "TestUserConfig", "ViteUserConfig"],
|
|
5421
|
-
why: "the runner itself, declared at the workspace ROOT today, which is what stops a module being testable on its own. Note the package is `vitest` and the specifier is `vitest/config`: the same split as nitro on the build side, and the reason one table holds both."
|
|
5422
|
-
},
|
|
5423
|
-
{
|
|
5424
|
-
package: "vite",
|
|
5425
|
-
specifier: "vite",
|
|
5426
|
-
named: ["loadEnv"],
|
|
5427
|
-
why: "`loadEnv` has no equivalent in `vitest/config`, and two of the six configs import it from vite to build their test env. Re-exported here rather than claimed: the BUILD role owns the `vite` package, and two roles owning one package is how a version conflict gets written down twice."
|
|
5428
|
-
}
|
|
5429
|
-
]
|
|
5430
|
-
};
|
|
5431
|
-
|
|
5432
|
-
// src/roles/test/preset-data.ts
|
|
5433
|
-
var OWNED_TEST_PACKAGES = toolchain_default2.owned;
|
|
5434
|
-
|
|
5435
|
-
// src/roles/test/config-policy.ts
|
|
5436
|
-
var TEST_PRESET_SPECIFIERS = {
|
|
5437
|
-
react: "@hublo/sentinel/test/react",
|
|
5438
|
-
nest: "@hublo/sentinel/test/nest"
|
|
5439
|
-
};
|
|
5440
|
-
function testPresetSpecifier(preset) {
|
|
5441
|
-
return TEST_PRESET_SPECIFIERS[preset] ?? TEST_PRESET_SPECIFIERS.react;
|
|
5442
|
-
}
|
|
5443
|
-
var ALL_TEST_PRESET_SPECIFIERS = Object.values(TEST_PRESET_SPECIFIERS);
|
|
5444
|
-
var TEST_PRESET_SPECIFIER = TEST_PRESET_SPECIFIERS.react;
|
|
5445
|
-
var TEST_CONFIG_FILES = [
|
|
5446
|
-
"vitest.config.ts",
|
|
5447
|
-
"vitest.config.mts",
|
|
5448
|
-
"vitest.config.js",
|
|
5449
|
-
"vitest.config.mjs"
|
|
5450
|
-
];
|
|
5451
|
-
var TEST_OWNED_PACKAGES = OWNED_TEST_PACKAGES;
|
|
5452
|
-
var SENTINEL_OWNED_TEST_PACKAGES = TEST_OWNED_PACKAGES.filter(
|
|
5453
|
-
(entry) => entry.package !== "vite"
|
|
5454
|
-
).map((entry) => entry.package);
|
|
5455
|
-
function testToolchain(preset) {
|
|
5456
|
-
return { presetSpecifier: testPresetSpecifier(preset), owned: TEST_OWNED_PACKAGES };
|
|
5457
|
-
}
|
|
5458
|
-
var TEST_SCRIPT_NAME = "test";
|
|
5459
|
-
var SENTINEL_TEST_COMMAND = "sentinel --run --test --";
|
|
5460
|
-
var VITEST_INVOCATION = /(^|&&\s*|\|\|\s*|;\s*)(?:npx\s+|pnpm\s+(?:exec\s+|dlx\s+)?)?vitest\b([^&|;]*)/g;
|
|
5461
|
-
function rewriteVitestScript(command) {
|
|
5462
|
-
return command.replace(VITEST_INVOCATION, (_match, lead, tail) => {
|
|
5463
|
-
const args = tail.trim().split(/\s+/).filter(Boolean);
|
|
5464
|
-
const oneShot = args[0] === "run" || args.includes("--run");
|
|
5465
|
-
const rest = args.filter((arg, index) => !(index === 0 && arg === "run") && arg !== "--run");
|
|
5466
|
-
const passthrough = oneShot ? rest : ["--watch", ...rest];
|
|
5467
|
-
const suffix = passthrough.length > 0 ? ` -- ${passthrough.join(" ")}` : "";
|
|
5468
|
-
const trailing = /\s$/.test(tail) ? " " : "";
|
|
5469
|
-
return `${lead}sentinel --run --test${suffix}${trailing}`;
|
|
5470
|
-
});
|
|
5471
|
-
}
|
|
5472
|
-
function testTarget(options) {
|
|
5473
|
-
const { name, configFiles, outputs, dependsOn, configurations } = options;
|
|
5474
|
-
const cached = outputs !== void 0 && outputs.length > 0;
|
|
5475
|
-
return {
|
|
5476
|
-
[name ?? TEST_SCRIPT_NAME]: {
|
|
5477
|
-
cache: cached,
|
|
5478
|
-
inputs: ["default", "^default", ...configFiles.map((name2) => `{projectRoot}/${name2}`)],
|
|
5479
|
-
...cached ? { outputs: [...outputs] } : {},
|
|
5480
|
-
...dependsOn !== void 0 && dependsOn.length > 0 ? { dependsOn: [...dependsOn] } : {},
|
|
5481
|
-
...configurations !== void 0 && Object.keys(configurations).length > 0 ? { configurations: { ...configurations } } : {}
|
|
5482
|
-
}
|
|
5483
|
-
};
|
|
5484
|
-
}
|
|
5346
|
+
import { isAbsolute as isAbsolute3, resolve as resolve8 } from "node:path";
|
|
5485
5347
|
|
|
5486
5348
|
// src/roles/test/jest-migration.ts
|
|
5487
|
-
import { existsSync as
|
|
5488
|
-
import { createRequire as
|
|
5489
|
-
import { dirname as
|
|
5349
|
+
import { existsSync as existsSync29, readFileSync as readFileSync29, readdirSync as readdirSync7 } from "node:fs";
|
|
5350
|
+
import { createRequire as createRequire5 } from "node:module";
|
|
5351
|
+
import { dirname as dirname10, join as join37, relative as relative7 } from "node:path";
|
|
5490
5352
|
|
|
5491
5353
|
// src/roles/test/codemod/migrate-module.ts
|
|
5492
|
-
import { readdirSync as
|
|
5493
|
-
import { join as
|
|
5354
|
+
import { readdirSync as readdirSync5, readFileSync as readFileSync26, statSync as statSync6 } from "node:fs";
|
|
5355
|
+
import { join as join32 } from "node:path";
|
|
5494
5356
|
import { parseSync as parseSync8 } from "oxc-parser";
|
|
5495
5357
|
|
|
5496
5358
|
// src/roles/test/msw-lifecycle.ts
|
|
5497
|
-
import { existsSync as
|
|
5498
|
-
import { join as
|
|
5359
|
+
import { existsSync as existsSync21, readFileSync as readFileSync20 } from "node:fs";
|
|
5360
|
+
import { join as join25 } from "node:path";
|
|
5499
5361
|
var ROOT_SETUP = "jest.setup.after.env.js";
|
|
5500
5362
|
function ownsMswLifecycle(cwd, setupFiles) {
|
|
5501
5363
|
for (const raw of setupFiles) {
|
|
5502
5364
|
if (raw.endsWith(ROOT_SETUP)) continue;
|
|
5503
|
-
const file =
|
|
5504
|
-
if (!
|
|
5365
|
+
const file = join25(cwd, raw.replaceAll("<rootDir>/", "").replaceAll("<rootDir>", "."));
|
|
5366
|
+
if (!existsSync21(file)) continue;
|
|
5505
5367
|
try {
|
|
5506
|
-
if (/\.listen\s*\(/.test(
|
|
5368
|
+
if (/\.listen\s*\(/.test(readFileSync20(file, "utf8"))) return true;
|
|
5507
5369
|
} catch {
|
|
5508
5370
|
continue;
|
|
5509
5371
|
}
|
|
@@ -5511,141 +5373,19 @@ function ownsMswLifecycle(cwd, setupFiles) {
|
|
|
5511
5373
|
return false;
|
|
5512
5374
|
}
|
|
5513
5375
|
|
|
5514
|
-
// src/roles/test/read-adoption.ts
|
|
5515
|
-
import { existsSync as existsSync24, readFileSync as readFileSync22, readdirSync as readdirSync3 } from "node:fs";
|
|
5516
|
-
import { join as join28, relative as relative4 } from "node:path";
|
|
5517
|
-
var JEST_CONFIG_FILES = [
|
|
5518
|
-
"jest.config.ts",
|
|
5519
|
-
"jest.config.js",
|
|
5520
|
-
"jest.prisma.config.ts",
|
|
5521
|
-
"jest.functional.config.ts",
|
|
5522
|
-
"jest.integration-config.ts"
|
|
5523
|
-
];
|
|
5524
|
-
function testConfigFile(cwd) {
|
|
5525
|
-
return TEST_CONFIG_FILES.find((name) => existsSync24(join28(cwd, name)));
|
|
5526
|
-
}
|
|
5527
|
-
function jestConfigFiles(cwd) {
|
|
5528
|
-
return JEST_CONFIG_FILES.filter((name) => existsSync24(join28(cwd, name)));
|
|
5529
|
-
}
|
|
5530
|
-
function rootJestConfigFiles(cwd) {
|
|
5531
|
-
const root = findWorkspaceRoot(cwd);
|
|
5532
|
-
if (root === void 0 || root === cwd) return [];
|
|
5533
|
-
return JEST_CONFIG_FILES.filter((name) => existsSync24(join28(root, name)));
|
|
5534
|
-
}
|
|
5535
|
-
var TEST_FILE = /[.-](spec|test)\.[cm]?[jt]sx?$/;
|
|
5536
|
-
var NOT_WALKED = /* @__PURE__ */ new Set(["node_modules", "dist", "coverage", ".git", ".nx", ".turbo"]);
|
|
5537
|
-
function hasTestFiles(cwd) {
|
|
5538
|
-
return walkTestFiles(cwd, true).length > 0;
|
|
5539
|
-
}
|
|
5540
|
-
function listTestFiles(cwd) {
|
|
5541
|
-
return walkTestFiles(cwd, false).sort();
|
|
5542
|
-
}
|
|
5543
|
-
function walkTestFiles(cwd, stopAtFirst) {
|
|
5544
|
-
const found = [];
|
|
5545
|
-
const stack = [cwd];
|
|
5546
|
-
while (stack.length > 0) {
|
|
5547
|
-
const dir = stack.pop();
|
|
5548
|
-
let entries;
|
|
5549
|
-
try {
|
|
5550
|
-
entries = readdirSync3(dir, { withFileTypes: true });
|
|
5551
|
-
} catch {
|
|
5552
|
-
continue;
|
|
5553
|
-
}
|
|
5554
|
-
for (const entry of entries) {
|
|
5555
|
-
if (entry.isDirectory()) {
|
|
5556
|
-
if (!NOT_WALKED.has(entry.name)) stack.push(join28(dir, entry.name));
|
|
5557
|
-
} else if (TEST_FILE.test(entry.name)) {
|
|
5558
|
-
found.push(relative4(cwd, join28(dir, entry.name)).replaceAll("\\", "/"));
|
|
5559
|
-
if (stopAtFirst) return found;
|
|
5560
|
-
}
|
|
5561
|
-
}
|
|
5562
|
-
}
|
|
5563
|
-
return found;
|
|
5564
|
-
}
|
|
5565
|
-
function readTestConfigSource(cwd, fileName) {
|
|
5566
|
-
try {
|
|
5567
|
-
return readFileSync22(join28(cwd, fileName), "utf8");
|
|
5568
|
-
} catch {
|
|
5569
|
-
return "";
|
|
5570
|
-
}
|
|
5571
|
-
}
|
|
5572
|
-
function importsPreset2(source) {
|
|
5573
|
-
return ALL_TEST_PRESET_SPECIFIERS.some((specifier) => {
|
|
5574
|
-
const escaped = specifier.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
5575
|
-
return new RegExp(String.raw`(?:from|import)\s*\(?\s*['"]${escaped}['"]`).test(source);
|
|
5576
|
-
});
|
|
5577
|
-
}
|
|
5578
|
-
function readTestAdoption(cwd) {
|
|
5579
|
-
const manifest = readProjectPackageJson(cwd);
|
|
5580
|
-
const jestConfigs = jestConfigFiles(cwd);
|
|
5581
|
-
const configFile = testConfigFile(cwd);
|
|
5582
|
-
const declared = { ...manifest.dependencies, ...manifest.devDependencies };
|
|
5583
|
-
const ownDeclarations = ["vitest", "jest", "@nx/jest", "jest-mock-extended", "@swc/jest"].filter((name) => declared[name] !== void 0).map((name) => ({ name, version: declared[name] }));
|
|
5584
|
-
if (configFile === void 0) {
|
|
5585
|
-
const hasTests = hasTestFiles(cwd);
|
|
5586
|
-
const inheritsRootConfig = hasTests && jestConfigs.length === 0 && rootJestConfigFiles(cwd).length > 0;
|
|
5587
|
-
return {
|
|
5588
|
-
configFile: null,
|
|
5589
|
-
preset: null,
|
|
5590
|
-
adopted: false,
|
|
5591
|
-
conformant: false,
|
|
5592
|
-
drift: [],
|
|
5593
|
-
unreadable: null,
|
|
5594
|
-
state: hasTests ? "jest" : "no-tests",
|
|
5595
|
-
runner: hasTests ? "jest" : "none",
|
|
5596
|
-
jestConfigs,
|
|
5597
|
-
inheritsRootConfig,
|
|
5598
|
-
ownDeclarations
|
|
5599
|
-
};
|
|
5600
|
-
}
|
|
5601
|
-
const source = readTestConfigSource(cwd, configFile);
|
|
5602
|
-
if (source === "") {
|
|
5603
|
-
return {
|
|
5604
|
-
configFile,
|
|
5605
|
-
preset: null,
|
|
5606
|
-
adopted: false,
|
|
5607
|
-
conformant: false,
|
|
5608
|
-
drift: [],
|
|
5609
|
-
unreadable: `${configFile} could not be read`,
|
|
5610
|
-
state: "vitest-own-toolchain",
|
|
5611
|
-
runner: "vitest",
|
|
5612
|
-
jestConfigs,
|
|
5613
|
-
inheritsRootConfig: false,
|
|
5614
|
-
// it has a config of its own, readable or not
|
|
5615
|
-
ownDeclarations
|
|
5616
|
-
};
|
|
5617
|
-
}
|
|
5618
|
-
const adopted = importsPreset2(source);
|
|
5619
|
-
const script = moduleScripts(cwd)["test"];
|
|
5620
|
-
return {
|
|
5621
|
-
configFile,
|
|
5622
|
-
preset: adopted ? "react" : null,
|
|
5623
|
-
adopted,
|
|
5624
|
-
conformant: adopted && script !== void 0 && jestConfigs.length === 0,
|
|
5625
|
-
drift: [],
|
|
5626
|
-
unreadable: null,
|
|
5627
|
-
state: adopted ? "adopted" : "vitest-own-toolchain",
|
|
5628
|
-
runner: "vitest",
|
|
5629
|
-
jestConfigs,
|
|
5630
|
-
inheritsRootConfig: false,
|
|
5631
|
-
// local always wins: this module is out of the root's reach
|
|
5632
|
-
ownDeclarations
|
|
5633
|
-
};
|
|
5634
|
-
}
|
|
5635
|
-
|
|
5636
5376
|
// src/roles/test/support-file-name.ts
|
|
5637
5377
|
var JEST_PREFIX = "jest.";
|
|
5638
5378
|
var VITEST_PREFIX = "vitest.";
|
|
5639
|
-
function vitestSupportName(
|
|
5640
|
-
const cut =
|
|
5641
|
-
const directory = cut === -1 ? "" :
|
|
5642
|
-
const base =
|
|
5643
|
-
if (!base.startsWith(JEST_PREFIX)) return
|
|
5379
|
+
function vitestSupportName(relative8) {
|
|
5380
|
+
const cut = relative8.lastIndexOf("/");
|
|
5381
|
+
const directory = cut === -1 ? "" : relative8.slice(0, cut + 1);
|
|
5382
|
+
const base = relative8.slice(cut + 1);
|
|
5383
|
+
if (!base.startsWith(JEST_PREFIX)) return relative8;
|
|
5644
5384
|
return `${directory}${VITEST_PREFIX}${base.slice(JEST_PREFIX.length)}`;
|
|
5645
5385
|
}
|
|
5646
5386
|
|
|
5647
5387
|
// src/roles/test/codemod/migrate-file.ts
|
|
5648
|
-
import { dirname as
|
|
5388
|
+
import { dirname as dirname7 } from "node:path";
|
|
5649
5389
|
import { parseSync as parseSync7 } from "oxc-parser";
|
|
5650
5390
|
|
|
5651
5391
|
// src/roles/test/codemod/assertion-return-value.ts
|
|
@@ -5774,12 +5514,38 @@ function rewriteAssertionReturnValue(source, program) {
|
|
|
5774
5514
|
return { source: result, rewritten: captures.length - refusals.length, refusals };
|
|
5775
5515
|
}
|
|
5776
5516
|
|
|
5777
|
-
// src/roles/test/codemod/
|
|
5517
|
+
// src/roles/test/codemod/bare-mock-factory.ts
|
|
5778
5518
|
var MEMBER_TYPES2 = /* @__PURE__ */ new Set(["MemberExpression", "StaticMemberExpression"]);
|
|
5519
|
+
function isMockFactory(node) {
|
|
5520
|
+
if (node === void 0 || !MEMBER_TYPES2.has(node.type)) return false;
|
|
5521
|
+
const object = node.object;
|
|
5522
|
+
const property = node.property;
|
|
5523
|
+
if (object?.type !== "Identifier") return false;
|
|
5524
|
+
if (object.name !== "vi" && object.name !== "jest") return false;
|
|
5525
|
+
return property?.type === "Identifier" && property.name === "fn";
|
|
5526
|
+
}
|
|
5527
|
+
function invokeBareMockFactories(source, program) {
|
|
5528
|
+
const edits = [];
|
|
5529
|
+
walk(program, (node) => {
|
|
5530
|
+
if (node.type !== "CallExpression") return;
|
|
5531
|
+
for (const argument of node.arguments ?? []) {
|
|
5532
|
+
if (isMockFactory(argument)) edits.push(argument.end);
|
|
5533
|
+
}
|
|
5534
|
+
});
|
|
5535
|
+
if (edits.length === 0) return { source, rewritten: 0 };
|
|
5536
|
+
let result = source;
|
|
5537
|
+
for (const end of [...edits].sort((left, right) => right - left)) {
|
|
5538
|
+
result = `${result.slice(0, end)}()${result.slice(end)}`;
|
|
5539
|
+
}
|
|
5540
|
+
return { source: result, rewritten: edits.length };
|
|
5541
|
+
}
|
|
5542
|
+
|
|
5543
|
+
// src/roles/test/codemod/constructible-mocks.ts
|
|
5544
|
+
var MEMBER_TYPES3 = /* @__PURE__ */ new Set(["MemberExpression", "StaticMemberExpression"]);
|
|
5779
5545
|
function mockImplementationArrow(node) {
|
|
5780
5546
|
if (node.type !== "CallExpression") return void 0;
|
|
5781
5547
|
const callee = node.callee;
|
|
5782
|
-
if (callee === void 0 || !
|
|
5548
|
+
if (callee === void 0 || !MEMBER_TYPES3.has(callee.type)) return void 0;
|
|
5783
5549
|
const property = callee.property;
|
|
5784
5550
|
if (property?.type !== "Identifier" || property.name !== "mockImplementation") return void 0;
|
|
5785
5551
|
const [argument] = node.arguments ?? [];
|
|
@@ -5788,7 +5554,7 @@ function mockImplementationArrow(node) {
|
|
|
5788
5554
|
function assertedMockedClass(source, node) {
|
|
5789
5555
|
if (node.type !== "CallExpression") return false;
|
|
5790
5556
|
const callee = node.callee;
|
|
5791
|
-
if (callee === void 0 || !
|
|
5557
|
+
if (callee === void 0 || !MEMBER_TYPES3.has(callee.type)) return false;
|
|
5792
5558
|
const object = callee.object;
|
|
5793
5559
|
if (object === void 0) return false;
|
|
5794
5560
|
return /\bMockedClass\b/.test(source.slice(object.start, object.end));
|
|
@@ -5864,16 +5630,16 @@ function normaliseDeepImports(source) {
|
|
|
5864
5630
|
}
|
|
5865
5631
|
|
|
5866
5632
|
// src/roles/test/codemod/each-table-rows.ts
|
|
5867
|
-
var
|
|
5633
|
+
var MEMBER_TYPES4 = /* @__PURE__ */ new Set(["MemberExpression", "StaticMemberExpression"]);
|
|
5868
5634
|
var RUNNERS = /* @__PURE__ */ new Set(["it", "test", "describe"]);
|
|
5869
5635
|
function eachTable(node) {
|
|
5870
5636
|
if (node.type !== "CallExpression") return void 0;
|
|
5871
5637
|
const callee = node.callee;
|
|
5872
|
-
if (callee === void 0 || !
|
|
5638
|
+
if (callee === void 0 || !MEMBER_TYPES4.has(callee.type)) return void 0;
|
|
5873
5639
|
const property = callee.property;
|
|
5874
5640
|
if (property?.type !== "Identifier" || property.name !== "each") return void 0;
|
|
5875
5641
|
let object = callee.object;
|
|
5876
|
-
while (object !== void 0 &&
|
|
5642
|
+
while (object !== void 0 && MEMBER_TYPES4.has(object.type)) {
|
|
5877
5643
|
object = object.object;
|
|
5878
5644
|
}
|
|
5879
5645
|
if (object?.type !== "Identifier" || !RUNNERS.has(object.name)) return void 0;
|
|
@@ -5900,13 +5666,13 @@ function rewriteEachTableRows(source, program) {
|
|
|
5900
5666
|
}
|
|
5901
5667
|
|
|
5902
5668
|
// src/roles/test/codemod/each-title.ts
|
|
5903
|
-
var
|
|
5669
|
+
var MEMBER_TYPES5 = /* @__PURE__ */ new Set(["MemberExpression", "StaticMemberExpression"]);
|
|
5904
5670
|
function eachTitle(node) {
|
|
5905
5671
|
if (node.type !== "CallExpression") return void 0;
|
|
5906
5672
|
const inner = node.callee;
|
|
5907
5673
|
if (inner?.type !== "CallExpression") return void 0;
|
|
5908
5674
|
const member = inner.callee;
|
|
5909
|
-
if (member === void 0 || !
|
|
5675
|
+
if (member === void 0 || !MEMBER_TYPES5.has(member.type)) return void 0;
|
|
5910
5676
|
const property = member.property;
|
|
5911
5677
|
if (property?.type !== "Identifier" || property.name !== "each") return void 0;
|
|
5912
5678
|
const [title] = node.arguments ?? [];
|
|
@@ -5959,14 +5725,14 @@ function rewriteEachTitles(source, program) {
|
|
|
5959
5725
|
|
|
5960
5726
|
// src/roles/test/codemod/empty-mock-implementation.ts
|
|
5961
5727
|
var METHODS = /* @__PURE__ */ new Set(["mockImplementation", "mockImplementationOnce"]);
|
|
5962
|
-
var
|
|
5728
|
+
var MEMBER_TYPES6 = /* @__PURE__ */ new Set(["MemberExpression", "StaticMemberExpression"]);
|
|
5963
5729
|
function rewriteEmptyMockImplementation(source, program) {
|
|
5964
5730
|
const insertAt = [];
|
|
5965
5731
|
walk(program, (node) => {
|
|
5966
5732
|
if (node.type !== "CallExpression") return;
|
|
5967
5733
|
if ((node.arguments ?? []).length > 0) return;
|
|
5968
5734
|
const callee = node.callee;
|
|
5969
|
-
if (callee === void 0 || !
|
|
5735
|
+
if (callee === void 0 || !MEMBER_TYPES6.has(callee.type)) return;
|
|
5970
5736
|
const property = callee.property;
|
|
5971
5737
|
if (property?.type !== "Identifier" || !METHODS.has(property.name)) return;
|
|
5972
5738
|
insertAt.push(node.end - 1);
|
|
@@ -5979,12 +5745,12 @@ function rewriteEmptyMockImplementation(source, program) {
|
|
|
5979
5745
|
}
|
|
5980
5746
|
|
|
5981
5747
|
// src/roles/test/codemod/fake-timer-options.ts
|
|
5982
|
-
var
|
|
5748
|
+
var MEMBER_TYPES7 = /* @__PURE__ */ new Set(["MemberExpression", "StaticMemberExpression"]);
|
|
5983
5749
|
var TIMER_CALLS = /* @__PURE__ */ new Set(["useFakeTimers"]);
|
|
5984
5750
|
function timerOptions(node) {
|
|
5985
5751
|
if (node.type !== "CallExpression") return void 0;
|
|
5986
5752
|
const callee = node.callee;
|
|
5987
|
-
if (callee === void 0 || !
|
|
5753
|
+
if (callee === void 0 || !MEMBER_TYPES7.has(callee.type)) return void 0;
|
|
5988
5754
|
const object = callee.object;
|
|
5989
5755
|
const property = callee.property;
|
|
5990
5756
|
if (object?.type !== "Identifier") return void 0;
|
|
@@ -6328,7 +6094,7 @@ function hoistCapturedBindings(source, program, factories, bindings, imported) {
|
|
|
6328
6094
|
|
|
6329
6095
|
// src/roles/test/codemod/hook-return-value.ts
|
|
6330
6096
|
var HOOKS = /* @__PURE__ */ new Set(["beforeEach", "afterEach", "beforeAll", "afterAll"]);
|
|
6331
|
-
var
|
|
6097
|
+
var MEMBER_TYPES8 = /* @__PURE__ */ new Set(["MemberExpression", "StaticMemberExpression"]);
|
|
6332
6098
|
function hookCallback(node) {
|
|
6333
6099
|
if (node.type !== "CallExpression") return void 0;
|
|
6334
6100
|
const callee = node.callee;
|
|
@@ -6339,7 +6105,7 @@ function hookCallback(node) {
|
|
|
6339
6105
|
function configuresAMock(body) {
|
|
6340
6106
|
if (body.type !== "CallExpression") return false;
|
|
6341
6107
|
const callee = body.callee;
|
|
6342
|
-
if (callee === void 0 || !
|
|
6108
|
+
if (callee === void 0 || !MEMBER_TYPES8.has(callee.type)) return false;
|
|
6343
6109
|
const property = callee.property;
|
|
6344
6110
|
return property?.type === "Identifier" && /^mock[A-Z]/.test(property.name);
|
|
6345
6111
|
}
|
|
@@ -6524,37 +6290,37 @@ ${source}`;
|
|
|
6524
6290
|
}
|
|
6525
6291
|
|
|
6526
6292
|
// src/roles/test/codemod/named-rules.ts
|
|
6527
|
-
import { existsSync as
|
|
6528
|
-
import { createRequire as
|
|
6529
|
-
import { dirname as
|
|
6293
|
+
import { existsSync as existsSync22, readFileSync as readFileSync21 } from "node:fs";
|
|
6294
|
+
import { createRequire as createRequire3 } from "node:module";
|
|
6295
|
+
import { dirname as dirname3, join as join26 } from "node:path";
|
|
6530
6296
|
function isCommonJsPackage(fromFile, specifier) {
|
|
6531
6297
|
if (specifier.startsWith(".") || specifier.startsWith("/")) return false;
|
|
6532
6298
|
let resolved;
|
|
6533
6299
|
try {
|
|
6534
|
-
resolved =
|
|
6300
|
+
resolved = createRequire3(fromFile).resolve(specifier);
|
|
6535
6301
|
} catch {
|
|
6536
6302
|
return false;
|
|
6537
6303
|
}
|
|
6538
6304
|
if (!resolved.includes(`${"/"}node_modules${"/"}`)) return false;
|
|
6539
6305
|
if (resolved.endsWith(".mjs")) return false;
|
|
6540
6306
|
if (resolved.endsWith(".cjs")) return true;
|
|
6541
|
-
let dir =
|
|
6307
|
+
let dir = dirname3(resolved);
|
|
6542
6308
|
for (let depth = 0; depth < 12; depth += 1) {
|
|
6543
|
-
const manifest =
|
|
6544
|
-
if (
|
|
6309
|
+
const manifest = join26(dir, "package.json");
|
|
6310
|
+
if (existsSync22(manifest)) {
|
|
6545
6311
|
try {
|
|
6546
|
-
return JSON.parse(
|
|
6312
|
+
return JSON.parse(readFileSync21(manifest, "utf8")).type !== "module";
|
|
6547
6313
|
} catch {
|
|
6548
6314
|
return false;
|
|
6549
6315
|
}
|
|
6550
6316
|
}
|
|
6551
|
-
const parent =
|
|
6317
|
+
const parent = dirname3(dir);
|
|
6552
6318
|
if (parent === dir) break;
|
|
6553
6319
|
dir = parent;
|
|
6554
6320
|
}
|
|
6555
6321
|
return false;
|
|
6556
6322
|
}
|
|
6557
|
-
var
|
|
6323
|
+
var MEMBER_TYPES9 = /* @__PURE__ */ new Set(["MemberExpression", "StaticMemberExpression"]);
|
|
6558
6324
|
var ASYNC_REPLACEMENTS = {
|
|
6559
6325
|
requireActual: "importActual",
|
|
6560
6326
|
requireMock: "importMock"
|
|
@@ -6564,7 +6330,7 @@ function mockedSpecifiers(program) {
|
|
|
6564
6330
|
walk(program, (node) => {
|
|
6565
6331
|
if (node.type !== "CallExpression") return;
|
|
6566
6332
|
const callee = node.callee;
|
|
6567
|
-
if (callee === void 0 || !
|
|
6333
|
+
if (callee === void 0 || !MEMBER_TYPES9.has(callee.type)) return;
|
|
6568
6334
|
const object = callee.object;
|
|
6569
6335
|
const property = callee.property;
|
|
6570
6336
|
if (object?.type !== "Identifier") return;
|
|
@@ -6601,7 +6367,7 @@ function bareRequire(node) {
|
|
|
6601
6367
|
function mockFactoryReturn(node) {
|
|
6602
6368
|
if (node.type !== "CallExpression") return void 0;
|
|
6603
6369
|
const callee = node.callee;
|
|
6604
|
-
if (callee === void 0 || !
|
|
6370
|
+
if (callee === void 0 || !MEMBER_TYPES9.has(callee.type)) return void 0;
|
|
6605
6371
|
const object = callee.object;
|
|
6606
6372
|
const property = callee.property;
|
|
6607
6373
|
if (object?.type !== "Identifier") return void 0;
|
|
@@ -6711,7 +6477,7 @@ function applyNamedRules(source, program, fileName = "") {
|
|
|
6711
6477
|
}
|
|
6712
6478
|
return;
|
|
6713
6479
|
}
|
|
6714
|
-
if (!
|
|
6480
|
+
if (!MEMBER_TYPES9.has(node.type)) return;
|
|
6715
6481
|
const object = node.object;
|
|
6716
6482
|
if (object !== void 0) readsANameOffIt.add(object);
|
|
6717
6483
|
});
|
|
@@ -6782,13 +6548,13 @@ function applyNamedRules(source, program, fileName = "") {
|
|
|
6782
6548
|
}
|
|
6783
6549
|
|
|
6784
6550
|
// src/roles/test/codemod/isolate-modules.ts
|
|
6785
|
-
var
|
|
6551
|
+
var MEMBER_TYPES10 = /* @__PURE__ */ new Set(["MemberExpression", "StaticMemberExpression"]);
|
|
6786
6552
|
var ISOLATORS = /* @__PURE__ */ new Set(["isolateModules", "isolateModulesAsync"]);
|
|
6787
6553
|
var FUNCTIONS2 = /* @__PURE__ */ new Set(["ArrowFunctionExpression", "FunctionExpression"]);
|
|
6788
6554
|
function isolatingCall(node) {
|
|
6789
6555
|
if (node.type !== "CallExpression") return void 0;
|
|
6790
6556
|
const callee = node.callee;
|
|
6791
|
-
if (callee === void 0 || !
|
|
6557
|
+
if (callee === void 0 || !MEMBER_TYPES10.has(callee.type)) return void 0;
|
|
6792
6558
|
const object = callee.object;
|
|
6793
6559
|
const property = callee.property;
|
|
6794
6560
|
if (object?.type !== "Identifier" || object.name !== "jest") return void 0;
|
|
@@ -6799,7 +6565,7 @@ function isolatingCall(node) {
|
|
|
6799
6565
|
function unusableIsolatingCall(node) {
|
|
6800
6566
|
if (node.type !== "CallExpression") return void 0;
|
|
6801
6567
|
const callee = node.callee;
|
|
6802
|
-
if (callee === void 0 || !
|
|
6568
|
+
if (callee === void 0 || !MEMBER_TYPES10.has(callee.type)) return void 0;
|
|
6803
6569
|
const object = callee.object;
|
|
6804
6570
|
const property = callee.property;
|
|
6805
6571
|
if (object?.type !== "Identifier" || object.name !== "jest") return void 0;
|
|
@@ -6850,11 +6616,11 @@ ${indent}await (${callback})()`
|
|
|
6850
6616
|
}
|
|
6851
6617
|
|
|
6852
6618
|
// src/roles/test/codemod/mock-as-value.ts
|
|
6853
|
-
var
|
|
6619
|
+
var MEMBER_TYPES11 = /* @__PURE__ */ new Set(["MemberExpression", "StaticMemberExpression"]);
|
|
6854
6620
|
function isViMockCall(node) {
|
|
6855
6621
|
if (node?.type !== "CallExpression") return false;
|
|
6856
6622
|
const callee = node.callee;
|
|
6857
|
-
if (callee === void 0 || !
|
|
6623
|
+
if (callee === void 0 || !MEMBER_TYPES11.has(callee.type)) return false;
|
|
6858
6624
|
const object = callee.object;
|
|
6859
6625
|
const property = callee.property;
|
|
6860
6626
|
return object?.type === "Identifier" && object.name === "vi" && property?.type === "Identifier" && (property.name === "mock" || property.name === "doMock");
|
|
@@ -6879,7 +6645,7 @@ function rewriteMockAsValue(source, program) {
|
|
|
6879
6645
|
const memberUses = /* @__PURE__ */ new Map();
|
|
6880
6646
|
const otherUses = /* @__PURE__ */ new Map();
|
|
6881
6647
|
walk(program, (node) => {
|
|
6882
|
-
if (
|
|
6648
|
+
if (MEMBER_TYPES11.has(node.type)) {
|
|
6883
6649
|
const object = node.object;
|
|
6884
6650
|
if (object?.type === "Identifier" && bindings.has(object.name)) {
|
|
6885
6651
|
const list = memberUses.get(object.name) ?? [];
|
|
@@ -6925,12 +6691,12 @@ function rewriteMockAsValue(source, program) {
|
|
|
6925
6691
|
}
|
|
6926
6692
|
|
|
6927
6693
|
// src/roles/test/codemod/mock-factory-default.ts
|
|
6928
|
-
var
|
|
6694
|
+
var MEMBER_TYPES12 = /* @__PURE__ */ new Set(["MemberExpression", "StaticMemberExpression"]);
|
|
6929
6695
|
var BINDING = "sentinelMockedModule";
|
|
6930
6696
|
function mockCall(node) {
|
|
6931
6697
|
if (node.type !== "CallExpression") return void 0;
|
|
6932
6698
|
const callee = node.callee;
|
|
6933
|
-
if (callee === void 0 || !
|
|
6699
|
+
if (callee === void 0 || !MEMBER_TYPES12.has(callee.type)) return void 0;
|
|
6934
6700
|
const property = callee.property;
|
|
6935
6701
|
if (property?.type !== "Identifier" || property.name !== "mock") return void 0;
|
|
6936
6702
|
const object = callee.object;
|
|
@@ -7043,7 +6809,7 @@ function rewriteMockFactoryDefault(source, program, defaultImported) {
|
|
|
7043
6809
|
|
|
7044
6810
|
// src/roles/test/codemod/mock-promise-resolve.ts
|
|
7045
6811
|
var MOCK_FACTORY = /* @__PURE__ */ new Set(["fn", "spyOn"]);
|
|
7046
|
-
function
|
|
6812
|
+
function isMockFactory2(source, node) {
|
|
7047
6813
|
if (node.type !== "CallExpression") return false;
|
|
7048
6814
|
const callee = node.callee;
|
|
7049
6815
|
if (callee?.type !== "MemberExpression") return false;
|
|
@@ -7086,7 +6852,7 @@ function resolvedValue(source, executor) {
|
|
|
7086
6852
|
function rewriteMockPromiseResolve(source, program) {
|
|
7087
6853
|
const edits = [];
|
|
7088
6854
|
walk(program, (node) => {
|
|
7089
|
-
if (!
|
|
6855
|
+
if (!isMockFactory2(source, node)) return;
|
|
7090
6856
|
for (const argument of node.arguments ?? []) {
|
|
7091
6857
|
walk(argument, (inner) => {
|
|
7092
6858
|
if (inner.type !== "NewExpression") return;
|
|
@@ -7114,11 +6880,11 @@ function rewriteMockPromiseResolve(source, program) {
|
|
|
7114
6880
|
}
|
|
7115
6881
|
|
|
7116
6882
|
// src/roles/test/codemod/mocked-module-binding.ts
|
|
7117
|
-
var
|
|
6883
|
+
var MEMBER_TYPES13 = /* @__PURE__ */ new Set(["MemberExpression", "StaticMemberExpression"]);
|
|
7118
6884
|
function mockedSpecifier(source, node) {
|
|
7119
6885
|
if (node.type !== "CallExpression") return void 0;
|
|
7120
6886
|
const callee = node.callee;
|
|
7121
|
-
if (callee === void 0 || !
|
|
6887
|
+
if (callee === void 0 || !MEMBER_TYPES13.has(callee.type)) return void 0;
|
|
7122
6888
|
const object = callee.object;
|
|
7123
6889
|
const property = callee.property;
|
|
7124
6890
|
if (object?.type !== "Identifier") return void 0;
|
|
@@ -7176,7 +6942,7 @@ function annotateMockedBindings(source, program) {
|
|
|
7176
6942
|
// src/roles/test/codemod/propagate-await.ts
|
|
7177
6943
|
import { parseSync as parseSync5 } from "oxc-parser";
|
|
7178
6944
|
var FUNCTIONS3 = /* @__PURE__ */ new Set(["ArrowFunctionExpression", "FunctionExpression", "FunctionDeclaration"]);
|
|
7179
|
-
var
|
|
6945
|
+
var MEMBER_TYPES14 = /* @__PURE__ */ new Set(["MemberExpression", "StaticMemberExpression"]);
|
|
7180
6946
|
var ALREADY_A_PROMISE = /* @__PURE__ */ new Set(["then", "catch", "finally"]);
|
|
7181
6947
|
function asyncFunctionNames(program) {
|
|
7182
6948
|
const names = /* @__PURE__ */ new Set();
|
|
@@ -7250,7 +7016,7 @@ function alreadyHandled(call, parent) {
|
|
|
7250
7016
|
if (parent === void 0) return false;
|
|
7251
7017
|
if (parent.type === "AwaitExpression") return true;
|
|
7252
7018
|
if (parent.type === "ReturnStatement" || parent.type === "ArrowFunctionExpression") return true;
|
|
7253
|
-
if (
|
|
7019
|
+
if (MEMBER_TYPES14.has(parent.type) && parent.object === call) {
|
|
7254
7020
|
const property = parent.property;
|
|
7255
7021
|
return property?.type === "Identifier" && ALREADY_A_PROMISE.has(property.name);
|
|
7256
7022
|
}
|
|
@@ -7300,10 +7066,10 @@ function propagateAwait(fileName, source, original, elsewhere = /* @__PURE__ */
|
|
|
7300
7066
|
}
|
|
7301
7067
|
|
|
7302
7068
|
// src/roles/test/codemod/reexport-barrel-mock.ts
|
|
7303
|
-
import { readFileSync as
|
|
7304
|
-
import { createRequire as
|
|
7305
|
-
import { dirname as
|
|
7306
|
-
var
|
|
7069
|
+
import { readFileSync as readFileSync22, readdirSync as readdirSync3, statSync as statSync4 } from "node:fs";
|
|
7070
|
+
import { createRequire as createRequire4 } from "node:module";
|
|
7071
|
+
import { dirname as dirname4, join as join27 } from "node:path";
|
|
7072
|
+
var MEMBER_TYPES15 = /* @__PURE__ */ new Set(["MemberExpression", "StaticMemberExpression"]);
|
|
7307
7073
|
var PACKAGE_SUBPATH = /^(@[^/]+\/[^/]+|[^@.][^/]*)\/(.+)$/;
|
|
7308
7074
|
var PURE_REEXPORT = /^module\.exports\s*=\s*require\(\s*(['"])([^'"]+)\1\s*\)\s*;?$/;
|
|
7309
7075
|
function mockCalls(program) {
|
|
@@ -7311,7 +7077,7 @@ function mockCalls(program) {
|
|
|
7311
7077
|
walk(program, (node) => {
|
|
7312
7078
|
if (node.type !== "CallExpression") return;
|
|
7313
7079
|
const callee = node.callee;
|
|
7314
|
-
if (callee === void 0 || !
|
|
7080
|
+
if (callee === void 0 || !MEMBER_TYPES15.has(callee.type)) return;
|
|
7315
7081
|
const object = callee.object;
|
|
7316
7082
|
const property = callee.property;
|
|
7317
7083
|
if (object?.type !== "Identifier") return;
|
|
@@ -7331,14 +7097,14 @@ function mockCalls(program) {
|
|
|
7331
7097
|
}
|
|
7332
7098
|
function packageRoot(fromFile, name) {
|
|
7333
7099
|
try {
|
|
7334
|
-
return
|
|
7100
|
+
return dirname4(createRequire4(fromFile).resolve(`${name}/package.json`));
|
|
7335
7101
|
} catch {
|
|
7336
7102
|
return void 0;
|
|
7337
7103
|
}
|
|
7338
7104
|
}
|
|
7339
7105
|
function resolveFrom(fromFile, specifier) {
|
|
7340
7106
|
try {
|
|
7341
|
-
return
|
|
7107
|
+
return createRequire4(fromFile).resolve(specifier);
|
|
7342
7108
|
} catch {
|
|
7343
7109
|
return void 0;
|
|
7344
7110
|
}
|
|
@@ -7348,18 +7114,18 @@ function barrelsFor(fromFile, name, target) {
|
|
|
7348
7114
|
if (root === void 0) return [];
|
|
7349
7115
|
let entries;
|
|
7350
7116
|
try {
|
|
7351
|
-
entries =
|
|
7117
|
+
entries = readdirSync3(root);
|
|
7352
7118
|
} catch {
|
|
7353
7119
|
return [];
|
|
7354
7120
|
}
|
|
7355
7121
|
const aliases = [];
|
|
7356
7122
|
for (const entry of entries) {
|
|
7357
7123
|
if (!entry.endsWith(".js")) continue;
|
|
7358
|
-
const path =
|
|
7124
|
+
const path = join27(root, entry);
|
|
7359
7125
|
let body;
|
|
7360
7126
|
try {
|
|
7361
7127
|
if (!statSync4(path).isFile()) continue;
|
|
7362
|
-
body =
|
|
7128
|
+
body = readFileSync22(path, "utf8");
|
|
7363
7129
|
} catch {
|
|
7364
7130
|
continue;
|
|
7365
7131
|
}
|
|
@@ -7438,17 +7204,17 @@ function repointMswServer(fileName, source) {
|
|
|
7438
7204
|
}
|
|
7439
7205
|
|
|
7440
7206
|
// src/roles/test/codemod/setup-static-imports.ts
|
|
7441
|
-
import { dirname as
|
|
7207
|
+
import { dirname as dirname6, resolve as resolve6 } from "node:path";
|
|
7442
7208
|
|
|
7443
7209
|
// src/core/context.ts
|
|
7444
|
-
import { existsSync as
|
|
7445
|
-
import { dirname as
|
|
7210
|
+
import { existsSync as existsSync23 } from "node:fs";
|
|
7211
|
+
import { dirname as dirname5, join as join29, resolve as resolve4 } from "node:path";
|
|
7446
7212
|
|
|
7447
7213
|
// src/core/discover-modules.ts
|
|
7448
7214
|
import { execFileSync } from "node:child_process";
|
|
7449
|
-
import { mkdtempSync, readFileSync as
|
|
7215
|
+
import { mkdtempSync, readFileSync as readFileSync23, rmSync as rmSync3 } from "node:fs";
|
|
7450
7216
|
import { tmpdir } from "node:os";
|
|
7451
|
-
import { join as
|
|
7217
|
+
import { join as join28 } from "node:path";
|
|
7452
7218
|
function runNx(cwd, args) {
|
|
7453
7219
|
const nx = resolveBin(cwd, "nx") ?? "nx";
|
|
7454
7220
|
try {
|
|
@@ -7466,11 +7232,11 @@ function runNx(cwd, args) {
|
|
|
7466
7232
|
}
|
|
7467
7233
|
}
|
|
7468
7234
|
function readGraph(cwd) {
|
|
7469
|
-
const dir = mkdtempSync(
|
|
7470
|
-
const file =
|
|
7235
|
+
const dir = mkdtempSync(join28(tmpdir(), "sentinel-nx-"));
|
|
7236
|
+
const file = join28(dir, "graph.json");
|
|
7471
7237
|
try {
|
|
7472
7238
|
runNx(cwd, ["graph", "--file", file]);
|
|
7473
|
-
const parsed = JSON.parse(
|
|
7239
|
+
const parsed = JSON.parse(readFileSync23(file, "utf8"));
|
|
7474
7240
|
const nodes = parsed.graph?.nodes;
|
|
7475
7241
|
if (!nodes || typeof nodes !== "object") {
|
|
7476
7242
|
throw new Error(
|
|
@@ -7479,7 +7245,7 @@ function readGraph(cwd) {
|
|
|
7479
7245
|
}
|
|
7480
7246
|
return Object.entries(nodes).map(([name, node]) => ({
|
|
7481
7247
|
name,
|
|
7482
|
-
root:
|
|
7248
|
+
root: join28(cwd, node.data.root)
|
|
7483
7249
|
}));
|
|
7484
7250
|
} finally {
|
|
7485
7251
|
rmSync3(dir, { recursive: true, force: true });
|
|
@@ -7497,20 +7263,20 @@ function discoverModules(cwd, options = {}) {
|
|
|
7497
7263
|
// src/core/context.ts
|
|
7498
7264
|
var MODULE_MARKERS = ["package.json", "project.json"];
|
|
7499
7265
|
function isModuleDir(cwd) {
|
|
7500
|
-
return MODULE_MARKERS.some((marker) =>
|
|
7266
|
+
return MODULE_MARKERS.some((marker) => existsSync23(join29(cwd, marker)));
|
|
7501
7267
|
}
|
|
7502
7268
|
function findModuleRoot(startDir, workspaceRoot) {
|
|
7503
7269
|
let dir = resolve4(startDir);
|
|
7504
7270
|
for (; ; ) {
|
|
7505
7271
|
if (workspaceRoot !== void 0 && dir === resolve4(workspaceRoot)) return void 0;
|
|
7506
7272
|
if (isModuleDir(dir)) return dir;
|
|
7507
|
-
const parent =
|
|
7273
|
+
const parent = dirname5(dir);
|
|
7508
7274
|
if (parent === dir) return void 0;
|
|
7509
7275
|
dir = parent;
|
|
7510
7276
|
}
|
|
7511
7277
|
}
|
|
7512
7278
|
function resolveContext(cwd, opts) {
|
|
7513
|
-
const atRoot =
|
|
7279
|
+
const atRoot = existsSync23(join29(cwd, WORKSPACE_ROOT_MARKER));
|
|
7514
7280
|
if (!atRoot && isModuleDir(cwd)) {
|
|
7515
7281
|
if (opts.module) {
|
|
7516
7282
|
throw new Error(
|
|
@@ -7538,16 +7304,16 @@ function resolveContext(cwd, opts) {
|
|
|
7538
7304
|
}
|
|
7539
7305
|
|
|
7540
7306
|
// src/roles/test/codemod/workspace-specifier.ts
|
|
7541
|
-
import { existsSync as
|
|
7542
|
-
import { join as
|
|
7307
|
+
import { existsSync as existsSync24, readFileSync as readFileSync24 } from "node:fs";
|
|
7308
|
+
import { join as join30, relative as relative4, resolve as resolve5 } from "node:path";
|
|
7543
7309
|
var EXTENSIONS = ["", ".ts", ".tsx", ".js", ".jsx", ".mts", ".cts", "/index.ts", "/index.js"];
|
|
7544
7310
|
function pathEntries(workspaceRoot) {
|
|
7545
|
-
const file =
|
|
7546
|
-
if (!
|
|
7311
|
+
const file = join30(workspaceRoot, "tsconfig.base.json");
|
|
7312
|
+
if (!existsSync24(file)) return [];
|
|
7547
7313
|
let paths;
|
|
7548
7314
|
try {
|
|
7549
7315
|
paths = parseJsonc(
|
|
7550
|
-
|
|
7316
|
+
readFileSync24(file, "utf8"),
|
|
7551
7317
|
"tsconfig.base.json"
|
|
7552
7318
|
)?.compilerOptions?.paths;
|
|
7553
7319
|
} catch {
|
|
@@ -7575,7 +7341,7 @@ function workspaceSpecifier(workspaceRoot, file) {
|
|
|
7575
7341
|
}
|
|
7576
7342
|
continue;
|
|
7577
7343
|
}
|
|
7578
|
-
const rest =
|
|
7344
|
+
const rest = relative4(entry.target, absolute);
|
|
7579
7345
|
if (rest === "" || rest.startsWith("..") || rest.startsWith("/")) continue;
|
|
7580
7346
|
const named = rest.replace(/\\/g, "/").replace(/\.(m|c)?(j|t)sx?$/, "");
|
|
7581
7347
|
return `${entry.key}/${named}`;
|
|
@@ -7596,7 +7362,7 @@ function requireCall(source, node) {
|
|
|
7596
7362
|
}
|
|
7597
7363
|
function importable(written, fileName, workspaceRoot) {
|
|
7598
7364
|
if (!written.startsWith(".")) return written;
|
|
7599
|
-
const fileDir =
|
|
7365
|
+
const fileDir = dirname6(fileName);
|
|
7600
7366
|
const moduleRoot = findModuleRoot(fileDir, workspaceRoot) ?? fileDir;
|
|
7601
7367
|
const target = resolve6(fileDir, written);
|
|
7602
7368
|
if (target.startsWith(`${moduleRoot}/`)) return written;
|
|
@@ -7742,7 +7508,7 @@ function migrateTestFile(fileName, source, defaultImported = /* @__PURE__ */ new
|
|
|
7742
7508
|
fileName,
|
|
7743
7509
|
source,
|
|
7744
7510
|
beforeStatic,
|
|
7745
|
-
findWorkspaceRoot(
|
|
7511
|
+
findWorkspaceRoot(dirname7(fileName))
|
|
7746
7512
|
);
|
|
7747
7513
|
source = statics.source;
|
|
7748
7514
|
const original = statics.rewritten === 0 ? beforeStatic : parse2(fileName, source);
|
|
@@ -7804,7 +7570,10 @@ function migrateTestFile(fileName, source, defaultImported = /* @__PURE__ */ new
|
|
|
7804
7570
|
const afterHoist = parse2(fileName, hoist.source);
|
|
7805
7571
|
if (afterHoist === void 0) return unparsable("hoisting captured bindings");
|
|
7806
7572
|
const mockedBindings = annotateMockedBindings(hoist.source, afterHoist);
|
|
7807
|
-
const
|
|
7573
|
+
const afterBindings = parse2(fileName, mockedBindings.source);
|
|
7574
|
+
if (afterBindings === void 0) return unparsable("mocked module bindings");
|
|
7575
|
+
const bareFactories = invokeBareMockFactories(mockedBindings.source, afterBindings);
|
|
7576
|
+
const withImport = injectTypeImport(fileName, bareFactories.source, [
|
|
7808
7577
|
...renamed.typeImports,
|
|
7809
7578
|
...spyTypes.typeImports,
|
|
7810
7579
|
...mockedBindings.typeImports
|
|
@@ -7831,6 +7600,7 @@ function migrateTestFile(fileName, source, defaultImported = /* @__PURE__ */ new
|
|
|
7831
7600
|
...hooks.rewritten > 0 ? ["hook body, so it does not return its mock"] : [],
|
|
7832
7601
|
...spyTypes.rewritten > 0 ? ["SpyInstance<T> as a signature, not a return type"] : [],
|
|
7833
7602
|
...mockedBindings.rewritten > 0 ? ["a mocked module binding, typed as mocked"] : [],
|
|
7603
|
+
...bareFactories.rewritten > 0 ? ["vi.fn passed as a value, invoked"] : [],
|
|
7834
7604
|
...awaited.rewritten > 0 ? ["await propagated to a helper that became async"] : [],
|
|
7835
7605
|
...barrels.added.map((alias) => `mock carried to ${alias}, which re-exports the mocked file`),
|
|
7836
7606
|
...fakeTimers.translated
|
|
@@ -7858,10 +7628,10 @@ function migrateTestFile(fileName, source, defaultImported = /* @__PURE__ */ new
|
|
|
7858
7628
|
}
|
|
7859
7629
|
|
|
7860
7630
|
// src/roles/test/codemod/test-support-files.ts
|
|
7861
|
-
import { existsSync as
|
|
7862
|
-
import { dirname as
|
|
7631
|
+
import { existsSync as existsSync25, readFileSync as readFileSync25, readdirSync as readdirSync4, statSync as statSync5 } from "node:fs";
|
|
7632
|
+
import { dirname as dirname8, join as join31, relative as relative5, resolve as resolve7 } from "node:path";
|
|
7863
7633
|
var SKIPPED = /* @__PURE__ */ new Set(["node_modules", "dist", "coverage", ".git", ".vite"]);
|
|
7864
|
-
var
|
|
7634
|
+
var TEST_FILE = /\.(spec|test)\.[cm]?[jt]sx?$/;
|
|
7865
7635
|
var SOURCE_FILE = /\.[cm]?[jt]sx?$/;
|
|
7866
7636
|
var EXTENSIONS2 = [".ts", ".tsx", ".js", ".jsx", ".mts", ".cts"];
|
|
7867
7637
|
function relativeSpecifiers(source) {
|
|
@@ -7878,14 +7648,14 @@ function relativeSpecifiers(source) {
|
|
|
7878
7648
|
return found;
|
|
7879
7649
|
}
|
|
7880
7650
|
function resolveSpecifier(fromFile, specifier) {
|
|
7881
|
-
const base = resolve7(
|
|
7882
|
-
if (
|
|
7651
|
+
const base = resolve7(dirname8(fromFile), specifier);
|
|
7652
|
+
if (existsSync25(base) && statSync5(base).isFile()) return base;
|
|
7883
7653
|
for (const extension of EXTENSIONS2) {
|
|
7884
|
-
if (
|
|
7654
|
+
if (existsSync25(`${base}${extension}`)) return `${base}${extension}`;
|
|
7885
7655
|
}
|
|
7886
7656
|
for (const extension of EXTENSIONS2) {
|
|
7887
|
-
const index =
|
|
7888
|
-
if (
|
|
7657
|
+
const index = join31(base, `index${extension}`);
|
|
7658
|
+
if (existsSync25(index)) return index;
|
|
7889
7659
|
}
|
|
7890
7660
|
return void 0;
|
|
7891
7661
|
}
|
|
@@ -7896,15 +7666,15 @@ function moduleSources(cwd) {
|
|
|
7896
7666
|
const dir = stack.pop();
|
|
7897
7667
|
let entries;
|
|
7898
7668
|
try {
|
|
7899
|
-
entries =
|
|
7669
|
+
entries = readdirSync4(dir, { withFileTypes: true });
|
|
7900
7670
|
} catch {
|
|
7901
7671
|
continue;
|
|
7902
7672
|
}
|
|
7903
7673
|
for (const entry of entries) {
|
|
7904
7674
|
if (entry.isDirectory()) {
|
|
7905
|
-
if (!SKIPPED.has(entry.name)) stack.push(
|
|
7675
|
+
if (!SKIPPED.has(entry.name)) stack.push(join31(dir, entry.name));
|
|
7906
7676
|
} else if (SOURCE_FILE.test(entry.name)) {
|
|
7907
|
-
found.push(
|
|
7677
|
+
found.push(join31(dir, entry.name));
|
|
7908
7678
|
}
|
|
7909
7679
|
}
|
|
7910
7680
|
}
|
|
@@ -7912,7 +7682,7 @@ function moduleSources(cwd) {
|
|
|
7912
7682
|
}
|
|
7913
7683
|
function read(path) {
|
|
7914
7684
|
try {
|
|
7915
|
-
return
|
|
7685
|
+
return readFileSync25(path, "utf8");
|
|
7916
7686
|
} catch {
|
|
7917
7687
|
return void 0;
|
|
7918
7688
|
}
|
|
@@ -7922,9 +7692,9 @@ function setupFilesInside(cwd, named) {
|
|
|
7922
7692
|
for (const raw of named) {
|
|
7923
7693
|
const withoutToken = raw.replaceAll("<rootDir>/", "").replaceAll("<rootDir>", ".");
|
|
7924
7694
|
const full = resolve7(cwd, withoutToken);
|
|
7925
|
-
const inside =
|
|
7695
|
+
const inside = relative5(cwd, full);
|
|
7926
7696
|
if (inside.startsWith("..") || inside === "") continue;
|
|
7927
|
-
if (!
|
|
7697
|
+
if (!existsSync25(full)) continue;
|
|
7928
7698
|
kept.push(inside.replaceAll("\\", "/"));
|
|
7929
7699
|
}
|
|
7930
7700
|
return kept;
|
|
@@ -7945,21 +7715,21 @@ function listTestSupportFiles(cwd, setupFiles = []) {
|
|
|
7945
7715
|
}
|
|
7946
7716
|
}
|
|
7947
7717
|
const testOnly = /* @__PURE__ */ new Set();
|
|
7948
|
-
const queue = sources.filter((file) =>
|
|
7718
|
+
const queue = sources.filter((file) => TEST_FILE.test(file));
|
|
7949
7719
|
const isTestOnly = (file) => (importedBy.get(file) ?? []).every(
|
|
7950
|
-
(importer) =>
|
|
7720
|
+
(importer) => TEST_FILE.test(importer) || testOnly.has(importer)
|
|
7951
7721
|
);
|
|
7952
7722
|
while (queue.length > 0) {
|
|
7953
7723
|
const file = queue.shift();
|
|
7954
7724
|
for (const specifier of relativeSpecifiers(contents.get(file) ?? "")) {
|
|
7955
7725
|
const target = resolveSpecifier(file, specifier);
|
|
7956
|
-
if (target === void 0 ||
|
|
7726
|
+
if (target === void 0 || TEST_FILE.test(target) || testOnly.has(target)) continue;
|
|
7957
7727
|
if (!isTestOnly(target)) continue;
|
|
7958
7728
|
testOnly.add(target);
|
|
7959
7729
|
queue.push(target);
|
|
7960
7730
|
}
|
|
7961
7731
|
}
|
|
7962
|
-
const reachable = [...testOnly].filter((file) => /\brequire\s*\(/.test(contents.get(file) ?? "")).map((file) =>
|
|
7732
|
+
const reachable = [...testOnly].filter((file) => /\brequire\s*\(/.test(contents.get(file) ?? "")).map((file) => relative5(cwd, file).replaceAll("\\", "/"));
|
|
7963
7733
|
return [.../* @__PURE__ */ new Set([...reachable, ...setupFilesInside(cwd, setupFiles)])].sort();
|
|
7964
7734
|
}
|
|
7965
7735
|
|
|
@@ -7970,7 +7740,7 @@ function parse3(source) {
|
|
|
7970
7740
|
}
|
|
7971
7741
|
function read2(path) {
|
|
7972
7742
|
try {
|
|
7973
|
-
return
|
|
7743
|
+
return readFileSync26(path, "utf8");
|
|
7974
7744
|
} catch {
|
|
7975
7745
|
return void 0;
|
|
7976
7746
|
}
|
|
@@ -7982,13 +7752,13 @@ function defaultImportedSpecifiers(cwd) {
|
|
|
7982
7752
|
const walk2 = (dir) => {
|
|
7983
7753
|
let entries;
|
|
7984
7754
|
try {
|
|
7985
|
-
entries =
|
|
7755
|
+
entries = readdirSync5(dir);
|
|
7986
7756
|
} catch {
|
|
7987
7757
|
return;
|
|
7988
7758
|
}
|
|
7989
7759
|
for (const entry of entries) {
|
|
7990
7760
|
if (SKIPPED2.has(entry)) continue;
|
|
7991
|
-
const path =
|
|
7761
|
+
const path = join32(dir, entry);
|
|
7992
7762
|
let directory;
|
|
7993
7763
|
try {
|
|
7994
7764
|
directory = statSync6(path).isDirectory();
|
|
@@ -8018,22 +7788,22 @@ function migrateModuleTests(cwd, setupFiles = []) {
|
|
|
8018
7788
|
let hoisted = 0;
|
|
8019
7789
|
const defaultImported = defaultImportedSpecifiers(cwd);
|
|
8020
7790
|
const asyncHelpers = /* @__PURE__ */ new Set();
|
|
8021
|
-
for (const
|
|
8022
|
-
const source = read2(
|
|
7791
|
+
for (const relative8 of listTestSupportFiles(cwd, setupFiles)) {
|
|
7792
|
+
const source = read2(join32(cwd, relative8));
|
|
8023
7793
|
if (source === void 0) {
|
|
8024
|
-
blockers.push({ file:
|
|
7794
|
+
blockers.push({ file: relative8, reason: "this file could not be read" });
|
|
8025
7795
|
continue;
|
|
8026
7796
|
}
|
|
8027
7797
|
const migrated = migrateTestFile(
|
|
8028
|
-
|
|
7798
|
+
join32(cwd, relative8),
|
|
8029
7799
|
source,
|
|
8030
7800
|
defaultImported,
|
|
8031
7801
|
/* @__PURE__ */ new Set(),
|
|
8032
7802
|
modulesOwnMsw
|
|
8033
7803
|
);
|
|
8034
|
-
const renamedTo = vitestSupportName(
|
|
8035
|
-
if (!migrated.changed && renamedTo ===
|
|
8036
|
-
if (renamedTo !==
|
|
7804
|
+
const renamedTo = vitestSupportName(relative8);
|
|
7805
|
+
if (!migrated.changed && renamedTo === relative8) continue;
|
|
7806
|
+
if (renamedTo !== relative8) operations.push({ kind: "delete", path: relative8 });
|
|
8037
7807
|
const before = parse3(source);
|
|
8038
7808
|
const after = parse3(migrated.source);
|
|
8039
7809
|
if (before !== void 0 && after !== void 0) {
|
|
@@ -8046,14 +7816,14 @@ function migrateModuleTests(cwd, setupFiles = []) {
|
|
|
8046
7816
|
renamed += migrated.renamed;
|
|
8047
7817
|
operations.push({ kind: "write", path: renamedTo, contents: migrated.source });
|
|
8048
7818
|
}
|
|
8049
|
-
for (const
|
|
8050
|
-
const source = read2(
|
|
7819
|
+
for (const relative8 of listTestFiles(cwd)) {
|
|
7820
|
+
const source = read2(join32(cwd, relative8));
|
|
8051
7821
|
if (source === void 0) {
|
|
8052
|
-
blockers.push({ file:
|
|
7822
|
+
blockers.push({ file: relative8, reason: "this file could not be read" });
|
|
8053
7823
|
continue;
|
|
8054
7824
|
}
|
|
8055
7825
|
const migrated = migrateTestFile(
|
|
8056
|
-
|
|
7826
|
+
join32(cwd, relative8),
|
|
8057
7827
|
source,
|
|
8058
7828
|
defaultImported,
|
|
8059
7829
|
asyncHelpers,
|
|
@@ -8061,27 +7831,27 @@ function migrateModuleTests(cwd, setupFiles = []) {
|
|
|
8061
7831
|
);
|
|
8062
7832
|
for (const member of migrated.unhandled) {
|
|
8063
7833
|
blockers.push({
|
|
8064
|
-
file: `${
|
|
7834
|
+
file: `${relative8}:${member.line}`,
|
|
8065
7835
|
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}`
|
|
8066
7836
|
});
|
|
8067
7837
|
}
|
|
8068
7838
|
collected.push(...migrated.warnings);
|
|
8069
7839
|
for (const refusal of migrated.refusals) {
|
|
8070
|
-
blockers.push({ file:
|
|
7840
|
+
blockers.push({ file: relative8, reason: refusal.reason });
|
|
8071
7841
|
}
|
|
8072
7842
|
if (!migrated.changed) continue;
|
|
8073
7843
|
files++;
|
|
8074
7844
|
renamed += migrated.renamed;
|
|
8075
7845
|
if (migrated.hoisted.length > 0) hoisted++;
|
|
8076
|
-
operations.push({ kind: "write", path:
|
|
7846
|
+
operations.push({ kind: "write", path: relative8, contents: migrated.source });
|
|
8077
7847
|
}
|
|
8078
7848
|
const warnings = [...new Set(collected)];
|
|
8079
7849
|
return blockers.length > 0 ? { operations: [], files, renamed, hoisted, blockers, warnings } : { operations, files, renamed, hoisted, blockers: [], warnings };
|
|
8080
7850
|
}
|
|
8081
7851
|
|
|
8082
7852
|
// src/roles/test/nest/generate-config.ts
|
|
8083
|
-
import { readdirSync as
|
|
8084
|
-
import { join as
|
|
7853
|
+
import { readdirSync as readdirSync6, readFileSync as readFileSync27, statSync as statSync7 } from "node:fs";
|
|
7854
|
+
import { join as join33, relative as relative6 } from "node:path";
|
|
8085
7855
|
var NEST_TEST_PRESET_SPECIFIER = "@hublo/sentinel/test/nest";
|
|
8086
7856
|
var REACT_TEST_PRESET_SPECIFIER = "@hublo/sentinel/test/react";
|
|
8087
7857
|
function flavourOf(reading) {
|
|
@@ -8091,7 +7861,7 @@ var SENTINEL_TEST_SETUP = "@hublo/sentinel/test/setup/jest-parity";
|
|
|
8091
7861
|
var SENTINEL_MSW_SETUP = "@hublo/sentinel/test/setup/msw-lifecycle";
|
|
8092
7862
|
var SENTINEL_WORKSPACE_SETUP = "@hublo/sentinel/test/setup/workspace";
|
|
8093
7863
|
function hopsToRoot(cwd, workspaceRoot) {
|
|
8094
|
-
const up =
|
|
7864
|
+
const up = relative6(cwd, workspaceRoot).replaceAll("\\", "/");
|
|
8095
7865
|
return up === "" ? "." : up;
|
|
8096
7866
|
}
|
|
8097
7867
|
function inlineBlock(packages) {
|
|
@@ -8119,13 +7889,13 @@ function readModuleTraits(cwd) {
|
|
|
8119
7889
|
const walk2 = (dir) => {
|
|
8120
7890
|
let entries;
|
|
8121
7891
|
try {
|
|
8122
|
-
entries =
|
|
7892
|
+
entries = readdirSync6(dir);
|
|
8123
7893
|
} catch {
|
|
8124
7894
|
return;
|
|
8125
7895
|
}
|
|
8126
7896
|
for (const entry of entries) {
|
|
8127
7897
|
if (SKIPPED3.has(entry)) continue;
|
|
8128
|
-
const path =
|
|
7898
|
+
const path = join33(dir, entry);
|
|
8129
7899
|
let directory;
|
|
8130
7900
|
try {
|
|
8131
7901
|
directory = statSync7(path).isDirectory();
|
|
@@ -8139,7 +7909,7 @@ function readModuleTraits(cwd) {
|
|
|
8139
7909
|
if (!/\.tsx?$/.test(entry)) continue;
|
|
8140
7910
|
let source;
|
|
8141
7911
|
try {
|
|
8142
|
-
source =
|
|
7912
|
+
source = readFileSync27(path, "utf8");
|
|
8143
7913
|
} catch {
|
|
8144
7914
|
continue;
|
|
8145
7915
|
}
|
|
@@ -8270,8 +8040,8 @@ ${overrides.join("\n")}
|
|
|
8270
8040
|
}
|
|
8271
8041
|
|
|
8272
8042
|
// src/roles/test/nest/read-jest-config.ts
|
|
8273
|
-
import { existsSync as
|
|
8274
|
-
import { join as
|
|
8043
|
+
import { existsSync as existsSync26, readFileSync as readFileSync28 } from "node:fs";
|
|
8044
|
+
import { join as join34 } from "node:path";
|
|
8275
8045
|
var CARRIED = [
|
|
8276
8046
|
"testEnvironment",
|
|
8277
8047
|
"coverageDirectory",
|
|
@@ -8461,7 +8231,7 @@ function extendedConfig(source, cwd) {
|
|
|
8461
8231
|
(name) => name.replace(/^\.\//, "")
|
|
8462
8232
|
);
|
|
8463
8233
|
const file = candidates.find(
|
|
8464
|
-
(name) => /^jest[\w.-]*\.(ts|js)$/.test(name) &&
|
|
8234
|
+
(name) => /^jest[\w.-]*\.(ts|js)$/.test(name) && existsSync26(join34(cwd, name))
|
|
8465
8235
|
);
|
|
8466
8236
|
if (file === void 0) continue;
|
|
8467
8237
|
if (!new RegExp(String.raw`\{\s*\.\.\.${binding}\b`).test(source)) continue;
|
|
@@ -8488,11 +8258,11 @@ function sideEffects(source, extended) {
|
|
|
8488
8258
|
return found;
|
|
8489
8259
|
}
|
|
8490
8260
|
function readJestConfig(cwd, named) {
|
|
8491
|
-
const file = named ?? JEST_CONFIG_FILES.find((name) =>
|
|
8492
|
-
if (file === void 0 || !
|
|
8261
|
+
const file = named ?? JEST_CONFIG_FILES.find((name) => existsSync26(join34(cwd, name)));
|
|
8262
|
+
if (file === void 0 || !existsSync26(join34(cwd, file))) return void 0;
|
|
8493
8263
|
let source;
|
|
8494
8264
|
try {
|
|
8495
|
-
source =
|
|
8265
|
+
source = readFileSync28(join34(cwd, file), "utf8");
|
|
8496
8266
|
} catch {
|
|
8497
8267
|
return { file, refusals: [`${file} could not be read`], notes: [] };
|
|
8498
8268
|
}
|
|
@@ -8573,13 +8343,13 @@ function readJestConfig(cwd, named) {
|
|
|
8573
8343
|
}
|
|
8574
8344
|
|
|
8575
8345
|
// src/roles/test/nest/run-modes.ts
|
|
8576
|
-
import { existsSync as
|
|
8577
|
-
import { basename
|
|
8346
|
+
import { existsSync as existsSync27 } from "node:fs";
|
|
8347
|
+
import { basename, join as join35 } from "node:path";
|
|
8578
8348
|
var JEST_EXECUTOR = "@nx/jest:jest";
|
|
8579
8349
|
var PRIMARY_CONFIG_FILE = "vitest.config.mts";
|
|
8580
8350
|
var PRIMARY_TARGET = "test";
|
|
8581
8351
|
function configName(declared) {
|
|
8582
|
-
return
|
|
8352
|
+
return basename(declared.replaceAll("\\", "/"));
|
|
8583
8353
|
}
|
|
8584
8354
|
function configFileFor(target) {
|
|
8585
8355
|
if (target === PRIMARY_TARGET) return PRIMARY_CONFIG_FILE;
|
|
@@ -8595,7 +8365,7 @@ function runModes(cwd, fallback) {
|
|
|
8595
8365
|
const jestConfig = entry.options?.jestConfig;
|
|
8596
8366
|
if (jestConfig === void 0) continue;
|
|
8597
8367
|
const name = configName(jestConfig);
|
|
8598
|
-
if (!
|
|
8368
|
+
if (!existsSync27(join35(cwd, name))) continue;
|
|
8599
8369
|
declared.push({
|
|
8600
8370
|
target,
|
|
8601
8371
|
jestConfig: name,
|
|
@@ -8620,8 +8390,8 @@ function runModes(cwd, fallback) {
|
|
|
8620
8390
|
}
|
|
8621
8391
|
|
|
8622
8392
|
// src/roles/test/written-file-formatter.ts
|
|
8623
|
-
import { existsSync as
|
|
8624
|
-
import { dirname as
|
|
8393
|
+
import { existsSync as existsSync28 } from "node:fs";
|
|
8394
|
+
import { dirname as dirname9, join as join36 } from "node:path";
|
|
8625
8395
|
var PRETTIER_CONFIGS = [
|
|
8626
8396
|
".prettierrc",
|
|
8627
8397
|
".prettierrc.json",
|
|
@@ -8640,9 +8410,9 @@ function prettierConfigFrom(cwd) {
|
|
|
8640
8410
|
let dir = cwd;
|
|
8641
8411
|
for (; ; ) {
|
|
8642
8412
|
for (const name of PRETTIER_CONFIGS) {
|
|
8643
|
-
if (
|
|
8413
|
+
if (existsSync28(join36(dir, name))) return join36(dir, name);
|
|
8644
8414
|
}
|
|
8645
|
-
const parent =
|
|
8415
|
+
const parent = dirname9(dir);
|
|
8646
8416
|
if (parent === dir) return void 0;
|
|
8647
8417
|
dir = parent;
|
|
8648
8418
|
}
|
|
@@ -8670,12 +8440,12 @@ function writtenFileFormatter(cwd) {
|
|
|
8670
8440
|
var SPEC_TSCONFIG = "tsconfig.spec.json";
|
|
8671
8441
|
var VITEST_GLOBAL_TYPES = "vitest/globals";
|
|
8672
8442
|
function specTypesOperation(cwd) {
|
|
8673
|
-
const path =
|
|
8674
|
-
if (!
|
|
8443
|
+
const path = join37(cwd, SPEC_TSCONFIG);
|
|
8444
|
+
if (!existsSync29(path)) return void 0;
|
|
8675
8445
|
let config;
|
|
8676
8446
|
try {
|
|
8677
8447
|
config = parseJsonc(
|
|
8678
|
-
|
|
8448
|
+
readFileSync29(path, "utf8"),
|
|
8679
8449
|
SPEC_TSCONFIG
|
|
8680
8450
|
);
|
|
8681
8451
|
} catch {
|
|
@@ -8695,10 +8465,10 @@ function specTypesOperation(cwd) {
|
|
|
8695
8465
|
}
|
|
8696
8466
|
function shippedTypesPath(cwd, declaration) {
|
|
8697
8467
|
try {
|
|
8698
|
-
const manifest =
|
|
8699
|
-
const file =
|
|
8700
|
-
if (
|
|
8701
|
-
const path =
|
|
8468
|
+
const manifest = createRequire5(join37(cwd, "noop.cjs")).resolve("@hublo/sentinel/package.json");
|
|
8469
|
+
const file = join37(dirname10(manifest), declaration);
|
|
8470
|
+
if (existsSync29(file)) {
|
|
8471
|
+
const path = relative7(cwd, file);
|
|
8702
8472
|
return path.startsWith(".") ? path : `./${path}`;
|
|
8703
8473
|
}
|
|
8704
8474
|
} catch {
|
|
@@ -8709,7 +8479,7 @@ function tsconfigFileListOperations(cwd) {
|
|
|
8709
8479
|
const operations = [];
|
|
8710
8480
|
let names;
|
|
8711
8481
|
try {
|
|
8712
|
-
names =
|
|
8482
|
+
names = readdirSync7(cwd).filter((name) => TSCONFIG_FILE.test(name));
|
|
8713
8483
|
} catch {
|
|
8714
8484
|
return operations;
|
|
8715
8485
|
}
|
|
@@ -8717,7 +8487,7 @@ function tsconfigFileListOperations(cwd) {
|
|
|
8717
8487
|
let config;
|
|
8718
8488
|
try {
|
|
8719
8489
|
config = parseJsonc(
|
|
8720
|
-
|
|
8490
|
+
readFileSync29(join37(cwd, name), "utf8"),
|
|
8721
8491
|
name
|
|
8722
8492
|
);
|
|
8723
8493
|
} catch {
|
|
@@ -9007,117 +8777,7 @@ function plan3(context) {
|
|
|
9007
8777
|
return { operations, notes };
|
|
9008
8778
|
}
|
|
9009
8779
|
|
|
9010
|
-
// src/roles/test/reference.ts
|
|
9011
|
-
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
9012
|
-
import { createHash } from "node:crypto";
|
|
9013
|
-
import { existsSync as existsSync33, mkdirSync, mkdtempSync as mkdtempSync2, readFileSync as readFileSync32, rmSync as rmSync4, writeFileSync as writeFileSync3 } from "node:fs";
|
|
9014
|
-
import { tmpdir as tmpdir2 } from "node:os";
|
|
9015
|
-
import { join as join41, resolve as resolve8 } from "node:path";
|
|
9016
|
-
|
|
9017
|
-
// src/roles/test/baseline.ts
|
|
9018
|
-
function readSnapshot(report) {
|
|
9019
|
-
const files = report?.testResults ?? [];
|
|
9020
|
-
const passing = [];
|
|
9021
|
-
const failing = [];
|
|
9022
|
-
const unloadable = [];
|
|
9023
|
-
for (const file of files) {
|
|
9024
|
-
const assertions = file?.assertionResults ?? [];
|
|
9025
|
-
if (file?.status === "failed" && assertions.length === 0) {
|
|
9026
|
-
unloadable.push(typeof file.name === "string" ? file.name : "an unnamed file");
|
|
9027
|
-
}
|
|
9028
|
-
for (const assertion of assertions) {
|
|
9029
|
-
const name = assertion?.fullName;
|
|
9030
|
-
if (typeof name !== "string" || name === "") continue;
|
|
9031
|
-
if (assertion.status === "passed") passing.push(name);
|
|
9032
|
-
else if (assertion.status === "failed") failing.push(name);
|
|
9033
|
-
}
|
|
9034
|
-
}
|
|
9035
|
-
const claimed = report?.numFailedTests;
|
|
9036
|
-
return {
|
|
9037
|
-
files: files.length,
|
|
9038
|
-
passing: passing.sort(),
|
|
9039
|
-
failing: failing.sort(),
|
|
9040
|
-
unloadable: unloadable.sort(),
|
|
9041
|
-
claimedFailing: typeof claimed === "number" ? claimed : failing.length
|
|
9042
|
-
};
|
|
9043
|
-
}
|
|
9044
|
-
function unusableAsBaseline(snapshot) {
|
|
9045
|
-
if (snapshot.unloadable.length > 0) {
|
|
9046
|
-
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`;
|
|
9047
|
-
}
|
|
9048
|
-
if (snapshot.claimedFailing > snapshot.failing.length) {
|
|
9049
|
-
return `the reference run says ${snapshot.claimedFailing} test(s) failed and names only ${snapshot.failing.length} of them, so the comparison has nothing to pair the rest against and would report them as invented by the migration`;
|
|
9050
|
-
}
|
|
9051
|
-
if (snapshot.passing.length === 0) {
|
|
9052
|
-
return `the reference run reports no passing test at all, so a green run after would prove nothing: there is no claim to preserve`;
|
|
9053
|
-
}
|
|
9054
|
-
return void 0;
|
|
9055
|
-
}
|
|
9056
|
-
|
|
9057
|
-
// src/roles/test/reference.ts
|
|
9058
|
-
function referencePath(cwd) {
|
|
9059
|
-
const key = createHash("sha256").update(resolve8(cwd)).digest("hex").slice(0, 16);
|
|
9060
|
-
return join41(tmpdir2(), "sentinel-test-reference", `${key}.json`);
|
|
9061
|
-
}
|
|
9062
|
-
function runJest(cwd, config) {
|
|
9063
|
-
const bin = resolveBin(cwd, "jest");
|
|
9064
|
-
if (bin === void 0) return void 0;
|
|
9065
|
-
const root = findWorkspaceRoot(cwd) ?? cwd;
|
|
9066
|
-
const out = join41(mkdtempSync2(join41(tmpdir2(), "sentinel-reference-")), "jest.json");
|
|
9067
|
-
try {
|
|
9068
|
-
execFileSync2(bin, ["-c", join41(cwd, config), "--json", `--outputFile=${out}`, "--silent"], {
|
|
9069
|
-
cwd: root,
|
|
9070
|
-
stdio: ["ignore", "ignore", "ignore"],
|
|
9071
|
-
maxBuffer: 1 << 28
|
|
9072
|
-
});
|
|
9073
|
-
} catch {
|
|
9074
|
-
}
|
|
9075
|
-
if (!existsSync33(out)) return void 0;
|
|
9076
|
-
try {
|
|
9077
|
-
return JSON.parse(readFileSync32(out, "utf8"));
|
|
9078
|
-
} catch {
|
|
9079
|
-
return void 0;
|
|
9080
|
-
}
|
|
9081
|
-
}
|
|
9082
|
-
function captureReference(cwd, config) {
|
|
9083
|
-
const report = runJest(cwd, config);
|
|
9084
|
-
if (report === void 0) {
|
|
9085
|
-
return {
|
|
9086
|
-
captured: false,
|
|
9087
|
-
message: `could not run jest to record a reference, so this migration cannot be PROVED. It is still applied: a module whose jest run is broken can move, it just cannot be compared.`
|
|
9088
|
-
};
|
|
9089
|
-
}
|
|
9090
|
-
const snapshot = readSnapshot(report);
|
|
9091
|
-
const unusable = unusableAsBaseline(snapshot);
|
|
9092
|
-
if (unusable !== void 0) {
|
|
9093
|
-
return {
|
|
9094
|
-
captured: false,
|
|
9095
|
-
message: `no reference recorded: ${unusable} The migration is applied anyway, unproved.`
|
|
9096
|
-
};
|
|
9097
|
-
}
|
|
9098
|
-
const stored = {
|
|
9099
|
-
runner: "jest",
|
|
9100
|
-
config,
|
|
9101
|
-
takenAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
9102
|
-
snapshot
|
|
9103
|
-
};
|
|
9104
|
-
const path = referencePath(cwd);
|
|
9105
|
-
mkdirSync(join41(path, ".."), { recursive: true });
|
|
9106
|
-
writeFileSync3(path, `${JSON.stringify(stored, void 0, 2)}
|
|
9107
|
-
`);
|
|
9108
|
-
return {
|
|
9109
|
-
captured: true,
|
|
9110
|
-
message: `recorded ${snapshot.passing.length} passing test name(s) from ${config} as the reference. The next \`sentinel --run --test\` compares against it.`
|
|
9111
|
-
};
|
|
9112
|
-
}
|
|
9113
|
-
|
|
9114
8780
|
// src/roles/test/adapters/vitest/vitest.adapter.ts
|
|
9115
|
-
function resolveVitest(cwd) {
|
|
9116
|
-
const fromSentinel = binFromOwnInstall("vitest", "vitest");
|
|
9117
|
-
if (fromSentinel !== void 0) return { bin: fromSentinel, origin: "sentinel" };
|
|
9118
|
-
const fromModule = resolveBin(cwd, "vitest");
|
|
9119
|
-
return fromModule !== void 0 ? { bin: fromModule, origin: "module" } : { bin: void 0, origin: "module" };
|
|
9120
|
-
}
|
|
9121
8781
|
var FORMATTABLE = /\.(m|c)?(j|t)sx?$|\.json$/;
|
|
9122
8782
|
var FORMAT_BATCH = 25;
|
|
9123
8783
|
var VitestAdapter = class extends BaseAdapter {
|
|
@@ -9127,19 +8787,28 @@ var VitestAdapter = class extends BaseAdapter {
|
|
|
9127
8787
|
return true;
|
|
9128
8788
|
}
|
|
9129
8789
|
/**
|
|
9130
|
-
*
|
|
8790
|
+
* Say, once, that this migration is about to become unprovable if nobody recorded a reference.
|
|
8791
|
+
*
|
|
8792
|
+
* ⚠️ It used to RECORD one here, which welded a measurement to an act that does not own it.
|
|
8793
|
+
* Héla, 2026-09-25: the verification phase is isolated behind its own verb, so it extends
|
|
8794
|
+
* without destroying. Two things were wrong with recording here, and they are one thing seen
|
|
8795
|
+
* twice: a migration that could not be proved was still reported as done, because the
|
|
8796
|
+
* measurement was a side effect; and the reference was taken the way the migration found
|
|
8797
|
+
* convenient rather than the way the module runs its tests, which is how it came to record 2958
|
|
8798
|
+
* passing on a module whose own target sees 2957.
|
|
9131
8799
|
*
|
|
9132
|
-
* The plan about to be applied deletes the jest config, and
|
|
9133
|
-
*
|
|
9134
|
-
* is the whole reason this role has a baseline gate at all.
|
|
8800
|
+
* So this warns and writes nothing. The plan about to be applied deletes the jest config, and
|
|
8801
|
+
* with it any way of asking again, which is precisely why the warning is here and not later.
|
|
9135
8802
|
*/
|
|
9136
|
-
|
|
8803
|
+
beforeInit(ctx) {
|
|
9137
8804
|
const adoption = readTestAdoption(ctx.cwd);
|
|
9138
8805
|
if (adoption.state !== "jest") return Promise.resolve();
|
|
9139
|
-
|
|
9140
|
-
|
|
9141
|
-
|
|
9142
|
-
this.say(
|
|
8806
|
+
if (adoption.jestConfigs.every((config) => hasReference(ctx.cwd, suiteOf(config)))) {
|
|
8807
|
+
return Promise.resolve();
|
|
8808
|
+
}
|
|
8809
|
+
this.say(
|
|
8810
|
+
`no reference is recorded for this module, so this migration will not be provable: the jest config this deletes is the only place the old suite could be read from. Record one first with \`sentinel --validate --test\`, then migrate. Proceeding without it.`
|
|
8811
|
+
);
|
|
9143
8812
|
return Promise.resolve();
|
|
9144
8813
|
}
|
|
9145
8814
|
/**
|
|
@@ -9282,7 +8951,7 @@ function fromWorkspaceRoot(moduleDir, options, paths) {
|
|
|
9282
8951
|
if (root === void 0 || root === moduleDir) {
|
|
9283
8952
|
return { cwd: moduleDir, options: [...options], paths: [...paths] };
|
|
9284
8953
|
}
|
|
9285
|
-
const absolute = (value) => isAbsolute3(value) ? value :
|
|
8954
|
+
const absolute = (value) => isAbsolute3(value) ? value : resolve8(moduleDir, value);
|
|
9286
8955
|
const moved = [];
|
|
9287
8956
|
let previousWasConfig = false;
|
|
9288
8957
|
for (const option of options) {
|
|
@@ -9311,9 +8980,9 @@ function registerTest() {
|
|
|
9311
8980
|
|
|
9312
8981
|
// src/roles/typescript/adapters/tsc/tsc.adapter.ts
|
|
9313
8982
|
import { spawnSync as spawnSync6 } from "node:child_process";
|
|
9314
|
-
import { existsSync as
|
|
9315
|
-
import { createRequire as
|
|
9316
|
-
import { join as
|
|
8983
|
+
import { existsSync as existsSync30, readFileSync as readFileSync31 } from "node:fs";
|
|
8984
|
+
import { createRequire as createRequire6 } from "node:module";
|
|
8985
|
+
import { join as join39 } from "node:path";
|
|
9317
8986
|
|
|
9318
8987
|
// src/roles/typescript/presets/nest.json
|
|
9319
8988
|
var nest_default2 = {
|
|
@@ -9494,8 +9163,8 @@ function readTsconfigAdoption(cwd) {
|
|
|
9494
9163
|
}
|
|
9495
9164
|
|
|
9496
9165
|
// src/roles/typescript/adapters/tsc/plan.ts
|
|
9497
|
-
import { readFileSync as
|
|
9498
|
-
import { join as
|
|
9166
|
+
import { readFileSync as readFileSync30 } from "node:fs";
|
|
9167
|
+
import { join as join38 } from "node:path";
|
|
9499
9168
|
|
|
9500
9169
|
// src/roles/typescript/typecheck-script.ts
|
|
9501
9170
|
var SENTINEL_TYPECHECK_COMMAND = "sentinel --run --typescript";
|
|
@@ -9588,7 +9257,7 @@ function planAdoption(context) {
|
|
|
9588
9257
|
};
|
|
9589
9258
|
}
|
|
9590
9259
|
const existing = parseJsonc(
|
|
9591
|
-
|
|
9260
|
+
readFileSync30(join38(context.cwd, target.path), "utf8"),
|
|
9592
9261
|
target.path
|
|
9593
9262
|
);
|
|
9594
9263
|
const extendsChain = composeExtends(existing.extends, preset);
|
|
@@ -9726,7 +9395,7 @@ var TscAdapter = class _TscAdapter extends BaseAdapter {
|
|
|
9726
9395
|
let chain;
|
|
9727
9396
|
try {
|
|
9728
9397
|
const parsed = parseJsonc(
|
|
9729
|
-
|
|
9398
|
+
readFileSync31(join39(cwd, target.path), "utf8"),
|
|
9730
9399
|
target.path
|
|
9731
9400
|
);
|
|
9732
9401
|
chain = parsed.extends;
|
|
@@ -9739,7 +9408,7 @@ var TscAdapter = class _TscAdapter extends BaseAdapter {
|
|
|
9739
9408
|
);
|
|
9740
9409
|
if (preset === void 0) return void 0;
|
|
9741
9410
|
try {
|
|
9742
|
-
|
|
9411
|
+
createRequire6(join39(cwd, "noop.js")).resolve(preset);
|
|
9743
9412
|
return void 0;
|
|
9744
9413
|
} catch {
|
|
9745
9414
|
return preset;
|
|
@@ -9835,7 +9504,7 @@ var TscAdapter = class _TscAdapter extends BaseAdapter {
|
|
|
9835
9504
|
referencedProjects(cwd, config) {
|
|
9836
9505
|
try {
|
|
9837
9506
|
const parsed = parseJsonc(
|
|
9838
|
-
|
|
9507
|
+
readFileSync31(join39(cwd, config), "utf8"),
|
|
9839
9508
|
config
|
|
9840
9509
|
);
|
|
9841
9510
|
const referenced = (parsed.references ?? []).map((reference) => reference.path).filter((path) => typeof path === "string" && path.length > 0);
|
|
@@ -9851,7 +9520,7 @@ var TscAdapter = class _TscAdapter extends BaseAdapter {
|
|
|
9851
9520
|
* check.
|
|
9852
9521
|
*/
|
|
9853
9522
|
typecheckTarget(cwd) {
|
|
9854
|
-
if (
|
|
9523
|
+
if (existsSync30(join39(cwd, "tsconfig.json"))) return "tsconfig.json";
|
|
9855
9524
|
const target = resolveTsconfigTarget(cwd);
|
|
9856
9525
|
return target.reason === "none" ? null : target.path;
|
|
9857
9526
|
}
|
|
@@ -10000,7 +9669,7 @@ function detectFramework(packageJson) {
|
|
|
10000
9669
|
}
|
|
10001
9670
|
|
|
10002
9671
|
// src/core/dispatch.ts
|
|
10003
|
-
import { basename as
|
|
9672
|
+
import { basename as basename2 } from "node:path";
|
|
10004
9673
|
|
|
10005
9674
|
// src/shared/text.ts
|
|
10006
9675
|
function ensureLines(current, lines) {
|
|
@@ -10056,8 +9725,8 @@ function replaceLines(current, replacements) {
|
|
|
10056
9725
|
}
|
|
10057
9726
|
|
|
10058
9727
|
// src/core/apply-plan.ts
|
|
10059
|
-
import { existsSync as
|
|
10060
|
-
import { resolve as
|
|
9728
|
+
import { existsSync as existsSync31, readFileSync as readFileSync32, renameSync, rmSync as rmSync4, writeFileSync as writeFileSync3 } from "node:fs";
|
|
9729
|
+
import { resolve as resolve9, sep } from "node:path";
|
|
10061
9730
|
import { applyEdits as applyEdits3, findNodeAtLocation, modify, parseTree } from "jsonc-parser";
|
|
10062
9731
|
|
|
10063
9732
|
// src/shared/deep-merge.ts
|
|
@@ -10067,15 +9736,15 @@ function isPlainObject(value) {
|
|
|
10067
9736
|
|
|
10068
9737
|
// src/core/apply-plan.ts
|
|
10069
9738
|
function resolveWithinRoot(cwd, relativePath) {
|
|
10070
|
-
const root =
|
|
10071
|
-
const absolutePath =
|
|
9739
|
+
const root = resolve9(cwd);
|
|
9740
|
+
const absolutePath = resolve9(root, relativePath);
|
|
10072
9741
|
if (absolutePath !== root && !absolutePath.startsWith(root + sep)) {
|
|
10073
9742
|
throw new Error(`Refusing to write outside the module root: "${relativePath}".`);
|
|
10074
9743
|
}
|
|
10075
9744
|
return absolutePath;
|
|
10076
9745
|
}
|
|
10077
9746
|
function readIfExists(absolutePath) {
|
|
10078
|
-
return
|
|
9747
|
+
return existsSync31(absolutePath) ? readFileSync32(absolutePath, "utf8") : void 0;
|
|
10079
9748
|
}
|
|
10080
9749
|
function* leaves(value, prefix = []) {
|
|
10081
9750
|
for (const [key, keyValue] of Object.entries(value)) {
|
|
@@ -10177,14 +9846,14 @@ function preparePlan(cwd, plan4) {
|
|
|
10177
9846
|
}
|
|
10178
9847
|
function writeFileAtomic(absolutePath, contents) {
|
|
10179
9848
|
const tempPath = `${absolutePath}.sentinel-${process.pid}.tmp`;
|
|
10180
|
-
|
|
9849
|
+
writeFileSync3(tempPath, contents);
|
|
10181
9850
|
renameSync(tempPath, absolutePath);
|
|
10182
9851
|
}
|
|
10183
9852
|
function applyPlan(cwd, plan4) {
|
|
10184
9853
|
const changed = preparePlan(cwd, plan4).filter((file) => file.before !== file.after);
|
|
10185
9854
|
for (const file of changed) {
|
|
10186
9855
|
if (file.deleted) {
|
|
10187
|
-
|
|
9856
|
+
rmSync4(file.absolutePath, { force: true });
|
|
10188
9857
|
continue;
|
|
10189
9858
|
}
|
|
10190
9859
|
writeFileAtomic(file.absolutePath, file.after);
|
|
@@ -10193,8 +9862,8 @@ function applyPlan(cwd, plan4) {
|
|
|
10193
9862
|
}
|
|
10194
9863
|
|
|
10195
9864
|
// src/core/config/preset-evidence.ts
|
|
10196
|
-
import { existsSync as
|
|
10197
|
-
import { join as
|
|
9865
|
+
import { existsSync as existsSync32, readdirSync as readdirSync8, readFileSync as readFileSync33 } from "node:fs";
|
|
9866
|
+
import { join as join40 } from "node:path";
|
|
10198
9867
|
var PATH_SIGNALS = [
|
|
10199
9868
|
{
|
|
10200
9869
|
preset: "nest",
|
|
@@ -10222,18 +9891,18 @@ function sourceImports(cwd, pattern) {
|
|
|
10222
9891
|
const dir = stack.pop();
|
|
10223
9892
|
let entries;
|
|
10224
9893
|
try {
|
|
10225
|
-
entries =
|
|
9894
|
+
entries = readdirSync8(dir, { withFileTypes: true });
|
|
10226
9895
|
} catch {
|
|
10227
9896
|
continue;
|
|
10228
9897
|
}
|
|
10229
9898
|
for (const entry of entries) {
|
|
10230
9899
|
if (entry.isDirectory()) {
|
|
10231
|
-
if (!NOT_SCANNED.has(entry.name)) stack.push(
|
|
9900
|
+
if (!NOT_SCANNED.has(entry.name)) stack.push(join40(dir, entry.name));
|
|
10232
9901
|
continue;
|
|
10233
9902
|
}
|
|
10234
9903
|
if (!SOURCE_FILE2.test(entry.name)) continue;
|
|
10235
9904
|
try {
|
|
10236
|
-
if (pattern.test(
|
|
9905
|
+
if (pattern.test(readFileSync33(join40(dir, entry.name), "utf8"))) return true;
|
|
10237
9906
|
} catch {
|
|
10238
9907
|
continue;
|
|
10239
9908
|
}
|
|
@@ -10242,11 +9911,11 @@ function sourceImports(cwd, pattern) {
|
|
|
10242
9911
|
return false;
|
|
10243
9912
|
}
|
|
10244
9913
|
function dependencyNames(cwd) {
|
|
10245
|
-
const path =
|
|
10246
|
-
if (!
|
|
9914
|
+
const path = join40(cwd, "package.json");
|
|
9915
|
+
if (!existsSync32(path)) return [];
|
|
10247
9916
|
try {
|
|
10248
9917
|
const manifest = parseJsonc(
|
|
10249
|
-
|
|
9918
|
+
readFileSync33(path, "utf8"),
|
|
10250
9919
|
path
|
|
10251
9920
|
);
|
|
10252
9921
|
return [
|
|
@@ -10260,7 +9929,7 @@ function dependencyNames(cwd) {
|
|
|
10260
9929
|
function declaresJsx(cwd) {
|
|
10261
9930
|
let entries;
|
|
10262
9931
|
try {
|
|
10263
|
-
entries =
|
|
9932
|
+
entries = readdirSync8(cwd).filter(
|
|
10264
9933
|
(name) => name.startsWith("tsconfig") && name.endsWith(".json")
|
|
10265
9934
|
);
|
|
10266
9935
|
} catch {
|
|
@@ -10269,7 +9938,7 @@ function declaresJsx(cwd) {
|
|
|
10269
9938
|
for (const name of entries) {
|
|
10270
9939
|
try {
|
|
10271
9940
|
const config = parseJsonc(
|
|
10272
|
-
|
|
9941
|
+
readFileSync33(join40(cwd, name), "utf8"),
|
|
10273
9942
|
name
|
|
10274
9943
|
);
|
|
10275
9944
|
if (config.compilerOptions?.jsx !== void 0) return true;
|
|
@@ -10416,7 +10085,7 @@ async function dispatch(opts) {
|
|
|
10416
10085
|
}
|
|
10417
10086
|
if (adapter.beforeInit) {
|
|
10418
10087
|
await adapter.beforeInit({
|
|
10419
|
-
module:
|
|
10088
|
+
module: basename2(opts.cwd),
|
|
10420
10089
|
cwd: opts.cwd,
|
|
10421
10090
|
preset,
|
|
10422
10091
|
ci: false,
|
|
@@ -10435,7 +10104,7 @@ async function dispatch(opts) {
|
|
|
10435
10104
|
process.stderr.write(` fixing what ${opts.target} can fix automatically...
|
|
10436
10105
|
`);
|
|
10437
10106
|
await adapter.afterInit({
|
|
10438
|
-
module:
|
|
10107
|
+
module: basename2(opts.cwd),
|
|
10439
10108
|
cwd: opts.cwd,
|
|
10440
10109
|
preset,
|
|
10441
10110
|
ci: false,
|