@solcreek/cli 0.4.29 → 0.4.31
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 +14 -0
- package/dist/utils/db-preflight.d.ts +105 -0
- package/dist/utils/db-preflight.js +199 -0
- package/dist/utils/nextjs.js +36 -6
- package/package.json +1 -1
package/dist/commands/deploy.js
CHANGED
|
@@ -8,6 +8,7 @@ import { CreekClient, CreekAuthError, detectFramework, resolveConfig, formatDete
|
|
|
8
8
|
import { buildDoctorContext } from "../utils/doctor-context.js";
|
|
9
9
|
import { getToken, getApiUrl } from "../utils/config.js";
|
|
10
10
|
import { collectAssets } from "../utils/bundle.js";
|
|
11
|
+
import { runDatabasePreflight, makePreflightIO, readProjectDeps } from "../utils/db-preflight.js";
|
|
11
12
|
import { sandboxDeploy, pollSandboxStatus, printSandboxSuccess, expiresInMinutes } from "../utils/sandbox.js";
|
|
12
13
|
import { prepareDeployBundle } from "../utils/prepare-bundle.js";
|
|
13
14
|
import { BuildLogEmitter } from "../utils/build-log.js";
|
|
@@ -345,6 +346,19 @@ export const deployCommand = defineCommand({
|
|
|
345
346
|
throw err;
|
|
346
347
|
}
|
|
347
348
|
if (resolved) {
|
|
349
|
+
// Database deploy preflight: when the app uses Prisma/Drizzle on SQLite
|
|
350
|
+
// but creek.toml hasn't declared a database, confirm provisioning a D1
|
|
351
|
+
// (a cloud instance, separate from the local file) and re-resolve so the
|
|
352
|
+
// binding is included in this deploy. Confirm-first; no-op when already
|
|
353
|
+
// decided or non-interactive without --yes.
|
|
354
|
+
const dbPreflight = await runDatabasePreflight({
|
|
355
|
+
deps: readProjectDeps(cwd),
|
|
356
|
+
projectName: resolved.projectName,
|
|
357
|
+
tty: isTTY && !jsonMode,
|
|
358
|
+
autoYes: shouldAutoConfirm(args),
|
|
359
|
+
}, makePreflightIO(cwd));
|
|
360
|
+
if (dbPreflight.wroteToml)
|
|
361
|
+
resolved = resolveConfig(cwd);
|
|
348
362
|
if (!jsonMode) {
|
|
349
363
|
consola.info(` Detected: ${formatDetectionSummary(resolved)}`);
|
|
350
364
|
for (const ub of resolved.unsupportedBindings) {
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Database deploy preflight: detect → confirm helpers.
|
|
3
|
+
*
|
|
4
|
+
* An app that uses Prisma or Drizzle on local SQLite runs on a Cloudflare D1
|
|
5
|
+
* database on Creek (a separate cloud instance from the local file). Getting
|
|
6
|
+
* there needs `database = true` under `[resources]` in creek.toml and, for
|
|
7
|
+
* Prisma, a generated client. These pure helpers detect that situation and
|
|
8
|
+
* patch creek.toml; the actual prompts, file writes, and `creek db migrate`
|
|
9
|
+
* are wired by the deploy command so the consequential steps stay behind
|
|
10
|
+
* explicit consent (see the deploy flow).
|
|
11
|
+
*
|
|
12
|
+
* Design split by risk: client generation is safe to automate; provisioning a
|
|
13
|
+
* (billed) database is confirm-first; applying migrations is never silent.
|
|
14
|
+
*
|
|
15
|
+
* Pure functions are exported for testing.
|
|
16
|
+
*/
|
|
17
|
+
export type SqliteOrm = "prisma" | "drizzle";
|
|
18
|
+
/**
|
|
19
|
+
* Detect an ORM configured against local SQLite — the case Creek swaps onto
|
|
20
|
+
* D1. The signal is the presence of the better-sqlite3 driver/adapter the
|
|
21
|
+
* adapter-creek build-time swap targets:
|
|
22
|
+
* - Prisma: `@prisma/adapter-better-sqlite3`
|
|
23
|
+
* - Drizzle: `drizzle-orm` + `better-sqlite3`
|
|
24
|
+
*
|
|
25
|
+
* Returns null when neither is present (e.g. an app on an external DB, or
|
|
26
|
+
* Drizzle pointed straight at `drizzle-orm/d1`), so we never guess a database
|
|
27
|
+
* the project didn't ask for.
|
|
28
|
+
*/
|
|
29
|
+
export declare function detectSqliteOrm(deps: Record<string, string | undefined>): SqliteOrm | null;
|
|
30
|
+
export type DatabaseDirective = "enabled" | "disabled" | "absent";
|
|
31
|
+
/**
|
|
32
|
+
* Read the `[resources].database` directive from raw creek.toml text — NOT the
|
|
33
|
+
* SDK-parsed config, because the parser defaults `database` to `false` and so
|
|
34
|
+
* can't tell "explicitly opted out" from "never decided". The distinction
|
|
35
|
+
* drives whether we may prompt:
|
|
36
|
+
* - "enabled" → already on, nothing to do
|
|
37
|
+
* - "disabled" → explicit opt-out, never prompt
|
|
38
|
+
* - "absent" → undecided, eligible to prompt
|
|
39
|
+
*/
|
|
40
|
+
export declare function databaseDirectiveState(rawToml: string | null): DatabaseDirective;
|
|
41
|
+
/**
|
|
42
|
+
* Patch raw creek.toml to enable the database resource, preserving existing
|
|
43
|
+
* content (so the file stays reviewable). Only called when the directive is
|
|
44
|
+
* "absent". Handles: no file, `[resources]` present (insert the key), and
|
|
45
|
+
* `[resources]` missing (append the section, prepending `[project]` when the
|
|
46
|
+
* file has none so the result is a valid creek.toml).
|
|
47
|
+
*/
|
|
48
|
+
export declare function enableDatabaseResource(rawToml: string | null, projectName: string): string;
|
|
49
|
+
/**
|
|
50
|
+
* Whether the project uses Prisma and its client hasn't been generated yet.
|
|
51
|
+
* Safe to act on automatically (generation is idempotent, no external effect).
|
|
52
|
+
* Conservative: only true when a schema exists, declares an `output`, and that
|
|
53
|
+
* directory is missing — otherwise we leave the user's setup untouched.
|
|
54
|
+
*/
|
|
55
|
+
export declare function prismaNeedsGenerate(cwd: string): boolean;
|
|
56
|
+
/**
|
|
57
|
+
* Side-effect surface for the database preflight, injected so the decision flow
|
|
58
|
+
* is testable without a real terminal or filesystem. `confirm` resolves the
|
|
59
|
+
* interactive yes/no; `readToml`/`writeToml` are the raw creek.toml.
|
|
60
|
+
*/
|
|
61
|
+
export interface PreflightIO {
|
|
62
|
+
readToml(): string | null;
|
|
63
|
+
writeToml(content: string): void;
|
|
64
|
+
confirm(message: string): Promise<boolean>;
|
|
65
|
+
log(message: string): void;
|
|
66
|
+
warn(message: string): void;
|
|
67
|
+
}
|
|
68
|
+
export interface PreflightOptions {
|
|
69
|
+
deps: Record<string, string | undefined>;
|
|
70
|
+
projectName: string;
|
|
71
|
+
/** Interactive terminal — may prompt. */
|
|
72
|
+
tty: boolean;
|
|
73
|
+
/** `--yes`: auto-accept the (low-risk) DB-resource provisioning. */
|
|
74
|
+
autoYes: boolean;
|
|
75
|
+
}
|
|
76
|
+
export interface PreflightResult {
|
|
77
|
+
/** creek.toml was patched — the caller must re-resolve config before deploy. */
|
|
78
|
+
wroteToml: boolean;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Confirm-first database provisioning. When the project uses an ORM on SQLite
|
|
82
|
+
* but creek.toml hasn't decided on a database resource, prompt (or auto-accept
|
|
83
|
+
* under --yes) to add `database = true`. Never overrides an explicit opt-out,
|
|
84
|
+
* never prompts in non-interactive contexts (warns and continues — the deploy
|
|
85
|
+
* still succeeds and DB routes return a self-documenting hint at runtime).
|
|
86
|
+
*/
|
|
87
|
+
export declare function runDatabasePreflight(opts: PreflightOptions, io: PreflightIO): Promise<PreflightResult>;
|
|
88
|
+
/**
|
|
89
|
+
* What to do about a detected migration directory after the database exists.
|
|
90
|
+
* Migrations can be destructive, so this is never silent:
|
|
91
|
+
* - "run" → explicit opt-in (`--migrate`)
|
|
92
|
+
* - "prompt" → interactive (ask, default no)
|
|
93
|
+
* - "suggest" → non-interactive (print the command, don't run)
|
|
94
|
+
* - "none" → no migrations to apply
|
|
95
|
+
*/
|
|
96
|
+
export declare function migrationOfferPlan(opts: {
|
|
97
|
+
migrationDir: string | null;
|
|
98
|
+
tty: boolean;
|
|
99
|
+
autoMigrate: boolean;
|
|
100
|
+
}): "run" | "prompt" | "suggest" | "none";
|
|
101
|
+
/** Merged dependencies + devDependencies from the project's package.json. */
|
|
102
|
+
export declare function readProjectDeps(cwd: string): Record<string, string | undefined>;
|
|
103
|
+
/** Real (consola + filesystem) PreflightIO for the deploy command. */
|
|
104
|
+
export declare function makePreflightIO(cwd: string): PreflightIO;
|
|
105
|
+
//# sourceMappingURL=db-preflight.d.ts.map
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Database deploy preflight: detect → confirm helpers.
|
|
3
|
+
*
|
|
4
|
+
* An app that uses Prisma or Drizzle on local SQLite runs on a Cloudflare D1
|
|
5
|
+
* database on Creek (a separate cloud instance from the local file). Getting
|
|
6
|
+
* there needs `database = true` under `[resources]` in creek.toml and, for
|
|
7
|
+
* Prisma, a generated client. These pure helpers detect that situation and
|
|
8
|
+
* patch creek.toml; the actual prompts, file writes, and `creek db migrate`
|
|
9
|
+
* are wired by the deploy command so the consequential steps stay behind
|
|
10
|
+
* explicit consent (see the deploy flow).
|
|
11
|
+
*
|
|
12
|
+
* Design split by risk: client generation is safe to automate; provisioning a
|
|
13
|
+
* (billed) database is confirm-first; applying migrations is never silent.
|
|
14
|
+
*
|
|
15
|
+
* Pure functions are exported for testing.
|
|
16
|
+
*/
|
|
17
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
18
|
+
import { join } from "node:path";
|
|
19
|
+
import consola from "consola";
|
|
20
|
+
/**
|
|
21
|
+
* Detect an ORM configured against local SQLite — the case Creek swaps onto
|
|
22
|
+
* D1. The signal is the presence of the better-sqlite3 driver/adapter the
|
|
23
|
+
* adapter-creek build-time swap targets:
|
|
24
|
+
* - Prisma: `@prisma/adapter-better-sqlite3`
|
|
25
|
+
* - Drizzle: `drizzle-orm` + `better-sqlite3`
|
|
26
|
+
*
|
|
27
|
+
* Returns null when neither is present (e.g. an app on an external DB, or
|
|
28
|
+
* Drizzle pointed straight at `drizzle-orm/d1`), so we never guess a database
|
|
29
|
+
* the project didn't ask for.
|
|
30
|
+
*/
|
|
31
|
+
export function detectSqliteOrm(deps) {
|
|
32
|
+
if (deps["@prisma/adapter-better-sqlite3"])
|
|
33
|
+
return "prisma";
|
|
34
|
+
if (deps["drizzle-orm"] && deps["better-sqlite3"])
|
|
35
|
+
return "drizzle";
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Read the `[resources].database` directive from raw creek.toml text — NOT the
|
|
40
|
+
* SDK-parsed config, because the parser defaults `database` to `false` and so
|
|
41
|
+
* can't tell "explicitly opted out" from "never decided". The distinction
|
|
42
|
+
* drives whether we may prompt:
|
|
43
|
+
* - "enabled" → already on, nothing to do
|
|
44
|
+
* - "disabled" → explicit opt-out, never prompt
|
|
45
|
+
* - "absent" → undecided, eligible to prompt
|
|
46
|
+
*/
|
|
47
|
+
export function databaseDirectiveState(rawToml) {
|
|
48
|
+
if (!rawToml)
|
|
49
|
+
return "absent";
|
|
50
|
+
let inResources = false;
|
|
51
|
+
for (const rawLine of rawToml.split(/\r?\n/)) {
|
|
52
|
+
const line = rawLine.trim();
|
|
53
|
+
if (line.startsWith("[")) {
|
|
54
|
+
// A new table header. `[resources]` exactly; `[resources.x]` is a
|
|
55
|
+
// different (sub)table and doesn't carry the boolean directive.
|
|
56
|
+
inResources = line === "[resources]";
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
if (!inResources)
|
|
60
|
+
continue;
|
|
61
|
+
const m = line.match(/^database\s*=\s*(true|false)\b/);
|
|
62
|
+
if (m)
|
|
63
|
+
return m[1] === "true" ? "enabled" : "disabled";
|
|
64
|
+
}
|
|
65
|
+
return "absent";
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Patch raw creek.toml to enable the database resource, preserving existing
|
|
69
|
+
* content (so the file stays reviewable). Only called when the directive is
|
|
70
|
+
* "absent". Handles: no file, `[resources]` present (insert the key), and
|
|
71
|
+
* `[resources]` missing (append the section, prepending `[project]` when the
|
|
72
|
+
* file has none so the result is a valid creek.toml).
|
|
73
|
+
*/
|
|
74
|
+
export function enableDatabaseResource(rawToml, projectName) {
|
|
75
|
+
const resourcesBlock = "[resources]\ndatabase = true\n";
|
|
76
|
+
if (rawToml === null || rawToml.trim() === "") {
|
|
77
|
+
return `[project]\nname = "${projectName}"\n\n${resourcesBlock}`;
|
|
78
|
+
}
|
|
79
|
+
const lines = rawToml.split(/\r?\n/);
|
|
80
|
+
const resourcesIdx = lines.findIndex((l) => l.trim() === "[resources]");
|
|
81
|
+
if (resourcesIdx !== -1) {
|
|
82
|
+
// Insert the key directly under the existing header.
|
|
83
|
+
lines.splice(resourcesIdx + 1, 0, "database = true");
|
|
84
|
+
return lines.join("\n");
|
|
85
|
+
}
|
|
86
|
+
// No [resources] table — append one, ensuring a [project] table exists.
|
|
87
|
+
const hasProject = lines.some((l) => l.trim() === "[project]");
|
|
88
|
+
const trimmed = rawToml.replace(/\s*$/, "");
|
|
89
|
+
const prefix = hasProject ? "" : `[project]\nname = "${projectName}"\n\n`;
|
|
90
|
+
const sep = trimmed === "" ? "" : "\n\n";
|
|
91
|
+
return `${prefix}${trimmed}${sep}${resourcesBlock}`;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Read the generator `output` path from a Prisma schema (Prisma 7's
|
|
95
|
+
* `prisma-client` generator requires one). Returns an absolute path or null.
|
|
96
|
+
*/
|
|
97
|
+
function prismaClientOutput(cwd, schemaPath) {
|
|
98
|
+
let schema;
|
|
99
|
+
try {
|
|
100
|
+
schema = readFileSync(schemaPath, "utf-8");
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
const m = schema.match(/\boutput\s*=\s*"([^"]+)"/);
|
|
106
|
+
if (!m)
|
|
107
|
+
return null;
|
|
108
|
+
const out = m[1];
|
|
109
|
+
return out.startsWith("/") ? out : join(cwd, "prisma", out);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Whether the project uses Prisma and its client hasn't been generated yet.
|
|
113
|
+
* Safe to act on automatically (generation is idempotent, no external effect).
|
|
114
|
+
* Conservative: only true when a schema exists, declares an `output`, and that
|
|
115
|
+
* directory is missing — otherwise we leave the user's setup untouched.
|
|
116
|
+
*/
|
|
117
|
+
export function prismaNeedsGenerate(cwd) {
|
|
118
|
+
const schemaPath = join(cwd, "prisma", "schema.prisma");
|
|
119
|
+
if (!existsSync(schemaPath))
|
|
120
|
+
return false;
|
|
121
|
+
const out = prismaClientOutput(cwd, schemaPath);
|
|
122
|
+
if (!out)
|
|
123
|
+
return false;
|
|
124
|
+
return !existsSync(out);
|
|
125
|
+
}
|
|
126
|
+
const ORM_LABEL = {
|
|
127
|
+
prisma: "Prisma",
|
|
128
|
+
drizzle: "Drizzle",
|
|
129
|
+
};
|
|
130
|
+
/**
|
|
131
|
+
* Confirm-first database provisioning. When the project uses an ORM on SQLite
|
|
132
|
+
* but creek.toml hasn't decided on a database resource, prompt (or auto-accept
|
|
133
|
+
* under --yes) to add `database = true`. Never overrides an explicit opt-out,
|
|
134
|
+
* never prompts in non-interactive contexts (warns and continues — the deploy
|
|
135
|
+
* still succeeds and DB routes return a self-documenting hint at runtime).
|
|
136
|
+
*/
|
|
137
|
+
export async function runDatabasePreflight(opts, io) {
|
|
138
|
+
const orm = detectSqliteOrm(opts.deps);
|
|
139
|
+
if (!orm)
|
|
140
|
+
return { wroteToml: false };
|
|
141
|
+
const state = databaseDirectiveState(io.readToml());
|
|
142
|
+
if (state !== "absent")
|
|
143
|
+
return { wroteToml: false }; // already enabled or opted out
|
|
144
|
+
if (!opts.tty && !opts.autoYes) {
|
|
145
|
+
io.warn(`Detected ${ORM_LABEL[orm]} on better-sqlite3 but creek.toml has no [resources] database. ` +
|
|
146
|
+
"Database routes will fail until you add `database = true` (run deploy in a terminal, or pass --yes).");
|
|
147
|
+
return { wroteToml: false };
|
|
148
|
+
}
|
|
149
|
+
const accepted = opts.autoYes
|
|
150
|
+
? true
|
|
151
|
+
: await io.confirm(`Detected ${ORM_LABEL[orm]} on better-sqlite3. On Creek this runs on a Cloudflare D1 ` +
|
|
152
|
+
"database in the cloud — a separate instance from your local file (local data is not " +
|
|
153
|
+
"copied). Add `database = true` under [resources] to creek.toml?");
|
|
154
|
+
if (!accepted) {
|
|
155
|
+
io.log("Skipped. Database routes will return a setup hint until you add `database = true` to creek.toml.");
|
|
156
|
+
return { wroteToml: false };
|
|
157
|
+
}
|
|
158
|
+
io.writeToml(enableDatabaseResource(io.readToml(), opts.projectName));
|
|
159
|
+
io.log("Enabled [resources] database in creek.toml (cloud D1 — separate from your local file).");
|
|
160
|
+
return { wroteToml: true };
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* What to do about a detected migration directory after the database exists.
|
|
164
|
+
* Migrations can be destructive, so this is never silent:
|
|
165
|
+
* - "run" → explicit opt-in (`--migrate`)
|
|
166
|
+
* - "prompt" → interactive (ask, default no)
|
|
167
|
+
* - "suggest" → non-interactive (print the command, don't run)
|
|
168
|
+
* - "none" → no migrations to apply
|
|
169
|
+
*/
|
|
170
|
+
export function migrationOfferPlan(opts) {
|
|
171
|
+
if (!opts.migrationDir)
|
|
172
|
+
return "none";
|
|
173
|
+
if (opts.autoMigrate)
|
|
174
|
+
return "run";
|
|
175
|
+
return opts.tty ? "prompt" : "suggest";
|
|
176
|
+
}
|
|
177
|
+
/** Merged dependencies + devDependencies from the project's package.json. */
|
|
178
|
+
export function readProjectDeps(cwd) {
|
|
179
|
+
try {
|
|
180
|
+
const pkg = JSON.parse(readFileSync(join(cwd, "package.json"), "utf-8"));
|
|
181
|
+
return { ...(pkg.dependencies ?? {}), ...(pkg.devDependencies ?? {}) };
|
|
182
|
+
}
|
|
183
|
+
catch {
|
|
184
|
+
return {};
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
/** Real (consola + filesystem) PreflightIO for the deploy command. */
|
|
188
|
+
export function makePreflightIO(cwd) {
|
|
189
|
+
const tomlPath = join(cwd, "creek.toml");
|
|
190
|
+
return {
|
|
191
|
+
readToml: () => (existsSync(tomlPath) ? readFileSync(tomlPath, "utf-8") : null),
|
|
192
|
+
writeToml: (content) => writeFileSync(tomlPath, content),
|
|
193
|
+
// DB provisioning is low-risk → default to yes.
|
|
194
|
+
confirm: async (message) => (await consola.prompt(message, { type: "confirm", initial: true })),
|
|
195
|
+
log: (message) => consola.success(` ${message}`),
|
|
196
|
+
warn: (message) => consola.warn(` ${message}`),
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
//# sourceMappingURL=db-preflight.js.map
|
package/dist/utils/nextjs.js
CHANGED
|
@@ -15,6 +15,7 @@ import { join, dirname, resolve } from "node:path";
|
|
|
15
15
|
import { createRequire } from "node:module";
|
|
16
16
|
import { execSync, execFileSync } from "node:child_process";
|
|
17
17
|
import consola from "consola";
|
|
18
|
+
import { prismaNeedsGenerate } from "./db-preflight.js";
|
|
18
19
|
// ---------------------------------------------------------------------------
|
|
19
20
|
// Version detection + unified entry point
|
|
20
21
|
// ---------------------------------------------------------------------------
|
|
@@ -128,6 +129,7 @@ export function buildNextjs(cwd, isMonorepo, projectName) {
|
|
|
128
129
|
if (version && semverGte(version, "16.2.3")) {
|
|
129
130
|
const adapterPath = ensureAdapter(cwd);
|
|
130
131
|
if (adapterPath) {
|
|
132
|
+
ensurePrismaClient(cwd);
|
|
131
133
|
ensurePrismaD1(cwd);
|
|
132
134
|
buildWithAdapter(cwd, adapterPath);
|
|
133
135
|
return;
|
|
@@ -210,12 +212,17 @@ const ADAPTER_VERSION = "^0.2.2";
|
|
|
210
212
|
// adapter and imports @prisma/adapter-d1 (an optional peer it doesn't ship).
|
|
211
213
|
const PRISMA_BSQLITE_PKG = "@prisma/adapter-better-sqlite3";
|
|
212
214
|
const PRISMA_D1_PKG = "@prisma/adapter-d1";
|
|
213
|
-
//
|
|
214
|
-
//
|
|
215
|
-
//
|
|
216
|
-
//
|
|
217
|
-
//
|
|
218
|
-
|
|
215
|
+
// Minimum adapter the CLI will REUSE from a prior .creek install; older
|
|
216
|
+
// cached copies are force-reinstalled. Each bump tracks a deploy-critical
|
|
217
|
+
// adapter fix that a stale cache would silently miss:
|
|
218
|
+
// 0.2.2 — wrangler resolved via module resolution (not a nested .bin guess)
|
|
219
|
+
// 0.2.6 — better-sqlite3 stubbed (else the native module inlines → a ~200MB
|
|
220
|
+
// worker that only fails at upload with "Payload Too Large")
|
|
221
|
+
// 0.2.7 — zero-change Prisma-on-D1 swap
|
|
222
|
+
// 0.2.10 — oversized-bundle fail-fast
|
|
223
|
+
// Kept at the latest because the reinstall cost is trivial and a cached copy
|
|
224
|
+
// in the 0.2.2–0.2.5 window builds successfully but produces a broken worker.
|
|
225
|
+
const ADAPTER_MIN_VERSION = "0.2.10";
|
|
219
226
|
/**
|
|
220
227
|
* Merge a dependency into .creek/package.json without clobbering deps that
|
|
221
228
|
* a previous install (adapter or opennext) may have already written.
|
|
@@ -288,6 +295,29 @@ function ensureAdapter(cwd) {
|
|
|
288
295
|
consola.success(` ${ADAPTER_PKG} installed`);
|
|
289
296
|
return resolved;
|
|
290
297
|
}
|
|
298
|
+
/**
|
|
299
|
+
* Generate the Prisma client before the Next build when it's missing.
|
|
300
|
+
* Prisma 7's `prisma-client` generator emits to a configured `output` dir that
|
|
301
|
+
* the app imports; without it the build fails. Safe to run automatically —
|
|
302
|
+
* generation is idempotent and has no external/persistent effect. No-op unless
|
|
303
|
+
* a Prisma schema exists and its output dir is absent (see prismaNeedsGenerate).
|
|
304
|
+
*/
|
|
305
|
+
function ensurePrismaClient(cwd) {
|
|
306
|
+
if (!prismaNeedsGenerate(cwd))
|
|
307
|
+
return;
|
|
308
|
+
consola.start(" Generating Prisma client (prisma generate)...");
|
|
309
|
+
try {
|
|
310
|
+
// `--no-install` uses the project's own prisma (a dependency) rather than
|
|
311
|
+
// fetching one; the schema's datasource needs no URL to generate.
|
|
312
|
+
execSync("npx --no-install prisma generate", { cwd, stdio: "pipe" });
|
|
313
|
+
consola.success(" Prisma client generated");
|
|
314
|
+
}
|
|
315
|
+
catch (err) {
|
|
316
|
+
// Non-fatal: the build will surface a clearer "client not found" error if
|
|
317
|
+
// generation was genuinely required.
|
|
318
|
+
consola.warn(` prisma generate failed (${err instanceof Error ? err.message : String(err)}); continuing`);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
291
321
|
/**
|
|
292
322
|
* Ensure @prisma/adapter-d1 is resolvable at build time for the zero-change
|
|
293
323
|
* Prisma-on-D1 swap. adapter-creek aliases `@prisma/adapter-better-sqlite3` to
|