@hublo/sentinel 1.4.0-alpha.32 → 1.4.0-alpha.34
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 +4 -3
- package/dist/{chunk-ZV5KMOS7.js → chunk-LF7QWHJ4.js} +38 -3
- package/dist/{chunk-ZV5KMOS7.js.map → chunk-LF7QWHJ4.js.map} +1 -1
- package/dist/{chunk-ORESQJAU.js → chunk-OORAEYSU.js} +510 -303
- package/dist/chunk-QXFCZON7.js +16 -0
- package/dist/chunk-QXFCZON7.js.map +1 -0
- package/dist/{chunk-3ZKTXODW.js → chunk-SWWQ7X7B.js} +6 -3
- package/dist/{chunk-3ZKTXODW.js.map → chunk-SWWQ7X7B.js.map} +1 -1
- package/dist/{chunk-SPW4KIQX.js → chunk-ZMUTKBZ2.js} +4 -2
- package/dist/index.js +3 -2
- package/dist/roles/build/nest/toolchain.js +2 -1
- package/dist/roles/build/nest/toolchain.js.map +1 -1
- package/dist/roles/test/nest/toolchain.js +3 -2
- package/dist/roles/test/nest/toolchain.js.map +1 -1
- package/dist/roles/test/react/toolchain.js +3 -2
- package/dist/roles/test/react/toolchain.js.map +1 -1
- package/dist/roles/test/shared-test-config.js +3 -2
- package/dist/{validate-5GABSOYH.js → validate-2RTPM5EB.js} +6 -6
- package/docs/using-sentinel.md +17 -1
- package/package.json +1 -1
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
matchesTsconfigPattern
|
|
3
3
|
} from "./chunk-O7REVMOC.js";
|
|
4
|
+
import {
|
|
5
|
+
parseJsonc
|
|
6
|
+
} from "./chunk-QXFCZON7.js";
|
|
4
7
|
import {
|
|
5
8
|
WORKSPACE_ROOT_MARKER,
|
|
6
9
|
findWorkspaceRoot,
|
|
@@ -24,8 +27,8 @@ var BaseAdapter = class {
|
|
|
24
27
|
};
|
|
25
28
|
|
|
26
29
|
// src/roles/test/read-adoption.ts
|
|
27
|
-
import { existsSync as existsSync2, readFileSync as
|
|
28
|
-
import { join as
|
|
30
|
+
import { existsSync as existsSync2, readFileSync as readFileSync3, readdirSync } from "node:fs";
|
|
31
|
+
import { join as join3, relative } from "node:path";
|
|
29
32
|
|
|
30
33
|
// src/core/config/manifest.ts
|
|
31
34
|
import { existsSync, readFileSync } from "node:fs";
|
|
@@ -81,6 +84,10 @@ function manifestOperation(cwd, scripts) {
|
|
|
81
84
|
};
|
|
82
85
|
}
|
|
83
86
|
|
|
87
|
+
// src/roles/test/config-policy.ts
|
|
88
|
+
import { readFileSync as readFileSync2 } from "node:fs";
|
|
89
|
+
import { join as join2 } from "node:path";
|
|
90
|
+
|
|
84
91
|
// src/roles/test/presets/toolchain.json
|
|
85
92
|
var toolchain_default = {
|
|
86
93
|
$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.",
|
|
@@ -141,13 +148,30 @@ function rewriteVitestScript(command) {
|
|
|
141
148
|
return `${lead}sentinel --run --test${suffix}${trailing}`;
|
|
142
149
|
});
|
|
143
150
|
}
|
|
151
|
+
function dependencyInput(cwd) {
|
|
152
|
+
const root = findWorkspaceRoot(cwd);
|
|
153
|
+
if (root === void 0) return "^default";
|
|
154
|
+
try {
|
|
155
|
+
const config = parseJsonc(
|
|
156
|
+
readFileSync2(join2(root, "nx.json"), "utf8"),
|
|
157
|
+
"nx.json"
|
|
158
|
+
);
|
|
159
|
+
return config?.namedInputs?.production === void 0 ? "^default" : "^production";
|
|
160
|
+
} catch {
|
|
161
|
+
return "^default";
|
|
162
|
+
}
|
|
163
|
+
}
|
|
144
164
|
function testTarget(options) {
|
|
145
|
-
const { name, configFiles, outputs, dependsOn, configurations } = options;
|
|
165
|
+
const { cwd, name, configFiles, outputs, dependsOn, configurations } = options;
|
|
146
166
|
const cached = outputs !== void 0 && outputs.length > 0;
|
|
147
167
|
return {
|
|
148
168
|
[name ?? TEST_SCRIPT_NAME]: {
|
|
149
169
|
cache: cached,
|
|
150
|
-
inputs: [
|
|
170
|
+
inputs: [
|
|
171
|
+
"default",
|
|
172
|
+
dependencyInput(cwd),
|
|
173
|
+
...configFiles.map((name2) => `{projectRoot}/${name2}`)
|
|
174
|
+
],
|
|
151
175
|
...cached ? { outputs: [...outputs] } : {},
|
|
152
176
|
...dependsOn !== void 0 && dependsOn.length > 0 ? { dependsOn: [...dependsOn] } : {},
|
|
153
177
|
...configurations !== void 0 && Object.keys(configurations).length > 0 ? { configurations: { ...configurations } } : {}
|
|
@@ -164,15 +188,15 @@ var JEST_CONFIG_FILES = [
|
|
|
164
188
|
"jest.integration-config.ts"
|
|
165
189
|
];
|
|
166
190
|
function testConfigFile(cwd) {
|
|
167
|
-
return TEST_CONFIG_FILES.find((name) => existsSync2(
|
|
191
|
+
return TEST_CONFIG_FILES.find((name) => existsSync2(join3(cwd, name)));
|
|
168
192
|
}
|
|
169
193
|
function jestConfigFiles(cwd) {
|
|
170
|
-
return JEST_CONFIG_FILES.filter((name) => existsSync2(
|
|
194
|
+
return JEST_CONFIG_FILES.filter((name) => existsSync2(join3(cwd, name)));
|
|
171
195
|
}
|
|
172
196
|
function rootJestConfigFiles(cwd) {
|
|
173
197
|
const root = findWorkspaceRoot(cwd);
|
|
174
198
|
if (root === void 0 || root === cwd) return [];
|
|
175
|
-
return JEST_CONFIG_FILES.filter((name) => existsSync2(
|
|
199
|
+
return JEST_CONFIG_FILES.filter((name) => existsSync2(join3(root, name)));
|
|
176
200
|
}
|
|
177
201
|
var TEST_FILE = /[.-](spec|test)\.[cm]?[jt]sx?$/;
|
|
178
202
|
var NOT_WALKED = /* @__PURE__ */ new Set(["node_modules", "dist", "coverage", ".git", ".nx", ".turbo"]);
|
|
@@ -195,9 +219,9 @@ function walkTestFiles(cwd, stopAtFirst) {
|
|
|
195
219
|
}
|
|
196
220
|
for (const entry of entries) {
|
|
197
221
|
if (entry.isDirectory()) {
|
|
198
|
-
if (!NOT_WALKED.has(entry.name)) stack.push(
|
|
222
|
+
if (!NOT_WALKED.has(entry.name)) stack.push(join3(dir, entry.name));
|
|
199
223
|
} else if (TEST_FILE.test(entry.name)) {
|
|
200
|
-
found.push(relative(cwd,
|
|
224
|
+
found.push(relative(cwd, join3(dir, entry.name)).replaceAll("\\", "/"));
|
|
201
225
|
if (stopAtFirst) return found;
|
|
202
226
|
}
|
|
203
227
|
}
|
|
@@ -206,7 +230,7 @@ function walkTestFiles(cwd, stopAtFirst) {
|
|
|
206
230
|
}
|
|
207
231
|
function readTestConfigSource(cwd, fileName) {
|
|
208
232
|
try {
|
|
209
|
-
return
|
|
233
|
+
return readFileSync3(join3(cwd, fileName), "utf8");
|
|
210
234
|
} catch {
|
|
211
235
|
return "";
|
|
212
236
|
}
|
|
@@ -277,15 +301,15 @@ function readTestAdoption(cwd) {
|
|
|
277
301
|
}
|
|
278
302
|
|
|
279
303
|
// src/roles/test/module-env.ts
|
|
280
|
-
import { existsSync as existsSync3, readFileSync as
|
|
281
|
-
import { join as
|
|
304
|
+
import { existsSync as existsSync3, readFileSync as readFileSync4 } from "node:fs";
|
|
305
|
+
import { join as join4 } from "node:path";
|
|
282
306
|
var CASCADE = [".env", ".env.test"];
|
|
283
307
|
var MODULE_CASCADE = [".env", ".env.local", ".env.test"];
|
|
284
308
|
function parse(path) {
|
|
285
309
|
const found = {};
|
|
286
310
|
let contents;
|
|
287
311
|
try {
|
|
288
|
-
contents =
|
|
312
|
+
contents = readFileSync4(path, "utf8");
|
|
289
313
|
} catch {
|
|
290
314
|
return found;
|
|
291
315
|
}
|
|
@@ -305,8 +329,8 @@ function moduleEnvironment(cwd) {
|
|
|
305
329
|
const loaded = [];
|
|
306
330
|
const added = {};
|
|
307
331
|
const files = [
|
|
308
|
-
...root === void 0 ? [] : CASCADE.map((name) => [
|
|
309
|
-
...MODULE_CASCADE.map((name) => [
|
|
332
|
+
...root === void 0 ? [] : CASCADE.map((name) => [join4(root, name), name]),
|
|
333
|
+
...MODULE_CASCADE.map((name) => [join4(cwd, name), `<module>/${name}`])
|
|
310
334
|
];
|
|
311
335
|
for (const [path, label] of files) {
|
|
312
336
|
if (!existsSync3(path)) continue;
|
|
@@ -320,19 +344,19 @@ function moduleEnvironment(cwd) {
|
|
|
320
344
|
// src/roles/test/reference.ts
|
|
321
345
|
import { execFileSync } from "node:child_process";
|
|
322
346
|
import { createHash } from "node:crypto";
|
|
323
|
-
import { existsSync as existsSync5, mkdirSync, mkdtempSync, readFileSync as
|
|
347
|
+
import { existsSync as existsSync5, mkdirSync, mkdtempSync, readFileSync as readFileSync5, rmSync, writeFileSync } from "node:fs";
|
|
324
348
|
import { tmpdir } from "node:os";
|
|
325
|
-
import { join as
|
|
349
|
+
import { join as join6, resolve } from "node:path";
|
|
326
350
|
|
|
327
351
|
// src/shared/resolve-bin.ts
|
|
328
352
|
import { existsSync as existsSync4 } from "node:fs";
|
|
329
353
|
import { createRequire } from "node:module";
|
|
330
|
-
import { delimiter, dirname, join as
|
|
354
|
+
import { delimiter, dirname, join as join5 } from "node:path";
|
|
331
355
|
var require2 = createRequire(import.meta.url);
|
|
332
356
|
function resolveBin(fromDir, name) {
|
|
333
357
|
let dir = fromDir;
|
|
334
358
|
for (; ; ) {
|
|
335
|
-
const candidate =
|
|
359
|
+
const candidate = join5(dir, "node_modules", ".bin", name);
|
|
336
360
|
if (existsSync4(candidate)) return candidate;
|
|
337
361
|
const parent = dirname(dir);
|
|
338
362
|
if (parent === dir) return void 0;
|
|
@@ -345,7 +369,7 @@ function binFromOwnInstall(packageName, binName) {
|
|
|
345
369
|
const bin = require2(manifest).bin;
|
|
346
370
|
const relative6 = typeof bin === "string" ? bin : bin?.[binName];
|
|
347
371
|
if (!relative6) return void 0;
|
|
348
|
-
const executable =
|
|
372
|
+
const executable = join5(dirname(manifest), relative6);
|
|
349
373
|
return existsSync4(executable) ? executable : void 0;
|
|
350
374
|
} catch {
|
|
351
375
|
return void 0;
|
|
@@ -623,7 +647,7 @@ function describeComparison(comparison) {
|
|
|
623
647
|
// src/roles/test/reference.ts
|
|
624
648
|
function referencePath(cwd, suite) {
|
|
625
649
|
const key = createHash("sha256").update(`${resolve(cwd)}\0${suite}`).digest("hex").slice(0, 16);
|
|
626
|
-
return
|
|
650
|
+
return join6(tmpdir(), "sentinel-test-reference", `${key}.json`);
|
|
627
651
|
}
|
|
628
652
|
function suiteOf(config) {
|
|
629
653
|
const base = config.replace(/^(jest|vitest)\./, "").replace(/\.[cm]?[jt]s$/, "");
|
|
@@ -634,9 +658,9 @@ function runJest(cwd, config) {
|
|
|
634
658
|
const bin = resolveBin(cwd, "jest");
|
|
635
659
|
if (bin === void 0) return void 0;
|
|
636
660
|
const root = findWorkspaceRoot(cwd) ?? cwd;
|
|
637
|
-
const out =
|
|
661
|
+
const out = join6(mkdtempSync(join6(tmpdir(), "sentinel-reference-")), "jest.json");
|
|
638
662
|
try {
|
|
639
|
-
execFileSync(bin, ["-c",
|
|
663
|
+
execFileSync(bin, ["-c", join6(cwd, config), "--json", `--outputFile=${out}`, "--silent"], {
|
|
640
664
|
cwd: root,
|
|
641
665
|
/*
|
|
642
666
|
* ⚠️ The module's environment, not the shell's, and this is what made the reference lie.
|
|
@@ -653,7 +677,7 @@ function runJest(cwd, config) {
|
|
|
653
677
|
}
|
|
654
678
|
if (!existsSync5(out)) return void 0;
|
|
655
679
|
try {
|
|
656
|
-
return JSON.parse(
|
|
680
|
+
return JSON.parse(readFileSync5(out, "utf8"));
|
|
657
681
|
} catch {
|
|
658
682
|
return void 0;
|
|
659
683
|
}
|
|
@@ -684,7 +708,7 @@ function captureReference(cwd, config) {
|
|
|
684
708
|
snapshot
|
|
685
709
|
};
|
|
686
710
|
const path = referencePath(cwd, suiteOf(config));
|
|
687
|
-
mkdirSync(
|
|
711
|
+
mkdirSync(join6(path, ".."), { recursive: true });
|
|
688
712
|
writeFileSync(path, `${JSON.stringify(stored, void 0, 2)}
|
|
689
713
|
`);
|
|
690
714
|
return {
|
|
@@ -699,7 +723,7 @@ function compareAgainstReference(cwd, suite, report) {
|
|
|
699
723
|
const path = referencePath(cwd, suite);
|
|
700
724
|
let stored;
|
|
701
725
|
try {
|
|
702
|
-
stored = JSON.parse(
|
|
726
|
+
stored = JSON.parse(readFileSync5(path, "utf8"));
|
|
703
727
|
} catch {
|
|
704
728
|
rmSync(path, { force: true });
|
|
705
729
|
return { ok: true, message: `the recorded reference could not be read, so nothing was proved.` };
|
|
@@ -723,7 +747,7 @@ function resolveVitest(cwd) {
|
|
|
723
747
|
|
|
724
748
|
// src/roles/test/adapters/vitest/vitest.adapter.ts
|
|
725
749
|
import { spawnSync } from "node:child_process";
|
|
726
|
-
import { isAbsolute as isAbsolute2, resolve as
|
|
750
|
+
import { isAbsolute as isAbsolute2, resolve as resolve8 } from "node:path";
|
|
727
751
|
|
|
728
752
|
// src/core/config/tool-args.ts
|
|
729
753
|
import { existsSync as existsSync6 } from "node:fs";
|
|
@@ -745,7 +769,7 @@ function splitToolArgs(cwd, toolArgs = [], { valueFlags = [] } = {}) {
|
|
|
745
769
|
|
|
746
770
|
// src/core/config/nx-target.ts
|
|
747
771
|
import { existsSync as existsSync7 } from "node:fs";
|
|
748
|
-
import { join as
|
|
772
|
+
import { join as join7 } from "node:path";
|
|
749
773
|
function nxTargetMetadataOperations(options) {
|
|
750
774
|
const { targets } = options;
|
|
751
775
|
if (Object.keys(targets).length === 0) return [];
|
|
@@ -756,7 +780,7 @@ function nxTargetOperations(options) {
|
|
|
756
780
|
const names = Object.keys(targets);
|
|
757
781
|
if (names.length === 0) return [];
|
|
758
782
|
const operations = [];
|
|
759
|
-
if (existsSync7(
|
|
783
|
+
if (existsSync7(join7(cwd, "project.json"))) {
|
|
760
784
|
operations.push({
|
|
761
785
|
kind: "remove-json-keys",
|
|
762
786
|
path: "project.json",
|
|
@@ -768,13 +792,13 @@ function nxTargetOperations(options) {
|
|
|
768
792
|
}
|
|
769
793
|
|
|
770
794
|
// src/core/config/project-json.ts
|
|
771
|
-
import { existsSync as existsSync8, readFileSync as
|
|
772
|
-
import { join as
|
|
795
|
+
import { existsSync as existsSync8, readFileSync as readFileSync6 } from "node:fs";
|
|
796
|
+
import { join as join8 } from "node:path";
|
|
773
797
|
function projectTargets(cwd) {
|
|
774
|
-
const path =
|
|
798
|
+
const path = join8(cwd, "project.json");
|
|
775
799
|
if (!existsSync8(path)) return void 0;
|
|
776
800
|
try {
|
|
777
|
-
return JSON.parse(
|
|
801
|
+
return JSON.parse(readFileSync6(path, "utf8")).targets;
|
|
778
802
|
} catch {
|
|
779
803
|
return void 0;
|
|
780
804
|
}
|
|
@@ -873,38 +897,26 @@ function rewriteToolchainImports(toolchain, source, fileName) {
|
|
|
873
897
|
}
|
|
874
898
|
|
|
875
899
|
// src/roles/test/jest-migration.ts
|
|
876
|
-
import { existsSync as existsSync18, readFileSync as
|
|
900
|
+
import { existsSync as existsSync18, readFileSync as readFileSync19, readdirSync as readdirSync6 } from "node:fs";
|
|
877
901
|
import { createRequire as createRequire5 } from "node:module";
|
|
878
|
-
import { dirname as
|
|
879
|
-
|
|
880
|
-
// src/shared/jsonc.ts
|
|
881
|
-
import { parse as parse2, printParseErrorCode } from "jsonc-parser";
|
|
882
|
-
function parseJsonc(text, source = "config") {
|
|
883
|
-
const errors = [];
|
|
884
|
-
const value = parse2(text, errors, { allowTrailingComma: true });
|
|
885
|
-
if (errors.length > 0) {
|
|
886
|
-
const details = errors.map((error) => printParseErrorCode(error.error)).join(", ");
|
|
887
|
-
throw new Error(`${source}: malformed JSONC (${details}).`);
|
|
888
|
-
}
|
|
889
|
-
return value;
|
|
890
|
-
}
|
|
902
|
+
import { dirname as dirname11, join as join24, relative as relative5 } from "node:path";
|
|
891
903
|
|
|
892
904
|
// src/roles/test/codemod/migrate-module.ts
|
|
893
|
-
import { readdirSync as readdirSync4, readFileSync as
|
|
894
|
-
import { join as
|
|
895
|
-
import { parseSync as
|
|
905
|
+
import { readdirSync as readdirSync4, readFileSync as readFileSync14, statSync as statSync4 } from "node:fs";
|
|
906
|
+
import { join as join17 } from "node:path";
|
|
907
|
+
import { parseSync as parseSync8 } from "oxc-parser";
|
|
896
908
|
|
|
897
909
|
// src/roles/test/msw-lifecycle.ts
|
|
898
|
-
import { existsSync as existsSync9, readFileSync as
|
|
899
|
-
import { join as
|
|
910
|
+
import { existsSync as existsSync9, readFileSync as readFileSync7 } from "node:fs";
|
|
911
|
+
import { join as join9 } from "node:path";
|
|
900
912
|
var ROOT_SETUP = "jest.setup.after.env.js";
|
|
901
913
|
function ownsMswLifecycle(cwd, setupFiles) {
|
|
902
914
|
for (const raw of setupFiles) {
|
|
903
915
|
if (raw.endsWith(ROOT_SETUP)) continue;
|
|
904
|
-
const file =
|
|
916
|
+
const file = join9(cwd, raw.replaceAll("<rootDir>/", "").replaceAll("<rootDir>", "."));
|
|
905
917
|
if (!existsSync9(file)) continue;
|
|
906
918
|
try {
|
|
907
|
-
if (/\.listen\s*\(/.test(
|
|
919
|
+
if (/\.listen\s*\(/.test(readFileSync7(file, "utf8"))) return true;
|
|
908
920
|
} catch {
|
|
909
921
|
continue;
|
|
910
922
|
}
|
|
@@ -943,6 +955,7 @@ function walk(node, visit) {
|
|
|
943
955
|
if (value !== null && typeof value === "object") walk(value, visit);
|
|
944
956
|
}
|
|
945
957
|
}
|
|
958
|
+
var MEMBER_TYPES = /* @__PURE__ */ new Set(["MemberExpression", "StaticMemberExpression"]);
|
|
946
959
|
|
|
947
960
|
// src/roles/test/codemod/rename.ts
|
|
948
961
|
var VITEST_TYPE_SOURCE = "vitest";
|
|
@@ -1121,11 +1134,19 @@ ${source}`;
|
|
|
1121
1134
|
}
|
|
1122
1135
|
|
|
1123
1136
|
// src/roles/test/codemod/migrate-file.ts
|
|
1124
|
-
import { dirname as
|
|
1125
|
-
import { parseSync as
|
|
1137
|
+
import { dirname as dirname7 } from "node:path";
|
|
1138
|
+
import { parseSync as parseSync7 } from "oxc-parser";
|
|
1139
|
+
|
|
1140
|
+
// src/roles/test/codemod/edits.ts
|
|
1141
|
+
function applyEdits(source, edits) {
|
|
1142
|
+
let result = source;
|
|
1143
|
+
for (const edit of [...edits].sort((left, right) => right.start - left.start)) {
|
|
1144
|
+
result = `${result.slice(0, edit.start)}${edit.text}${result.slice(edit.end)}`;
|
|
1145
|
+
}
|
|
1146
|
+
return result;
|
|
1147
|
+
}
|
|
1126
1148
|
|
|
1127
1149
|
// src/roles/test/codemod/assertion-return-value.ts
|
|
1128
|
-
var MEMBER_TYPES = /* @__PURE__ */ new Set(["MemberExpression", "StaticMemberExpression"]);
|
|
1129
1150
|
function rootedAtExpect(node) {
|
|
1130
1151
|
let current = node;
|
|
1131
1152
|
for (let depth = 0; current !== void 0 && depth < 12; depth += 1) {
|
|
@@ -1243,17 +1264,13 @@ function rewriteAssertionReturnValue(source, program) {
|
|
|
1243
1264
|
edits.push({ start: head, end: to, text: "" });
|
|
1244
1265
|
}
|
|
1245
1266
|
}
|
|
1246
|
-
|
|
1247
|
-
for (const edit of [...edits].sort((left, right) => right.start - left.start)) {
|
|
1248
|
-
result = `${result.slice(0, edit.start)}${edit.text}${result.slice(edit.end)}`;
|
|
1249
|
-
}
|
|
1267
|
+
const result = applyEdits(source, edits);
|
|
1250
1268
|
return { source: result, rewritten: captures.length - refusals.length, refusals };
|
|
1251
1269
|
}
|
|
1252
1270
|
|
|
1253
1271
|
// src/roles/test/codemod/bare-mock-factory.ts
|
|
1254
|
-
var MEMBER_TYPES2 = /* @__PURE__ */ new Set(["MemberExpression", "StaticMemberExpression"]);
|
|
1255
1272
|
function isMockFactory(node) {
|
|
1256
|
-
if (node === void 0 || !
|
|
1273
|
+
if (node === void 0 || !MEMBER_TYPES.has(node.type)) return false;
|
|
1257
1274
|
const object = node.object;
|
|
1258
1275
|
const property = node.property;
|
|
1259
1276
|
if (object?.type !== "Identifier") return false;
|
|
@@ -1277,11 +1294,10 @@ function invokeBareMockFactories(source, program) {
|
|
|
1277
1294
|
}
|
|
1278
1295
|
|
|
1279
1296
|
// src/roles/test/codemod/constructible-mocks.ts
|
|
1280
|
-
var MEMBER_TYPES3 = /* @__PURE__ */ new Set(["MemberExpression", "StaticMemberExpression"]);
|
|
1281
1297
|
function mockImplementationArrow(node) {
|
|
1282
1298
|
if (node.type !== "CallExpression") return void 0;
|
|
1283
1299
|
const callee = node.callee;
|
|
1284
|
-
if (callee === void 0 || !
|
|
1300
|
+
if (callee === void 0 || !MEMBER_TYPES.has(callee.type)) return void 0;
|
|
1285
1301
|
const property = callee.property;
|
|
1286
1302
|
if (property?.type !== "Identifier" || property.name !== "mockImplementation") return void 0;
|
|
1287
1303
|
const [argument] = node.arguments ?? [];
|
|
@@ -1290,7 +1306,7 @@ function mockImplementationArrow(node) {
|
|
|
1290
1306
|
function assertedMockedClass(source, node) {
|
|
1291
1307
|
if (node.type !== "CallExpression") return false;
|
|
1292
1308
|
const callee = node.callee;
|
|
1293
|
-
if (callee === void 0 || !
|
|
1309
|
+
if (callee === void 0 || !MEMBER_TYPES.has(callee.type)) return false;
|
|
1294
1310
|
const object = callee.object;
|
|
1295
1311
|
if (object === void 0) return false;
|
|
1296
1312
|
return /\bMockedClass\b/.test(source.slice(object.start, object.end));
|
|
@@ -1348,10 +1364,7 @@ function rewriteConstructibleMocks(source, program, factories) {
|
|
|
1348
1364
|
rewritten += 1;
|
|
1349
1365
|
});
|
|
1350
1366
|
}
|
|
1351
|
-
|
|
1352
|
-
for (const edit of [...edits].sort((left, right) => right.start - left.start)) {
|
|
1353
|
-
result = result.slice(0, edit.start) + edit.text + result.slice(edit.end);
|
|
1354
|
-
}
|
|
1367
|
+
const result = applyEdits(source, edits);
|
|
1355
1368
|
return { source: result, rewritten, refusals };
|
|
1356
1369
|
}
|
|
1357
1370
|
|
|
@@ -1380,16 +1393,15 @@ function normaliseDeepImports(source) {
|
|
|
1380
1393
|
}
|
|
1381
1394
|
|
|
1382
1395
|
// src/roles/test/codemod/each-table-rows.ts
|
|
1383
|
-
var MEMBER_TYPES4 = /* @__PURE__ */ new Set(["MemberExpression", "StaticMemberExpression"]);
|
|
1384
1396
|
var RUNNERS = /* @__PURE__ */ new Set(["it", "test", "describe"]);
|
|
1385
1397
|
function eachTable(node) {
|
|
1386
1398
|
if (node.type !== "CallExpression") return void 0;
|
|
1387
1399
|
const callee = node.callee;
|
|
1388
|
-
if (callee === void 0 || !
|
|
1400
|
+
if (callee === void 0 || !MEMBER_TYPES.has(callee.type)) return void 0;
|
|
1389
1401
|
const property = callee.property;
|
|
1390
1402
|
if (property?.type !== "Identifier" || property.name !== "each") return void 0;
|
|
1391
1403
|
let object = callee.object;
|
|
1392
|
-
while (object !== void 0 &&
|
|
1404
|
+
while (object !== void 0 && MEMBER_TYPES.has(object.type)) {
|
|
1393
1405
|
object = object.object;
|
|
1394
1406
|
}
|
|
1395
1407
|
if (object?.type !== "Identifier" || !RUNNERS.has(object.name)) return void 0;
|
|
@@ -1408,21 +1420,17 @@ function rewriteEachTableRows(source, program) {
|
|
|
1408
1420
|
const wrapped = rows.map((row) => source.slice(row.start, row.end)).map((text) => `[${text}]`).join(", ");
|
|
1409
1421
|
edits.push({ start: table.start, end: table.end, text: `[${wrapped}]` });
|
|
1410
1422
|
});
|
|
1411
|
-
|
|
1412
|
-
for (const edit of [...edits].sort((left, right) => right.start - left.start)) {
|
|
1413
|
-
result = `${result.slice(0, edit.start)}${edit.text}${result.slice(edit.end)}`;
|
|
1414
|
-
}
|
|
1423
|
+
const result = applyEdits(source, edits);
|
|
1415
1424
|
return { source: result, rewritten: edits.length };
|
|
1416
1425
|
}
|
|
1417
1426
|
|
|
1418
1427
|
// src/roles/test/codemod/each-title.ts
|
|
1419
|
-
var MEMBER_TYPES5 = /* @__PURE__ */ new Set(["MemberExpression", "StaticMemberExpression"]);
|
|
1420
1428
|
function eachTitle(node) {
|
|
1421
1429
|
if (node.type !== "CallExpression") return void 0;
|
|
1422
1430
|
const inner = node.callee;
|
|
1423
1431
|
if (inner?.type !== "CallExpression") return void 0;
|
|
1424
1432
|
const member = inner.callee;
|
|
1425
|
-
if (member === void 0 || !
|
|
1433
|
+
if (member === void 0 || !MEMBER_TYPES.has(member.type)) return void 0;
|
|
1426
1434
|
const property = member.property;
|
|
1427
1435
|
if (property?.type !== "Identifier" || property.name !== "each") return void 0;
|
|
1428
1436
|
const [title] = node.arguments ?? [];
|
|
@@ -1466,23 +1474,19 @@ function rewriteEachTitles(source, program) {
|
|
|
1466
1474
|
edits.push({ start, end, text: replacement.text });
|
|
1467
1475
|
rewritten += replacement.rewritten;
|
|
1468
1476
|
});
|
|
1469
|
-
|
|
1470
|
-
for (const edit of [...edits].sort((left, right) => right.start - left.start)) {
|
|
1471
|
-
result = result.slice(0, edit.start) + edit.text + result.slice(edit.end);
|
|
1472
|
-
}
|
|
1477
|
+
const result = applyEdits(source, edits);
|
|
1473
1478
|
return { source: result, rewritten };
|
|
1474
1479
|
}
|
|
1475
1480
|
|
|
1476
1481
|
// src/roles/test/codemod/empty-mock-implementation.ts
|
|
1477
1482
|
var METHODS = /* @__PURE__ */ new Set(["mockImplementation", "mockImplementationOnce"]);
|
|
1478
|
-
var MEMBER_TYPES6 = /* @__PURE__ */ new Set(["MemberExpression", "StaticMemberExpression"]);
|
|
1479
1483
|
function rewriteEmptyMockImplementation(source, program) {
|
|
1480
1484
|
const insertAt = [];
|
|
1481
1485
|
walk(program, (node) => {
|
|
1482
1486
|
if (node.type !== "CallExpression") return;
|
|
1483
1487
|
if ((node.arguments ?? []).length > 0) return;
|
|
1484
1488
|
const callee = node.callee;
|
|
1485
|
-
if (callee === void 0 || !
|
|
1489
|
+
if (callee === void 0 || !MEMBER_TYPES.has(callee.type)) return;
|
|
1486
1490
|
const property = callee.property;
|
|
1487
1491
|
if (property?.type !== "Identifier" || !METHODS.has(property.name)) return;
|
|
1488
1492
|
insertAt.push(node.end - 1);
|
|
@@ -1495,12 +1499,11 @@ function rewriteEmptyMockImplementation(source, program) {
|
|
|
1495
1499
|
}
|
|
1496
1500
|
|
|
1497
1501
|
// src/roles/test/codemod/fake-timer-options.ts
|
|
1498
|
-
var MEMBER_TYPES7 = /* @__PURE__ */ new Set(["MemberExpression", "StaticMemberExpression"]);
|
|
1499
1502
|
var TIMER_CALLS = /* @__PURE__ */ new Set(["useFakeTimers"]);
|
|
1500
1503
|
function timerOptions(node) {
|
|
1501
1504
|
if (node.type !== "CallExpression") return void 0;
|
|
1502
1505
|
const callee = node.callee;
|
|
1503
|
-
if (callee === void 0 || !
|
|
1506
|
+
if (callee === void 0 || !MEMBER_TYPES.has(callee.type)) return void 0;
|
|
1504
1507
|
const object = callee.object;
|
|
1505
1508
|
const property = callee.property;
|
|
1506
1509
|
if (object?.type !== "Identifier") return void 0;
|
|
@@ -1614,10 +1617,7 @@ function rewriteFakeTimerOptions(source, program) {
|
|
|
1614
1617
|
}
|
|
1615
1618
|
});
|
|
1616
1619
|
if (edits.length === 0) return { source, translated, refusals, warnings };
|
|
1617
|
-
|
|
1618
|
-
for (const edit of [...edits].sort((left, right) => right.start - left.start)) {
|
|
1619
|
-
result = result.slice(0, edit.start) + edit.text + result.slice(edit.end);
|
|
1620
|
-
}
|
|
1620
|
+
const result = applyEdits(source, edits);
|
|
1621
1621
|
return { source: result, translated, refusals, warnings };
|
|
1622
1622
|
}
|
|
1623
1623
|
|
|
@@ -1835,16 +1835,12 @@ function hoistCapturedBindings(source, program, factories, bindings, imported) {
|
|
|
1835
1835
|
const span = statementSpan(source, statement2);
|
|
1836
1836
|
return { ...span, text: index === 0 ? hoistedLine : "" };
|
|
1837
1837
|
});
|
|
1838
|
-
|
|
1839
|
-
for (const edit of edits.sort((left, right) => right.start - left.start)) {
|
|
1840
|
-
rewritten = rewritten.slice(0, edit.start) + edit.text + rewritten.slice(edit.end);
|
|
1841
|
-
}
|
|
1838
|
+
const rewritten = applyEdits(source, edits);
|
|
1842
1839
|
return { source: rewritten, hoisted: ordered.map(({ name }) => name), refusals: [] };
|
|
1843
1840
|
}
|
|
1844
1841
|
|
|
1845
1842
|
// src/roles/test/codemod/hook-return-value.ts
|
|
1846
1843
|
var HOOKS = /* @__PURE__ */ new Set(["beforeEach", "afterEach", "beforeAll", "afterAll"]);
|
|
1847
|
-
var MEMBER_TYPES8 = /* @__PURE__ */ new Set(["MemberExpression", "StaticMemberExpression"]);
|
|
1848
1844
|
function hookCallback(node) {
|
|
1849
1845
|
if (node.type !== "CallExpression") return void 0;
|
|
1850
1846
|
const callee = node.callee;
|
|
@@ -1855,7 +1851,7 @@ function hookCallback(node) {
|
|
|
1855
1851
|
function configuresAMock(body) {
|
|
1856
1852
|
if (body.type !== "CallExpression") return false;
|
|
1857
1853
|
const callee = body.callee;
|
|
1858
|
-
if (callee === void 0 || !
|
|
1854
|
+
if (callee === void 0 || !MEMBER_TYPES.has(callee.type)) return false;
|
|
1859
1855
|
const property = callee.property;
|
|
1860
1856
|
return property?.type === "Identifier" && /^mock[A-Z]/.test(property.name);
|
|
1861
1857
|
}
|
|
@@ -1873,17 +1869,170 @@ function rewriteHookReturnValue(source, program) {
|
|
|
1873
1869
|
${source.slice(start, end)}
|
|
1874
1870
|
}` });
|
|
1875
1871
|
});
|
|
1876
|
-
|
|
1877
|
-
for (const edit of [...edits].sort((left, right) => right.start - left.start)) {
|
|
1878
|
-
result = `${result.slice(0, edit.start)}${edit.text}${result.slice(edit.end)}`;
|
|
1879
|
-
}
|
|
1872
|
+
const result = applyEdits(source, edits);
|
|
1880
1873
|
return { source: result, rewritten: edits.length };
|
|
1881
1874
|
}
|
|
1882
1875
|
|
|
1883
1876
|
// src/roles/test/codemod/named-rules.ts
|
|
1884
|
-
import { existsSync as existsSync10, readFileSync as
|
|
1877
|
+
import { existsSync as existsSync10, readFileSync as readFileSync9 } from "node:fs";
|
|
1885
1878
|
import { createRequire as createRequire2 } from "node:module";
|
|
1886
|
-
import { dirname as
|
|
1879
|
+
import { dirname as dirname3, join as join11 } from "node:path";
|
|
1880
|
+
|
|
1881
|
+
// src/roles/test/codemod/static-import-for-require.ts
|
|
1882
|
+
import { readFileSync as readFileSync8, statSync } from "node:fs";
|
|
1883
|
+
import { dirname as dirname2, join as join10, resolve as resolve3 } from "node:path";
|
|
1884
|
+
import { parseSync as parseSync4 } from "oxc-parser";
|
|
1885
|
+
var EXTENSIONS = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"];
|
|
1886
|
+
function resolveRelative(fromFile, specifier) {
|
|
1887
|
+
const base = resolve3(dirname2(fromFile), specifier);
|
|
1888
|
+
const candidates = [
|
|
1889
|
+
base,
|
|
1890
|
+
...EXTENSIONS.map((extension) => `${base}${extension}`),
|
|
1891
|
+
...EXTENSIONS.map((extension) => join10(base, `index${extension}`))
|
|
1892
|
+
];
|
|
1893
|
+
for (const candidate of candidates) {
|
|
1894
|
+
try {
|
|
1895
|
+
if (statSync(candidate).isFile()) return candidate;
|
|
1896
|
+
} catch {
|
|
1897
|
+
}
|
|
1898
|
+
}
|
|
1899
|
+
return void 0;
|
|
1900
|
+
}
|
|
1901
|
+
function relativeSpecifiers(source) {
|
|
1902
|
+
const found = [];
|
|
1903
|
+
const patterns = [
|
|
1904
|
+
/\bfrom\s+['"](\.[^'"]*)['"]/g,
|
|
1905
|
+
/\bimport\s+['"](\.[^'"]*)['"]/g,
|
|
1906
|
+
/\bimport\s*\(\s*['"](\.[^'"]*)['"]\s*\)/g,
|
|
1907
|
+
/\brequire\s*\(\s*['"](\.[^'"]*)['"]\s*\)/g
|
|
1908
|
+
];
|
|
1909
|
+
for (const pattern of patterns) {
|
|
1910
|
+
for (const match of source.matchAll(pattern)) found.push(match[1]);
|
|
1911
|
+
}
|
|
1912
|
+
return found;
|
|
1913
|
+
}
|
|
1914
|
+
function reachesBack(fromFile, specifier) {
|
|
1915
|
+
const entry = resolveRelative(fromFile, specifier);
|
|
1916
|
+
if (entry === void 0) return true;
|
|
1917
|
+
const target = resolve3(fromFile);
|
|
1918
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1919
|
+
const stack = [entry];
|
|
1920
|
+
while (stack.length > 0 && seen.size < 200) {
|
|
1921
|
+
const file = stack.pop();
|
|
1922
|
+
if (seen.has(file)) continue;
|
|
1923
|
+
seen.add(file);
|
|
1924
|
+
if (resolve3(file) === target) return true;
|
|
1925
|
+
let source;
|
|
1926
|
+
try {
|
|
1927
|
+
source = readFileSync8(file, "utf8");
|
|
1928
|
+
} catch {
|
|
1929
|
+
continue;
|
|
1930
|
+
}
|
|
1931
|
+
for (const relative6 of relativeSpecifiers(source)) {
|
|
1932
|
+
const next = resolveRelative(file, relative6);
|
|
1933
|
+
if (next !== void 0) stack.push(next);
|
|
1934
|
+
}
|
|
1935
|
+
}
|
|
1936
|
+
return seen.size >= 200;
|
|
1937
|
+
}
|
|
1938
|
+
function namedRequireDeclarations(program) {
|
|
1939
|
+
const found = /* @__PURE__ */ new Map();
|
|
1940
|
+
walk(program, (node) => {
|
|
1941
|
+
if (node.type !== "VariableDeclaration") return;
|
|
1942
|
+
const declarators = node.declarations ?? [];
|
|
1943
|
+
if (declarators.length !== 1) return;
|
|
1944
|
+
const declarator = declarators[0];
|
|
1945
|
+
const init = declarator.init;
|
|
1946
|
+
if (init?.type !== "CallExpression") return;
|
|
1947
|
+
const callee = init.callee;
|
|
1948
|
+
if (callee?.type !== "Identifier" || callee.name !== "require") return;
|
|
1949
|
+
const [argument] = init.arguments ?? [];
|
|
1950
|
+
if (argument?.type !== "StringLiteral" && argument?.type !== "Literal") return;
|
|
1951
|
+
const specifier = String(argument.value);
|
|
1952
|
+
if (!specifier.startsWith(".")) return;
|
|
1953
|
+
const id = declarator.id;
|
|
1954
|
+
if (id?.type !== "ObjectPattern") return;
|
|
1955
|
+
const names = [];
|
|
1956
|
+
for (const property of id.properties ?? []) {
|
|
1957
|
+
if (property.type !== "Property" && property.type !== "ObjectProperty") return;
|
|
1958
|
+
if (property.computed === true || property.shorthand !== true) return;
|
|
1959
|
+
const key = property.key;
|
|
1960
|
+
const value = property.value;
|
|
1961
|
+
if (key?.type !== "Identifier" || value?.type !== "Identifier") return;
|
|
1962
|
+
if (key.name !== value.name) return;
|
|
1963
|
+
names.push(key.name);
|
|
1964
|
+
}
|
|
1965
|
+
if (names.length === 0) return;
|
|
1966
|
+
found.set(init, { names, specifier, start: node.start, end: node.end });
|
|
1967
|
+
});
|
|
1968
|
+
return found;
|
|
1969
|
+
}
|
|
1970
|
+
function topLevelNames(program) {
|
|
1971
|
+
const names = /* @__PURE__ */ new Set();
|
|
1972
|
+
for (const node of program.body ?? []) {
|
|
1973
|
+
if (node.type === "ImportDeclaration") {
|
|
1974
|
+
for (const specifier of node.specifiers ?? []) {
|
|
1975
|
+
const local = specifier.local;
|
|
1976
|
+
if (local?.type === "Identifier") names.add(local.name);
|
|
1977
|
+
}
|
|
1978
|
+
continue;
|
|
1979
|
+
}
|
|
1980
|
+
if (node.type === "VariableDeclaration") {
|
|
1981
|
+
for (const declarator of node.declarations ?? []) {
|
|
1982
|
+
const id = declarator.id;
|
|
1983
|
+
if (id?.type === "Identifier") names.add(id.name);
|
|
1984
|
+
}
|
|
1985
|
+
continue;
|
|
1986
|
+
}
|
|
1987
|
+
if ((node.type === "FunctionDeclaration" || node.type === "ClassDeclaration") && node.id?.type === "Identifier") {
|
|
1988
|
+
names.add(node.id.name);
|
|
1989
|
+
}
|
|
1990
|
+
}
|
|
1991
|
+
return names;
|
|
1992
|
+
}
|
|
1993
|
+
function withLeadingComments(source, comments, start) {
|
|
1994
|
+
let from = start;
|
|
1995
|
+
for (; ; ) {
|
|
1996
|
+
const before = source.slice(0, from);
|
|
1997
|
+
const blank = before.length - before.trimEnd().length;
|
|
1998
|
+
const candidate = comments.find((comment) => comment.end === from - blank);
|
|
1999
|
+
if (candidate === void 0) break;
|
|
2000
|
+
const lineStart = source.lastIndexOf("\n", candidate.start) + 1;
|
|
2001
|
+
if (source.slice(lineStart, candidate.start).trim() !== "") break;
|
|
2002
|
+
from = lineStart;
|
|
2003
|
+
}
|
|
2004
|
+
return from;
|
|
2005
|
+
}
|
|
2006
|
+
function planStaticImport(fileName, source, program, requireCall2, semi) {
|
|
2007
|
+
const declaration = namedRequireDeclarations(program).get(requireCall2);
|
|
2008
|
+
if (declaration === void 0) return void 0;
|
|
2009
|
+
const bound = topLevelNames(program);
|
|
2010
|
+
if (declaration.names.some((name) => bound.has(name))) return void 0;
|
|
2011
|
+
if (reachesBack(fileName, declaration.specifier)) return void 0;
|
|
2012
|
+
const { comments } = parseSync4(fileName, source, { sourceType: "module" });
|
|
2013
|
+
const lineStart = source.lastIndexOf("\n", declaration.start - 1) + 1;
|
|
2014
|
+
const ownsItsLine = source.slice(lineStart, declaration.start).trim() === "";
|
|
2015
|
+
const start = withLeadingComments(
|
|
2016
|
+
source,
|
|
2017
|
+
comments,
|
|
2018
|
+
ownsItsLine ? lineStart : declaration.start
|
|
2019
|
+
);
|
|
2020
|
+
return {
|
|
2021
|
+
line: `import { ${declaration.names.join(", ")} } from '${declaration.specifier}'${semi ? ";" : ""}`,
|
|
2022
|
+
// To the end of the line, so the statement does not leave an empty one behind.
|
|
2023
|
+
remove: { start, end: endOfLine(source, declaration.end) }
|
|
2024
|
+
};
|
|
2025
|
+
}
|
|
2026
|
+
function endOfLine(source, end) {
|
|
2027
|
+
let at = end;
|
|
2028
|
+
if (source[at] === ";") at += 1;
|
|
2029
|
+
while (source[at] === " " || source[at] === " ") at += 1;
|
|
2030
|
+
if (source[at] === "\r") at += 1;
|
|
2031
|
+
if (source[at] === "\n") at += 1;
|
|
2032
|
+
return at;
|
|
2033
|
+
}
|
|
2034
|
+
|
|
2035
|
+
// src/roles/test/codemod/named-rules.ts
|
|
1887
2036
|
function isCommonJsPackage(fromFile, specifier) {
|
|
1888
2037
|
if (specifier.startsWith(".") || specifier.startsWith("/")) return false;
|
|
1889
2038
|
let resolved;
|
|
@@ -1895,23 +2044,26 @@ function isCommonJsPackage(fromFile, specifier) {
|
|
|
1895
2044
|
if (!resolved.includes(`${"/"}node_modules${"/"}`)) return false;
|
|
1896
2045
|
if (resolved.endsWith(".mjs")) return false;
|
|
1897
2046
|
if (resolved.endsWith(".cjs")) return true;
|
|
1898
|
-
let dir =
|
|
2047
|
+
let dir = dirname3(resolved);
|
|
1899
2048
|
for (let depth = 0; depth < 12; depth += 1) {
|
|
1900
|
-
const manifest =
|
|
2049
|
+
const manifest = join11(dir, "package.json");
|
|
1901
2050
|
if (existsSync10(manifest)) {
|
|
1902
2051
|
try {
|
|
1903
|
-
return JSON.parse(
|
|
2052
|
+
return JSON.parse(readFileSync9(manifest, "utf8")).type !== "module";
|
|
1904
2053
|
} catch {
|
|
1905
2054
|
return false;
|
|
1906
2055
|
}
|
|
1907
2056
|
}
|
|
1908
|
-
const parent =
|
|
2057
|
+
const parent = dirname3(dir);
|
|
1909
2058
|
if (parent === dir) break;
|
|
1910
2059
|
dir = parent;
|
|
1911
2060
|
}
|
|
1912
2061
|
return false;
|
|
1913
2062
|
}
|
|
1914
|
-
|
|
2063
|
+
function fileUsesSemicolons(source) {
|
|
2064
|
+
const first = /^import\s[^\n]*$/m.exec(source);
|
|
2065
|
+
return first !== null && first[0].trimEnd().endsWith(";");
|
|
2066
|
+
}
|
|
1915
2067
|
var ASYNC_REPLACEMENTS = {
|
|
1916
2068
|
requireActual: "importActual",
|
|
1917
2069
|
requireMock: "importMock"
|
|
@@ -1921,7 +2073,7 @@ function mockedSpecifiers(program) {
|
|
|
1921
2073
|
walk(program, (node) => {
|
|
1922
2074
|
if (node.type !== "CallExpression") return;
|
|
1923
2075
|
const callee = node.callee;
|
|
1924
|
-
if (callee === void 0 || !
|
|
2076
|
+
if (callee === void 0 || !MEMBER_TYPES.has(callee.type)) return;
|
|
1925
2077
|
const object = callee.object;
|
|
1926
2078
|
const property = callee.property;
|
|
1927
2079
|
if (object?.type !== "Identifier") return;
|
|
@@ -1934,6 +2086,16 @@ function mockedSpecifiers(program) {
|
|
|
1934
2086
|
});
|
|
1935
2087
|
return found;
|
|
1936
2088
|
}
|
|
2089
|
+
function methodValues(program) {
|
|
2090
|
+
const found = /* @__PURE__ */ new Set();
|
|
2091
|
+
walk(program, (node) => {
|
|
2092
|
+
const isMethod = node.type === "MethodDefinition" || node.type === "ClassMethod" || node.type === "ObjectMethod" || (node.type === "Property" || node.type === "ObjectProperty") && (node.kind === "get" || node.kind === "set" || node.method === true);
|
|
2093
|
+
if (!isMethod) return;
|
|
2094
|
+
const value = node.value ?? node.body;
|
|
2095
|
+
if (value !== void 0) found.add(value);
|
|
2096
|
+
});
|
|
2097
|
+
return found;
|
|
2098
|
+
}
|
|
1937
2099
|
var FUNCTIONS = /* @__PURE__ */ new Set(["ArrowFunctionExpression", "FunctionExpression", "FunctionDeclaration"]);
|
|
1938
2100
|
function walkWithEnclosingFunction(node, enclosing, visit) {
|
|
1939
2101
|
if (node === null || typeof node !== "object") return;
|
|
@@ -1958,7 +2120,7 @@ function bareRequire(node) {
|
|
|
1958
2120
|
function mockFactoryReturn(node) {
|
|
1959
2121
|
if (node.type !== "CallExpression") return void 0;
|
|
1960
2122
|
const callee = node.callee;
|
|
1961
|
-
if (callee === void 0 || !
|
|
2123
|
+
if (callee === void 0 || !MEMBER_TYPES.has(callee.type)) return void 0;
|
|
1962
2124
|
const object = callee.object;
|
|
1963
2125
|
const property = callee.property;
|
|
1964
2126
|
if (object?.type !== "Identifier") return void 0;
|
|
@@ -2005,18 +2167,29 @@ function typeArgumentText(source, call) {
|
|
|
2005
2167
|
if (node?.start === void 0 || node.end === void 0) return "";
|
|
2006
2168
|
return source.slice(node.start, node.end);
|
|
2007
2169
|
}
|
|
2008
|
-
function applyEdits(source, edits) {
|
|
2009
|
-
let result = source;
|
|
2010
|
-
for (const edit of [...edits].sort((left, right) => right.start - left.start)) {
|
|
2011
|
-
result = result.slice(0, edit.start) + edit.text + result.slice(edit.end);
|
|
2012
|
-
}
|
|
2013
|
-
return result;
|
|
2014
|
-
}
|
|
2015
2170
|
function applyNamedRules(source, program, fileName = "") {
|
|
2016
2171
|
const edits = [];
|
|
2017
2172
|
const applied = /* @__PURE__ */ new Set();
|
|
2018
2173
|
const asyncify = /* @__PURE__ */ new Set();
|
|
2174
|
+
const refusals = [];
|
|
2175
|
+
const staticImports = [];
|
|
2019
2176
|
const mocked = mockedSpecifiers(program);
|
|
2177
|
+
const methods = methodValues(program);
|
|
2178
|
+
const cannotAwaitHere = (enclosing, what, call) => {
|
|
2179
|
+
if (enclosing === void 0 || !methods.has(enclosing)) return false;
|
|
2180
|
+
const plan2 = planStaticImport(fileName, source, program, call, fileUsesSemicolons(source));
|
|
2181
|
+
if (plan2 !== void 0) {
|
|
2182
|
+
edits.push({ start: plan2.remove.start, end: plan2.remove.end, text: "" });
|
|
2183
|
+
staticImports.push(plan2.line);
|
|
2184
|
+
applied.add(`${what} as a static import`);
|
|
2185
|
+
return true;
|
|
2186
|
+
}
|
|
2187
|
+
refusals.push({
|
|
2188
|
+
binding: what,
|
|
2189
|
+
reason: `\`${what}\` sits inside a class or object METHOD, which cannot become async here: \`async get\` is not valid, and making a method that returns void return a promise changes what every caller gets. Left as it was. Under Vitest \`require\` is Node's own resolver, which knows nothing of \`.ts\`, so this one needs a person: a static import, or the dynamic one kept on purpose.`
|
|
2190
|
+
});
|
|
2191
|
+
return true;
|
|
2192
|
+
};
|
|
2020
2193
|
const wholeStatement = /* @__PURE__ */ new Map();
|
|
2021
2194
|
walk(program, (node) => {
|
|
2022
2195
|
if (node.type !== "ExpressionStatement") return;
|
|
@@ -2073,7 +2246,7 @@ function applyNamedRules(source, program, fileName = "") {
|
|
|
2073
2246
|
}
|
|
2074
2247
|
return;
|
|
2075
2248
|
}
|
|
2076
|
-
if (!
|
|
2249
|
+
if (!MEMBER_TYPES.has(node.type)) return;
|
|
2077
2250
|
const object = node.object;
|
|
2078
2251
|
if (object !== void 0) readsANameOffIt.add(object);
|
|
2079
2252
|
});
|
|
@@ -2084,6 +2257,7 @@ function applyNamedRules(source, program, fileName = "") {
|
|
|
2084
2257
|
const [specifier] = node.arguments ?? [];
|
|
2085
2258
|
const literal = specifier?.type === "StringLiteral" || specifier?.type === "Literal" ? String(specifier.value) : void 0;
|
|
2086
2259
|
if (literal !== void 0 && mocked.has(literal)) {
|
|
2260
|
+
if (cannotAwaitHere(enclosing, "jest.requireMock", node)) return;
|
|
2087
2261
|
edits.push({
|
|
2088
2262
|
start: node.start,
|
|
2089
2263
|
end: node.end,
|
|
@@ -2096,6 +2270,7 @@ function applyNamedRules(source, program, fileName = "") {
|
|
|
2096
2270
|
}
|
|
2097
2271
|
const asyncReplacement = member === void 0 ? void 0 : ASYNC_REPLACEMENTS[member];
|
|
2098
2272
|
if (asyncReplacement !== void 0) {
|
|
2273
|
+
if (cannotAwaitHere(enclosing, `jest.${member}`, node)) return;
|
|
2099
2274
|
edits.push({
|
|
2100
2275
|
start: node.start,
|
|
2101
2276
|
end: node.end,
|
|
@@ -2109,6 +2284,7 @@ function applyNamedRules(source, program, fileName = "") {
|
|
|
2109
2284
|
return;
|
|
2110
2285
|
}
|
|
2111
2286
|
if (bareRequire(node)) {
|
|
2287
|
+
if (cannotAwaitHere(enclosing, "require", node)) return;
|
|
2112
2288
|
const [specifier] = node.arguments ?? [];
|
|
2113
2289
|
const literal = specifier?.type === "StringLiteral" || specifier?.type === "Literal" ? String(specifier.value) : void 0;
|
|
2114
2290
|
const interop = literal !== void 0 && !readsANameOffIt.has(node) && !handedToTheRunnerAsAModule.has(node) && !wholeStatement.has(node) && isCommonJsPackage(fileName, literal) ? ".default" : "";
|
|
@@ -2143,17 +2319,36 @@ function applyNamedRules(source, program, fileName = "") {
|
|
|
2143
2319
|
for (const fn of asyncify) {
|
|
2144
2320
|
edits.push({ start: fn.start, end: fn.start, text: "async " });
|
|
2145
2321
|
}
|
|
2146
|
-
|
|
2322
|
+
if (staticImports.length > 0) {
|
|
2323
|
+
const first = (program.body ?? []).find(
|
|
2324
|
+
(node) => node.type === "ImportDeclaration"
|
|
2325
|
+
);
|
|
2326
|
+
const byModule = /* @__PURE__ */ new Map();
|
|
2327
|
+
for (const line of staticImports) {
|
|
2328
|
+
const parsed = /^import \{ (.+) \} from '(.+)'(;?)$/.exec(line);
|
|
2329
|
+
if (parsed === null) continue;
|
|
2330
|
+
const names = byModule.get(parsed[2]) ?? /* @__PURE__ */ new Set();
|
|
2331
|
+
for (const name of parsed[1].split(", ")) names.add(name);
|
|
2332
|
+
byModule.set(parsed[2], names);
|
|
2333
|
+
}
|
|
2334
|
+
const semi = staticImports[0]?.endsWith(";") === true ? ";" : "";
|
|
2335
|
+
const block = `${[...byModule].map(([specifier, names]) => `import { ${[...names].join(", ")} } from '${specifier}'${semi}`).join("\n")}
|
|
2336
|
+
`;
|
|
2337
|
+
edits.push(
|
|
2338
|
+
first === void 0 ? { start: 0, end: 0, text: `${block}
|
|
2339
|
+
` } : { start: first.start, end: first.start, text: block }
|
|
2340
|
+
);
|
|
2341
|
+
}
|
|
2342
|
+
return { source: applyEdits(source, edits), applied: [...applied].sort(), refusals };
|
|
2147
2343
|
}
|
|
2148
2344
|
|
|
2149
2345
|
// src/roles/test/codemod/isolate-modules.ts
|
|
2150
|
-
var MEMBER_TYPES10 = /* @__PURE__ */ new Set(["MemberExpression", "StaticMemberExpression"]);
|
|
2151
2346
|
var ISOLATORS = /* @__PURE__ */ new Set(["isolateModules", "isolateModulesAsync"]);
|
|
2152
2347
|
var FUNCTIONS2 = /* @__PURE__ */ new Set(["ArrowFunctionExpression", "FunctionExpression"]);
|
|
2153
2348
|
function isolatingCall(node) {
|
|
2154
2349
|
if (node.type !== "CallExpression") return void 0;
|
|
2155
2350
|
const callee = node.callee;
|
|
2156
|
-
if (callee === void 0 || !
|
|
2351
|
+
if (callee === void 0 || !MEMBER_TYPES.has(callee.type)) return void 0;
|
|
2157
2352
|
const object = callee.object;
|
|
2158
2353
|
const property = callee.property;
|
|
2159
2354
|
if (object?.type !== "Identifier" || object.name !== "jest") return void 0;
|
|
@@ -2164,7 +2359,7 @@ function isolatingCall(node) {
|
|
|
2164
2359
|
function unusableIsolatingCall(node) {
|
|
2165
2360
|
if (node.type !== "CallExpression") return void 0;
|
|
2166
2361
|
const callee = node.callee;
|
|
2167
|
-
if (callee === void 0 || !
|
|
2362
|
+
if (callee === void 0 || !MEMBER_TYPES.has(callee.type)) return void 0;
|
|
2168
2363
|
const object = callee.object;
|
|
2169
2364
|
const property = callee.property;
|
|
2170
2365
|
if (object?.type !== "Identifier" || object.name !== "jest") return void 0;
|
|
@@ -2207,19 +2402,15 @@ ${indent}await (${callback})()`
|
|
|
2207
2402
|
for (const fn of asyncify) {
|
|
2208
2403
|
edits.push({ start: fn.start, end: fn.start, text: "async " });
|
|
2209
2404
|
}
|
|
2210
|
-
|
|
2211
|
-
for (const edit of [...edits].sort((left, right) => right.start - left.start)) {
|
|
2212
|
-
result = result.slice(0, edit.start) + edit.text + result.slice(edit.end);
|
|
2213
|
-
}
|
|
2405
|
+
const result = applyEdits(source, edits);
|
|
2214
2406
|
return { source: result, rewritten, refusals };
|
|
2215
2407
|
}
|
|
2216
2408
|
|
|
2217
2409
|
// src/roles/test/codemod/mock-as-value.ts
|
|
2218
|
-
var MEMBER_TYPES11 = /* @__PURE__ */ new Set(["MemberExpression", "StaticMemberExpression"]);
|
|
2219
2410
|
function isViMockCall(node) {
|
|
2220
2411
|
if (node?.type !== "CallExpression") return false;
|
|
2221
2412
|
const callee = node.callee;
|
|
2222
|
-
if (callee === void 0 || !
|
|
2413
|
+
if (callee === void 0 || !MEMBER_TYPES.has(callee.type)) return false;
|
|
2223
2414
|
const object = callee.object;
|
|
2224
2415
|
const property = callee.property;
|
|
2225
2416
|
return object?.type === "Identifier" && object.name === "vi" && property?.type === "Identifier" && (property.name === "mock" || property.name === "doMock");
|
|
@@ -2244,7 +2435,7 @@ function rewriteMockAsValue(source, program) {
|
|
|
2244
2435
|
const memberUses = /* @__PURE__ */ new Map();
|
|
2245
2436
|
const otherUses = /* @__PURE__ */ new Map();
|
|
2246
2437
|
walk(program, (node) => {
|
|
2247
|
-
if (
|
|
2438
|
+
if (MEMBER_TYPES.has(node.type)) {
|
|
2248
2439
|
const object = node.object;
|
|
2249
2440
|
if (object?.type === "Identifier" && bindings.has(object.name)) {
|
|
2250
2441
|
const list = memberUses.get(object.name) ?? [];
|
|
@@ -2282,20 +2473,16 @@ function rewriteMockAsValue(source, program) {
|
|
|
2282
2473
|
}
|
|
2283
2474
|
rewritten += 1;
|
|
2284
2475
|
}
|
|
2285
|
-
|
|
2286
|
-
for (const edit of [...edits].sort((left, right) => right.start - left.start)) {
|
|
2287
|
-
result = result.slice(0, edit.start) + edit.text + result.slice(edit.end);
|
|
2288
|
-
}
|
|
2476
|
+
const result = applyEdits(source, edits);
|
|
2289
2477
|
return { source: result, rewritten, refusals };
|
|
2290
2478
|
}
|
|
2291
2479
|
|
|
2292
2480
|
// src/roles/test/codemod/mock-factory-default.ts
|
|
2293
|
-
var MEMBER_TYPES12 = /* @__PURE__ */ new Set(["MemberExpression", "StaticMemberExpression"]);
|
|
2294
2481
|
var BINDING = "sentinelMockedModule";
|
|
2295
2482
|
function mockCall(node) {
|
|
2296
2483
|
if (node.type !== "CallExpression") return void 0;
|
|
2297
2484
|
const callee = node.callee;
|
|
2298
|
-
if (callee === void 0 || !
|
|
2485
|
+
if (callee === void 0 || !MEMBER_TYPES.has(callee.type)) return void 0;
|
|
2299
2486
|
const property = callee.property;
|
|
2300
2487
|
if (property?.type !== "Identifier" || property.name !== "mock") return void 0;
|
|
2301
2488
|
const object = callee.object;
|
|
@@ -2394,11 +2581,14 @@ function rewriteMockFactoryDefault(source, program, defaultImported) {
|
|
|
2394
2581
|
wrap: true
|
|
2395
2582
|
});
|
|
2396
2583
|
});
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2584
|
+
const result = applyEdits(
|
|
2585
|
+
source,
|
|
2586
|
+
edits.map((edit) => ({
|
|
2587
|
+
start: edit.start,
|
|
2588
|
+
end: edit.end,
|
|
2589
|
+
text: edit.wrap ? `{ const ${BINDING} = ${edit.literal}; return { ...${BINDING}, default: ${BINDING} } }` : edit.literal
|
|
2590
|
+
}))
|
|
2591
|
+
);
|
|
2402
2592
|
return {
|
|
2403
2593
|
source: result,
|
|
2404
2594
|
rewritten: edits.length,
|
|
@@ -2471,19 +2661,15 @@ function rewriteMockPromiseResolve(source, program) {
|
|
|
2471
2661
|
});
|
|
2472
2662
|
}
|
|
2473
2663
|
});
|
|
2474
|
-
|
|
2475
|
-
for (const edit of [...edits].sort((left, right) => right.start - left.start)) {
|
|
2476
|
-
result = `${result.slice(0, edit.start)}${edit.text}${result.slice(edit.end)}`;
|
|
2477
|
-
}
|
|
2664
|
+
const result = applyEdits(source, edits);
|
|
2478
2665
|
return { source: result, rewritten: edits.length };
|
|
2479
2666
|
}
|
|
2480
2667
|
|
|
2481
2668
|
// src/roles/test/codemod/mocked-module-binding.ts
|
|
2482
|
-
var MEMBER_TYPES13 = /* @__PURE__ */ new Set(["MemberExpression", "StaticMemberExpression"]);
|
|
2483
2669
|
function mockedSpecifier(source, node) {
|
|
2484
2670
|
if (node.type !== "CallExpression") return void 0;
|
|
2485
2671
|
const callee = node.callee;
|
|
2486
|
-
if (callee === void 0 || !
|
|
2672
|
+
if (callee === void 0 || !MEMBER_TYPES.has(callee.type)) return void 0;
|
|
2487
2673
|
const object = callee.object;
|
|
2488
2674
|
const property = callee.property;
|
|
2489
2675
|
if (object?.type !== "Identifier") return void 0;
|
|
@@ -2531,17 +2717,13 @@ function annotateMockedBindings(source, program) {
|
|
|
2531
2717
|
});
|
|
2532
2718
|
}
|
|
2533
2719
|
if (edits.length === 0) return { source, rewritten: 0, typeImports: [] };
|
|
2534
|
-
|
|
2535
|
-
for (const edit of [...edits].sort((left, right) => right.start - left.start)) {
|
|
2536
|
-
result = `${result.slice(0, edit.start)}${edit.text}${result.slice(edit.end)}`;
|
|
2537
|
-
}
|
|
2720
|
+
const result = applyEdits(source, edits);
|
|
2538
2721
|
return { source: result, rewritten: edits.length, typeImports: ["Mock"] };
|
|
2539
2722
|
}
|
|
2540
2723
|
|
|
2541
2724
|
// src/roles/test/codemod/propagate-await.ts
|
|
2542
|
-
import { parseSync as
|
|
2725
|
+
import { parseSync as parseSync5 } from "oxc-parser";
|
|
2543
2726
|
var FUNCTIONS3 = /* @__PURE__ */ new Set(["ArrowFunctionExpression", "FunctionExpression", "FunctionDeclaration"]);
|
|
2544
|
-
var MEMBER_TYPES14 = /* @__PURE__ */ new Set(["MemberExpression", "StaticMemberExpression"]);
|
|
2545
2727
|
var ALREADY_A_PROMISE = /* @__PURE__ */ new Set(["then", "catch", "finally"]);
|
|
2546
2728
|
function asyncFunctionNames(program) {
|
|
2547
2729
|
const names = /* @__PURE__ */ new Set();
|
|
@@ -2615,19 +2797,12 @@ function alreadyHandled(call, parent) {
|
|
|
2615
2797
|
if (parent === void 0) return false;
|
|
2616
2798
|
if (parent.type === "AwaitExpression") return true;
|
|
2617
2799
|
if (parent.type === "ReturnStatement" || parent.type === "ArrowFunctionExpression") return true;
|
|
2618
|
-
if (
|
|
2800
|
+
if (MEMBER_TYPES.has(parent.type) && parent.object === call) {
|
|
2619
2801
|
const property = parent.property;
|
|
2620
2802
|
return property?.type === "Identifier" && ALREADY_A_PROMISE.has(property.name);
|
|
2621
2803
|
}
|
|
2622
2804
|
return false;
|
|
2623
2805
|
}
|
|
2624
|
-
function applyEdits2(source, edits) {
|
|
2625
|
-
let result = source;
|
|
2626
|
-
for (const edit of [...edits].sort((left, right) => right.start - left.start)) {
|
|
2627
|
-
result = result.slice(0, edit.start) + edit.text + result.slice(edit.end);
|
|
2628
|
-
}
|
|
2629
|
-
return result;
|
|
2630
|
-
}
|
|
2631
2806
|
function propagateAwait(fileName, source, original, elsewhere = /* @__PURE__ */ new Set()) {
|
|
2632
2807
|
const wasAsync = asyncFunctionNames(original);
|
|
2633
2808
|
let current = source;
|
|
@@ -2635,7 +2810,7 @@ function propagateAwait(fileName, source, original, elsewhere = /* @__PURE__ */
|
|
|
2635
2810
|
for (let round = 0; round < 12; round += 1) {
|
|
2636
2811
|
let parsed;
|
|
2637
2812
|
try {
|
|
2638
|
-
parsed =
|
|
2813
|
+
parsed = parseSync5(fileName, current);
|
|
2639
2814
|
} catch {
|
|
2640
2815
|
return { source: current, rewritten };
|
|
2641
2816
|
}
|
|
@@ -2659,16 +2834,15 @@ function propagateAwait(fileName, source, original, elsewhere = /* @__PURE__ */
|
|
|
2659
2834
|
edits.push({ start: fn.start, end: fn.start, text: "async " });
|
|
2660
2835
|
}
|
|
2661
2836
|
rewritten += edits.length - asyncify.size;
|
|
2662
|
-
current =
|
|
2837
|
+
current = applyEdits(current, edits);
|
|
2663
2838
|
}
|
|
2664
2839
|
return { source: current, rewritten };
|
|
2665
2840
|
}
|
|
2666
2841
|
|
|
2667
2842
|
// src/roles/test/codemod/reexport-barrel-mock.ts
|
|
2668
|
-
import { readFileSync as
|
|
2843
|
+
import { readFileSync as readFileSync10, readdirSync as readdirSync2, statSync as statSync2 } from "node:fs";
|
|
2669
2844
|
import { createRequire as createRequire3 } from "node:module";
|
|
2670
|
-
import { dirname as
|
|
2671
|
-
var MEMBER_TYPES15 = /* @__PURE__ */ new Set(["MemberExpression", "StaticMemberExpression"]);
|
|
2845
|
+
import { dirname as dirname4, join as join12 } from "node:path";
|
|
2672
2846
|
var PACKAGE_SUBPATH = /^(@[^/]+\/[^/]+|[^@.][^/]*)\/(.+)$/;
|
|
2673
2847
|
var PURE_REEXPORT = /^module\.exports\s*=\s*require\(\s*(['"])([^'"]+)\1\s*\)\s*;?$/;
|
|
2674
2848
|
function mockCalls(program) {
|
|
@@ -2676,7 +2850,7 @@ function mockCalls(program) {
|
|
|
2676
2850
|
walk(program, (node) => {
|
|
2677
2851
|
if (node.type !== "CallExpression") return;
|
|
2678
2852
|
const callee = node.callee;
|
|
2679
|
-
if (callee === void 0 || !
|
|
2853
|
+
if (callee === void 0 || !MEMBER_TYPES.has(callee.type)) return;
|
|
2680
2854
|
const object = callee.object;
|
|
2681
2855
|
const property = callee.property;
|
|
2682
2856
|
if (object?.type !== "Identifier") return;
|
|
@@ -2696,7 +2870,7 @@ function mockCalls(program) {
|
|
|
2696
2870
|
}
|
|
2697
2871
|
function packageRoot(fromFile, name) {
|
|
2698
2872
|
try {
|
|
2699
|
-
return
|
|
2873
|
+
return dirname4(createRequire3(fromFile).resolve(`${name}/package.json`));
|
|
2700
2874
|
} catch {
|
|
2701
2875
|
return void 0;
|
|
2702
2876
|
}
|
|
@@ -2720,11 +2894,11 @@ function barrelsFor(fromFile, name, target) {
|
|
|
2720
2894
|
const aliases = [];
|
|
2721
2895
|
for (const entry of entries) {
|
|
2722
2896
|
if (!entry.endsWith(".js")) continue;
|
|
2723
|
-
const path =
|
|
2897
|
+
const path = join12(root, entry);
|
|
2724
2898
|
let body;
|
|
2725
2899
|
try {
|
|
2726
|
-
if (!
|
|
2727
|
-
body =
|
|
2900
|
+
if (!statSync2(path).isFile()) continue;
|
|
2901
|
+
body = readFileSync10(path, "utf8");
|
|
2728
2902
|
} catch {
|
|
2729
2903
|
continue;
|
|
2730
2904
|
}
|
|
@@ -2764,7 +2938,7 @@ ${text}` });
|
|
|
2764
2938
|
}
|
|
2765
2939
|
|
|
2766
2940
|
// src/roles/test/codemod/repoint-msw.ts
|
|
2767
|
-
import { parseSync as
|
|
2941
|
+
import { parseSync as parseSync6 } from "oxc-parser";
|
|
2768
2942
|
var SENTINEL_MSW_SERVER = "@hublo/sentinel/test/msw";
|
|
2769
2943
|
var SENTINEL_MSW_API = "@hublo/sentinel/test/tools/msw";
|
|
2770
2944
|
var MSW_PACKAGE = /^msw$/;
|
|
@@ -2777,7 +2951,7 @@ function importsServer(declaration) {
|
|
|
2777
2951
|
});
|
|
2778
2952
|
}
|
|
2779
2953
|
function repointMswServer(fileName, source) {
|
|
2780
|
-
const { program, errors } =
|
|
2954
|
+
const { program, errors } = parseSync6(fileName, source, { sourceType: "module" });
|
|
2781
2955
|
if (errors.length > 0) return { source, repointed: false };
|
|
2782
2956
|
const edits = [];
|
|
2783
2957
|
walk(program, (node) => {
|
|
@@ -2794,26 +2968,28 @@ function repointMswServer(fileName, source) {
|
|
|
2794
2968
|
});
|
|
2795
2969
|
});
|
|
2796
2970
|
if (edits.length === 0) return { source, repointed: false };
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2971
|
+
const rewritten = applyEdits(
|
|
2972
|
+
source,
|
|
2973
|
+
edits.map((edit) => {
|
|
2974
|
+
const quote = source[edit.start] === '"' ? '"' : "'";
|
|
2975
|
+
return { start: edit.start, end: edit.end, text: `${quote}${edit.to}${quote}` };
|
|
2976
|
+
})
|
|
2977
|
+
);
|
|
2802
2978
|
return { source: rewritten, repointed: true };
|
|
2803
2979
|
}
|
|
2804
2980
|
|
|
2805
2981
|
// src/roles/test/codemod/setup-static-imports.ts
|
|
2806
|
-
import { dirname as
|
|
2982
|
+
import { dirname as dirname6, resolve as resolve6 } from "node:path";
|
|
2807
2983
|
|
|
2808
2984
|
// src/core/context.ts
|
|
2809
2985
|
import { existsSync as existsSync11 } from "node:fs";
|
|
2810
|
-
import { dirname as
|
|
2986
|
+
import { dirname as dirname5, join as join14, resolve as resolve4 } from "node:path";
|
|
2811
2987
|
|
|
2812
2988
|
// src/core/discover-modules.ts
|
|
2813
2989
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
2814
|
-
import { mkdtempSync as mkdtempSync2, readFileSync as
|
|
2990
|
+
import { mkdtempSync as mkdtempSync2, readFileSync as readFileSync11, rmSync as rmSync2 } from "node:fs";
|
|
2815
2991
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
2816
|
-
import { join as
|
|
2992
|
+
import { join as join13 } from "node:path";
|
|
2817
2993
|
function runNx(cwd, args) {
|
|
2818
2994
|
const nx = resolveBin(cwd, "nx") ?? "nx";
|
|
2819
2995
|
try {
|
|
@@ -2831,11 +3007,11 @@ function runNx(cwd, args) {
|
|
|
2831
3007
|
}
|
|
2832
3008
|
}
|
|
2833
3009
|
function readGraph(cwd) {
|
|
2834
|
-
const dir = mkdtempSync2(
|
|
2835
|
-
const file =
|
|
3010
|
+
const dir = mkdtempSync2(join13(tmpdir2(), "sentinel-nx-"));
|
|
3011
|
+
const file = join13(dir, "graph.json");
|
|
2836
3012
|
try {
|
|
2837
3013
|
runNx(cwd, ["graph", "--file", file]);
|
|
2838
|
-
const parsed = JSON.parse(
|
|
3014
|
+
const parsed = JSON.parse(readFileSync11(file, "utf8"));
|
|
2839
3015
|
const nodes = parsed.graph?.nodes;
|
|
2840
3016
|
if (!nodes || typeof nodes !== "object") {
|
|
2841
3017
|
throw new Error(
|
|
@@ -2844,38 +3020,61 @@ function readGraph(cwd) {
|
|
|
2844
3020
|
}
|
|
2845
3021
|
return Object.entries(nodes).map(([name, node]) => ({
|
|
2846
3022
|
name,
|
|
2847
|
-
root:
|
|
3023
|
+
root: join13(cwd, node.data.root)
|
|
2848
3024
|
}));
|
|
2849
3025
|
} finally {
|
|
2850
3026
|
rmSync2(dir, { recursive: true, force: true });
|
|
2851
3027
|
}
|
|
2852
3028
|
}
|
|
3029
|
+
function parseProjectNames(raw) {
|
|
3030
|
+
const asNames = (text) => {
|
|
3031
|
+
try {
|
|
3032
|
+
const parsed = JSON.parse(text);
|
|
3033
|
+
return Array.isArray(parsed) && parsed.every((one) => typeof one === "string") ? parsed : void 0;
|
|
3034
|
+
} catch {
|
|
3035
|
+
return void 0;
|
|
3036
|
+
}
|
|
3037
|
+
};
|
|
3038
|
+
const end = raw.lastIndexOf("]");
|
|
3039
|
+
if (end === -1) return void 0;
|
|
3040
|
+
for (let start = raw.indexOf("["); start !== -1 && start < end; start = raw.indexOf("[", start + 1)) {
|
|
3041
|
+
const names = asNames(raw.slice(start, end + 1));
|
|
3042
|
+
if (names !== void 0) return names;
|
|
3043
|
+
}
|
|
3044
|
+
return void 0;
|
|
3045
|
+
}
|
|
2853
3046
|
function discoverModules(cwd, options = {}) {
|
|
2854
3047
|
const modules = readGraph(cwd);
|
|
2855
3048
|
if (!options.affected) return modules;
|
|
2856
|
-
const
|
|
2857
|
-
|
|
2858
|
-
)
|
|
3049
|
+
const raw = runNx(cwd, ["show", "projects", "--affected", "--json"]);
|
|
3050
|
+
const names = parseProjectNames(raw);
|
|
3051
|
+
if (names === void 0) {
|
|
3052
|
+
throw new Error(
|
|
3053
|
+
`sentinel: could not read the affected projects from nx. It answered:
|
|
3054
|
+
${raw.slice(0, 300)}`
|
|
3055
|
+
);
|
|
3056
|
+
}
|
|
3057
|
+
const affected = new Set(names);
|
|
2859
3058
|
return modules.filter((module) => affected.has(module.name));
|
|
2860
3059
|
}
|
|
2861
3060
|
|
|
2862
3061
|
// src/core/context.ts
|
|
2863
3062
|
var MODULE_MARKERS = ["package.json", "project.json"];
|
|
2864
3063
|
function isModuleDir(cwd) {
|
|
2865
|
-
return MODULE_MARKERS.some((marker) => existsSync11(
|
|
3064
|
+
return MODULE_MARKERS.some((marker) => existsSync11(join14(cwd, marker)));
|
|
2866
3065
|
}
|
|
2867
3066
|
function findModuleRoot(startDir, workspaceRoot) {
|
|
2868
|
-
let dir =
|
|
3067
|
+
let dir = resolve4(startDir);
|
|
2869
3068
|
for (; ; ) {
|
|
2870
|
-
if (workspaceRoot !== void 0 && dir ===
|
|
3069
|
+
if (workspaceRoot !== void 0 && dir === resolve4(workspaceRoot)) return void 0;
|
|
2871
3070
|
if (isModuleDir(dir)) return dir;
|
|
2872
|
-
const parent =
|
|
3071
|
+
const parent = dirname5(dir);
|
|
2873
3072
|
if (parent === dir) return void 0;
|
|
2874
3073
|
dir = parent;
|
|
2875
3074
|
}
|
|
2876
3075
|
}
|
|
2877
3076
|
function resolveContext(cwd, opts) {
|
|
2878
|
-
const atRoot = existsSync11(
|
|
3077
|
+
const atRoot = existsSync11(join14(cwd, WORKSPACE_ROOT_MARKER));
|
|
2879
3078
|
if (!atRoot && isModuleDir(cwd)) {
|
|
2880
3079
|
if (opts.module) {
|
|
2881
3080
|
throw new Error(
|
|
@@ -2903,16 +3102,16 @@ function resolveContext(cwd, opts) {
|
|
|
2903
3102
|
}
|
|
2904
3103
|
|
|
2905
3104
|
// src/roles/test/codemod/workspace-specifier.ts
|
|
2906
|
-
import { existsSync as existsSync12, readFileSync as
|
|
2907
|
-
import { join as
|
|
2908
|
-
var
|
|
3105
|
+
import { existsSync as existsSync12, readFileSync as readFileSync12 } from "node:fs";
|
|
3106
|
+
import { join as join15, relative as relative2, resolve as resolve5 } from "node:path";
|
|
3107
|
+
var EXTENSIONS2 = ["", ".ts", ".tsx", ".js", ".jsx", ".mts", ".cts", "/index.ts", "/index.js"];
|
|
2909
3108
|
function pathEntries(workspaceRoot) {
|
|
2910
|
-
const file =
|
|
3109
|
+
const file = join15(workspaceRoot, "tsconfig.base.json");
|
|
2911
3110
|
if (!existsSync12(file)) return [];
|
|
2912
3111
|
let paths;
|
|
2913
3112
|
try {
|
|
2914
3113
|
paths = parseJsonc(
|
|
2915
|
-
|
|
3114
|
+
readFileSync12(file, "utf8"),
|
|
2916
3115
|
"tsconfig.base.json"
|
|
2917
3116
|
)?.compilerOptions?.paths;
|
|
2918
3117
|
} catch {
|
|
@@ -2925,17 +3124,17 @@ function pathEntries(workspaceRoot) {
|
|
|
2925
3124
|
const wildcard = key.endsWith("/*") && target.endsWith("/*");
|
|
2926
3125
|
entries.push({
|
|
2927
3126
|
key: wildcard ? key.slice(0, -2) : key,
|
|
2928
|
-
target:
|
|
3127
|
+
target: resolve5(workspaceRoot, wildcard ? target.slice(0, -2) : target),
|
|
2929
3128
|
wildcard
|
|
2930
3129
|
});
|
|
2931
3130
|
}
|
|
2932
3131
|
return entries.sort((left, right) => right.target.length - left.target.length);
|
|
2933
3132
|
}
|
|
2934
3133
|
function workspaceSpecifier(workspaceRoot, file) {
|
|
2935
|
-
const absolute =
|
|
3134
|
+
const absolute = resolve5(file);
|
|
2936
3135
|
for (const entry of pathEntries(workspaceRoot)) {
|
|
2937
3136
|
if (!entry.wildcard) {
|
|
2938
|
-
if (
|
|
3137
|
+
if (EXTENSIONS2.some((extension) => `${entry.target}${extension}` === absolute)) {
|
|
2939
3138
|
return entry.key;
|
|
2940
3139
|
}
|
|
2941
3140
|
continue;
|
|
@@ -2961,9 +3160,9 @@ function requireCall(source, node) {
|
|
|
2961
3160
|
}
|
|
2962
3161
|
function importable(written, fileName, workspaceRoot) {
|
|
2963
3162
|
if (!written.startsWith(".")) return written;
|
|
2964
|
-
const fileDir =
|
|
3163
|
+
const fileDir = dirname6(fileName);
|
|
2965
3164
|
const moduleRoot = findModuleRoot(fileDir, workspaceRoot) ?? fileDir;
|
|
2966
|
-
const target =
|
|
3165
|
+
const target = resolve6(fileDir, written);
|
|
2967
3166
|
if (target.startsWith(`${moduleRoot}/`)) return written;
|
|
2968
3167
|
if (workspaceRoot === void 0) return void 0;
|
|
2969
3168
|
return workspaceSpecifier(workspaceRoot, target);
|
|
@@ -3009,10 +3208,7 @@ function rewriteSetupStaticImports(fileName, source, program, workspaceRoot) {
|
|
|
3009
3208
|
if (text === void 0) break;
|
|
3010
3209
|
edits.push({ start: node.start, end: node.end, text });
|
|
3011
3210
|
}
|
|
3012
|
-
|
|
3013
|
-
for (const edit of [...edits].sort((left, right) => right.start - left.start)) {
|
|
3014
|
-
result = `${result.slice(0, edit.start)}${edit.text}${result.slice(edit.end)}`;
|
|
3015
|
-
}
|
|
3211
|
+
const result = applyEdits(source, edits);
|
|
3016
3212
|
return { source: result, rewritten: edits.length, refusals };
|
|
3017
3213
|
}
|
|
3018
3214
|
|
|
@@ -3020,7 +3216,6 @@ function rewriteSetupStaticImports(fileName, source, program, workspaceRoot) {
|
|
|
3020
3216
|
var SPY_TYPES = /* @__PURE__ */ new Set(["SpyInstance"]);
|
|
3021
3217
|
var QUALIFIED_ONLY = /* @__PURE__ */ new Set(["Mock"]);
|
|
3022
3218
|
var VITEST_NAME = { SpyInstance: "MockInstance", Mock: "Mock" };
|
|
3023
|
-
var MEMBER_TYPES16 = /* @__PURE__ */ new Set(["MemberExpression", "StaticMemberExpression"]);
|
|
3024
3219
|
function typeNameOf(source, node) {
|
|
3025
3220
|
const name = node.typeName;
|
|
3026
3221
|
if (name === void 0) return void 0;
|
|
@@ -3048,10 +3243,7 @@ function rewriteSpyInstanceType(source, program) {
|
|
|
3048
3243
|
imports: target
|
|
3049
3244
|
});
|
|
3050
3245
|
});
|
|
3051
|
-
|
|
3052
|
-
for (const edit of [...edits].sort((left, right) => right.start - left.start)) {
|
|
3053
|
-
result = `${result.slice(0, edit.start)}${edit.text}${result.slice(edit.end)}`;
|
|
3054
|
-
}
|
|
3246
|
+
const result = applyEdits(source, edits);
|
|
3055
3247
|
return {
|
|
3056
3248
|
source: result,
|
|
3057
3249
|
rewritten: edits.length,
|
|
@@ -3064,7 +3256,7 @@ function rewriteMockFactoryGenerics(source, program) {
|
|
|
3064
3256
|
walk(program, (node) => {
|
|
3065
3257
|
if (node.type !== "CallExpression") return;
|
|
3066
3258
|
const callee = node.callee;
|
|
3067
|
-
if (callee === void 0 || !
|
|
3259
|
+
if (callee === void 0 || !MEMBER_TYPES.has(callee.type)) return;
|
|
3068
3260
|
const object = callee.object;
|
|
3069
3261
|
const property = callee.property;
|
|
3070
3262
|
if (object?.type !== "Identifier" || object.name !== "jest") return;
|
|
@@ -3079,10 +3271,7 @@ function rewriteMockFactoryGenerics(source, program) {
|
|
|
3079
3271
|
text: `<(...args: ${text(args[1])}) => ${text(args[0])}>`
|
|
3080
3272
|
});
|
|
3081
3273
|
});
|
|
3082
|
-
|
|
3083
|
-
for (const edit of [...edits].sort((left, right) => right.start - left.start)) {
|
|
3084
|
-
result = `${result.slice(0, edit.start)}${edit.text}${result.slice(edit.end)}`;
|
|
3085
|
-
}
|
|
3274
|
+
const result = applyEdits(source, edits);
|
|
3086
3275
|
return { source: result, rewritten: edits.length, typeImports: [] };
|
|
3087
3276
|
}
|
|
3088
3277
|
|
|
@@ -3103,8 +3292,8 @@ function mockFactories(program) {
|
|
|
3103
3292
|
});
|
|
3104
3293
|
return factories;
|
|
3105
3294
|
}
|
|
3106
|
-
function
|
|
3107
|
-
const { program, errors } =
|
|
3295
|
+
function parse2(fileName, source) {
|
|
3296
|
+
const { program, errors } = parseSync7(fileName, source, { sourceType: "module" });
|
|
3108
3297
|
return errors.length > 0 ? void 0 : program;
|
|
3109
3298
|
}
|
|
3110
3299
|
function migrateTestFile(fileName, source, defaultImported = /* @__PURE__ */ new Set(), asyncHelpers = /* @__PURE__ */ new Set(), modulesOwnMsw = false) {
|
|
@@ -3128,66 +3317,66 @@ function migrateTestFile(fileName, source, defaultImported = /* @__PURE__ */ new
|
|
|
3128
3317
|
}
|
|
3129
3318
|
]
|
|
3130
3319
|
});
|
|
3131
|
-
const beforeStatic =
|
|
3320
|
+
const beforeStatic = parse2(fileName, source);
|
|
3132
3321
|
if (beforeStatic === void 0) return unparsable("reading the file");
|
|
3133
3322
|
const statics = rewriteSetupStaticImports(
|
|
3134
3323
|
fileName,
|
|
3135
3324
|
source,
|
|
3136
3325
|
beforeStatic,
|
|
3137
|
-
findWorkspaceRoot(
|
|
3326
|
+
findWorkspaceRoot(dirname7(fileName))
|
|
3138
3327
|
);
|
|
3139
3328
|
source = statics.source;
|
|
3140
|
-
const original = statics.rewritten === 0 ? beforeStatic :
|
|
3329
|
+
const original = statics.rewritten === 0 ? beforeStatic : parse2(fileName, source);
|
|
3141
3330
|
if (original === void 0) return unparsable("hoisting the setup requires");
|
|
3142
3331
|
const titles = rewriteEachTitles(source, original);
|
|
3143
3332
|
const tables = rewriteEachTableRows(titles.source, original);
|
|
3144
|
-
const afterTables =
|
|
3333
|
+
const afterTables = parse2(fileName, tables.source);
|
|
3145
3334
|
if (afterTables === void 0) return unparsable("each table rows");
|
|
3146
3335
|
const spyTypes = rewriteSpyInstanceType(tables.source, afterTables);
|
|
3147
|
-
const afterSpyTypes =
|
|
3336
|
+
const afterSpyTypes = parse2(fileName, spyTypes.source);
|
|
3148
3337
|
if (afterSpyTypes === void 0) return unparsable("SpyInstance types");
|
|
3149
3338
|
const factoryGenerics = rewriteMockFactoryGenerics(spyTypes.source, afterSpyTypes);
|
|
3150
|
-
const afterFactoryGenerics =
|
|
3339
|
+
const afterFactoryGenerics = parse2(fileName, factoryGenerics.source);
|
|
3151
3340
|
if (afterFactoryGenerics === void 0) return unparsable("mock factory generics");
|
|
3152
3341
|
const ruled = applyNamedRules(factoryGenerics.source, afterFactoryGenerics, fileName);
|
|
3153
3342
|
const renamed = renameJestToVitest(fileName, ruled.source);
|
|
3154
|
-
const afterRename =
|
|
3343
|
+
const afterRename = parse2(fileName, renamed.source);
|
|
3155
3344
|
if (afterRename === void 0) return unparsable("jest to vi rename");
|
|
3156
3345
|
const fakeTimers = rewriteFakeTimerOptions(renamed.source, afterRename);
|
|
3157
|
-
const afterFakeTimers =
|
|
3346
|
+
const afterFakeTimers = parse2(fileName, fakeTimers.source);
|
|
3158
3347
|
if (afterFakeTimers === void 0) return unparsable("fake timer options");
|
|
3159
3348
|
const mocks = rewriteMockAsValue(fakeTimers.source, afterFakeTimers);
|
|
3160
|
-
const afterMocks =
|
|
3349
|
+
const afterMocks = parse2(fileName, mocks.source);
|
|
3161
3350
|
if (afterMocks === void 0) return unparsable("mock as a value");
|
|
3162
3351
|
const constructible = rewriteConstructibleMocks(
|
|
3163
3352
|
mocks.source,
|
|
3164
3353
|
afterMocks,
|
|
3165
3354
|
mockFactories(afterMocks)
|
|
3166
3355
|
);
|
|
3167
|
-
const afterConstructible =
|
|
3356
|
+
const afterConstructible = parse2(fileName, constructible.source);
|
|
3168
3357
|
if (afterConstructible === void 0) return unparsable("constructible mocks");
|
|
3169
3358
|
const factoryDefault = rewriteMockFactoryDefault(
|
|
3170
3359
|
constructible.source,
|
|
3171
3360
|
afterConstructible,
|
|
3172
3361
|
defaultImported
|
|
3173
3362
|
);
|
|
3174
|
-
const beforeReturnValue =
|
|
3363
|
+
const beforeReturnValue = parse2(fileName, factoryDefault.source);
|
|
3175
3364
|
if (beforeReturnValue === void 0) return unparsable("mock factory default");
|
|
3176
3365
|
const returnValue = rewriteAssertionReturnValue(factoryDefault.source, beforeReturnValue);
|
|
3177
|
-
const afterReturnValue =
|
|
3366
|
+
const afterReturnValue = parse2(fileName, returnValue.source);
|
|
3178
3367
|
if (afterReturnValue === void 0) return unparsable("assertion return value");
|
|
3179
3368
|
const isolated = rewriteIsolateModules(returnValue.source, afterReturnValue);
|
|
3180
|
-
const afterIsolate =
|
|
3369
|
+
const afterIsolate = parse2(fileName, isolated.source);
|
|
3181
3370
|
if (afterIsolate === void 0) return unparsable("isolate modules");
|
|
3182
3371
|
const emptyImplementations = rewriteEmptyMockImplementation(isolated.source, afterIsolate);
|
|
3183
|
-
const afterEmpty =
|
|
3372
|
+
const afterEmpty = parse2(fileName, emptyImplementations.source);
|
|
3184
3373
|
if (afterEmpty === void 0) return unparsable("empty mock implementation");
|
|
3185
3374
|
const hooks = rewriteHookReturnValue(emptyImplementations.source, afterEmpty);
|
|
3186
|
-
const afterHooks =
|
|
3375
|
+
const afterHooks = parse2(fileName, hooks.source);
|
|
3187
3376
|
if (afterHooks === void 0) return unparsable("hook return value");
|
|
3188
3377
|
const promises = rewriteMockPromiseResolve(hooks.source, afterHooks);
|
|
3189
3378
|
const awaited = propagateAwait(fileName, promises.source, original, asyncHelpers);
|
|
3190
|
-
const program =
|
|
3379
|
+
const program = parse2(fileName, awaited.source);
|
|
3191
3380
|
if (program === void 0) return unparsable("hook body");
|
|
3192
3381
|
const hoist = hoistCapturedBindings(
|
|
3193
3382
|
awaited.source,
|
|
@@ -3196,10 +3385,10 @@ function migrateTestFile(fileName, source, defaultImported = /* @__PURE__ */ new
|
|
|
3196
3385
|
moduleBindings(program),
|
|
3197
3386
|
importedNames(program)
|
|
3198
3387
|
);
|
|
3199
|
-
const afterHoist =
|
|
3388
|
+
const afterHoist = parse2(fileName, hoist.source);
|
|
3200
3389
|
if (afterHoist === void 0) return unparsable("hoisting captured bindings");
|
|
3201
3390
|
const mockedBindings = annotateMockedBindings(hoist.source, afterHoist);
|
|
3202
|
-
const afterBindings =
|
|
3391
|
+
const afterBindings = parse2(fileName, mockedBindings.source);
|
|
3203
3392
|
if (afterBindings === void 0) return unparsable("mocked module bindings");
|
|
3204
3393
|
const bareFactories = invokeBareMockFactories(mockedBindings.source, afterBindings);
|
|
3205
3394
|
const withImport = injectTypeImport(fileName, bareFactories.source, [
|
|
@@ -3209,7 +3398,7 @@ function migrateTestFile(fileName, source, defaultImported = /* @__PURE__ */ new
|
|
|
3209
3398
|
]);
|
|
3210
3399
|
const deep = normaliseDeepImports(withImport);
|
|
3211
3400
|
const repointed = modulesOwnMsw ? { source: deep.source, repointed: false } : repointMswServer(fileName, deep.source);
|
|
3212
|
-
const finalProgram =
|
|
3401
|
+
const finalProgram = parse2(fileName, repointed.source);
|
|
3213
3402
|
if (finalProgram === void 0) return unparsable("msw server import");
|
|
3214
3403
|
const barrels = rewriteReexportBarrelMocks(fileName, repointed.source, finalProgram);
|
|
3215
3404
|
return {
|
|
@@ -3249,7 +3438,8 @@ function migrateTestFile(fileName, source, defaultImported = /* @__PURE__ */ new
|
|
|
3249
3438
|
...hoist.refusals,
|
|
3250
3439
|
...mocks.refusals.map((refusal) => ({ binding: refusal.binding, reason: refusal.reason })),
|
|
3251
3440
|
...constructible.refusals,
|
|
3252
|
-
...isolated.refusals
|
|
3441
|
+
...isolated.refusals,
|
|
3442
|
+
...ruled.refusals
|
|
3253
3443
|
],
|
|
3254
3444
|
warnings: fakeTimers.warnings,
|
|
3255
3445
|
mswRepointed: repointed.repointed
|
|
@@ -3257,13 +3447,13 @@ function migrateTestFile(fileName, source, defaultImported = /* @__PURE__ */ new
|
|
|
3257
3447
|
}
|
|
3258
3448
|
|
|
3259
3449
|
// src/roles/test/codemod/test-support-files.ts
|
|
3260
|
-
import { existsSync as existsSync13, readFileSync as
|
|
3261
|
-
import { dirname as
|
|
3450
|
+
import { existsSync as existsSync13, readFileSync as readFileSync13, readdirSync as readdirSync3, statSync as statSync3 } from "node:fs";
|
|
3451
|
+
import { dirname as dirname8, join as join16, relative as relative3, resolve as resolve7 } from "node:path";
|
|
3262
3452
|
var SKIPPED = /* @__PURE__ */ new Set(["node_modules", "dist", "coverage", ".git", ".vite"]);
|
|
3263
3453
|
var TEST_FILE2 = /\.(spec|test)\.[cm]?[jt]sx?$/;
|
|
3264
3454
|
var SOURCE_FILE = /\.[cm]?[jt]sx?$/;
|
|
3265
|
-
var
|
|
3266
|
-
function
|
|
3455
|
+
var EXTENSIONS3 = [".ts", ".tsx", ".js", ".jsx", ".mts", ".cts"];
|
|
3456
|
+
function relativeSpecifiers2(source) {
|
|
3267
3457
|
const found = [];
|
|
3268
3458
|
const patterns = [
|
|
3269
3459
|
/\bfrom\s+['"](\.[^'"]*)['"]/g,
|
|
@@ -3277,13 +3467,13 @@ function relativeSpecifiers(source) {
|
|
|
3277
3467
|
return found;
|
|
3278
3468
|
}
|
|
3279
3469
|
function resolveSpecifier(fromFile, specifier) {
|
|
3280
|
-
const base =
|
|
3281
|
-
if (existsSync13(base) &&
|
|
3282
|
-
for (const extension of
|
|
3470
|
+
const base = resolve7(dirname8(fromFile), specifier);
|
|
3471
|
+
if (existsSync13(base) && statSync3(base).isFile()) return base;
|
|
3472
|
+
for (const extension of EXTENSIONS3) {
|
|
3283
3473
|
if (existsSync13(`${base}${extension}`)) return `${base}${extension}`;
|
|
3284
3474
|
}
|
|
3285
|
-
for (const extension of
|
|
3286
|
-
const index =
|
|
3475
|
+
for (const extension of EXTENSIONS3) {
|
|
3476
|
+
const index = join16(base, `index${extension}`);
|
|
3287
3477
|
if (existsSync13(index)) return index;
|
|
3288
3478
|
}
|
|
3289
3479
|
return void 0;
|
|
@@ -3301,9 +3491,9 @@ function moduleSources(cwd) {
|
|
|
3301
3491
|
}
|
|
3302
3492
|
for (const entry of entries) {
|
|
3303
3493
|
if (entry.isDirectory()) {
|
|
3304
|
-
if (!SKIPPED.has(entry.name)) stack.push(
|
|
3494
|
+
if (!SKIPPED.has(entry.name)) stack.push(join16(dir, entry.name));
|
|
3305
3495
|
} else if (SOURCE_FILE.test(entry.name)) {
|
|
3306
|
-
found.push(
|
|
3496
|
+
found.push(join16(dir, entry.name));
|
|
3307
3497
|
}
|
|
3308
3498
|
}
|
|
3309
3499
|
}
|
|
@@ -3311,7 +3501,7 @@ function moduleSources(cwd) {
|
|
|
3311
3501
|
}
|
|
3312
3502
|
function read(path) {
|
|
3313
3503
|
try {
|
|
3314
|
-
return
|
|
3504
|
+
return readFileSync13(path, "utf8");
|
|
3315
3505
|
} catch {
|
|
3316
3506
|
return void 0;
|
|
3317
3507
|
}
|
|
@@ -3320,7 +3510,7 @@ function setupFilesInside(cwd, named) {
|
|
|
3320
3510
|
const kept = [];
|
|
3321
3511
|
for (const raw of named) {
|
|
3322
3512
|
const withoutToken = raw.replaceAll("<rootDir>/", "").replaceAll("<rootDir>", ".");
|
|
3323
|
-
const full =
|
|
3513
|
+
const full = resolve7(cwd, withoutToken);
|
|
3324
3514
|
const inside = relative3(cwd, full);
|
|
3325
3515
|
if (inside.startsWith("..") || inside === "") continue;
|
|
3326
3516
|
if (!existsSync13(full)) continue;
|
|
@@ -3337,7 +3527,7 @@ function listTestSupportFiles(cwd, setupFiles = []) {
|
|
|
3337
3527
|
}
|
|
3338
3528
|
const importedBy = /* @__PURE__ */ new Map();
|
|
3339
3529
|
for (const [file, source] of contents) {
|
|
3340
|
-
for (const specifier of
|
|
3530
|
+
for (const specifier of relativeSpecifiers2(source)) {
|
|
3341
3531
|
const target = resolveSpecifier(file, specifier);
|
|
3342
3532
|
if (target === void 0 || !contents.has(target)) continue;
|
|
3343
3533
|
importedBy.set(target, [...importedBy.get(target) ?? [], file]);
|
|
@@ -3350,7 +3540,7 @@ function listTestSupportFiles(cwd, setupFiles = []) {
|
|
|
3350
3540
|
);
|
|
3351
3541
|
while (queue.length > 0) {
|
|
3352
3542
|
const file = queue.shift();
|
|
3353
|
-
for (const specifier of
|
|
3543
|
+
for (const specifier of relativeSpecifiers2(contents.get(file) ?? "")) {
|
|
3354
3544
|
const target = resolveSpecifier(file, specifier);
|
|
3355
3545
|
if (target === void 0 || TEST_FILE2.test(target) || testOnly.has(target)) continue;
|
|
3356
3546
|
if (!isTestOnly(target)) continue;
|
|
@@ -3363,13 +3553,13 @@ function listTestSupportFiles(cwd, setupFiles = []) {
|
|
|
3363
3553
|
}
|
|
3364
3554
|
|
|
3365
3555
|
// src/roles/test/codemod/migrate-module.ts
|
|
3366
|
-
function
|
|
3367
|
-
const { program, errors } =
|
|
3556
|
+
function parse3(source) {
|
|
3557
|
+
const { program, errors } = parseSync8("file.ts", source, { sourceType: "module" });
|
|
3368
3558
|
return errors.length > 0 ? void 0 : program;
|
|
3369
3559
|
}
|
|
3370
3560
|
function read2(path) {
|
|
3371
3561
|
try {
|
|
3372
|
-
return
|
|
3562
|
+
return readFileSync14(path, "utf8");
|
|
3373
3563
|
} catch {
|
|
3374
3564
|
return void 0;
|
|
3375
3565
|
}
|
|
@@ -3387,10 +3577,10 @@ function defaultImportedSpecifiers(cwd) {
|
|
|
3387
3577
|
}
|
|
3388
3578
|
for (const entry of entries) {
|
|
3389
3579
|
if (SKIPPED2.has(entry)) continue;
|
|
3390
|
-
const path =
|
|
3580
|
+
const path = join17(dir, entry);
|
|
3391
3581
|
let directory;
|
|
3392
3582
|
try {
|
|
3393
|
-
directory =
|
|
3583
|
+
directory = statSync4(path).isDirectory();
|
|
3394
3584
|
} catch {
|
|
3395
3585
|
continue;
|
|
3396
3586
|
}
|
|
@@ -3418,23 +3608,33 @@ function migrateModuleTests(cwd, setupFiles = []) {
|
|
|
3418
3608
|
const defaultImported = defaultImportedSpecifiers(cwd);
|
|
3419
3609
|
const asyncHelpers = /* @__PURE__ */ new Set();
|
|
3420
3610
|
for (const relative6 of listTestSupportFiles(cwd, setupFiles)) {
|
|
3421
|
-
const source = read2(
|
|
3611
|
+
const source = read2(join17(cwd, relative6));
|
|
3422
3612
|
if (source === void 0) {
|
|
3423
3613
|
blockers.push({ file: relative6, reason: "this file could not be read" });
|
|
3424
3614
|
continue;
|
|
3425
3615
|
}
|
|
3426
3616
|
const migrated = migrateTestFile(
|
|
3427
|
-
|
|
3617
|
+
join17(cwd, relative6),
|
|
3428
3618
|
source,
|
|
3429
3619
|
defaultImported,
|
|
3430
3620
|
/* @__PURE__ */ new Set(),
|
|
3431
3621
|
modulesOwnMsw
|
|
3432
3622
|
);
|
|
3623
|
+
for (const member of migrated.unhandled) {
|
|
3624
|
+
blockers.push({
|
|
3625
|
+
file: `${relative6}:${member.line}`,
|
|
3626
|
+
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}`
|
|
3627
|
+
});
|
|
3628
|
+
}
|
|
3629
|
+
for (const refusal of migrated.refusals) {
|
|
3630
|
+
blockers.push({ file: relative6, reason: refusal.reason });
|
|
3631
|
+
}
|
|
3632
|
+
collected.push(...migrated.warnings);
|
|
3433
3633
|
const renamedTo = vitestSupportName(relative6);
|
|
3434
3634
|
if (!migrated.changed && renamedTo === relative6) continue;
|
|
3435
3635
|
if (renamedTo !== relative6) operations.push({ kind: "delete", path: relative6 });
|
|
3436
|
-
const before =
|
|
3437
|
-
const after =
|
|
3636
|
+
const before = parse3(source);
|
|
3637
|
+
const after = parse3(migrated.source);
|
|
3438
3638
|
if (before !== void 0 && after !== void 0) {
|
|
3439
3639
|
const wasAsync = asyncFunctionNames(before);
|
|
3440
3640
|
for (const name of asyncFunctionNames(after)) {
|
|
@@ -3443,17 +3643,17 @@ function migrateModuleTests(cwd, setupFiles = []) {
|
|
|
3443
3643
|
}
|
|
3444
3644
|
files++;
|
|
3445
3645
|
renamed += migrated.renamed;
|
|
3446
|
-
const contents = /\bvi\./.test(migrated.source) ? injectViImport(
|
|
3646
|
+
const contents = /\bvi\./.test(migrated.source) ? injectViImport(join17(cwd, renamedTo), migrated.source) : migrated.source;
|
|
3447
3647
|
operations.push({ kind: "write", path: renamedTo, contents });
|
|
3448
3648
|
}
|
|
3449
3649
|
for (const relative6 of listTestFiles(cwd)) {
|
|
3450
|
-
const source = read2(
|
|
3650
|
+
const source = read2(join17(cwd, relative6));
|
|
3451
3651
|
if (source === void 0) {
|
|
3452
3652
|
blockers.push({ file: relative6, reason: "this file could not be read" });
|
|
3453
3653
|
continue;
|
|
3454
3654
|
}
|
|
3455
3655
|
const migrated = migrateTestFile(
|
|
3456
|
-
|
|
3656
|
+
join17(cwd, relative6),
|
|
3457
3657
|
source,
|
|
3458
3658
|
defaultImported,
|
|
3459
3659
|
asyncHelpers,
|
|
@@ -3480,8 +3680,8 @@ function migrateModuleTests(cwd, setupFiles = []) {
|
|
|
3480
3680
|
}
|
|
3481
3681
|
|
|
3482
3682
|
// src/roles/test/nest/generate-config.ts
|
|
3483
|
-
import { readdirSync as readdirSync5, readFileSync as
|
|
3484
|
-
import { join as
|
|
3683
|
+
import { readdirSync as readdirSync5, readFileSync as readFileSync15, statSync as statSync5 } from "node:fs";
|
|
3684
|
+
import { join as join18, relative as relative4 } from "node:path";
|
|
3485
3685
|
var NEST_TEST_PRESET_SPECIFIER = "@hublo/sentinel/test/nest";
|
|
3486
3686
|
var REACT_TEST_PRESET_SPECIFIER = "@hublo/sentinel/test/react";
|
|
3487
3687
|
function flavourOf(reading) {
|
|
@@ -3527,10 +3727,10 @@ function readModuleTraits(cwd) {
|
|
|
3527
3727
|
}
|
|
3528
3728
|
for (const entry of entries) {
|
|
3529
3729
|
if (SKIPPED3.has(entry)) continue;
|
|
3530
|
-
const path =
|
|
3730
|
+
const path = join18(dir, entry);
|
|
3531
3731
|
let directory;
|
|
3532
3732
|
try {
|
|
3533
|
-
directory =
|
|
3733
|
+
directory = statSync5(path).isDirectory();
|
|
3534
3734
|
} catch {
|
|
3535
3735
|
continue;
|
|
3536
3736
|
}
|
|
@@ -3541,7 +3741,7 @@ function readModuleTraits(cwd) {
|
|
|
3541
3741
|
if (!/\.tsx?$/.test(entry)) continue;
|
|
3542
3742
|
let source;
|
|
3543
3743
|
try {
|
|
3544
|
-
source =
|
|
3744
|
+
source = readFileSync15(path, "utf8");
|
|
3545
3745
|
} catch {
|
|
3546
3746
|
continue;
|
|
3547
3747
|
}
|
|
@@ -3674,8 +3874,8 @@ ${overrides.join("\n")}
|
|
|
3674
3874
|
}
|
|
3675
3875
|
|
|
3676
3876
|
// src/roles/test/nest/read-jest-config.ts
|
|
3677
|
-
import { existsSync as existsSync14, readFileSync as
|
|
3678
|
-
import { join as
|
|
3877
|
+
import { existsSync as existsSync14, readFileSync as readFileSync16 } from "node:fs";
|
|
3878
|
+
import { join as join19 } from "node:path";
|
|
3679
3879
|
var CARRIED = [
|
|
3680
3880
|
"testEnvironment",
|
|
3681
3881
|
"coverageDirectory",
|
|
@@ -3865,7 +4065,7 @@ function extendedConfig(source, cwd) {
|
|
|
3865
4065
|
(name) => name.replace(/^\.\//, "")
|
|
3866
4066
|
);
|
|
3867
4067
|
const file = candidates.find(
|
|
3868
|
-
(name) => /^jest[\w.-]*\.(ts|js)$/.test(name) && existsSync14(
|
|
4068
|
+
(name) => /^jest[\w.-]*\.(ts|js)$/.test(name) && existsSync14(join19(cwd, name))
|
|
3869
4069
|
);
|
|
3870
4070
|
if (file === void 0) continue;
|
|
3871
4071
|
if (!new RegExp(String.raw`\{\s*\.\.\.${binding}\b`).test(source)) continue;
|
|
@@ -3892,11 +4092,11 @@ function sideEffects(source, extended) {
|
|
|
3892
4092
|
return found;
|
|
3893
4093
|
}
|
|
3894
4094
|
function readJestConfig(cwd, named) {
|
|
3895
|
-
const file = named ?? JEST_CONFIG_FILES.find((name) => existsSync14(
|
|
3896
|
-
if (file === void 0 || !existsSync14(
|
|
4095
|
+
const file = named ?? JEST_CONFIG_FILES.find((name) => existsSync14(join19(cwd, name)));
|
|
4096
|
+
if (file === void 0 || !existsSync14(join19(cwd, file))) return void 0;
|
|
3897
4097
|
let source;
|
|
3898
4098
|
try {
|
|
3899
|
-
source =
|
|
4099
|
+
source = readFileSync16(join19(cwd, file), "utf8");
|
|
3900
4100
|
} catch {
|
|
3901
4101
|
return { file, refusals: [`${file} could not be read`], notes: [] };
|
|
3902
4102
|
}
|
|
@@ -3978,7 +4178,7 @@ function readJestConfig(cwd, named) {
|
|
|
3978
4178
|
|
|
3979
4179
|
// src/roles/test/nest/run-modes.ts
|
|
3980
4180
|
import { existsSync as existsSync15 } from "node:fs";
|
|
3981
|
-
import { basename as basename2, join as
|
|
4181
|
+
import { basename as basename2, join as join20 } from "node:path";
|
|
3982
4182
|
var JEST_EXECUTOR = "@nx/jest:jest";
|
|
3983
4183
|
var PRIMARY_CONFIG_FILE = "vitest.config.mts";
|
|
3984
4184
|
var PRIMARY_TARGET = "test";
|
|
@@ -3999,7 +4199,7 @@ function runModes(cwd, fallback) {
|
|
|
3999
4199
|
const jestConfig = entry.options?.jestConfig;
|
|
4000
4200
|
if (jestConfig === void 0) continue;
|
|
4001
4201
|
const name = configName(jestConfig);
|
|
4002
|
-
if (!existsSync15(
|
|
4202
|
+
if (!existsSync15(join20(cwd, name))) continue;
|
|
4003
4203
|
declared.push({
|
|
4004
4204
|
target,
|
|
4005
4205
|
jestConfig: name,
|
|
@@ -4025,11 +4225,11 @@ function runModes(cwd, fallback) {
|
|
|
4025
4225
|
|
|
4026
4226
|
// src/roles/test/written-file-formatter.ts
|
|
4027
4227
|
import { existsSync as existsSync17 } from "node:fs";
|
|
4028
|
-
import { dirname as
|
|
4228
|
+
import { dirname as dirname10, join as join23 } from "node:path";
|
|
4029
4229
|
|
|
4030
4230
|
// src/roles/format/read-adoption.ts
|
|
4031
|
-
import { existsSync as existsSync16, readFileSync as
|
|
4032
|
-
import { join as
|
|
4231
|
+
import { existsSync as existsSync16, readFileSync as readFileSync17 } from "node:fs";
|
|
4232
|
+
import { join as join21 } from "node:path";
|
|
4033
4233
|
|
|
4034
4234
|
// src/roles/format/config-policy.ts
|
|
4035
4235
|
var FORMAT_CONFIG_FILE = ".oxfmtrc.json";
|
|
@@ -4135,11 +4335,11 @@ function sameValue(a, b) {
|
|
|
4135
4335
|
return JSON.stringify(a) === JSON.stringify(b);
|
|
4136
4336
|
}
|
|
4137
4337
|
function readFormatAdoption(cwd) {
|
|
4138
|
-
const path =
|
|
4338
|
+
const path = join21(cwd, FORMAT_CONFIG_FILE);
|
|
4139
4339
|
if (!existsSync16(path)) return NOT_ADOPTED(null);
|
|
4140
4340
|
let parsed;
|
|
4141
4341
|
try {
|
|
4142
|
-
parsed = parseJsonc(
|
|
4342
|
+
parsed = parseJsonc(readFileSync17(path, "utf8"), FORMAT_CONFIG_FILE);
|
|
4143
4343
|
} catch (error) {
|
|
4144
4344
|
const reason = error instanceof Error ? error.message : String(error);
|
|
4145
4345
|
return NOT_ADOPTED(FORMAT_CONFIG_FILE, `${FORMAT_CONFIG_FILE} could not be parsed (${reason})`);
|
|
@@ -4183,9 +4383,9 @@ function readFormatAdoption(cwd) {
|
|
|
4183
4383
|
}
|
|
4184
4384
|
|
|
4185
4385
|
// src/roles/format/resolve-oxfmt.ts
|
|
4186
|
-
import { readFileSync as
|
|
4386
|
+
import { readFileSync as readFileSync18 } from "node:fs";
|
|
4187
4387
|
import { createRequire as createRequire4 } from "node:module";
|
|
4188
|
-
import { dirname as
|
|
4388
|
+
import { dirname as dirname9, join as join22 } from "node:path";
|
|
4189
4389
|
function resolveOxfmt(cwd) {
|
|
4190
4390
|
return resolveBin(cwd, "oxfmt") ?? binFromOwnInstall("oxfmt", "oxfmt");
|
|
4191
4391
|
}
|
|
@@ -4214,8 +4414,8 @@ function configSchema() {
|
|
|
4214
4414
|
function readConfigSchema() {
|
|
4215
4415
|
try {
|
|
4216
4416
|
const manifest = createRequire4(import.meta.url).resolve("oxfmt/package.json");
|
|
4217
|
-
const schemaPath =
|
|
4218
|
-
return JSON.parse(
|
|
4417
|
+
const schemaPath = join22(dirname9(manifest), "configuration_schema.json");
|
|
4418
|
+
return JSON.parse(readFileSync18(schemaPath, "utf8"));
|
|
4219
4419
|
} catch {
|
|
4220
4420
|
return void 0;
|
|
4221
4421
|
}
|
|
@@ -4240,9 +4440,9 @@ function prettierConfigFrom(cwd) {
|
|
|
4240
4440
|
let dir = cwd;
|
|
4241
4441
|
for (; ; ) {
|
|
4242
4442
|
for (const name of PRETTIER_CONFIGS) {
|
|
4243
|
-
if (existsSync17(
|
|
4443
|
+
if (existsSync17(join23(dir, name))) return join23(dir, name);
|
|
4244
4444
|
}
|
|
4245
|
-
const parent =
|
|
4445
|
+
const parent = dirname10(dir);
|
|
4246
4446
|
if (parent === dir) return void 0;
|
|
4247
4447
|
dir = parent;
|
|
4248
4448
|
}
|
|
@@ -4270,12 +4470,12 @@ function writtenFileFormatter(cwd) {
|
|
|
4270
4470
|
var SPEC_TSCONFIG = "tsconfig.spec.json";
|
|
4271
4471
|
var VITEST_GLOBAL_TYPES = "vitest/globals";
|
|
4272
4472
|
function specTypesOperation(cwd) {
|
|
4273
|
-
const path =
|
|
4473
|
+
const path = join24(cwd, SPEC_TSCONFIG);
|
|
4274
4474
|
if (!existsSync18(path)) return void 0;
|
|
4275
4475
|
let config;
|
|
4276
4476
|
try {
|
|
4277
4477
|
config = parseJsonc(
|
|
4278
|
-
|
|
4478
|
+
readFileSync19(path, "utf8"),
|
|
4279
4479
|
SPEC_TSCONFIG
|
|
4280
4480
|
);
|
|
4281
4481
|
} catch {
|
|
@@ -4295,8 +4495,8 @@ function specTypesOperation(cwd) {
|
|
|
4295
4495
|
}
|
|
4296
4496
|
function shippedTypesPath(cwd, declaration) {
|
|
4297
4497
|
try {
|
|
4298
|
-
const manifest = createRequire5(
|
|
4299
|
-
const file =
|
|
4498
|
+
const manifest = createRequire5(join24(cwd, "noop.cjs")).resolve("@hublo/sentinel/package.json");
|
|
4499
|
+
const file = join24(dirname11(manifest), declaration);
|
|
4300
4500
|
if (existsSync18(file)) {
|
|
4301
4501
|
const path = relative5(cwd, file);
|
|
4302
4502
|
return path.startsWith(".") ? path : `./${path}`;
|
|
@@ -4316,7 +4516,7 @@ function helpersStillCallingJest(cwd) {
|
|
|
4316
4516
|
return;
|
|
4317
4517
|
}
|
|
4318
4518
|
for (const entry of entries) {
|
|
4319
|
-
const path =
|
|
4519
|
+
const path = join24(dir, entry.name);
|
|
4320
4520
|
if (entry.isDirectory()) {
|
|
4321
4521
|
if (!skip.has(entry.name)) walk2(path);
|
|
4322
4522
|
continue;
|
|
@@ -4326,7 +4526,7 @@ function helpersStillCallingJest(cwd) {
|
|
|
4326
4526
|
if (/^(jest|vitest)\./.test(entry.name)) continue;
|
|
4327
4527
|
let source;
|
|
4328
4528
|
try {
|
|
4329
|
-
source =
|
|
4529
|
+
source = readFileSync19(path, "utf8");
|
|
4330
4530
|
} catch {
|
|
4331
4531
|
continue;
|
|
4332
4532
|
}
|
|
@@ -4338,8 +4538,7 @@ function helpersStillCallingJest(cwd) {
|
|
|
4338
4538
|
walk2(cwd);
|
|
4339
4539
|
return found;
|
|
4340
4540
|
}
|
|
4341
|
-
function compilesATestHelper(
|
|
4342
|
-
const helpers = helpersStillCallingJest(cwd);
|
|
4541
|
+
function compilesATestHelper(helpers, config) {
|
|
4343
4542
|
if (helpers.length === 0) return false;
|
|
4344
4543
|
const include = Array.isArray(config?.include) ? config.include : void 0;
|
|
4345
4544
|
const exclude = Array.isArray(config?.exclude) ? config.exclude : [];
|
|
@@ -4358,11 +4557,13 @@ function tsconfigFileListOperations(cwd) {
|
|
|
4358
4557
|
} catch {
|
|
4359
4558
|
return operations;
|
|
4360
4559
|
}
|
|
4560
|
+
let walked;
|
|
4561
|
+
const helpers = () => walked ??= helpersStillCallingJest(cwd);
|
|
4361
4562
|
for (const name of names) {
|
|
4362
4563
|
let config;
|
|
4363
4564
|
try {
|
|
4364
4565
|
config = parseJsonc(
|
|
4365
|
-
|
|
4566
|
+
readFileSync19(join24(cwd, name), "utf8"),
|
|
4366
4567
|
name
|
|
4367
4568
|
);
|
|
4368
4569
|
} catch {
|
|
@@ -4371,7 +4572,7 @@ function tsconfigFileListOperations(cwd) {
|
|
|
4371
4572
|
const include = Array.isArray(config?.include) ? rewriteFileList(config.include) : void 0;
|
|
4372
4573
|
const exclude = Array.isArray(config?.exclude) ? rewriteFileList(config.exclude) : void 0;
|
|
4373
4574
|
const files = Array.isArray(config?.files) ? rewriteFileList(config.files) : void 0;
|
|
4374
|
-
const wantsTypes = name === SPEC_TSCONFIG || compilesATestHelper(
|
|
4575
|
+
const wantsTypes = name === SPEC_TSCONFIG || compilesATestHelper(helpers(), config);
|
|
4375
4576
|
const withTypes = wantsTypes ? withShippedTypes(cwd, files ?? config?.files) : void 0;
|
|
4376
4577
|
if (include === void 0 && exclude === void 0 && files === void 0 && withTypes === void 0)
|
|
4377
4578
|
continue;
|
|
@@ -4474,6 +4675,7 @@ function planJestMigration(context, adoption) {
|
|
|
4474
4675
|
({ mode }) => nxTargetOperations({
|
|
4475
4676
|
cwd: context.cwd,
|
|
4476
4677
|
targets: testTarget({
|
|
4678
|
+
cwd: context.cwd,
|
|
4477
4679
|
name: mode.target,
|
|
4478
4680
|
configFiles: [mode.vitestConfig],
|
|
4479
4681
|
outputs: existingFor(mode.target)?.outputs ?? [],
|
|
@@ -4638,7 +4840,13 @@ function plan(context) {
|
|
|
4638
4840
|
operations.push(
|
|
4639
4841
|
...nxTargetOperations({
|
|
4640
4842
|
cwd: context.cwd,
|
|
4641
|
-
targets: testTarget({
|
|
4843
|
+
targets: testTarget({
|
|
4844
|
+
cwd: context.cwd,
|
|
4845
|
+
configFiles: [configFile],
|
|
4846
|
+
outputs,
|
|
4847
|
+
dependsOn,
|
|
4848
|
+
configurations
|
|
4849
|
+
})
|
|
4642
4850
|
})
|
|
4643
4851
|
);
|
|
4644
4852
|
const owned = ownedTestDependencies(context.cwd, adoption.ownDeclarations);
|
|
@@ -4830,7 +5038,7 @@ function fromWorkspaceRoot(moduleDir, options, paths) {
|
|
|
4830
5038
|
if (root === void 0 || root === moduleDir) {
|
|
4831
5039
|
return { cwd: moduleDir, options: [...options], paths: [...paths] };
|
|
4832
5040
|
}
|
|
4833
|
-
const absolute = (value) => isAbsolute2(value) ? value :
|
|
5041
|
+
const absolute = (value) => isAbsolute2(value) ? value : resolve8(moduleDir, value);
|
|
4834
5042
|
const moved = [];
|
|
4835
5043
|
let previousWasConfig = false;
|
|
4836
5044
|
for (const option of options) {
|
|
@@ -4862,7 +5070,6 @@ export {
|
|
|
4862
5070
|
resolveBin,
|
|
4863
5071
|
binFromOwnInstall,
|
|
4864
5072
|
binSearchPath,
|
|
4865
|
-
parseJsonc,
|
|
4866
5073
|
nxTargetOperations,
|
|
4867
5074
|
FORMAT_CONFIG_FILE,
|
|
4868
5075
|
FORMAT_SCRIPT_NAME,
|