Skip to content

Commit e13c759

Browse files
committed
Use devEngines for generated package managers
- write pnpm into `devEngines.packageManager` - drop top-level `packageManager` - update init warnings and tests
1 parent f1dd2c5 commit e13c759

9 files changed

Lines changed: 69 additions & 13 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@proofkit/cli": patch
3+
---
4+
5+
Use devEngines packageManager in generated apps.

packages/cli/src/cli/init.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,13 @@ type ProofKitPackageJSON = PackageJson & {
126126
proofkitMetadata?: {
127127
initVersion: string;
128128
};
129+
devEngines?: {
130+
packageManager: {
131+
name: string;
132+
version: string;
133+
onFail: "download";
134+
};
135+
};
129136
};
130137

131138
const missingTypegenCommandPatterns = [
@@ -286,7 +293,14 @@ export const runInit = async (name?: string, opts?: CliFlags) => {
286293
const { stdout } = await execa(pkgManager, ["-v"], {
287294
cwd: projectDir,
288295
});
289-
pkgJson.packageManager = `${pkgManager}>=${stdout.trim()}`;
296+
pkgJson.packageManager = undefined;
297+
pkgJson.devEngines = {
298+
packageManager: {
299+
name: pkgManager,
300+
version: `^${stdout.trim()}`,
301+
onFail: "download",
302+
},
303+
};
290304
}
291305

292306
fs.writeJSONSync(path.join(projectDir, "package.json"), pkgJson, {

packages/cli/src/core/planInit.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,14 @@ export function planInit(
9797

9898
const packageJson: InitPlan["packageJson"] = {
9999
name: request.scopedAppName,
100-
packageManager: options.packageManagerVersion
101-
? `${request.packageManager}@${options.packageManagerVersion}`
100+
devEngines: options.packageManagerVersion
101+
? {
102+
packageManager: {
103+
name: request.packageManager,
104+
version: `^${options.packageManagerVersion}`,
105+
onFail: "download",
106+
},
107+
}
102108
: undefined,
103109
proofkitMetadata: {
104110
initVersion: getScaffoldVersion(),
@@ -202,8 +208,9 @@ export function applyPackageJsonMutations(
202208
) {
203209
packageJson.name = mutations.name;
204210
packageJson.proofkitMetadata = mutations.proofkitMetadata as PackageJson["proofkitMetadata"];
205-
if (mutations.packageManager) {
206-
packageJson.packageManager = mutations.packageManager;
211+
if (mutations.devEngines) {
212+
packageJson.devEngines = mutations.devEngines;
213+
packageJson.packageManager = undefined;
207214
}
208215

209216
if (!packageJson.dependencies) {

packages/cli/src/core/types.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,13 @@ export interface InitPlan {
105105
packageManagerExecuteCommand: string;
106106
packageJson: {
107107
name: string;
108-
packageManager?: string;
108+
devEngines?: {
109+
packageManager: {
110+
name: PackageManager;
111+
version: string;
112+
onFail: "download";
113+
};
114+
};
109115
proofkitMetadata: {
110116
initVersion: string;
111117
scaffoldPackage: "@proofkit/cli";

packages/cli/src/utils/sortPackageJson.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ const ROOT_KEY_ORDER = [
1313
"funding",
1414
"type",
1515
"packageManager",
16+
"devEngines",
1617
"engines",
1718
"bin",
1819
"exports",

packages/cli/tests/executor.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,7 @@ describe("executeInitPlan command paths", () => {
366366
await Effect.runPromise(executeInitPlan(plan).pipe(makeTestLayer({ cwd, packageManager: "npm", console })));
367367

368368
expect(console.info.join("\n")).toContain(
369-
"Warning: We strongly suggest using pnpm 11 or greater as your package manager for security reasons.",
369+
"Warning: We strongly suggest using PNPM 11 or greater as your package manager to better protect your computer and your app.",
370370
);
371371
});
372372

packages/cli/tests/init-scaffold-contract.test.ts

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@ interface PackageJsonShape {
88
version?: string;
99
name?: string;
1010
packageManager?: string;
11+
devEngines?: {
12+
packageManager?: {
13+
name?: string;
14+
version?: string;
15+
onFail?: string;
16+
};
17+
};
1118
scripts?: Record<string, string>;
1219
dependencies?: Record<string, string>;
1320
devDependencies?: Record<string, string>;
@@ -47,7 +54,7 @@ const expectedProofkitVersions = new Map([
4754
`^${readJsonFile<PackageJsonShape>(join(__dirname, "..", "..", "webviewer", "package.json")).version}`,
4855
],
4956
]);
50-
const packageManagerPattern = /^(npm|pnpm|yarn|bun)@/;
57+
const packageManagerVersionPattern = /^\^?\d+\.\d+\.\d+/;
5158
const ansiStylePrefixPattern = /^[0-9;]*m/;
5259

5360
function runInit({ appType, projectName }: { appType: "browser" | "webviewer"; projectName: string }): string {
@@ -110,7 +117,7 @@ function checkNodeSyntax(projectDir: string, relativeFilePath: string): boolean
110117
}
111118

112119
function getPackageManagerName(packageJson: PackageJsonShape): "npm" | "pnpm" | "yarn" | "bun" {
113-
const raw = packageJson.packageManager?.split("@")[0];
120+
const raw = packageJson.devEngines?.packageManager?.name ?? packageJson.packageManager?.split("@")[0];
114121
if (raw === "pnpm" || raw === "yarn" || raw === "bun") {
115122
return raw;
116123
}
@@ -161,7 +168,10 @@ describe("Init scaffold contract tests", () => {
161168
expect(packageJson.scripts?.build).toBe("next build --turbopack");
162169
expect(packageJson.scripts?.proofkit).toBe("proofkit");
163170
expect(packageJson.proofkitMetadata?.initVersion).toBe(cliVersion);
164-
expect(packageJson.packageManager).toMatch(packageManagerPattern);
171+
expect(packageJson.packageManager).toBeUndefined();
172+
expect(packageJson.devEngines?.packageManager?.name).toBe("pnpm");
173+
expect(packageJson.devEngines?.packageManager?.version).toMatch(packageManagerVersionPattern);
174+
expect(packageJson.devEngines?.packageManager?.onFail).toBe("download");
165175
expect(allProofkitDependenciesUseCurrentVersions(packageJson)).toBe(true);
166176
expect(readFileSync(join(browserProjectDir, "CLAUDE.md"), "utf-8")).toBe("@AGENTS.md\n");
167177
expect(readFileSync(join(browserProjectDir, ".cursorignore"), "utf-8")).toBe("CLAUDE.md\n");
@@ -213,7 +223,10 @@ describe("Init scaffold contract tests", () => {
213223
expect(packageJson.scripts?.["typegen:ui"]).toBe("pnpx @proofkit/typegen ui");
214224
expect(packageJson.scripts?.proofkit).toBe("proofkit");
215225
expect(packageJson.proofkitMetadata?.initVersion).toBe(cliVersion);
216-
expect(packageJson.packageManager).toMatch(packageManagerPattern);
226+
expect(packageJson.packageManager).toBeUndefined();
227+
expect(packageJson.devEngines?.packageManager?.name).toBe("pnpm");
228+
expect(packageJson.devEngines?.packageManager?.version).toMatch(packageManagerVersionPattern);
229+
expect(packageJson.devEngines?.packageManager?.onFail).toBe("download");
217230
expect(allProofkitDependenciesUseCurrentVersions(packageJson)).toBe(true);
218231
expect(readFileSync(join(webviewerProjectDir, "CLAUDE.md"), "utf-8")).toBe("@AGENTS.md\n");
219232
expect(readFileSync(join(webviewerProjectDir, ".cursorignore"), "utf-8")).toBe("CLAUDE.md\n");

packages/cli/tests/integration.test.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,12 @@ describe("integration scaffold generation", () => {
6666
await readScaffoldArtifacts(projectDir);
6767

6868
expect(packageJson.name).toBe("browser-app");
69-
expect(packageJson.packageManager).toBe("pnpm@11.1.0");
69+
expect(packageJson.packageManager).toBeUndefined();
70+
expect(packageJson.devEngines?.packageManager).toEqual({
71+
name: "pnpm",
72+
version: "^11.1.0",
73+
onFail: "download",
74+
});
7075
expect(packageJson.proofkitMetadata).toMatchObject({
7176
scaffoldPackage: "@proofkit/cli",
7277
});

packages/cli/tests/planner.test.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ describe("planInit", () => {
2525
expect(plan.targetDir).toBe(path.resolve("/tmp/workspace", "demo-app"));
2626
expect(plan.templateDir).toBe("/templates/browser");
2727
expect(plan.packageJson.name).toBe("demo-app");
28+
expect(plan.packageJson.devEngines?.packageManager).toEqual({
29+
name: "pnpm",
30+
version: "^11.0.0",
31+
onFail: "download",
32+
});
2833
expect(plan.settings.appType).toBe("browser");
2934
expect(plan.packageJson.devDependencies["@proofkit/cli"]).toBe(proofkitCliVersion);
3035
expect(plan.packageJson.devDependencies["@proofkit/typegen"]).toBe(proofkitTypegenVersion);
@@ -126,7 +131,7 @@ describe("planInit", () => {
126131
);
127132

128133
expect(plan.nextSteps).toContain(
129-
"Warning: We strongly suggest using pnpm 11 or greater as your package manager for security reasons.",
134+
"Warning: We strongly suggest using PNPM 11 or greater as your package manager to better protect your computer and your app.",
130135
);
131136
});
132137

0 commit comments

Comments
 (0)