Skip to content

Commit c3da9ef

Browse files
authored
Strip prepare script from internal dependency manifests (#170)
In v1.28.3, scripts were preserved in internal dependency manifests to support lifecycle hooks like `postinstall` (e.g. Prisma client generation). However, the `prepare` script is problematic because it runs during `pnpm install` and typically depends on devDependency binaries (e.g. `tsdown`, `del-cli`) that are not available in the isolated output, causing the install to fail. This strips the `prepare` script from internal dependency manifests while preserving all other scripts. Documentation has been updated to explain this behavior. Fixes #169 Scope: isolate-package Visibility: user-facing
1 parent 990893f commit c3da9ef

3 files changed

Lines changed: 69 additions & 0 deletions

File tree

docs/configuration.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,15 @@ to preserve all of the other scripts, set it to `["build"]`.
9898
By default, all scripts are omitted, and the [pickFromScripts](#pickfromscripts)
9999
configuration overrules this configuration.
100100

101+
::: info Scripts in internal dependencies
102+
The `pickFromScripts` and `omitFromScripts` options only apply to the target
103+
package manifest. Internal dependency manifests preserve their scripts by
104+
default (e.g. for `postinstall` hooks like Prisma client generation), with one
105+
exception: the `prepare` script is always stripped from internal dependencies
106+
because it runs during `pnpm install` and typically depends on devDependency
107+
binaries that are not available in the isolated output.
108+
:::
109+
101110
### omitPackageManager
102111

103112
Type: `boolean`, default: `false`

src/lib/manifest/helpers/adapt-internal-package-manifests.test.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,55 @@ describe("adaptInternalPackageManifests", () => {
9595
});
9696
});
9797

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+
98147
it("should strip devDependencies from internal dependency manifests", async () => {
99148
const manifest: PackageManifest = {
100149
name: "@repo/shared",

src/lib/manifest/helpers/adapt-internal-package-manifests.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,17 @@ export async function adaptInternalPackageManifests({
3434
/** Dev dependencies are never included for internal deps */
3535
const strippedManifest = omit(manifest, ["devDependencies"]);
3636

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+
}
47+
3748
/** Resolve catalog dependencies before adapting internal deps */
3849
const manifestWithResolvedCatalogs = {
3950
...strippedManifest,

0 commit comments

Comments
 (0)