void 0.20.2 → 0.20.3

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 (68) hide show
  1. package/dist/{auth-cmd-gniL2fNt.mjs → auth-cmd-CzwquNiP.mjs} +3 -3
  2. package/dist/{auth-link-NZdjCmSc.mjs → auth-link-ElDTgF7j.mjs} +3 -3
  3. package/dist/{build-cmd-sI18tX_O.mjs → build-cmd-BpJe6boP.mjs} +1 -1
  4. package/dist/{cache-IHn5MwBC.mjs → cache-D98YTqeE.mjs} +1 -1
  5. package/dist/{cancel-deploy-C5qTOdLi.mjs → cancel-deploy-CPbEQLMG.mjs} +1 -1
  6. package/dist/cli/cli.mjs +27 -26
  7. package/dist/{client-dHfSJvAN.mjs → client-BQBrZoCX.mjs} +143 -78
  8. package/dist/{connect-Bfk31O_8.mjs → connect-WCQZ_u3m.mjs} +3 -3
  9. package/dist/{create-project-Bk9Z0-Jg.mjs → create-project-D0oXA090.mjs} +2 -3
  10. package/dist/{db-BkRoptAt.mjs → db-DJ-9qs3S.mjs} +2 -2
  11. package/dist/{delete-DouASY9P.mjs → delete-BZ4-WaGm.mjs} +1 -1
  12. package/dist/{deploy-DTaWUS1S.mjs → deploy-BAhhcg5q.mjs} +17 -10
  13. package/dist/{domain-1RhhOVrC.mjs → domain-BxAyhxXN.mjs} +1 -1
  14. package/dist/{email-C-lGh51B.mjs → email-Bj7Cvdwp.mjs} +2 -2
  15. package/dist/{env-DJHsPE7Z.mjs → env-DP_EErve.mjs} +1 -1
  16. package/dist/{github-cmd-PW7ZnWTp.mjs → github-cmd-C-z_xRrQ.mjs} +13 -19
  17. package/dist/index.mjs +4 -4
  18. package/dist/{init-BWZ7q5Z4.mjs → init-BGktCXgA.mjs} +4 -4
  19. package/dist/{link-Rmvu2Wl_.mjs → link-D2kbqhWb.mjs} +2 -2
  20. package/dist/{list-DEE2S6mY.mjs → list-CvkK_G7k.mjs} +1 -1
  21. package/dist/{login-Uvferzmm.mjs → login-WIjNc77c.mjs} +2 -2
  22. package/dist/{logs-27FenuiC.mjs → logs-dLUFCapG.mjs} +1 -1
  23. package/dist/{operator-cmd-CjOTmAYE.mjs → operator-cmd-CKJ7xIRs.mjs} +2 -2
  24. package/dist/{platform-auth-config-DrbQXXiW.mjs → platform-auth-config-CdVWRRJr.mjs} +2 -2
  25. package/dist/{platform-auth-protection-Bhtvp0B_.mjs → platform-auth-protection-Drl0qhrn.mjs} +2 -2
  26. package/dist/{platform-auth-recovery-CeOKGVeJ.mjs → platform-auth-recovery-CmKEWpDo.mjs} +2 -2
  27. package/dist/{platform-cmd-BFhieCdV.mjs → platform-cmd-5q_k56xS.mjs} +3 -3
  28. package/dist/{platform-domain-C74PULqV.mjs → platform-domain-4GiDlcqx.mjs} +2 -2
  29. package/dist/{platform-lifecycle-BwAIgz-t.mjs → platform-lifecycle-R9xAxvtG.mjs} +61 -25
  30. package/dist/{platform-management-COogu_Se.mjs → platform-management-BfWsXHEW.mjs} +5 -3
  31. package/dist/{platform-recovery-ewqLefp1.mjs → platform-recovery-CbK-I1FB.mjs} +2 -2
  32. package/dist/{project-cmd-DmZK9Hxf.mjs → project-cmd-CTdmnzvc.mjs} +12 -12
  33. package/dist/{project-team-D8jOJMUJ.mjs → project-team-CGxsQe3_.mjs} +4 -2
  34. package/dist/{project-token-DA34bf-C.mjs → project-token-Cirx7uwZ.mjs} +1 -1
  35. package/dist/{requests-CUExwGQQ.mjs → requests-4Nq59hOr.mjs} +1 -1
  36. package/dist/{rollback-CDNGU1gr.mjs → rollback-Dr7u0Ljx.mjs} +1 -1
  37. package/dist/runtime/remote/index.mjs +49 -8
  38. package/dist/runtime/sandbox.d.mts +4 -56
  39. package/dist/runtime/sandbox.mjs +81 -220
  40. package/dist/{secret-Bzzi2e9E.mjs → secret-AcPi-FoA.mjs} +1 -1
  41. package/package.json +7 -7
  42. package/skills/void/SKILL.md +2 -2
  43. package/skills/void/docs/guide/deployment.md +14 -14
  44. package/skills/void/docs/guide/email.md +12 -10
  45. package/skills/void/docs/guide/platform/administration/access.md +163 -0
  46. package/skills/void/docs/guide/platform/administration/email.md +121 -0
  47. package/skills/void/docs/guide/platform/administration/operations.md +97 -0
  48. package/skills/void/docs/guide/platform/administration/projects.md +54 -0
  49. package/skills/void/docs/guide/platform/development/local.md +119 -0
  50. package/skills/void/docs/guide/platform/development/runtime.md +124 -0
  51. package/skills/void/docs/guide/platform/development/schema-ci.md +95 -0
  52. package/skills/void/docs/guide/platform/installation/ci.md +55 -0
  53. package/skills/void/docs/guide/platform/installation/credentials.md +80 -0
  54. package/skills/void/docs/guide/platform/installation/domains.md +68 -0
  55. package/skills/void/docs/guide/platform/installation/first-deployment.md +82 -0
  56. package/skills/void/docs/guide/platform/installation/maintenance.md +137 -0
  57. package/skills/void/docs/guide/platform/installation/prerequisites.md +86 -0
  58. package/skills/void/docs/guide/platform/installation/setup.md +169 -0
  59. package/skills/void/docs/guide/platform/installation/uninstall.md +54 -0
  60. package/skills/void/docs/guide/platform-administration.md +6 -414
  61. package/skills/void/docs/guide/platform-development.md +5 -316
  62. package/skills/void/docs/guide/project-collaboration.md +1 -1
  63. package/skills/void/docs/guide/sandboxes.md +9 -24
  64. package/skills/void/docs/guide/self-hosted-platform.md +11 -694
  65. package/skills/void/docs/reference/api.md +34 -34
  66. package/skills/void/docs/reference/cli.md +28 -11
  67. package/skills/void/docs/reference/config.md +1 -1
  68. package/skills/void/docs/reference/resource-inference.md +10 -10
@@ -4,13 +4,89 @@ import { B as ensureCloudflaredToken, U as isCloudflareAccessChallenge, V as ens
4
4
  import { t as cfAccessHeaders } from "./cf-access-DRsQRe6k.mjs";
5
5
  import { o as getApiUrl } from "./auth-DPl6kck4.mjs";
6
6
  import { readFileSync } from "node:fs";
7
+ import { stripVTControlCharacters } from "node:util";
8
+ //#region src/cli/platform-errors.ts
9
+ function parsePlatformErrorBody(body) {
10
+ try {
11
+ const parsed = JSON.parse(body);
12
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return null;
13
+ const result = {};
14
+ for (const key of [
15
+ "error",
16
+ "message",
17
+ "deployment",
18
+ "minVersion",
19
+ "clientVersion"
20
+ ]) {
21
+ const value = parsed[key];
22
+ if (typeof value === "string") result[key] = value;
23
+ }
24
+ return result;
25
+ } catch {
26
+ return null;
27
+ }
28
+ }
29
+ function plainExplanation(value) {
30
+ const text = value ? stripVTControlCharacters(value).replace(/[\u0000-\u0008\u000b-\u001f\u007f]/g, " ").trim() : void 0;
31
+ return text && !text.startsWith("{") && !text.startsWith("[") && !/<[^>]+>/.test(text) ? text : void 0;
32
+ }
33
+ function platformErrorMessage(payload) {
34
+ const message = plainExplanation(payload?.message);
35
+ return message && !/^(forbidden|unauthorized|access denied|permission denied)[.!]?$/i.test(message) ? message : void 0;
36
+ }
37
+ function unexplainedRejection(status) {
38
+ if (status === 401) return "Authentication was rejected. Check the credentials for the selected platform and any access gateway in front of it.";
39
+ if (status === 403) return "Access was denied by the platform or its access gateway. Check the selected platform and ask its administrator to confirm your access.";
40
+ return "The platform did not provide an explanation. Retry the operation; if it still fails, contact the platform administrator.";
41
+ }
42
+ function permissionMessage(permission) {
43
+ if (permission === "owner") return "Only the project owner can perform this action. Ask the owner to run it using their platform login.";
44
+ if (permission === "read") return "This action requires project membership (reader or higher). Ask a project admin or owner for access.";
45
+ if (permission === "settings" || permission === "members") return "This action requires admin or owner access. Ask a project admin or owner to confirm your access.";
46
+ if (permission === "configure" || permission === "deploy") return "This action requires collaborator, admin, or owner access. Ask a project admin or owner to confirm your access.";
47
+ return "Ask the platform administrator to check your access to this action.";
48
+ }
49
+ const rejectionMessages = {
50
+ "invalid or expired token": "The platform reported an invalid or expired token. Sign in again with `void connect <platform-url>`, or replace `VOID_TOKEN` if you supplied it.",
51
+ "missing authorization header": "A platform login or token is required. Sign in with `void connect <platform-url>`, or supply a valid `VOID_TOKEN` for that platform.",
52
+ "session revoked; sign in again": "Your platform session was revoked. Sign in again with `void connect <platform-url>`, or replace `VOID_TOKEN` if you supplied it.",
53
+ "user not found": "This account is no longer available. Contact the platform administrator or sign in with an active account on this platform.",
54
+ "deploy credential revoked or expired": "This project deploy credential was revoked or expired. Ask the project owner to issue a replacement and update the credential used by your automation.",
55
+ "deploy token build is no longer active": "This build is no longer active. Start a new build to obtain a valid deployment credential.",
56
+ github_identity_required: "Link your GitHub account with `void github link`, then retry this operation.",
57
+ connect_authorization_required: "This GitHub repository requires authorization. Run `void github connect` in an interactive terminal to authorize access, then retry.",
58
+ "invalid connect grant": "GitHub authorization failed or expired. Run `void github connect` again.",
59
+ "installation access revoked": "Access to this GitHub installation was revoked. Ask its administrator to restore access, then run `void github join`.",
60
+ "account suspended": "This account is suspended. Contact the platform administrator to restore access.",
61
+ "project owner suspended": "The project owner is suspended. Ask the owner to contact the platform administrator.",
62
+ "project is being deleted": "This project is being deleted. Wait for deletion to finish before creating a replacement.",
63
+ "registered user not found": "No registered account matches that email address. Ask the recipient to sign in to this platform first, then invite their registered email.",
64
+ "the project owner cannot be invited or changed as a member": "The project owner cannot be invited or changed through team membership commands. Choose another member.",
65
+ "the project owner cannot leave the project": "The project owner cannot leave. Ask a platform administrator to transfer ownership first.",
66
+ "user is already a project member": "This user is already a project member. Use `void project team list` to find their user ID, then `void project team role` to change their role.",
67
+ "project member not found": "This user is no longer a project member. Run `void project team list` to check current members.",
68
+ "project has too many pending invitations": "This project has reached its pending invitation limit. Run `void project team invitations` and revoke invitations that are no longer needed."
69
+ };
70
+ function formatPlatformApiError(action, status, body, permission) {
71
+ const parsed = parsePlatformErrorBody(body);
72
+ const message = platformErrorMessage(parsed);
73
+ if (status === 426 && parsed?.error === "cli_outdated" && message) return message;
74
+ if (!parsed) {
75
+ if (status === 401 || status === 403) {
76
+ const plain = plainExplanation(body);
77
+ return `${action} (HTTP ${status}): ${plain && !/^(forbidden|unauthorized|access denied|permission denied)[.!]?$/i.test(plain) ? plain.replace(/\s+/g, " ").slice(0, 240) : unexplainedRejection(status)}`;
78
+ }
79
+ return `${action}: ${status} ${body}`;
80
+ }
81
+ return `${action} (HTTP ${status}): ${(message ?? (status === 403 && parsed.error === "forbidden" ? `Access denied. ${permissionMessage(permission)}` : (parsed.error && Object.hasOwn(rejectionMessages, parsed.error) ? rejectionMessages[parsed.error] : void 0) ?? (status === 401 && ["unauthorized", "missing token"].includes(parsed.error ?? "") ? rejectionMessages["invalid or expired token"] : plainExplanation(parsed.error)))) || unexplainedRejection(status)}`;
82
+ }
83
+ //#endregion
7
84
  //#region src/cli/client.ts
8
85
  var client_exports = /* @__PURE__ */ __exportAll({
9
86
  PlatformApiError: () => PlatformApiError,
10
87
  PlatformClient: () => PlatformClient,
11
88
  isCliOutdatedError: () => isCliOutdatedError,
12
89
  isExpiredTokenError: () => isExpiredTokenError,
13
- parsePlatformErrorBody: () => parsePlatformErrorBody,
14
90
  readCliVersion: () => readCliVersion
15
91
  });
16
92
  /**
@@ -36,15 +112,6 @@ function readCliVersion() {
36
112
  }
37
113
  }
38
114
  const VOID_CLI_VERSION = readCliVersion();
39
- function parsePlatformErrorBody(body) {
40
- try {
41
- const parsed = JSON.parse(body);
42
- if (!parsed || typeof parsed !== "object") return null;
43
- return parsed;
44
- } catch {
45
- return null;
46
- }
47
- }
48
115
  /**
49
116
  * Detects the `cli_outdated` 426 response shape emitted by the platform's
50
117
  * `cliVersionGate` middleware. When present, callers should surface the
@@ -61,23 +128,25 @@ var PlatformApiError = class extends Error {
61
128
  status;
62
129
  body;
63
130
  code;
64
- constructor(action, status, body) {
131
+ constructor(action, status, body, permission) {
65
132
  const parsed = parsePlatformErrorBody(body);
66
- const message = status === 426 && parsed?.error === "cli_outdated" && parsed.message ? parsed.message : `${action}: ${status} ${body}`;
67
- super(message);
133
+ super(formatPlatformApiError(action, status, body, permission));
68
134
  this.name = "PlatformApiError";
69
135
  this.status = status;
70
136
  this.body = body;
71
137
  this.code = parsed?.error ?? parsed?.message;
72
138
  }
73
139
  };
74
- async function throwPlatformApiError(action, res) {
75
- throw new PlatformApiError(action, res.status, await res.text());
140
+ async function throwPlatformApiError(action, res, permission) {
141
+ throw new PlatformApiError(action, res.status, await res.text(), isCloudflareAccessChallenge(res) ? void 0 : permission);
76
142
  }
77
143
  function isExpiredTokenError(error) {
78
144
  if (error instanceof PlatformApiError) return error.status === 401 && error.code === "invalid or expired token";
79
145
  return false;
80
146
  }
147
+ function isPreflightRejection(error) {
148
+ return error instanceof PlatformApiError && ([401, 403].includes(error.status) && !!parsePlatformErrorBody(error.body)?.error || isCliOutdatedError(error));
149
+ }
81
150
  /**
82
151
  * Retry contract for the deploy POST's transport phase.
83
152
  *
@@ -176,7 +245,7 @@ var PlatformClient = class {
176
245
  }
177
246
  async listProjectTokens(projectId) {
178
247
  const res = await this.request(`${this.baseUrl}/projects/${projectId}/tokens`, { headers: { ...this.authHeaders } });
179
- if (!res.ok) await throwPlatformApiError("Failed to list project tokens", res);
248
+ if (!res.ok) await throwPlatformApiError("Failed to list project tokens", res, "owner");
180
249
  return res.json();
181
250
  }
182
251
  async createProjectToken(projectId, input) {
@@ -188,17 +257,17 @@ var PlatformClient = class {
188
257
  },
189
258
  body: JSON.stringify(input)
190
259
  });
191
- if (!res.ok) await throwPlatformApiError("Failed to create project token", res);
260
+ if (!res.ok) await throwPlatformApiError("Failed to create project token", res, "owner");
192
261
  return res.json();
193
262
  }
194
263
  async listProjectMembers(projectId) {
195
264
  const res = await this.request(`${this.baseUrl}/projects/${projectId}/members`, { headers: { ...this.authHeaders } });
196
- if (!res.ok) await throwPlatformApiError("Failed to list project members", res);
265
+ if (!res.ok) await throwPlatformApiError("Failed to list project members", res, "read");
197
266
  return (await res.json()).members;
198
267
  }
199
268
  async listProjectInvitations(projectId) {
200
269
  const res = await this.request(`${this.baseUrl}/projects/${projectId}/invitations`, { headers: { ...this.authHeaders } });
201
- if (!res.ok) await throwPlatformApiError("Failed to list project invitations", res);
270
+ if (!res.ok) await throwPlatformApiError("Failed to list project invitations", res, "members");
202
271
  return (await res.json()).invitations;
203
272
  }
204
273
  async inviteProjectMember(projectId, email, role) {
@@ -213,7 +282,7 @@ var PlatformClient = class {
213
282
  role
214
283
  })
215
284
  });
216
- if (!res.ok) await throwPlatformApiError("Failed to invite project member", res);
285
+ if (!res.ok) await throwPlatformApiError("Failed to invite project member", res, "members");
217
286
  return res.json();
218
287
  }
219
288
  async renewProjectToken(projectId, credentialId, expiresInDays) {
@@ -225,7 +294,7 @@ var PlatformClient = class {
225
294
  },
226
295
  body: JSON.stringify(expiresInDays ? { expiresInDays } : {})
227
296
  });
228
- if (!res.ok) await throwPlatformApiError("Failed to renew project token", res);
297
+ if (!res.ok) await throwPlatformApiError("Failed to renew project token", res, "owner");
229
298
  return res.json();
230
299
  }
231
300
  async updateProjectMemberRole(projectId, userId, role) {
@@ -237,7 +306,7 @@ var PlatformClient = class {
237
306
  },
238
307
  body: JSON.stringify({ role })
239
308
  });
240
- if (!res.ok) await throwPlatformApiError("Failed to change project member role", res);
309
+ if (!res.ok) await throwPlatformApiError("Failed to change project member role", res, "members");
241
310
  return res.json();
242
311
  }
243
312
  async revokeProjectToken(projectId, credentialId) {
@@ -245,7 +314,7 @@ var PlatformClient = class {
245
314
  method: "DELETE",
246
315
  headers: { ...this.authHeaders }
247
316
  });
248
- if (!res.ok) await throwPlatformApiError("Failed to revoke project token", res);
317
+ if (!res.ok) await throwPlatformApiError("Failed to revoke project token", res, "owner");
249
318
  return res.json();
250
319
  }
251
320
  async removeProjectMember(projectId, userId) {
@@ -253,14 +322,14 @@ var PlatformClient = class {
253
322
  method: "DELETE",
254
323
  headers: { ...this.authHeaders }
255
324
  });
256
- if (!res.ok) await throwPlatformApiError("Failed to remove project member", res);
325
+ if (!res.ok) await throwPlatformApiError("Failed to remove project member", res, "members");
257
326
  }
258
327
  async revokeProjectInvitation(projectId, invitationId) {
259
328
  const res = await this.request(`${this.baseUrl}/projects/${projectId}/invitations/${encodeURIComponent(invitationId)}`, {
260
329
  method: "DELETE",
261
330
  headers: { ...this.authHeaders }
262
331
  });
263
- if (!res.ok) await throwPlatformApiError("Failed to revoke project invitation", res);
332
+ if (!res.ok) await throwPlatformApiError("Failed to revoke project invitation", res, "members");
264
333
  }
265
334
  async leaveProject(projectId) {
266
335
  const res = await this.request(`${this.baseUrl}/projects/${projectId}/leave`, {
@@ -283,7 +352,7 @@ var PlatformClient = class {
283
352
  }
284
353
  async listDeployments(projectId) {
285
354
  const res = await this.request(`${this.baseUrl}/projects/${projectId}/deployments`, { headers: { ...this.authHeaders } });
286
- if (!res.ok) await throwPlatformApiError("Failed to list deployments", res);
355
+ if (!res.ok) await throwPlatformApiError("Failed to list deployments", res, "read");
287
356
  return res.json();
288
357
  }
289
358
  async rollback(projectId, deploymentId, options) {
@@ -297,7 +366,7 @@ var PlatformClient = class {
297
366
  },
298
367
  body: JSON.stringify(body)
299
368
  });
300
- if (!res.ok) await throwPlatformApiError("Rollback failed", res);
369
+ if (!res.ok) await throwPlatformApiError("Rollback failed", res, "deploy");
301
370
  return res.json();
302
371
  }
303
372
  async cancelDeployment(projectId, deploymentId) {
@@ -305,7 +374,7 @@ var PlatformClient = class {
305
374
  method: "POST",
306
375
  headers: { ...this.authHeaders }
307
376
  });
308
- if (!res.ok) await throwPlatformApiError("Cancel deployment failed", res);
377
+ if (!res.ok) await throwPlatformApiError("Cancel deployment failed", res, "deploy");
309
378
  return res.json();
310
379
  }
311
380
  async createProject(slug) {
@@ -335,8 +404,8 @@ var PlatformClient = class {
335
404
  })
336
405
  });
337
406
  if (!res.ok) {
338
- const error = new PlatformApiError("Preflight failed", res.status, await res.text());
339
- if (isExpiredTokenError(error)) throw error;
407
+ const error = new PlatformApiError("Preflight failed", res.status, await res.text(), isCloudflareAccessChallenge(res) ? void 0 : "deploy");
408
+ if (isPreflightRejection(error)) throw error;
340
409
  return {
341
410
  needed: Object.keys(assetManifest),
342
411
  total,
@@ -345,7 +414,7 @@ var PlatformClient = class {
345
414
  }
346
415
  return res.json();
347
416
  } catch (error) {
348
- if (isExpiredTokenError(error)) throw error;
417
+ if (isPreflightRejection(error)) throw error;
349
418
  return {
350
419
  needed: Object.keys(assetManifest),
351
420
  total,
@@ -380,7 +449,7 @@ var PlatformClient = class {
380
449
  cfRay,
381
450
  cfCacheStatus
382
451
  });
383
- if (!res.ok) await throwPlatformApiError("Failed to request upload URLs", res);
452
+ if (!res.ok) await throwPlatformApiError("Failed to request upload URLs", res, "deploy");
384
453
  return (await res.json()).urls;
385
454
  }
386
455
  /**
@@ -440,11 +509,7 @@ var PlatformClient = class {
440
509
  if (!res.ok) {
441
510
  const body = await res.text();
442
511
  if (res.status === 409) {
443
- let parsed = null;
444
- try {
445
- const raw = JSON.parse(body);
446
- if (raw !== null && typeof raw === "object") parsed = raw;
447
- } catch {}
512
+ const parsed = parsePlatformErrorBody(body);
448
513
  if (parsed?.deployment) {
449
514
  cliLog?.warn("deploy_conflict", {
450
515
  url,
@@ -454,12 +519,12 @@ var PlatformClient = class {
454
519
  yield {
455
520
  event: "error",
456
521
  step: "finalize",
457
- message: `${parsed.error ?? "deploy in progress"}: deployment ${parsed.deployment} — it may be an earlier attempt of this deploy or a concurrent one; inspect with \`void project status\` before redeploying`
522
+ message: `${platformErrorMessage(parsed) ?? platformErrorMessage({ message: parsed.error }) ?? "deploy in progress"}: deployment ${parsed.deployment} — it may be an earlier attempt of this deploy or a concurrent one; inspect with \`void project status\` before redeploying`
458
523
  };
459
524
  return;
460
525
  }
461
526
  }
462
- throw new PlatformApiError("Deploy failed", res.status, body);
527
+ throw new PlatformApiError("Deploy failed", res.status, body, isCloudflareAccessChallenge(res) ? void 0 : "deploy");
463
528
  }
464
529
  const reader = res.body.getReader();
465
530
  const decoder = new TextDecoder();
@@ -514,7 +579,7 @@ var PlatformClient = class {
514
579
  }
515
580
  async listSecrets(projectId) {
516
581
  const res = await this.request(`${this.baseUrl}/projects/${projectId}/secrets`, { headers: { ...this.authHeaders } });
517
- if (!res.ok) await throwPlatformApiError("Failed to list secrets", res);
582
+ if (!res.ok) await throwPlatformApiError("Failed to list secrets", res, "configure");
518
583
  return res.json();
519
584
  }
520
585
  async setSecret(projectId, name, value) {
@@ -526,7 +591,7 @@ var PlatformClient = class {
526
591
  },
527
592
  body: JSON.stringify({ value })
528
593
  });
529
- if (!res.ok) await throwPlatformApiError("Failed to set secret", res);
594
+ if (!res.ok) await throwPlatformApiError("Failed to set secret", res, "configure");
530
595
  return res.json();
531
596
  }
532
597
  async deleteProject(projectId) {
@@ -534,14 +599,14 @@ var PlatformClient = class {
534
599
  method: "DELETE",
535
600
  headers: { ...this.authHeaders }
536
601
  });
537
- if (!res.ok) await throwPlatformApiError("Failed to delete project", res);
602
+ if (!res.ok) await throwPlatformApiError("Failed to delete project", res, "owner");
538
603
  return res.json();
539
604
  }
540
605
  async getMigrationStatus(projectId, dialect) {
541
606
  const url = new URL(`${this.baseUrl}/projects/${projectId}/migrations`);
542
607
  if (dialect) url.searchParams.set("dialect", dialect);
543
608
  const res = await this.request(url, { headers: { ...this.authHeaders } });
544
- if (!res.ok) await throwPlatformApiError("Failed to get migration status", res);
609
+ if (!res.ok) await throwPlatformApiError("Failed to get migration status", res, "read");
545
610
  return res.json();
546
611
  }
547
612
  async applyRemoteMigrations(projectId, migrations) {
@@ -553,7 +618,7 @@ var PlatformClient = class {
553
618
  },
554
619
  body: JSON.stringify({ migrations })
555
620
  });
556
- if (!res.ok) await throwPlatformApiError("Failed to apply remote migrations", res);
621
+ if (!res.ok) await throwPlatformApiError("Failed to apply remote migrations", res, "configure");
557
622
  return res.json();
558
623
  }
559
624
  async renameMigrations(projectId, renames) {
@@ -565,7 +630,7 @@ var PlatformClient = class {
565
630
  },
566
631
  body: JSON.stringify({ renames })
567
632
  });
568
- if (!res.ok) await throwPlatformApiError("Failed to rename remote migrations", res);
633
+ if (!res.ok) await throwPlatformApiError("Failed to rename remote migrations", res, "configure");
569
634
  return res.json();
570
635
  }
571
636
  async addDomain(projectId, hostname) {
@@ -577,17 +642,17 @@ var PlatformClient = class {
577
642
  },
578
643
  body: JSON.stringify({ hostname })
579
644
  });
580
- if (!res.ok) await throwPlatformApiError("Failed to add domain", res);
645
+ if (!res.ok) await throwPlatformApiError("Failed to add domain", res, "settings");
581
646
  return res.json();
582
647
  }
583
648
  async listDomains(projectId) {
584
649
  const res = await this.request(`${this.baseUrl}/projects/${projectId}/domains`, { headers: { ...this.authHeaders } });
585
- if (!res.ok) await throwPlatformApiError("Failed to list domains", res);
650
+ if (!res.ok) await throwPlatformApiError("Failed to list domains", res, "read");
586
651
  return res.json();
587
652
  }
588
653
  async getDomainStatus(projectId, domainId) {
589
654
  const res = await this.request(`${this.baseUrl}/projects/${projectId}/domains/${domainId}`, { headers: { ...this.authHeaders } });
590
- if (!res.ok) await throwPlatformApiError("Failed to get domain status", res);
655
+ if (!res.ok) await throwPlatformApiError("Failed to get domain status", res, "read");
591
656
  return res.json();
592
657
  }
593
658
  async removeDomain(projectId, domainId) {
@@ -595,7 +660,7 @@ var PlatformClient = class {
595
660
  method: "DELETE",
596
661
  headers: { ...this.authHeaders }
597
662
  });
598
- if (!res.ok) await throwPlatformApiError("Failed to remove domain", res);
663
+ if (!res.ok) await throwPlatformApiError("Failed to remove domain", res, "settings");
599
664
  return res.json();
600
665
  }
601
666
  async deleteSecret(projectId, name) {
@@ -603,12 +668,12 @@ var PlatformClient = class {
603
668
  method: "DELETE",
604
669
  headers: { ...this.authHeaders }
605
670
  });
606
- if (!res.ok) await throwPlatformApiError("Failed to delete secret", res);
671
+ if (!res.ok) await throwPlatformApiError("Failed to delete secret", res, "configure");
607
672
  return res.json();
608
673
  }
609
674
  async getResources(projectId) {
610
675
  const res = await this.request(`${this.baseUrl}/projects/${projectId}/resources`, { headers: { ...this.authHeaders } });
611
- if (!res.ok) await throwPlatformApiError("Failed to get resources", res);
676
+ if (!res.ok) await throwPlatformApiError("Failed to get resources", res, "read");
612
677
  return res.json();
613
678
  }
614
679
  async createPrerenderToken(projectId) {
@@ -616,7 +681,7 @@ var PlatformClient = class {
616
681
  method: "POST",
617
682
  headers: { ...this.authHeaders }
618
683
  });
619
- if (!res.ok) await throwPlatformApiError("Failed to create prerender token", res);
684
+ if (!res.ok) await throwPlatformApiError("Failed to create prerender token", res, "deploy");
620
685
  return (await res.json()).token;
621
686
  }
622
687
  async provisionDatabase(projectId, connectionString) {
@@ -628,7 +693,7 @@ var PlatformClient = class {
628
693
  },
629
694
  body: JSON.stringify({ connectionString })
630
695
  });
631
- if (!res.ok) await throwPlatformApiError("Failed to provision database", res);
696
+ if (!res.ok) await throwPlatformApiError("Failed to provision database", res, "configure");
632
697
  return res.json();
633
698
  }
634
699
  async setDatabaseUrl(projectId, connectionString) {
@@ -640,12 +705,12 @@ var PlatformClient = class {
640
705
  },
641
706
  body: JSON.stringify({ connectionString })
642
707
  });
643
- if (!res.ok) await throwPlatformApiError("Failed to update database URL", res);
708
+ if (!res.ok) await throwPlatformApiError("Failed to update database URL", res, "configure");
644
709
  return res.json();
645
710
  }
646
711
  async getDatabaseUrl(projectId) {
647
712
  const res = await this.request(`${this.baseUrl}/projects/${projectId}/database-url`, { headers: { ...this.authHeaders } });
648
- if (!res.ok) await throwPlatformApiError("Failed to fetch database URL", res);
713
+ if (!res.ok) await throwPlatformApiError("Failed to fetch database URL", res, "owner");
649
714
  return res.json();
650
715
  }
651
716
  async purgeCache(projectId) {
@@ -657,7 +722,7 @@ var PlatformClient = class {
657
722
  },
658
723
  body: JSON.stringify({ all: true })
659
724
  });
660
- if (!res.ok) await throwPlatformApiError("Cache purge failed", res);
725
+ if (!res.ok) await throwPlatformApiError("Cache purge failed", res, "deploy");
661
726
  return res.json();
662
727
  }
663
728
  async getLogs(projectId, since, limit = 200, deploymentId, level) {
@@ -668,7 +733,7 @@ var PlatformClient = class {
668
733
  if (deploymentId) params.set("deploymentId", deploymentId);
669
734
  if (level && level !== "all") params.set("level", level);
670
735
  const res = await this.request(`${this.baseUrl}/projects/${projectId}/logs?${params}`, { headers: { ...this.authHeaders } });
671
- if (!res.ok) await throwPlatformApiError("Failed to fetch logs", res);
736
+ if (!res.ok) await throwPlatformApiError("Failed to fetch logs", res, "read");
672
737
  return (await res.json()).data;
673
738
  }
674
739
  async getRequests(projectId, since, limit = 200, status) {
@@ -678,19 +743,19 @@ var PlatformClient = class {
678
743
  });
679
744
  if (status && status !== "all") params.set("status", status);
680
745
  const res = await this.request(`${this.baseUrl}/projects/${projectId}/requests?${params}`, { headers: { ...this.authHeaders } });
681
- if (!res.ok) await throwPlatformApiError("Failed to fetch requests", res);
746
+ if (!res.ok) await throwPlatformApiError("Failed to fetch requests", res, "read");
682
747
  return (await res.json()).data;
683
748
  }
684
749
  async listBuilds(projectId, limit = 20) {
685
750
  const params = new URLSearchParams({ limit: String(limit) });
686
751
  const res = await this.request(`${this.baseUrl}/projects/${projectId}/builds?${params}`, { headers: { ...this.authHeaders } });
687
- if (!res.ok) await throwPlatformApiError("Failed to list builds", res);
752
+ if (!res.ok) await throwPlatformApiError("Failed to list builds", res, "read");
688
753
  return (await res.json()).builds;
689
754
  }
690
755
  async getBuildLogs(projectId, buildId, since = 0) {
691
756
  const params = new URLSearchParams({ since: String(since) });
692
757
  const res = await this.request(`${this.baseUrl}/projects/${projectId}/builds/${buildId}/logs?${params}`, { headers: { ...this.authHeaders } });
693
- if (!res.ok) await throwPlatformApiError("Failed to fetch build logs", res);
758
+ if (!res.ok) await throwPlatformApiError("Failed to fetch build logs", res, "read");
694
759
  return res.json();
695
760
  }
696
761
  async getGithubInstallUrl() {
@@ -712,7 +777,7 @@ var PlatformClient = class {
712
777
  },
713
778
  body: JSON.stringify(body)
714
779
  });
715
- if (!res.ok) await throwPlatformApiError("Failed to connect GitHub repository", res);
780
+ if (!res.ok) await throwPlatformApiError("Failed to connect GitHub repository", res, "settings");
716
781
  return res.json();
717
782
  }
718
783
  /**
@@ -736,7 +801,7 @@ var PlatformClient = class {
736
801
  }
737
802
  async getGithubConnection(projectId) {
738
803
  const res = await this.request(`${this.baseUrl}/projects/${projectId}/github`, { headers: { ...this.authHeaders } });
739
- if (!res.ok) await throwPlatformApiError("Failed to get GitHub connection", res);
804
+ if (!res.ok) await throwPlatformApiError("Failed to get GitHub connection", res, "read");
740
805
  return res.json();
741
806
  }
742
807
  async updateGithubConnection(projectId, body) {
@@ -748,7 +813,7 @@ var PlatformClient = class {
748
813
  },
749
814
  body: JSON.stringify(body)
750
815
  });
751
- if (!res.ok) await throwPlatformApiError("Failed to update GitHub connection", res);
816
+ if (!res.ok) await throwPlatformApiError("Failed to update GitHub connection", res, "settings");
752
817
  return res.json();
753
818
  }
754
819
  async deleteGithubConnection(projectId) {
@@ -756,7 +821,7 @@ var PlatformClient = class {
756
821
  method: "DELETE",
757
822
  headers: { ...this.authHeaders }
758
823
  });
759
- if (!res.ok) await throwPlatformApiError("Failed to disconnect GitHub repository", res);
824
+ if (!res.ok) await throwPlatformApiError("Failed to disconnect GitHub repository", res, "settings");
760
825
  return res.json();
761
826
  }
762
827
  async getGithubLinkUrl(redirect, codeChallenge) {
@@ -811,24 +876,24 @@ var PlatformClient = class {
811
876
  }
812
877
  async getEmailUsage(projectId) {
813
878
  const res = await this.request(`${this.baseUrl}/projects/${projectId}/email/usage`, { headers: { ...this.authHeaders } });
814
- if (!res.ok) await throwPlatformApiError("Failed to fetch email usage", res);
879
+ if (!res.ok) await throwPlatformApiError("Failed to fetch email usage", res, "read");
815
880
  return res.json();
816
881
  }
817
882
  async getEmailLogs(projectId, limit) {
818
883
  const url = new URL(`${this.baseUrl}/projects/${projectId}/email/logs`);
819
884
  if (limit !== void 0) url.searchParams.set("limit", String(limit));
820
885
  const res = await this.request(url, { headers: { ...this.authHeaders } });
821
- if (!res.ok) await throwPlatformApiError("Failed to fetch email logs", res);
886
+ if (!res.ok) await throwPlatformApiError("Failed to fetch email logs", res, "read");
822
887
  return res.json();
823
888
  }
824
889
  async getEmailOperation(projectId, operationId) {
825
890
  const res = await this.request(`${this.baseUrl}/projects/${encodeURIComponent(projectId)}/email/operations/${encodeURIComponent(operationId)}`, { headers: { ...this.authHeaders } });
826
- if (!res.ok) await throwPlatformApiError("Failed to fetch email operation", res);
891
+ if (!res.ok) await throwPlatformApiError("Failed to fetch email operation", res, "read");
827
892
  return res.json();
828
893
  }
829
894
  async listEmailDestinations(projectId) {
830
895
  const res = await this.request(`${this.baseUrl}/projects/${projectId}/email/destinations`, { headers: { ...this.authHeaders } });
831
- if (!res.ok) await throwPlatformApiError("Failed to list email destinations", res);
896
+ if (!res.ok) await throwPlatformApiError("Failed to list email destinations", res, "read");
832
897
  return res.json();
833
898
  }
834
899
  async addEmailDestination(projectId, address) {
@@ -840,7 +905,7 @@ var PlatformClient = class {
840
905
  },
841
906
  body: JSON.stringify({ address })
842
907
  });
843
- if (!res.ok) await throwPlatformApiError("Failed to add email destination", res);
908
+ if (!res.ok) await throwPlatformApiError("Failed to add email destination", res, "settings");
844
909
  return {
845
910
  ...await res.json(),
846
911
  created: res.status === 201
@@ -851,18 +916,18 @@ var PlatformClient = class {
851
916
  method: "DELETE",
852
917
  headers: { ...this.authHeaders }
853
918
  });
854
- if (!res.ok) await throwPlatformApiError("Failed to remove email destination", res);
919
+ if (!res.ok) await throwPlatformApiError("Failed to remove email destination", res, "settings");
855
920
  return res.json();
856
921
  }
857
922
  /** Installation email settings the CLI reads before starting a credential flow. */
858
923
  async getEmailSettings(projectId) {
859
924
  const res = await this.request(`${this.baseUrl}/projects/${projectId}/email/settings`, { headers: { ...this.authHeaders } });
860
- if (!res.ok) await throwPlatformApiError("Failed to read email settings", res);
925
+ if (!res.ok) await throwPlatformApiError("Failed to read email settings", res, "read");
861
926
  return res.json();
862
927
  }
863
928
  async listEmailDomains(projectId) {
864
929
  const res = await this.request(`${this.baseUrl}/projects/${projectId}/email/domains`, { headers: { ...this.authHeaders } });
865
- if (!res.ok) await throwPlatformApiError("Failed to list email domains", res);
930
+ if (!res.ok) await throwPlatformApiError("Failed to list email domains", res, "read");
866
931
  return res.json();
867
932
  }
868
933
  /** Submit a scoped token once; later operations address the domain without it. */
@@ -879,12 +944,12 @@ var PlatformClient = class {
879
944
  ...input.attemptId !== void 0 ? { attemptId: input.attemptId } : {}
880
945
  })
881
946
  });
882
- if (!res.ok) await throwPlatformApiError("Failed to add email domain", res);
947
+ if (!res.ok) await throwPlatformApiError("Failed to add email domain", res, "settings");
883
948
  return res.json();
884
949
  }
885
950
  async getEmailDomain(projectId, domain) {
886
951
  const res = await this.request(`${this.baseUrl}/projects/${projectId}/email/domains/${encodeURIComponent(domain)}`, { headers: { ...this.authHeaders } });
887
- if (!res.ok) await throwPlatformApiError("Failed to fetch email domain status", res);
952
+ if (!res.ok) await throwPlatformApiError("Failed to fetch email domain status", res, "read");
888
953
  return res.json();
889
954
  }
890
955
  /** Rotates the shared zone connection secret. */
@@ -897,7 +962,7 @@ var PlatformClient = class {
897
962
  },
898
963
  body: JSON.stringify({ attemptId })
899
964
  });
900
- if (!res.ok) await throwPlatformApiError("Failed to rotate email connection secret", res);
965
+ if (!res.ok) await throwPlatformApiError("Failed to rotate email connection secret", res, "settings");
901
966
  return res.json();
902
967
  }
903
968
  async syncEmailDomain(projectId, domain) {
@@ -905,7 +970,7 @@ var PlatformClient = class {
905
970
  method: "POST",
906
971
  headers: { ...this.authHeaders }
907
972
  });
908
- if (!res.ok) await throwPlatformApiError("Failed to sync email domain", res);
973
+ if (!res.ok) await throwPlatformApiError("Failed to sync email domain", res, "settings");
909
974
  return res.json();
910
975
  }
911
976
  async removeEmailDomain(projectId, domain) {
@@ -913,7 +978,7 @@ var PlatformClient = class {
913
978
  method: "DELETE",
914
979
  headers: { ...this.authHeaders }
915
980
  });
916
- if (!res.ok) await throwPlatformApiError("Failed to remove email domain", res);
981
+ if (!res.ok) await throwPlatformApiError("Failed to remove email domain", res, "settings");
917
982
  return res.json();
918
983
  }
919
984
  };
@@ -921,4 +986,4 @@ function sleep(ms) {
921
986
  return new Promise((resolve) => setTimeout(resolve, ms));
922
987
  }
923
988
  //#endregion
924
- export { isExpiredTokenError as a, isCliOutdatedError as i, PlatformClient as n, parsePlatformErrorBody as o, client_exports as r, PlatformApiError as t };
989
+ export { isExpiredTokenError as a, isCliOutdatedError as i, PlatformClient as n, parsePlatformErrorBody as o, client_exports as r, platformErrorMessage as s, PlatformApiError as t };
@@ -1,8 +1,8 @@
1
1
  import { D as log, I as isCancel, M as select, X as normalizePlatformApiUrl, Y as listPlatformConnections } from "./output-B0cfNSx5.mjs";
2
2
  import { T as writePlatformSelection, p as readPlatformToken, w as writeDeploymentPlatform, x as readDeploymentPlatform } from "./auth-DPl6kck4.mjs";
3
- import { a as isExpiredTokenError, n as PlatformClient } from "./client-dHfSJvAN.mjs";
4
- import { n as promptForLoginToken } from "./login-Uvferzmm.mjs";
5
- import { discoverPlatform, promptPlatformUrl, saveDiscoveredPlatform } from "./platform-cmd-BFhieCdV.mjs";
3
+ import { a as isExpiredTokenError, n as PlatformClient } from "./client-BQBrZoCX.mjs";
4
+ import { n as promptForLoginToken } from "./login-WIjNc77c.mjs";
5
+ import { discoverPlatform, promptPlatformUrl, saveDiscoveredPlatform } from "./platform-cmd-5q_k56xS.mjs";
6
6
  import { t as connectCloudflare } from "./cloudflare-connect-t1UU5svD.mjs";
7
7
  //#region src/cli/connect.ts
8
8
  async function selectVoidPlatform(interactive) {
@@ -1,7 +1,7 @@
1
1
  import { n as __exportAll } from "./rolldown-runtime-rQ84J-ij.mjs";
2
2
  import { C as cancel, D as log, I as isCancel, M as select, P as text, c as import_picocolors, w as confirm } from "./output-B0cfNSx5.mjs";
3
3
  import { E as writeProjectConfig, c as getSiteDomain, y as attachSelectedPlatform } from "./auth-DPl6kck4.mjs";
4
- import { t as PlatformApiError } from "./client-dHfSJvAN.mjs";
4
+ import { t as PlatformApiError } from "./client-BQBrZoCX.mjs";
5
5
  import { n as inferDefaultSlug } from "./resolve-project--Vxawf7z.mjs";
6
6
  //#region src/cli/project-slug.ts
7
7
  var project_slug_exports = /* @__PURE__ */ __exportAll({
@@ -105,8 +105,7 @@ async function createProjectWithSlugRetry(client, initialDefaultSlug, promptSlug
105
105
  return project;
106
106
  } catch (error) {
107
107
  if (error instanceof PlatformApiError && isRetryableCreateError(error)) {
108
- const reason = error.code || error.body || `HTTP ${error.status}`;
109
- log.error(`project: Could not create project '${slug}': ${reason}.`);
108
+ log.error(`project: ${error.message}`);
110
109
  defaultSlug = slug;
111
110
  continue;
112
111
  }
@@ -8,7 +8,7 @@ import { r as detectFramework } from "./plugin-inference-BDRfZngg.mjs";
8
8
  import { c as collectMigrations, d as stripSqlExt, f as writeJournal, n as listDrizzleArtifacts, r as validateMigrations, t as assertJournalCoherence, u as readJournal } from "./validate-tBBN_dXH.mjs";
9
9
  import { t as resolveLocalD1Target } from "./local-d1-D2I6Ox5F.mjs";
10
10
  import { a as loadLocalEnv } from "./env-DBKmK4vc.mjs";
11
- import { n as PlatformClient, t as PlatformApiError } from "./client-dHfSJvAN.mjs";
11
+ import { n as PlatformClient, t as PlatformApiError } from "./client-BQBrZoCX.mjs";
12
12
  import { formatTimestamp } from "./gen-B_wPnVTK.mjs";
13
13
  import { createRequire } from "node:module";
14
14
  import { existsSync, readFileSync, readdirSync, renameSync, rmSync, writeFileSync } from "node:fs";
@@ -822,7 +822,7 @@ async function runMigrate(root, dialect, remote) {
822
822
  log.error(getErrorMessage(error));
823
823
  process.exit(1);
824
824
  }
825
- const { checkWranglerMigrationApplySet, parseRootWranglerConfig } = await import("./deploy-DTaWUS1S.mjs").then((n) => n.n);
825
+ const { checkWranglerMigrationApplySet, parseRootWranglerConfig } = await import("./deploy-BAhhcg5q.mjs").then((n) => n.n);
826
826
  const applySet = await checkWranglerMigrationApplySet(context.operation.configPath, parseRootWranglerConfig(context.operation.configPath), binding, context.migrationsDir, rawMigrations);
827
827
  if (!applySet.ok) {
828
828
  log.error(applySet.reason);