@prisma/compute-sdk 0.13.0 → 0.15.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 (44) hide show
  1. package/dist/astro-build.d.ts +14 -0
  2. package/dist/astro-build.d.ts.map +1 -0
  3. package/dist/astro-build.js +59 -0
  4. package/dist/astro-build.js.map +1 -0
  5. package/dist/auto-build.d.ts.map +1 -1
  6. package/dist/auto-build.js +6 -0
  7. package/dist/auto-build.js.map +1 -1
  8. package/dist/build-strategy.d.ts +30 -0
  9. package/dist/build-strategy.d.ts.map +1 -1
  10. package/dist/build-strategy.js +101 -1
  11. package/dist/build-strategy.js.map +1 -1
  12. package/dist/errors.d.ts +6 -0
  13. package/dist/errors.d.ts.map +1 -1
  14. package/dist/errors.js +2 -0
  15. package/dist/errors.js.map +1 -1
  16. package/dist/index.d.ts +6 -1
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +5 -3
  19. package/dist/index.js.map +1 -1
  20. package/dist/log-stream.d.ts +40 -0
  21. package/dist/log-stream.d.ts.map +1 -0
  22. package/dist/log-stream.js +151 -0
  23. package/dist/log-stream.js.map +1 -0
  24. package/dist/nextjs-build.d.ts.map +1 -1
  25. package/dist/nextjs-build.js +23 -87
  26. package/dist/nextjs-build.js.map +1 -1
  27. package/dist/nuxt-build.d.ts +14 -0
  28. package/dist/nuxt-build.d.ts.map +1 -0
  29. package/dist/nuxt-build.js +59 -0
  30. package/dist/nuxt-build.js.map +1 -0
  31. package/dist/tanstack-start-build.d.ts +14 -0
  32. package/dist/tanstack-start-build.d.ts.map +1 -0
  33. package/dist/tanstack-start-build.js +55 -0
  34. package/dist/tanstack-start-build.js.map +1 -0
  35. package/package.json +4 -2
  36. package/src/astro-build.ts +76 -0
  37. package/src/auto-build.ts +6 -0
  38. package/src/build-strategy.ts +141 -1
  39. package/src/errors.ts +5 -0
  40. package/src/index.ts +13 -5
  41. package/src/log-stream.ts +218 -0
  42. package/src/nextjs-build.ts +30 -109
  43. package/src/nuxt-build.ts +76 -0
  44. package/src/tanstack-start-build.ts +66 -0
@@ -1,7 +1,7 @@
1
- import { execFile } from "node:child_process";
2
- import { cp, mkdtemp, readdir, readFile, rm, stat } from "node:fs/promises";
1
+ import { cp, mkdtemp, rm, stat } from "node:fs/promises";
3
2
  import os from "node:os";
4
3
  import path from "node:path";
4
+ import { hasPackageDependency, hasRootFile, runPackageCli, } from "./build-strategy.js";
5
5
  const NEXT_CONFIG_FILENAMES = [
6
6
  "next.config.js",
7
7
  "next.config.mjs",
@@ -18,10 +18,17 @@ export class NextjsBuild {
18
18
  this.#appPath = options.appPath;
19
19
  }
20
20
  async canBuild() {
21
- return (await this.#hasNextConfig()) || (await this.#hasNextDependency());
21
+ return ((await hasRootFile(this.#appPath, NEXT_CONFIG_FILENAMES)) ||
22
+ (await hasPackageDependency(this.#appPath, ["next"])));
22
23
  }
23
24
  async execute() {
24
- await this.#runBuild();
25
+ await runPackageCli({
26
+ appPath: this.#appPath,
27
+ cliName: "next",
28
+ args: ["build"],
29
+ failurePrefix: "Next.js",
30
+ missingMessage: "Could not find the Next.js CLI. Install it with `npm install next` or ensure npx/bunx is available.",
31
+ });
25
32
  const standaloneDir = path.join(this.#appPath, ".next", "standalone");
26
33
  const standaloneStat = await stat(standaloneDir).catch(() => null);
27
34
  if (!standaloneStat?.isDirectory()) {
@@ -30,17 +37,22 @@ export class NextjsBuild {
30
37
  const outDir = await mkdtemp(path.join(os.tmpdir(), "compute-build-"));
31
38
  try {
32
39
  const artifactDir = path.join(outDir, "app");
33
- await cp(standaloneDir, artifactDir, { recursive: true });
40
+ await cp(standaloneDir, artifactDir, {
41
+ recursive: true,
42
+ verbatimSymlinks: true,
43
+ });
34
44
  const publicDir = path.join(this.#appPath, "public");
35
- if (await this.#directoryExists(publicDir)) {
45
+ if (await directoryExists(publicDir)) {
36
46
  await cp(publicDir, path.join(artifactDir, "public"), {
37
47
  recursive: true,
48
+ verbatimSymlinks: true,
38
49
  });
39
50
  }
40
51
  const staticDir = path.join(this.#appPath, ".next", "static");
41
- if (await this.#directoryExists(staticDir)) {
52
+ if (await directoryExists(staticDir)) {
42
53
  await cp(staticDir, path.join(artifactDir, ".next", "static"), {
43
54
  recursive: true,
55
+ verbatimSymlinks: true,
44
56
  });
45
57
  }
46
58
  return {
@@ -55,85 +67,9 @@ export class NextjsBuild {
55
67
  throw error;
56
68
  }
57
69
  }
58
- async #hasNextConfig() {
59
- let entries;
60
- try {
61
- entries = await readdir(this.#appPath);
62
- }
63
- catch {
64
- return false;
65
- }
66
- return entries.some((entry) => NEXT_CONFIG_FILENAMES.includes(entry));
67
- }
68
- async #hasNextDependency() {
69
- const packageJsonPath = path.join(this.#appPath, "package.json");
70
- let content;
71
- try {
72
- content = await readFile(packageJsonPath, "utf-8");
73
- }
74
- catch {
75
- return false;
76
- }
77
- let parsed;
78
- try {
79
- parsed = JSON.parse(content);
80
- }
81
- catch {
82
- return false;
83
- }
84
- const deps = typeof parsed.dependencies === "object" && parsed.dependencies !== null
85
- ? parsed.dependencies
86
- : {};
87
- const devDeps = typeof parsed.devDependencies === "object" &&
88
- parsed.devDependencies !== null
89
- ? parsed.devDependencies
90
- : {};
91
- return "next" in deps || "next" in devDeps;
92
- }
93
- async #runBuild() {
94
- const localBin = path.join(this.#appPath, "node_modules", ".bin", "next");
95
- const candidates = [
96
- { command: localBin, args: ["build"] },
97
- { command: "npx", args: ["next", "build"] },
98
- { command: "bunx", args: ["next", "build"] },
99
- ];
100
- for (const { command, args } of candidates) {
101
- try {
102
- await this.#exec(command, args);
103
- return;
104
- }
105
- catch (error) {
106
- if (error instanceof Error &&
107
- "code" in error &&
108
- error.code === "ENOENT") {
109
- continue;
110
- }
111
- throw error;
112
- }
113
- }
114
- throw new Error("Could not find the Next.js CLI. Install it with `npm install next` or ensure npx/bunx is available.");
115
- }
116
- #exec(command, args) {
117
- return new Promise((resolve, reject) => {
118
- execFile(command, args, { cwd: this.#appPath }, (error, _stdout, stderr) => {
119
- if (error) {
120
- if ("code" in error && error.code === "ENOENT") {
121
- reject(Object.assign(new Error(`${command} not found`), {
122
- code: "ENOENT",
123
- }));
124
- return;
125
- }
126
- const message = stderr.trim() || error.message;
127
- reject(new Error(`Next.js build failed:\n${message}`));
128
- return;
129
- }
130
- resolve();
131
- });
132
- });
133
- }
134
- async #directoryExists(dirPath) {
135
- const s = await stat(dirPath).catch(() => null);
136
- return s?.isDirectory() ?? false;
137
- }
70
+ }
71
+ async function directoryExists(dirPath) {
72
+ const s = await stat(dirPath).catch(() => null);
73
+ return s?.isDirectory() ?? false;
138
74
  }
139
75
  //# sourceMappingURL=nextjs-build.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"nextjs-build.js","sourceRoot":"","sources":["../src/nextjs-build.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC5E,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B,MAAM,qBAAqB,GAAG;IAC5B,gBAAgB;IAChB,iBAAiB;IACjB,gBAAgB;IAChB,iBAAiB;CAClB,CAAC;AAEF;;;GAGG;AACH,MAAM,OAAO,WAAW;IACb,QAAQ,CAAS;IAE1B,YAAY,OAA4B;QACtC,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;IAClC,CAAC;IAED,KAAK,CAAC,QAAQ;QACZ,OAAO,CAAC,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,kBAAkB,EAAE,CAAC,CAAC;IAC5E,CAAC;IAED,KAAK,CAAC,OAAO;QACX,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;QAEvB,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC;QACtE,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;QACnE,IAAI,CAAC,cAAc,EAAE,WAAW,EAAE,EAAE,CAAC;YACnC,MAAM,IAAI,KAAK,CACb,qGAAqG,CACtG,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC;QAEvE,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;YAE7C,MAAM,EAAE,CAAC,aAAa,EAAE,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAE1D,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;YACrD,IAAI,MAAM,IAAI,CAAC,gBAAgB,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC3C,MAAM,EAAE,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,EAAE;oBACpD,SAAS,EAAE,IAAI;iBAChB,CAAC,CAAC;YACL,CAAC;YAED,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;YAC9D,IAAI,MAAM,IAAI,CAAC,gBAAgB,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC3C,MAAM,EAAE,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE;oBAC7D,SAAS,EAAE,IAAI;iBAChB,CAAC,CAAC;YACL,CAAC;YAED,OAAO;gBACL,SAAS,EAAE,WAAW;gBACtB,UAAU,EAAE,WAAW;gBACvB,kBAAkB,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE;gBAClC,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;aAC5D,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YACnD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED,KAAK,CAAC,cAAc;QAClB,IAAI,OAAiB,CAAC;QACtB,IAAI,CAAC;YACH,OAAO,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACzC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;QACD,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,qBAAqB,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;IACxE,CAAC;IAED,KAAK,CAAC,kBAAkB;QACtB,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;QAEjE,IAAI,OAAe,CAAC;QACpB,IAAI,CAAC;YACH,OAAO,GAAG,MAAM,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;QACrD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,MAA6D,CAAC;QAClE,IAAI,CAAC;YACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAG1B,CAAC;QACJ,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,IAAI,GACR,OAAO,MAAM,CAAC,YAAY,KAAK,QAAQ,IAAI,MAAM,CAAC,YAAY,KAAK,IAAI;YACrE,CAAC,CAAC,MAAM,CAAC,YAAY;YACrB,CAAC,CAAC,EAAE,CAAC;QACT,MAAM,OAAO,GACX,OAAO,MAAM,CAAC,eAAe,KAAK,QAAQ;YAC1C,MAAM,CAAC,eAAe,KAAK,IAAI;YAC7B,CAAC,CAAC,MAAM,CAAC,eAAe;YACxB,CAAC,CAAC,EAAE,CAAC;QAET,OAAO,MAAM,IAAI,IAAI,IAAI,MAAM,IAAI,OAAO,CAAC;IAC7C,CAAC;IAED,KAAK,CAAC,SAAS;QACb,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QAC1E,MAAM,UAAU,GAA+C;YAC7D,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,OAAO,CAAC,EAAE;YACtC,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE;YAC3C,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE;SAC7C,CAAC;QAEF,KAAK,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,UAAU,EAAE,CAAC;YAC3C,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;gBAChC,OAAO;YACT,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IACE,KAAK,YAAY,KAAK;oBACtB,MAAM,IAAI,KAAK;oBACf,KAAK,CAAC,IAAI,KAAK,QAAQ,EACvB,CAAC;oBACD,SAAS;gBACX,CAAC;gBACD,MAAM,KAAK,CAAC;YACd,CAAC;QACH,CAAC;QAED,MAAM,IAAI,KAAK,CACb,qGAAqG,CACtG,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,IAAc;QACnC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,QAAQ,CACN,OAAO,EACP,IAAI,EACJ,EAAE,GAAG,EAAE,IAAI,CAAC,QAAQ,EAAE,EACtB,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE;gBACzB,IAAI,KAAK,EAAE,CAAC;oBACV,IAAI,MAAM,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;wBAC/C,MAAM,CACJ,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,GAAG,OAAO,YAAY,CAAC,EAAE;4BAC/C,IAAI,EAAE,QAAQ;yBACf,CAAC,CACH,CAAC;wBACF,OAAO;oBACT,CAAC;oBACD,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,IAAI,KAAK,CAAC,OAAO,CAAC;oBAC/C,MAAM,CAAC,IAAI,KAAK,CAAC,0BAA0B,OAAO,EAAE,CAAC,CAAC,CAAC;oBACvD,OAAO;gBACT,CAAC;gBACD,OAAO,EAAE,CAAC;YACZ,CAAC,CACF,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,OAAe;QACpC,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;QAChD,OAAO,CAAC,EAAE,WAAW,EAAE,IAAI,KAAK,CAAC;IACnC,CAAC;CACF"}
1
+ {"version":3,"file":"nextjs-build.js","sourceRoot":"","sources":["../src/nextjs-build.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { BuildArtifact, BuildStrategy } from "./build-strategy.ts";
2
+ /**
3
+ * Build strategy for Nuxt applications using the Nitro `node-server` preset
4
+ * (the default). Runs `nuxt build` and produces an artifact from `.output/`.
5
+ */
6
+ export declare class NuxtBuild implements BuildStrategy {
7
+ #private;
8
+ constructor(options: {
9
+ appPath: string;
10
+ });
11
+ canBuild(): Promise<boolean>;
12
+ execute(): Promise<BuildArtifact>;
13
+ }
14
+ //# sourceMappingURL=nuxt-build.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nuxt-build.d.ts","sourceRoot":"","sources":["../src/nuxt-build.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAexE;;;GAGG;AACH,qBAAa,SAAU,YAAW,aAAa;;gBAGjC,OAAO,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE;IAIlC,QAAQ,IAAI,OAAO,CAAC,OAAO,CAAC;IAO5B,OAAO,IAAI,OAAO,CAAC,aAAa,CAAC;CAuCxC"}
@@ -0,0 +1,59 @@
1
+ import { cp, mkdtemp, rm, stat } from "node:fs/promises";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ import { hasPackageDependency, hasRootFile, runPackageCli, } from "./build-strategy.js";
5
+ const NUXT_CONFIG_FILENAMES = [
6
+ "nuxt.config.js",
7
+ "nuxt.config.mjs",
8
+ "nuxt.config.cjs",
9
+ "nuxt.config.ts",
10
+ "nuxt.config.mts",
11
+ ];
12
+ /**
13
+ * Build strategy for Nuxt applications using the Nitro `node-server` preset
14
+ * (the default). Runs `nuxt build` and produces an artifact from `.output/`.
15
+ */
16
+ export class NuxtBuild {
17
+ #appPath;
18
+ constructor(options) {
19
+ this.#appPath = options.appPath;
20
+ }
21
+ async canBuild() {
22
+ return ((await hasRootFile(this.#appPath, NUXT_CONFIG_FILENAMES)) ||
23
+ (await hasPackageDependency(this.#appPath, ["nuxt"])));
24
+ }
25
+ async execute() {
26
+ await runPackageCli({
27
+ appPath: this.#appPath,
28
+ cliName: "nuxt",
29
+ args: ["build"],
30
+ failurePrefix: "Nuxt",
31
+ missingMessage: "Could not find the Nuxt CLI. Install it with `npm install nuxt` or ensure npx/bunx is available.",
32
+ });
33
+ const outputDir = path.join(this.#appPath, ".output");
34
+ const entryPath = path.join(outputDir, "server", "index.mjs");
35
+ const entryStat = await stat(entryPath).catch(() => null);
36
+ if (!entryStat?.isFile()) {
37
+ throw new Error("Nuxt build did not produce a Nitro node server entrypoint at .output/server/index.mjs. Ensure nitro.preset is 'node-server' (the default) — set NITRO_PRESET=node-server or remove any custom preset from nuxt.config.");
38
+ }
39
+ const outDir = await mkdtemp(path.join(os.tmpdir(), "compute-build-"));
40
+ try {
41
+ const artifactDir = path.join(outDir, "app");
42
+ await cp(outputDir, artifactDir, {
43
+ recursive: true,
44
+ verbatimSymlinks: true,
45
+ });
46
+ return {
47
+ directory: artifactDir,
48
+ entrypoint: "server/index.mjs",
49
+ defaultPortMapping: { http: 3000 },
50
+ cleanup: () => rm(outDir, { recursive: true, force: true }),
51
+ };
52
+ }
53
+ catch (error) {
54
+ await rm(outDir, { recursive: true, force: true });
55
+ throw error;
56
+ }
57
+ }
58
+ }
59
+ //# sourceMappingURL=nuxt-build.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nuxt-build.js","sourceRoot":"","sources":["../src/nuxt-build.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EACL,oBAAoB,EACpB,WAAW,EACX,aAAa,GACd,MAAM,qBAAqB,CAAC;AAE7B,MAAM,qBAAqB,GAAG;IAC5B,gBAAgB;IAChB,iBAAiB;IACjB,iBAAiB;IACjB,gBAAgB;IAChB,iBAAiB;CAClB,CAAC;AAEF;;;GAGG;AACH,MAAM,OAAO,SAAS;IACX,QAAQ,CAAS;IAE1B,YAAY,OAA4B;QACtC,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;IAClC,CAAC;IAED,KAAK,CAAC,QAAQ;QACZ,OAAO,CACL,CAAC,MAAM,WAAW,CAAC,IAAI,CAAC,QAAQ,EAAE,qBAAqB,CAAC,CAAC;YACzD,CAAC,MAAM,oBAAoB,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CACtD,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,OAAO;QACX,MAAM,aAAa,CAAC;YAClB,OAAO,EAAE,IAAI,CAAC,QAAQ;YACtB,OAAO,EAAE,MAAM;YACf,IAAI,EAAE,CAAC,OAAO,CAAC;YACf,aAAa,EAAE,MAAM;YACrB,cAAc,EACZ,kGAAkG;SACrG,CAAC,CAAC;QAEH,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QACtD,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;QAC9D,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;QAC1D,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CACb,wNAAwN,CACzN,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC;QAEvE,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;YAC7C,MAAM,EAAE,CAAC,SAAS,EAAE,WAAW,EAAE;gBAC/B,SAAS,EAAE,IAAI;gBACf,gBAAgB,EAAE,IAAI;aACvB,CAAC,CAAC;YAEH,OAAO;gBACL,SAAS,EAAE,WAAW;gBACtB,UAAU,EAAE,kBAAkB;gBAC9B,kBAAkB,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE;gBAClC,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;aAC5D,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YACnD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,14 @@
1
+ import type { BuildArtifact, BuildStrategy } from "./build-strategy.ts";
2
+ /**
3
+ * Build strategy for TanStack Start applications targeting the Nitro node
4
+ * preset. Runs `vite build` and produces an artifact from `.output/`.
5
+ */
6
+ export declare class TanstackStartBuild implements BuildStrategy {
7
+ #private;
8
+ constructor(options: {
9
+ appPath: string;
10
+ });
11
+ canBuild(): Promise<boolean>;
12
+ execute(): Promise<BuildArtifact>;
13
+ }
14
+ //# sourceMappingURL=tanstack-start-build.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tanstack-start-build.d.ts","sourceRoot":"","sources":["../src/tanstack-start-build.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAQxE;;;GAGG;AACH,qBAAa,kBAAmB,YAAW,aAAa;;gBAG1C,OAAO,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE;IAIlC,QAAQ,IAAI,OAAO,CAAC,OAAO,CAAC;IAI5B,OAAO,IAAI,OAAO,CAAC,aAAa,CAAC;CAuCxC"}
@@ -0,0 +1,55 @@
1
+ import { cp, mkdtemp, rm, stat } from "node:fs/promises";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ import { hasPackageDependency, runPackageCli } from "./build-strategy.js";
5
+ const TANSTACK_START_PACKAGES = [
6
+ "@tanstack/react-start",
7
+ "@tanstack/solid-start",
8
+ ];
9
+ /**
10
+ * Build strategy for TanStack Start applications targeting the Nitro node
11
+ * preset. Runs `vite build` and produces an artifact from `.output/`.
12
+ */
13
+ export class TanstackStartBuild {
14
+ #appPath;
15
+ constructor(options) {
16
+ this.#appPath = options.appPath;
17
+ }
18
+ async canBuild() {
19
+ return hasPackageDependency(this.#appPath, TANSTACK_START_PACKAGES);
20
+ }
21
+ async execute() {
22
+ await runPackageCli({
23
+ appPath: this.#appPath,
24
+ cliName: "vite",
25
+ args: ["build"],
26
+ failurePrefix: "TanStack Start",
27
+ missingMessage: "Could not find the Vite CLI. Install it with `npm install vite` or ensure npx/bunx is available.",
28
+ });
29
+ const outputDir = path.join(this.#appPath, ".output");
30
+ const entryPath = path.join(outputDir, "server", "index.mjs");
31
+ const entryStat = await stat(entryPath).catch(() => null);
32
+ if (!entryStat?.isFile()) {
33
+ throw new Error("TanStack Start build did not produce a Nitro node server entrypoint at .output/server/index.mjs. Ensure your vite.config includes the tanstackStart() and nitro() plugins with the default node preset.");
34
+ }
35
+ const outDir = await mkdtemp(path.join(os.tmpdir(), "compute-build-"));
36
+ try {
37
+ const artifactDir = path.join(outDir, "app");
38
+ await cp(outputDir, artifactDir, {
39
+ recursive: true,
40
+ verbatimSymlinks: true,
41
+ });
42
+ return {
43
+ directory: artifactDir,
44
+ entrypoint: "server/index.mjs",
45
+ defaultPortMapping: { http: 3000 },
46
+ cleanup: () => rm(outDir, { recursive: true, force: true }),
47
+ };
48
+ }
49
+ catch (error) {
50
+ await rm(outDir, { recursive: true, force: true });
51
+ throw error;
52
+ }
53
+ }
54
+ }
55
+ //# sourceMappingURL=tanstack-start-build.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tanstack-start-build.js","sourceRoot":"","sources":["../src/tanstack-start-build.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAE1E,MAAM,uBAAuB,GAAG;IAC9B,uBAAuB;IACvB,uBAAuB;CACxB,CAAC;AAEF;;;GAGG;AACH,MAAM,OAAO,kBAAkB;IACpB,QAAQ,CAAS;IAE1B,YAAY,OAA4B;QACtC,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;IAClC,CAAC;IAED,KAAK,CAAC,QAAQ;QACZ,OAAO,oBAAoB,CAAC,IAAI,CAAC,QAAQ,EAAE,uBAAuB,CAAC,CAAC;IACtE,CAAC;IAED,KAAK,CAAC,OAAO;QACX,MAAM,aAAa,CAAC;YAClB,OAAO,EAAE,IAAI,CAAC,QAAQ;YACtB,OAAO,EAAE,MAAM;YACf,IAAI,EAAE,CAAC,OAAO,CAAC;YACf,aAAa,EAAE,gBAAgB;YAC/B,cAAc,EACZ,kGAAkG;SACrG,CAAC,CAAC;QAEH,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QACtD,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;QAC9D,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;QAC1D,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CACb,yMAAyM,CAC1M,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC;QAEvE,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;YAC7C,MAAM,EAAE,CAAC,SAAS,EAAE,WAAW,EAAE;gBAC/B,SAAS,EAAE,IAAI;gBACf,gBAAgB,EAAE,IAAI;aACvB,CAAC,CAAC;YAEH,OAAO;gBACL,SAAS,EAAE,WAAW;gBACtB,UAAU,EAAE,kBAAkB;gBAC9B,kBAAkB,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE;gBAClC,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;aAC5D,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YACnD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;CACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prisma/compute-sdk",
3
- "version": "0.13.0",
3
+ "version": "0.15.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",
@@ -31,8 +31,9 @@
31
31
  },
32
32
  "dependencies": {
33
33
  "better-result": "^2.7.0",
34
+ "tar-stream": "^3.1.8",
34
35
  "tiny-invariant": "1.3.3",
35
- "tar-stream": "^3.1.8"
36
+ "ws": "^8.20.0"
36
37
  },
37
38
  "peerDependencies": {
38
39
  "@prisma/management-api-sdk": ">=1.23.0"
@@ -40,6 +41,7 @@
40
41
  "devDependencies": {
41
42
  "@types/bun": "latest",
42
43
  "@types/tar-stream": "^3.1.4",
44
+ "@types/ws": "^8.18.1",
43
45
  "typescript": "^6.0.2"
44
46
  }
45
47
  }
@@ -0,0 +1,76 @@
1
+ import { cp, mkdtemp, rm, stat } from "node:fs/promises";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ import type { BuildArtifact, BuildStrategy } from "./build-strategy.ts";
5
+ import {
6
+ hasPackageDependency,
7
+ hasRootFile,
8
+ runPackageCli,
9
+ } from "./build-strategy.ts";
10
+
11
+ const ASTRO_CONFIG_FILENAMES = [
12
+ "astro.config.js",
13
+ "astro.config.mjs",
14
+ "astro.config.cjs",
15
+ "astro.config.ts",
16
+ "astro.config.mts",
17
+ ];
18
+
19
+ /**
20
+ * Build strategy for Astro applications using the @astrojs/node adapter
21
+ * in standalone mode. Runs `astro build` and produces an artifact from `dist/`.
22
+ */
23
+ export class AstroBuild implements BuildStrategy {
24
+ readonly #appPath: string;
25
+
26
+ constructor(options: { appPath: string }) {
27
+ this.#appPath = options.appPath;
28
+ }
29
+
30
+ async canBuild(): Promise<boolean> {
31
+ return (
32
+ (await hasRootFile(this.#appPath, ASTRO_CONFIG_FILENAMES)) ||
33
+ (await hasPackageDependency(this.#appPath, ["astro"]))
34
+ );
35
+ }
36
+
37
+ async execute(): Promise<BuildArtifact> {
38
+ await runPackageCli({
39
+ appPath: this.#appPath,
40
+ cliName: "astro",
41
+ args: ["build"],
42
+ failurePrefix: "Astro",
43
+ missingMessage:
44
+ "Could not find the Astro CLI. Install it with `npm install astro` or ensure npx/bunx is available.",
45
+ });
46
+
47
+ const distDir = path.join(this.#appPath, "dist");
48
+ const entryPath = path.join(distDir, "server", "entry.mjs");
49
+ const entryStat = await stat(entryPath).catch(() => null);
50
+ if (!entryStat?.isFile()) {
51
+ throw new Error(
52
+ '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.',
53
+ );
54
+ }
55
+
56
+ const outDir = await mkdtemp(path.join(os.tmpdir(), "compute-build-"));
57
+
58
+ try {
59
+ const artifactDir = path.join(outDir, "app");
60
+ await cp(distDir, artifactDir, {
61
+ recursive: true,
62
+ verbatimSymlinks: true,
63
+ });
64
+
65
+ return {
66
+ directory: artifactDir,
67
+ entrypoint: "server/entry.mjs",
68
+ defaultPortMapping: { http: 4321 },
69
+ cleanup: () => rm(outDir, { recursive: true, force: true }),
70
+ };
71
+ } catch (error) {
72
+ await rm(outDir, { recursive: true, force: true });
73
+ throw error;
74
+ }
75
+ }
76
+ }
package/src/auto-build.ts CHANGED
@@ -1,6 +1,9 @@
1
+ import { AstroBuild } from "./astro-build.ts";
1
2
  import type { BuildArtifact, BuildStrategy } from "./build-strategy.ts";
2
3
  import { BunBuild } from "./bun-build.ts";
3
4
  import { NextjsBuild } from "./nextjs-build.ts";
5
+ import { NuxtBuild } from "./nuxt-build.ts";
6
+ import { TanstackStartBuild } from "./tanstack-start-build.ts";
4
7
 
5
8
  /**
6
9
  * Meta-strategy that auto-detects the appropriate build strategy.
@@ -12,6 +15,9 @@ export class AutoBuild implements BuildStrategy {
12
15
  constructor(options: { appPath: string; entrypoint?: string }) {
13
16
  this.#strategies = [
14
17
  new NextjsBuild({ appPath: options.appPath }),
18
+ new NuxtBuild({ appPath: options.appPath }),
19
+ new AstroBuild({ appPath: options.appPath }),
20
+ new TanstackStartBuild({ appPath: options.appPath }),
15
21
  new BunBuild({
16
22
  appPath: options.appPath,
17
23
  entrypoint: options.entrypoint,
@@ -1,4 +1,5 @@
1
- import { stat } from "node:fs/promises";
1
+ import { execFile } from "node:child_process";
2
+ import { readdir, readFile, stat } from "node:fs/promises";
2
3
  import path from "node:path";
3
4
  import type { PortMapping } from "./types.ts";
4
5
 
@@ -77,3 +78,142 @@ export class PreBuilt implements BuildStrategy {
77
78
  };
78
79
  }
79
80
  }
81
+
82
+ // ---------------------------------------------------------------------------
83
+ // Shared helpers used by framework strategies (Next, Nuxt, Astro, TanStack
84
+ // Start). Live here because they're tightly tied to the BuildStrategy surface
85
+ // (framework detection + CLI dispatch) and don't justify their own module.
86
+ // ---------------------------------------------------------------------------
87
+
88
+ /**
89
+ * True if any of `filenames` exists at the root of `appPath`. Swallows
90
+ * readdir errors (missing/unreadable dir) and returns false.
91
+ */
92
+ export async function hasRootFile(
93
+ appPath: string,
94
+ filenames: readonly string[],
95
+ ): Promise<boolean> {
96
+ let entries: string[];
97
+ try {
98
+ entries = await readdir(appPath);
99
+ } catch {
100
+ return false;
101
+ }
102
+ return entries.some((entry) => filenames.includes(entry));
103
+ }
104
+
105
+ /**
106
+ * True if any of `packageNames` is listed in `package.json`'s `dependencies`
107
+ * or `devDependencies`. Swallows missing-file / invalid-JSON errors and
108
+ * returns false.
109
+ */
110
+ export async function hasPackageDependency(
111
+ appPath: string,
112
+ packageNames: readonly string[],
113
+ ): Promise<boolean> {
114
+ let content: string;
115
+ try {
116
+ content = await readFile(path.join(appPath, "package.json"), "utf-8");
117
+ } catch {
118
+ return false;
119
+ }
120
+
121
+ let parsed: { dependencies?: unknown; devDependencies?: unknown };
122
+ try {
123
+ parsed = JSON.parse(content) as {
124
+ dependencies?: unknown;
125
+ devDependencies?: unknown;
126
+ };
127
+ } catch {
128
+ return false;
129
+ }
130
+
131
+ const deps = isRecord(parsed.dependencies) ? parsed.dependencies : {};
132
+ const devDeps = isRecord(parsed.devDependencies)
133
+ ? parsed.devDependencies
134
+ : {};
135
+
136
+ return packageNames.some((name) => name in deps || name in devDeps);
137
+ }
138
+
139
+ /**
140
+ * Run a package's CLI inside `appPath`. Tries the project-local bin first,
141
+ * then `npx <cliName>`, then `bunx <cliName>`. Each candidate that fails
142
+ * with ENOENT is skipped; other failures (e.g., build errors) re-throw
143
+ * with stderr surfaced.
144
+ *
145
+ * Throws with `missingMessage` if none of the launchers is available.
146
+ */
147
+ export async function runPackageCli(opts: {
148
+ appPath: string;
149
+ /** Executable name, e.g. "astro", "next", "nuxt", "vite". */
150
+ cliName: string;
151
+ /** Args passed to the CLI, e.g. ["build"]. */
152
+ args: string[];
153
+ /** Prefix used when surfacing a build failure, e.g. "Astro". */
154
+ failurePrefix: string;
155
+ /** Thrown when no launcher is available. */
156
+ missingMessage: string;
157
+ }): Promise<void> {
158
+ const localBin = path.join(
159
+ opts.appPath,
160
+ "node_modules",
161
+ ".bin",
162
+ opts.cliName,
163
+ );
164
+ const candidates: Array<{ command: string; args: string[] }> = [
165
+ { command: localBin, args: opts.args },
166
+ { command: "npx", args: [opts.cliName, ...opts.args] },
167
+ { command: "bunx", args: [opts.cliName, ...opts.args] },
168
+ ];
169
+
170
+ for (const { command, args } of candidates) {
171
+ try {
172
+ await exec(command, args, opts.appPath, opts.failurePrefix);
173
+ return;
174
+ } catch (error) {
175
+ if (isENOENT(error)) continue;
176
+ throw error;
177
+ }
178
+ }
179
+
180
+ throw new Error(opts.missingMessage);
181
+ }
182
+
183
+ function isRecord(value: unknown): value is Record<string, unknown> {
184
+ return typeof value === "object" && value !== null;
185
+ }
186
+
187
+ function isENOENT(error: unknown): boolean {
188
+ return (
189
+ error instanceof Error &&
190
+ "code" in error &&
191
+ (error as { code?: string }).code === "ENOENT"
192
+ );
193
+ }
194
+
195
+ function exec(
196
+ command: string,
197
+ args: string[],
198
+ cwd: string,
199
+ failurePrefix: string,
200
+ ): Promise<void> {
201
+ return new Promise((resolve, reject) => {
202
+ execFile(command, args, { cwd }, (error, _stdout, stderr) => {
203
+ if (error) {
204
+ if ("code" in error && error.code === "ENOENT") {
205
+ reject(
206
+ Object.assign(new Error(`${command} not found`), {
207
+ code: "ENOENT",
208
+ }),
209
+ );
210
+ return;
211
+ }
212
+ const message = stderr.trim() || error.message;
213
+ reject(new Error(`${failurePrefix} build failed:\n${message}`));
214
+ return;
215
+ }
216
+ resolve();
217
+ });
218
+ });
219
+ }
package/src/errors.ts CHANGED
@@ -125,6 +125,11 @@ export class InvalidOptionsError extends TaggedError("InvalidOptionsError")<{
125
125
  message: string;
126
126
  }>() {}
127
127
 
128
+ export class LogStreamError extends TaggedError("LogStreamError")<{
129
+ statusCode: number;
130
+ message: string;
131
+ }>() {}
132
+
128
133
  export type DeployError =
129
134
  | AuthenticationError
130
135
  | ApiError
package/src/index.ts CHANGED
@@ -7,12 +7,11 @@ export {
7
7
  type Result,
8
8
  TaggedError,
9
9
  } from "better-result";
10
+ export { AstroBuild } from "./astro-build.ts";
10
11
  export { AutoBuild } from "./auto-build.ts";
11
- // Build strategy
12
12
  export type { BuildArtifact, BuildStrategy } from "./build-strategy.ts";
13
13
  export { PreBuilt } from "./build-strategy.ts";
14
14
  export { BunBuild } from "./bun-build.ts";
15
- // Callbacks
16
15
  export type {
17
16
  DeployInteraction,
18
17
  DeployProgress,
@@ -45,7 +44,6 @@ export type {
45
44
  UpdateEnvOptions,
46
45
  UpdateEnvResult,
47
46
  } from "./compute-client.ts";
48
- // Core client
49
47
  export { ComputeClient } from "./compute-client.ts";
50
48
  export type {
51
49
  ApiRequestError,
@@ -56,7 +54,6 @@ export type {
56
54
  UpdateEnvError,
57
55
  VersionOperationError,
58
56
  } from "./errors.ts";
59
- // Errors
60
57
  export {
61
58
  ApiError,
62
59
  ArtifactError,
@@ -65,14 +62,25 @@ export {
65
62
  CancelledError,
66
63
  DestroyAggregateError,
67
64
  InvalidOptionsError,
65
+ LogStreamError,
68
66
  MissingArgumentError,
69
67
  NoExistingVersionError,
70
68
  NoVersionsFoundError,
71
69
  TimeoutError,
72
70
  VersionFailedError,
73
71
  } from "./errors.ts";
72
+ export type {
73
+ LogRecord,
74
+ LogStreamOptions,
75
+ StreamLogsError,
76
+ StreamRecord,
77
+ StreamResult,
78
+ TerminalRecord,
79
+ } from "./log-stream.ts";
80
+ export { streamLogs } from "./log-stream.ts";
74
81
  export { NextjsBuild } from "./nextjs-build.ts";
75
- // Domain types
82
+ export { NuxtBuild } from "./nuxt-build.ts";
83
+ export { TanstackStartBuild } from "./tanstack-start-build.ts";
76
84
  export type {
77
85
  CreateProjectResult,
78
86
  DatabaseInfo,