@solcreek/cli 0.4.25 → 0.4.27

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.
@@ -13,7 +13,7 @@ import { prepareDeployBundle } from "../utils/prepare-bundle.js";
13
13
  import { BuildLogEmitter } from "../utils/build-log.js";
14
14
  import { isTTY, jsonOutput, resolveJsonMode, globalArgs, shouldAutoConfirm, AUTH_BREADCRUMBS, NO_PROJECT_BREADCRUMBS } from "../utils/output.js";
15
15
  import { ensureTosAccepted } from "../utils/tos.js";
16
- import { hasAdapterOutput } from "../utils/nextjs.js";
16
+ import { hasAdapterOutput, readAdapterCompat } from "../utils/nextjs.js";
17
17
  import { isRepoUrl, parseRepoUrl, validateRepoUrl, validateSubpath, RepoUrlError } from "../utils/repo-url.js";
18
18
  import { checkGitInstalled, cloneRepo, detectPackageManager, installDependencies, cleanupDir as cleanupCloneDir, GitCloneError } from "../utils/git-clone.js";
19
19
  import { CreekdClient, getCreekdUrl } from "../utils/creekd-client.js";
@@ -991,6 +991,14 @@ async function deploySandbox(cwd, skipBuild, jsonMode = false, resolved, tos) {
991
991
  section("Deploy");
992
992
  consola.start(" Deploying to edge...");
993
993
  }
994
+ // An adapter build records the exact compat it was built against in its
995
+ // manifest; deploy with that so the worker validates at upload (e.g.
996
+ // node:http server modules need nodejs_compat + compatibility_date
997
+ // >= 2025-09-01). Fall back to the resolved config for non-adapter builds.
998
+ const sandboxAdapterCompat = readAdapterCompat(cwd);
999
+ const sandboxCompatDate = sandboxAdapterCompat?.compatibilityDate ?? resolved?.compatibilityDate;
1000
+ const sandboxCompatFlags = sandboxAdapterCompat?.compatibilityFlags ??
1001
+ (resolved && resolved.compatibilityFlags.length > 0 ? resolved.compatibilityFlags : undefined);
994
1002
  try {
995
1003
  const result = await sandboxDeploy({
996
1004
  manifest: {
@@ -1006,11 +1014,9 @@ async function deploySandbox(cwd, skipBuild, jsonMode = false, resolved, tos) {
1006
1014
  ...(resolved
1007
1015
  ? { bindings: resolvedConfigToBindingRequirements(resolved) }
1008
1016
  : {}),
1009
- ...(resolved?.compatibilityDate
1010
- ? { compatibilityDate: resolved.compatibilityDate }
1011
- : {}),
1012
- ...(resolved && resolved.compatibilityFlags.length > 0
1013
- ? { compatibilityFlags: resolved.compatibilityFlags }
1017
+ ...(sandboxCompatDate ? { compatibilityDate: sandboxCompatDate } : {}),
1018
+ ...(sandboxCompatFlags && sandboxCompatFlags.length > 0
1019
+ ? { compatibilityFlags: sandboxCompatFlags }
1014
1020
  : {}),
1015
1021
  }, { tos });
1016
1022
  const status = await pollSandboxStatus(result.statusUrl);
@@ -1234,6 +1240,16 @@ async function deployAuthenticated(cwd, resolved, token, skipBuild, jsonMode = f
1234
1240
  buildLog.info("bundle", `${fileList.length} assets (${assetSummary(fileList)})`);
1235
1241
  consola.start(" Uploading bundle...");
1236
1242
  const effectiveHasWorker = serverFiles !== undefined;
1243
+ // Prefer the compat the adapter built the worker against (recorded in its
1244
+ // manifest) so the deploy matches the build — node:http server modules
1245
+ // need nodejs_compat + compatibility_date >= 2025-09-01. Falls back to the
1246
+ // resolved config + a framework-aware default for non-adapter builds.
1247
+ const prodAdapterCompat = readAdapterCompat(cwd);
1248
+ const prodCompatDate = prodAdapterCompat?.compatibilityDate ?? resolved.compatibilityDate;
1249
+ const prodCompatFlags = prodAdapterCompat?.compatibilityFlags ??
1250
+ (hasAdapterOutput(cwd)
1251
+ ? ["nodejs_compat"]
1252
+ : ["nodejs_compat", ...resolved.compatibilityFlags.filter((f) => f !== "nodejs_compat")]);
1237
1253
  const bundle = {
1238
1254
  manifest: {
1239
1255
  assets: fileList,
@@ -1249,15 +1265,8 @@ async function deployAuthenticated(cwd, resolved, token, skipBuild, jsonMode = f
1249
1265
  bindings: resolvedConfigToBindingRequirements(resolved),
1250
1266
  // Pass through wrangler vars and compat settings
1251
1267
  ...(Object.keys(resolved.vars).length > 0 ? { vars: resolved.vars } : {}),
1252
- ...(resolved.compatibilityDate ? { compatibilityDate: resolved.compatibilityDate } : {}),
1253
- // nodejs_compat required for Creek runtime (AsyncLocalStorage).
1254
- // Adapter path uses nodejs_compat_v2 for full Node.js APIs.
1255
- ...(hasAdapterOutput(cwd)
1256
- ? { compatibilityFlags: ["nodejs_compat_v2"] }
1257
- : { compatibilityFlags: [
1258
- "nodejs_compat",
1259
- ...resolved.compatibilityFlags.filter((f) => f !== "nodejs_compat"),
1260
- ] }),
1268
+ ...(prodCompatDate ? { compatibilityDate: prodCompatDate } : {}),
1269
+ compatibilityFlags: prodCompatFlags,
1261
1270
  ...(resolved.cron.length > 0 ? { cron: resolved.cron } : {}),
1262
1271
  ...(resolved.queue ? { queue: true } : {}),
1263
1272
  };
@@ -26,6 +26,18 @@ export declare function getNextVersion(cwd: string): string | null;
26
26
  export declare function buildNextjs(cwd: string, isMonorepo: boolean, projectName?: string): void;
27
27
  /** Check if the adapter output exists (vs legacy opennext output). */
28
28
  export declare function hasAdapterOutput(cwd: string): boolean;
29
+ /**
30
+ * Read the compat settings the adapter built the worker with from
31
+ * `.creek/adapter-output/manifest.json`. The worker is validated at upload
32
+ * against the date/flags it ships with (e.g. node:http server modules need
33
+ * `nodejs_compat` + compatibility_date >= 2025-09-01), so the deploy must
34
+ * use exactly what the adapter built against rather than a hardcoded default
35
+ * that can drift. Returns null when absent/unparseable (caller falls back).
36
+ */
37
+ export declare function readAdapterCompat(cwd: string): {
38
+ compatibilityDate?: string;
39
+ compatibilityFlags?: string[];
40
+ } | null;
29
41
  /**
30
42
  * Patch the bundled worker to fix opennext's dynamic require issues.
31
43
  *
@@ -142,6 +142,31 @@ export function buildNextjs(cwd, isMonorepo, projectName) {
142
142
  export function hasAdapterOutput(cwd) {
143
143
  return existsSync(join(cwd, ".creek/adapter-output/manifest.json"));
144
144
  }
145
+ /**
146
+ * Read the compat settings the adapter built the worker with from
147
+ * `.creek/adapter-output/manifest.json`. The worker is validated at upload
148
+ * against the date/flags it ships with (e.g. node:http server modules need
149
+ * `nodejs_compat` + compatibility_date >= 2025-09-01), so the deploy must
150
+ * use exactly what the adapter built against rather than a hardcoded default
151
+ * that can drift. Returns null when absent/unparseable (caller falls back).
152
+ */
153
+ export function readAdapterCompat(cwd) {
154
+ const manifestPath = join(cwd, ".creek/adapter-output/manifest.json");
155
+ if (!existsSync(manifestPath))
156
+ return null;
157
+ try {
158
+ const m = JSON.parse(readFileSync(manifestPath, "utf-8"));
159
+ const out = {};
160
+ if (typeof m.compatibilityDate === "string")
161
+ out.compatibilityDate = m.compatibilityDate;
162
+ if (Array.isArray(m.compatibilityFlags))
163
+ out.compatibilityFlags = m.compatibilityFlags;
164
+ return out;
165
+ }
166
+ catch {
167
+ return null;
168
+ }
169
+ }
145
170
  /**
146
171
  * Patch the bundled worker to fix opennext's dynamic require issues.
147
172
  *
@@ -179,11 +204,13 @@ const CREEK_DIR = ".creek";
179
204
  const OPENNEXT_PKG = "@opennextjs/cloudflare";
180
205
  const OPENNEXT_VERSION = "^1.18.0";
181
206
  const ADAPTER_PKG = "@solcreek/adapter-creek";
182
- const ADAPTER_VERSION = "^0.2.1";
183
- // Adapter < 0.2.1 resolves its cache handler against paths that don't exist
184
- // under the .creek lazy install, failing every Next.js build with webpack
185
- // "Module not found". Installs below this are re-installed, not reused.
186
- const ADAPTER_MIN_VERSION = "0.2.1";
207
+ const ADAPTER_VERSION = "^0.2.2";
208
+ // Adapter < 0.2.2 resolves its dependencies against paths that don't exist
209
+ // under the .creek lazy install (0.2.0: the cache handler; 0.2.1: the
210
+ // wrangler bin) npm hoists them to the top of the tree, so the adapter's
211
+ // guessed nested paths fail every Next.js build. Installs below this are
212
+ // re-installed, not reused.
213
+ const ADAPTER_MIN_VERSION = "0.2.2";
187
214
  /**
188
215
  * Merge a dependency into .creek/package.json without clobbering deps that
189
216
  * a previous install (adapter or opennext) may have already written.
@@ -213,7 +240,11 @@ function installCreekDep(creekDir, pkg, version) {
213
240
  mkdirSync(creekDir, { recursive: true });
214
241
  upsertCreekDep(creekDir, pkg, version);
215
242
  try {
216
- execSync("npm install --no-audit --no-fund --ignore-scripts --no-optional", {
243
+ // No --no-optional: the adapter bundles the worker with wrangler, whose
244
+ // workerd dependency ships its platform binary (@cloudflare/workerd-*)
245
+ // as an optionalDependency. Omitting optionals fails the build with
246
+ // "package could not be found, and is needed by workerd".
247
+ execSync("npm install --no-audit --no-fund --ignore-scripts", {
217
248
  cwd: creekDir,
218
249
  stdio: "pipe",
219
250
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solcreek/cli",
3
- "version": "0.4.25",
3
+ "version": "0.4.27",
4
4
  "description": "CLI for the Creek deployment platform",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",