isolate-package 1.31.0 → 1.32.1
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-DtNAHzfa.mjs → isolate-DyRD5Zd_.mjs} +442 -124
- package/dist/isolate-DyRD5Zd_.mjs.map +1 -0
- package/dist/isolate-bin.mjs +1 -1
- package/package.json +1 -1
- package/src/isolate.ts +7 -4
- package/src/lib/lockfile/helpers/__fixtures__/internal-deps/workspace/package-lock.json +82 -0
- package/src/lib/lockfile/helpers/__fixtures__/internal-deps/workspace/package.json +8 -0
- package/src/lib/lockfile/helpers/__fixtures__/internal-deps/workspace/packages/api/package.json +12 -0
- package/src/lib/lockfile/helpers/__fixtures__/internal-deps/workspace/packages/shared/package.json +12 -0
- package/src/lib/lockfile/helpers/__fixtures__/internal-deps/workspace/packages/utils/package.json +11 -0
- package/src/lib/lockfile/helpers/__fixtures__/nested-version-override/workspace/package-lock.json +56 -0
- package/src/lib/lockfile/helpers/__fixtures__/nested-version-override/workspace/package.json +8 -0
- package/src/lib/lockfile/helpers/__fixtures__/nested-version-override/workspace/packages/api/package.json +11 -0
- package/src/lib/lockfile/helpers/__fixtures__/nested-version-override/workspace/packages/other/package.json +11 -0
- package/src/lib/lockfile/helpers/generate-npm-lockfile.integration.test.ts +243 -0
- package/src/lib/lockfile/helpers/generate-npm-lockfile.test.ts +604 -0
- package/src/lib/lockfile/helpers/generate-npm-lockfile.ts +417 -21
- package/src/lib/lockfile/process-lockfile.test.ts +4 -0
- package/src/lib/lockfile/process-lockfile.ts +14 -16
- package/src/lib/patches/copy-patches.test.ts +78 -0
- package/src/lib/patches/copy-patches.ts +22 -1
- package/src/lib/patches/write-isolate-pnpm-workspace.test.ts +189 -0
- package/src/lib/patches/write-isolate-pnpm-workspace.ts +80 -0
- package/src/lib/registry/collect-reachable-package-names.test.ts +239 -0
- package/src/lib/registry/collect-reachable-package-names.ts +60 -0
- package/src/lib/registry/index.ts +1 -0
- package/src/lib/utils/filter-patched-dependencies.test.ts +77 -0
- package/src/lib/utils/filter-patched-dependencies.ts +41 -17
- package/dist/isolate-DtNAHzfa.mjs.map +0 -1
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import type { PackageManifest, PackagesRegistry } from "~/lib/types";
|
|
3
|
+
import { collectReachablePackageNames } from "./collect-reachable-package-names";
|
|
4
|
+
|
|
5
|
+
function entry(manifest: PackageManifest) {
|
|
6
|
+
return {
|
|
7
|
+
absoluteDir: `/workspace/packages/${manifest.name}`,
|
|
8
|
+
rootRelativeDir: `packages/${manifest.name}`,
|
|
9
|
+
manifest,
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
describe("collectReachablePackageNames", () => {
|
|
14
|
+
it("returns target direct deps", () => {
|
|
15
|
+
const manifest: PackageManifest = {
|
|
16
|
+
name: "app",
|
|
17
|
+
version: "1.0.0",
|
|
18
|
+
dependencies: { lodash: "^4.0.0", tslib: "^2.0.0" },
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const result = collectReachablePackageNames({
|
|
22
|
+
targetPackageManifest: manifest,
|
|
23
|
+
packagesRegistry: {},
|
|
24
|
+
includeDevDependencies: false,
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
expect([...result].sort()).toEqual(["lodash", "tslib"]);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("excludes target devDependencies when includeDevDependencies is false", () => {
|
|
31
|
+
const manifest: PackageManifest = {
|
|
32
|
+
name: "app",
|
|
33
|
+
version: "1.0.0",
|
|
34
|
+
dependencies: { lodash: "^4.0.0" },
|
|
35
|
+
devDependencies: { vitest: "^1.0.0" },
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const result = collectReachablePackageNames({
|
|
39
|
+
targetPackageManifest: manifest,
|
|
40
|
+
packagesRegistry: {},
|
|
41
|
+
includeDevDependencies: false,
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
expect(result.has("lodash")).toBe(true);
|
|
45
|
+
expect(result.has("vitest")).toBe(false);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it("includes target devDependencies when includeDevDependencies is true", () => {
|
|
49
|
+
const manifest: PackageManifest = {
|
|
50
|
+
name: "app",
|
|
51
|
+
version: "1.0.0",
|
|
52
|
+
dependencies: { lodash: "^4.0.0" },
|
|
53
|
+
devDependencies: { vitest: "^1.0.0" },
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const result = collectReachablePackageNames({
|
|
57
|
+
targetPackageManifest: manifest,
|
|
58
|
+
packagesRegistry: {},
|
|
59
|
+
includeDevDependencies: true,
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
expect([...result].sort()).toEqual(["lodash", "vitest"]);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it("recurses through internal workspace packages to pick up their deps", () => {
|
|
66
|
+
/** Mirrors issue #167: consumer → firebase-package (internal) → tslib */
|
|
67
|
+
const consumerManifest: PackageManifest = {
|
|
68
|
+
name: "consumer",
|
|
69
|
+
version: "1.0.0",
|
|
70
|
+
dependencies: { "firebase-package": "workspace:*" },
|
|
71
|
+
};
|
|
72
|
+
const firebaseManifest: PackageManifest = {
|
|
73
|
+
name: "firebase-package",
|
|
74
|
+
version: "1.0.0",
|
|
75
|
+
dependencies: { tslib: "^2.0.0" },
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const registry: PackagesRegistry = {
|
|
79
|
+
"firebase-package": entry(firebaseManifest),
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const result = collectReachablePackageNames({
|
|
83
|
+
targetPackageManifest: consumerManifest,
|
|
84
|
+
packagesRegistry: registry,
|
|
85
|
+
includeDevDependencies: false,
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
expect(result.has("firebase-package")).toBe(true);
|
|
89
|
+
expect(result.has("tslib")).toBe(true);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it("does not include devDependencies of internal packages", () => {
|
|
93
|
+
const consumerManifest: PackageManifest = {
|
|
94
|
+
name: "consumer",
|
|
95
|
+
version: "1.0.0",
|
|
96
|
+
dependencies: { "firebase-package": "workspace:*" },
|
|
97
|
+
};
|
|
98
|
+
const firebaseManifest: PackageManifest = {
|
|
99
|
+
name: "firebase-package",
|
|
100
|
+
version: "1.0.0",
|
|
101
|
+
dependencies: { tslib: "^2.0.0" },
|
|
102
|
+
devDependencies: { vitest: "^1.0.0" },
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const registry: PackagesRegistry = {
|
|
106
|
+
"firebase-package": entry(firebaseManifest),
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const result = collectReachablePackageNames({
|
|
110
|
+
targetPackageManifest: consumerManifest,
|
|
111
|
+
packagesRegistry: registry,
|
|
112
|
+
/**
|
|
113
|
+
* Even with includeDevDependencies true for the target, internal
|
|
114
|
+
* packages' devDependencies stay out — they aren't installed in the
|
|
115
|
+
* isolate.
|
|
116
|
+
*/
|
|
117
|
+
includeDevDependencies: true,
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
expect(result.has("tslib")).toBe(true);
|
|
121
|
+
expect(result.has("vitest")).toBe(false);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it("handles multi-level internal chains", () => {
|
|
125
|
+
const appManifest: PackageManifest = {
|
|
126
|
+
name: "app",
|
|
127
|
+
version: "1.0.0",
|
|
128
|
+
dependencies: { "pkg-a": "workspace:*" },
|
|
129
|
+
};
|
|
130
|
+
const pkgAManifest: PackageManifest = {
|
|
131
|
+
name: "pkg-a",
|
|
132
|
+
version: "1.0.0",
|
|
133
|
+
dependencies: { "pkg-b": "workspace:*" },
|
|
134
|
+
};
|
|
135
|
+
const pkgBManifest: PackageManifest = {
|
|
136
|
+
name: "pkg-b",
|
|
137
|
+
version: "1.0.0",
|
|
138
|
+
dependencies: { "@scope/leaf": "^1.0.0" },
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
const registry: PackagesRegistry = {
|
|
142
|
+
"pkg-a": entry(pkgAManifest),
|
|
143
|
+
"pkg-b": entry(pkgBManifest),
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
const result = collectReachablePackageNames({
|
|
147
|
+
targetPackageManifest: appManifest,
|
|
148
|
+
packagesRegistry: registry,
|
|
149
|
+
includeDevDependencies: false,
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
expect([...result].sort()).toEqual(["@scope/leaf", "pkg-a", "pkg-b"]);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it("walks optionalDependencies of target and internal packages", () => {
|
|
156
|
+
const appManifest: PackageManifest = {
|
|
157
|
+
name: "app",
|
|
158
|
+
version: "1.0.0",
|
|
159
|
+
dependencies: { "pkg-a": "workspace:*" },
|
|
160
|
+
optionalDependencies: { "optional-on-target": "^1.0.0" },
|
|
161
|
+
};
|
|
162
|
+
const pkgAManifest: PackageManifest = {
|
|
163
|
+
name: "pkg-a",
|
|
164
|
+
version: "1.0.0",
|
|
165
|
+
optionalDependencies: { "optional-on-internal": "^1.0.0" },
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
const registry: PackagesRegistry = {
|
|
169
|
+
"pkg-a": entry(pkgAManifest),
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
const result = collectReachablePackageNames({
|
|
173
|
+
targetPackageManifest: appManifest,
|
|
174
|
+
packagesRegistry: registry,
|
|
175
|
+
includeDevDependencies: false,
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
expect(result.has("optional-on-target")).toBe(true);
|
|
179
|
+
expect(result.has("optional-on-internal")).toBe(true);
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
it("walks peerDependencies of target and internal packages", () => {
|
|
183
|
+
/**
|
|
184
|
+
* With pnpm's default autoInstallPeers, peer deps typically end up
|
|
185
|
+
* installed in the isolate and may carry patches.
|
|
186
|
+
*/
|
|
187
|
+
const appManifest: PackageManifest = {
|
|
188
|
+
name: "app",
|
|
189
|
+
version: "1.0.0",
|
|
190
|
+
dependencies: { "pkg-a": "workspace:*" },
|
|
191
|
+
peerDependencies: { "peer-on-target": "^1.0.0" },
|
|
192
|
+
};
|
|
193
|
+
const pkgAManifest: PackageManifest = {
|
|
194
|
+
name: "pkg-a",
|
|
195
|
+
version: "1.0.0",
|
|
196
|
+
peerDependencies: { "peer-on-internal": "^1.0.0" },
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
const registry: PackagesRegistry = {
|
|
200
|
+
"pkg-a": entry(pkgAManifest),
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
const result = collectReachablePackageNames({
|
|
204
|
+
targetPackageManifest: appManifest,
|
|
205
|
+
packagesRegistry: registry,
|
|
206
|
+
includeDevDependencies: false,
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
expect(result.has("peer-on-target")).toBe(true);
|
|
210
|
+
expect(result.has("peer-on-internal")).toBe(true);
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
it("tolerates cycles between internal packages", () => {
|
|
214
|
+
/** Each package already visited is skipped on re-entry */
|
|
215
|
+
const aManifest: PackageManifest = {
|
|
216
|
+
name: "pkg-a",
|
|
217
|
+
version: "1.0.0",
|
|
218
|
+
dependencies: { "pkg-b": "workspace:*", tslib: "^2.0.0" },
|
|
219
|
+
};
|
|
220
|
+
const bManifest: PackageManifest = {
|
|
221
|
+
name: "pkg-b",
|
|
222
|
+
version: "1.0.0",
|
|
223
|
+
dependencies: { "pkg-a": "workspace:*" },
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
const registry: PackagesRegistry = {
|
|
227
|
+
"pkg-a": entry(aManifest),
|
|
228
|
+
"pkg-b": entry(bManifest),
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
const result = collectReachablePackageNames({
|
|
232
|
+
targetPackageManifest: aManifest,
|
|
233
|
+
packagesRegistry: registry,
|
|
234
|
+
includeDevDependencies: false,
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
expect([...result].sort()).toEqual(["pkg-a", "pkg-b", "tslib"]);
|
|
238
|
+
});
|
|
239
|
+
});
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { PackageManifest, PackagesRegistry } from "../types";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Walk the target manifest and the manifests of any internal (workspace)
|
|
5
|
+
* packages reachable from it, collecting every dependency name encountered
|
|
6
|
+
* (both internal and external).
|
|
7
|
+
*
|
|
8
|
+
* The resulting set is a superset of the target's direct dependencies: it also
|
|
9
|
+
* includes dependencies of internal workspace packages that will end up in the
|
|
10
|
+
* isolated output. This is used to filter workspace-level
|
|
11
|
+
* `patchedDependencies` so that patches for deps introduced via internal
|
|
12
|
+
* packages aren't dropped.
|
|
13
|
+
*
|
|
14
|
+
* `dependencies`, `optionalDependencies`, and `peerDependencies` are all
|
|
15
|
+
* walked — any of them can lead to a package being installed in the isolate
|
|
16
|
+
* (pnpm installs peers by default via `autoInstallPeers`). devDependencies of
|
|
17
|
+
* internal packages are never followed, and devDependencies of the *target*
|
|
18
|
+
* are followed only when `includeDevDependencies` is true.
|
|
19
|
+
*
|
|
20
|
+
* Note: only recurses through internal packages — manifests of external deps
|
|
21
|
+
* aren't available here. Deep external→external transitives therefore won't
|
|
22
|
+
* appear in the set.
|
|
23
|
+
*/
|
|
24
|
+
export function collectReachablePackageNames({
|
|
25
|
+
targetPackageManifest,
|
|
26
|
+
packagesRegistry,
|
|
27
|
+
includeDevDependencies,
|
|
28
|
+
}: {
|
|
29
|
+
targetPackageManifest: PackageManifest;
|
|
30
|
+
packagesRegistry: PackagesRegistry;
|
|
31
|
+
includeDevDependencies: boolean;
|
|
32
|
+
}): Set<string> {
|
|
33
|
+
const names = new Set<string>();
|
|
34
|
+
const visitedInternal = new Set<string>();
|
|
35
|
+
|
|
36
|
+
walk(targetPackageManifest, true);
|
|
37
|
+
|
|
38
|
+
return names;
|
|
39
|
+
|
|
40
|
+
function walk(manifest: PackageManifest, isTarget: boolean) {
|
|
41
|
+
const depNames = [
|
|
42
|
+
...Object.keys(manifest.dependencies ?? {}),
|
|
43
|
+
...Object.keys(manifest.optionalDependencies ?? {}),
|
|
44
|
+
...Object.keys(manifest.peerDependencies ?? {}),
|
|
45
|
+
...(isTarget && includeDevDependencies
|
|
46
|
+
? Object.keys(manifest.devDependencies ?? {})
|
|
47
|
+
: []),
|
|
48
|
+
];
|
|
49
|
+
|
|
50
|
+
for (const name of depNames) {
|
|
51
|
+
names.add(name);
|
|
52
|
+
|
|
53
|
+
const internalPkg = packagesRegistry[name];
|
|
54
|
+
if (internalPkg && !visitedInternal.has(name)) {
|
|
55
|
+
visitedInternal.add(name);
|
|
56
|
+
walk(internalPkg.manifest, false);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -182,6 +182,83 @@ describe("filterPatchedDependencies", () => {
|
|
|
182
182
|
expect(result).toBeUndefined();
|
|
183
183
|
});
|
|
184
184
|
|
|
185
|
+
it("should include patches for packages reachable via internal workspace packages", () => {
|
|
186
|
+
/** Issue #167: patch targets a transitive dep via an internal package */
|
|
187
|
+
const manifest: PackageManifest = {
|
|
188
|
+
name: "consumer",
|
|
189
|
+
version: "1.0.0",
|
|
190
|
+
dependencies: { "firebase-package": "file:./packages/firebase-package" },
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
const result = filterPatchedDependencies({
|
|
194
|
+
patchedDependencies: { "tslib@2.0.0": "patches/tslib.patch" },
|
|
195
|
+
targetPackageManifest: manifest,
|
|
196
|
+
includeDevDependencies: false,
|
|
197
|
+
reachableDependencyNames: new Set(["firebase-package", "tslib"]),
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
expect(result).toEqual({ "tslib@2.0.0": "patches/tslib.patch" });
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
it("should exclude patches for packages not in direct deps nor the reachable set", () => {
|
|
204
|
+
const manifest: PackageManifest = {
|
|
205
|
+
name: "consumer",
|
|
206
|
+
version: "1.0.0",
|
|
207
|
+
dependencies: { "firebase-package": "file:./packages/firebase-package" },
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
const result = filterPatchedDependencies({
|
|
211
|
+
patchedDependencies: { "unrelated@1.0.0": "patches/unrelated.patch" },
|
|
212
|
+
targetPackageManifest: manifest,
|
|
213
|
+
includeDevDependencies: false,
|
|
214
|
+
reachableDependencyNames: new Set(["firebase-package", "tslib"]),
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
expect(result).toBeUndefined();
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
it("should include a patch when a target devDep is also reachable as a prod transitive", () => {
|
|
221
|
+
/**
|
|
222
|
+
* The target lists `tslib` as a devDep and runs with
|
|
223
|
+
* includeDevDependencies=false, but `tslib` is also a prod dep of an
|
|
224
|
+
* internal workspace package that IS installed in the isolate. The
|
|
225
|
+
* patch must be preserved because tslib will be present at install
|
|
226
|
+
* time through the internal package.
|
|
227
|
+
*/
|
|
228
|
+
const manifest: PackageManifest = {
|
|
229
|
+
name: "app",
|
|
230
|
+
version: "1.0.0",
|
|
231
|
+
dependencies: { "firebase-package": "file:./packages/firebase-package" },
|
|
232
|
+
devDependencies: { tslib: "^2.0.0" },
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
const result = filterPatchedDependencies({
|
|
236
|
+
patchedDependencies: { "tslib@2.0.0": "patches/tslib.patch" },
|
|
237
|
+
targetPackageManifest: manifest,
|
|
238
|
+
includeDevDependencies: false,
|
|
239
|
+
reachableDependencyNames: new Set(["firebase-package", "tslib"]),
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
expect(result).toEqual({ "tslib@2.0.0": "patches/tslib.patch" });
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
it("should still exclude a pure target devDep patch when not reachable and dev deps are off", () => {
|
|
246
|
+
const manifest: PackageManifest = {
|
|
247
|
+
name: "app",
|
|
248
|
+
version: "1.0.0",
|
|
249
|
+
devDependencies: { vitest: "^1.0.0" },
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
const result = filterPatchedDependencies({
|
|
253
|
+
patchedDependencies: { "vitest@1.0.0": "patches/vitest.patch" },
|
|
254
|
+
targetPackageManifest: manifest,
|
|
255
|
+
includeDevDependencies: false,
|
|
256
|
+
reachableDependencyNames: new Set(),
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
expect(result).toBeUndefined();
|
|
260
|
+
});
|
|
261
|
+
|
|
185
262
|
it("should preserve patch value types", () => {
|
|
186
263
|
const manifest: PackageManifest = {
|
|
187
264
|
name: "test",
|
|
@@ -3,17 +3,26 @@ import type { PackageManifest } from "~/lib/types";
|
|
|
3
3
|
import { getPackageName } from "./get-package-name";
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
* Filters patched dependencies to only include patches for packages that
|
|
7
|
-
* present in the
|
|
6
|
+
* Filters patched dependencies to only include patches for packages that will
|
|
7
|
+
* be present in the isolated output, either as a direct dependency of the
|
|
8
|
+
* target or as a transitive dependency reachable through internal workspace
|
|
9
|
+
* packages.
|
|
8
10
|
*/
|
|
9
11
|
export function filterPatchedDependencies<T>({
|
|
10
12
|
patchedDependencies,
|
|
11
13
|
targetPackageManifest,
|
|
12
14
|
includeDevDependencies,
|
|
15
|
+
reachableDependencyNames,
|
|
13
16
|
}: {
|
|
14
17
|
patchedDependencies: Record<string, T> | undefined;
|
|
15
18
|
targetPackageManifest: PackageManifest;
|
|
16
19
|
includeDevDependencies: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Additional set of dependency names reachable from the target (e.g. via
|
|
22
|
+
* internal workspace packages). Used to preserve patches for transitive
|
|
23
|
+
* deps that are not listed directly on the target manifest.
|
|
24
|
+
*/
|
|
25
|
+
reachableDependencyNames?: Set<string>;
|
|
17
26
|
}): Record<string, T> | undefined {
|
|
18
27
|
const log = useLogger();
|
|
19
28
|
if (!patchedDependencies || typeof patchedDependencies !== "object") {
|
|
@@ -27,7 +36,7 @@ export function filterPatchedDependencies<T>({
|
|
|
27
36
|
for (const [packageSpec, patchInfo] of Object.entries(patchedDependencies)) {
|
|
28
37
|
const packageName = getPackageName(packageSpec);
|
|
29
38
|
|
|
30
|
-
/**
|
|
39
|
+
/** Direct production dependency */
|
|
31
40
|
if (targetPackageManifest.dependencies?.[packageName]) {
|
|
32
41
|
filteredPatches[packageSpec] = patchInfo;
|
|
33
42
|
includedCount++;
|
|
@@ -35,23 +44,38 @@ export function filterPatchedDependencies<T>({
|
|
|
35
44
|
continue;
|
|
36
45
|
}
|
|
37
46
|
|
|
38
|
-
/**
|
|
39
|
-
if (
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
47
|
+
/** Direct dev dependency (respects the dev-deps flag) */
|
|
48
|
+
if (
|
|
49
|
+
includeDevDependencies &&
|
|
50
|
+
targetPackageManifest.devDependencies?.[packageName]
|
|
51
|
+
) {
|
|
52
|
+
filteredPatches[packageSpec] = patchInfo;
|
|
53
|
+
includedCount++;
|
|
54
|
+
log.debug(`Including dev dependency patch: ${packageSpec}`);
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Reachable via an internal workspace package. This fires even when the
|
|
60
|
+
* package is also listed in the target's devDependencies with
|
|
61
|
+
* `includeDevDependencies=false`, because the package is still installed
|
|
62
|
+
* in the isolate as a prod transitive.
|
|
63
|
+
*/
|
|
64
|
+
if (reachableDependencyNames?.has(packageName)) {
|
|
65
|
+
filteredPatches[packageSpec] = patchInfo;
|
|
66
|
+
includedCount++;
|
|
67
|
+
log.debug(`Including transitive dependency patch: ${packageSpec}`);
|
|
48
68
|
continue;
|
|
49
69
|
}
|
|
50
70
|
|
|
51
|
-
/** Package
|
|
52
|
-
|
|
53
|
-
`Excluding patch: ${packageSpec}
|
|
54
|
-
|
|
71
|
+
/** Package won't be installed in the isolate */
|
|
72
|
+
if (targetPackageManifest.devDependencies?.[packageName]) {
|
|
73
|
+
log.debug(`Excluding dev dependency patch: ${packageSpec}`);
|
|
74
|
+
} else {
|
|
75
|
+
log.debug(
|
|
76
|
+
`Excluding patch: ${packageSpec} (package "${packageName}" not reachable from target)`,
|
|
77
|
+
);
|
|
78
|
+
}
|
|
55
79
|
excludedCount++;
|
|
56
80
|
}
|
|
57
81
|
|