isolate-package 1.33.0 → 1.35.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.
Files changed (68) hide show
  1. package/dist/index.mjs +1 -1
  2. package/dist/index.mjs.map +1 -1
  3. package/dist/isolate-bin.mjs +5 -6
  4. package/dist/isolate-bin.mjs.map +1 -1
  5. package/dist/{isolate-DyRD5Zd_.mjs → isolate-ts-Igq7C.mjs} +888 -271
  6. package/dist/isolate-ts-Igq7C.mjs.map +1 -0
  7. package/package.json +23 -19
  8. package/src/get-internal-package-names.test.ts +1 -1
  9. package/src/get-internal-package-names.ts +2 -2
  10. package/src/isolate-bin.ts +5 -5
  11. package/src/isolate.ts +22 -17
  12. package/src/lib/config.test.ts +1 -1
  13. package/src/lib/config.ts +3 -3
  14. package/src/lib/lockfile/helpers/bun-lockfile.ts +153 -0
  15. package/src/lib/lockfile/helpers/generate-bun-lockfile.test.ts +3 -3
  16. package/src/lib/lockfile/helpers/generate-bun-lockfile.ts +14 -146
  17. package/src/lib/lockfile/helpers/generate-npm-lockfile.integration.test.ts +1 -5
  18. package/src/lib/lockfile/helpers/generate-npm-lockfile.test.ts +311 -16
  19. package/src/lib/lockfile/helpers/generate-npm-lockfile.ts +193 -22
  20. package/src/lib/lockfile/helpers/generate-pnpm-lockfile.test.ts +83 -2
  21. package/src/lib/lockfile/helpers/generate-pnpm-lockfile.ts +33 -6
  22. package/src/lib/lockfile/helpers/generate-yarn-lockfile.ts +5 -5
  23. package/src/lib/lockfile/process-lockfile.test.ts +2 -2
  24. package/src/lib/manifest/adapt-target-package-manifest.ts +22 -13
  25. package/src/lib/manifest/helpers/adapt-internal-package-manifests.test.ts +72 -3
  26. package/src/lib/manifest/helpers/adapt-internal-package-manifests.ts +22 -12
  27. package/src/lib/manifest/helpers/adapt-manifest-internal-deps.ts +1 -1
  28. package/src/lib/manifest/helpers/adopt-pnpm-fields-from-root.test.ts +4 -4
  29. package/src/lib/manifest/helpers/adopt-pnpm-fields-from-root.ts +7 -7
  30. package/src/lib/manifest/helpers/resolve-catalog-dependencies.test.ts +410 -0
  31. package/src/lib/manifest/helpers/resolve-catalog-dependencies.ts +115 -27
  32. package/src/lib/manifest/io.ts +6 -2
  33. package/src/lib/manifest/validate-manifest.ts +2 -2
  34. package/src/lib/output/get-build-output-dir.ts +1 -1
  35. package/src/lib/output/pack-dependencies.ts +1 -1
  36. package/src/lib/output/process-build-output-files.ts +6 -17
  37. package/src/lib/package-manager/helpers/infer-from-files.ts +5 -5
  38. package/src/lib/package-manager/helpers/infer-from-manifest.ts +7 -8
  39. package/src/lib/package-manager/index.ts +1 -1
  40. package/src/lib/package-manager/names.ts +8 -10
  41. package/src/lib/patches/collect-installed-names-bun.test.ts +154 -0
  42. package/src/lib/patches/collect-installed-names-bun.ts +87 -0
  43. package/src/lib/patches/collect-installed-names-pnpm.test.ts +316 -0
  44. package/src/lib/patches/collect-installed-names-pnpm.ts +365 -0
  45. package/src/lib/patches/copy-patches.test.ts +130 -13
  46. package/src/lib/patches/copy-patches.ts +47 -10
  47. package/src/lib/patches/write-isolate-pnpm-workspace.test.ts +83 -3
  48. package/src/lib/patches/write-isolate-pnpm-workspace.ts +4 -4
  49. package/src/lib/registry/collect-reachable-package-names.test.ts +1 -1
  50. package/src/lib/registry/create-packages-registry.ts +34 -31
  51. package/src/lib/registry/helpers/find-packages-globs.ts +23 -19
  52. package/src/lib/registry/list-internal-packages.test.ts +2 -2
  53. package/src/lib/types.ts +2 -2
  54. package/src/lib/utils/filter-patched-dependencies.test.ts +1 -1
  55. package/src/lib/utils/filter-patched-dependencies.ts +2 -2
  56. package/src/lib/utils/get-dirname.ts +1 -1
  57. package/src/lib/utils/index.ts +1 -1
  58. package/src/lib/utils/json.ts +12 -14
  59. package/src/lib/utils/pack.ts +32 -22
  60. package/src/lib/utils/reset-isolate-dir.test.ts +165 -0
  61. package/src/lib/utils/reset-isolate-dir.ts +147 -0
  62. package/src/lib/utils/unpack.test.ts +76 -0
  63. package/src/lib/utils/unpack.ts +16 -10
  64. package/src/lib/utils/wait-for-complete-file.test.ts +105 -0
  65. package/src/lib/utils/wait-for-complete-file.ts +44 -0
  66. package/src/lib/utils/yaml.ts +8 -9
  67. package/src/testing/setup.ts +1 -1
  68. package/dist/isolate-DyRD5Zd_.mjs.map +0 -1
@@ -0,0 +1,410 @@
1
+ import os from "node:os";
2
+ import path from "node:path";
3
+ import fs from "fs-extra";
4
+ import yaml from "yaml";
5
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
6
+
7
+ const mockLogger = {
8
+ debug: vi.fn(),
9
+ warn: vi.fn(),
10
+ };
11
+
12
+ vi.mock("#/lib/logger", () => ({
13
+ useLogger: vi.fn(() => mockLogger),
14
+ }));
15
+
16
+ const { resolveCatalogDependencies } =
17
+ await import("./resolve-catalog-dependencies");
18
+
19
+ /**
20
+ * Creates a temporary directory with optional pnpm-workspace.yaml and
21
+ * package.json for testing catalog resolution.
22
+ */
23
+ async function createTempWorkspace({
24
+ workspaceYaml,
25
+ workspaceYamlRaw,
26
+ packageJson,
27
+ }: {
28
+ workspaceYaml?: object;
29
+ workspaceYamlRaw?: string;
30
+ packageJson?: object;
31
+ }): Promise<string> {
32
+ const dir = await fs.mkdtemp(path.join(os.tmpdir(), "isolate-test-"));
33
+
34
+ if (workspaceYaml !== undefined) {
35
+ await fs.writeFile(
36
+ path.join(dir, "pnpm-workspace.yaml"),
37
+ yaml.stringify(workspaceYaml),
38
+ "utf-8",
39
+ );
40
+ } else if (workspaceYamlRaw !== undefined) {
41
+ await fs.writeFile(
42
+ path.join(dir, "pnpm-workspace.yaml"),
43
+ workspaceYamlRaw,
44
+ "utf-8",
45
+ );
46
+ }
47
+
48
+ /** Always write a minimal package.json so the fallback doesn't throw. */
49
+ const manifest = packageJson ?? { name: "root", version: "0.0.0" };
50
+ await fs.writeJson(path.join(dir, "package.json"), manifest);
51
+
52
+ return dir;
53
+ }
54
+
55
+ describe("resolveCatalogDependencies", () => {
56
+ let tmpDir: string;
57
+
58
+ beforeEach(() => {
59
+ vi.clearAllMocks();
60
+ });
61
+
62
+ afterEach(async () => {
63
+ if (tmpDir) {
64
+ await fs.remove(tmpDir);
65
+ }
66
+ });
67
+
68
+ describe("with no dependencies", () => {
69
+ it("returns undefined when dependencies is undefined", async () => {
70
+ tmpDir = await createTempWorkspace({});
71
+ const result = await resolveCatalogDependencies(undefined, tmpDir);
72
+ expect(result).toBeUndefined();
73
+ });
74
+ });
75
+
76
+ describe("pnpm-workspace.yaml: default catalog (catalog:)", () => {
77
+ it("resolves catalog: specifiers from pnpm-workspace.yaml", async () => {
78
+ tmpDir = await createTempWorkspace({
79
+ workspaceYaml: {
80
+ packages: ["packages/*"],
81
+ catalog: {
82
+ react: "^18.3.1",
83
+ typescript: "^5.0.0",
84
+ },
85
+ },
86
+ });
87
+
88
+ const result = await resolveCatalogDependencies(
89
+ { react: "catalog:", typescript: "catalog:", lodash: "^4.0.0" },
90
+ tmpDir,
91
+ );
92
+
93
+ expect(result).toEqual({
94
+ react: "^18.3.1",
95
+ typescript: "^5.0.0",
96
+ lodash: "^4.0.0",
97
+ });
98
+ });
99
+
100
+ it("also handles catalog:default as the default catalog name", async () => {
101
+ tmpDir = await createTempWorkspace({
102
+ workspaceYaml: {
103
+ packages: ["packages/*"],
104
+ catalogs: {
105
+ default: {
106
+ react: "^18.3.1",
107
+ },
108
+ },
109
+ },
110
+ });
111
+
112
+ const result = await resolveCatalogDependencies(
113
+ { react: "catalog:default" },
114
+ tmpDir,
115
+ );
116
+
117
+ expect(result).toEqual({ react: "^18.3.1" });
118
+ });
119
+
120
+ it("resolves catalog:default from the top-level catalog field", async () => {
121
+ tmpDir = await createTempWorkspace({
122
+ workspaceYaml: {
123
+ packages: ["packages/*"],
124
+ catalog: {
125
+ react: "^18.3.1",
126
+ },
127
+ },
128
+ });
129
+
130
+ const result = await resolveCatalogDependencies(
131
+ { react: "catalog:default" },
132
+ tmpDir,
133
+ );
134
+
135
+ expect(result).toEqual({ react: "^18.3.1" });
136
+ });
137
+ });
138
+
139
+ describe("pnpm-workspace.yaml: named catalogs (catalog:<name>)", () => {
140
+ it("resolves named catalog specifiers from pnpm-workspace.yaml", async () => {
141
+ tmpDir = await createTempWorkspace({
142
+ workspaceYaml: {
143
+ packages: ["packages/*"],
144
+ catalogs: {
145
+ react18: {
146
+ react: "^18.3.1",
147
+ "react-dom": "^18.3.1",
148
+ },
149
+ react19: {
150
+ react: "^19.0.0",
151
+ },
152
+ },
153
+ },
154
+ });
155
+
156
+ const result = await resolveCatalogDependencies(
157
+ {
158
+ react: "catalog:react18",
159
+ "react-dom": "catalog:react18",
160
+ },
161
+ tmpDir,
162
+ );
163
+
164
+ expect(result).toEqual({
165
+ react: "^18.3.1",
166
+ "react-dom": "^18.3.1",
167
+ });
168
+ });
169
+ });
170
+
171
+ describe("pnpm-workspace.yaml: missing package in catalog", () => {
172
+ it("keeps original specifier and warns when package not found in catalog", async () => {
173
+ tmpDir = await createTempWorkspace({
174
+ workspaceYaml: {
175
+ packages: ["packages/*"],
176
+ catalog: { react: "^18.0.0" },
177
+ },
178
+ });
179
+
180
+ const result = await resolveCatalogDependencies(
181
+ { react: "catalog:", "missing-pkg": "catalog:" },
182
+ tmpDir,
183
+ );
184
+
185
+ expect(result).toEqual({
186
+ react: "^18.0.0",
187
+ "missing-pkg": "catalog:", // kept as-is with a warning
188
+ });
189
+ });
190
+ });
191
+
192
+ describe("package.json fallback (Bun format)", () => {
193
+ it("resolves catalog: from root-level catalog field in package.json", async () => {
194
+ tmpDir = await createTempWorkspace({
195
+ packageJson: {
196
+ name: "root",
197
+ version: "0.0.0",
198
+ catalog: {
199
+ react: "^18.3.1",
200
+ },
201
+ },
202
+ });
203
+
204
+ const result = await resolveCatalogDependencies(
205
+ { react: "catalog:" },
206
+ tmpDir,
207
+ );
208
+
209
+ expect(result).toEqual({ react: "^18.3.1" });
210
+ });
211
+
212
+ it("resolves catalog: from workspaces.catalog in package.json", async () => {
213
+ tmpDir = await createTempWorkspace({
214
+ packageJson: {
215
+ name: "root",
216
+ version: "0.0.0",
217
+ workspaces: {
218
+ packages: ["packages/*"],
219
+ catalog: {
220
+ typescript: "^5.4.0",
221
+ },
222
+ },
223
+ },
224
+ });
225
+
226
+ const result = await resolveCatalogDependencies(
227
+ { typescript: "catalog:" },
228
+ tmpDir,
229
+ );
230
+
231
+ expect(result).toEqual({ typescript: "^5.4.0" });
232
+ });
233
+
234
+ it("resolves named catalog: from root-level catalogs field in package.json", async () => {
235
+ tmpDir = await createTempWorkspace({
236
+ packageJson: {
237
+ name: "root",
238
+ version: "0.0.0",
239
+ catalogs: {
240
+ react18: {
241
+ react: "^18.3.1",
242
+ "react-dom": "^18.3.1",
243
+ },
244
+ },
245
+ },
246
+ });
247
+
248
+ const result = await resolveCatalogDependencies(
249
+ {
250
+ react: "catalog:react18",
251
+ "react-dom": "catalog:react18",
252
+ },
253
+ tmpDir,
254
+ );
255
+
256
+ expect(result).toEqual({
257
+ react: "^18.3.1",
258
+ "react-dom": "^18.3.1",
259
+ });
260
+ });
261
+
262
+ it("resolves named catalog: from workspaces.catalogs in package.json", async () => {
263
+ tmpDir = await createTempWorkspace({
264
+ packageJson: {
265
+ name: "root",
266
+ version: "0.0.0",
267
+ workspaces: {
268
+ packages: ["packages/*"],
269
+ catalogs: {
270
+ tools: {
271
+ typescript: "^5.4.0",
272
+ eslint: "^8.0.0",
273
+ },
274
+ },
275
+ },
276
+ },
277
+ });
278
+
279
+ const result = await resolveCatalogDependencies(
280
+ { typescript: "catalog:tools", eslint: "catalog:tools" },
281
+ tmpDir,
282
+ );
283
+
284
+ expect(result).toEqual({
285
+ typescript: "^5.4.0",
286
+ eslint: "^8.0.0",
287
+ });
288
+ });
289
+ });
290
+
291
+ describe("precedence", () => {
292
+ it("prefers pnpm-workspace.yaml over package.json when both define the same catalog dependency", async () => {
293
+ tmpDir = await createTempWorkspace({
294
+ workspaceYaml: {
295
+ packages: ["packages/*"],
296
+ catalog: {
297
+ react: "^18.3.1",
298
+ },
299
+ },
300
+ packageJson: {
301
+ name: "root",
302
+ version: "0.0.0",
303
+ catalog: {
304
+ react: "^18.2.0",
305
+ },
306
+ },
307
+ });
308
+
309
+ const result = await resolveCatalogDependencies(
310
+ { react: "catalog:" },
311
+ tmpDir,
312
+ );
313
+
314
+ expect(result).toEqual({ react: "^18.3.1" });
315
+ });
316
+ });
317
+
318
+ describe("pnpm-workspace.yaml with invalid YAML", () => {
319
+ it("warns about invalid YAML and falls back to package.json", async () => {
320
+ tmpDir = await createTempWorkspace({
321
+ workspaceYamlRaw: "catalog:\n react: ^18.3.1\n - invalid format",
322
+ packageJson: {
323
+ name: "root",
324
+ version: "0.0.0",
325
+ catalog: { react: "^18.0.0" },
326
+ },
327
+ });
328
+
329
+ const result = await resolveCatalogDependencies(
330
+ { react: "catalog:" },
331
+ tmpDir,
332
+ );
333
+
334
+ /** Verify it fell back to package.json correctly. */
335
+ expect(result).toEqual({ react: "^18.0.0" });
336
+
337
+ /** Verify a warning was logged. */
338
+ expect(mockLogger.warn).toHaveBeenCalledWith(
339
+ expect.stringContaining(
340
+ `Failed to parse ${path.join(tmpDir, "pnpm-workspace.yaml")}:`,
341
+ ),
342
+ );
343
+ });
344
+ });
345
+
346
+ describe("pnpm-workspace.yaml without catalog fields", () => {
347
+ it("falls back to package.json when pnpm-workspace.yaml has no catalog", async () => {
348
+ tmpDir = await createTempWorkspace({
349
+ workspaceYaml: {
350
+ /** No catalog or catalogs field - just packages. */
351
+ packages: ["packages/*"],
352
+ },
353
+ packageJson: {
354
+ name: "root",
355
+ version: "0.0.0",
356
+ catalog: { react: "^18.0.0" },
357
+ },
358
+ });
359
+
360
+ const result = await resolveCatalogDependencies(
361
+ { react: "catalog:" },
362
+ tmpDir,
363
+ );
364
+
365
+ expect(result).toEqual({ react: "^18.0.0" });
366
+ });
367
+ });
368
+
369
+ describe("no catalog defined anywhere", () => {
370
+ it("returns dependencies as-is when no catalog is found", async () => {
371
+ tmpDir = await createTempWorkspace({});
372
+
373
+ const result = await resolveCatalogDependencies(
374
+ { react: "^18.0.0", typescript: "^5.0.0" },
375
+ tmpDir,
376
+ );
377
+
378
+ expect(result).toEqual({
379
+ react: "^18.0.0",
380
+ typescript: "^5.0.0",
381
+ });
382
+ });
383
+ });
384
+
385
+ describe("non-catalog specifiers", () => {
386
+ it("leaves non-catalog specifiers unchanged", async () => {
387
+ tmpDir = await createTempWorkspace({
388
+ workspaceYaml: {
389
+ packages: ["packages/*"],
390
+ catalog: { react: "^18.0.0" },
391
+ },
392
+ });
393
+
394
+ const result = await resolveCatalogDependencies(
395
+ {
396
+ react: "catalog:",
397
+ lodash: "^4.0.0",
398
+ typescript: "workspace:*",
399
+ },
400
+ tmpDir,
401
+ );
402
+
403
+ expect(result).toEqual({
404
+ react: "^18.0.0",
405
+ lodash: "^4.0.0",
406
+ typescript: "workspace:*",
407
+ });
408
+ });
409
+ });
410
+ });
@@ -1,16 +1,112 @@
1
+ import fs from "fs-extra";
1
2
  import path from "node:path";
2
- import { useLogger } from "~/lib/logger";
3
- import type { PackageManifest } from "~/lib/types";
4
- import { readTypedJson } from "~/lib/utils";
3
+ import { useLogger } from "#/lib/logger";
4
+ import type { PackageManifest } from "#/lib/types";
5
+ import { readTypedJson } from "#/lib/utils";
6
+ import yaml from "yaml";
7
+
8
+ type CatalogMap = Record<string, string>;
9
+ type CatalogsMap = Record<string, CatalogMap>;
10
+
11
+ type CatalogSource = {
12
+ catalog?: CatalogMap;
13
+ catalogs?: CatalogsMap;
14
+ };
15
+
16
+ const catalogSourceCache = new Map<string, Promise<CatalogSource>>();
17
+
18
+ /**
19
+ * Loads catalog definitions by checking pnpm-workspace.yaml first (pnpm
20
+ * format), then falling back to the root package.json (Bun format).
21
+ *
22
+ * Pnpm defines catalogs in pnpm-workspace.yaml:
23
+ *
24
+ * ```yaml
25
+ * catalog:
26
+ * react: ^18.3.1
27
+ * catalogs:
28
+ * react18:
29
+ * react: ^18.3.1
30
+ * ```
31
+ *
32
+ * Bun defines catalogs in package.json (at root level or under workspaces).
33
+ */
34
+ async function loadCatalogSource(
35
+ workspaceRootDir: string,
36
+ ): Promise<CatalogSource> {
37
+ const cached = catalogSourceCache.get(workspaceRootDir);
38
+ if (cached) {
39
+ return cached;
40
+ }
41
+
42
+ const loadPromise = (async () => {
43
+ const log = useLogger();
44
+
45
+ /** Try pnpm-workspace.yaml first. */
46
+ const workspaceYamlPath = path.join(
47
+ workspaceRootDir,
48
+ "pnpm-workspace.yaml",
49
+ );
50
+
51
+ if (await fs.pathExists(workspaceYamlPath)) {
52
+ try {
53
+ const rawContent = await fs.readFile(workspaceYamlPath, "utf-8");
54
+ const yamlConfig = yaml.parse(rawContent) as CatalogSource | null;
55
+
56
+ if (yamlConfig?.catalog || yamlConfig?.catalogs) {
57
+ return {
58
+ catalog: yamlConfig.catalog,
59
+ catalogs: yamlConfig.catalogs,
60
+ };
61
+ }
62
+ } catch (error) {
63
+ log.warn(
64
+ `Failed to parse ${workspaceYamlPath}: ${error instanceof Error ? error.message : String(error)}. Falling back to package.json for catalog definitions.`,
65
+ );
66
+ }
67
+ }
68
+
69
+ /** Fall back to package.json (Bun format). */
70
+ const rootManifestPath = path.join(workspaceRootDir, "package.json");
71
+ const rootManifest = (await readTypedJson(
72
+ rootManifestPath,
73
+ )) as PackageManifest & {
74
+ catalog?: CatalogMap;
75
+ catalogs?: CatalogsMap;
76
+ workspaces?: {
77
+ catalog?: CatalogMap;
78
+ catalogs?: CatalogsMap;
79
+ };
80
+ };
81
+
82
+ return {
83
+ catalog: rootManifest.catalog ?? rootManifest.workspaces?.catalog,
84
+ catalogs: rootManifest.catalogs ?? rootManifest.workspaces?.catalogs,
85
+ };
86
+ })();
87
+
88
+ /**
89
+ * Drop the cache entry if loading fails so a subsequent call can retry
90
+ * instead of immediately rethrowing the same rejection.
91
+ */
92
+ const cachedLoadPromise = loadPromise.catch((error) => {
93
+ catalogSourceCache.delete(workspaceRootDir);
94
+ throw error;
95
+ });
96
+
97
+ catalogSourceCache.set(workspaceRootDir, cachedLoadPromise);
98
+ return cachedLoadPromise;
99
+ }
5
100
 
6
101
  /**
7
102
  * Resolves catalog dependencies by replacing "catalog:" specifiers with their
8
- * actual versions from the root package.json catalog field.
103
+ * actual versions.
9
104
  *
10
105
  * Supports both pnpm and Bun catalog formats:
11
106
  *
12
- * - Pnpm: catalog at root level
13
- * - Bun: catalog or catalogs at root level, or workspaces.catalog
107
+ * - Pnpm: catalog/catalogs defined in pnpm-workspace.yaml
108
+ * - Bun: catalog or catalogs at root level, or workspaces.catalog in
109
+ * package.json
14
110
  */
15
111
  export async function resolveCatalogDependencies(
16
112
  dependencies: Record<string, string> | undefined,
@@ -21,22 +117,8 @@ export async function resolveCatalogDependencies(
21
117
  }
22
118
 
23
119
  const log = useLogger();
24
- const rootManifestPath = path.join(workspaceRootDir, "package.json");
25
- const rootManifest = await readTypedJson<
26
- PackageManifest & {
27
- catalog?: Record<string, string>;
28
- catalogs?: Record<string, Record<string, string>>;
29
- workspaces?: {
30
- catalog?: Record<string, string>;
31
- catalogs?: Record<string, Record<string, string>>;
32
- };
33
- }
34
- >(rootManifestPath);
35
-
36
- // Try to find catalog in various locations (pnpm and Bun formats)
37
- const flatCatalog = rootManifest.catalog || rootManifest.workspaces?.catalog;
38
- const nestedCatalogs =
39
- rootManifest.catalogs || rootManifest.workspaces?.catalogs;
120
+ const { catalog: flatCatalog, catalogs: nestedCatalogs } =
121
+ await loadCatalogSource(workspaceRootDir);
40
122
 
41
123
  if (!flatCatalog && !nestedCatalogs) {
42
124
  // No catalog found, return dependencies as-is
@@ -50,12 +132,18 @@ export async function resolveCatalogDependencies(
50
132
  if (specifier === "catalog:" || specifier.startsWith("catalog:")) {
51
133
  let catalogVersion: string | undefined;
52
134
 
53
- if (specifier === "catalog:") {
54
- // Simple catalog reference - use package name as key
55
- catalogVersion = flatCatalog?.[packageName];
135
+ const groupName =
136
+ specifier === "catalog:" ? "default" : specifier.slice(8);
137
+
138
+ if (groupName === "default") {
139
+ /**
140
+ * Per pnpm semantics, `catalog:` and `catalog:default` are
141
+ * equivalent: the default catalog can live under the top-level
142
+ * `catalog` field or under `catalogs.default`, so check both.
143
+ */
144
+ catalogVersion =
145
+ flatCatalog?.[packageName] ?? nestedCatalogs?.default?.[packageName];
56
146
  } else {
57
- // Catalog group reference (e.g., "catalog:group1")
58
- const groupName = specifier.slice(8);
59
147
  catalogVersion = nestedCatalogs?.[groupName]?.[packageName];
60
148
  }
61
149
 
@@ -3,8 +3,12 @@ import path from "node:path";
3
3
  import type { PackageManifest } from "../types";
4
4
  import { readTypedJson } from "../utils";
5
5
 
6
- export async function readManifest(packageDir: string) {
7
- return readTypedJson<PackageManifest>(path.join(packageDir, "package.json"));
6
+ export async function readManifest(
7
+ packageDir: string,
8
+ ): Promise<PackageManifest> {
9
+ return (await readTypedJson(
10
+ path.join(packageDir, "package.json"),
11
+ )) as PackageManifest;
8
12
  }
9
13
 
10
14
  export async function writeManifest(
@@ -45,8 +45,8 @@ export function validateManifestMandatoryFields(
45
45
  missingFields.push("files");
46
46
  }
47
47
 
48
- if (missingFields.length > 0) {
49
- const field = missingFields[0]!;
48
+ const [field] = missingFields;
49
+ if (field) {
50
50
  const errorMessage =
51
51
  missingFields.length === 1
52
52
  ? `Package at ${packagePath} is missing the "${field}" field in its package.json. See ${fieldDocUrls[field] ?? "https://isolate-package.codecompose.dev/getting-started#prerequisites"}`
@@ -3,7 +3,7 @@ import path from "node:path";
3
3
  import outdent from "outdent";
4
4
  import { useLogger } from "../logger";
5
5
 
6
- export async function getBuildOutputDir({
6
+ export function getBuildOutputDir({
7
7
  targetPackageDir,
8
8
  buildDirName,
9
9
  tsconfigPath,
@@ -2,7 +2,7 @@ import { got } from "get-or-throw";
2
2
  import assert from "node:assert";
3
3
  import { useLogger } from "../logger";
4
4
  import type { PackagesRegistry } from "../types";
5
- import { pack } from "../utils";
5
+ import { pack } from "../utils/pack";
6
6
 
7
7
  /**
8
8
  * Pack dependencies so that we extract only the files that are supposed to be
@@ -1,9 +1,7 @@
1
1
  import fs from "fs-extra";
2
2
  import path from "node:path";
3
- import { useLogger } from "../logger";
4
- import { pack, unpack } from "../utils";
5
-
6
- const TIMEOUT_MS = 5000;
3
+ import { unpack } from "../utils";
4
+ import { pack } from "../utils/pack";
7
5
 
8
6
  export async function processBuildOutputFiles({
9
7
  targetPackageDir,
@@ -14,22 +12,13 @@ export async function processBuildOutputFiles({
14
12
  tmpDir: string;
15
13
  isolateDir: string;
16
14
  }) {
17
- const log = useLogger();
18
-
19
15
  const packedFilePath = await pack(targetPackageDir, tmpDir);
20
16
  const unpackDir = path.join(tmpDir, "target");
21
17
 
22
- const now = Date.now();
23
- let isWaitingYet = false;
24
-
25
- while (!fs.existsSync(packedFilePath) && Date.now() - now < TIMEOUT_MS) {
26
- if (!isWaitingYet) {
27
- log.debug(`Waiting for ${packedFilePath} to become available...`);
28
- }
29
- isWaitingYet = true;
30
- await new Promise((resolve) => setTimeout(resolve, 100));
31
- }
32
-
18
+ /**
19
+ * `pack` already waits for the tarball to be fully written before returning,
20
+ * so it is safe to unpack immediately.
21
+ */
33
22
  await unpack(packedFilePath, unpackDir);
34
23
  await fs.copy(path.join(unpackDir, "package"), isolateDir);
35
24
  }
@@ -1,8 +1,8 @@
1
1
  import fs from "fs-extra";
2
2
  import { execSync } from "node:child_process";
3
3
  import path from "node:path";
4
- import { getErrorMessage } from "~/lib/utils";
5
- import { getMajorVersion } from "~/lib/utils/get-major-version";
4
+ import { getErrorMessage } from "#/lib/utils";
5
+ import { getMajorVersion } from "#/lib/utils/get-major-version";
6
6
  import type { PackageManager, PackageManagerName } from "../names";
7
7
  import { getLockfileFileName, supportedPackageManagerNames } from "../names";
8
8
 
@@ -15,10 +15,10 @@ export function inferFromFiles(workspaceRoot: string): PackageManager {
15
15
  const version = getVersion(name);
16
16
 
17
17
  return { name, version, majorVersion: getMajorVersion(version) };
18
- } catch (err) {
18
+ } catch (error) {
19
19
  throw new Error(
20
- `Failed to find package manager version for ${name}: ${getErrorMessage(err)}`,
21
- { cause: err },
20
+ `Failed to find package manager version for ${name}: ${getErrorMessage(error)}`,
21
+ { cause: error },
22
22
  );
23
23
  }
24
24
  }