@solcreek/cli 0.4.26 → 0.4.28
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/commands/deploy.js +24 -15
- package/dist/utils/nextjs.d.ts +28 -0
- package/dist/utils/nextjs.js +80 -0
- package/package.json +2 -1
package/dist/commands/deploy.js
CHANGED
|
@@ -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
|
-
...(
|
|
1010
|
-
|
|
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
|
-
...(
|
|
1253
|
-
|
|
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
|
};
|
package/dist/utils/nextjs.d.ts
CHANGED
|
@@ -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
|
*
|
|
@@ -33,6 +45,22 @@ export declare function hasAdapterOutput(cwd: string): boolean;
|
|
|
33
45
|
* the Creek adapter handles middleware via typed AdapterOutputs.
|
|
34
46
|
*/
|
|
35
47
|
export declare function patchBundledWorker(bundleDir: string, openNextDir: string): void;
|
|
48
|
+
/**
|
|
49
|
+
* Ensure @prisma/adapter-d1 is resolvable at build time for the zero-change
|
|
50
|
+
* Prisma-on-D1 swap. adapter-creek aliases `@prisma/adapter-better-sqlite3` to
|
|
51
|
+
* a PrismaD1-backed shim that imports `@prisma/adapter-d1`; that package is an
|
|
52
|
+
* OPTIONAL peer of the adapter (not shipped to non-Prisma projects), so it is
|
|
53
|
+
* lazily installed into .creek only when the project actually uses the
|
|
54
|
+
* better-sqlite3 Prisma adapter. Installed matching the project's Prisma
|
|
55
|
+
* version — the adapter packages release in lockstep with @prisma/client, so a
|
|
56
|
+
* matching driver-adapter interface avoids subtle version skew.
|
|
57
|
+
*
|
|
58
|
+
* No-op unless @prisma/adapter-better-sqlite3 is present, or if adapter-d1 is
|
|
59
|
+
* already resolvable (project dep or a prior .creek install).
|
|
60
|
+
*
|
|
61
|
+
* Exported for tests.
|
|
62
|
+
*/
|
|
63
|
+
export declare function ensurePrismaD1(cwd: string): void;
|
|
36
64
|
/**
|
|
37
65
|
* Fix the standalone output path for monorepo builds.
|
|
38
66
|
*
|
package/dist/utils/nextjs.js
CHANGED
|
@@ -128,6 +128,7 @@ export function buildNextjs(cwd, isMonorepo, projectName) {
|
|
|
128
128
|
if (version && semverGte(version, "16.2.3")) {
|
|
129
129
|
const adapterPath = ensureAdapter(cwd);
|
|
130
130
|
if (adapterPath) {
|
|
131
|
+
ensurePrismaD1(cwd);
|
|
131
132
|
buildWithAdapter(cwd, adapterPath);
|
|
132
133
|
return;
|
|
133
134
|
}
|
|
@@ -142,6 +143,31 @@ export function buildNextjs(cwd, isMonorepo, projectName) {
|
|
|
142
143
|
export function hasAdapterOutput(cwd) {
|
|
143
144
|
return existsSync(join(cwd, ".creek/adapter-output/manifest.json"));
|
|
144
145
|
}
|
|
146
|
+
/**
|
|
147
|
+
* Read the compat settings the adapter built the worker with from
|
|
148
|
+
* `.creek/adapter-output/manifest.json`. The worker is validated at upload
|
|
149
|
+
* against the date/flags it ships with (e.g. node:http server modules need
|
|
150
|
+
* `nodejs_compat` + compatibility_date >= 2025-09-01), so the deploy must
|
|
151
|
+
* use exactly what the adapter built against rather than a hardcoded default
|
|
152
|
+
* that can drift. Returns null when absent/unparseable (caller falls back).
|
|
153
|
+
*/
|
|
154
|
+
export function readAdapterCompat(cwd) {
|
|
155
|
+
const manifestPath = join(cwd, ".creek/adapter-output/manifest.json");
|
|
156
|
+
if (!existsSync(manifestPath))
|
|
157
|
+
return null;
|
|
158
|
+
try {
|
|
159
|
+
const m = JSON.parse(readFileSync(manifestPath, "utf-8"));
|
|
160
|
+
const out = {};
|
|
161
|
+
if (typeof m.compatibilityDate === "string")
|
|
162
|
+
out.compatibilityDate = m.compatibilityDate;
|
|
163
|
+
if (Array.isArray(m.compatibilityFlags))
|
|
164
|
+
out.compatibilityFlags = m.compatibilityFlags;
|
|
165
|
+
return out;
|
|
166
|
+
}
|
|
167
|
+
catch {
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
145
171
|
/**
|
|
146
172
|
* Patch the bundled worker to fix opennext's dynamic require issues.
|
|
147
173
|
*
|
|
@@ -180,6 +206,10 @@ const OPENNEXT_PKG = "@opennextjs/cloudflare";
|
|
|
180
206
|
const OPENNEXT_VERSION = "^1.18.0";
|
|
181
207
|
const ADAPTER_PKG = "@solcreek/adapter-creek";
|
|
182
208
|
const ADAPTER_VERSION = "^0.2.2";
|
|
209
|
+
// Zero-change Prisma-on-D1: the adapter's build-time swap targets this
|
|
210
|
+
// adapter and imports @prisma/adapter-d1 (an optional peer it doesn't ship).
|
|
211
|
+
const PRISMA_BSQLITE_PKG = "@prisma/adapter-better-sqlite3";
|
|
212
|
+
const PRISMA_D1_PKG = "@prisma/adapter-d1";
|
|
183
213
|
// Adapter < 0.2.2 resolves its dependencies against paths that don't exist
|
|
184
214
|
// under the .creek lazy install (0.2.0: the cache handler; 0.2.1: the
|
|
185
215
|
// wrangler bin) — npm hoists them to the top of the tree, so the adapter's
|
|
@@ -258,6 +288,56 @@ function ensureAdapter(cwd) {
|
|
|
258
288
|
consola.success(` ${ADAPTER_PKG} installed`);
|
|
259
289
|
return resolved;
|
|
260
290
|
}
|
|
291
|
+
/**
|
|
292
|
+
* Ensure @prisma/adapter-d1 is resolvable at build time for the zero-change
|
|
293
|
+
* Prisma-on-D1 swap. adapter-creek aliases `@prisma/adapter-better-sqlite3` to
|
|
294
|
+
* a PrismaD1-backed shim that imports `@prisma/adapter-d1`; that package is an
|
|
295
|
+
* OPTIONAL peer of the adapter (not shipped to non-Prisma projects), so it is
|
|
296
|
+
* lazily installed into .creek only when the project actually uses the
|
|
297
|
+
* better-sqlite3 Prisma adapter. Installed matching the project's Prisma
|
|
298
|
+
* version — the adapter packages release in lockstep with @prisma/client, so a
|
|
299
|
+
* matching driver-adapter interface avoids subtle version skew.
|
|
300
|
+
*
|
|
301
|
+
* No-op unless @prisma/adapter-better-sqlite3 is present, or if adapter-d1 is
|
|
302
|
+
* already resolvable (project dep or a prior .creek install).
|
|
303
|
+
*
|
|
304
|
+
* Exported for tests.
|
|
305
|
+
*/
|
|
306
|
+
export function ensurePrismaD1(cwd) {
|
|
307
|
+
const projectRequire = createRequire(join(cwd, "noop.js"));
|
|
308
|
+
try {
|
|
309
|
+
projectRequire.resolve(PRISMA_BSQLITE_PKG);
|
|
310
|
+
}
|
|
311
|
+
catch {
|
|
312
|
+
return; // Not a Prisma-on-D1 (better-sqlite3 adapter) project.
|
|
313
|
+
}
|
|
314
|
+
// createRequire from .creek walks up into the project's node_modules too, so
|
|
315
|
+
// this single check covers both a prior .creek install and a project dep.
|
|
316
|
+
const creekDir = join(cwd, CREEK_DIR);
|
|
317
|
+
try {
|
|
318
|
+
createRequire(join(creekDir, "noop.js")).resolve(PRISMA_D1_PKG);
|
|
319
|
+
return; // Already available.
|
|
320
|
+
}
|
|
321
|
+
catch {
|
|
322
|
+
// Fall through to install.
|
|
323
|
+
}
|
|
324
|
+
let version = "latest";
|
|
325
|
+
try {
|
|
326
|
+
const clientPkg = JSON.parse(readFileSync(projectRequire.resolve("@prisma/client/package.json"), "utf-8"));
|
|
327
|
+
if (clientPkg.version)
|
|
328
|
+
version = clientPkg.version;
|
|
329
|
+
}
|
|
330
|
+
catch {
|
|
331
|
+
// No @prisma/client version readable — fall back to latest.
|
|
332
|
+
}
|
|
333
|
+
consola.start(` Installing ${PRISMA_D1_PKG}@${version} (Prisma on D1)...`);
|
|
334
|
+
if (installCreekDep(creekDir, PRISMA_D1_PKG, version)) {
|
|
335
|
+
consola.success(` ${PRISMA_D1_PKG} installed`);
|
|
336
|
+
}
|
|
337
|
+
else {
|
|
338
|
+
consola.warn(` Could not install ${PRISMA_D1_PKG} — Prisma build may fail`);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
261
341
|
/**
|
|
262
342
|
* Ensure @opennextjs/cloudflare is available in .creek/node_modules.
|
|
263
343
|
* Returns the path to the opennextjs-cloudflare CLI binary.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solcreek/cli",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.28",
|
|
4
4
|
"description": "CLI for the Creek deployment platform",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
"hono": "^4.7.4",
|
|
45
45
|
"jsdom": "^29.0.1",
|
|
46
46
|
"miniflare": "^4.20260317.3",
|
|
47
|
+
"msw": "^2.12.14",
|
|
47
48
|
"react": "^19.2.4",
|
|
48
49
|
"react-dom": "^19.2.4",
|
|
49
50
|
"typescript": "^5.8.2",
|