@prisma/compute-sdk 0.26.0 → 0.28.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/dist/artifact-stage.d.ts +24 -0
- package/dist/artifact-stage.d.ts.map +1 -0
- package/dist/artifact-stage.js +165 -0
- package/dist/artifact-stage.js.map +1 -0
- package/dist/astro-build.d.ts +2 -0
- package/dist/astro-build.d.ts.map +1 -1
- package/dist/astro-build.js +8 -0
- package/dist/astro-build.js.map +1 -1
- package/dist/auto-build.d.ts +7 -4
- package/dist/auto-build.d.ts.map +1 -1
- package/dist/auto-build.js +25 -33
- package/dist/auto-build.js.map +1 -1
- package/dist/build-settings.d.ts +55 -0
- package/dist/build-settings.d.ts.map +1 -0
- package/dist/build-settings.js +311 -0
- package/dist/build-settings.js.map +1 -0
- package/dist/build-strategy.d.ts +4 -0
- package/dist/build-strategy.d.ts.map +1 -1
- package/dist/build-strategy.js +13 -20
- package/dist/build-strategy.js.map +1 -1
- package/dist/build.d.ts +45 -0
- package/dist/build.d.ts.map +1 -0
- package/dist/build.js +89 -0
- package/dist/build.js.map +1 -0
- package/dist/bun-build.d.ts +8 -0
- package/dist/bun-build.d.ts.map +1 -1
- package/dist/bun-build.js +47 -23
- package/dist/bun-build.js.map +1 -1
- package/dist/config/frameworks.d.ts +2 -2
- package/dist/config/frameworks.d.ts.map +1 -1
- package/dist/config/frameworks.js +12 -0
- package/dist/config/frameworks.js.map +1 -1
- package/dist/config/types.d.ts +1 -1
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/types.js +1 -0
- package/dist/config/types.js.map +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/nestjs-build.d.ts +23 -0
- package/dist/nestjs-build.d.ts.map +1 -0
- package/dist/nestjs-build.js +317 -0
- package/dist/nestjs-build.js.map +1 -0
- package/dist/nextjs-build.d.ts +12 -2
- package/dist/nextjs-build.d.ts.map +1 -1
- package/dist/nextjs-build.js +156 -75
- package/dist/nextjs-build.js.map +1 -1
- package/dist/nuxt-build.d.ts +2 -0
- package/dist/nuxt-build.d.ts.map +1 -1
- package/dist/nuxt-build.js +8 -0
- package/dist/nuxt-build.js.map +1 -1
- package/dist/tanstack-start-build.d.ts +6 -1
- package/dist/tanstack-start-build.d.ts.map +1 -1
- package/dist/tanstack-start-build.js +35 -15
- package/dist/tanstack-start-build.js.map +1 -1
- package/dist/workspace.d.ts +90 -0
- package/dist/workspace.d.ts.map +1 -0
- package/dist/workspace.js +205 -0
- package/dist/workspace.js.map +1 -0
- package/package.json +5 -3
- package/src/artifact-stage.ts +280 -0
- package/src/astro-build.ts +11 -1
- package/src/auto-build.ts +28 -34
- package/src/build-settings.ts +448 -0
- package/src/build-strategy.ts +22 -29
- package/src/build.ts +127 -0
- package/src/bun-build.ts +60 -27
- package/src/config/frameworks.ts +13 -0
- package/src/config/types.ts +1 -0
- package/src/index.ts +29 -0
- package/src/nestjs-build.ts +425 -0
- package/src/nextjs-build.ts +206 -103
- package/src/nuxt-build.ts +11 -1
- package/src/tanstack-start-build.ts +44 -18
- package/src/workspace.ts +319 -0
package/src/workspace.ts
ADDED
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { readFile, stat } from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import type { Readable } from "node:stream";
|
|
5
|
+
|
|
6
|
+
import { sourceRootLineage } from "./config/source-root.ts";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Workspace-aware build primitives shared by the framework strategies. These
|
|
10
|
+
* are location-agnostic: they take an explicit app directory and walk up to
|
|
11
|
+
* the source root (the repository or workspace boundary), so a build invoked
|
|
12
|
+
* from inside a monorepo package resolves the same package manager and
|
|
13
|
+
* binaries it would at the workspace root. Nothing here reads `process.cwd()`
|
|
14
|
+
* or prompts.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
export type PackageManager = "bun" | "pnpm" | "yarn" | "npm";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Build-environment hooks a consumer threads into a strategy: extra `env` for
|
|
21
|
+
* the build child and a per-line output tap. Both are optional, so the CLI
|
|
22
|
+
* keeps today's behavior while a headless consumer (the build-runner) injects
|
|
23
|
+
* deploy vars and streams a live build log.
|
|
24
|
+
*/
|
|
25
|
+
export interface BuildCommandIo {
|
|
26
|
+
env?: NodeJS.ProcessEnv;
|
|
27
|
+
onOutput?: (line: string, source: "stdout" | "stderr") => void;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Detects the package manager governing `appPath` by walking from the app up
|
|
32
|
+
* to the source root: the nearest `packageManager` field wins, then the
|
|
33
|
+
* nearest lockfile. Workspace repos keep both at the root, so a package
|
|
34
|
+
* deep in a monorepo still resolves correctly. Returns undefined when no
|
|
35
|
+
* signal is found.
|
|
36
|
+
*/
|
|
37
|
+
export async function resolvePackageManager(
|
|
38
|
+
appPath: string,
|
|
39
|
+
signal?: AbortSignal,
|
|
40
|
+
): Promise<PackageManager | undefined> {
|
|
41
|
+
for (const directory of await sourceRootLineage(appPath, signal)) {
|
|
42
|
+
const manifest = await readPackageManifest(directory, signal);
|
|
43
|
+
const fromField = packageManagerFromField(manifest?.packageManager);
|
|
44
|
+
if (fromField) {
|
|
45
|
+
return fromField;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (
|
|
49
|
+
(await pathExists(path.join(directory, "bun.lock"), signal)) ||
|
|
50
|
+
(await pathExists(path.join(directory, "bun.lockb"), signal))
|
|
51
|
+
) {
|
|
52
|
+
return "bun";
|
|
53
|
+
}
|
|
54
|
+
if (await pathExists(path.join(directory, "pnpm-lock.yaml"), signal)) {
|
|
55
|
+
return "pnpm";
|
|
56
|
+
}
|
|
57
|
+
if (await pathExists(path.join(directory, "yarn.lock"), signal)) {
|
|
58
|
+
return "yarn";
|
|
59
|
+
}
|
|
60
|
+
if (await pathExists(path.join(directory, "package-lock.json"), signal)) {
|
|
61
|
+
return "npm";
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Build environment for `appPath`: every `node_modules/.bin` between the app
|
|
70
|
+
* and its source root, prepended to PATH. Workspace repos hoist binaries like
|
|
71
|
+
* `next` to the workspace root, so a build run from a package directory still
|
|
72
|
+
* finds them. The returned object is suitable as the `env` for a child build
|
|
73
|
+
* process.
|
|
74
|
+
*/
|
|
75
|
+
export async function buildCommandEnv(
|
|
76
|
+
appPath: string,
|
|
77
|
+
baseEnv: NodeJS.ProcessEnv,
|
|
78
|
+
signal?: AbortSignal,
|
|
79
|
+
): Promise<NodeJS.ProcessEnv> {
|
|
80
|
+
const binDirs = (await sourceRootLineage(appPath, signal)).map((directory) =>
|
|
81
|
+
path.join(directory, "node_modules", ".bin"),
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
return {
|
|
85
|
+
...baseEnv,
|
|
86
|
+
PATH: [...binDirs, baseEnv.PATH].filter(Boolean).join(path.delimiter),
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Runs a build command string inside `appPath`, with every ancestor
|
|
92
|
+
* `node_modules/.bin` on PATH so workspace-hoisted binaries resolve. Rejects
|
|
93
|
+
* with the framework prefix and captured output on a non-zero exit.
|
|
94
|
+
*/
|
|
95
|
+
export async function runBuildCommand(options: {
|
|
96
|
+
appPath: string;
|
|
97
|
+
command: string;
|
|
98
|
+
failurePrefix: string;
|
|
99
|
+
/**
|
|
100
|
+
* Extra environment merged over `process.env` for the build child (after
|
|
101
|
+
* the ancestor-bin PATH). A headless consumer (e.g. the build-runner) uses
|
|
102
|
+
* this to inject per-branch deploy vars and build flags; the CLI passes none.
|
|
103
|
+
*/
|
|
104
|
+
env?: NodeJS.ProcessEnv;
|
|
105
|
+
/**
|
|
106
|
+
* Per-line tap for build output, called as each line arrives on stdout or
|
|
107
|
+
* stderr. Lets a consumer stream a live build log instead of waiting for the
|
|
108
|
+
* process to exit; the CLI passes none.
|
|
109
|
+
*/
|
|
110
|
+
onOutput?: (line: string, source: "stdout" | "stderr") => void;
|
|
111
|
+
signal?: AbortSignal;
|
|
112
|
+
}): Promise<void> {
|
|
113
|
+
const env = await buildCommandEnv(
|
|
114
|
+
options.appPath,
|
|
115
|
+
{ ...process.env, ...options.env },
|
|
116
|
+
options.signal,
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
// `shell: true` preserves the platform shell so a command string like
|
|
120
|
+
// `pnpm run build` works the same as the CLI's previous `exec`.
|
|
121
|
+
await runChildProcess({
|
|
122
|
+
command: options.command,
|
|
123
|
+
args: [],
|
|
124
|
+
cwd: options.appPath,
|
|
125
|
+
env,
|
|
126
|
+
shell: true,
|
|
127
|
+
failurePrefix: options.failurePrefix,
|
|
128
|
+
onOutput: options.onOutput,
|
|
129
|
+
signal: options.signal,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Spawns a child build process, streaming each output line to `onOutput` and
|
|
135
|
+
* keeping a bounded tail for the failure message instead of buffering the whole
|
|
136
|
+
* build. Resolves on a zero exit; rejects on a non-zero exit (with the prefix,
|
|
137
|
+
* exit code, and tail) or a spawn error (whose `code`, e.g. ENOENT, is
|
|
138
|
+
* preserved on the rejection so a launcher ladder can branch on it).
|
|
139
|
+
*
|
|
140
|
+
* Shared by `runBuildCommand` (a shell command string) and `runPackageCli`
|
|
141
|
+
* (an explicit binary + args).
|
|
142
|
+
*/
|
|
143
|
+
export function runChildProcess(options: {
|
|
144
|
+
command: string;
|
|
145
|
+
args: readonly string[];
|
|
146
|
+
cwd: string;
|
|
147
|
+
env: NodeJS.ProcessEnv;
|
|
148
|
+
shell?: boolean;
|
|
149
|
+
failurePrefix: string;
|
|
150
|
+
onOutput?: (line: string, source: "stdout" | "stderr") => void;
|
|
151
|
+
signal?: AbortSignal;
|
|
152
|
+
}): Promise<void> {
|
|
153
|
+
return new Promise((resolve, reject) => {
|
|
154
|
+
const tail = createBoundedTail();
|
|
155
|
+
const child = spawn(options.command, [...options.args], {
|
|
156
|
+
cwd: options.cwd,
|
|
157
|
+
env: options.env,
|
|
158
|
+
signal: options.signal,
|
|
159
|
+
shell: options.shell ?? false,
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
const streamed = Promise.all([
|
|
163
|
+
streamLines(child.stdout, "stdout", tail, options.onOutput),
|
|
164
|
+
streamLines(child.stderr, "stderr", tail, options.onOutput),
|
|
165
|
+
]);
|
|
166
|
+
|
|
167
|
+
child.on("error", (error) => {
|
|
168
|
+
// Preserve `code` (e.g. ENOENT) so a launcher ladder can fall through.
|
|
169
|
+
reject(
|
|
170
|
+
Object.assign(
|
|
171
|
+
new Error(`${options.failurePrefix} build failed:\n${error.message}`),
|
|
172
|
+
{ code: (error as NodeJS.ErrnoException).code },
|
|
173
|
+
),
|
|
174
|
+
);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
child.on("close", (code) => {
|
|
178
|
+
streamed.then(() => {
|
|
179
|
+
if (code === 0) {
|
|
180
|
+
resolve();
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
const detail = tail.text().trim();
|
|
184
|
+
const exit = code != null ? ` (exit code ${code})` : "";
|
|
185
|
+
reject(
|
|
186
|
+
new Error(
|
|
187
|
+
`${options.failurePrefix} build failed${exit}${detail ? `:\n${detail}` : "."}`,
|
|
188
|
+
),
|
|
189
|
+
);
|
|
190
|
+
}, reject);
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/** Splits a child stream into lines, taps each, and records it in the tail. */
|
|
196
|
+
function streamLines(
|
|
197
|
+
stream: Readable | null,
|
|
198
|
+
source: "stdout" | "stderr",
|
|
199
|
+
tail: BoundedTail,
|
|
200
|
+
onOutput?: (line: string, source: "stdout" | "stderr") => void,
|
|
201
|
+
): Promise<void> {
|
|
202
|
+
return new Promise((resolve) => {
|
|
203
|
+
if (!stream) {
|
|
204
|
+
resolve();
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
stream.setEncoding("utf8");
|
|
208
|
+
let buffer = "";
|
|
209
|
+
const emit = (line: string): void => {
|
|
210
|
+
tail.push(line);
|
|
211
|
+
onOutput?.(line, source);
|
|
212
|
+
};
|
|
213
|
+
stream.on("data", (chunk: string) => {
|
|
214
|
+
buffer += chunk;
|
|
215
|
+
let newline = buffer.indexOf("\n");
|
|
216
|
+
while (newline !== -1) {
|
|
217
|
+
emit(buffer.slice(0, newline));
|
|
218
|
+
buffer = buffer.slice(newline + 1);
|
|
219
|
+
newline = buffer.indexOf("\n");
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
stream.on("end", () => {
|
|
223
|
+
if (buffer.length > 0) {
|
|
224
|
+
emit(buffer);
|
|
225
|
+
}
|
|
226
|
+
resolve();
|
|
227
|
+
});
|
|
228
|
+
// A stream error surfaces through the child's own error/close handlers.
|
|
229
|
+
stream.on("error", () => resolve());
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
interface BoundedTail {
|
|
234
|
+
push(line: string): void;
|
|
235
|
+
text(): string;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/** A ring of the most recent output lines, for the failure message. */
|
|
239
|
+
function createBoundedTail(maxLines = 200): BoundedTail {
|
|
240
|
+
const lines: string[] = [];
|
|
241
|
+
return {
|
|
242
|
+
push(line: string): void {
|
|
243
|
+
lines.push(line);
|
|
244
|
+
if (lines.length > maxLines) {
|
|
245
|
+
lines.shift();
|
|
246
|
+
}
|
|
247
|
+
},
|
|
248
|
+
text(): string {
|
|
249
|
+
return lines.join("\n");
|
|
250
|
+
},
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/** A `package.json`'s build-relevant fields. */
|
|
255
|
+
export interface PackageManifest {
|
|
256
|
+
packageManager?: unknown;
|
|
257
|
+
scripts?: Record<string, unknown>;
|
|
258
|
+
main?: unknown;
|
|
259
|
+
module?: unknown;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/** Reads and parses `appPath/package.json`, returning null on any failure. */
|
|
263
|
+
export async function readPackageManifest(
|
|
264
|
+
appPath: string,
|
|
265
|
+
signal?: AbortSignal,
|
|
266
|
+
): Promise<PackageManifest | null> {
|
|
267
|
+
signal?.throwIfAborted();
|
|
268
|
+
try {
|
|
269
|
+
const content = await readFile(path.join(appPath, "package.json"), {
|
|
270
|
+
encoding: "utf-8",
|
|
271
|
+
signal,
|
|
272
|
+
});
|
|
273
|
+
const parsed = JSON.parse(content) as unknown;
|
|
274
|
+
return isRecord(parsed) ? (parsed as PackageManifest) : null;
|
|
275
|
+
} catch (error) {
|
|
276
|
+
// A missing file or invalid JSON is expected; an abort must propagate.
|
|
277
|
+
if (signal?.aborted) throw error;
|
|
278
|
+
return null;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/** The trimmed `scripts.build` string, or null when absent or empty. */
|
|
283
|
+
export function readBuildScript(
|
|
284
|
+
manifest: PackageManifest | null,
|
|
285
|
+
): string | null {
|
|
286
|
+
const build = manifest?.scripts?.build;
|
|
287
|
+
if (typeof build !== "string") {
|
|
288
|
+
return null;
|
|
289
|
+
}
|
|
290
|
+
const trimmed = build.trim();
|
|
291
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
function packageManagerFromField(value: unknown): PackageManager | null {
|
|
295
|
+
if (typeof value !== "string") {
|
|
296
|
+
return null;
|
|
297
|
+
}
|
|
298
|
+
const name = value.split("@")[0];
|
|
299
|
+
return name === "bun" || name === "pnpm" || name === "yarn" || name === "npm"
|
|
300
|
+
? name
|
|
301
|
+
: null;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
async function pathExists(
|
|
305
|
+
targetPath: string,
|
|
306
|
+
signal?: AbortSignal,
|
|
307
|
+
): Promise<boolean> {
|
|
308
|
+
signal?.throwIfAborted();
|
|
309
|
+
try {
|
|
310
|
+
await stat(targetPath);
|
|
311
|
+
return true;
|
|
312
|
+
} catch {
|
|
313
|
+
return false;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
318
|
+
return typeof value === "object" && value !== null;
|
|
319
|
+
}
|