@moinulmoin/eden 0.7.4 → 0.8.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/README.md +3 -3
- package/dist/eve-control-plane.js +81 -4
- package/dist/eve-packaging.d.ts +9 -22
- package/dist/eve-packaging.js +110 -38
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -12,15 +12,15 @@ If you already have an Eve project, start with `eden deploy`.
|
|
|
12
12
|
Use any one of these package managers:
|
|
13
13
|
|
|
14
14
|
```sh
|
|
15
|
-
npm install --global @moinulmoin/eden@0.
|
|
15
|
+
npm install --global @moinulmoin/eden@0.8.0
|
|
16
16
|
```
|
|
17
17
|
|
|
18
18
|
```sh
|
|
19
|
-
pnpm add --global @moinulmoin/eden@0.
|
|
19
|
+
pnpm add --global @moinulmoin/eden@0.8.0
|
|
20
20
|
```
|
|
21
21
|
|
|
22
22
|
```sh
|
|
23
|
-
bun add --global @moinulmoin/eden@0.
|
|
23
|
+
bun add --global @moinulmoin/eden@0.8.0
|
|
24
24
|
```
|
|
25
25
|
|
|
26
26
|
Then confirm the CLI is available:
|
|
@@ -214,10 +214,82 @@ function pooledPostgresReason(connectionString) {
|
|
|
214
214
|
return undefined;
|
|
215
215
|
}
|
|
216
216
|
/**
|
|
217
|
-
*
|
|
218
|
-
*
|
|
219
|
-
* Postgres URL breaks the World streamer, which relies on LISTEN/NOTIFY.
|
|
217
|
+
* Recognizes the generated channel, not arbitrary user authentication policies.
|
|
218
|
+
* The calls below match the Eve 0.82 initializer's agent/channels/eve.ts.
|
|
220
219
|
*/
|
|
220
|
+
async function collectEveSetupWarnings(projectRoot) {
|
|
221
|
+
const warnings = [];
|
|
222
|
+
const source = async (path) => {
|
|
223
|
+
try {
|
|
224
|
+
return await readFile(join(projectRoot, path), "utf8");
|
|
225
|
+
}
|
|
226
|
+
catch {
|
|
227
|
+
return "";
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
const channel = (await source("agent/channels/eve.ts"))
|
|
231
|
+
.replace(/\/\*[\s\S]*?\*\/|\/\/[^\n]*/gu, "")
|
|
232
|
+
.replace(/\s+/gu, "");
|
|
233
|
+
if (/exportdefaulteveChannel\(\{auth:\[vercelOidc\(\),localDev\(\),placeholderAuth\(\),?\],?\}\);?$/u
|
|
234
|
+
.test(channel)) {
|
|
235
|
+
warnings.push({
|
|
236
|
+
id: "EVE_AUTH_SCAFFOLD",
|
|
237
|
+
message: "Eve's generated channel auth does not grant Cloudflare callers access.",
|
|
238
|
+
remediation: "Replace agent/channels/eve.ts auth with your app's authenticator; put credentials in --env-file.",
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
try {
|
|
242
|
+
const manifest = JSON.parse(await source("package.json"));
|
|
243
|
+
const agent = await source("agent/agent.ts");
|
|
244
|
+
if (/export\s+default\s+defineAgent\s*\(\s*\{\s*model\s*:\s*["'][^"']+["']\s*,\s*reasoning\s*:\s*["'][^"']+["']\s*,?\s*\}\s*\)/u.test(agent)) {
|
|
245
|
+
warnings.push({
|
|
246
|
+
id: "EVE_WORLD_LOCAL",
|
|
247
|
+
message: "Local World stores memory on container disk; updates or a lost sleep snapshot reset sessions and approvals.",
|
|
248
|
+
remediation: "Configure @workflow/world-postgres; see docs/deploy.md#durable-state-postgres-world.",
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
if (manifest.dependencies?.["just-bash"] === undefined &&
|
|
252
|
+
agent.length > 0 &&
|
|
253
|
+
!/\bsandbox\s*:/u.test(agent)) {
|
|
254
|
+
const command = manifest.packageManager?.startsWith("pnpm@")
|
|
255
|
+
? "pnpm add just-bash"
|
|
256
|
+
: "npm install just-bash";
|
|
257
|
+
warnings.push({
|
|
258
|
+
id: "EVE_JUST_BASH_MISSING",
|
|
259
|
+
message: "Eve's default sandbox needs the just-bash production dependency in Eden's builder.",
|
|
260
|
+
remediation: `Run ${command}, commit the updated manifest and lockfile, then retry.`,
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
if (!manifest.packageManager?.startsWith("pnpm@")) {
|
|
264
|
+
const lockText = await source("package-lock.json");
|
|
265
|
+
// Same trust level as the manifest above: npm wrote it; packaging validates it.
|
|
266
|
+
const lock = JSON.parse(lockText === "" ? "{}" : lockText);
|
|
267
|
+
const entries = lock.packages ?? {};
|
|
268
|
+
const skipped = new Set();
|
|
269
|
+
for (const [path, entry] of Object.entries(entries)) {
|
|
270
|
+
const at = path.lastIndexOf("node_modules/");
|
|
271
|
+
if (at !== -1 &&
|
|
272
|
+
entry.hasInstallScript === true &&
|
|
273
|
+
entry.dev !== true &&
|
|
274
|
+
entry.optional !== true &&
|
|
275
|
+
entry.devOptional !== true) {
|
|
276
|
+
skipped.add(path.slice(at + "node_modules/".length));
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
if (skipped.size > 0) {
|
|
280
|
+
warnings.push({
|
|
281
|
+
id: "EVE_NPM_INSTALL_SCRIPTS_SKIPPED",
|
|
282
|
+
message: `Eden's npm install skips dependency install scripts; these production dependencies have one and may fail at runtime: ${[...skipped].sort().join(", ")}.`,
|
|
283
|
+
remediation: "Use packages that need no install script, or switch to exact-pinned pnpm and list them under allowBuilds in pnpm-workspace.yaml.",
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
catch {
|
|
289
|
+
// Packaging reports invalid manifests; setup hints must not mask that result.
|
|
290
|
+
}
|
|
291
|
+
return warnings;
|
|
292
|
+
}
|
|
221
293
|
async function collectEveWorldWarnings(candidate, runtimeConfig) {
|
|
222
294
|
const warnings = [];
|
|
223
295
|
if (candidate !== undefined) {
|
|
@@ -227,7 +299,7 @@ async function collectEveWorldWarnings(candidate, runtimeConfig) {
|
|
|
227
299
|
world === "@workflow/world-local") {
|
|
228
300
|
warnings.push({
|
|
229
301
|
id: "EVE_WORLD_LOCAL",
|
|
230
|
-
message: "
|
|
302
|
+
message: "Local World stores memory on container disk; updates or a lost sleep snapshot reset sessions and approvals.",
|
|
231
303
|
remediation: "Configure a durable Workflow World such as @workflow/world-postgres; see docs/deploy.md#durable-state-postgres-world.",
|
|
232
304
|
});
|
|
233
305
|
}
|
|
@@ -1981,6 +2053,7 @@ async function collectEvePreflight(request, options) {
|
|
|
1981
2053
|
runtimeConfig,
|
|
1982
2054
|
};
|
|
1983
2055
|
}
|
|
2056
|
+
warnings.push(...await collectEveSetupWarnings(request.projectRoot));
|
|
1984
2057
|
eveProgress(options, "packaging project — snapshot, frozen install, eve build");
|
|
1985
2058
|
const nodeImage = options.nodeImage ?? DEFAULT_EVE_NODE_IMAGE;
|
|
1986
2059
|
const artifactRoot = options.artifactRoot ??
|
|
@@ -2087,6 +2160,10 @@ async function collectEvePreflight(request, options) {
|
|
|
2087
2160
|
if (workflowWorld === "@moinulmoin/eden-world-cloudflare") {
|
|
2088
2161
|
checks.push(check("EVE-WORLD", "passed", "world: Cloudflare Durable Object"));
|
|
2089
2162
|
}
|
|
2163
|
+
// Compiled configuration supersedes the early generated-source hint.
|
|
2164
|
+
const localHint = warnings.findIndex((warning) => warning.id === "EVE_WORLD_LOCAL");
|
|
2165
|
+
if (localHint !== -1)
|
|
2166
|
+
warnings.splice(localHint, 1);
|
|
2090
2167
|
warnings.push(...(await collectEveWorldWarnings(candidate, undefined)));
|
|
2091
2168
|
const schedules = await readCompiledSchedules(candidate);
|
|
2092
2169
|
const expressible = schedules.filter((schedule) => parseEveScheduleCron(schedule.cron) !== undefined);
|
package/dist/eve-packaging.d.ts
CHANGED
|
@@ -19,18 +19,15 @@ export interface EveNodeImage {
|
|
|
19
19
|
readonly reference: string;
|
|
20
20
|
readonly digest: string;
|
|
21
21
|
}
|
|
22
|
+
export type EvePackageManager = "pnpm" | "npm";
|
|
23
|
+
export type EveInstallCommand = readonly ["corepack", "pnpm", "install", "--frozen-lockfile"] | readonly ["npm", "ci", "--ignore-scripts", "--no-audit", "--no-fund"];
|
|
22
24
|
export interface EveProjectBuilderRequest {
|
|
23
25
|
readonly generationRoot: string;
|
|
24
26
|
readonly snapshotRoot: string;
|
|
25
27
|
readonly inputManifestPath: string;
|
|
26
28
|
readonly dockerfilePath: string | undefined;
|
|
27
29
|
readonly packageManagerVersion: string;
|
|
28
|
-
readonly installCommand:
|
|
29
|
-
"corepack",
|
|
30
|
-
"pnpm",
|
|
31
|
-
"install",
|
|
32
|
-
"--frozen-lockfile"
|
|
33
|
-
];
|
|
30
|
+
readonly installCommand: EveInstallCommand;
|
|
34
31
|
readonly buildCommand: readonly ["./node_modules/.bin/eve", "build"];
|
|
35
32
|
readonly platform: "linux/amd64";
|
|
36
33
|
readonly sourceDigest: string;
|
|
@@ -75,7 +72,7 @@ export interface EveProjectInputManifest {
|
|
|
75
72
|
readonly requestedRoot: string;
|
|
76
73
|
readonly canonicalRoot: string;
|
|
77
74
|
readonly projectId: string;
|
|
78
|
-
readonly packageManager:
|
|
75
|
+
readonly packageManager: EvePackageManager;
|
|
79
76
|
readonly packageManagerVersion: string;
|
|
80
77
|
readonly packageJsonSha256: string;
|
|
81
78
|
readonly lockfileSha256: string;
|
|
@@ -123,14 +120,9 @@ export interface EveProjectBuildCandidate {
|
|
|
123
120
|
readonly generationRoot: string;
|
|
124
121
|
readonly snapshotRoot: string;
|
|
125
122
|
readonly inputManifestPath: string;
|
|
126
|
-
readonly packageManager:
|
|
123
|
+
readonly packageManager: EvePackageManager;
|
|
127
124
|
readonly packageManagerVersion: string;
|
|
128
|
-
readonly installCommand:
|
|
129
|
-
"corepack",
|
|
130
|
-
"pnpm",
|
|
131
|
-
"install",
|
|
132
|
-
"--frozen-lockfile"
|
|
133
|
-
];
|
|
125
|
+
readonly installCommand: EveInstallCommand;
|
|
134
126
|
readonly buildCommand: readonly ["./node_modules/.bin/eve", "build"];
|
|
135
127
|
readonly eveExecutable: "node_modules/.bin/eve";
|
|
136
128
|
readonly eveVersion: string;
|
|
@@ -145,14 +137,9 @@ export interface EveProjectBuildCandidate {
|
|
|
145
137
|
}
|
|
146
138
|
export interface EveProjectToolchain {
|
|
147
139
|
readonly nodeVersion: "24.17.0";
|
|
148
|
-
readonly packageManager:
|
|
140
|
+
readonly packageManager: EvePackageManager;
|
|
149
141
|
readonly packageManagerVersion: string;
|
|
150
|
-
readonly installCommand:
|
|
151
|
-
"corepack",
|
|
152
|
-
"pnpm",
|
|
153
|
-
"install",
|
|
154
|
-
"--frozen-lockfile"
|
|
155
|
-
];
|
|
142
|
+
readonly installCommand: EveInstallCommand;
|
|
156
143
|
readonly buildCommand: readonly ["./node_modules/.bin/eve", "build"];
|
|
157
144
|
readonly startCommand: readonly [
|
|
158
145
|
"./node_modules/.bin/eve",
|
|
@@ -227,7 +214,7 @@ export interface EveProjectPackagingResult {
|
|
|
227
214
|
readonly sha256: string;
|
|
228
215
|
};
|
|
229
216
|
readonly lockfile: {
|
|
230
|
-
readonly path: "pnpm-lock.yaml";
|
|
217
|
+
readonly path: "pnpm-lock.yaml" | "package-lock.json";
|
|
231
218
|
readonly sha256: string;
|
|
232
219
|
};
|
|
233
220
|
readonly sourceDigest: string;
|
package/dist/eve-packaging.js
CHANGED
|
@@ -167,6 +167,9 @@ const INSTALL_COMMAND = [
|
|
|
167
167
|
"install",
|
|
168
168
|
"--frozen-lockfile",
|
|
169
169
|
];
|
|
170
|
+
const NPM_INSTALL_COMMAND = ["npm", "ci", "--ignore-scripts", "--no-audit", "--no-fund"];
|
|
171
|
+
// Install this exact isolated manager without consulting project npm configuration.
|
|
172
|
+
const NPM_VERSION = "11.13.0";
|
|
170
173
|
const BUILD_COMMAND = ["./node_modules/.bin/eve", "build"];
|
|
171
174
|
const EVE_ENTRYPOINT = ".output/server/index.mjs";
|
|
172
175
|
const EVE_EXCLUDED_DIRECTORY_NAMES = new Set([
|
|
@@ -201,6 +204,7 @@ const EVE_COMPETING_LOCKFILES = new Set([
|
|
|
201
204
|
"bun.lock",
|
|
202
205
|
"bun.lockb",
|
|
203
206
|
"npm-shrinkwrap.json",
|
|
207
|
+
"pnpm-lock.yaml",
|
|
204
208
|
"package-lock.json",
|
|
205
209
|
"yarn.lock",
|
|
206
210
|
]);
|
|
@@ -548,37 +552,76 @@ function validateProjectContract(inputs) {
|
|
|
548
552
|
remediation: "Add a non-empty package.json name and retry.",
|
|
549
553
|
});
|
|
550
554
|
}
|
|
551
|
-
const
|
|
552
|
-
const
|
|
553
|
-
|
|
554
|
-
|
|
555
|
+
const npmLock = inputs.files.find((file) => file.relativePath === "package-lock.json");
|
|
556
|
+
const packageManager = npmLock === undefined ? "pnpm" : "npm";
|
|
557
|
+
const lockfilePath = packageManager === "npm" ? "package-lock.json" : "pnpm-lock.yaml";
|
|
558
|
+
const npmPin = typeof packageValue.packageManager === "string"
|
|
559
|
+
? /^npm@((?:[7-9]|[1-9][0-9]+)\.(?:0|[1-9][0-9]*)\.(?:0|[1-9][0-9]*))$/u.exec(packageValue.packageManager)?.[1]
|
|
560
|
+
: undefined;
|
|
561
|
+
const packageManagerVersion = packageManager === "pnpm"
|
|
562
|
+
? parsePnpmVersion(packageValue.packageManager)
|
|
563
|
+
: npmPin ?? NPM_VERSION;
|
|
564
|
+
const lockFiles = inputs.files.filter((file) => file.relativePath === lockfilePath || file.relativePath.endsWith(`/${lockfilePath}`));
|
|
565
|
+
if (lockFiles.length !== 1 || lockFiles[0]?.relativePath !== lockfilePath) {
|
|
555
566
|
throw new EvePackagingError({
|
|
556
567
|
code: "DEPENDENCY_AMBIGUITY",
|
|
557
|
-
subject:
|
|
558
|
-
reason: "The selected Eve root must contain exactly one regular root
|
|
568
|
+
subject: lockfilePath,
|
|
569
|
+
reason: "The selected Eve root must contain exactly one regular root lockfile.",
|
|
559
570
|
remediation: "Remove competing or nested lockfiles and retry with the matching root lockfile.",
|
|
560
571
|
});
|
|
561
572
|
}
|
|
562
|
-
const competing = inputs.files.find((file) => EVE_COMPETING_LOCKFILES.has(basename(file.relativePath)));
|
|
573
|
+
const competing = inputs.files.find((file) => EVE_COMPETING_LOCKFILES.has(basename(file.relativePath)) && file.relativePath !== lockfilePath);
|
|
563
574
|
if (competing !== undefined) {
|
|
564
575
|
throw new EvePackagingError({
|
|
565
576
|
code: "DEPENDENCY_AMBIGUITY",
|
|
566
577
|
subject: competing.relativePath,
|
|
567
578
|
reason: "A competing package-manager lockfile was found at the selected Eve root.",
|
|
568
|
-
remediation: "Keep only
|
|
579
|
+
remediation: "Keep only one supported package manager and its matching root lockfile.",
|
|
580
|
+
});
|
|
581
|
+
}
|
|
582
|
+
if (packageManager === "npm" && packageValue.packageManager !== undefined &&
|
|
583
|
+
npmPin === undefined) {
|
|
584
|
+
throw new EvePackagingError({
|
|
585
|
+
code: "UNSUPPORTED_TOOLCHAIN",
|
|
586
|
+
subject: "package.json.packageManager",
|
|
587
|
+
reason: "npm projects may omit packageManager or declare an exact npm version (major 7 or newer).",
|
|
588
|
+
remediation: `Remove the optional packageManager field to use npm@${NPM_VERSION}, or declare an exact npm@<major>.<minor>.<patch> pin.`,
|
|
569
589
|
});
|
|
570
590
|
}
|
|
571
591
|
const lockfile = lockFiles[0];
|
|
572
|
-
|
|
592
|
+
let npmLockValid = false;
|
|
593
|
+
if (packageManager === "npm" && lockfile !== undefined) {
|
|
594
|
+
try {
|
|
595
|
+
const parsed = JSON.parse(lockfile.bytes.toString("utf8"));
|
|
596
|
+
npmLockValid = (parsed.lockfileVersion === 2 || parsed.lockfileVersion === 3) &&
|
|
597
|
+
parsed.packages !== null && typeof parsed.packages === "object" &&
|
|
598
|
+
!Array.isArray(parsed.packages) && parsed.packages[""] !== undefined;
|
|
599
|
+
for (const entry of Object.values(parsed.packages ?? {})) {
|
|
600
|
+
const dependency = entry;
|
|
601
|
+
if (typeof dependency.resolved === "string" &&
|
|
602
|
+
!dependency.resolved.startsWith("https://registry.npmjs.org/"))
|
|
603
|
+
npmLockValid = false;
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
catch {
|
|
607
|
+
npmLockValid = false;
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
if (lockfile === undefined || (packageManager === "pnpm"
|
|
611
|
+
? !lockfileMatchesPnpm(packageManagerVersion, lockfile.bytes)
|
|
612
|
+
: !npmLockValid)) {
|
|
573
613
|
throw new EvePackagingError({
|
|
574
614
|
code: "DEPENDENCY_AMBIGUITY",
|
|
575
|
-
subject:
|
|
576
|
-
reason: "The root
|
|
577
|
-
remediation: "Regenerate the lockfile with the
|
|
615
|
+
subject: lockfilePath,
|
|
616
|
+
reason: "The root lockfile is malformed or incompatible with the selected package manager or public registry.",
|
|
617
|
+
remediation: "Regenerate the root lockfile with the selected manager and public npm registry; private registries and project .npmrc configuration are not supported.",
|
|
578
618
|
});
|
|
579
619
|
}
|
|
580
620
|
return {
|
|
581
621
|
projectId,
|
|
622
|
+
packageManager,
|
|
623
|
+
lockfilePath,
|
|
624
|
+
installCommand: packageManager === "npm" ? NPM_INSTALL_COMMAND : INSTALL_COMMAND,
|
|
582
625
|
packageManagerVersion,
|
|
583
626
|
packageJsonSha256: packageFile.sha256,
|
|
584
627
|
lockfileSha256: lockfile.sha256,
|
|
@@ -1077,7 +1120,7 @@ export async function eveSnapshotSourceEntries(snapshotRoot) {
|
|
|
1077
1120
|
}
|
|
1078
1121
|
async function writeDockerBuildFiles(options) {
|
|
1079
1122
|
const image = imageReference(options.nodeImage, "The Linux/amd64 builder requires an immutable Node 24 image digest.", "Supply a verified Node 24 image reference and sha256 digest.");
|
|
1080
|
-
const installSources = ["package.json",
|
|
1123
|
+
const installSources = ["package.json", options.lockfilePath];
|
|
1081
1124
|
if ((await lstat(join(options.snapshotRoot, "pnpm-workspace.yaml"))
|
|
1082
1125
|
.catch(() => undefined))?.isFile() === true) {
|
|
1083
1126
|
installSources.push("pnpm-workspace.yaml");
|
|
@@ -1085,17 +1128,27 @@ async function writeDockerBuildFiles(options) {
|
|
|
1085
1128
|
const runtimeSourceCopies = (await eveSnapshotSourceEntries(options.snapshotRoot))
|
|
1086
1129
|
.map((name) => `COPY --from=builder ${JSON.stringify([`/workspace/${name}`, `/app/${name}`])}`)
|
|
1087
1130
|
.join("\n");
|
|
1131
|
+
const npm = options.packageManager === "npm";
|
|
1132
|
+
const lockCheck = `test "$(sha256sum ${options.lockfilePath} | cut -d ' ' -f1)" = "${options.lockfileSha256}"`;
|
|
1133
|
+
const managerSetup = npm
|
|
1134
|
+
? `npm install --global npm@${options.packageManagerVersion} --ignore-scripts --no-audit --no-fund --registry=https://registry.npmjs.org/ && test "$(npm --version)" = "${options.packageManagerVersion}"`
|
|
1135
|
+
: `corepack enable && corepack prepare pnpm@${options.packageManagerVersion} --activate && test "$(corepack pnpm --version)" = "${options.packageManagerVersion}"`;
|
|
1136
|
+
const install = npm
|
|
1137
|
+
? "npm ci --ignore-scripts --no-audit --no-fund --registry=https://registry.npmjs.org/"
|
|
1138
|
+
: "corepack pnpm install --frozen-lockfile --config.node-linker=hoisted --config.strict-dep-builds=false";
|
|
1139
|
+
const productionInstall = npm
|
|
1140
|
+
? `${install} --omit=dev`
|
|
1141
|
+
: "corepack pnpm install --frozen-lockfile --prod --config.node-linker=hoisted --config.strict-dep-builds=false";
|
|
1142
|
+
const policy = npm ? "" : ` && ${IGNORED_BUILDS_GUARD}`;
|
|
1088
1143
|
const dockerfile = `# syntax=docker/dockerfile:1
|
|
1089
1144
|
FROM --platform=linux/amd64 ${image} AS builder
|
|
1090
1145
|
WORKDIR /workspace
|
|
1091
1146
|
COPY ${JSON.stringify([...installSources, "./"])}
|
|
1092
|
-
RUN
|
|
1093
|
-
&&
|
|
1094
|
-
&&
|
|
1095
|
-
&&
|
|
1096
|
-
|
|
1097
|
-
&& ${IGNORED_BUILDS_GUARD}
|
|
1098
|
-
${EVE_SANDBOX_RESUME_PATCH_DOCKERFILE_STEP}RUN test "$(sha256sum pnpm-lock.yaml | cut -d ' ' -f1)" = "${options.lockfileSha256}"
|
|
1147
|
+
RUN ${managerSetup} \\
|
|
1148
|
+
&& ${lockCheck} \\
|
|
1149
|
+
&& ${install}${policy} \\
|
|
1150
|
+
&& ${lockCheck}
|
|
1151
|
+
${EVE_SANDBOX_RESUME_PATCH_DOCKERFILE_STEP}RUN ${lockCheck}
|
|
1099
1152
|
COPY . ./
|
|
1100
1153
|
RUN test -x ./node_modules/.bin/eve \\
|
|
1101
1154
|
&& ./node_modules/.bin/eve build \\
|
|
@@ -1103,10 +1156,10 @@ RUN test -x ./node_modules/.bin/eve \\
|
|
|
1103
1156
|
|
|
1104
1157
|
FROM builder AS runtime-deps
|
|
1105
1158
|
RUN rm -rf node_modules \\
|
|
1106
|
-
&&
|
|
1107
|
-
&& ${
|
|
1159
|
+
&& ${productionInstall}${policy} \\
|
|
1160
|
+
&& ${lockCheck} \\
|
|
1108
1161
|
&& for l in node_modules/.bin/*; do t=$(readlink "$l") || continue; case "$t" in /*) ln -sfn "$(realpath --relative-to=node_modules/.bin "$t")" "$l" ;; esac; done
|
|
1109
|
-
${EVE_SANDBOX_RESUME_PATCH_DOCKERFILE_STEP}
|
|
1162
|
+
${EVE_SANDBOX_RESUME_PATCH_DOCKERFILE_STEP}RUN ${lockCheck}
|
|
1110
1163
|
|
|
1111
1164
|
FROM --platform=linux/amd64 ${image} AS runtime
|
|
1112
1165
|
WORKDIR /app
|
|
@@ -1627,13 +1680,24 @@ function classifyPnpmInstallFailure(stderr) {
|
|
|
1627
1680
|
}
|
|
1628
1681
|
return undefined;
|
|
1629
1682
|
}
|
|
1683
|
+
function classifyNpmInstallFailure(stderr) {
|
|
1684
|
+
if (!/\bnpm (?:ci|install|error|ERR!)/u.test(stderr))
|
|
1685
|
+
return undefined;
|
|
1686
|
+
const code = /npm (?:error|ERR!) code ([A-Z0-9_]+)/u.exec(stderr)?.[1];
|
|
1687
|
+
return new EvePackagingError({
|
|
1688
|
+
code: "DEPENDENCY_AMBIGUITY",
|
|
1689
|
+
subject: code === undefined ? "frozen npm install" : `npm ${code}`,
|
|
1690
|
+
reason: "The isolated pinned npm install could not complete with the captured lockfile and disabled lifecycle scripts.",
|
|
1691
|
+
remediation: "Fix the reported npm failure; regenerate package-lock.json with the selected exact npm version if it is out of sync. Use public registry dependencies without .npmrc credentials or dependency build scripts.",
|
|
1692
|
+
});
|
|
1693
|
+
}
|
|
1630
1694
|
function classifyEveBuildFailure(stderr) {
|
|
1631
1695
|
if (/\bjust-bash\b/u.test(stderr)) {
|
|
1632
1696
|
return new EvePackagingError({
|
|
1633
1697
|
code: "EVE_BUILD_FAILED",
|
|
1634
1698
|
subject: "eve build",
|
|
1635
1699
|
reason: "The project-local Eve build failed inside the isolated Linux/amd64 builder because Eve's default sandbox needs just-bash where no Docker daemon or /dev/kvm exists.",
|
|
1636
|
-
remediation: "Declare just-bash as a production dependency of the Eve project, regenerate
|
|
1700
|
+
remediation: "Declare just-bash as a production dependency of the Eve project, regenerate its package-manager lockfile, and retry.",
|
|
1637
1701
|
});
|
|
1638
1702
|
}
|
|
1639
1703
|
return new EvePackagingError({
|
|
@@ -1655,6 +1719,9 @@ function classifyDockerBuildFailure(error) {
|
|
|
1655
1719
|
if (/\beve\b/u.test(step) && /\bbuild\b/u.test(step)) {
|
|
1656
1720
|
return classifyEveBuildFailure(stderr);
|
|
1657
1721
|
}
|
|
1722
|
+
if (/\bnpm\b/u.test(step)) {
|
|
1723
|
+
return classifyNpmInstallFailure(`npm ci\n${stderr}`);
|
|
1724
|
+
}
|
|
1658
1725
|
if (/pnpm|corepack/u.test(step)) {
|
|
1659
1726
|
const pnpmFailure = classifyPnpmInstallFailure(stderr);
|
|
1660
1727
|
if (pnpmFailure !== undefined)
|
|
@@ -1670,6 +1737,9 @@ function classifyDockerBuildFailure(error) {
|
|
|
1670
1737
|
const pnpmFailure = classifyPnpmInstallFailure(stderr);
|
|
1671
1738
|
if (pnpmFailure !== undefined)
|
|
1672
1739
|
return pnpmFailure;
|
|
1740
|
+
const npmFailure = classifyNpmInstallFailure(stderr);
|
|
1741
|
+
if (npmFailure !== undefined)
|
|
1742
|
+
return npmFailure;
|
|
1673
1743
|
if (/\bjust-bash\b|Cannot find package/u.test(stderr)) {
|
|
1674
1744
|
return classifyEveBuildFailure(stderr);
|
|
1675
1745
|
}
|
|
@@ -1915,7 +1985,7 @@ export async function buildEveProjectSnapshot(options) {
|
|
|
1915
1985
|
requestedRoot: roots.requestedRoot,
|
|
1916
1986
|
canonicalRoot: roots.canonicalRoot,
|
|
1917
1987
|
projectId: contract.projectId,
|
|
1918
|
-
packageManager:
|
|
1988
|
+
packageManager: contract.packageManager,
|
|
1919
1989
|
packageManagerVersion: contract.packageManagerVersion,
|
|
1920
1990
|
packageJsonSha256: contract.packageJsonSha256,
|
|
1921
1991
|
lockfileSha256: contract.lockfileSha256,
|
|
@@ -1965,6 +2035,8 @@ export async function buildEveProjectSnapshot(options) {
|
|
|
1965
2035
|
snapshotRoot,
|
|
1966
2036
|
dockerfilePath,
|
|
1967
2037
|
nodeImage,
|
|
2038
|
+
packageManager: contract.packageManager,
|
|
2039
|
+
lockfilePath: contract.lockfilePath,
|
|
1968
2040
|
packageManagerVersion: contract.packageManagerVersion,
|
|
1969
2041
|
lockfileSha256: contract.lockfileSha256,
|
|
1970
2042
|
});
|
|
@@ -1977,7 +2049,7 @@ export async function buildEveProjectSnapshot(options) {
|
|
|
1977
2049
|
inputManifestPath,
|
|
1978
2050
|
dockerfilePath: actualDockerfilePath,
|
|
1979
2051
|
packageManagerVersion: contract.packageManagerVersion,
|
|
1980
|
-
installCommand:
|
|
2052
|
+
installCommand: contract.installCommand,
|
|
1981
2053
|
buildCommand: BUILD_COMMAND,
|
|
1982
2054
|
platform: "linux/amd64",
|
|
1983
2055
|
sourceDigest: initialInputs.sourceDigest,
|
|
@@ -2009,14 +2081,14 @@ export async function buildEveProjectSnapshot(options) {
|
|
|
2009
2081
|
const cleanupError = await discardBuiltCandidate();
|
|
2010
2082
|
return blockedResult(cleanupError ?? afterBuildRace, { writtenPaths });
|
|
2011
2083
|
}
|
|
2012
|
-
const snapshotLockfile = await readStableFile(join(snapshotRoot,
|
|
2084
|
+
const snapshotLockfile = await readStableFile(join(snapshotRoot, contract.lockfilePath), snapshotRoot);
|
|
2013
2085
|
if (snapshotLockfile.sha256 !== contract.lockfileSha256 ||
|
|
2014
2086
|
!snapshotLockfile.bytes.equals(contract.lockfileBytes)) {
|
|
2015
2087
|
const dependencyError = new EvePackagingError({
|
|
2016
2088
|
code: "DEPENDENCY_AMBIGUITY",
|
|
2017
|
-
subject:
|
|
2089
|
+
subject: contract.lockfilePath,
|
|
2018
2090
|
reason: "The frozen install changed the captured lockfile bytes.",
|
|
2019
|
-
remediation: "Use the exact
|
|
2091
|
+
remediation: "Use the selected exact package manager with its frozen install command.",
|
|
2020
2092
|
});
|
|
2021
2093
|
const cleanupError = await discardBuiltCandidate();
|
|
2022
2094
|
return blockedResult(cleanupError ?? dependencyError, { writtenPaths });
|
|
@@ -2031,9 +2103,9 @@ export async function buildEveProjectSnapshot(options) {
|
|
|
2031
2103
|
await writeJson(runtimeManifestPath, {
|
|
2032
2104
|
version: 1,
|
|
2033
2105
|
generationId: basename(generationRoot),
|
|
2034
|
-
packageManager:
|
|
2106
|
+
packageManager: contract.packageManager,
|
|
2035
2107
|
packageManagerVersion: contract.packageManagerVersion,
|
|
2036
|
-
installCommand:
|
|
2108
|
+
installCommand: contract.installCommand,
|
|
2037
2109
|
buildCommand: BUILD_COMMAND,
|
|
2038
2110
|
startCommand: START_COMMAND,
|
|
2039
2111
|
sourceDigest: initialInputs.sourceDigest,
|
|
@@ -2093,7 +2165,7 @@ export async function buildEveProjectSnapshot(options) {
|
|
|
2093
2165
|
sha256: contract.packageJsonSha256,
|
|
2094
2166
|
},
|
|
2095
2167
|
lockfile: {
|
|
2096
|
-
path:
|
|
2168
|
+
path: contract.lockfilePath,
|
|
2097
2169
|
sha256: contract.lockfileSha256,
|
|
2098
2170
|
},
|
|
2099
2171
|
sourceDigest: initialInputs.sourceDigest,
|
|
@@ -2104,9 +2176,9 @@ export async function buildEveProjectSnapshot(options) {
|
|
|
2104
2176
|
generationRoot,
|
|
2105
2177
|
snapshotRoot,
|
|
2106
2178
|
inputManifestPath,
|
|
2107
|
-
packageManager:
|
|
2179
|
+
packageManager: contract.packageManager,
|
|
2108
2180
|
packageManagerVersion: contract.packageManagerVersion,
|
|
2109
|
-
installCommand:
|
|
2181
|
+
installCommand: contract.installCommand,
|
|
2110
2182
|
buildCommand: BUILD_COMMAND,
|
|
2111
2183
|
eveExecutable: "node_modules/.bin/eve",
|
|
2112
2184
|
eveVersion: eve.version,
|
|
@@ -2137,9 +2209,9 @@ export async function buildEveProjectSnapshot(options) {
|
|
|
2137
2209
|
snapshot,
|
|
2138
2210
|
toolchain: {
|
|
2139
2211
|
nodeVersion: "24.17.0",
|
|
2140
|
-
packageManager:
|
|
2212
|
+
packageManager: contract.packageManager,
|
|
2141
2213
|
packageManagerVersion: contract.packageManagerVersion,
|
|
2142
|
-
installCommand:
|
|
2214
|
+
installCommand: contract.installCommand,
|
|
2143
2215
|
buildCommand: BUILD_COMMAND,
|
|
2144
2216
|
startCommand: START_COMMAND,
|
|
2145
2217
|
eveExecutable: eve.path,
|
|
@@ -2172,7 +2244,7 @@ export async function buildEveProjectSnapshot(options) {
|
|
|
2172
2244
|
id: "VAL-BUILD-001",
|
|
2173
2245
|
status: "pass",
|
|
2174
2246
|
subject: "package-manager",
|
|
2175
|
-
reason: "The
|
|
2247
|
+
reason: "The selected package manager and one matching regular root lockfile were verified.",
|
|
2176
2248
|
remediation: null,
|
|
2177
2249
|
},
|
|
2178
2250
|
{
|
|
@@ -2287,7 +2359,7 @@ export async function revalidateEveProjectCandidateInputs(candidate, runtimeConf
|
|
|
2287
2359
|
}
|
|
2288
2360
|
const observedLatest = latest ?? fail();
|
|
2289
2361
|
const packageFile = observedLatest.files.find((file) => file.relativePath === "package.json");
|
|
2290
|
-
const lockfile = observedLatest.files.find((file) => file.relativePath === "pnpm-lock.yaml");
|
|
2362
|
+
const lockfile = observedLatest.files.find((file) => file.relativePath === (candidate.packageManager === "npm" ? "package-lock.json" : "pnpm-lock.yaml"));
|
|
2291
2363
|
if (packageFile === undefined ||
|
|
2292
2364
|
lockfile === undefined ||
|
|
2293
2365
|
packageFile.sha256 !== candidate.packageJsonSha256 ||
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@moinulmoin/eden",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Deploy existing Eve projects to your own Cloudflare account.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"NOTICE"
|
|
32
32
|
],
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@moinulmoin/eden-runtime-cloudflare": "0.
|
|
34
|
+
"@moinulmoin/eden-runtime-cloudflare": "0.8.0",
|
|
35
35
|
"wrangler": "4.147.0"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|