isolate-package 1.30.0-0 → 1.30.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.d.mts +7 -1
- package/dist/index.mjs +2 -3
- package/dist/index.mjs.map +1 -1
- package/dist/{isolate-BZjQHi0U.mjs → isolate-CJy3YyKG.mjs} +85 -69
- package/dist/isolate-CJy3YyKG.mjs.map +1 -0
- package/dist/isolate-bin.mjs +3 -5
- package/dist/isolate-bin.mjs.map +1 -1
- package/package.json +21 -20
- package/src/index.ts +6 -0
- package/src/isolate.ts +13 -5
- package/src/lib/lockfile/helpers/generate-bun-lockfile.ts +17 -3
- package/src/lib/manifest/adapt-target-package-manifest.ts +2 -1
- package/src/lib/manifest/helpers/adapt-internal-package-manifests.test.ts +181 -0
- package/src/lib/manifest/helpers/adapt-internal-package-manifests.ts +17 -5
- package/src/lib/manifest/helpers/adopt-pnpm-fields-from-root.test.ts +61 -0
- package/src/lib/manifest/helpers/adopt-pnpm-fields-from-root.ts +42 -3
- package/src/lib/manifest/validate-manifest.test.ts +19 -10
- package/src/lib/manifest/validate-manifest.ts +13 -1
- package/src/lib/patches/copy-patches.test.ts +316 -243
- package/src/lib/patches/copy-patches.ts +54 -15
- package/src/lib/types.ts +6 -0
- package/dist/isolate-BZjQHi0U.mjs.map +0 -1
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, vi } from "vitest";
|
|
2
|
+
import type { PackageManifest, PackagesRegistry } from "~/lib/types";
|
|
3
|
+
|
|
4
|
+
/** Mock dependencies */
|
|
5
|
+
vi.mock("~/lib/package-manager", () => ({
|
|
6
|
+
usePackageManager: vi.fn(),
|
|
7
|
+
}));
|
|
8
|
+
|
|
9
|
+
vi.mock("../io", () => ({
|
|
10
|
+
writeManifest: vi.fn(),
|
|
11
|
+
}));
|
|
12
|
+
|
|
13
|
+
vi.mock("./adapt-manifest-internal-deps", () => ({
|
|
14
|
+
adaptManifestInternalDeps: vi.fn(({ manifest }) => manifest),
|
|
15
|
+
}));
|
|
16
|
+
|
|
17
|
+
vi.mock("./resolve-catalog-dependencies", () => ({
|
|
18
|
+
resolveCatalogDependencies: vi.fn((deps) => Promise.resolve(deps)),
|
|
19
|
+
}));
|
|
20
|
+
|
|
21
|
+
const { usePackageManager } = vi.mocked(await import("~/lib/package-manager"));
|
|
22
|
+
|
|
23
|
+
const { writeManifest } = vi.mocked(await import("../io"));
|
|
24
|
+
|
|
25
|
+
const { adaptInternalPackageManifests } =
|
|
26
|
+
await import("./adapt-internal-package-manifests");
|
|
27
|
+
|
|
28
|
+
describe("adaptInternalPackageManifests", () => {
|
|
29
|
+
beforeEach(() => {
|
|
30
|
+
vi.clearAllMocks();
|
|
31
|
+
usePackageManager.mockReturnValue({
|
|
32
|
+
name: "pnpm",
|
|
33
|
+
version: "9.0.0",
|
|
34
|
+
majorVersion: 9,
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
function createRegistry(
|
|
39
|
+
entries: Record<
|
|
40
|
+
string,
|
|
41
|
+
{ rootRelativeDir: string; manifest: PackageManifest }
|
|
42
|
+
>,
|
|
43
|
+
): PackagesRegistry {
|
|
44
|
+
const registry: PackagesRegistry = {};
|
|
45
|
+
for (const [name, { rootRelativeDir, manifest }] of Object.entries(
|
|
46
|
+
entries,
|
|
47
|
+
)) {
|
|
48
|
+
registry[name] = {
|
|
49
|
+
absoluteDir: `/workspace/${rootRelativeDir}`,
|
|
50
|
+
rootRelativeDir,
|
|
51
|
+
manifest,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
return registry;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
it("should preserve scripts in internal dependency manifests", async () => {
|
|
58
|
+
const manifest: PackageManifest = {
|
|
59
|
+
name: "@repo/database",
|
|
60
|
+
version: "1.0.0",
|
|
61
|
+
scripts: {
|
|
62
|
+
postinstall: "prisma generate",
|
|
63
|
+
build: "tsc",
|
|
64
|
+
},
|
|
65
|
+
dependencies: {
|
|
66
|
+
prisma: "^5.0.0",
|
|
67
|
+
},
|
|
68
|
+
devDependencies: {
|
|
69
|
+
typescript: "^5.0.0",
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const packagesRegistry = createRegistry({
|
|
74
|
+
"@repo/database": {
|
|
75
|
+
rootRelativeDir: "packages/database",
|
|
76
|
+
manifest,
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
await adaptInternalPackageManifests({
|
|
81
|
+
internalPackageNames: ["@repo/database"],
|
|
82
|
+
packagesRegistry,
|
|
83
|
+
isolateDir: "/output",
|
|
84
|
+
forceNpm: false,
|
|
85
|
+
workspaceRootDir: "/workspace",
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
expect(writeManifest).toHaveBeenCalledOnce();
|
|
89
|
+
|
|
90
|
+
const writtenManifest = writeManifest.mock.calls[0]![1];
|
|
91
|
+
|
|
92
|
+
expect(writtenManifest.scripts).toEqual({
|
|
93
|
+
postinstall: "prisma generate",
|
|
94
|
+
build: "tsc",
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it("should strip the prepare script from internal dependency manifests", async () => {
|
|
99
|
+
const manifest: PackageManifest = {
|
|
100
|
+
name: "@repo/common",
|
|
101
|
+
version: "1.0.0",
|
|
102
|
+
scripts: {
|
|
103
|
+
prepare: "npm run clean && npm run build",
|
|
104
|
+
clean: "del-cli dist",
|
|
105
|
+
build: "tsdown",
|
|
106
|
+
postinstall: "prisma generate",
|
|
107
|
+
},
|
|
108
|
+
dependencies: {
|
|
109
|
+
ky: "^1.0.0",
|
|
110
|
+
},
|
|
111
|
+
devDependencies: {
|
|
112
|
+
"del-cli": "^7.0.0",
|
|
113
|
+
tsdown: "^0.20.0",
|
|
114
|
+
},
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
const packagesRegistry = createRegistry({
|
|
118
|
+
"@repo/common": {
|
|
119
|
+
rootRelativeDir: "packages/common",
|
|
120
|
+
manifest,
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
await adaptInternalPackageManifests({
|
|
125
|
+
internalPackageNames: ["@repo/common"],
|
|
126
|
+
packagesRegistry,
|
|
127
|
+
isolateDir: "/output",
|
|
128
|
+
forceNpm: false,
|
|
129
|
+
workspaceRootDir: "/workspace",
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
expect(writeManifest).toHaveBeenCalledOnce();
|
|
133
|
+
|
|
134
|
+
const writtenManifest = writeManifest.mock.calls[0]![1];
|
|
135
|
+
|
|
136
|
+
/** prepare should be stripped because it depends on devDependency binaries */
|
|
137
|
+
expect(writtenManifest.scripts?.prepare).toBeUndefined();
|
|
138
|
+
|
|
139
|
+
/** Other scripts should be preserved */
|
|
140
|
+
expect(writtenManifest.scripts).toEqual({
|
|
141
|
+
clean: "del-cli dist",
|
|
142
|
+
build: "tsdown",
|
|
143
|
+
postinstall: "prisma generate",
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it("should strip devDependencies from internal dependency manifests", async () => {
|
|
148
|
+
const manifest: PackageManifest = {
|
|
149
|
+
name: "@repo/shared",
|
|
150
|
+
version: "1.0.0",
|
|
151
|
+
dependencies: {
|
|
152
|
+
lodash: "^4.0.0",
|
|
153
|
+
},
|
|
154
|
+
devDependencies: {
|
|
155
|
+
vitest: "^1.0.0",
|
|
156
|
+
typescript: "^5.0.0",
|
|
157
|
+
},
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
const packagesRegistry = createRegistry({
|
|
161
|
+
"@repo/shared": {
|
|
162
|
+
rootRelativeDir: "packages/shared",
|
|
163
|
+
manifest,
|
|
164
|
+
},
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
await adaptInternalPackageManifests({
|
|
168
|
+
internalPackageNames: ["@repo/shared"],
|
|
169
|
+
packagesRegistry,
|
|
170
|
+
isolateDir: "/output",
|
|
171
|
+
forceNpm: false,
|
|
172
|
+
workspaceRootDir: "/workspace",
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
expect(writeManifest).toHaveBeenCalledOnce();
|
|
176
|
+
|
|
177
|
+
const writtenManifest = writeManifest.mock.calls[0]![1];
|
|
178
|
+
|
|
179
|
+
expect(writtenManifest.devDependencies).toBeUndefined();
|
|
180
|
+
});
|
|
181
|
+
});
|
|
@@ -31,8 +31,19 @@ export async function adaptInternalPackageManifests({
|
|
|
31
31
|
internalPackageNames.map(async (packageName) => {
|
|
32
32
|
const { manifest, rootRelativeDir } = got(packagesRegistry, packageName);
|
|
33
33
|
|
|
34
|
-
/** Dev dependencies
|
|
35
|
-
const strippedManifest = omit(manifest, ["
|
|
34
|
+
/** Dev dependencies are never included for internal deps */
|
|
35
|
+
const strippedManifest = omit(manifest, ["devDependencies"]);
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Strip the `prepare` script because it runs during `pnpm install` and
|
|
39
|
+
* typically depends on devDependency binaries (e.g. tsdown, del-cli)
|
|
40
|
+
* which are not available in the isolated output. Other lifecycle
|
|
41
|
+
* scripts like `postinstall` are preserved because they handle runtime
|
|
42
|
+
* setup (e.g. Prisma client generation).
|
|
43
|
+
*/
|
|
44
|
+
if (strippedManifest.scripts) {
|
|
45
|
+
strippedManifest.scripts = omit(strippedManifest.scripts, ["prepare"]);
|
|
46
|
+
}
|
|
36
47
|
|
|
37
48
|
/** Resolve catalog dependencies before adapting internal deps */
|
|
38
49
|
const manifestWithResolvedCatalogs = {
|
|
@@ -44,10 +55,11 @@ export async function adaptInternalPackageManifests({
|
|
|
44
55
|
};
|
|
45
56
|
|
|
46
57
|
const outputManifest =
|
|
47
|
-
packageManager.name === "pnpm" &&
|
|
58
|
+
(packageManager.name === "pnpm" || packageManager.name === "bun") &&
|
|
59
|
+
!forceNpm
|
|
48
60
|
? /**
|
|
49
|
-
* For PNPM the output itself is a workspace so we can preserve
|
|
50
|
-
* with "workspace:*" in the output manifest.
|
|
61
|
+
* For PNPM and Bun the output itself is a workspace so we can preserve
|
|
62
|
+
* the specifiers with "workspace:*" in the output manifest.
|
|
51
63
|
*/
|
|
52
64
|
manifestWithResolvedCatalogs
|
|
53
65
|
: /** For other package managers we replace the links to internal dependencies */
|
|
@@ -12,10 +12,16 @@ vi.mock("~/lib/utils", () => ({
|
|
|
12
12
|
readTypedJson: vi.fn(),
|
|
13
13
|
}));
|
|
14
14
|
|
|
15
|
+
vi.mock("~/lib/package-manager", () => ({
|
|
16
|
+
usePackageManager: vi.fn(() => ({ name: "pnpm", majorVersion: 9 })),
|
|
17
|
+
}));
|
|
18
|
+
|
|
15
19
|
const { isRushWorkspace, readTypedJson } = vi.mocked(
|
|
16
20
|
await import("~/lib/utils"),
|
|
17
21
|
);
|
|
18
22
|
|
|
23
|
+
const { usePackageManager } = vi.mocked(await import("~/lib/package-manager"));
|
|
24
|
+
|
|
19
25
|
describe("adoptPnpmFieldsFromRoot", () => {
|
|
20
26
|
beforeEach(() => {
|
|
21
27
|
vi.clearAllMocks();
|
|
@@ -209,4 +215,59 @@ describe("adoptPnpmFieldsFromRoot", () => {
|
|
|
209
215
|
},
|
|
210
216
|
});
|
|
211
217
|
});
|
|
218
|
+
|
|
219
|
+
it("should adopt top-level overrides for Bun", async () => {
|
|
220
|
+
usePackageManager.mockReturnValue({
|
|
221
|
+
name: "bun",
|
|
222
|
+
majorVersion: 1,
|
|
223
|
+
version: "1.0.0",
|
|
224
|
+
packageManagerString: "bun@1.0.0",
|
|
225
|
+
} as ReturnType<typeof usePackageManager>);
|
|
226
|
+
isRushWorkspace.mockReturnValue(false);
|
|
227
|
+
readTypedJson.mockResolvedValue({
|
|
228
|
+
name: "root",
|
|
229
|
+
version: "1.0.0",
|
|
230
|
+
overrides: {
|
|
231
|
+
foo: "^1.0.0",
|
|
232
|
+
},
|
|
233
|
+
} as unknown as ProjectManifest);
|
|
234
|
+
|
|
235
|
+
const targetManifest: PackageManifest = {
|
|
236
|
+
name: "test-package",
|
|
237
|
+
version: "1.0.0",
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
const result = await adoptPnpmFieldsFromRoot(targetManifest, "/workspace");
|
|
241
|
+
|
|
242
|
+
expect(result).toEqual({
|
|
243
|
+
name: "test-package",
|
|
244
|
+
version: "1.0.0",
|
|
245
|
+
overrides: {
|
|
246
|
+
foo: "^1.0.0",
|
|
247
|
+
},
|
|
248
|
+
});
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
it("should return original manifest for Bun when no overrides are present", async () => {
|
|
252
|
+
usePackageManager.mockReturnValue({
|
|
253
|
+
name: "bun",
|
|
254
|
+
majorVersion: 1,
|
|
255
|
+
version: "1.0.0",
|
|
256
|
+
packageManagerString: "bun@1.0.0",
|
|
257
|
+
} as ReturnType<typeof usePackageManager>);
|
|
258
|
+
isRushWorkspace.mockReturnValue(false);
|
|
259
|
+
readTypedJson.mockResolvedValue({
|
|
260
|
+
name: "root",
|
|
261
|
+
version: "1.0.0",
|
|
262
|
+
} as ProjectManifest);
|
|
263
|
+
|
|
264
|
+
const targetManifest: PackageManifest = {
|
|
265
|
+
name: "test-package",
|
|
266
|
+
version: "1.0.0",
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
const result = await adoptPnpmFieldsFromRoot(targetManifest, "/workspace");
|
|
270
|
+
|
|
271
|
+
expect(result).toEqual(targetManifest);
|
|
272
|
+
});
|
|
212
273
|
});
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import type { ProjectManifest, PnpmSettings } from "@pnpm/types";
|
|
2
2
|
import path from "path";
|
|
3
|
+
import { usePackageManager } from "~/lib/package-manager";
|
|
3
4
|
import type { PackageManifest } from "~/lib/types";
|
|
4
5
|
import { isRushWorkspace, readTypedJson } from "~/lib/utils";
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
|
-
* Adopts
|
|
8
|
-
* overrides, onlyBuiltDependencies, and ignoredBuiltDependencies
|
|
9
|
-
*
|
|
8
|
+
* Adopts workspace-level fields from the root package manifest. For pnpm this
|
|
9
|
+
* reads overrides, onlyBuiltDependencies, and ignoredBuiltDependencies from the
|
|
10
|
+
* `pnpm` key. For Bun it reads `overrides` from the top level.
|
|
10
11
|
*/
|
|
11
12
|
export async function adoptPnpmFieldsFromRoot(
|
|
12
13
|
targetPackageManifest: PackageManifest,
|
|
@@ -20,6 +21,44 @@ export async function adoptPnpmFieldsFromRoot(
|
|
|
20
21
|
path.join(workspaceRootDir, "package.json"),
|
|
21
22
|
);
|
|
22
23
|
|
|
24
|
+
const packageManager = usePackageManager();
|
|
25
|
+
|
|
26
|
+
if (packageManager.name === "bun") {
|
|
27
|
+
return adoptBunFieldsFromRoot(targetPackageManifest, rootPackageManifest);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return adoptPnpmFieldsOnly(targetPackageManifest, rootPackageManifest);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Adopt Bun's top-level overrides from the root manifest */
|
|
34
|
+
function adoptBunFieldsFromRoot(
|
|
35
|
+
targetPackageManifest: PackageManifest,
|
|
36
|
+
rootPackageManifest: ProjectManifest,
|
|
37
|
+
): PackageManifest {
|
|
38
|
+
/**
|
|
39
|
+
* Bun supports `overrides` at the top level of package.json (same as npm).
|
|
40
|
+
* Read from the root manifest and set them on the output manifest so that
|
|
41
|
+
* `bun install --frozen-lockfile` succeeds.
|
|
42
|
+
*/
|
|
43
|
+
const overrides = (rootPackageManifest as Record<string, unknown>)[
|
|
44
|
+
"overrides"
|
|
45
|
+
] as Record<string, string> | undefined;
|
|
46
|
+
|
|
47
|
+
if (!overrides) {
|
|
48
|
+
return targetPackageManifest;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
...targetPackageManifest,
|
|
53
|
+
overrides,
|
|
54
|
+
} as PackageManifest;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Adopt pnpm-specific fields from the root manifest */
|
|
58
|
+
function adoptPnpmFieldsOnly(
|
|
59
|
+
targetPackageManifest: PackageManifest,
|
|
60
|
+
rootPackageManifest: ProjectManifest,
|
|
61
|
+
): PackageManifest {
|
|
23
62
|
const { overrides, onlyBuiltDependencies, ignoredBuiltDependencies } =
|
|
24
63
|
rootPackageManifest.pnpm || {};
|
|
25
64
|
|
|
@@ -43,7 +43,7 @@ describe("validateManifestMandatoryFields", () => {
|
|
|
43
43
|
|
|
44
44
|
expect(() =>
|
|
45
45
|
validateManifestMandatoryFields(invalidDevManifest, packagePath, false),
|
|
46
|
-
).toThrow(/missing
|
|
46
|
+
).toThrow(/missing the "version" field/);
|
|
47
47
|
});
|
|
48
48
|
|
|
49
49
|
it("should throw error when version field is missing", () => {
|
|
@@ -54,7 +54,7 @@ describe("validateManifestMandatoryFields", () => {
|
|
|
54
54
|
|
|
55
55
|
expect(() =>
|
|
56
56
|
validateManifestMandatoryFields(invalidManifest, packagePath),
|
|
57
|
-
).toThrow(/missing
|
|
57
|
+
).toThrow(/missing the "version" field/);
|
|
58
58
|
});
|
|
59
59
|
|
|
60
60
|
it("should throw error when files field is missing", () => {
|
|
@@ -65,7 +65,7 @@ describe("validateManifestMandatoryFields", () => {
|
|
|
65
65
|
|
|
66
66
|
expect(() =>
|
|
67
67
|
validateManifestMandatoryFields(invalidManifest, packagePath),
|
|
68
|
-
).toThrow(/missing
|
|
68
|
+
).toThrow(/missing the "files" field/);
|
|
69
69
|
});
|
|
70
70
|
|
|
71
71
|
it("should throw error when files field is empty array", () => {
|
|
@@ -77,7 +77,7 @@ describe("validateManifestMandatoryFields", () => {
|
|
|
77
77
|
|
|
78
78
|
expect(() =>
|
|
79
79
|
validateManifestMandatoryFields(invalidManifest, packagePath),
|
|
80
|
-
).toThrow(/missing
|
|
80
|
+
).toThrow(/missing the "files" field/);
|
|
81
81
|
});
|
|
82
82
|
|
|
83
83
|
it("should throw error when files field is not an array", () => {
|
|
@@ -89,7 +89,7 @@ describe("validateManifestMandatoryFields", () => {
|
|
|
89
89
|
|
|
90
90
|
expect(() =>
|
|
91
91
|
validateManifestMandatoryFields(invalidManifest, packagePath),
|
|
92
|
-
).toThrow(/missing
|
|
92
|
+
).toThrow(/missing the "files" field/);
|
|
93
93
|
});
|
|
94
94
|
|
|
95
95
|
it("should throw error when both fields are missing", () => {
|
|
@@ -99,20 +99,29 @@ describe("validateManifestMandatoryFields", () => {
|
|
|
99
99
|
|
|
100
100
|
expect(() =>
|
|
101
101
|
validateManifestMandatoryFields(invalidManifest, packagePath),
|
|
102
|
-
).toThrow(/missing mandatory fields: version, files/);
|
|
102
|
+
).toThrow(/missing mandatory fields in its package\.json: version, files/);
|
|
103
103
|
});
|
|
104
104
|
|
|
105
|
-
it("should include
|
|
105
|
+
it("should include documentation URL in error message", () => {
|
|
106
106
|
const invalidManifest = {
|
|
107
107
|
name: "test-package",
|
|
108
108
|
} as PackageManifest;
|
|
109
109
|
|
|
110
110
|
expect(() =>
|
|
111
111
|
validateManifestMandatoryFields(invalidManifest, packagePath),
|
|
112
|
-
).toThrow(
|
|
112
|
+
).toThrow(
|
|
113
|
+
/See https:\/\/isolate-package\.codecompose\.dev\/getting-started#prerequisites/,
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
const singleFieldManifest = {
|
|
117
|
+
name: "test-package",
|
|
118
|
+
version: "1.0.0",
|
|
119
|
+
} as PackageManifest;
|
|
113
120
|
|
|
114
121
|
expect(() =>
|
|
115
|
-
validateManifestMandatoryFields(
|
|
116
|
-
).toThrow(
|
|
122
|
+
validateManifestMandatoryFields(singleFieldManifest, packagePath),
|
|
123
|
+
).toThrow(
|
|
124
|
+
/See https:\/\/isolate-package\.codecompose\.dev\/getting-started#define-files-field-in-each-package-manifest/,
|
|
125
|
+
);
|
|
117
126
|
});
|
|
118
127
|
});
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import { useLogger } from "../logger";
|
|
2
2
|
import type { PackageManifest } from "../types";
|
|
3
3
|
|
|
4
|
+
/** Maps field names to their documentation URLs */
|
|
5
|
+
const fieldDocUrls: Record<string, string> = {
|
|
6
|
+
version:
|
|
7
|
+
"https://isolate-package.codecompose.dev/getting-started#define-version-field-in-each-package-manifest",
|
|
8
|
+
files:
|
|
9
|
+
"https://isolate-package.codecompose.dev/getting-started#define-files-field-in-each-package-manifest",
|
|
10
|
+
};
|
|
11
|
+
|
|
4
12
|
/**
|
|
5
13
|
* Validate that mandatory fields are present in the package manifest. These
|
|
6
14
|
* fields are required for the isolate process to work properly.
|
|
@@ -38,7 +46,11 @@ export function validateManifestMandatoryFields(
|
|
|
38
46
|
}
|
|
39
47
|
|
|
40
48
|
if (missingFields.length > 0) {
|
|
41
|
-
const
|
|
49
|
+
const field = missingFields[0]!;
|
|
50
|
+
const errorMessage =
|
|
51
|
+
missingFields.length === 1
|
|
52
|
+
? `Package at ${packagePath} is missing the "${field}" field in its package.json. See ${fieldDocUrls[field] ?? "https://isolate-package.codecompose.dev/getting-started#prerequisites"}`
|
|
53
|
+
: `Package at ${packagePath} is missing mandatory fields in its package.json: ${missingFields.join(", ")}. See https://isolate-package.codecompose.dev/getting-started#prerequisites`;
|
|
42
54
|
|
|
43
55
|
log.error(errorMessage);
|
|
44
56
|
throw new Error(errorMessage);
|