@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
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
import { chmod, copyFile, lstat, mkdir, mkdtemp, readFile, readlink, rm, stat, symlink, } from "node:fs/promises";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { nodeFileTrace } from "@vercel/nft";
|
|
5
|
+
import { joinPosix, resolveBuildSettings, } from "./build-settings.js";
|
|
6
|
+
import { hasPackageDependency, hasRootFile, runPackageCli, } from "./build-strategy.js";
|
|
7
|
+
import { defaultHttpPortForBuildType } from "./config/frameworks.js";
|
|
8
|
+
import { resolveSourceRoot } from "./config/source-root.js";
|
|
9
|
+
import { readPackageManifest, runBuildCommand, } from "./workspace.js";
|
|
10
|
+
const NEST_CLI_FILENAME = "nest-cli.json";
|
|
11
|
+
/** Compiled entrypoints probed, in order, when config does not resolve one. */
|
|
12
|
+
const DEFAULT_COMPILED_ENTRYPOINTS = ["dist/src/main.js", "dist/main.js"];
|
|
13
|
+
/**
|
|
14
|
+
* Build strategy for NestJS applications. Runs the user's build (so `nest build`
|
|
15
|
+
* and any `prisma generate` in the `build` script run), resolves the compiled
|
|
16
|
+
* entrypoint, then stages a lean artifact by file-tracing that entrypoint with
|
|
17
|
+
* `@vercel/nft`: it ships only the compiled output and the `node_modules` files
|
|
18
|
+
* actually reachable, not the full dependency tree. NestJS has no Next-style
|
|
19
|
+
* standalone output, so the trace is the lean equivalent that keeps the
|
|
20
|
+
* artifact under the compute runtime's disk ceiling.
|
|
21
|
+
*/
|
|
22
|
+
export class NestjsBuild {
|
|
23
|
+
#appPath;
|
|
24
|
+
#buildSettings;
|
|
25
|
+
#io;
|
|
26
|
+
constructor(options) {
|
|
27
|
+
this.#appPath = options.appPath;
|
|
28
|
+
this.#buildSettings = options.buildSettings;
|
|
29
|
+
this.#io = options.io;
|
|
30
|
+
}
|
|
31
|
+
async canBuild(signal) {
|
|
32
|
+
return ((await hasRootFile(this.#appPath, [NEST_CLI_FILENAME], signal)) ||
|
|
33
|
+
(await hasPackageDependency(this.#appPath, ["@nestjs/core"], signal)));
|
|
34
|
+
}
|
|
35
|
+
async execute(signal) {
|
|
36
|
+
signal?.throwIfAborted();
|
|
37
|
+
const settings = this.#buildSettings ??
|
|
38
|
+
(await resolveBuildSettings({
|
|
39
|
+
appPath: this.#appPath,
|
|
40
|
+
buildType: "nestjs",
|
|
41
|
+
signal,
|
|
42
|
+
}));
|
|
43
|
+
// `resolveBuildSettings` always returns a non-null `nest build` fallback, so
|
|
44
|
+
// route by source: a user `build` script runs as-is, the framework default
|
|
45
|
+
// goes through the launcher ladder (local bin -> npx -> bunx).
|
|
46
|
+
const usingFrameworkDefault = settings.buildCommand === null ||
|
|
47
|
+
settings.buildCommandSource === "NestJS default";
|
|
48
|
+
if (!usingFrameworkDefault && settings.buildCommand) {
|
|
49
|
+
await runBuildCommand({
|
|
50
|
+
appPath: this.#appPath,
|
|
51
|
+
command: settings.buildCommand,
|
|
52
|
+
failurePrefix: "NestJS",
|
|
53
|
+
env: this.#io?.env,
|
|
54
|
+
onOutput: this.#io?.onOutput,
|
|
55
|
+
signal,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
await runPackageCli({
|
|
60
|
+
appPath: this.#appPath,
|
|
61
|
+
cliName: "nest",
|
|
62
|
+
args: ["build"],
|
|
63
|
+
failurePrefix: "NestJS",
|
|
64
|
+
missingMessage: "Could not find the Nest CLI. Add a `build` script to package.json, install @nestjs/cli, or ensure npx/bunx is available.",
|
|
65
|
+
env: this.#io?.env,
|
|
66
|
+
onOutput: this.#io?.onOutput,
|
|
67
|
+
signal,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
signal?.throwIfAborted();
|
|
71
|
+
const compiledEntry = await this.#resolveCompiledEntrypoint(signal);
|
|
72
|
+
const outDir = await mkdtemp(path.join(os.tmpdir(), "compute-build-"));
|
|
73
|
+
try {
|
|
74
|
+
const artifactDir = path.join(outDir, "app");
|
|
75
|
+
const entrypoint = await stageTracedArtifact({
|
|
76
|
+
appPath: this.#appPath,
|
|
77
|
+
artifactDir,
|
|
78
|
+
compiledEntry,
|
|
79
|
+
signal,
|
|
80
|
+
});
|
|
81
|
+
return {
|
|
82
|
+
directory: artifactDir,
|
|
83
|
+
entrypoint,
|
|
84
|
+
defaultPortMapping: { http: defaultHttpPortForBuildType("nestjs") },
|
|
85
|
+
cleanup: () => rm(outDir, { recursive: true, force: true }),
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
await rm(outDir, { recursive: true, force: true });
|
|
90
|
+
throw error;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Resolves the compiled entrypoint relative to the app root, using posix
|
|
95
|
+
* separators. Prefers `package.json` `main`, then the path computed from
|
|
96
|
+
* `nest-cli.json` and the tsconfig `outDir`, then the common defaults.
|
|
97
|
+
*/
|
|
98
|
+
async #resolveCompiledEntrypoint(signal) {
|
|
99
|
+
const candidates = [];
|
|
100
|
+
const fromMain = await this.#mainFieldEntrypoint(signal);
|
|
101
|
+
if (fromMain) {
|
|
102
|
+
candidates.push(fromMain);
|
|
103
|
+
}
|
|
104
|
+
const fromConfig = await this.#configuredCompiledEntrypoint(signal);
|
|
105
|
+
if (fromConfig) {
|
|
106
|
+
candidates.push(fromConfig);
|
|
107
|
+
}
|
|
108
|
+
candidates.push(...DEFAULT_COMPILED_ENTRYPOINTS);
|
|
109
|
+
for (const candidate of candidates) {
|
|
110
|
+
signal?.throwIfAborted();
|
|
111
|
+
const normalized = normalizeRelative(candidate);
|
|
112
|
+
if (!normalized) {
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
if (await isFile(path.join(this.#appPath, normalized))) {
|
|
116
|
+
return normalized;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
throw new Error(`NestJS build did not produce a compiled entrypoint. Looked for ${candidates.join(", ")} under ${this.#appPath}. ` +
|
|
120
|
+
"Ensure `nest build` ran and check the `main` field, nest-cli.json, or tsconfig outDir.");
|
|
121
|
+
}
|
|
122
|
+
async #mainFieldEntrypoint(signal) {
|
|
123
|
+
const manifest = await readPackageManifest(this.#appPath, signal);
|
|
124
|
+
return typeof manifest?.main === "string" && manifest.main.trim().length > 0
|
|
125
|
+
? manifest.main.trim()
|
|
126
|
+
: null;
|
|
127
|
+
}
|
|
128
|
+
async #configuredCompiledEntrypoint(signal) {
|
|
129
|
+
const nestCli = await readNestCliConfig(this.#appPath, signal);
|
|
130
|
+
const sourceRoot = nestCli.sourceRoot ?? "src";
|
|
131
|
+
const entryFile = nestCli.entryFile ?? "main";
|
|
132
|
+
const outDir = await readTsconfigOutDir(this.#appPath, signal);
|
|
133
|
+
const relativeEntry = path.posix.join(path.posix.relative(".", sourceRoot) || ".", `${entryFile}.js`);
|
|
134
|
+
return joinPosix(outDir, relativeEntry);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
async function readNestCliConfig(appPath, signal) {
|
|
138
|
+
signal?.throwIfAborted();
|
|
139
|
+
let content;
|
|
140
|
+
try {
|
|
141
|
+
content = await readFile(path.join(appPath, NEST_CLI_FILENAME), {
|
|
142
|
+
encoding: "utf-8",
|
|
143
|
+
signal,
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
if (signal?.aborted)
|
|
148
|
+
throw error;
|
|
149
|
+
return {};
|
|
150
|
+
}
|
|
151
|
+
try {
|
|
152
|
+
const parsed = JSON.parse(content);
|
|
153
|
+
return {
|
|
154
|
+
sourceRoot: typeof parsed.sourceRoot === "string" ? parsed.sourceRoot : undefined,
|
|
155
|
+
entryFile: typeof parsed.entryFile === "string" ? parsed.entryFile : undefined,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
catch {
|
|
159
|
+
return {};
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
const TSCONFIG_FILENAMES = ["tsconfig.build.json", "tsconfig.json"];
|
|
163
|
+
/** Best-effort read of `compilerOptions.outDir`, defaulting to `dist`. */
|
|
164
|
+
async function readTsconfigOutDir(appPath, signal) {
|
|
165
|
+
for (const fileName of TSCONFIG_FILENAMES) {
|
|
166
|
+
signal?.throwIfAborted();
|
|
167
|
+
let content;
|
|
168
|
+
try {
|
|
169
|
+
content = await readFile(path.join(appPath, fileName), {
|
|
170
|
+
encoding: "utf-8",
|
|
171
|
+
signal,
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
catch (error) {
|
|
175
|
+
if (signal?.aborted)
|
|
176
|
+
throw error;
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
const outDir = parseTsconfigOutDir(content);
|
|
180
|
+
if (outDir) {
|
|
181
|
+
return outDir;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return "dist";
|
|
185
|
+
}
|
|
186
|
+
/** Reads `compilerOptions.outDir` from a tsconfig source, tolerating comments. */
|
|
187
|
+
function parseTsconfigOutDir(content) {
|
|
188
|
+
try {
|
|
189
|
+
const parsed = JSON.parse(stripJsonComments(content));
|
|
190
|
+
const outDir = parsed.compilerOptions?.outDir;
|
|
191
|
+
if (typeof outDir !== "string") {
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
return normalizeRelative(outDir);
|
|
195
|
+
}
|
|
196
|
+
catch {
|
|
197
|
+
return null;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Stages the compiled entrypoint and its transitive dependencies into
|
|
202
|
+
* `artifactDir` by tracing with `@vercel/nft`, then copying only the traced
|
|
203
|
+
* paths. Returns the artifact-root-relative entrypoint to run with `node`.
|
|
204
|
+
*
|
|
205
|
+
* The trace base is the source root, not the app dir, because nft ignores
|
|
206
|
+
* everything above `base`: in a workspace, deps hoisted to the repo root sit
|
|
207
|
+
* above the app and would be dropped, leaving the artifact with no usable
|
|
208
|
+
* `node_modules`. Tracing from the source root keeps the workspace-relative
|
|
209
|
+
* layout (e.g. `apps/api/dist/main.js` plus root and app-local `node_modules`),
|
|
210
|
+
* so `node <dir>/<entrypoint>` resolves deps by walking up. For a single-app
|
|
211
|
+
* repo the source root equals the app dir, so the entrypoint stays `dist/main.js`.
|
|
212
|
+
*
|
|
213
|
+
* The trace lists both the visible `node_modules/<pkg>` symlinks and the real
|
|
214
|
+
* files they resolve to (e.g. pnpm `.pnpm/<pkg>` / bun `.bun/<pkg>` stores), so
|
|
215
|
+
* symlinks are recreated verbatim and the store files are copied alongside.
|
|
216
|
+
*/
|
|
217
|
+
async function stageTracedArtifact(options) {
|
|
218
|
+
const appPath = path.resolve(options.appPath);
|
|
219
|
+
const sourceRoot = await resolveSourceRoot(appPath, options.signal);
|
|
220
|
+
const entry = path.join(appPath, options.compiledEntry);
|
|
221
|
+
const entrypoint = path.posix.normalize(path.relative(sourceRoot, entry).split(path.sep).join("/"));
|
|
222
|
+
options.signal?.throwIfAborted();
|
|
223
|
+
const { fileList } = await nodeFileTrace([entry], { base: sourceRoot });
|
|
224
|
+
await mkdir(options.artifactDir, { recursive: true });
|
|
225
|
+
for (const relativePath of fileList) {
|
|
226
|
+
options.signal?.throwIfAborted();
|
|
227
|
+
await stageTracedPath(path.join(sourceRoot, relativePath), path.join(options.artifactDir, relativePath));
|
|
228
|
+
}
|
|
229
|
+
return entrypoint;
|
|
230
|
+
}
|
|
231
|
+
/** Copies one traced path, preserving symlinks and file mode. */
|
|
232
|
+
async function stageTracedPath(sourcePath, destinationPath) {
|
|
233
|
+
const info = await lstat(sourcePath).catch(() => null);
|
|
234
|
+
if (!info) {
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
await mkdir(path.dirname(destinationPath), { recursive: true });
|
|
238
|
+
if (info.isSymbolicLink()) {
|
|
239
|
+
await symlink(await readlink(sourcePath), destinationPath);
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
if (info.isFile()) {
|
|
243
|
+
await copyFile(sourcePath, destinationPath);
|
|
244
|
+
await chmod(destinationPath, info.mode);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
function normalizeRelative(value) {
|
|
248
|
+
const raw = value.trim().replace(/\\/g, "/");
|
|
249
|
+
if (raw.length === 0) {
|
|
250
|
+
return null;
|
|
251
|
+
}
|
|
252
|
+
const normalized = path.posix.normalize(raw);
|
|
253
|
+
if (path.posix.isAbsolute(normalized) ||
|
|
254
|
+
normalized === ".." ||
|
|
255
|
+
normalized.startsWith("../")) {
|
|
256
|
+
return null;
|
|
257
|
+
}
|
|
258
|
+
return normalized === "." ? null : normalized;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Removes `//` line comments and block comments from JSONC, tracking
|
|
262
|
+
* string state so a `//` inside a string value (e.g. `"https://..."`) is
|
|
263
|
+
* preserved. A naive regex strips such content and mis-reads the surrounding
|
|
264
|
+
* keys; on any malformed input the caller falls back to the default outDir.
|
|
265
|
+
*/
|
|
266
|
+
function stripJsonComments(content) {
|
|
267
|
+
let result = "";
|
|
268
|
+
let inString = false;
|
|
269
|
+
let escaped = false;
|
|
270
|
+
for (let i = 0; i < content.length; i++) {
|
|
271
|
+
const char = content[i];
|
|
272
|
+
if (inString) {
|
|
273
|
+
result += char;
|
|
274
|
+
if (escaped) {
|
|
275
|
+
escaped = false;
|
|
276
|
+
}
|
|
277
|
+
else if (char === "\\") {
|
|
278
|
+
escaped = true;
|
|
279
|
+
}
|
|
280
|
+
else if (char === '"') {
|
|
281
|
+
inString = false;
|
|
282
|
+
}
|
|
283
|
+
continue;
|
|
284
|
+
}
|
|
285
|
+
if (char === '"') {
|
|
286
|
+
inString = true;
|
|
287
|
+
result += char;
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
const next = content[i + 1];
|
|
291
|
+
if (char === "/" && next === "/") {
|
|
292
|
+
while (i < content.length && content[i] !== "\n") {
|
|
293
|
+
i++;
|
|
294
|
+
}
|
|
295
|
+
if (i < content.length) {
|
|
296
|
+
result += content[i];
|
|
297
|
+
}
|
|
298
|
+
continue;
|
|
299
|
+
}
|
|
300
|
+
if (char === "/" && next === "*") {
|
|
301
|
+
i += 2;
|
|
302
|
+
while (i < content.length &&
|
|
303
|
+
!(content[i] === "*" && content[i + 1] === "/")) {
|
|
304
|
+
i++;
|
|
305
|
+
}
|
|
306
|
+
i++;
|
|
307
|
+
continue;
|
|
308
|
+
}
|
|
309
|
+
result += char;
|
|
310
|
+
}
|
|
311
|
+
return result;
|
|
312
|
+
}
|
|
313
|
+
async function isFile(targetPath) {
|
|
314
|
+
const info = await stat(targetPath).catch(() => null);
|
|
315
|
+
return info?.isFile() ?? false;
|
|
316
|
+
}
|
|
317
|
+
//# sourceMappingURL=nestjs-build.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nestjs-build.js","sourceRoot":"","sources":["../src/nestjs-build.ts"],"names":[],"mappings":"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"}
|
package/dist/nextjs-build.d.ts
CHANGED
|
@@ -1,12 +1,22 @@
|
|
|
1
|
+
import { type BuildSettings } from "./build-settings.ts";
|
|
1
2
|
import type { BuildArtifact, BuildStrategy } from "./build-strategy.ts";
|
|
3
|
+
import { type BuildCommandIo } from "./workspace.ts";
|
|
2
4
|
/**
|
|
3
|
-
* Build strategy for Next.js applications
|
|
4
|
-
*
|
|
5
|
+
* Build strategy for Next.js applications. Runs the resolved build command
|
|
6
|
+
* (the user's `package.json` build script, or `next build`), then stages the
|
|
7
|
+
* `output: "standalone"` tree — materializing workspace symlinks and hoisting
|
|
8
|
+
* isolated-store dependencies. Apps built without standalone output fall back
|
|
9
|
+
* to packaging the full tree and serving with `next start`, unless
|
|
10
|
+
* `requireStandalone` is set (a disk-limited deploy target opts out of that).
|
|
5
11
|
*/
|
|
6
12
|
export declare class NextjsBuild implements BuildStrategy {
|
|
7
13
|
#private;
|
|
8
14
|
constructor(options: {
|
|
9
15
|
appPath: string;
|
|
16
|
+
buildSettings?: BuildSettings;
|
|
17
|
+
io?: BuildCommandIo;
|
|
18
|
+
/** Fail instead of falling back to the full-tree `next start` artifact. */
|
|
19
|
+
requireStandalone?: boolean;
|
|
10
20
|
});
|
|
11
21
|
canBuild(signal?: AbortSignal): Promise<boolean>;
|
|
12
22
|
execute(signal?: AbortSignal): Promise<BuildArtifact>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nextjs-build.d.ts","sourceRoot":"","sources":["../src/nextjs-build.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"nextjs-build.d.ts","sourceRoot":"","sources":["../src/nextjs-build.ts"],"names":[],"mappings":"AAKA,OAAO,EACL,KAAK,aAAa,EAGnB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGxE,OAAO,EAAE,KAAK,cAAc,EAAmB,MAAM,gBAAgB,CAAC;AAStE;;;;;;;GAOG;AACH,qBAAa,WAAY,YAAW,aAAa;;gBAMnC,OAAO,EAAE;QACnB,OAAO,EAAE,MAAM,CAAC;QAChB,aAAa,CAAC,EAAE,aAAa,CAAC;QAC9B,EAAE,CAAC,EAAE,cAAc,CAAC;QACpB,2EAA2E;QAC3E,iBAAiB,CAAC,EAAE,OAAO,CAAC;KAC7B;IAOK,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;IAOhD,OAAO,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC;CAiE5D"}
|
package/dist/nextjs-build.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import { cp, mkdtemp, readdir, rm, stat } from "node:fs/promises";
|
|
1
|
+
import { cp, mkdtemp, readdir, rm, stat, writeFile } from "node:fs/promises";
|
|
2
2
|
import os from "node:os";
|
|
3
3
|
import path from "node:path";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { stageStandaloneArtifact } from "./artifact-stage.js";
|
|
5
|
+
import { nextOutputRootFromStandaloneDirectory, resolveBuildSettings, } from "./build-settings.js";
|
|
6
|
+
import { hasPackageDependency, hasRootFile } from "./build-strategy.js";
|
|
6
7
|
import { defaultHttpPortForBuildType } from "./config/frameworks.js";
|
|
8
|
+
import { runBuildCommand } from "./workspace.js";
|
|
7
9
|
const NEXT_CONFIG_FILENAMES = [
|
|
8
10
|
"next.config.js",
|
|
9
11
|
"next.config.mjs",
|
|
@@ -11,13 +13,23 @@ const NEXT_CONFIG_FILENAMES = [
|
|
|
11
13
|
"next.config.mts",
|
|
12
14
|
];
|
|
13
15
|
/**
|
|
14
|
-
* Build strategy for Next.js applications
|
|
15
|
-
*
|
|
16
|
+
* Build strategy for Next.js applications. Runs the resolved build command
|
|
17
|
+
* (the user's `package.json` build script, or `next build`), then stages the
|
|
18
|
+
* `output: "standalone"` tree — materializing workspace symlinks and hoisting
|
|
19
|
+
* isolated-store dependencies. Apps built without standalone output fall back
|
|
20
|
+
* to packaging the full tree and serving with `next start`, unless
|
|
21
|
+
* `requireStandalone` is set (a disk-limited deploy target opts out of that).
|
|
16
22
|
*/
|
|
17
23
|
export class NextjsBuild {
|
|
18
24
|
#appPath;
|
|
25
|
+
#buildSettings;
|
|
26
|
+
#io;
|
|
27
|
+
#requireStandalone;
|
|
19
28
|
constructor(options) {
|
|
20
29
|
this.#appPath = options.appPath;
|
|
30
|
+
this.#buildSettings = options.buildSettings;
|
|
31
|
+
this.#io = options.io;
|
|
32
|
+
this.#requireStandalone = options.requireStandalone ?? false;
|
|
21
33
|
}
|
|
22
34
|
async canBuild(signal) {
|
|
23
35
|
return ((await hasRootFile(this.#appPath, NEXT_CONFIG_FILENAMES, signal)) ||
|
|
@@ -25,53 +37,50 @@ export class NextjsBuild {
|
|
|
25
37
|
}
|
|
26
38
|
async execute(signal) {
|
|
27
39
|
signal?.throwIfAborted();
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
+
const settings = this.#buildSettings ??
|
|
41
|
+
(await resolveBuildSettings({
|
|
42
|
+
appPath: this.#appPath,
|
|
43
|
+
buildType: "nextjs",
|
|
44
|
+
signal,
|
|
45
|
+
}));
|
|
46
|
+
if (settings.buildCommand) {
|
|
47
|
+
await runBuildCommand({
|
|
48
|
+
appPath: this.#appPath,
|
|
49
|
+
command: settings.buildCommand,
|
|
50
|
+
failurePrefix: "Next.js",
|
|
51
|
+
env: this.#io?.env,
|
|
52
|
+
onOutput: this.#io?.onOutput,
|
|
53
|
+
signal,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
const standaloneDir = path.join(this.#appPath, settings.outputDirectory);
|
|
57
|
+
if (!(await directoryExists(standaloneDir))) {
|
|
58
|
+
if (this.#requireStandalone) {
|
|
59
|
+
throw new Error(`Next.js build did not produce standalone output at ${settings.outputDirectory}. ` +
|
|
60
|
+
'Set output: "standalone" in your next.config; this deploy target requires it.');
|
|
61
|
+
}
|
|
62
|
+
// No `output: "standalone"` in next.config: the build succeeded, so
|
|
63
|
+
// package the full tree and serve with `next start`. Bigger artifact,
|
|
64
|
+
// same running app.
|
|
65
|
+
return stageFullTreeFallbackArtifact(this.#appPath, signal);
|
|
40
66
|
}
|
|
41
67
|
const outDir = await mkdtemp(path.join(os.tmpdir(), "compute-build-"));
|
|
42
68
|
try {
|
|
43
69
|
const artifactDir = path.join(outDir, "app");
|
|
44
|
-
await
|
|
45
|
-
|
|
46
|
-
|
|
70
|
+
await stageStandaloneArtifact({
|
|
71
|
+
standaloneDir,
|
|
72
|
+
artifactDir,
|
|
73
|
+
appPath: this.#appPath,
|
|
74
|
+
signal,
|
|
75
|
+
});
|
|
76
|
+
const entrypoint = await findStandaloneEntrypoint(artifactDir);
|
|
77
|
+
await copyStaticAssets({
|
|
78
|
+
appPath: this.#appPath,
|
|
79
|
+
artifactDir,
|
|
80
|
+
outputRoot: nextOutputRootFromStandaloneDirectory(settings.outputDirectory),
|
|
81
|
+
entrypoint,
|
|
82
|
+
signal,
|
|
47
83
|
});
|
|
48
|
-
// In monorepos, Next preserves the workspace-relative path from the
|
|
49
|
-
// workspace root down to the app, so server.js lands at e.g.
|
|
50
|
-
// .next/standalone/apps/web/server.js, not at the standalone root.
|
|
51
|
-
// The runtime needs the correct entrypoint, and Next expects public/
|
|
52
|
-
// and .next/static/ to be siblings of server.js.
|
|
53
|
-
const serverSubpath = await findServerSubpath(artifactDir);
|
|
54
|
-
const serverDir = serverSubpath === undefined
|
|
55
|
-
? artifactDir
|
|
56
|
-
: path.join(artifactDir, serverSubpath);
|
|
57
|
-
const publicDir = path.join(this.#appPath, "public");
|
|
58
|
-
if (await directoryExists(publicDir)) {
|
|
59
|
-
await cp(publicDir, path.join(serverDir, "public"), {
|
|
60
|
-
recursive: true,
|
|
61
|
-
verbatimSymlinks: true,
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
const staticDir = path.join(this.#appPath, ".next", "static");
|
|
65
|
-
if (await directoryExists(staticDir)) {
|
|
66
|
-
await cp(staticDir, path.join(serverDir, ".next", "static"), {
|
|
67
|
-
recursive: true,
|
|
68
|
-
verbatimSymlinks: true,
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
const entrypoint = serverSubpath === undefined
|
|
72
|
-
? "server.js"
|
|
73
|
-
: path.posix.join(serverSubpath, "server.js");
|
|
74
|
-
await normalizeArtifactSymlinks(artifactDir, this.#appPath, signal);
|
|
75
84
|
return {
|
|
76
85
|
directory: artifactDir,
|
|
77
86
|
entrypoint,
|
|
@@ -85,44 +94,116 @@ export class NextjsBuild {
|
|
|
85
94
|
}
|
|
86
95
|
}
|
|
87
96
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
97
|
+
const FULL_TREE_ENTRYPOINT = "prisma-next-start.cjs";
|
|
98
|
+
// Bootstrap for apps built without `output: "standalone"`. Entering through
|
|
99
|
+
// the CLI bin (not `next/dist/server/lib/start-server`) keeps Next in charge
|
|
100
|
+
// of config loading, which is the part that drifts across Next majors.
|
|
101
|
+
const FULL_TREE_START_SOURCE = [
|
|
102
|
+
// The runtime unpacks us at the artifact root, but `next start` resolves
|
|
103
|
+
// `.next` from cwd.
|
|
104
|
+
"process.chdir(__dirname);",
|
|
105
|
+
'process.env.NODE_ENV = "production";',
|
|
106
|
+
'process.argv.push("start", "-p", process.env.PORT ?? "3000");',
|
|
107
|
+
'require("next/dist/bin/next");',
|
|
108
|
+
"",
|
|
109
|
+
].join("\n");
|
|
110
|
+
async function stageFullTreeFallbackArtifact(appPath, signal) {
|
|
111
|
+
const outDir = await mkdtemp(path.join(os.tmpdir(), "compute-build-"));
|
|
112
|
+
try {
|
|
113
|
+
const artifactDir = path.join(outDir, "app");
|
|
114
|
+
// node_modules ships on purpose: without standalone output the artifact
|
|
115
|
+
// must carry the full runtime dependency tree for `next start`.
|
|
116
|
+
signal?.throwIfAborted();
|
|
117
|
+
await cp(appPath, artifactDir, {
|
|
118
|
+
recursive: true,
|
|
119
|
+
// Keep relative symlinks relative (node_modules/.bin/*): the default
|
|
120
|
+
// rewrites them to absolute paths into the source tree, which the
|
|
121
|
+
// archiver rejects as escaping the artifact root.
|
|
122
|
+
verbatimSymlinks: true,
|
|
123
|
+
filter: (source) => !isExcludedFromFullTree(path.basename(source)),
|
|
124
|
+
});
|
|
125
|
+
signal?.throwIfAborted();
|
|
126
|
+
await writeFile(path.join(artifactDir, FULL_TREE_ENTRYPOINT), FULL_TREE_START_SOURCE);
|
|
127
|
+
return {
|
|
128
|
+
directory: artifactDir,
|
|
129
|
+
entrypoint: FULL_TREE_ENTRYPOINT,
|
|
130
|
+
defaultPortMapping: { http: defaultHttpPortForBuildType("nextjs") },
|
|
131
|
+
cleanup: () => rm(outDir, { recursive: true, force: true }),
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
await rm(outDir, { recursive: true, force: true });
|
|
136
|
+
throw error;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
/** Excludes VCS internals and dotenv files (local secrets, superseded by the deploy env). */
|
|
140
|
+
function isExcludedFromFullTree(basename) {
|
|
141
|
+
return (basename === ".git" || basename === ".env" || basename.startsWith(".env."));
|
|
142
|
+
}
|
|
143
|
+
async function copyStaticAssets(options) {
|
|
144
|
+
const serverSubpath = serverSubpathOf(options.entrypoint);
|
|
145
|
+
const serverDir = serverSubpath
|
|
146
|
+
? path.join(options.artifactDir, serverSubpath)
|
|
147
|
+
: options.artifactDir;
|
|
148
|
+
const publicDir = path.join(options.appPath, "public");
|
|
149
|
+
if (await directoryExists(publicDir)) {
|
|
150
|
+
options.signal?.throwIfAborted();
|
|
151
|
+
await cp(publicDir, path.join(serverDir, "public"), {
|
|
152
|
+
recursive: true,
|
|
153
|
+
verbatimSymlinks: true,
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
const staticDir = path.join(options.appPath, options.outputRoot, "static");
|
|
157
|
+
if (await directoryExists(staticDir)) {
|
|
158
|
+
options.signal?.throwIfAborted();
|
|
159
|
+
await cp(staticDir, path.join(serverDir, options.outputRoot, "static"), {
|
|
160
|
+
recursive: true,
|
|
161
|
+
verbatimSymlinks: true,
|
|
162
|
+
});
|
|
163
|
+
}
|
|
91
164
|
}
|
|
92
165
|
/**
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
* third-party packages may ship a file named server.js.
|
|
166
|
+
* Locates `server.js` in the staged standalone output. In monorepos Next
|
|
167
|
+
* preserves the workspace-relative path (e.g. `apps/web/server.js`), so the
|
|
168
|
+
* entrypoint is the shallowest match. `node_modules` is skipped because
|
|
169
|
+
* third-party packages may ship their own `server.js`.
|
|
98
170
|
*/
|
|
99
|
-
async function
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
|
|
171
|
+
async function findStandaloneEntrypoint(artifactDir) {
|
|
172
|
+
const rootStat = await stat(path.join(artifactDir, "server.js")).catch(() => null);
|
|
173
|
+
if (rootStat?.isFile()) {
|
|
174
|
+
return "server.js";
|
|
175
|
+
}
|
|
176
|
+
const candidates = [];
|
|
177
|
+
await walk(artifactDir);
|
|
178
|
+
candidates.sort((left, right) => left.split("/").length - right.split("/").length ||
|
|
179
|
+
left.localeCompare(right));
|
|
180
|
+
const selected = candidates[0];
|
|
181
|
+
if (!selected) {
|
|
182
|
+
throw new Error(`Next.js standalone output did not contain server.js in ${artifactDir}`);
|
|
183
|
+
}
|
|
184
|
+
return selected;
|
|
185
|
+
async function walk(directory) {
|
|
186
|
+
const entries = await readdir(directory, { withFileTypes: true });
|
|
103
187
|
for (const entry of entries) {
|
|
104
|
-
if (entry.name === "node_modules")
|
|
188
|
+
if (entry.name === "node_modules") {
|
|
105
189
|
continue;
|
|
106
|
-
|
|
190
|
+
}
|
|
191
|
+
const fullPath = path.join(directory, entry.name);
|
|
107
192
|
if (entry.isDirectory()) {
|
|
108
|
-
|
|
109
|
-
? entry.name
|
|
110
|
-
: path.posix.join(relative, entry.name);
|
|
111
|
-
await walk(fullPath, nextRelative);
|
|
193
|
+
await walk(fullPath);
|
|
112
194
|
}
|
|
113
195
|
else if (entry.isFile() && entry.name === "server.js") {
|
|
114
|
-
|
|
196
|
+
candidates.push(path.relative(artifactDir, fullPath).split(path.sep).join("/"));
|
|
115
197
|
}
|
|
116
198
|
}
|
|
117
199
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
return matches[0];
|
|
200
|
+
}
|
|
201
|
+
function serverSubpathOf(entrypoint) {
|
|
202
|
+
const dir = path.posix.dirname(entrypoint);
|
|
203
|
+
return dir === "." ? "" : dir;
|
|
204
|
+
}
|
|
205
|
+
async function directoryExists(dirPath) {
|
|
206
|
+
const s = await stat(dirPath).catch(() => null);
|
|
207
|
+
return s?.isDirectory() ?? false;
|
|
127
208
|
}
|
|
128
209
|
//# sourceMappingURL=nextjs-build.js.map
|