isolate-package 1.32.1 → 1.33.0-0
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/index.mjs +1 -1
- package/dist/{isolate-DyRD5Zd_.mjs → isolate-DTwgcMAN.mjs} +300 -35
- package/dist/isolate-DTwgcMAN.mjs.map +1 -0
- package/dist/isolate-bin.mjs +1 -1
- package/package.json +1 -1
- package/src/isolate.ts +2 -0
- package/src/lib/lockfile/helpers/bun-lockfile.ts +143 -0
- package/src/lib/lockfile/helpers/generate-bun-lockfile.ts +7 -139
- package/src/lib/patches/collect-installed-names-bun.test.ts +154 -0
- package/src/lib/patches/collect-installed-names-bun.ts +87 -0
- package/src/lib/patches/collect-installed-names-pnpm.test.ts +316 -0
- package/src/lib/patches/collect-installed-names-pnpm.ts +364 -0
- package/src/lib/patches/copy-patches.test.ts +125 -0
- package/src/lib/patches/copy-patches.ts +38 -1
- package/dist/isolate-DyRD5Zd_.mjs.map +0 -1
|
@@ -15,9 +15,17 @@ vi.mock("fs-extra", () => ({
|
|
|
15
15
|
vi.mock("~/lib/utils", () => ({
|
|
16
16
|
filterPatchedDependencies: vi.fn(),
|
|
17
17
|
getIsolateRelativeLogPath: vi.fn((p: string) => p),
|
|
18
|
+
getPackageName: vi.fn((spec: string) => {
|
|
19
|
+
if (spec.startsWith("@")) {
|
|
20
|
+
const parts = spec.split("@");
|
|
21
|
+
return `@${parts[1] ?? ""}`;
|
|
22
|
+
}
|
|
23
|
+
return spec.split("@")[0] ?? "";
|
|
24
|
+
}),
|
|
18
25
|
getRootRelativeLogPath: vi.fn((p: string) => p),
|
|
19
26
|
isRushWorkspace: vi.fn(() => false),
|
|
20
27
|
readTypedJson: vi.fn(),
|
|
28
|
+
readTypedJsonSync: vi.fn(),
|
|
21
29
|
readTypedYamlSync: vi.fn(),
|
|
22
30
|
}));
|
|
23
31
|
|
|
@@ -29,16 +37,25 @@ vi.mock("~/lib/package-manager", () => ({
|
|
|
29
37
|
/** Mock the pnpm lockfile readers */
|
|
30
38
|
vi.mock("pnpm_lockfile_file_v8", () => ({
|
|
31
39
|
readWantedLockfile: vi.fn(() => Promise.resolve(null)),
|
|
40
|
+
getLockfileImporterId: vi.fn(
|
|
41
|
+
(root: string, dir: string) => dir.replace(`${root}/`, "") || ".",
|
|
42
|
+
),
|
|
32
43
|
}));
|
|
33
44
|
|
|
34
45
|
vi.mock("pnpm_lockfile_file_v9", () => ({
|
|
35
46
|
readWantedLockfile: vi.fn(() => Promise.resolve(null)),
|
|
47
|
+
getLockfileImporterId: vi.fn(
|
|
48
|
+
(root: string, dir: string) => dir.replace(`${root}/`, "") || ".",
|
|
49
|
+
),
|
|
36
50
|
}));
|
|
37
51
|
|
|
38
52
|
const fs = vi.mocked((await import("fs-extra")).default);
|
|
39
53
|
const { filterPatchedDependencies, readTypedJson, readTypedYamlSync } =
|
|
40
54
|
vi.mocked(await import("~/lib/utils"));
|
|
41
55
|
const { usePackageManager } = vi.mocked(await import("~/lib/package-manager"));
|
|
56
|
+
const { readWantedLockfile: readWantedLockfile_v9 } = vi.mocked(
|
|
57
|
+
await import("pnpm_lockfile_file_v9"),
|
|
58
|
+
);
|
|
42
59
|
|
|
43
60
|
describe("copyPatches", () => {
|
|
44
61
|
beforeEach(() => {
|
|
@@ -65,6 +82,8 @@ describe("copyPatches", () => {
|
|
|
65
82
|
|
|
66
83
|
const result = await copyPatches({
|
|
67
84
|
workspaceRootDir: "/workspace",
|
|
85
|
+
targetPackageDir: "/workspace/packages/test",
|
|
86
|
+
internalDepPackageNames: [],
|
|
68
87
|
targetPackageManifest: { name: "test", version: "1.0.0" },
|
|
69
88
|
isolateDir: "/workspace/isolate",
|
|
70
89
|
packagesRegistry: {},
|
|
@@ -126,6 +145,8 @@ describe("copyPatches", () => {
|
|
|
126
145
|
|
|
127
146
|
const result = await copyPatches({
|
|
128
147
|
workspaceRootDir: "/workspace",
|
|
148
|
+
targetPackageDir: "/workspace/packages/test",
|
|
149
|
+
internalDepPackageNames: [],
|
|
129
150
|
targetPackageManifest: { name: "test", version: "1.0.0" },
|
|
130
151
|
isolateDir: "/workspace/isolate",
|
|
131
152
|
packagesRegistry: {},
|
|
@@ -146,6 +167,8 @@ describe("copyPatches", () => {
|
|
|
146
167
|
|
|
147
168
|
const result = await copyPatches({
|
|
148
169
|
workspaceRootDir: "/workspace",
|
|
170
|
+
targetPackageDir: "/workspace/packages/test",
|
|
171
|
+
internalDepPackageNames: [],
|
|
149
172
|
targetPackageManifest: { name: "test", version: "1.0.0" },
|
|
150
173
|
isolateDir: "/workspace/isolate",
|
|
151
174
|
packagesRegistry: {},
|
|
@@ -176,6 +199,8 @@ describe("copyPatches", () => {
|
|
|
176
199
|
|
|
177
200
|
const result = await copyPatches({
|
|
178
201
|
workspaceRootDir: "/workspace",
|
|
202
|
+
targetPackageDir: "/workspace/packages/test",
|
|
203
|
+
internalDepPackageNames: [],
|
|
179
204
|
targetPackageManifest: targetManifest,
|
|
180
205
|
isolateDir: "/workspace/isolate",
|
|
181
206
|
packagesRegistry: {},
|
|
@@ -214,6 +239,8 @@ describe("copyPatches", () => {
|
|
|
214
239
|
|
|
215
240
|
const result = await copyPatches({
|
|
216
241
|
workspaceRootDir: "/workspace",
|
|
242
|
+
targetPackageDir: "/workspace/packages/test",
|
|
243
|
+
internalDepPackageNames: [],
|
|
217
244
|
targetPackageManifest: targetManifest,
|
|
218
245
|
isolateDir: "/workspace/isolate",
|
|
219
246
|
packagesRegistry: {},
|
|
@@ -256,6 +283,8 @@ describe("copyPatches", () => {
|
|
|
256
283
|
|
|
257
284
|
const result = await copyPatches({
|
|
258
285
|
workspaceRootDir: "/workspace",
|
|
286
|
+
targetPackageDir: "/workspace/packages/test",
|
|
287
|
+
internalDepPackageNames: [],
|
|
259
288
|
targetPackageManifest: targetManifest,
|
|
260
289
|
isolateDir: "/workspace/isolate",
|
|
261
290
|
packagesRegistry: {},
|
|
@@ -287,6 +316,8 @@ describe("copyPatches", () => {
|
|
|
287
316
|
|
|
288
317
|
const result = await copyPatches({
|
|
289
318
|
workspaceRootDir: "/workspace",
|
|
319
|
+
targetPackageDir: "/workspace/packages/test",
|
|
320
|
+
internalDepPackageNames: [],
|
|
290
321
|
targetPackageManifest: targetManifest,
|
|
291
322
|
isolateDir: "/workspace/isolate",
|
|
292
323
|
packagesRegistry: {},
|
|
@@ -321,6 +352,8 @@ describe("copyPatches", () => {
|
|
|
321
352
|
|
|
322
353
|
const result = await copyPatches({
|
|
323
354
|
workspaceRootDir: "/workspace",
|
|
355
|
+
targetPackageDir: "/workspace/packages/test",
|
|
356
|
+
internalDepPackageNames: [],
|
|
324
357
|
targetPackageManifest: targetManifest,
|
|
325
358
|
isolateDir: "/workspace/isolate",
|
|
326
359
|
packagesRegistry: {},
|
|
@@ -364,6 +397,8 @@ describe("copyPatches", () => {
|
|
|
364
397
|
|
|
365
398
|
const result = await copyPatches({
|
|
366
399
|
workspaceRootDir: "/workspace",
|
|
400
|
+
targetPackageDir: "/workspace/packages/test",
|
|
401
|
+
internalDepPackageNames: [],
|
|
367
402
|
targetPackageManifest: targetManifest,
|
|
368
403
|
isolateDir: "/workspace/isolate",
|
|
369
404
|
packagesRegistry: {},
|
|
@@ -409,6 +444,8 @@ describe("copyPatches", () => {
|
|
|
409
444
|
|
|
410
445
|
const result = await copyPatches({
|
|
411
446
|
workspaceRootDir: "/workspace",
|
|
447
|
+
targetPackageDir: "/workspace/packages/test",
|
|
448
|
+
internalDepPackageNames: [],
|
|
412
449
|
targetPackageManifest: targetManifest,
|
|
413
450
|
isolateDir: "/workspace/isolate",
|
|
414
451
|
packagesRegistry: {},
|
|
@@ -456,6 +493,8 @@ describe("copyPatches", () => {
|
|
|
456
493
|
|
|
457
494
|
const result = await copyPatches({
|
|
458
495
|
workspaceRootDir: "/workspace",
|
|
496
|
+
targetPackageDir: "/workspace/packages/test",
|
|
497
|
+
internalDepPackageNames: [],
|
|
459
498
|
targetPackageManifest: targetManifest,
|
|
460
499
|
isolateDir: "/workspace/isolate",
|
|
461
500
|
packagesRegistry: {},
|
|
@@ -509,6 +548,8 @@ describe("copyPatches", () => {
|
|
|
509
548
|
|
|
510
549
|
const result = await copyPatches({
|
|
511
550
|
workspaceRootDir: "/workspace",
|
|
551
|
+
targetPackageDir: "/workspace/packages/test",
|
|
552
|
+
internalDepPackageNames: [],
|
|
512
553
|
targetPackageManifest: consumerManifest,
|
|
513
554
|
isolateDir: "/workspace/isolate",
|
|
514
555
|
packagesRegistry: {
|
|
@@ -536,4 +577,88 @@ describe("copyPatches", () => {
|
|
|
536
577
|
expect(reachable!.has("firebase-package")).toBe(true);
|
|
537
578
|
expect(reachable!.has("tslib")).toBe(true);
|
|
538
579
|
});
|
|
580
|
+
|
|
581
|
+
it("should pick up deep external-to-external transitives from the pnpm lockfile (regression: issue #167 follow-up)", async () => {
|
|
582
|
+
/**
|
|
583
|
+
* Target depends on `@react-pdf/renderer` (external). The patched
|
|
584
|
+
* `@react-pdf/render` is only a transitive of `@react-pdf/renderer`. The
|
|
585
|
+
* manifest walker can't see it because it can't open external manifests,
|
|
586
|
+
* so the lockfile walker has to surface it.
|
|
587
|
+
*/
|
|
588
|
+
const targetManifest: PackageManifest = {
|
|
589
|
+
name: "consumer",
|
|
590
|
+
version: "1.0.0",
|
|
591
|
+
dependencies: { "@react-pdf/renderer": "^4.0.0" },
|
|
592
|
+
};
|
|
593
|
+
|
|
594
|
+
readTypedYamlSync.mockReturnValue({
|
|
595
|
+
patchedDependencies: {
|
|
596
|
+
"@react-pdf/render@4.3.0": "patches/@react-pdf__render@4.3.0.patch",
|
|
597
|
+
},
|
|
598
|
+
});
|
|
599
|
+
readTypedJson.mockResolvedValue({
|
|
600
|
+
name: "root",
|
|
601
|
+
version: "1.0.0",
|
|
602
|
+
} as PackageManifest);
|
|
603
|
+
|
|
604
|
+
filterPatchedDependencies.mockReturnValue({
|
|
605
|
+
"@react-pdf/render@4.3.0": "patches/@react-pdf__render@4.3.0.patch",
|
|
606
|
+
});
|
|
607
|
+
|
|
608
|
+
fs.existsSync.mockReturnValue(true);
|
|
609
|
+
|
|
610
|
+
usePackageManager.mockReturnValue({
|
|
611
|
+
name: "pnpm",
|
|
612
|
+
majorVersion: 9,
|
|
613
|
+
version: "9.0.0",
|
|
614
|
+
packageManagerString: "pnpm@9.0.0",
|
|
615
|
+
});
|
|
616
|
+
|
|
617
|
+
/**
|
|
618
|
+
* Fake v9 lockfile: target importer depends on @react-pdf/renderer, which
|
|
619
|
+
* has @react-pdf/render as its only resolved dep.
|
|
620
|
+
*/
|
|
621
|
+
readWantedLockfile_v9.mockResolvedValue({
|
|
622
|
+
lockfileVersion: "9.0",
|
|
623
|
+
importers: {
|
|
624
|
+
"packages/consumer": {
|
|
625
|
+
specifiers: { "@react-pdf/renderer": "^4.0.0" },
|
|
626
|
+
dependencies: { "@react-pdf/renderer": "4.0.0" },
|
|
627
|
+
},
|
|
628
|
+
},
|
|
629
|
+
packages: {
|
|
630
|
+
"@react-pdf/renderer@4.0.0": {
|
|
631
|
+
resolution: { integrity: "sha512-x" },
|
|
632
|
+
dependencies: { "@react-pdf/render": "4.3.0" },
|
|
633
|
+
},
|
|
634
|
+
"@react-pdf/render@4.3.0": {
|
|
635
|
+
resolution: { integrity: "sha512-y" },
|
|
636
|
+
},
|
|
637
|
+
},
|
|
638
|
+
} as unknown as Awaited<ReturnType<typeof readWantedLockfile_v9>>);
|
|
639
|
+
|
|
640
|
+
const result = await copyPatches({
|
|
641
|
+
workspaceRootDir: "/workspace",
|
|
642
|
+
targetPackageDir: "/workspace/packages/consumer",
|
|
643
|
+
internalDepPackageNames: [],
|
|
644
|
+
targetPackageManifest: targetManifest,
|
|
645
|
+
isolateDir: "/workspace/isolate",
|
|
646
|
+
packagesRegistry: {},
|
|
647
|
+
includeDevDependencies: false,
|
|
648
|
+
});
|
|
649
|
+
|
|
650
|
+
expect(result).toEqual({
|
|
651
|
+
"@react-pdf/render@4.3.0": {
|
|
652
|
+
path: "patches/@react-pdf__render@4.3.0.patch",
|
|
653
|
+
hash: "",
|
|
654
|
+
},
|
|
655
|
+
});
|
|
656
|
+
|
|
657
|
+
const filterCall = filterPatchedDependencies.mock.calls[0]?.[0];
|
|
658
|
+
expect(filterCall).toBeDefined();
|
|
659
|
+
const reachable = filterCall!.reachableDependencyNames;
|
|
660
|
+
expect(reachable).toBeInstanceOf(Set);
|
|
661
|
+
expect(reachable!.has("@react-pdf/renderer")).toBe(true);
|
|
662
|
+
expect(reachable!.has("@react-pdf/render")).toBe(true);
|
|
663
|
+
});
|
|
539
664
|
});
|
|
@@ -18,23 +18,29 @@ import {
|
|
|
18
18
|
readTypedJson,
|
|
19
19
|
readTypedYamlSync,
|
|
20
20
|
} from "~/lib/utils";
|
|
21
|
+
import { collectInstalledNamesFromBunLockfile } from "./collect-installed-names-bun";
|
|
22
|
+
import { collectInstalledNamesFromPnpmLockfile } from "./collect-installed-names-pnpm";
|
|
21
23
|
|
|
22
24
|
export async function copyPatches({
|
|
23
25
|
workspaceRootDir,
|
|
26
|
+
targetPackageDir,
|
|
24
27
|
targetPackageManifest,
|
|
25
28
|
packagesRegistry,
|
|
29
|
+
internalDepPackageNames,
|
|
26
30
|
isolateDir,
|
|
27
31
|
includeDevDependencies,
|
|
28
32
|
}: {
|
|
29
33
|
workspaceRootDir: string;
|
|
34
|
+
targetPackageDir: string;
|
|
30
35
|
targetPackageManifest: PackageManifest;
|
|
31
36
|
packagesRegistry: PackagesRegistry;
|
|
37
|
+
internalDepPackageNames: string[];
|
|
32
38
|
isolateDir: string;
|
|
33
39
|
includeDevDependencies: boolean;
|
|
34
40
|
}): Promise<Record<string, PatchFile>> {
|
|
35
41
|
const log = useLogger();
|
|
36
42
|
|
|
37
|
-
const { name: packageManagerName } = usePackageManager();
|
|
43
|
+
const { name: packageManagerName, majorVersion } = usePackageManager();
|
|
38
44
|
|
|
39
45
|
let patchedDependencies: Record<string, string> | undefined;
|
|
40
46
|
|
|
@@ -102,6 +108,37 @@ export async function copyPatches({
|
|
|
102
108
|
includeDevDependencies,
|
|
103
109
|
});
|
|
104
110
|
|
|
111
|
+
/**
|
|
112
|
+
* Manifest-based reachability misses external→external transitives because
|
|
113
|
+
* external manifests aren't loaded here. Walk the package-manager's
|
|
114
|
+
* lockfile to also pick up those names, so a patch for a deeply-nested
|
|
115
|
+
* external dep (e.g. `@react-pdf/render` reached via `@react-pdf/renderer`)
|
|
116
|
+
* survives isolation.
|
|
117
|
+
*/
|
|
118
|
+
const lockfileInstalledNames =
|
|
119
|
+
packageManagerName === "pnpm"
|
|
120
|
+
? await collectInstalledNamesFromPnpmLockfile({
|
|
121
|
+
workspaceRootDir,
|
|
122
|
+
targetPackageDir,
|
|
123
|
+
internalDepPackageNames,
|
|
124
|
+
packagesRegistry,
|
|
125
|
+
majorVersion,
|
|
126
|
+
includeDevDependencies,
|
|
127
|
+
})
|
|
128
|
+
: packageManagerName === "bun"
|
|
129
|
+
? collectInstalledNamesFromBunLockfile({
|
|
130
|
+
workspaceRootDir,
|
|
131
|
+
targetPackageDir,
|
|
132
|
+
internalDepPackageNames,
|
|
133
|
+
packagesRegistry,
|
|
134
|
+
includeDevDependencies,
|
|
135
|
+
})
|
|
136
|
+
: new Set<string>();
|
|
137
|
+
|
|
138
|
+
for (const name of lockfileInstalledNames) {
|
|
139
|
+
reachableDependencyNames.add(name);
|
|
140
|
+
}
|
|
141
|
+
|
|
105
142
|
const filteredPatches = filterPatchedDependencies({
|
|
106
143
|
patchedDependencies,
|
|
107
144
|
targetPackageManifest,
|