@prisma/compute-sdk 0.27.0 → 0.29.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/astro-build.d.ts +2 -0
  2. package/dist/astro-build.d.ts.map +1 -1
  3. package/dist/astro-build.js +31 -39
  4. package/dist/astro-build.js.map +1 -1
  5. package/dist/build-settings.d.ts +3 -0
  6. package/dist/build-settings.d.ts.map +1 -1
  7. package/dist/build-settings.js +23 -0
  8. package/dist/build-settings.js.map +1 -1
  9. package/dist/build-strategy.d.ts +20 -0
  10. package/dist/build-strategy.d.ts.map +1 -1
  11. package/dist/build-strategy.js +33 -1
  12. package/dist/build-strategy.js.map +1 -1
  13. package/dist/build.d.ts +2 -1
  14. package/dist/build.d.ts.map +1 -1
  15. package/dist/build.js +19 -4
  16. package/dist/build.js.map +1 -1
  17. package/dist/bun-build.d.ts +1 -1
  18. package/dist/bun-build.d.ts.map +1 -1
  19. package/dist/bun-build.js +25 -9
  20. package/dist/bun-build.js.map +1 -1
  21. package/dist/config/frameworks.d.ts +4 -8
  22. package/dist/config/frameworks.d.ts.map +1 -1
  23. package/dist/config/frameworks.js +29 -5
  24. package/dist/config/frameworks.js.map +1 -1
  25. package/dist/config/normalize.d.ts +6 -0
  26. package/dist/config/normalize.d.ts.map +1 -1
  27. package/dist/config/normalize.js +53 -12
  28. package/dist/config/normalize.js.map +1 -1
  29. package/dist/config/types.d.ts +3 -1
  30. package/dist/config/types.d.ts.map +1 -1
  31. package/dist/config/types.js +2 -0
  32. package/dist/config/types.js.map +1 -1
  33. package/dist/configured-artifact.d.ts +20 -0
  34. package/dist/configured-artifact.d.ts.map +1 -0
  35. package/dist/configured-artifact.js +104 -0
  36. package/dist/configured-artifact.js.map +1 -0
  37. package/dist/custom-build.d.ts +20 -0
  38. package/dist/custom-build.d.ts.map +1 -0
  39. package/dist/custom-build.js +53 -0
  40. package/dist/custom-build.js.map +1 -0
  41. package/dist/index.d.ts +2 -0
  42. package/dist/index.d.ts.map +1 -1
  43. package/dist/index.js +2 -0
  44. package/dist/index.js.map +1 -1
  45. package/dist/nestjs-build.d.ts +23 -0
  46. package/dist/nestjs-build.d.ts.map +1 -0
  47. package/dist/nestjs-build.js +316 -0
  48. package/dist/nestjs-build.js.map +1 -0
  49. package/dist/nextjs-build.d.ts +1 -1
  50. package/dist/nextjs-build.d.ts.map +1 -1
  51. package/dist/nextjs-build.js +25 -14
  52. package/dist/nextjs-build.js.map +1 -1
  53. package/dist/nuxt-build.d.ts +2 -0
  54. package/dist/nuxt-build.d.ts.map +1 -1
  55. package/dist/nuxt-build.js +31 -39
  56. package/dist/nuxt-build.js.map +1 -1
  57. package/dist/tanstack-start-build.d.ts +1 -1
  58. package/dist/tanstack-start-build.d.ts.map +1 -1
  59. package/dist/tanstack-start-build.js +26 -47
  60. package/dist/tanstack-start-build.js.map +1 -1
  61. package/package.json +2 -1
  62. package/src/astro-build.ts +39 -46
  63. package/src/build-settings.ts +34 -0
  64. package/src/build-strategy.ts +56 -1
  65. package/src/build.ts +19 -4
  66. package/src/bun-build.ts +39 -10
  67. package/src/config/frameworks.ts +31 -5
  68. package/src/config/normalize.ts +74 -13
  69. package/src/config/types.ts +4 -0
  70. package/src/configured-artifact.ts +169 -0
  71. package/src/custom-build.ts +73 -0
  72. package/src/index.ts +2 -0
  73. package/src/nestjs-build.ts +428 -0
  74. package/src/nextjs-build.ts +31 -14
  75. package/src/nuxt-build.ts +39 -46
  76. package/src/tanstack-start-build.ts +31 -53
@@ -1,11 +1,6 @@
1
- import { cp, mkdtemp, rm, stat } from "node:fs/promises";
2
- import os from "node:os";
3
- import path from "node:path";
4
- import { normalizeArtifactSymlinks } from "./artifact-postprocess.js";
5
1
  import { resolveBuildSettings } from "./build-settings.js";
6
- import { hasPackageDependency } from "./build-strategy.js";
7
- import { defaultHttpPortForBuildType } from "./config/frameworks.js";
8
- import { runBuildCommand } from "./workspace.js";
2
+ import { hasPackageDependency, runBuildSettingsCommand, } from "./build-strategy.js";
3
+ import { stageConfiguredArtifact } from "./configured-artifact.js";
9
4
  const TANSTACK_START_PACKAGES = [
10
5
  "@tanstack/react-start",
11
6
  "@tanstack/solid-start",
@@ -35,46 +30,30 @@ export class TanstackStartBuild {
35
30
  buildType: "tanstack-start",
36
31
  signal,
37
32
  }));
38
- if (settings.buildCommand) {
39
- await runBuildCommand({
40
- appPath: this.#appPath,
41
- command: settings.buildCommand,
42
- failurePrefix: "TanStack Start",
43
- env: this.#io?.env,
44
- onOutput: this.#io?.onOutput,
45
- signal,
46
- });
47
- }
48
- const outputDir = path.join(this.#appPath, settings.outputDirectory);
49
- const entrypoint = "server/index.mjs";
50
- const entryStat = await stat(path.join(outputDir, entrypoint)).catch(() => null);
51
- if (!entryStat?.isFile()) {
52
- throw new Error(`TanStack Start build did not produce a Nitro node server entrypoint at ${settings.outputDirectory}/${entrypoint}. ` +
53
- "Ensure your vite.config includes the tanstackStart() and nitro() plugins with the default node preset.");
54
- }
55
- const outDir = await mkdtemp(path.join(os.tmpdir(), "compute-build-"));
56
- try {
57
- const artifactDir = path.join(outDir, "app");
58
- await cp(outputDir, artifactDir, {
59
- recursive: true,
60
- verbatimSymlinks: true,
61
- });
62
- // Materialize any symlinks into the app/workspace node_modules so the
63
- // artifact is self-contained once unpacked elsewhere.
64
- await normalizeArtifactSymlinks(artifactDir, this.#appPath, signal);
65
- return {
66
- directory: artifactDir,
67
- entrypoint,
68
- defaultPortMapping: {
69
- http: defaultHttpPortForBuildType("tanstack-start"),
70
- },
71
- cleanup: () => rm(outDir, { recursive: true, force: true }),
72
- };
73
- }
74
- catch (error) {
75
- await rm(outDir, { recursive: true, force: true });
76
- throw error;
77
- }
33
+ await runBuildSettingsCommand({
34
+ appPath: this.#appPath,
35
+ settings,
36
+ failurePrefix: "TanStack Start",
37
+ defaultCli: {
38
+ source: "TanStack Start default",
39
+ cliName: "vite",
40
+ args: ["build"],
41
+ missingMessage: "Could not find the Vite CLI. Install it with `npm install vite` or ensure npx/bunx is available.",
42
+ },
43
+ io: this.#io,
44
+ signal,
45
+ });
46
+ return stageConfiguredArtifact({
47
+ appPath: this.#appPath,
48
+ outputDirectory: settings.outputDirectory,
49
+ entrypoint: settings.entrypoint ?? "server/index.mjs",
50
+ buildType: "tanstack-start",
51
+ label: "TanStack Start",
52
+ missingEntrypointMessage: settings.entrypoint
53
+ ? undefined
54
+ : `TanStack Start build did not produce a Nitro node server entrypoint at ${settings.outputDirectory}/server/index.mjs. Ensure your vite.config includes the tanstackStart() and nitro() plugins with the default node preset.`,
55
+ signal,
56
+ });
78
57
  }
79
58
  }
80
59
  //# sourceMappingURL=tanstack-start-build.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tanstack-start-build.js","sourceRoot":"","sources":["../src/tanstack-start-build.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tanstack-start-build.js","sourceRoot":"","sources":["../src/tanstack-start-build.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAE/E,OAAO,EACL,oBAAoB,EACpB,uBAAuB,GACxB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAGnE,MAAM,uBAAuB,GAAG;IAC9B,uBAAuB;IACvB,uBAAuB;CACxB,CAAC;AAEF;;;;GAIG;AACH,MAAM,OAAO,kBAAkB;IACpB,QAAQ,CAAS;IACjB,cAAc,CAAiB;IAC/B,GAAG,CAAkB;IAE9B,YAAY,OAIX;QACC,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;QAChC,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;QAC5C,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,EAAE,CAAC;IACxB,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,MAAoB;QACjC,OAAO,oBAAoB,CAAC,IAAI,CAAC,QAAQ,EAAE,uBAAuB,EAAE,MAAM,CAAC,CAAC;IAC9E,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,MAAoB;QAChC,MAAM,EAAE,cAAc,EAAE,CAAC;QACzB,MAAM,QAAQ,GACZ,IAAI,CAAC,cAAc;YACnB,CAAC,MAAM,oBAAoB,CAAC;gBAC1B,OAAO,EAAE,IAAI,CAAC,QAAQ;gBACtB,SAAS,EAAE,gBAAgB;gBAC3B,MAAM;aACP,CAAC,CAAC,CAAC;QACN,MAAM,uBAAuB,CAAC;YAC5B,OAAO,EAAE,IAAI,CAAC,QAAQ;YACtB,QAAQ;YACR,aAAa,EAAE,gBAAgB;YAC/B,UAAU,EAAE;gBACV,MAAM,EAAE,wBAAwB;gBAChC,OAAO,EAAE,MAAM;gBACf,IAAI,EAAE,CAAC,OAAO,CAAC;gBACf,cAAc,EACZ,kGAAkG;aACrG;YACD,EAAE,EAAE,IAAI,CAAC,GAAG;YACZ,MAAM;SACP,CAAC,CAAC;QAEH,OAAO,uBAAuB,CAAC;YAC7B,OAAO,EAAE,IAAI,CAAC,QAAQ;YACtB,eAAe,EAAE,QAAQ,CAAC,eAAe;YACzC,UAAU,EAAE,QAAQ,CAAC,UAAU,IAAI,kBAAkB;YACrD,SAAS,EAAE,gBAAgB;YAC3B,KAAK,EAAE,gBAAgB;YACvB,wBAAwB,EAAE,QAAQ,CAAC,UAAU;gBAC3C,CAAC,CAAC,SAAS;gBACX,CAAC,CAAC,0EAA0E,QAAQ,CAAC,eAAe,2HAA2H;YACjO,MAAM;SACP,CAAC,CAAC;IACL,CAAC;CACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prisma/compute-sdk",
3
- "version": "0.27.0",
3
+ "version": "0.29.0",
4
4
  "description": "TypeScript SDK for deploying and managing applications on Prisma Compute",
5
5
  "license": "Apache-2.0",
6
6
  "repository": "prisma/project-compute",
@@ -37,6 +37,7 @@
37
37
  "check:types": "tsc --noEmit"
38
38
  },
39
39
  "dependencies": {
40
+ "@vercel/nft": "^1.10.2",
40
41
  "better-result": "^2.7.0",
41
42
  "jiti": "^2.7.0",
42
43
  "magicast": "^0.5.3",
@@ -1,15 +1,11 @@
1
- import { cp, mkdtemp, rm, stat } from "node:fs/promises";
2
- import os from "node:os";
3
- import path from "node:path";
4
-
5
- import { normalizeArtifactSymlinks } from "./artifact-postprocess.ts";
1
+ import { type BuildSettings, resolveBuildSettings } from "./build-settings.ts";
6
2
  import type { BuildArtifact, BuildStrategy } from "./build-strategy.ts";
7
3
  import {
8
4
  hasPackageDependency,
9
5
  hasRootFile,
10
- runPackageCli,
6
+ runBuildSettingsCommand,
11
7
  } from "./build-strategy.ts";
12
- import { defaultHttpPortForBuildType } from "./config/frameworks.ts";
8
+ import { stageConfiguredArtifact } from "./configured-artifact.ts";
13
9
  import type { BuildCommandIo } from "./workspace.ts";
14
10
 
15
11
  const ASTRO_CONFIG_FILENAMES = [
@@ -26,10 +22,16 @@ const ASTRO_CONFIG_FILENAMES = [
26
22
  */
27
23
  export class AstroBuild implements BuildStrategy {
28
24
  readonly #appPath: string;
25
+ readonly #buildSettings?: BuildSettings;
29
26
  readonly #io?: BuildCommandIo;
30
27
 
31
- constructor(options: { appPath: string; io?: BuildCommandIo }) {
28
+ constructor(options: {
29
+ appPath: string;
30
+ buildSettings?: BuildSettings;
31
+ io?: BuildCommandIo;
32
+ }) {
32
33
  this.#appPath = options.appPath;
34
+ this.#buildSettings = options.buildSettings;
33
35
  this.#io = options.io;
34
36
  }
35
37
 
@@ -42,48 +44,39 @@ export class AstroBuild implements BuildStrategy {
42
44
 
43
45
  async execute(signal?: AbortSignal): Promise<BuildArtifact> {
44
46
  signal?.throwIfAborted();
45
- await runPackageCli({
47
+ const settings =
48
+ this.#buildSettings ??
49
+ (await resolveBuildSettings({
50
+ appPath: this.#appPath,
51
+ buildType: "astro",
52
+ signal,
53
+ }));
54
+
55
+ await runBuildSettingsCommand({
46
56
  appPath: this.#appPath,
47
- cliName: "astro",
48
- args: ["build"],
57
+ settings,
49
58
  failurePrefix: "Astro",
50
- missingMessage:
51
- "Could not find the Astro CLI. Install it with `npm install astro` or ensure npx/bunx is available.",
52
- env: this.#io?.env,
53
- onOutput: this.#io?.onOutput,
59
+ defaultCli: {
60
+ source: "Astro default",
61
+ cliName: "astro",
62
+ args: ["build"],
63
+ missingMessage:
64
+ "Could not find the Astro CLI. Install it with `npm install astro` or ensure npx/bunx is available.",
65
+ },
66
+ io: this.#io,
54
67
  signal,
55
68
  });
56
69
 
57
- const distDir = path.join(this.#appPath, "dist");
58
- const entryPath = path.join(distDir, "server", "entry.mjs");
59
- const entryStat = await stat(entryPath).catch(() => null);
60
- if (!entryStat?.isFile()) {
61
- throw new Error(
62
- 'Astro build did not produce a standalone server entrypoint. Install @astrojs/node and configure it with adapter: node({ mode: "standalone" }) in your astro.config file.',
63
- );
64
- }
65
-
66
- const outDir = await mkdtemp(path.join(os.tmpdir(), "compute-build-"));
67
-
68
- try {
69
- const artifactDir = path.join(outDir, "app");
70
- await cp(distDir, artifactDir, {
71
- recursive: true,
72
- verbatimSymlinks: true,
73
- });
74
- // Materialize any symlinks into the app/workspace node_modules so the
75
- // artifact is self-contained once unpacked elsewhere.
76
- await normalizeArtifactSymlinks(artifactDir, this.#appPath, signal);
77
-
78
- return {
79
- directory: artifactDir,
80
- entrypoint: "server/entry.mjs",
81
- defaultPortMapping: { http: defaultHttpPortForBuildType("astro") },
82
- cleanup: () => rm(outDir, { recursive: true, force: true }),
83
- };
84
- } catch (error) {
85
- await rm(outDir, { recursive: true, force: true });
86
- throw error;
87
- }
70
+ return stageConfiguredArtifact({
71
+ appPath: this.#appPath,
72
+ outputDirectory: settings.outputDirectory,
73
+ entrypoint: settings.entrypoint ?? "server/entry.mjs",
74
+ buildType: "astro",
75
+ label: "Astro",
76
+ missingEntrypointMessage: settings.entrypoint
77
+ ? undefined
78
+ : 'Astro build did not produce a standalone server entrypoint. Install @astrojs/node and configure it with adapter: node({ mode: "standalone" }) in your astro.config file.',
79
+ signal,
80
+ });
88
81
  }
89
82
  }
@@ -22,6 +22,8 @@ export interface BuildSettings {
22
22
  buildCommandSource: string | null;
23
23
  outputDirectory: string;
24
24
  outputDirectorySource: string | null;
25
+ entrypoint?: string;
26
+ entrypointSource?: string | null;
25
27
  }
26
28
 
27
29
  /**
@@ -75,6 +77,24 @@ export async function resolveBuildSettings(options: {
75
77
  outputRoot === ".next" ? "Next.js output" : "next.config distDir",
76
78
  };
77
79
  }
80
+ case "nestjs": {
81
+ const manifest = await readPackageManifest(
82
+ options.appPath,
83
+ options.signal,
84
+ );
85
+ const buildCommand = await resolveFrameworkBuildCommand(
86
+ options.appPath,
87
+ manifest,
88
+ { command: "nest build", source: "NestJS default" },
89
+ options.signal,
90
+ );
91
+ return {
92
+ buildCommand: buildCommand.command,
93
+ buildCommandSource: buildCommand.source,
94
+ outputDirectory: "dist",
95
+ outputDirectorySource: "NestJS output",
96
+ };
97
+ }
78
98
  case "tanstack-start": {
79
99
  const manifest = await readPackageManifest(
80
100
  options.appPath,
@@ -93,6 +113,13 @@ export async function resolveBuildSettings(options: {
93
113
  outputDirectorySource: "TanStack Start output",
94
114
  };
95
115
  }
116
+ case "custom":
117
+ return {
118
+ buildCommand: null,
119
+ buildCommandSource: null,
120
+ outputDirectory: ".",
121
+ outputDirectorySource: "app root",
122
+ };
96
123
  case "bun": {
97
124
  const manifest = await readPackageManifest(
98
125
  options.appPath,
@@ -125,6 +152,7 @@ export async function resolveConfiguredBuildSettings(options: {
125
152
  configured: {
126
153
  command: string | null | undefined;
127
154
  outputDirectory: string | undefined;
155
+ entrypoint?: string | undefined;
128
156
  };
129
157
  /** Label for configured values, e.g. the config file basename. */
130
158
  source: string;
@@ -151,6 +179,12 @@ export async function resolveConfiguredBuildSettings(options: {
151
179
  options.configured.outputDirectory !== undefined
152
180
  ? options.source
153
181
  : (fallback as BuildSettings).outputDirectorySource,
182
+ ...(options.configured.entrypoint !== undefined
183
+ ? {
184
+ entrypoint: options.configured.entrypoint,
185
+ entrypointSource: options.source,
186
+ }
187
+ : {}),
154
188
  };
155
189
  }
156
190
 
@@ -1,7 +1,13 @@
1
1
  import { readdir, readFile, stat } from "node:fs/promises";
2
2
  import path from "node:path";
3
+ import type { BuildSettings } from "./build-settings.ts";
3
4
  import type { PortMapping } from "./types.ts";
4
- import { buildCommandEnv, runChildProcess } from "./workspace.ts";
5
+ import {
6
+ type BuildCommandIo,
7
+ buildCommandEnv,
8
+ runBuildCommand,
9
+ runChildProcess,
10
+ } from "./workspace.ts";
5
11
 
6
12
  /**
7
13
  * The result of executing a build strategy.
@@ -207,6 +213,55 @@ export async function runPackageCli(opts: {
207
213
  throw new Error(opts.missingMessage);
208
214
  }
209
215
 
216
+ /**
217
+ * Runs the command described by build settings. A configured shell command runs
218
+ * as-is; a framework default can use the launcher ladder so local binaries,
219
+ * npx, and bunx all work consistently. `null` means "skip build".
220
+ */
221
+ export async function runBuildSettingsCommand(options: {
222
+ appPath: string;
223
+ settings: Pick<BuildSettings, "buildCommand" | "buildCommandSource">;
224
+ failurePrefix: string;
225
+ defaultCli?: {
226
+ source: string;
227
+ cliName: string;
228
+ args: string[];
229
+ missingMessage: string;
230
+ };
231
+ io?: BuildCommandIo;
232
+ signal?: AbortSignal;
233
+ }): Promise<void> {
234
+ if (!options.settings.buildCommand) {
235
+ return;
236
+ }
237
+
238
+ if (
239
+ options.defaultCli &&
240
+ options.settings.buildCommandSource === options.defaultCli.source
241
+ ) {
242
+ await runPackageCli({
243
+ appPath: options.appPath,
244
+ cliName: options.defaultCli.cliName,
245
+ args: options.defaultCli.args,
246
+ failurePrefix: options.failurePrefix,
247
+ missingMessage: options.defaultCli.missingMessage,
248
+ env: options.io?.env,
249
+ onOutput: options.io?.onOutput,
250
+ signal: options.signal,
251
+ });
252
+ return;
253
+ }
254
+
255
+ await runBuildCommand({
256
+ appPath: options.appPath,
257
+ command: options.settings.buildCommand,
258
+ failurePrefix: options.failurePrefix,
259
+ env: options.io?.env,
260
+ onOutput: options.io?.onOutput,
261
+ signal: options.signal,
262
+ });
263
+ }
264
+
210
265
  function isRecord(value: unknown): value is Record<string, unknown> {
211
266
  return typeof value === "object" && value !== null;
212
267
  }
package/src/build.ts CHANGED
@@ -3,6 +3,8 @@ import type { BuildSettings } from "./build-settings.ts";
3
3
  import type { BuildStrategy } from "./build-strategy.ts";
4
4
  import { BunBuild } from "./bun-build.ts";
5
5
  import { FRAMEWORKS, type FrameworkBuildType } from "./config/frameworks.ts";
6
+ import { CustomBuild } from "./custom-build.ts";
7
+ import { NestjsBuild } from "./nestjs-build.ts";
6
8
  import { NextjsBuild } from "./nextjs-build.ts";
7
9
  import { NuxtBuild } from "./nuxt-build.ts";
8
10
  import { TanstackStartBuild } from "./tanstack-start-build.ts";
@@ -32,12 +34,16 @@ const DETECTION_ORDER: FrameworkBuildType[] = (() => {
32
34
  const buildTypes = [
33
35
  ...new Set(FRAMEWORKS.map((framework) => framework.buildType)),
34
36
  ];
35
- return [...buildTypes.filter((type) => type !== "bun"), "bun"];
37
+ return [
38
+ ...buildTypes.filter((type) => type !== "bun" && type !== "custom"),
39
+ "bun",
40
+ ];
36
41
  })();
37
42
 
38
43
  /**
39
44
  * Constructs the build strategy for an explicit framework build type, wiring
40
- * through optional committed build settings and (for bun) the entrypoint.
45
+ * through optional committed build settings and entrypoints for strategies
46
+ * that need one.
41
47
  */
42
48
  export function createBuildStrategy(
43
49
  options: {
@@ -57,11 +63,20 @@ export function createBuildStrategy(
57
63
  requireStandalone: options.requireStandalone,
58
64
  });
59
65
  case "nuxt":
60
- return new NuxtBuild({ appPath, io });
66
+ return new NuxtBuild({ appPath, buildSettings, io });
61
67
  case "astro":
62
- return new AstroBuild({ appPath, io });
68
+ return new AstroBuild({ appPath, buildSettings, io });
69
+ case "nestjs":
70
+ return new NestjsBuild({ appPath, buildSettings, io });
63
71
  case "tanstack-start":
64
72
  return new TanstackStartBuild({ appPath, buildSettings, io });
73
+ case "custom":
74
+ return new CustomBuild({
75
+ appPath,
76
+ entrypoint: options.entrypoint,
77
+ buildSettings,
78
+ io,
79
+ });
65
80
  case "bun":
66
81
  return new BunBuild({
67
82
  appPath,
package/src/bun-build.ts CHANGED
@@ -9,12 +9,16 @@ import {
9
9
  import os from "node:os";
10
10
  import path from "node:path";
11
11
  import type { BuildSettings } from "./build-settings.ts";
12
- import type { BuildArtifact, BuildStrategy } from "./build-strategy.ts";
12
+ import {
13
+ type BuildArtifact,
14
+ type BuildStrategy,
15
+ runBuildSettingsCommand,
16
+ } from "./build-strategy.ts";
13
17
  import { defaultHttpPortForBuildType } from "./config/frameworks.ts";
18
+ import { stageConfiguredArtifact } from "./configured-artifact.ts";
14
19
  import {
15
20
  type BuildCommandIo,
16
21
  buildCommandEnv,
17
- runBuildCommand,
18
22
  runChildProcess,
19
23
  } from "./workspace.ts";
20
24
 
@@ -50,17 +54,36 @@ export class BunBuild implements BuildStrategy {
50
54
 
51
55
  async execute(signal?: AbortSignal): Promise<BuildArtifact> {
52
56
  signal?.throwIfAborted();
53
- if (this.#buildSettings?.buildCommand) {
54
- await runBuildCommand({
57
+ if (this.#buildSettings) {
58
+ await runBuildSettingsCommand({
55
59
  appPath: this.#appPath,
56
- command: this.#buildSettings.buildCommand,
60
+ settings: this.#buildSettings,
57
61
  failurePrefix: "Bun",
58
- env: this.#io?.env,
59
- onOutput: this.#io?.onOutput,
62
+ io: this.#io,
63
+ signal,
64
+ });
65
+ }
66
+
67
+ if (this.#buildSettings && this.#buildSettings.outputDirectory !== ".") {
68
+ if (!this.#buildSettings.entrypoint) {
69
+ throw new Error(
70
+ "Bun build entrypoint is required when outputDirectory is configured",
71
+ );
72
+ }
73
+ return stageConfiguredArtifact({
74
+ appPath: this.#appPath,
75
+ outputDirectory: this.#buildSettings.outputDirectory,
76
+ entrypoint: this.#buildSettings.entrypoint,
77
+ buildType: "bun",
78
+ label: "Bun",
60
79
  signal,
61
80
  });
62
81
  }
63
- const entrypoint = await this.#resolveEntrypoint(signal);
82
+
83
+ const entrypoint = await this.#resolveEntrypoint(
84
+ signal,
85
+ this.#buildSettings?.entrypoint,
86
+ );
64
87
 
65
88
  const outDir = await mkdtemp(path.join(os.tmpdir(), "compute-build-"));
66
89
  const bundleDir = path.join(outDir, "bundle");
@@ -94,9 +117,15 @@ export class BunBuild implements BuildStrategy {
94
117
  };
95
118
  }
96
119
 
97
- async #resolveEntrypoint(signal?: AbortSignal): Promise<string> {
120
+ async #resolveEntrypoint(
121
+ signal?: AbortSignal,
122
+ configuredEntrypoint?: string,
123
+ ): Promise<string> {
98
124
  signal?.throwIfAborted();
99
- const candidate = this.#entrypoint ?? (await this.#readPackageJsonMain());
125
+ const candidate =
126
+ this.#entrypoint ??
127
+ configuredEntrypoint ??
128
+ (await this.#readPackageJsonMain());
100
129
 
101
130
  if (!candidate) {
102
131
  throw new Error(
@@ -11,7 +11,9 @@ export type FrameworkBuildType =
11
11
  | "nextjs"
12
12
  | "nuxt"
13
13
  | "astro"
14
+ | "nestjs"
14
15
  | "tanstack-start"
16
+ | "custom"
15
17
  | "bun";
16
18
 
17
19
  export interface FrameworkDescriptor {
@@ -108,6 +110,18 @@ export const FRAMEWORKS: readonly FrameworkDescriptor[] = [
108
110
  hasLocalDevServer: true,
109
111
  defaultHttpPort: 3000,
110
112
  },
113
+ {
114
+ key: "nestjs",
115
+ displayName: "NestJS",
116
+ buildType: "nestjs",
117
+ aliases: ["nestjs", "nest"],
118
+ detectPackages: ["@nestjs/core"],
119
+ detectConfigFiles: ["nest-cli.json"],
120
+ usesEntrypoint: false,
121
+ defaultEntrypoint: null,
122
+ hasLocalDevServer: false,
123
+ defaultHttpPort: 3000,
124
+ },
111
125
  {
112
126
  key: "tanstack-start",
113
127
  displayName: "TanStack Start",
@@ -125,6 +139,18 @@ export const FRAMEWORKS: readonly FrameworkDescriptor[] = [
125
139
  hasLocalDevServer: false,
126
140
  defaultHttpPort: 3000,
127
141
  },
142
+ {
143
+ key: "custom",
144
+ displayName: "Custom",
145
+ buildType: "custom",
146
+ aliases: ["custom"],
147
+ detectPackages: [],
148
+ detectConfigFiles: [],
149
+ usesEntrypoint: false,
150
+ defaultEntrypoint: null,
151
+ hasLocalDevServer: false,
152
+ defaultHttpPort: 3000,
153
+ },
128
154
  {
129
155
  key: "bun",
130
156
  displayName: "Bun",
@@ -141,14 +167,14 @@ export const FRAMEWORKS: readonly FrameworkDescriptor[] = [
141
167
 
142
168
  export const FRAMEWORK_KEYS = FRAMEWORKS.map((framework) => framework.key);
143
169
 
144
- /**
145
- * Build types whose preview build consumes committed build settings. The
146
- * others (nuxt, astro) run their framework CLI and stage fixed output, so a
147
- * config `build` block has nothing to apply to.
148
- */
170
+ /** Build types whose preview build consumes committed build settings. */
149
171
  export const CONFIG_BACKED_BUILD_TYPES = [
150
172
  "nextjs",
173
+ "nuxt",
174
+ "astro",
175
+ "nestjs",
151
176
  "tanstack-start",
177
+ "custom",
152
178
  "bun",
153
179
  ] as const satisfies readonly FrameworkBuildType[];
154
180