@prisma/cli 3.0.0-beta.2 → 3.0.0-beta.21

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 (87) hide show
  1. package/README.md +5 -16
  2. package/dist/adapters/git.js +8 -3
  3. package/dist/adapters/local-state.js +26 -7
  4. package/dist/adapters/mock-api.js +81 -2
  5. package/dist/adapters/token-storage.js +344 -25
  6. package/dist/cli.js +18 -3
  7. package/dist/cli2.js +12 -4
  8. package/dist/commands/agent/index.js +60 -0
  9. package/dist/commands/app/index.js +90 -61
  10. package/dist/commands/auth/index.js +55 -2
  11. package/dist/commands/branch/index.js +2 -27
  12. package/dist/commands/build/index.js +29 -0
  13. package/dist/commands/database/index.js +159 -0
  14. package/dist/commands/env.js +8 -4
  15. package/dist/commands/git/index.js +1 -1
  16. package/dist/commands/project/index.js +1 -1
  17. package/dist/controllers/agent.js +228 -0
  18. package/dist/controllers/app-env-api.js +55 -0
  19. package/dist/controllers/app-env-file.js +181 -0
  20. package/dist/controllers/app-env.js +286 -131
  21. package/dist/controllers/app.js +849 -309
  22. package/dist/controllers/auth.js +255 -11
  23. package/dist/controllers/branch.js +78 -48
  24. package/dist/controllers/build.js +88 -0
  25. package/dist/controllers/database.js +318 -0
  26. package/dist/controllers/project.js +156 -87
  27. package/dist/controllers/select-prompt-port.js +1 -0
  28. package/dist/lib/agent/cli-command.js +17 -0
  29. package/dist/lib/agent/constants.js +12 -0
  30. package/dist/lib/agent/package-manager.js +99 -0
  31. package/dist/lib/agent/setup-status.js +83 -0
  32. package/dist/lib/app/app-interaction.js +5 -0
  33. package/dist/lib/app/{preview-provider.js → app-provider.js} +220 -104
  34. package/dist/lib/app/branch-database-api.js +102 -0
  35. package/dist/lib/app/branch-database-deploy.js +326 -0
  36. package/dist/lib/app/branch-database.js +216 -0
  37. package/dist/lib/app/build-settings.js +93 -0
  38. package/dist/lib/app/build.js +82 -0
  39. package/dist/lib/app/bun-project.js +15 -9
  40. package/dist/lib/app/compute-config.js +145 -0
  41. package/dist/lib/app/deploy-plan.js +59 -0
  42. package/dist/lib/app/{preview-progress.js → deploy-progress.js} +12 -12
  43. package/dist/lib/app/env-config.js +1 -1
  44. package/dist/lib/app/env-file.js +82 -0
  45. package/dist/lib/app/env-vars.js +28 -2
  46. package/dist/lib/app/local-dev.js +8 -49
  47. package/dist/lib/app/production-deploy-gate.js +162 -0
  48. package/dist/lib/app/read-branch.js +30 -0
  49. package/dist/lib/auth/auth-ops.js +38 -23
  50. package/dist/lib/auth/guard.js +6 -2
  51. package/dist/lib/auth/login.js +117 -15
  52. package/dist/lib/database/provider.js +167 -0
  53. package/dist/lib/diagnostics.js +15 -0
  54. package/dist/lib/fs/home-path.js +24 -0
  55. package/dist/lib/git/local-branch.js +53 -0
  56. package/dist/lib/git/local-status.js +57 -0
  57. package/dist/lib/project/interactive-setup.js +2 -1
  58. package/dist/lib/project/local-pin.js +183 -34
  59. package/dist/lib/project/resolution.js +206 -50
  60. package/dist/lib/project/setup.js +64 -18
  61. package/dist/output/patterns.js +1 -1
  62. package/dist/presenters/agent.js +74 -0
  63. package/dist/presenters/app-env.js +149 -14
  64. package/dist/presenters/app.js +187 -26
  65. package/dist/presenters/auth.js +99 -2
  66. package/dist/presenters/branch.js +37 -102
  67. package/dist/presenters/database.js +274 -0
  68. package/dist/presenters/project.js +44 -26
  69. package/dist/presenters/verbose-context.js +64 -0
  70. package/dist/shell/cli-command.js +12 -0
  71. package/dist/shell/command-arguments.js +7 -1
  72. package/dist/shell/command-meta.js +243 -15
  73. package/dist/shell/command-runner.js +60 -21
  74. package/dist/shell/diagnostics-output.js +57 -0
  75. package/dist/shell/errors.js +61 -1
  76. package/dist/shell/help.js +31 -20
  77. package/dist/shell/output.js +10 -1
  78. package/dist/shell/prompt.js +7 -3
  79. package/dist/shell/runtime.js +10 -6
  80. package/dist/shell/ui.js +42 -3
  81. package/dist/shell/update-check.js +247 -0
  82. package/dist/use-cases/auth.js +68 -1
  83. package/dist/use-cases/branch.js +20 -68
  84. package/dist/use-cases/create-cli-gateways.js +2 -17
  85. package/package.json +27 -10
  86. package/dist/lib/app/preview-build.js +0 -284
  87. package/dist/lib/app/preview-interaction.js +0 -5
@@ -0,0 +1,83 @@
1
+ import { PRISMA_SKILLS_LOCK_FILENAME } from "./constants.js";
2
+ import path from "node:path";
3
+ import { readFile, stat } from "node:fs/promises";
4
+ import { findComputeConfigDir } from "@prisma/compute-sdk/config";
5
+ //#region src/lib/agent/setup-status.ts
6
+ async function readPrismaAgentSetupStatus(options) {
7
+ const setupCwd = await resolvePrismaAgentSetupCwd(options);
8
+ const skillsLockPath = path.join(setupCwd, PRISMA_SKILLS_LOCK_FILENAME);
9
+ const [skillsInstalled, promptDismissedAt] = await Promise.all([hasPrismaSkillsLock(skillsLockPath, options.signal, options.requiredSkill), options.stateStore?.readAgentSetupPromptDismissedAt() ?? null]);
10
+ return {
11
+ skillsLockPath: path.basename(skillsLockPath),
12
+ skillsInstalled,
13
+ promptDismissedAt
14
+ };
15
+ }
16
+ async function resolvePrismaAgentSetupCwd(options) {
17
+ options.signal.throwIfAborted();
18
+ const configDir = await findComputeConfigDir(options.cwd, options.signal);
19
+ options.signal.throwIfAborted();
20
+ return configDir ?? options.cwd;
21
+ }
22
+ function isPrismaAgentSetupComplete(status) {
23
+ return status.skillsInstalled;
24
+ }
25
+ function shouldOfferPrismaAgentSetup(status) {
26
+ return !isPrismaAgentSetupComplete(status) && !status.promptDismissedAt;
27
+ }
28
+ async function isLikelyProjectDirectory(options) {
29
+ return (await Promise.all([
30
+ "package.json",
31
+ "prisma.compute.ts",
32
+ "prisma.config.ts",
33
+ ".git"
34
+ ].map((fileName) => pathExists(path.join(options.cwd, fileName), options.signal)))).some(Boolean);
35
+ }
36
+ async function hasPrismaSkillsLock(filePath, signal, requiredSkill) {
37
+ try {
38
+ const raw = await readFile(filePath, {
39
+ encoding: "utf8",
40
+ signal
41
+ });
42
+ return hasPrismaSkillsLockEntry(JSON.parse(raw), requiredSkill);
43
+ } catch (error) {
44
+ if (isNotFoundError(error) || error instanceof SyntaxError) return false;
45
+ throw error;
46
+ }
47
+ }
48
+ function hasPrismaSkillsLockEntry(value, requiredSkill) {
49
+ if (!isRecord(value)) return false;
50
+ if (requiredSkill) return skillLockEntryUsesPrismaSource(readSkillLockEntries(value)[requiredSkill]);
51
+ if (readLegacySources(value).includes("prisma/skills")) return true;
52
+ return Object.values(readSkillLockEntries(value)).some(skillLockEntryUsesPrismaSource);
53
+ }
54
+ function readLegacySources(value) {
55
+ return Array.isArray(value.sources) ? value.sources.filter((source) => typeof source === "string") : [];
56
+ }
57
+ function readSkillLockEntries(value) {
58
+ return isRecord(value.skills) ? value.skills : {};
59
+ }
60
+ function skillLockEntryUsesPrismaSource(value) {
61
+ return isRecord(value) && value.source === "prisma/skills";
62
+ }
63
+ function isRecord(value) {
64
+ return typeof value === "object" && value !== null;
65
+ }
66
+ async function pathExists(filePath, signal) {
67
+ signal.throwIfAborted();
68
+ try {
69
+ await stat(filePath);
70
+ signal.throwIfAborted();
71
+ return true;
72
+ } catch (error) {
73
+ if (signal.aborted) throw error;
74
+ if (isNotFoundError(error)) return false;
75
+ throw error;
76
+ }
77
+ }
78
+ function isNotFoundError(error) {
79
+ const code = error.code;
80
+ return code === "ENOENT" || code === "ENOTDIR";
81
+ }
82
+ //#endregion
83
+ export { isLikelyProjectDirectory, readPrismaAgentSetupStatus, resolvePrismaAgentSetupCwd, shouldOfferPrismaAgentSetup };
@@ -0,0 +1,5 @@
1
+ import "../../shell/prompt.js";
2
+ //#region src/lib/app/app-interaction.ts
3
+ const DEFAULT_REGION = "eu-central-1";
4
+ //#endregion
5
+ export { DEFAULT_REGION };
@@ -1,25 +1,29 @@
1
+ import { createBranchDatabase, createEnvironmentVariable, deleteBranchDatabase, deleteEnvironmentVariable, listEnvironmentVariables, updateEnvironmentVariable } from "./branch-database-api.js";
2
+ import { AppBuildStrategy } from "./build.js";
1
3
  import { envVarNames } from "./env-vars.js";
2
- import { PreviewBuildStrategy } from "./preview-build.js";
3
4
  import path from "node:path";
4
5
  import { ApiError, CancelledError, ComputeClient, streamLogs } from "@prisma/compute-sdk";
5
- //#region src/lib/app/preview-provider.ts
6
- var PreviewDomainApiError = class extends Error {
6
+ //#region src/lib/app/app-provider.ts
7
+ var DomainApiError = class extends Error {
7
8
  status;
8
9
  code;
9
10
  hint;
10
11
  constructor(options) {
11
12
  super(`${options.summary}: ${options.message}${options.hint ? ` ${options.hint}` : ""}`);
12
- this.name = "PreviewDomainApiError";
13
+ this.name = "DomainApiError";
13
14
  this.status = options.status;
14
15
  this.code = options.code ?? null;
15
16
  this.hint = options.hint ?? null;
16
17
  }
17
18
  };
18
- function createPreviewAppProvider(client, options) {
19
+ function createAppProvider(client, options) {
19
20
  const sdk = new ComputeClient(client);
20
21
  return {
21
22
  async createProject(options) {
22
- const projectResult = await sdk.createProject({ name: options.name });
23
+ const projectResult = await sdk.createProject({
24
+ name: options.name,
25
+ signal: options.signal
26
+ });
23
27
  if (projectResult.isErr()) throw new Error(projectResult.error.message);
24
28
  return {
25
29
  id: projectResult.value.id,
@@ -29,17 +33,52 @@ function createPreviewAppProvider(client, options) {
29
33
  async listApps(projectId, options) {
30
34
  return listComputeServices(client, {
31
35
  projectId,
32
- branchGitName: options?.branchName
36
+ branchGitName: options?.branchName,
37
+ signal: options?.signal
38
+ });
39
+ },
40
+ async resolveBranch(projectId, options) {
41
+ const branch = await resolveOrCreateBranch(client, {
42
+ projectId,
43
+ gitName: options.branchName,
44
+ signal: options.signal
33
45
  });
46
+ return {
47
+ id: branch.id,
48
+ name: branch.gitName,
49
+ role: branch.role
50
+ };
51
+ },
52
+ async createBranchDatabase(options) {
53
+ return createBranchDatabase(client, options);
54
+ },
55
+ async deleteBranchDatabase(options) {
56
+ return deleteBranchDatabase(client, options);
57
+ },
58
+ async listEnvironmentVariables(options) {
59
+ return listEnvironmentVariables(client, options);
60
+ },
61
+ async createEnvironmentVariable(options) {
62
+ return createEnvironmentVariable(client, options);
63
+ },
64
+ async updateEnvironmentVariable(options) {
65
+ return updateEnvironmentVariable(client, options);
66
+ },
67
+ async deleteEnvironmentVariable(options) {
68
+ return deleteEnvironmentVariable(client, options);
34
69
  },
35
- async removeApp(appId) {
36
- const appResult = await sdk.showService({ serviceId: appId });
70
+ async removeApp(appId, options) {
71
+ const appResult = await sdk.showApp({
72
+ appId,
73
+ signal: options?.signal
74
+ });
37
75
  if (appResult.isErr()) throw new Error(appResult.error.message);
38
- const destroyResult = await sdk.destroyService({
39
- serviceId: appId,
40
- keepService: false,
76
+ const destroyResult = await sdk.destroyApp({
77
+ appId,
78
+ keepApp: false,
41
79
  timeoutSeconds: 120,
42
- pollIntervalMs: 2e3
80
+ pollIntervalMs: 2e3,
81
+ signal: options?.signal
43
82
  });
44
83
  if (destroyResult.isErr()) throw new Error(destroyResult.error.message);
45
84
  return {
@@ -47,17 +86,18 @@ function createPreviewAppProvider(client, options) {
47
86
  name: appResult.value.name
48
87
  };
49
88
  },
50
- async listDomains(appId) {
51
- return listComputeServiceDomains(client, appId);
89
+ async listDomains(appId, options) {
90
+ return listComputeServiceDomains(client, appId, options?.signal);
52
91
  },
53
92
  async addDomain(options) {
54
- const result = await client.POST("/v1/compute-services/{computeServiceId}/domains", {
55
- params: { path: { computeServiceId: options.appId } },
56
- body: { hostname: options.hostname }
93
+ const result = await client.POST("/v1/apps/{appId}/domains", {
94
+ params: { path: { appId: options.appId } },
95
+ body: { hostname: options.hostname },
96
+ signal: options.signal
57
97
  });
58
98
  if (result.error || !result.data) {
59
99
  if (result.response.status === 409) {
60
- const existing = (await listComputeServiceDomains(client, options.appId)).find((domain) => sameHostname(domain.hostname, options.hostname));
100
+ const existing = (await listComputeServiceDomains(client, options.appId, options.signal)).find((domain) => sameHostname(domain.hostname, options.hostname));
61
101
  if (existing) return {
62
102
  domain: existing,
63
103
  existing: true
@@ -70,26 +110,36 @@ function createPreviewAppProvider(client, options) {
70
110
  existing: false
71
111
  };
72
112
  },
73
- async showDomain(domainId) {
74
- const result = await client.GET("/v1/domains/{domainId}", { params: { path: { domainId } } });
113
+ async showDomain(domainId, options) {
114
+ const result = await client.GET("/v1/domains/{domainId}", {
115
+ params: { path: { domainId } },
116
+ signal: options?.signal
117
+ });
75
118
  if (result.error || !result.data) throw domainApiCallError("Failed to show custom domain", result.response, result.error);
76
119
  return normalizeDomainRecord(result.data.data);
77
120
  },
78
- async removeDomain(domainId) {
79
- const result = await client.DELETE("/v1/domains/{domainId}", { params: { path: { domainId } } });
121
+ async removeDomain(domainId, options) {
122
+ const result = await client.DELETE("/v1/domains/{domainId}", {
123
+ params: { path: { domainId } },
124
+ signal: options?.signal
125
+ });
80
126
  if (result.error) throw domainApiCallError("Failed to remove custom domain", result.response, result.error);
81
127
  },
82
- async retryDomain(domainId) {
83
- const result = await client.POST("/v1/domains/{domainId}/retry", { params: { path: { domainId } } });
128
+ async retryDomain(domainId, options) {
129
+ const result = await client.POST("/v1/domains/{domainId}/retry", {
130
+ params: { path: { domainId } },
131
+ signal: options?.signal
132
+ });
84
133
  if (result.error || !result.data) throw domainApiCallError("Failed to retry custom domain", result.response, result.error);
85
134
  return normalizeDomainRecord(result.data.data);
86
135
  },
87
136
  async promoteDeployment(options) {
88
137
  const promoteResult = await sdk.promote({
89
- serviceId: options.appId,
90
- versionId: options.deploymentId,
138
+ appId: options.appId,
139
+ deploymentId: options.deploymentId,
91
140
  timeoutSeconds: 120,
92
141
  pollIntervalMs: 2e3,
142
+ signal: options.signal,
93
143
  progress: options.progress
94
144
  });
95
145
  if (promoteResult.isErr()) throw new Error(promoteResult.error.message);
@@ -103,27 +153,32 @@ function createPreviewAppProvider(client, options) {
103
153
  projectId: options.projectId,
104
154
  branchName: options.branchName,
105
155
  appName: options.appName,
106
- region: options.region
156
+ region: options.region,
157
+ signal: options.signal
107
158
  }) : {
108
159
  appId: void 0,
109
160
  appName: options.appName,
110
161
  region: options.region
111
162
  };
112
163
  const deployResult = await sdk.deploy({
113
- strategy: new PreviewBuildStrategy({
164
+ strategy: new AppBuildStrategy({
114
165
  appPath: path.resolve(options.cwd),
115
166
  entrypoint: options.entrypoint,
116
- buildType: options.buildType
167
+ buildType: options.buildType,
168
+ signal: options.signal,
169
+ buildSettings: options.buildSettings
117
170
  }),
118
171
  projectId: options.projectId,
119
- serviceId: resolvedApp.appId,
120
- serviceName: resolvedApp.appName,
172
+ appId: resolvedApp.appId,
173
+ appName: resolvedApp.appName,
121
174
  region: resolvedApp.region,
122
175
  portMapping: options.portMapping,
123
176
  envVars: options.envVars,
177
+ skipPromote: options.skipPromote,
124
178
  timeoutSeconds: 120,
125
179
  pollIntervalMs: 2e3,
126
180
  interaction: options.interaction,
181
+ signal: options.signal,
127
182
  progress: options.progress
128
183
  });
129
184
  if (deployResult.isErr()) throw new Error(deployResult.error.message);
@@ -131,37 +186,47 @@ function createPreviewAppProvider(client, options) {
131
186
  return {
132
187
  projectId: deployed.projectId,
133
188
  app: {
134
- id: deployed.serviceId,
135
- name: deployed.serviceName,
189
+ id: deployed.appId,
190
+ name: deployed.appName,
136
191
  region: deployed.region ?? null,
137
- liveDeploymentId: deployed.versionId,
138
- liveUrl: toAbsoluteUrl(deployed.serviceEndpointDomain ?? null)
192
+ liveDeploymentId: deployed.promoted ? deployed.deploymentId : deployed.previousDeploymentId,
193
+ liveUrl: toAbsoluteUrl(deployed.appEndpointDomain ?? null)
139
194
  },
140
195
  deployment: {
141
- id: deployed.versionId,
196
+ id: deployed.deploymentId,
142
197
  status: "running",
143
- url: toAbsoluteUrl(deployed.serviceEndpointDomain ?? deployed.versionEndpointDomain ?? null)
144
- }
198
+ url: toAbsoluteUrl(deployed.appEndpointDomain ?? deployed.deploymentEndpointDomain ?? null),
199
+ live: deployed.promoted
200
+ },
201
+ promoted: deployed.promoted
145
202
  };
146
203
  },
147
204
  async updateAppEnv(options) {
148
205
  const updateResult = await sdk.updateEnv({
149
- serviceId: options.appId,
206
+ appId: options.appId,
150
207
  envVars: options.envVars,
151
208
  timeoutSeconds: 120,
152
209
  pollIntervalMs: 2e3,
210
+ signal: options.signal,
153
211
  progress: options.progress
154
212
  });
155
213
  if (updateResult.isErr()) throw new Error(updateResult.error.message);
156
214
  const promoteResult = await sdk.promote({
157
- serviceId: options.appId,
158
- versionId: updateResult.value.versionId,
215
+ appId: options.appId,
216
+ deploymentId: updateResult.value.deploymentId,
159
217
  timeoutSeconds: 120,
160
218
  pollIntervalMs: 2e3,
219
+ signal: options.signal,
161
220
  progress: options.promoteProgress
162
221
  });
163
222
  if (promoteResult.isErr()) throw new Error(promoteResult.error.message);
164
- const [serviceResult, versionResult] = await Promise.all([sdk.showService({ serviceId: options.appId }), sdk.showVersion({ versionId: updateResult.value.versionId })]);
223
+ const [serviceResult, versionResult] = await Promise.all([sdk.showApp({
224
+ appId: options.appId,
225
+ signal: options.signal
226
+ }), sdk.showDeployment({
227
+ deploymentId: updateResult.value.deploymentId,
228
+ signal: options.signal
229
+ })]);
165
230
  if (serviceResult.isErr()) throw new Error(serviceResult.error.message);
166
231
  if (versionResult.isErr()) throw new Error(versionResult.error.message);
167
232
  return {
@@ -170,21 +235,27 @@ function createPreviewAppProvider(client, options) {
170
235
  id: serviceResult.value.id,
171
236
  name: serviceResult.value.name,
172
237
  region: serviceResult.value.region ?? null,
173
- liveDeploymentId: serviceResult.value.latestVersionId ?? null,
174
- liveUrl: toAbsoluteUrl(serviceResult.value.serviceEndpointDomain ?? null)
238
+ liveDeploymentId: serviceResult.value.latestDeploymentId ?? null,
239
+ liveUrl: toAbsoluteUrl(serviceResult.value.appEndpointDomain ?? null)
175
240
  },
176
241
  deployment: {
177
242
  id: versionResult.value.id,
178
243
  status: versionResult.value.status,
179
244
  createdAt: versionResult.value.createdAt,
180
- url: toAbsoluteUrl(serviceResult.value.serviceEndpointDomain ?? versionResult.value.previewDomain ?? null),
245
+ url: toAbsoluteUrl(serviceResult.value.appEndpointDomain ?? versionResult.value.previewDomain ?? null),
181
246
  live: true
182
247
  },
183
248
  variables: envVarNames(versionResult.value.envVars)
184
249
  };
185
250
  },
186
251
  async listAppEnvNames(options) {
187
- const [serviceResult, versionResult] = await Promise.all([sdk.showService({ serviceId: options.appId }), sdk.showVersion({ versionId: options.deploymentId })]);
252
+ const [serviceResult, versionResult] = await Promise.all([sdk.showApp({
253
+ appId: options.appId,
254
+ signal: options.signal
255
+ }), sdk.showDeployment({
256
+ deploymentId: options.deploymentId,
257
+ signal: options.signal
258
+ })]);
188
259
  if (serviceResult.isErr()) throw new Error(serviceResult.error.message);
189
260
  if (versionResult.isErr()) throw new Error(versionResult.error.message);
190
261
  return {
@@ -193,21 +264,27 @@ function createPreviewAppProvider(client, options) {
193
264
  id: serviceResult.value.id,
194
265
  name: serviceResult.value.name,
195
266
  region: serviceResult.value.region ?? null,
196
- liveDeploymentId: serviceResult.value.latestVersionId ?? null,
197
- liveUrl: toAbsoluteUrl(serviceResult.value.serviceEndpointDomain ?? null)
267
+ liveDeploymentId: serviceResult.value.latestDeploymentId ?? null,
268
+ liveUrl: toAbsoluteUrl(serviceResult.value.appEndpointDomain ?? null)
198
269
  },
199
270
  deployment: {
200
271
  id: versionResult.value.id,
201
272
  status: versionResult.value.status,
202
273
  createdAt: versionResult.value.createdAt,
203
274
  url: toAbsoluteUrl(versionResult.value.previewDomain ?? null),
204
- live: serviceResult.value.latestVersionId === versionResult.value.id
275
+ live: serviceResult.value.latestDeploymentId === versionResult.value.id
205
276
  },
206
277
  variables: envVarNames(versionResult.value.envVars)
207
278
  };
208
279
  },
209
- async listDeployments(appId) {
210
- const [appResult, versionsResult] = await Promise.all([sdk.showService({ serviceId: appId }), sdk.listVersions({ serviceId: appId })]);
280
+ async listDeployments(appId, options) {
281
+ const [appResult, versionsResult] = await Promise.all([sdk.showApp({
282
+ appId,
283
+ signal: options?.signal
284
+ }), sdk.listDeployments({
285
+ appId,
286
+ signal: options?.signal
287
+ })]);
211
288
  if (appResult.isErr()) throw new Error(appResult.error.message);
212
289
  if (versionsResult.isErr()) throw new Error(versionsResult.error.message);
213
290
  return {
@@ -215,8 +292,8 @@ function createPreviewAppProvider(client, options) {
215
292
  id: appResult.value.id,
216
293
  name: appResult.value.name,
217
294
  region: appResult.value.region ?? null,
218
- liveDeploymentId: appResult.value.latestVersionId ?? null,
219
- liveUrl: toAbsoluteUrl(appResult.value.serviceEndpointDomain ?? null)
295
+ liveDeploymentId: appResult.value.latestDeploymentId ?? null,
296
+ liveUrl: toAbsoluteUrl(appResult.value.appEndpointDomain ?? null)
220
297
  },
221
298
  deployments: versionsResult.value.slice().sort((left, right) => {
222
299
  const byDate = right.createdAt.localeCompare(left.createdAt);
@@ -230,14 +307,17 @@ function createPreviewAppProvider(client, options) {
230
307
  }))
231
308
  };
232
309
  },
233
- async showDeployment(deploymentId) {
234
- const deploymentResult = await sdk.showVersion({ versionId: deploymentId });
310
+ async showDeployment(deploymentId, options) {
311
+ const deploymentResult = await sdk.showDeployment({
312
+ deploymentId,
313
+ signal: options?.signal
314
+ });
235
315
  if (deploymentResult.isErr()) {
236
316
  if (ApiError.is(deploymentResult.error) && deploymentResult.error.statusCode === 404) return null;
237
317
  throw new Error(deploymentResult.error.message);
238
318
  }
239
319
  return {
240
- app: await findAppForDeployment(sdk, deploymentId),
320
+ app: await findAppForDeployment(sdk, deploymentId, options?.signal),
241
321
  deployment: {
242
322
  id: deploymentResult.value.id,
243
323
  status: deploymentResult.value.status,
@@ -252,7 +332,7 @@ function createPreviewAppProvider(client, options) {
252
332
  const result = await streamLogs({
253
333
  baseUrl: options.baseUrl,
254
334
  token: await options.getToken(),
255
- versionId: streamOptions.deploymentId,
335
+ deploymentId: streamOptions.deploymentId,
256
336
  signal: streamOptions.signal
257
337
  }, streamOptions.onRecord);
258
338
  if (result.isErr()) {
@@ -263,22 +343,28 @@ function createPreviewAppProvider(client, options) {
263
343
  };
264
344
  }
265
345
  async function listBranches(client, options) {
266
- const result = await client.GET("/v1/projects/{projectId}/branches", { params: {
267
- path: { projectId: options.projectId },
268
- query: { gitName: options.gitName }
269
- } });
346
+ const result = await client.GET("/v1/projects/{projectId}/branches", {
347
+ params: {
348
+ path: { projectId: options.projectId },
349
+ query: { gitName: options.gitName }
350
+ },
351
+ signal: options.signal
352
+ });
270
353
  if (result.error || !result.data) throw apiCallError("Failed to list branches", result.response, result.error);
271
- return result.data.data;
354
+ return result.data.data.map((branch) => ({
355
+ id: branch.id,
356
+ gitName: branch.gitName,
357
+ isDefault: branch.isDefault,
358
+ role: branch.role
359
+ }));
272
360
  }
273
361
  async function resolveOrCreateBranch(client, options) {
274
362
  const existing = (await listBranches(client, options))[0];
275
363
  if (existing) return existing;
276
364
  const result = await client.POST("/v1/projects/{projectId}/branches", {
277
365
  params: { path: { projectId: options.projectId } },
278
- body: {
279
- gitName: options.gitName,
280
- isDefault: options.gitName === "main"
281
- }
366
+ body: { gitName: options.gitName },
367
+ signal: options.signal
282
368
  });
283
369
  if (result.error || !result.data) {
284
370
  if (result.response.status === 409) {
@@ -287,17 +373,26 @@ async function resolveOrCreateBranch(client, options) {
287
373
  }
288
374
  throw apiCallError(`Failed to create branch "${options.gitName}"`, result.response, result.error);
289
375
  }
290
- return result.data.data;
376
+ const branch = result.data.data;
377
+ return {
378
+ id: branch.id,
379
+ gitName: branch.gitName,
380
+ isDefault: branch.isDefault,
381
+ role: branch.role
382
+ };
291
383
  }
292
384
  async function listComputeServices(client, options) {
293
385
  const services = [];
294
386
  let cursor;
295
387
  while (true) {
296
- const result = await client.GET("/v1/compute-services", { params: { query: {
297
- projectId: options.projectId,
298
- branchGitName: options.branchGitName,
299
- cursor
300
- } } });
388
+ const result = await client.GET("/v1/apps", {
389
+ params: { query: {
390
+ projectId: options.projectId,
391
+ branchGitName: options.branchGitName,
392
+ cursor
393
+ } },
394
+ signal: options.signal
395
+ });
301
396
  if (result.error || !result.data) throw apiCallError("Failed to list apps", result.response, result.error);
302
397
  services.push(...result.data.data);
303
398
  if (!result.data.pagination.hasMore || !result.data.pagination.nextCursor) break;
@@ -308,12 +403,15 @@ async function listComputeServices(client, options) {
308
403
  name: service.name,
309
404
  region: service.region.id ?? null,
310
405
  branchId: service.branchId,
311
- liveDeploymentId: service.latestVersionId ?? null,
312
- liveUrl: toAbsoluteUrl(service.serviceEndpointDomain ?? null)
406
+ liveDeploymentId: service.latestDeploymentId ?? null,
407
+ liveUrl: toAbsoluteUrl(service.appEndpointDomain ?? null)
313
408
  }));
314
409
  }
315
- async function listComputeServiceDomains(client, computeServiceId) {
316
- const result = await client.GET("/v1/compute-services/{computeServiceId}/domains", { params: { path: { computeServiceId } } });
410
+ async function listComputeServiceDomains(client, appId, signal) {
411
+ const result = await client.GET("/v1/apps/{appId}/domains", {
412
+ params: { path: { appId } },
413
+ signal
414
+ });
317
415
  if (result.error || !result.data) throw domainApiCallError("Failed to list custom domains", result.response, result.error);
318
416
  return result.data.data.map((domain) => normalizeDomainRecord(domain));
319
417
  }
@@ -323,7 +421,7 @@ function normalizeDomainRecord(domain) {
323
421
  type: domain.type,
324
422
  url: domain.url,
325
423
  hostname: domain.hostname,
326
- computeServiceId: domain.computeServiceId,
424
+ appId: domain.appId,
327
425
  status: domain.status,
328
426
  foundryStatus: domain.foundryStatus,
329
427
  failureReason: domain.failureReason,
@@ -355,19 +453,24 @@ function normalizeHostnameForComparison(hostname) {
355
453
  async function createBranchApp(client, options) {
356
454
  const branch = await resolveOrCreateBranch(client, {
357
455
  projectId: options.projectId,
358
- gitName: options.branchName
456
+ gitName: options.branchName,
457
+ signal: options.signal
458
+ });
459
+ const result = await client.POST("/v1/apps", {
460
+ body: {
461
+ projectId: options.projectId,
462
+ branchId: branch.id,
463
+ displayName: options.appName,
464
+ ...options.region ? { regionId: options.region } : {}
465
+ },
466
+ signal: options.signal
359
467
  });
360
- const result = await client.POST("/v1/compute-services", { body: {
361
- projectId: options.projectId,
362
- branchId: branch.id,
363
- displayName: options.appName,
364
- ...options.region ? { regionId: options.region } : {}
365
- } });
366
468
  if (result.error || !result.data) {
367
469
  if (result.response.status === 409) {
368
470
  const matched = (await listComputeServices(client, {
369
471
  projectId: options.projectId,
370
- branchGitName: options.branchName
472
+ branchGitName: options.branchName,
473
+ signal: options.signal
371
474
  })).find((app) => app.name === options.appName);
372
475
  if (matched) return {
373
476
  appId: matched.id,
@@ -391,7 +494,7 @@ function apiCallError(summary, response, error) {
391
494
  return /* @__PURE__ */ new Error(`${summary}: ${message}${hint}`);
392
495
  }
393
496
  function domainApiCallError(summary, response, error) {
394
- return new PreviewDomainApiError({
497
+ return new DomainApiError({
395
498
  summary,
396
499
  status: response.status,
397
500
  code: error.error?.code ?? null,
@@ -399,33 +502,46 @@ function domainApiCallError(summary, response, error) {
399
502
  hint: error.error?.hint ?? null
400
503
  });
401
504
  }
402
- async function findAppForDeployment(sdk, deploymentId) {
403
- const projectsResult = await sdk.listProjects();
505
+ async function findAppForDeployment(sdk, deploymentId, signal) {
506
+ const projectsResult = await sdk.listProjects({ signal });
404
507
  if (projectsResult.isErr()) throw new Error(projectsResult.error.message);
405
508
  for (const project of projectsResult.value) {
406
- const servicesResult = await sdk.listServices({ projectId: project.id });
509
+ const servicesResult = await sdk.listApps({
510
+ projectId: project.id,
511
+ signal
512
+ });
407
513
  if (servicesResult.isErr()) throw new Error(servicesResult.error.message);
408
514
  for (const service of servicesResult.value) {
409
- const detailResult = await sdk.showService({ serviceId: service.id });
410
- if (detailResult.isErr()) throw new Error(detailResult.error.message);
411
- const app = {
412
- id: detailResult.value.id,
413
- name: detailResult.value.name,
414
- region: detailResult.value.region ?? null,
415
- liveDeploymentId: detailResult.value.latestVersionId ?? null,
416
- liveUrl: toAbsoluteUrl(detailResult.value.serviceEndpointDomain ?? null)
417
- };
418
- if (app.liveDeploymentId === deploymentId) return app;
419
- const versionsResult = await sdk.listVersions({ serviceId: service.id });
420
- if (versionsResult.isErr()) throw new Error(versionsResult.error.message);
421
- if (versionsResult.value.some((version) => version.id === deploymentId)) return app;
515
+ const app = await findServiceAppForDeployment(sdk, service.id, deploymentId, signal);
516
+ if (app) return app;
422
517
  }
423
518
  }
424
519
  return null;
425
520
  }
521
+ async function findServiceAppForDeployment(sdk, serviceId, deploymentId, signal) {
522
+ const detailResult = await sdk.showApp({
523
+ appId: serviceId,
524
+ signal
525
+ });
526
+ if (detailResult.isErr()) throw new Error(detailResult.error.message);
527
+ const app = {
528
+ id: detailResult.value.id,
529
+ name: detailResult.value.name,
530
+ region: detailResult.value.region ?? null,
531
+ liveDeploymentId: detailResult.value.latestDeploymentId ?? null,
532
+ liveUrl: toAbsoluteUrl(detailResult.value.appEndpointDomain ?? null)
533
+ };
534
+ if (app.liveDeploymentId === deploymentId) return app;
535
+ const versionsResult = await sdk.listDeployments({
536
+ appId: serviceId,
537
+ signal
538
+ });
539
+ if (versionsResult.isErr()) throw new Error(versionsResult.error.message);
540
+ return versionsResult.value.some((version) => version.id === deploymentId) ? app : null;
541
+ }
426
542
  function toAbsoluteUrl(url) {
427
543
  if (!url) return null;
428
544
  return url.startsWith("https://") || url.startsWith("http://") ? url : `https://${url}`;
429
545
  }
430
546
  //#endregion
431
- export { PreviewDomainApiError, createPreviewAppProvider };
547
+ export { DomainApiError, createAppProvider };