@prisma/cli 2.20.1 → 3.0.0-alpha.1

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 (217) hide show
  1. package/LICENSE +158 -0
  2. package/README.md +29 -28
  3. package/dist/adapters/config.js +74 -0
  4. package/dist/adapters/local-state.js +98 -0
  5. package/dist/adapters/mock-api.js +57 -0
  6. package/dist/adapters/token-storage.js +43 -0
  7. package/dist/cli.js +9 -0
  8. package/dist/cli2.js +59 -0
  9. package/dist/commands/app/index.js +216 -0
  10. package/dist/commands/auth/index.js +42 -0
  11. package/dist/commands/branch/index.js +51 -0
  12. package/dist/commands/project/index.js +45 -0
  13. package/dist/controllers/app.js +834 -0
  14. package/dist/controllers/auth.js +107 -0
  15. package/dist/controllers/branch.js +73 -0
  16. package/dist/controllers/project.js +214 -0
  17. package/dist/controllers/select-prompt-port.js +12 -0
  18. package/dist/lib/app/bun-project.js +39 -0
  19. package/dist/lib/app/env-vars.js +24 -0
  20. package/dist/lib/app/local-dev.js +150 -0
  21. package/dist/lib/app/preview-build.js +142 -0
  22. package/dist/lib/app/preview-interaction.js +38 -0
  23. package/dist/lib/app/preview-progress.js +139 -0
  24. package/dist/lib/app/preview-provider.js +232 -0
  25. package/dist/lib/auth/auth-ops.js +57 -0
  26. package/dist/lib/auth/client.js +22 -0
  27. package/dist/lib/auth/guard.js +34 -0
  28. package/dist/lib/auth/login.js +117 -0
  29. package/dist/output/patterns.js +93 -0
  30. package/dist/presenters/app.js +405 -0
  31. package/dist/presenters/auth.js +73 -0
  32. package/dist/presenters/branch.js +111 -0
  33. package/dist/presenters/project.js +84 -0
  34. package/dist/shell/command-meta.js +329 -0
  35. package/dist/shell/command-runner.js +33 -0
  36. package/dist/shell/errors.js +66 -0
  37. package/dist/shell/global-flags.js +25 -0
  38. package/dist/shell/help.js +78 -0
  39. package/dist/shell/output.js +54 -0
  40. package/dist/shell/prompt.js +31 -0
  41. package/dist/shell/runtime.js +51 -0
  42. package/dist/shell/ui.js +59 -0
  43. package/dist/use-cases/auth.js +70 -0
  44. package/dist/use-cases/branch.js +95 -0
  45. package/dist/use-cases/create-cli-gateways.js +93 -0
  46. package/dist/use-cases/project.js +75 -0
  47. package/package.json +49 -137
  48. package/build/child.js +0 -4110
  49. package/build/index.js +0 -104447
  50. package/build/public/.DS_Store +0 -0
  51. package/build/public/assets/alert.60ea9f84.svg +0 -5
  52. package/build/public/assets/array.1a36c222.svg +0 -4
  53. package/build/public/assets/boolean.9188b434.svg +0 -4
  54. package/build/public/assets/browser.21a575be.js +0 -1
  55. package/build/public/assets/browser.38b7fdb1.js +0 -1
  56. package/build/public/assets/browser.cdd2249a.js +0 -1
  57. package/build/public/assets/chevron-down.24f76e3c.svg +0 -3
  58. package/build/public/assets/cross.c2610cf5.svg +0 -11
  59. package/build/public/assets/datetime.a3bf710a.svg +0 -4
  60. package/build/public/assets/download.8d34b65a.svg +0 -4
  61. package/build/public/assets/ellipsis.a8c5a34a.svg +0 -10
  62. package/build/public/assets/enum.7ec0b64c.svg +0 -6
  63. package/build/public/assets/folder.d77b8eaf.svg +0 -6
  64. package/build/public/assets/hamburger.5fdadeac.svg +0 -4
  65. package/build/public/assets/logotype.a960b169.svg +0 -4
  66. package/build/public/assets/number.85ddf96b.svg +0 -7
  67. package/build/public/assets/object.0ba944a6.svg +0 -5
  68. package/build/public/assets/play.8811691e.svg +0 -6
  69. package/build/public/assets/plus.8fbf7ad3.svg +0 -4
  70. package/build/public/assets/read.79154521.svg +0 -1
  71. package/build/public/assets/refresh.d5448ccc.svg +0 -4
  72. package/build/public/assets/search.2ed766ce.svg +0 -7
  73. package/build/public/assets/settings.5ad25af2.svg +0 -8
  74. package/build/public/assets/string.ea615a24.svg +0 -4
  75. package/build/public/assets/tick-indeterminate.aec8a44d.svg +0 -3
  76. package/build/public/assets/tick.8cbb6a93.svg +0 -4
  77. package/build/public/assets/vendor.c4d0f081.js +0 -354
  78. package/build/public/demo.html +0 -17
  79. package/build/public/demoChunk.js +0 -2
  80. package/build/public/electron-darwin.html +0 -19
  81. package/build/public/electron-linux.html +0 -18
  82. package/build/public/electron-mac.html +0 -18
  83. package/build/public/electron-win.html +0 -17
  84. package/build/public/electron-win32.html +0 -18
  85. package/build/public/electron.html +0 -17
  86. package/build/public/electronBus.js +0 -2
  87. package/build/public/electronChunk.js +0 -2
  88. package/build/public/favicon/apple-touch-icon.png +0 -0
  89. package/build/public/favicon/favicon-16x16.png +0 -0
  90. package/build/public/favicon/favicon-32x32.png +0 -0
  91. package/build/public/favicon/prisma.png +0 -0
  92. package/build/public/favicon.svg +0 -5
  93. package/build/public/fonts/.DS_Store +0 -0
  94. package/build/public/fonts/Inter.ttf +0 -0
  95. package/build/public/fonts/RobotoMono.ttf +0 -0
  96. package/build/public/icons/.DS_Store +0 -0
  97. package/build/public/icons/alert.svg +0 -5
  98. package/build/public/icons/array.svg +0 -4
  99. package/build/public/icons/bin.svg +0 -37
  100. package/build/public/icons/boolean.svg +0 -4
  101. package/build/public/icons/check.svg +0 -3
  102. package/build/public/icons/chevron-down.svg +0 -3
  103. package/build/public/icons/code.svg +0 -4
  104. package/build/public/icons/cross.svg +0 -11
  105. package/build/public/icons/data-tool.svg +0 -5
  106. package/build/public/icons/database.svg +0 -4
  107. package/build/public/icons/datetime.svg +0 -4
  108. package/build/public/icons/double-arrow-right.svg +0 -4
  109. package/build/public/icons/download.svg +0 -4
  110. package/build/public/icons/ellipsis.svg +0 -10
  111. package/build/public/icons/enum.svg +0 -6
  112. package/build/public/icons/expand.svg +0 -4
  113. package/build/public/icons/eye.svg +0 -20
  114. package/build/public/icons/filters.svg +0 -5
  115. package/build/public/icons/folder.svg +0 -6
  116. package/build/public/icons/hamburger.svg +0 -4
  117. package/build/public/icons/icon.svg +0 -199
  118. package/build/public/icons/logo.svg +0 -199
  119. package/build/public/icons/logotype.svg +0 -4
  120. package/build/public/icons/number.svg +0 -7
  121. package/build/public/icons/object.svg +0 -5
  122. package/build/public/icons/play.svg +0 -6
  123. package/build/public/icons/plus.svg +0 -4
  124. package/build/public/icons/refresh.svg +0 -4
  125. package/build/public/icons/search.svg +0 -7
  126. package/build/public/icons/settings.svg +0 -8
  127. package/build/public/icons/string.svg +0 -4
  128. package/build/public/icons/tick-indeterminate.svg +0 -3
  129. package/build/public/icons/tick.svg +0 -4
  130. package/build/public/illustrations/.DS_Store +0 -0
  131. package/build/public/illustrations/empty.svg +0 -1
  132. package/build/public/illustrations/read.svg +0 -1
  133. package/build/public/illustrations/searching.svg +0 -1
  134. package/build/public/images/.DS_Store +0 -0
  135. package/build/public/images/icon-1024.png +0 -0
  136. package/build/public/index.css +0 -1
  137. package/build/public/index.html +0 -49
  138. package/build/public/index.js +0 -1
  139. package/build/public/main.31f688a6254e294d9128.css +0 -118
  140. package/build/public/main.31f688a6254e294d9128.css.map +0 -1
  141. package/build/public/main.364c712f32662ff0e43d.css +0 -116
  142. package/build/public/main.364c712f32662ff0e43d.css.map +0 -1
  143. package/build/public/main.42ef3fe7e97347765c91.css +0 -118
  144. package/build/public/main.42ef3fe7e97347765c91.css.map +0 -1
  145. package/build/public/main.503446defafe7aeca2f3.css +0 -116
  146. package/build/public/main.503446defafe7aeca2f3.css.map +0 -1
  147. package/build/public/main.c50a3b5980fe26f78b65.css +0 -118
  148. package/build/public/main.c50a3b5980fe26f78b65.css.map +0 -1
  149. package/build/public/main.cda25e5813776c2af295.css +0 -116
  150. package/build/public/main.cda25e5813776c2af295.css.map +0 -1
  151. package/build/public/main.dbac3b290f78404ff579.css +0 -116
  152. package/build/public/main.dbac3b290f78404ff579.css.map +0 -1
  153. package/build/public/main.f8ce44e122e5e2b8f778.css +0 -118
  154. package/build/public/main.f8ce44e122e5e2b8f778.css.map +0 -1
  155. package/build/public/main.fc9ea7521a4aecce1a77.css +0 -118
  156. package/build/public/main.fc9ea7521a4aecce1a77.css.map +0 -1
  157. package/build/public/main.js +0 -403
  158. package/build/public/main.js.map +0 -1
  159. package/build/public/mainChunk.0a84f3ba4d2ab481e877.css +0 -116
  160. package/build/public/mainChunk.1b327d58afbddc917bce.css +0 -118
  161. package/build/public/mainChunk.2cdf583b2bd51aa67587.css +0 -118
  162. package/build/public/mainChunk.544af00f7e9ffcbe782c.css +0 -118
  163. package/build/public/mainChunk.56f96a13868b2b4a53be.css +0 -118
  164. package/build/public/mainChunk.5cee429bfbf06e7ecb39.css +0 -118
  165. package/build/public/mainChunk.a862474ed4cdb421ffa2.css +0 -118
  166. package/build/public/mainChunk.ada34153c4911b5ac22b.css +0 -118
  167. package/build/public/mainChunk.c16a8d01b2c49b2f2751.css +0 -118
  168. package/build/public/mainChunk.ca4a878d5478b9320be8.css +0 -116
  169. package/build/public/mainChunk.e3adc8758b4395546cef.css +0 -116
  170. package/build/public/mainChunk.f2c59fcbfc455d8b9de5.css +0 -118
  171. package/build/public/mainChunk.js +0 -396
  172. package/build/public/manifest.json +0 -34
  173. package/build/public/preview.html +0 -16
  174. package/build/public/previewBus.js +0 -2
  175. package/build/public/previewChunk.js +0 -2
  176. package/build/public/projects.html +0 -86
  177. package/build/public/server.html +0 -16
  178. package/build/public/serverBus.js +0 -2
  179. package/build/public/serverChunk.js +0 -2
  180. package/build/public/splash.html +0 -17
  181. package/build/public/studioBundle.828f34b1781061528841.css +0 -118
  182. package/build/public/studioBundle.bfe9138b2e0293fcb7da.css +0 -118
  183. package/build/public/studioBundle.c5b256eede880e502aac.css +0 -118
  184. package/build/public/studioBundle.e43df511c8e2e368900a.css +0 -118
  185. package/build/public/studioBundle.e69382554c2a2942ae32.css +0 -118
  186. package/build/public/studioBundle.ee21aa56a3999a2b380b.css +0 -118
  187. package/build/public/studioBundle.js +0 -396
  188. package/build/public/vercel.html +0 -16
  189. package/build/public/vercelChunk.js +0 -2
  190. package/build/public/views/index.pug +0 -89
  191. package/build/xdg-open +0 -1066
  192. package/install/index.js +0 -5
  193. package/preinstall/index.js +0 -46
  194. package/prisma-client/README.md +0 -27
  195. package/prisma-client/generator-build/.DS_Store +0 -0
  196. package/prisma-client/generator-build/index.js +0 -79697
  197. package/prisma-client/index-browser.js +0 -3
  198. package/prisma-client/index.d.ts +0 -1
  199. package/prisma-client/index.js +0 -11
  200. package/prisma-client/package.json +0 -138
  201. package/prisma-client/runtime/index-browser.d.ts +0 -267
  202. package/prisma-client/runtime/index-browser.js +0 -2273
  203. package/prisma-client/runtime/index.d.ts +0 -1018
  204. package/prisma-client/runtime/index.js +0 -35028
  205. package/prisma-client/scripts/backup-index-browser.js +0 -3
  206. package/prisma-client/scripts/backup-index.d.ts +0 -1
  207. package/prisma-client/scripts/backup-index.js +0 -11
  208. package/prisma-client/scripts/colors.js +0 -180
  209. package/prisma-client/scripts/default-index-browser.js +0 -12
  210. package/prisma-client/scripts/default-index.d.ts +0 -47
  211. package/prisma-client/scripts/default-index.js +0 -12
  212. package/prisma-client/scripts/get-packed-client.js +0 -12
  213. package/prisma-client/scripts/mock-fs.js +0 -14
  214. package/prisma-client/scripts/postinstall.d.ts +0 -5
  215. package/prisma-client/scripts/postinstall.js +0 -398
  216. package/scripts/install-entry.js +0 -8
  217. package/scripts/preinstall-entry.js +0 -9
@@ -0,0 +1,142 @@
1
+ import { resolveBunEntrypoint } from "./bun-project.js";
2
+ import path from "node:path";
3
+ import { cp, readdir, readlink, rm, stat } from "node:fs/promises";
4
+ import { AstroBuild, BunBuild, NextjsBuild, NuxtBuild, TanstackStartBuild } from "@prisma/compute-sdk";
5
+ //#region src/lib/app/preview-build.ts
6
+ const PREVIEW_BUILD_TYPES = [
7
+ "auto",
8
+ "bun",
9
+ "nextjs",
10
+ "nuxt",
11
+ "astro",
12
+ "tanstack-start"
13
+ ];
14
+ const RESOLVED_PREVIEW_BUILD_TYPES = PREVIEW_BUILD_TYPES.filter((buildType) => buildType !== "auto");
15
+ var PreviewBuildStrategy = class {
16
+ #appPath;
17
+ #entrypoint;
18
+ #buildType;
19
+ constructor(options) {
20
+ this.#appPath = options.appPath;
21
+ this.#entrypoint = options.entrypoint;
22
+ this.#buildType = options.buildType ?? "auto";
23
+ }
24
+ async canBuild() {
25
+ const { strategy } = await resolvePreviewBuildStrategy({
26
+ appPath: this.#appPath,
27
+ entrypoint: this.#entrypoint,
28
+ buildType: this.#buildType
29
+ });
30
+ return strategy.canBuild();
31
+ }
32
+ async execute() {
33
+ const { artifact } = await executePreviewBuild({
34
+ appPath: this.#appPath,
35
+ entrypoint: this.#entrypoint,
36
+ buildType: this.#buildType
37
+ });
38
+ return artifact;
39
+ }
40
+ };
41
+ async function executePreviewBuild(options) {
42
+ const { strategy, buildType } = await resolvePreviewBuildStrategy({
43
+ appPath: options.appPath,
44
+ entrypoint: options.entrypoint,
45
+ buildType: options.buildType ?? "auto"
46
+ });
47
+ const artifact = await strategy.execute();
48
+ try {
49
+ await normalizeArtifactSymlinks(artifact.directory, options.appPath);
50
+ return {
51
+ artifact,
52
+ buildType
53
+ };
54
+ } catch (error) {
55
+ await artifact.cleanup?.().catch(() => void 0);
56
+ throw error;
57
+ }
58
+ }
59
+ async function resolvePreviewBuildStrategy(options) {
60
+ if (options.buildType !== "auto") {
61
+ const strategy = await createPreviewBuildStrategy({
62
+ appPath: options.appPath,
63
+ entrypoint: options.entrypoint,
64
+ buildType: options.buildType
65
+ });
66
+ return {
67
+ buildType: options.buildType,
68
+ strategy
69
+ };
70
+ }
71
+ for (const buildType of RESOLVED_PREVIEW_BUILD_TYPES) {
72
+ if (buildType === "bun") continue;
73
+ const strategy = await createPreviewBuildStrategy({
74
+ appPath: options.appPath,
75
+ entrypoint: options.entrypoint,
76
+ buildType
77
+ });
78
+ if (await strategy.canBuild()) return {
79
+ buildType,
80
+ strategy
81
+ };
82
+ }
83
+ return {
84
+ buildType: "bun",
85
+ strategy: await createPreviewBuildStrategy({
86
+ appPath: options.appPath,
87
+ entrypoint: options.entrypoint,
88
+ buildType: "bun"
89
+ })
90
+ };
91
+ }
92
+ async function createPreviewBuildStrategy(options) {
93
+ switch (options.buildType) {
94
+ case "nextjs": return new NextjsBuild({ appPath: options.appPath });
95
+ case "nuxt": return new NuxtBuild({ appPath: options.appPath });
96
+ case "astro": return new AstroBuild({ appPath: options.appPath });
97
+ case "tanstack-start": return new TanstackStartBuild({ appPath: options.appPath });
98
+ case "bun": {
99
+ const entrypoint = await resolveBunEntrypoint(options.appPath, options.entrypoint);
100
+ return new BunBuild({
101
+ appPath: options.appPath,
102
+ entrypoint
103
+ });
104
+ }
105
+ }
106
+ }
107
+ async function normalizeArtifactSymlinks(artifactDir, appPath) {
108
+ const normalizedArtifactDir = path.resolve(artifactDir);
109
+ const normalizedAppPath = path.resolve(appPath);
110
+ await walkDirectory(normalizedArtifactDir);
111
+ async function walkDirectory(directory) {
112
+ const entries = await readdir(directory, { withFileTypes: true });
113
+ for (const entry of entries) {
114
+ const fullPath = path.join(directory, entry.name);
115
+ if (entry.isDirectory()) {
116
+ await walkDirectory(fullPath);
117
+ continue;
118
+ }
119
+ if (!entry.isSymbolicLink()) continue;
120
+ const target = await readlink(fullPath);
121
+ const resolvedTarget = path.resolve(path.dirname(fullPath), target);
122
+ if (isPathWithin(normalizedArtifactDir, resolvedTarget)) continue;
123
+ if (!isPathWithin(normalizedAppPath, resolvedTarget)) throw new Error(`Build artifact symlink escapes the app directory: ${resolvedTarget}`);
124
+ const targetStat = await stat(resolvedTarget);
125
+ await rm(fullPath, {
126
+ force: true,
127
+ recursive: true
128
+ });
129
+ await cp(resolvedTarget, fullPath, {
130
+ recursive: targetStat.isDirectory(),
131
+ dereference: true
132
+ });
133
+ if (targetStat.isDirectory()) await walkDirectory(fullPath);
134
+ }
135
+ }
136
+ }
137
+ function isPathWithin(rootPath, candidatePath) {
138
+ const relativePath = path.relative(rootPath, candidatePath);
139
+ return relativePath === "" || !relativePath.startsWith(`..${path.sep}`) && relativePath !== ".." && !path.isAbsolute(relativePath);
140
+ }
141
+ //#endregion
142
+ export { PREVIEW_BUILD_TYPES, PreviewBuildStrategy, RESOLVED_PREVIEW_BUILD_TYPES, executePreviewBuild };
@@ -0,0 +1,38 @@
1
+ import { selectPrompt, textPrompt } from "../../shell/prompt.js";
2
+ //#region src/lib/app/preview-interaction.ts
3
+ const CREATE_NEW_APP = "__create_new_app__";
4
+ const PREVIEW_DEFAULT_REGION = "eu-central-1";
5
+ function createPreviewDeployInteraction(context) {
6
+ return {
7
+ async selectService(services) {
8
+ const sorted = services.slice().sort((left, right) => left.name.localeCompare(right.name) || left.id.localeCompare(right.id));
9
+ const selection = await selectPrompt({
10
+ input: context.runtime.stdin,
11
+ output: context.runtime.stderr,
12
+ message: "Select an app",
13
+ choices: [...sorted.map((service) => ({
14
+ label: service.name,
15
+ value: service.id
16
+ })), {
17
+ label: "Create a new app",
18
+ value: CREATE_NEW_APP
19
+ }]
20
+ });
21
+ return selection === CREATE_NEW_APP ? null : selection;
22
+ },
23
+ async provideServiceName() {
24
+ return textPrompt({
25
+ input: context.runtime.stdin,
26
+ output: context.runtime.stderr,
27
+ message: "App name",
28
+ placeholder: "hello-world",
29
+ validate: (value) => !value?.trim() ? "App name is required" : void 0
30
+ }).then((value) => value.trim());
31
+ },
32
+ async selectRegion(_regions) {
33
+ return PREVIEW_DEFAULT_REGION;
34
+ }
35
+ };
36
+ }
37
+ //#endregion
38
+ export { PREVIEW_DEFAULT_REGION, createPreviewDeployInteraction };
@@ -0,0 +1,139 @@
1
+ //#region src/lib/app/preview-progress.ts
2
+ function createPreviewDeployProgress(output, enabled) {
3
+ if (!enabled) return;
4
+ const write = (line) => {
5
+ output.write(`${line}\n`);
6
+ };
7
+ return {
8
+ onBuildStart() {
9
+ write("Building application...");
10
+ },
11
+ onBuildComplete() {
12
+ write("Build complete.");
13
+ },
14
+ onArchiveCreating() {
15
+ write("Creating deployment artifact...");
16
+ },
17
+ onArchiveReady(byteLength) {
18
+ write(`Artifact ready (${(byteLength / 1024).toFixed(1)} KB).`);
19
+ },
20
+ onVersionCreated(versionId) {
21
+ write(`Deployment ${versionId} created.`);
22
+ },
23
+ onUploadComplete() {
24
+ write("Upload complete.");
25
+ },
26
+ onStartRequested() {
27
+ write("Starting deployment...");
28
+ },
29
+ onStatusChange(status) {
30
+ write(`Status: ${status}`);
31
+ },
32
+ onRunning(url) {
33
+ if (url) {
34
+ write(`Deployment is running at ${url}.`);
35
+ return;
36
+ }
37
+ write("Deployment is running.");
38
+ },
39
+ onPromoteStart() {
40
+ write("Promoting deployment...");
41
+ },
42
+ onPromoted(url) {
43
+ if (url) {
44
+ write(`Promoted to ${url}.`);
45
+ return;
46
+ }
47
+ write("Promotion complete.");
48
+ },
49
+ onPromoteFailed(error) {
50
+ write(`Promotion failed${error?.message ? `: ${error.message}` : "."}`);
51
+ },
52
+ onOldVersionStopping(versionId) {
53
+ write(`Stopping previous deployment ${versionId}...`);
54
+ },
55
+ onOldVersionStopped(versionId) {
56
+ write(`Previous deployment ${versionId} stopped.`);
57
+ },
58
+ onOldVersionStopFailed(versionId) {
59
+ write(`Failed to stop previous deployment ${versionId} (non-fatal).`);
60
+ },
61
+ onOldVersionDeleting(versionId) {
62
+ write(`Deleting previous deployment ${versionId}...`);
63
+ },
64
+ onOldVersionDeleted(versionId) {
65
+ write(`Previous deployment ${versionId} deleted.`);
66
+ },
67
+ onOldVersionDeleteFailed(versionId) {
68
+ write(`Failed to delete previous deployment ${versionId} (non-fatal).`);
69
+ },
70
+ onCleanupDanglingVersion(versionId) {
71
+ write(`Cleaning up deployment ${versionId}...`);
72
+ },
73
+ onCleanupDanglingVersionComplete(versionId) {
74
+ write(`Deployment ${versionId} cleaned up.`);
75
+ },
76
+ onCleanupDanglingVersionFailed(versionId) {
77
+ write(`Failed to clean up deployment ${versionId}.`);
78
+ }
79
+ };
80
+ }
81
+ function createPreviewPromoteProgress(output, enabled) {
82
+ if (!enabled) return;
83
+ const write = (line) => {
84
+ output.write(`${line}\n`);
85
+ };
86
+ return {
87
+ onVersionStarting(versionId) {
88
+ write(`Starting deployment ${versionId}...`);
89
+ },
90
+ onVersionStartRequested() {
91
+ write("Requesting deployment start...");
92
+ },
93
+ onStatusChange(status) {
94
+ write(`Status: ${status}`);
95
+ },
96
+ onVersionRunning() {
97
+ write("Deployment is running.");
98
+ },
99
+ onPromoteStart() {
100
+ write("Promoting deployment...");
101
+ },
102
+ onPromoted(url) {
103
+ if (url) {
104
+ write(`Promoted to ${url}.`);
105
+ return;
106
+ }
107
+ write("Promotion complete.");
108
+ },
109
+ onPromoteFailed(error) {
110
+ write(`Promotion failed${error?.message ? `: ${error.message}` : "."}`);
111
+ }
112
+ };
113
+ }
114
+ function createPreviewUpdateEnvProgress(output, enabled) {
115
+ if (!enabled) return;
116
+ const write = (line) => {
117
+ output.write(`${line}\n`);
118
+ };
119
+ return {
120
+ onVersionCreated(versionId) {
121
+ write(`Creating updated deployment ${versionId}...`);
122
+ },
123
+ onStartRequested() {
124
+ write("Starting deployment...");
125
+ },
126
+ onStatusChange(status) {
127
+ write(`Status: ${status}`);
128
+ },
129
+ onRunning(url) {
130
+ if (url) {
131
+ write(`Deployment is running at ${url}.`);
132
+ return;
133
+ }
134
+ write("Deployment is running.");
135
+ }
136
+ };
137
+ }
138
+ //#endregion
139
+ export { createPreviewDeployProgress, createPreviewPromoteProgress, createPreviewUpdateEnvProgress };
@@ -0,0 +1,232 @@
1
+ import { envVarNames } from "./env-vars.js";
2
+ import { PreviewBuildStrategy } from "./preview-build.js";
3
+ import path from "node:path";
4
+ import { ApiError, ComputeClient } from "@prisma/compute-sdk";
5
+ //#region src/lib/app/preview-provider.ts
6
+ function createPreviewAppProvider(client) {
7
+ const sdk = new ComputeClient(client);
8
+ return {
9
+ async createProject(options) {
10
+ const projectResult = await sdk.createProject({ name: options.name });
11
+ if (projectResult.isErr()) throw new Error(projectResult.error.message);
12
+ return {
13
+ id: projectResult.value.id,
14
+ name: projectResult.value.name
15
+ };
16
+ },
17
+ async listApps(projectId) {
18
+ const servicesResult = await sdk.listServices({ projectId });
19
+ if (servicesResult.isErr()) throw new Error(servicesResult.error.message);
20
+ return (await Promise.all(servicesResult.value.map(async (service) => {
21
+ const detailResult = await sdk.showService({ serviceId: service.id });
22
+ return detailResult.isOk() ? detailResult.value : {
23
+ id: service.id,
24
+ name: service.name,
25
+ region: service.region,
26
+ latestVersionId: null,
27
+ serviceEndpointDomain: void 0
28
+ };
29
+ }))).map((service) => ({
30
+ id: service.id,
31
+ name: service.name,
32
+ region: service.region ?? null,
33
+ liveDeploymentId: service.latestVersionId ?? null,
34
+ liveUrl: toAbsoluteUrl(service.serviceEndpointDomain ?? null)
35
+ }));
36
+ },
37
+ async removeApp(appId) {
38
+ const appResult = await sdk.showService({ serviceId: appId });
39
+ if (appResult.isErr()) throw new Error(appResult.error.message);
40
+ const destroyResult = await sdk.destroyService({
41
+ serviceId: appId,
42
+ keepService: false,
43
+ timeoutSeconds: 120,
44
+ pollIntervalMs: 2e3
45
+ });
46
+ if (destroyResult.isErr()) throw new Error(destroyResult.error.message);
47
+ return {
48
+ id: appResult.value.id,
49
+ name: appResult.value.name
50
+ };
51
+ },
52
+ async promoteDeployment(options) {
53
+ const promoteResult = await sdk.promote({
54
+ serviceId: options.appId,
55
+ versionId: options.deploymentId,
56
+ timeoutSeconds: 120,
57
+ pollIntervalMs: 2e3,
58
+ progress: options.progress
59
+ });
60
+ if (promoteResult.isErr()) throw new Error(promoteResult.error.message);
61
+ },
62
+ async deployApp(options) {
63
+ const deployResult = await sdk.deploy({
64
+ strategy: new PreviewBuildStrategy({
65
+ appPath: path.resolve(options.cwd),
66
+ entrypoint: options.entrypoint,
67
+ buildType: options.buildType
68
+ }),
69
+ projectId: options.projectId,
70
+ serviceId: options.appId,
71
+ serviceName: options.appName,
72
+ region: options.region,
73
+ portMapping: options.portMapping,
74
+ envVars: options.envVars,
75
+ timeoutSeconds: 120,
76
+ pollIntervalMs: 2e3,
77
+ interaction: options.interaction,
78
+ progress: options.progress
79
+ });
80
+ if (deployResult.isErr()) throw new Error(deployResult.error.message);
81
+ const deployed = deployResult.value;
82
+ return {
83
+ projectId: deployed.projectId,
84
+ app: {
85
+ id: deployed.serviceId,
86
+ name: deployed.serviceName,
87
+ region: deployed.region ?? null,
88
+ liveDeploymentId: deployed.versionId,
89
+ liveUrl: toAbsoluteUrl(deployed.serviceEndpointDomain ?? null)
90
+ },
91
+ deployment: {
92
+ id: deployed.versionId,
93
+ status: "running",
94
+ url: toAbsoluteUrl(deployed.serviceEndpointDomain ?? deployed.versionEndpointDomain ?? null)
95
+ }
96
+ };
97
+ },
98
+ async updateAppEnv(options) {
99
+ const updateResult = await sdk.updateEnv({
100
+ serviceId: options.appId,
101
+ envVars: options.envVars,
102
+ timeoutSeconds: 120,
103
+ pollIntervalMs: 2e3,
104
+ progress: options.progress
105
+ });
106
+ if (updateResult.isErr()) throw new Error(updateResult.error.message);
107
+ const promoteResult = await sdk.promote({
108
+ serviceId: options.appId,
109
+ versionId: updateResult.value.versionId,
110
+ timeoutSeconds: 120,
111
+ pollIntervalMs: 2e3,
112
+ progress: options.promoteProgress
113
+ });
114
+ if (promoteResult.isErr()) throw new Error(promoteResult.error.message);
115
+ const [serviceResult, versionResult] = await Promise.all([sdk.showService({ serviceId: options.appId }), sdk.showVersion({ versionId: updateResult.value.versionId })]);
116
+ if (serviceResult.isErr()) throw new Error(serviceResult.error.message);
117
+ if (versionResult.isErr()) throw new Error(versionResult.error.message);
118
+ return {
119
+ projectId: updateResult.value.projectId,
120
+ app: {
121
+ id: serviceResult.value.id,
122
+ name: serviceResult.value.name,
123
+ region: serviceResult.value.region ?? null,
124
+ liveDeploymentId: serviceResult.value.latestVersionId ?? null,
125
+ liveUrl: toAbsoluteUrl(serviceResult.value.serviceEndpointDomain ?? null)
126
+ },
127
+ deployment: {
128
+ id: versionResult.value.id,
129
+ status: versionResult.value.status,
130
+ createdAt: versionResult.value.createdAt,
131
+ url: toAbsoluteUrl(serviceResult.value.serviceEndpointDomain ?? versionResult.value.previewDomain ?? null),
132
+ live: true
133
+ },
134
+ variables: envVarNames(versionResult.value.envVars)
135
+ };
136
+ },
137
+ async listAppEnvNames(options) {
138
+ const [serviceResult, versionResult] = await Promise.all([sdk.showService({ serviceId: options.appId }), sdk.showVersion({ versionId: options.deploymentId })]);
139
+ if (serviceResult.isErr()) throw new Error(serviceResult.error.message);
140
+ if (versionResult.isErr()) throw new Error(versionResult.error.message);
141
+ return {
142
+ projectId: serviceResult.value.projectId,
143
+ app: {
144
+ id: serviceResult.value.id,
145
+ name: serviceResult.value.name,
146
+ region: serviceResult.value.region ?? null,
147
+ liveDeploymentId: serviceResult.value.latestVersionId ?? null,
148
+ liveUrl: toAbsoluteUrl(serviceResult.value.serviceEndpointDomain ?? null)
149
+ },
150
+ deployment: {
151
+ id: versionResult.value.id,
152
+ status: versionResult.value.status,
153
+ createdAt: versionResult.value.createdAt,
154
+ url: toAbsoluteUrl(versionResult.value.previewDomain ?? null),
155
+ live: serviceResult.value.latestVersionId === versionResult.value.id
156
+ },
157
+ variables: envVarNames(versionResult.value.envVars)
158
+ };
159
+ },
160
+ async listDeployments(appId) {
161
+ const [appResult, versionsResult] = await Promise.all([sdk.showService({ serviceId: appId }), sdk.listVersions({ serviceId: appId })]);
162
+ if (appResult.isErr()) throw new Error(appResult.error.message);
163
+ if (versionsResult.isErr()) throw new Error(versionsResult.error.message);
164
+ return {
165
+ app: {
166
+ id: appResult.value.id,
167
+ name: appResult.value.name,
168
+ region: appResult.value.region ?? null,
169
+ liveDeploymentId: appResult.value.latestVersionId ?? null,
170
+ liveUrl: toAbsoluteUrl(appResult.value.serviceEndpointDomain ?? null)
171
+ },
172
+ deployments: versionsResult.value.slice().sort((left, right) => {
173
+ const byDate = right.createdAt.localeCompare(left.createdAt);
174
+ return byDate !== 0 ? byDate : right.id.localeCompare(left.id);
175
+ }).map((deployment) => ({
176
+ id: deployment.id,
177
+ status: deployment.status,
178
+ createdAt: deployment.createdAt,
179
+ url: toAbsoluteUrl(deployment.previewDomain ?? null),
180
+ live: null
181
+ }))
182
+ };
183
+ },
184
+ async showDeployment(deploymentId) {
185
+ const deploymentResult = await sdk.showVersion({ versionId: deploymentId });
186
+ if (deploymentResult.isErr()) {
187
+ if (ApiError.is(deploymentResult.error) && deploymentResult.error.statusCode === 404) return null;
188
+ throw new Error(deploymentResult.error.message);
189
+ }
190
+ return {
191
+ app: await findAppForDeployment(sdk, deploymentId),
192
+ deployment: {
193
+ id: deploymentResult.value.id,
194
+ status: deploymentResult.value.status,
195
+ createdAt: deploymentResult.value.createdAt,
196
+ url: toAbsoluteUrl(deploymentResult.value.previewDomain ?? null),
197
+ live: null
198
+ }
199
+ };
200
+ }
201
+ };
202
+ }
203
+ async function findAppForDeployment(sdk, deploymentId) {
204
+ const projectsResult = await sdk.listProjects();
205
+ if (projectsResult.isErr()) throw new Error(projectsResult.error.message);
206
+ for (const project of projectsResult.value) {
207
+ const servicesResult = await sdk.listServices({ projectId: project.id });
208
+ if (servicesResult.isErr()) throw new Error(servicesResult.error.message);
209
+ for (const service of servicesResult.value) {
210
+ const detailResult = await sdk.showService({ serviceId: service.id });
211
+ if (detailResult.isErr()) throw new Error(detailResult.error.message);
212
+ const app = {
213
+ id: detailResult.value.id,
214
+ name: detailResult.value.name,
215
+ region: detailResult.value.region ?? null,
216
+ liveDeploymentId: detailResult.value.latestVersionId ?? null,
217
+ liveUrl: toAbsoluteUrl(detailResult.value.serviceEndpointDomain ?? null)
218
+ };
219
+ if (app.liveDeploymentId === deploymentId) return app;
220
+ const versionsResult = await sdk.listVersions({ serviceId: service.id });
221
+ if (versionsResult.isErr()) throw new Error(versionsResult.error.message);
222
+ if (versionsResult.value.some((version) => version.id === deploymentId)) return app;
223
+ }
224
+ }
225
+ return null;
226
+ }
227
+ function toAbsoluteUrl(url) {
228
+ if (!url) return null;
229
+ return url.startsWith("https://") || url.startsWith("http://") ? url : `https://${url}`;
230
+ }
231
+ //#endregion
232
+ export { createPreviewAppProvider };
@@ -0,0 +1,57 @@
1
+ import { FileTokenStorage } from "../../adapters/token-storage.js";
2
+ import { requireComputeAuth } from "./guard.js";
3
+ import { login } from "./login.js";
4
+ //#region src/lib/auth/auth-ops.ts
5
+ function decodeJwtPayload(token) {
6
+ try {
7
+ const payload = token.split(".")[1];
8
+ if (!payload) return {};
9
+ return JSON.parse(Buffer.from(payload, "base64url").toString("utf8"));
10
+ } catch {
11
+ return {};
12
+ }
13
+ }
14
+ async function performLogin(env) {
15
+ await login({
16
+ tokenStorage: new FileTokenStorage(env),
17
+ env
18
+ });
19
+ }
20
+ async function readAuthState(env) {
21
+ const tokens = await new FileTokenStorage(env).getTokens();
22
+ if (!tokens) return {
23
+ authenticated: false,
24
+ provider: null,
25
+ user: null,
26
+ workspace: null,
27
+ linkedProjectId: null
28
+ };
29
+ const claims = decodeJwtPayload(tokens.accessToken);
30
+ const client = await requireComputeAuth(env);
31
+ let workspaceId = tokens.workspaceId;
32
+ let workspaceName = tokens.workspaceId;
33
+ if (client) try {
34
+ const { data } = await client.GET("/v1/workspaces/{id}", { params: { path: { id: tokens.workspaceId } } });
35
+ if (data?.data?.id) workspaceId = data.data.id;
36
+ if (data?.data?.name) workspaceName = data.data.name;
37
+ } catch {}
38
+ return {
39
+ authenticated: true,
40
+ provider: null,
41
+ user: {
42
+ id: claims.sub ?? "",
43
+ name: claims.name ?? "",
44
+ email: claims.email ?? ""
45
+ },
46
+ workspace: {
47
+ id: workspaceId,
48
+ name: workspaceName
49
+ },
50
+ linkedProjectId: null
51
+ };
52
+ }
53
+ async function performLogout(env) {
54
+ await new FileTokenStorage(env).clearTokens();
55
+ }
56
+ //#endregion
57
+ export { performLogin, performLogout, readAuthState };
@@ -0,0 +1,22 @@
1
+ import path from "node:path";
2
+ import os from "node:os";
3
+ //#region src/lib/auth/client.ts
4
+ const CLIENT_ID = "cmm3lndn701oo0uefvxzo0ivw";
5
+ const SERVICE_TOKEN_ENV_VAR = "PRISMA_API_TOKEN";
6
+ const AUTH_FILE_ENV_VAR = "PRISMA_COMPUTE_AUTH_FILE";
7
+ function getApiBaseUrl(env = process.env) {
8
+ return env.PRISMA_MANAGEMENT_API_URL?.trim() || "https://api.prisma.io";
9
+ }
10
+ function getAuthFilePath(env = process.env) {
11
+ const configured = env[AUTH_FILE_ENV_VAR];
12
+ if (configured?.trim()) return path.resolve(configured);
13
+ if (process.platform === "darwin") return path.join(os.homedir(), "Library", "Application Support", "prisma", "auth.json");
14
+ if (process.platform === "win32") {
15
+ const appData = env.APPDATA ?? path.join(os.homedir(), "AppData", "Roaming");
16
+ return path.join(appData, "prisma", "auth.json");
17
+ }
18
+ const xdgConfigHome = env.XDG_CONFIG_HOME ?? path.join(os.homedir(), ".config");
19
+ return path.join(xdgConfigHome, "prisma", "auth.json");
20
+ }
21
+ //#endregion
22
+ export { CLIENT_ID, SERVICE_TOKEN_ENV_VAR, getApiBaseUrl, getAuthFilePath };
@@ -0,0 +1,34 @@
1
+ import { CLIENT_ID, SERVICE_TOKEN_ENV_VAR, getApiBaseUrl } from "./client.js";
2
+ import { FileTokenStorage } from "../../adapters/token-storage.js";
3
+ import { createManagementApiClient, createManagementApiSdk } from "@prisma/management-api-sdk";
4
+ //#region src/lib/auth/guard.ts
5
+ /**
6
+ * Resolve authentication and return a ManagementApiClient.
7
+ *
8
+ * Priority:
9
+ * 1. PRISMA_API_TOKEN env var → service token (CI / headless)
10
+ * 2. Stored OAuth tokens → SDK with auto-refresh
11
+ *
12
+ * Returns null if not authenticated.
13
+ */
14
+ async function requireComputeAuth(env = process.env) {
15
+ const rawToken = env[SERVICE_TOKEN_ENV_VAR];
16
+ if (rawToken !== void 0) {
17
+ const token = rawToken.trim();
18
+ if (token.length === 0) throw new Error(`${SERVICE_TOKEN_ENV_VAR} is set but empty. Provide a valid token or unset the variable.`);
19
+ return createManagementApiClient({
20
+ baseUrl: getApiBaseUrl(env),
21
+ token
22
+ });
23
+ }
24
+ const tokenStorage = new FileTokenStorage(env);
25
+ if (!await tokenStorage.getTokens()) return null;
26
+ return createManagementApiSdk({
27
+ clientId: CLIENT_ID,
28
+ redirectUri: "http://localhost:0/auth/callback",
29
+ tokenStorage,
30
+ apiBaseUrl: getApiBaseUrl(env)
31
+ }).client;
32
+ }
33
+ //#endregion
34
+ export { requireComputeAuth };