@prisma/cli 3.0.0-dev.97.1 → 8.0.0-rc.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.
- package/README.md +3 -14
- package/dist/adapters/local-state.js +14 -3
- package/dist/{lib/auth → auth}/client.js +11 -3
- package/dist/auth/errors.js +50 -0
- package/dist/{lib/auth → auth}/guard.js +7 -6
- package/dist/{lib/auth → auth}/login.js +147 -6
- package/dist/{lib/auth/auth-ops.js → auth/operations.js} +63 -13
- package/dist/auth/recipient.js +42 -0
- package/dist/{adapters → auth}/token-storage.js +28 -7
- package/dist/auth/workspaces.js +171 -0
- package/dist/cli-command.js +14 -0
- package/dist/cli-name.js +12 -0
- package/dist/cli.js +1 -1
- package/dist/cli2.js +25 -8
- package/dist/command-arguments.js +12 -0
- package/dist/commands/agent/index.js +60 -0
- package/dist/commands/app/index.js +11 -6
- package/dist/commands/auth/index.js +2 -3
- package/dist/commands/bucket/index.js +123 -0
- package/dist/commands/build/index.js +29 -0
- package/dist/commands/database/index.js +92 -2
- package/dist/commands/feedback/index.js +20 -0
- package/dist/commands/git/index.js +1 -1
- package/dist/commands/init/index.js +33 -0
- package/dist/commands/project/index.js +54 -5
- package/dist/controllers/agent-setup.js +52 -0
- package/dist/controllers/agent.js +228 -0
- package/dist/controllers/app-env-api.js +3 -2
- package/dist/controllers/app-env-file.js +1 -1
- package/dist/controllers/app-env.js +5 -5
- package/dist/controllers/app.js +423 -358
- package/dist/controllers/auth.js +62 -254
- package/dist/controllers/branch.js +5 -16
- package/dist/controllers/bucket.js +184 -0
- package/dist/controllers/build.js +88 -0
- package/dist/controllers/database.js +230 -85
- package/dist/controllers/feedback.js +90 -0
- package/dist/controllers/init.js +814 -0
- package/dist/controllers/project.js +345 -184
- package/dist/controllers/select-prompt-port.js +1 -0
- package/dist/{shell/errors.js → errors.js} +8 -40
- package/dist/lib/agent/cli-command.js +20 -0
- package/dist/lib/agent/constants.js +12 -0
- package/dist/lib/agent/package-manager.js +99 -0
- package/dist/lib/agent/setup-status.js +83 -0
- package/dist/lib/app/app-provider.js +168 -95
- package/dist/lib/app/branch-database-deploy.js +70 -42
- package/dist/lib/app/branch-database.js +39 -20
- package/dist/lib/app/build-settings.js +8 -3
- package/dist/lib/app/build.js +16 -14
- package/dist/lib/app/bun-project.js +1 -1
- package/dist/lib/app/compute-config.js +29 -31
- package/dist/lib/app/deploy-plan.js +1 -0
- package/dist/lib/app/deploy-progress.js +7 -7
- package/dist/lib/app/env-config.js +1 -1
- package/dist/lib/app/env-file.js +2 -2
- package/dist/lib/app/env-vars.js +1 -1
- package/dist/lib/app/local-dev.js +1 -1
- package/dist/lib/app/production-deploy-gate.js +3 -2
- package/dist/lib/bucket/provider.js +139 -0
- package/dist/lib/database/provider.js +235 -17
- package/dist/lib/diagnostics.js +2 -1
- package/dist/lib/feedback.js +15 -0
- package/dist/lib/git/local-branch.js +1 -1
- package/dist/lib/project/interactive-setup.js +6 -5
- package/dist/lib/project/local-pin.js +1 -1
- package/dist/lib/project/provider.js +93 -0
- package/dist/lib/project/resolution.js +11 -8
- package/dist/lib/project/setup.js +9 -6
- package/dist/lib/version.js +3 -2
- package/dist/lib/workspace-id.js +18 -0
- package/dist/payload-B88Qvzxk-CrtTXSOe.js +34 -0
- package/dist/presenters/agent.js +74 -0
- package/dist/presenters/app.js +33 -7
- package/dist/presenters/auth.js +3 -2
- package/dist/presenters/bucket.js +174 -0
- package/dist/presenters/database.js +193 -5
- package/dist/presenters/feedback.js +26 -0
- package/dist/presenters/init.js +30 -0
- package/dist/presenters/project.js +98 -4
- package/dist/shell/cli-command.js +2 -0
- package/dist/shell/command-meta.js +303 -4
- package/dist/shell/command-runner.js +13 -6
- package/dist/shell/help.js +6 -5
- package/dist/shell/output.js +65 -3
- package/dist/shell/prompt.js +12 -5
- package/dist/shell/runtime.js +4 -21
- package/dist/state-dir.js +12 -0
- package/dist/{shell/update-check.js → update-check.js} +6 -5
- package/dist/v8/cli.js +14699 -0
- package/dist/v8/sender.js +192 -0
- package/package.json +21 -13
- package/dist/adapters/mock-api.js +0 -136
- package/dist/lib/app/app-interaction.js +0 -5
- package/dist/shell/command-arguments.js +0 -6
- package/dist/use-cases/auth.js +0 -145
- package/dist/use-cases/branch.js +0 -47
- package/dist/use-cases/create-cli-gateways.js +0 -68
- package/dist/use-cases/project.js +0 -30
|
@@ -22,12 +22,14 @@ function createAppProvider(client, options) {
|
|
|
22
22
|
async createProject(options) {
|
|
23
23
|
const projectResult = await sdk.createProject({
|
|
24
24
|
name: options.name,
|
|
25
|
+
region: options.region,
|
|
25
26
|
signal: options.signal
|
|
26
27
|
});
|
|
27
28
|
if (projectResult.isErr()) throw new Error(projectResult.error.message);
|
|
28
29
|
return {
|
|
29
30
|
id: projectResult.value.id,
|
|
30
|
-
name: projectResult.value.name
|
|
31
|
+
name: projectResult.value.name,
|
|
32
|
+
defaultRegion: projectResult.value.defaultRegion
|
|
31
33
|
};
|
|
32
34
|
},
|
|
33
35
|
async listApps(projectId, options) {
|
|
@@ -37,6 +39,15 @@ function createAppProvider(client, options) {
|
|
|
37
39
|
signal: options?.signal
|
|
38
40
|
});
|
|
39
41
|
},
|
|
42
|
+
async createApp(options) {
|
|
43
|
+
return createComputeService(client, {
|
|
44
|
+
projectId: options.projectId,
|
|
45
|
+
branchName: options.branchName,
|
|
46
|
+
displayName: options.name,
|
|
47
|
+
...options.region !== void 0 ? { region: options.region } : {},
|
|
48
|
+
...options.signal !== void 0 ? { signal: options.signal } : {}
|
|
49
|
+
});
|
|
50
|
+
},
|
|
40
51
|
async resolveBranch(projectId, options) {
|
|
41
52
|
const branch = await resolveOrCreateBranch(client, {
|
|
42
53
|
projectId,
|
|
@@ -68,17 +79,18 @@ function createAppProvider(client, options) {
|
|
|
68
79
|
return deleteEnvironmentVariable(client, options);
|
|
69
80
|
},
|
|
70
81
|
async removeApp(appId, options) {
|
|
71
|
-
const appResult = await sdk.
|
|
72
|
-
|
|
82
|
+
const appResult = await sdk.showApp({
|
|
83
|
+
appId,
|
|
73
84
|
signal: options?.signal
|
|
74
85
|
});
|
|
75
86
|
if (appResult.isErr()) throw new Error(appResult.error.message);
|
|
76
|
-
const destroyResult = await sdk.
|
|
77
|
-
|
|
78
|
-
|
|
87
|
+
const destroyResult = await sdk.destroyApp({
|
|
88
|
+
appId,
|
|
89
|
+
keepApp: false,
|
|
79
90
|
timeoutSeconds: 120,
|
|
80
91
|
pollIntervalMs: 2e3,
|
|
81
|
-
signal: options?.signal
|
|
92
|
+
signal: options?.signal,
|
|
93
|
+
progress: options?.progress
|
|
82
94
|
});
|
|
83
95
|
if (destroyResult.isErr()) throw new Error(destroyResult.error.message);
|
|
84
96
|
return {
|
|
@@ -90,8 +102,8 @@ function createAppProvider(client, options) {
|
|
|
90
102
|
return listComputeServiceDomains(client, appId, options?.signal);
|
|
91
103
|
},
|
|
92
104
|
async addDomain(options) {
|
|
93
|
-
const result = await client.POST("/v1/
|
|
94
|
-
params: { path: {
|
|
105
|
+
const result = await client.POST("/v1/apps/{appId}/domains", {
|
|
106
|
+
params: { path: { appId: options.appId } },
|
|
95
107
|
body: { hostname: options.hostname },
|
|
96
108
|
signal: options.signal
|
|
97
109
|
});
|
|
@@ -135,8 +147,8 @@ function createAppProvider(client, options) {
|
|
|
135
147
|
},
|
|
136
148
|
async promoteDeployment(options) {
|
|
137
149
|
const promoteResult = await sdk.promote({
|
|
138
|
-
|
|
139
|
-
|
|
150
|
+
appId: options.appId,
|
|
151
|
+
deploymentId: options.deploymentId,
|
|
140
152
|
timeoutSeconds: 120,
|
|
141
153
|
pollIntervalMs: 2e3,
|
|
142
154
|
signal: options.signal,
|
|
@@ -144,6 +156,41 @@ function createAppProvider(client, options) {
|
|
|
144
156
|
});
|
|
145
157
|
if (promoteResult.isErr()) throw new Error(promoteResult.error.message);
|
|
146
158
|
},
|
|
159
|
+
async startDeployment(options) {
|
|
160
|
+
const result = await sdk.startDeployment({
|
|
161
|
+
deploymentId: options.deploymentId,
|
|
162
|
+
signal: options.signal
|
|
163
|
+
});
|
|
164
|
+
if (result.isErr()) throw new Error(result.error.message);
|
|
165
|
+
},
|
|
166
|
+
async stopDeployment(options) {
|
|
167
|
+
const result = await sdk.stopDeployment({
|
|
168
|
+
deploymentId: options.deploymentId,
|
|
169
|
+
signal: options.signal
|
|
170
|
+
});
|
|
171
|
+
if (result.isErr()) throw new Error(result.error.message);
|
|
172
|
+
},
|
|
173
|
+
async deleteDeployment(options) {
|
|
174
|
+
const result = await sdk.deleteDeployment({
|
|
175
|
+
deploymentId: options.deploymentId,
|
|
176
|
+
signal: options.signal
|
|
177
|
+
});
|
|
178
|
+
if (result.isErr()) throw new Error(result.error.message);
|
|
179
|
+
},
|
|
180
|
+
async readDeployment(options) {
|
|
181
|
+
const result = await sdk.showDeployment({
|
|
182
|
+
deploymentId: options.deploymentId,
|
|
183
|
+
signal: options.signal
|
|
184
|
+
});
|
|
185
|
+
if (result.isErr()) throw new Error(result.error.message);
|
|
186
|
+
return {
|
|
187
|
+
id: result.value.id,
|
|
188
|
+
status: result.value.status,
|
|
189
|
+
createdAt: result.value.createdAt,
|
|
190
|
+
url: toAbsoluteUrl(result.value.previewDomain ?? null),
|
|
191
|
+
live: null
|
|
192
|
+
};
|
|
193
|
+
},
|
|
147
194
|
async deployApp(options) {
|
|
148
195
|
const resolvedApp = options.appId ? {
|
|
149
196
|
appId: options.appId,
|
|
@@ -169,11 +216,12 @@ function createAppProvider(client, options) {
|
|
|
169
216
|
buildSettings: options.buildSettings
|
|
170
217
|
}),
|
|
171
218
|
projectId: options.projectId,
|
|
172
|
-
|
|
173
|
-
|
|
219
|
+
appId: resolvedApp.appId,
|
|
220
|
+
appName: resolvedApp.appName,
|
|
174
221
|
region: resolvedApp.region,
|
|
175
222
|
portMapping: options.portMapping,
|
|
176
223
|
envVars: options.envVars,
|
|
224
|
+
skipPromote: options.skipPromote,
|
|
177
225
|
timeoutSeconds: 120,
|
|
178
226
|
pollIntervalMs: 2e3,
|
|
179
227
|
interaction: options.interaction,
|
|
@@ -185,22 +233,24 @@ function createAppProvider(client, options) {
|
|
|
185
233
|
return {
|
|
186
234
|
projectId: deployed.projectId,
|
|
187
235
|
app: {
|
|
188
|
-
id: deployed.
|
|
189
|
-
name: deployed.
|
|
236
|
+
id: deployed.appId,
|
|
237
|
+
name: deployed.appName,
|
|
190
238
|
region: deployed.region ?? null,
|
|
191
|
-
liveDeploymentId: deployed.
|
|
192
|
-
liveUrl: toAbsoluteUrl(deployed.
|
|
239
|
+
liveDeploymentId: deployed.promoted ? deployed.deploymentId : deployed.previousDeploymentId,
|
|
240
|
+
liveUrl: toAbsoluteUrl(deployed.appEndpointDomain ?? null)
|
|
193
241
|
},
|
|
194
242
|
deployment: {
|
|
195
|
-
id: deployed.
|
|
243
|
+
id: deployed.deploymentId,
|
|
196
244
|
status: "running",
|
|
197
|
-
url: toAbsoluteUrl(deployed.
|
|
198
|
-
|
|
245
|
+
url: toAbsoluteUrl(deployed.appEndpointDomain ?? deployed.deploymentEndpointDomain ?? null),
|
|
246
|
+
live: deployed.promoted
|
|
247
|
+
},
|
|
248
|
+
promoted: deployed.promoted
|
|
199
249
|
};
|
|
200
250
|
},
|
|
201
251
|
async updateAppEnv(options) {
|
|
202
252
|
const updateResult = await sdk.updateEnv({
|
|
203
|
-
|
|
253
|
+
appId: options.appId,
|
|
204
254
|
envVars: options.envVars,
|
|
205
255
|
timeoutSeconds: 120,
|
|
206
256
|
pollIntervalMs: 2e3,
|
|
@@ -209,19 +259,19 @@ function createAppProvider(client, options) {
|
|
|
209
259
|
});
|
|
210
260
|
if (updateResult.isErr()) throw new Error(updateResult.error.message);
|
|
211
261
|
const promoteResult = await sdk.promote({
|
|
212
|
-
|
|
213
|
-
|
|
262
|
+
appId: options.appId,
|
|
263
|
+
deploymentId: updateResult.value.deploymentId,
|
|
214
264
|
timeoutSeconds: 120,
|
|
215
265
|
pollIntervalMs: 2e3,
|
|
216
266
|
signal: options.signal,
|
|
217
267
|
progress: options.promoteProgress
|
|
218
268
|
});
|
|
219
269
|
if (promoteResult.isErr()) throw new Error(promoteResult.error.message);
|
|
220
|
-
const [serviceResult, versionResult] = await Promise.all([sdk.
|
|
221
|
-
|
|
270
|
+
const [serviceResult, versionResult] = await Promise.all([sdk.showApp({
|
|
271
|
+
appId: options.appId,
|
|
222
272
|
signal: options.signal
|
|
223
|
-
}), sdk.
|
|
224
|
-
|
|
273
|
+
}), sdk.showDeployment({
|
|
274
|
+
deploymentId: updateResult.value.deploymentId,
|
|
225
275
|
signal: options.signal
|
|
226
276
|
})]);
|
|
227
277
|
if (serviceResult.isErr()) throw new Error(serviceResult.error.message);
|
|
@@ -232,25 +282,25 @@ function createAppProvider(client, options) {
|
|
|
232
282
|
id: serviceResult.value.id,
|
|
233
283
|
name: serviceResult.value.name,
|
|
234
284
|
region: serviceResult.value.region ?? null,
|
|
235
|
-
liveDeploymentId: serviceResult.value.
|
|
236
|
-
liveUrl: toAbsoluteUrl(serviceResult.value.
|
|
285
|
+
liveDeploymentId: serviceResult.value.latestDeploymentId ?? null,
|
|
286
|
+
liveUrl: toAbsoluteUrl(serviceResult.value.appEndpointDomain ?? null)
|
|
237
287
|
},
|
|
238
288
|
deployment: {
|
|
239
289
|
id: versionResult.value.id,
|
|
240
290
|
status: versionResult.value.status,
|
|
241
291
|
createdAt: versionResult.value.createdAt,
|
|
242
|
-
url: toAbsoluteUrl(serviceResult.value.
|
|
292
|
+
url: toAbsoluteUrl(serviceResult.value.appEndpointDomain ?? versionResult.value.previewDomain ?? null),
|
|
243
293
|
live: true
|
|
244
294
|
},
|
|
245
295
|
variables: envVarNames(versionResult.value.envVars)
|
|
246
296
|
};
|
|
247
297
|
},
|
|
248
298
|
async listAppEnvNames(options) {
|
|
249
|
-
const [serviceResult, versionResult] = await Promise.all([sdk.
|
|
250
|
-
|
|
299
|
+
const [serviceResult, versionResult] = await Promise.all([sdk.showApp({
|
|
300
|
+
appId: options.appId,
|
|
251
301
|
signal: options.signal
|
|
252
|
-
}), sdk.
|
|
253
|
-
|
|
302
|
+
}), sdk.showDeployment({
|
|
303
|
+
deploymentId: options.deploymentId,
|
|
254
304
|
signal: options.signal
|
|
255
305
|
})]);
|
|
256
306
|
if (serviceResult.isErr()) throw new Error(serviceResult.error.message);
|
|
@@ -261,25 +311,25 @@ function createAppProvider(client, options) {
|
|
|
261
311
|
id: serviceResult.value.id,
|
|
262
312
|
name: serviceResult.value.name,
|
|
263
313
|
region: serviceResult.value.region ?? null,
|
|
264
|
-
liveDeploymentId: serviceResult.value.
|
|
265
|
-
liveUrl: toAbsoluteUrl(serviceResult.value.
|
|
314
|
+
liveDeploymentId: serviceResult.value.latestDeploymentId ?? null,
|
|
315
|
+
liveUrl: toAbsoluteUrl(serviceResult.value.appEndpointDomain ?? null)
|
|
266
316
|
},
|
|
267
317
|
deployment: {
|
|
268
318
|
id: versionResult.value.id,
|
|
269
319
|
status: versionResult.value.status,
|
|
270
320
|
createdAt: versionResult.value.createdAt,
|
|
271
321
|
url: toAbsoluteUrl(versionResult.value.previewDomain ?? null),
|
|
272
|
-
live: serviceResult.value.
|
|
322
|
+
live: serviceResult.value.latestDeploymentId === versionResult.value.id
|
|
273
323
|
},
|
|
274
324
|
variables: envVarNames(versionResult.value.envVars)
|
|
275
325
|
};
|
|
276
326
|
},
|
|
277
327
|
async listDeployments(appId, options) {
|
|
278
|
-
const [appResult, versionsResult] = await Promise.all([sdk.
|
|
279
|
-
|
|
328
|
+
const [appResult, versionsResult] = await Promise.all([sdk.showApp({
|
|
329
|
+
appId,
|
|
280
330
|
signal: options?.signal
|
|
281
|
-
}), sdk.
|
|
282
|
-
|
|
331
|
+
}), sdk.listDeployments({
|
|
332
|
+
appId,
|
|
283
333
|
signal: options?.signal
|
|
284
334
|
})]);
|
|
285
335
|
if (appResult.isErr()) throw new Error(appResult.error.message);
|
|
@@ -289,8 +339,8 @@ function createAppProvider(client, options) {
|
|
|
289
339
|
id: appResult.value.id,
|
|
290
340
|
name: appResult.value.name,
|
|
291
341
|
region: appResult.value.region ?? null,
|
|
292
|
-
liveDeploymentId: appResult.value.
|
|
293
|
-
liveUrl: toAbsoluteUrl(appResult.value.
|
|
342
|
+
liveDeploymentId: appResult.value.latestDeploymentId ?? null,
|
|
343
|
+
liveUrl: toAbsoluteUrl(appResult.value.appEndpointDomain ?? null)
|
|
294
344
|
},
|
|
295
345
|
deployments: versionsResult.value.slice().sort((left, right) => {
|
|
296
346
|
const byDate = right.createdAt.localeCompare(left.createdAt);
|
|
@@ -305,21 +355,23 @@ function createAppProvider(client, options) {
|
|
|
305
355
|
};
|
|
306
356
|
},
|
|
307
357
|
async showDeployment(deploymentId, options) {
|
|
308
|
-
const deploymentResult = await sdk.
|
|
309
|
-
|
|
358
|
+
const deploymentResult = await sdk.showDeployment({
|
|
359
|
+
deploymentId,
|
|
310
360
|
signal: options?.signal
|
|
311
361
|
});
|
|
312
362
|
if (deploymentResult.isErr()) {
|
|
313
363
|
if (ApiError.is(deploymentResult.error) && deploymentResult.error.statusCode === 404) return null;
|
|
314
364
|
throw new Error(deploymentResult.error.message);
|
|
315
365
|
}
|
|
366
|
+
const app = await findAppForDeployment(sdk, deploymentId, options?.signal);
|
|
367
|
+
const promotedUrl = app !== null && app.liveDeploymentId === deploymentResult.value.id ? app.liveUrl : null;
|
|
316
368
|
return {
|
|
317
|
-
app
|
|
369
|
+
app,
|
|
318
370
|
deployment: {
|
|
319
371
|
id: deploymentResult.value.id,
|
|
320
372
|
status: deploymentResult.value.status,
|
|
321
373
|
createdAt: deploymentResult.value.createdAt,
|
|
322
|
-
url: toAbsoluteUrl(deploymentResult.value.previewDomain ?? null),
|
|
374
|
+
url: promotedUrl ?? toAbsoluteUrl(deploymentResult.value.previewDomain ?? null),
|
|
323
375
|
live: null
|
|
324
376
|
}
|
|
325
377
|
};
|
|
@@ -329,7 +381,7 @@ function createAppProvider(client, options) {
|
|
|
329
381
|
const result = await streamLogs({
|
|
330
382
|
baseUrl: options.baseUrl,
|
|
331
383
|
token: await options.getToken(),
|
|
332
|
-
|
|
384
|
+
deploymentId: streamOptions.deploymentId,
|
|
333
385
|
signal: streamOptions.signal
|
|
334
386
|
}, streamOptions.onRecord);
|
|
335
387
|
if (result.isErr()) {
|
|
@@ -382,7 +434,7 @@ async function listComputeServices(client, options) {
|
|
|
382
434
|
const services = [];
|
|
383
435
|
let cursor;
|
|
384
436
|
while (true) {
|
|
385
|
-
const result = await client.GET("/v1/
|
|
437
|
+
const result = await client.GET("/v1/apps", {
|
|
386
438
|
params: { query: {
|
|
387
439
|
projectId: options.projectId,
|
|
388
440
|
branchGitName: options.branchGitName,
|
|
@@ -395,18 +447,62 @@ async function listComputeServices(client, options) {
|
|
|
395
447
|
if (!result.data.pagination.hasMore || !result.data.pagination.nextCursor) break;
|
|
396
448
|
cursor = result.data.pagination.nextCursor;
|
|
397
449
|
}
|
|
398
|
-
return services.map(
|
|
450
|
+
return services.map(toAppRecord);
|
|
451
|
+
}
|
|
452
|
+
function toAppRecord(service) {
|
|
453
|
+
return {
|
|
399
454
|
id: service.id,
|
|
400
455
|
name: service.name,
|
|
401
456
|
region: service.region.id ?? null,
|
|
402
457
|
branchId: service.branchId,
|
|
403
|
-
liveDeploymentId: service.
|
|
404
|
-
liveUrl: toAbsoluteUrl(service.
|
|
405
|
-
}
|
|
458
|
+
liveDeploymentId: service.latestDeploymentId ?? null,
|
|
459
|
+
liveUrl: toAbsoluteUrl(service.appEndpointDomain ?? null)
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
/**
|
|
463
|
+
* Creates a service on a branch, resolving (or creating) the branch
|
|
464
|
+
* first because the create body needs its id. A name already taken on
|
|
465
|
+
* the branch comes back as the existing service rather than an error:
|
|
466
|
+
* the API answers 409 and the caller asked for a service by that name,
|
|
467
|
+
* which already exists.
|
|
468
|
+
*/
|
|
469
|
+
async function createComputeService(client, options) {
|
|
470
|
+
const branch = await resolveOrCreateBranch(client, {
|
|
471
|
+
projectId: options.projectId,
|
|
472
|
+
gitName: options.branchName,
|
|
473
|
+
signal: options.signal
|
|
474
|
+
});
|
|
475
|
+
const result = await client.POST("/v1/apps", {
|
|
476
|
+
body: {
|
|
477
|
+
projectId: options.projectId,
|
|
478
|
+
branchId: branch.id,
|
|
479
|
+
displayName: options.displayName,
|
|
480
|
+
...options.region ? { regionId: options.region } : {}
|
|
481
|
+
},
|
|
482
|
+
signal: options.signal
|
|
483
|
+
});
|
|
484
|
+
if (result.error || !result.data) {
|
|
485
|
+
if (result.response.status === 409) {
|
|
486
|
+
const matched = (await listComputeServices(client, {
|
|
487
|
+
projectId: options.projectId,
|
|
488
|
+
branchGitName: options.branchName,
|
|
489
|
+
signal: options.signal
|
|
490
|
+
})).find((service) => service.name === options.displayName);
|
|
491
|
+
if (matched) return {
|
|
492
|
+
service: matched,
|
|
493
|
+
existing: true
|
|
494
|
+
};
|
|
495
|
+
}
|
|
496
|
+
throw apiCallError(`Failed to create app "${options.displayName}"`, result.response, result.error);
|
|
497
|
+
}
|
|
498
|
+
return {
|
|
499
|
+
service: toAppRecord(result.data.data),
|
|
500
|
+
existing: false
|
|
501
|
+
};
|
|
406
502
|
}
|
|
407
|
-
async function listComputeServiceDomains(client,
|
|
408
|
-
const result = await client.GET("/v1/
|
|
409
|
-
params: { path: {
|
|
503
|
+
async function listComputeServiceDomains(client, appId, signal) {
|
|
504
|
+
const result = await client.GET("/v1/apps/{appId}/domains", {
|
|
505
|
+
params: { path: { appId } },
|
|
410
506
|
signal
|
|
411
507
|
});
|
|
412
508
|
if (result.error || !result.data) throw domainApiCallError("Failed to list custom domains", result.response, result.error);
|
|
@@ -418,7 +514,7 @@ function normalizeDomainRecord(domain) {
|
|
|
418
514
|
type: domain.type,
|
|
419
515
|
url: domain.url,
|
|
420
516
|
hostname: domain.hostname,
|
|
421
|
-
|
|
517
|
+
appId: domain.appId,
|
|
422
518
|
status: domain.status,
|
|
423
519
|
foundryStatus: domain.foundryStatus,
|
|
424
520
|
failureReason: domain.failureReason,
|
|
@@ -448,40 +544,17 @@ function normalizeHostnameForComparison(hostname) {
|
|
|
448
544
|
return hostname.trim().replace(/\.$/, "").toLowerCase();
|
|
449
545
|
}
|
|
450
546
|
async function createBranchApp(client, options) {
|
|
451
|
-
const
|
|
547
|
+
const created = await createComputeService(client, {
|
|
452
548
|
projectId: options.projectId,
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
body: {
|
|
458
|
-
projectId: options.projectId,
|
|
459
|
-
branchId: branch.id,
|
|
460
|
-
displayName: options.appName,
|
|
461
|
-
...options.region ? { regionId: options.region } : {}
|
|
462
|
-
},
|
|
463
|
-
signal: options.signal
|
|
549
|
+
branchName: options.branchName,
|
|
550
|
+
displayName: options.appName,
|
|
551
|
+
...options.region !== void 0 ? { region: options.region } : {},
|
|
552
|
+
...options.signal !== void 0 ? { signal: options.signal } : {}
|
|
464
553
|
});
|
|
465
|
-
if (result.error || !result.data) {
|
|
466
|
-
if (result.response.status === 409) {
|
|
467
|
-
const matched = (await listComputeServices(client, {
|
|
468
|
-
projectId: options.projectId,
|
|
469
|
-
branchGitName: options.branchName,
|
|
470
|
-
signal: options.signal
|
|
471
|
-
})).find((app) => app.name === options.appName);
|
|
472
|
-
if (matched) return {
|
|
473
|
-
appId: matched.id,
|
|
474
|
-
appName: matched.name,
|
|
475
|
-
region: matched.region ?? options.region
|
|
476
|
-
};
|
|
477
|
-
}
|
|
478
|
-
throw apiCallError(`Failed to create app "${options.appName}"`, result.response, result.error);
|
|
479
|
-
}
|
|
480
|
-
const service = result.data.data;
|
|
481
554
|
return {
|
|
482
|
-
appId: service.id,
|
|
483
|
-
appName: service.name,
|
|
484
|
-
region: service.region
|
|
555
|
+
appId: created.service.id,
|
|
556
|
+
appName: created.service.name,
|
|
557
|
+
region: created.service.region ?? options.region
|
|
485
558
|
};
|
|
486
559
|
}
|
|
487
560
|
function apiCallError(summary, response, error) {
|
|
@@ -503,7 +576,7 @@ async function findAppForDeployment(sdk, deploymentId, signal) {
|
|
|
503
576
|
const projectsResult = await sdk.listProjects({ signal });
|
|
504
577
|
if (projectsResult.isErr()) throw new Error(projectsResult.error.message);
|
|
505
578
|
for (const project of projectsResult.value) {
|
|
506
|
-
const servicesResult = await sdk.
|
|
579
|
+
const servicesResult = await sdk.listApps({
|
|
507
580
|
projectId: project.id,
|
|
508
581
|
signal
|
|
509
582
|
});
|
|
@@ -516,8 +589,8 @@ async function findAppForDeployment(sdk, deploymentId, signal) {
|
|
|
516
589
|
return null;
|
|
517
590
|
}
|
|
518
591
|
async function findServiceAppForDeployment(sdk, serviceId, deploymentId, signal) {
|
|
519
|
-
const detailResult = await sdk.
|
|
520
|
-
serviceId,
|
|
592
|
+
const detailResult = await sdk.showApp({
|
|
593
|
+
appId: serviceId,
|
|
521
594
|
signal
|
|
522
595
|
});
|
|
523
596
|
if (detailResult.isErr()) throw new Error(detailResult.error.message);
|
|
@@ -525,12 +598,12 @@ async function findServiceAppForDeployment(sdk, serviceId, deploymentId, signal)
|
|
|
525
598
|
id: detailResult.value.id,
|
|
526
599
|
name: detailResult.value.name,
|
|
527
600
|
region: detailResult.value.region ?? null,
|
|
528
|
-
liveDeploymentId: detailResult.value.
|
|
529
|
-
liveUrl: toAbsoluteUrl(detailResult.value.
|
|
601
|
+
liveDeploymentId: detailResult.value.latestDeploymentId ?? null,
|
|
602
|
+
liveUrl: toAbsoluteUrl(detailResult.value.appEndpointDomain ?? null)
|
|
530
603
|
};
|
|
531
604
|
if (app.liveDeploymentId === deploymentId) return app;
|
|
532
|
-
const versionsResult = await sdk.
|
|
533
|
-
serviceId,
|
|
605
|
+
const versionsResult = await sdk.listDeployments({
|
|
606
|
+
appId: serviceId,
|
|
534
607
|
signal
|
|
535
608
|
});
|
|
536
609
|
if (versionsResult.isErr()) throw new Error(versionsResult.error.message);
|
|
@@ -1,61 +1,86 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { formatCommandArgument } from "../../command-arguments.js";
|
|
2
|
+
import { CliError, usageError } from "../../errors.js";
|
|
3
3
|
import { renderSummaryLine } from "../../shell/ui.js";
|
|
4
4
|
import { canPrompt } from "../../shell/runtime.js";
|
|
5
|
-
import {
|
|
6
|
-
import "../project/setup.js";
|
|
5
|
+
import { confirmPrompt } from "../../shell/prompt.js";
|
|
7
6
|
import { hasBranchDatabaseSignal, inspectBranchDatabaseSignal } from "./branch-database.js";
|
|
8
7
|
import path from "node:path";
|
|
9
8
|
//#region src/lib/app/branch-database-deploy.ts
|
|
10
9
|
async function maybeSetupBranchDatabase(context, provider, projectId, branch, options) {
|
|
11
10
|
if (options.db === false) return emptyBranchDatabaseSetupOutcome();
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
if (branch.kind === "production" && !options.firstProductionDeploy) {
|
|
17
|
-
if (options.db === true) throw productionDatabaseSetupAfterFirstDeployError();
|
|
11
|
+
const databaseRequested = options.db === true;
|
|
12
|
+
const conflict = findBranchDatabaseSetupConflict(branch, options);
|
|
13
|
+
if (conflict) {
|
|
14
|
+
if (databaseRequested) throw branchDatabaseSetupConflictError(conflict);
|
|
18
15
|
return emptyBranchDatabaseSetupOutcome();
|
|
19
16
|
}
|
|
20
17
|
const envState = await inspectBranchDatabaseEnv(provider, projectId, branch, context.runtime.signal);
|
|
21
|
-
|
|
22
|
-
if (hasExistingDatabaseEnvForTarget(branch, envState)) {
|
|
23
|
-
const warning = options.db === true ? existingDatabaseEnvWarning(branch, targetEnvVars) : null;
|
|
24
|
-
if (warning) emitBranchDatabaseWarning(context, warning);
|
|
25
|
-
return {
|
|
26
|
-
result: options.db === true ? {
|
|
27
|
-
status: "skipped",
|
|
28
|
-
reason: existingDatabaseEnvReason(branch),
|
|
29
|
-
envVars: targetEnvVars
|
|
30
|
-
} : void 0,
|
|
31
|
-
warnings: warning ? [warning] : []
|
|
32
|
-
};
|
|
33
|
-
}
|
|
18
|
+
if (hasExistingDatabaseEnvForTarget(branch, envState)) return existingDatabaseEnvOutcome(context, branch, envState, databaseRequested);
|
|
34
19
|
const localSignal = await inspectBranchDatabaseSignal(options.projectDir, context.runtime.signal);
|
|
35
20
|
if (localSignal.unsupportedSchema) {
|
|
36
|
-
if (
|
|
21
|
+
if (databaseRequested) throw unsupportedBranchDatabaseSchemaError(localSignal.unsupportedSchema, branch, context);
|
|
37
22
|
return emptyBranchDatabaseSetupOutcome();
|
|
38
23
|
}
|
|
39
|
-
const
|
|
40
|
-
if (
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
24
|
+
const confirmation = await confirmBranchDatabaseSetup(context, branch, localSignal, envState, databaseRequested);
|
|
25
|
+
if (!confirmation.confirmed) return confirmation.outcome;
|
|
26
|
+
return setupBranchDatabase(context, provider, projectId, branch, localSignal, envState, options.projectDir);
|
|
27
|
+
}
|
|
28
|
+
function findBranchDatabaseSetupConflict(branch, options) {
|
|
29
|
+
if (hasProvidedDatabaseEnvVars(options.providedEnvVars)) return "provided-env-vars";
|
|
30
|
+
if (branch.kind === "production" && !options.firstProductionDeploy) return "production-after-first-deploy";
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
function branchDatabaseSetupConflictError(conflict) {
|
|
34
|
+
switch (conflict) {
|
|
35
|
+
case "provided-env-vars": return providedDatabaseEnvVarsError();
|
|
36
|
+
case "production-after-first-deploy": return productionDatabaseSetupAfterFirstDeployError();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function existingDatabaseEnvOutcome(context, branch, envState, databaseRequested) {
|
|
40
|
+
if (!databaseRequested) return emptyBranchDatabaseSetupOutcome();
|
|
41
|
+
const envVars = getTargetDatabaseEnvVarKeys(envState);
|
|
42
|
+
const warning = existingDatabaseEnvWarning(branch, envVars);
|
|
43
|
+
emitBranchDatabaseWarning(context, warning);
|
|
44
|
+
return {
|
|
45
|
+
result: {
|
|
46
|
+
status: "skipped",
|
|
47
|
+
reason: existingDatabaseEnvReason(branch),
|
|
48
|
+
envVars
|
|
49
|
+
},
|
|
50
|
+
warnings: [warning]
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
async function confirmBranchDatabaseSetup(context, branch, signal, envState, databaseRequested) {
|
|
54
|
+
if (databaseRequested) {
|
|
55
|
+
if (!canPrompt(context) && !context.flags.yes) throw nonInteractiveDatabaseSetupRequiresYesError(branch);
|
|
56
|
+
return { confirmed: true };
|
|
57
|
+
}
|
|
58
|
+
if (!(hasBranchDatabaseSignal(signal) || Boolean(envState.inheritedPreviewDatabaseUrl))) return {
|
|
59
|
+
confirmed: false,
|
|
60
|
+
outcome: emptyBranchDatabaseSetupOutcome()
|
|
61
|
+
};
|
|
62
|
+
if (!canPrompt(context) || context.flags.yes) {
|
|
63
|
+
const warning = databasePromptSuppressedWarning(branch);
|
|
64
|
+
emitBranchDatabaseWarning(context, warning);
|
|
65
|
+
return {
|
|
66
|
+
confirmed: false,
|
|
67
|
+
outcome: {
|
|
46
68
|
result: void 0,
|
|
47
69
|
warnings: [warning]
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
maybeRenderBranchDatabaseSignal(context, branch, signal, envState);
|
|
74
|
+
return await confirmPrompt({
|
|
75
|
+
input: context.runtime.stdin,
|
|
76
|
+
output: context.output.stderr,
|
|
77
|
+
signal: context.runtime.signal,
|
|
78
|
+
message: databasePromptMessage(branch),
|
|
79
|
+
initialValue: false
|
|
80
|
+
}) ? { confirmed: true } : {
|
|
81
|
+
confirmed: false,
|
|
82
|
+
outcome: emptyBranchDatabaseSetupOutcome()
|
|
83
|
+
};
|
|
59
84
|
}
|
|
60
85
|
async function setupBranchDatabase(context, provider, projectId, branch, signal, envState, projectDir) {
|
|
61
86
|
emitBranchDatabaseProgress(context, "pending", "Creating database");
|
|
@@ -224,6 +249,9 @@ function emptyBranchDatabaseSetupOutcome() {
|
|
|
224
249
|
warnings: []
|
|
225
250
|
};
|
|
226
251
|
}
|
|
252
|
+
function providedDatabaseEnvVarsError() {
|
|
253
|
+
return usageError("Database setup cannot be combined with provided database env vars", "The deploy command received --db and a DATABASE_URL or DIRECT_URL value from --env.", "Remove the --env database value to let --db create and wire a database, or remove --db to deploy with the provided value.", ["prisma-cli app deploy --db", "prisma-cli app deploy --env DATABASE_URL=postgresql://example"], "app");
|
|
254
|
+
}
|
|
227
255
|
function productionDatabaseSetupAfterFirstDeployError() {
|
|
228
256
|
return usageError("Database setup is only available during the first production deploy", "The selected production app already has a live deployment.", "Use project env commands to manage production DATABASE_URL, or deploy a preview branch with --db.", ["prisma-cli project env add DATABASE_URL=<value> --role production", "prisma-cli app deploy --branch feature/db --db"], "app");
|
|
229
257
|
}
|