@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.
Files changed (76) hide show
  1. package/dist/artifact-stage.d.ts +24 -0
  2. package/dist/artifact-stage.d.ts.map +1 -0
  3. package/dist/artifact-stage.js +165 -0
  4. package/dist/artifact-stage.js.map +1 -0
  5. package/dist/astro-build.d.ts +2 -0
  6. package/dist/astro-build.d.ts.map +1 -1
  7. package/dist/astro-build.js +8 -0
  8. package/dist/astro-build.js.map +1 -1
  9. package/dist/auto-build.d.ts +7 -4
  10. package/dist/auto-build.d.ts.map +1 -1
  11. package/dist/auto-build.js +25 -33
  12. package/dist/auto-build.js.map +1 -1
  13. package/dist/build-settings.d.ts +55 -0
  14. package/dist/build-settings.d.ts.map +1 -0
  15. package/dist/build-settings.js +311 -0
  16. package/dist/build-settings.js.map +1 -0
  17. package/dist/build-strategy.d.ts +4 -0
  18. package/dist/build-strategy.d.ts.map +1 -1
  19. package/dist/build-strategy.js +13 -20
  20. package/dist/build-strategy.js.map +1 -1
  21. package/dist/build.d.ts +45 -0
  22. package/dist/build.d.ts.map +1 -0
  23. package/dist/build.js +89 -0
  24. package/dist/build.js.map +1 -0
  25. package/dist/bun-build.d.ts +8 -0
  26. package/dist/bun-build.d.ts.map +1 -1
  27. package/dist/bun-build.js +47 -23
  28. package/dist/bun-build.js.map +1 -1
  29. package/dist/config/frameworks.d.ts +2 -2
  30. package/dist/config/frameworks.d.ts.map +1 -1
  31. package/dist/config/frameworks.js +12 -0
  32. package/dist/config/frameworks.js.map +1 -1
  33. package/dist/config/types.d.ts +1 -1
  34. package/dist/config/types.d.ts.map +1 -1
  35. package/dist/config/types.js +1 -0
  36. package/dist/config/types.js.map +1 -1
  37. package/dist/index.d.ts +5 -0
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.js +5 -0
  40. package/dist/index.js.map +1 -1
  41. package/dist/nestjs-build.d.ts +23 -0
  42. package/dist/nestjs-build.d.ts.map +1 -0
  43. package/dist/nestjs-build.js +317 -0
  44. package/dist/nestjs-build.js.map +1 -0
  45. package/dist/nextjs-build.d.ts +12 -2
  46. package/dist/nextjs-build.d.ts.map +1 -1
  47. package/dist/nextjs-build.js +156 -75
  48. package/dist/nextjs-build.js.map +1 -1
  49. package/dist/nuxt-build.d.ts +2 -0
  50. package/dist/nuxt-build.d.ts.map +1 -1
  51. package/dist/nuxt-build.js +8 -0
  52. package/dist/nuxt-build.js.map +1 -1
  53. package/dist/tanstack-start-build.d.ts +6 -1
  54. package/dist/tanstack-start-build.d.ts.map +1 -1
  55. package/dist/tanstack-start-build.js +35 -15
  56. package/dist/tanstack-start-build.js.map +1 -1
  57. package/dist/workspace.d.ts +90 -0
  58. package/dist/workspace.d.ts.map +1 -0
  59. package/dist/workspace.js +205 -0
  60. package/dist/workspace.js.map +1 -0
  61. package/package.json +5 -3
  62. package/src/artifact-stage.ts +280 -0
  63. package/src/astro-build.ts +11 -1
  64. package/src/auto-build.ts +28 -34
  65. package/src/build-settings.ts +448 -0
  66. package/src/build-strategy.ts +22 -29
  67. package/src/build.ts +127 -0
  68. package/src/bun-build.ts +60 -27
  69. package/src/config/frameworks.ts +13 -0
  70. package/src/config/types.ts +1 -0
  71. package/src/index.ts +29 -0
  72. package/src/nestjs-build.ts +425 -0
  73. package/src/nextjs-build.ts +206 -103
  74. package/src/nuxt-build.ts +11 -1
  75. package/src/tanstack-start-build.ts +44 -18
  76. package/src/workspace.ts +319 -0
@@ -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
+ }