@prisma/cli 8.0.0-rc.1 → 8.0.0-rc.2

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 (110) hide show
  1. package/dist/cli.js +15115 -16
  2. package/dist/deploy-framework-C7bQM00A.js +23 -0
  3. package/dist/{v8/sender.js → sender.js} +2 -2
  4. package/package.json +11 -15
  5. package/dist/adapters/git.js +0 -54
  6. package/dist/adapters/local-state.js +0 -155
  7. package/dist/auth/client.js +0 -30
  8. package/dist/auth/errors.js +0 -50
  9. package/dist/auth/guard.js +0 -39
  10. package/dist/auth/login.js +0 -471
  11. package/dist/auth/operations.js +0 -208
  12. package/dist/auth/recipient.js +0 -42
  13. package/dist/auth/token-storage.js +0 -439
  14. package/dist/auth/workspaces.js +0 -171
  15. package/dist/cli-command.js +0 -14
  16. package/dist/cli-name.js +0 -12
  17. package/dist/cli2.js +0 -136
  18. package/dist/command-arguments.js +0 -12
  19. package/dist/commands/agent/index.js +0 -60
  20. package/dist/commands/app/index.js +0 -350
  21. package/dist/commands/auth/index.js +0 -95
  22. package/dist/commands/branch/index.js +0 -27
  23. package/dist/commands/bucket/index.js +0 -123
  24. package/dist/commands/build/index.js +0 -29
  25. package/dist/commands/database/index.js +0 -249
  26. package/dist/commands/env.js +0 -99
  27. package/dist/commands/feedback/index.js +0 -20
  28. package/dist/commands/git/index.js +0 -36
  29. package/dist/commands/init/index.js +0 -33
  30. package/dist/commands/project/index.js +0 -118
  31. package/dist/commands/version/index.js +0 -18
  32. package/dist/controllers/agent-setup.js +0 -52
  33. package/dist/controllers/agent.js +0 -228
  34. package/dist/controllers/app-env-api.js +0 -55
  35. package/dist/controllers/app-env-file.js +0 -181
  36. package/dist/controllers/app-env.js +0 -502
  37. package/dist/controllers/app.js +0 -2508
  38. package/dist/controllers/auth.js +0 -124
  39. package/dist/controllers/branch.js +0 -92
  40. package/dist/controllers/bucket.js +0 -184
  41. package/dist/controllers/build.js +0 -88
  42. package/dist/controllers/database.js +0 -463
  43. package/dist/controllers/feedback.js +0 -90
  44. package/dist/controllers/init.js +0 -814
  45. package/dist/controllers/project.js +0 -892
  46. package/dist/controllers/select-prompt-port.js +0 -13
  47. package/dist/controllers/version.js +0 -12
  48. package/dist/errors.js +0 -102
  49. package/dist/lib/agent/cli-command.js +0 -20
  50. package/dist/lib/agent/constants.js +0 -12
  51. package/dist/lib/agent/package-manager.js +0 -99
  52. package/dist/lib/agent/setup-status.js +0 -83
  53. package/dist/lib/app/app-provider.js +0 -617
  54. package/dist/lib/app/branch-database-api.js +0 -102
  55. package/dist/lib/app/branch-database-deploy.js +0 -353
  56. package/dist/lib/app/branch-database.js +0 -234
  57. package/dist/lib/app/build-settings.js +0 -98
  58. package/dist/lib/app/build.js +0 -82
  59. package/dist/lib/app/bun-project.js +0 -45
  60. package/dist/lib/app/compute-config.js +0 -145
  61. package/dist/lib/app/deploy-output.js +0 -24
  62. package/dist/lib/app/deploy-plan.js +0 -59
  63. package/dist/lib/app/deploy-progress.js +0 -100
  64. package/dist/lib/app/domain-guidance.js +0 -14
  65. package/dist/lib/app/env-config.js +0 -67
  66. package/dist/lib/app/env-file.js +0 -82
  67. package/dist/lib/app/env-vars.js +0 -50
  68. package/dist/lib/app/local-dev.js +0 -109
  69. package/dist/lib/app/production-deploy-gate.js +0 -162
  70. package/dist/lib/app/read-branch.js +0 -30
  71. package/dist/lib/bucket/provider.js +0 -139
  72. package/dist/lib/database/provider.js +0 -385
  73. package/dist/lib/diagnostics.js +0 -16
  74. package/dist/lib/feedback.js +0 -15
  75. package/dist/lib/fs/home-path.js +0 -24
  76. package/dist/lib/git/local-branch.js +0 -53
  77. package/dist/lib/git/local-status.js +0 -57
  78. package/dist/lib/project/interactive-setup.js +0 -57
  79. package/dist/lib/project/local-pin.js +0 -200
  80. package/dist/lib/project/provider.js +0 -93
  81. package/dist/lib/project/resolution.js +0 -389
  82. package/dist/lib/project/setup.js +0 -138
  83. package/dist/lib/version.js +0 -56
  84. package/dist/lib/workspace-id.js +0 -18
  85. package/dist/output/patterns.js +0 -90
  86. package/dist/presenters/agent.js +0 -74
  87. package/dist/presenters/app-env.js +0 -265
  88. package/dist/presenters/app.js +0 -672
  89. package/dist/presenters/auth.js +0 -184
  90. package/dist/presenters/branch.js +0 -46
  91. package/dist/presenters/bucket.js +0 -174
  92. package/dist/presenters/database.js +0 -462
  93. package/dist/presenters/feedback.js +0 -26
  94. package/dist/presenters/init.js +0 -30
  95. package/dist/presenters/project.js +0 -268
  96. package/dist/presenters/verbose-context.js +0 -64
  97. package/dist/presenters/version.js +0 -29
  98. package/dist/shell/cli-command.js +0 -2
  99. package/dist/shell/command-meta.js +0 -923
  100. package/dist/shell/command-runner.js +0 -119
  101. package/dist/shell/diagnostics-output.js +0 -57
  102. package/dist/shell/global-flags.js +0 -37
  103. package/dist/shell/help.js +0 -90
  104. package/dist/shell/output.js +0 -144
  105. package/dist/shell/prompt.js +0 -48
  106. package/dist/shell/runtime.js +0 -38
  107. package/dist/shell/ui.js +0 -116
  108. package/dist/state-dir.js +0 -12
  109. package/dist/update-check.js +0 -248
  110. package/dist/v8/cli.js +0 -14699
@@ -1,42 +0,0 @@
1
- import { getApiBaseUrl } from "./client.js";
2
- import { FileTokenStorage } from "./token-storage.js";
3
- import { createManagementApiSdk } from "@prisma/management-api-sdk";
4
- //#region src/auth/recipient.ts
5
- var RecipientSessionInvalidError = class extends Error {
6
- constructor(workspaceRef) {
7
- super(`The stored session for workspace "${workspaceRef}" could not be validated.`);
8
- this.workspaceRef = workspaceRef;
9
- this.name = "RecipientSessionInvalidError";
10
- }
11
- };
12
- /**
13
- * Resolve a locally stored OAuth workspace session and return a validated
14
- * access token for it, refreshing through the SDK when the stored token has
15
- * expired. The active workspace pointer is never touched.
16
- *
17
- * Throws WorkspaceSelectionError when the ref does not match exactly one
18
- * stored session, and RecipientSessionInvalidError when the session cannot
19
- * be validated or refreshed.
20
- */
21
- async function resolveRecipientWorkspaceSession(workspaceRef, env = process.env, signal) {
22
- const workspace = await new FileTokenStorage(env, signal).resolveWorkspace(workspaceRef);
23
- const pinnedStorage = new FileTokenStorage(env, signal, {
24
- activateOnSetTokens: false,
25
- lockSetTokens: false,
26
- pinnedWorkspaceId: workspace.credentialWorkspaceId
27
- });
28
- if ((await createManagementApiSdk({
29
- clientId: "cmm3lndn701oo0uefvxzo0ivw",
30
- redirectUri: "http://localhost:0/auth/callback",
31
- tokenStorage: pinnedStorage,
32
- apiBaseUrl: getApiBaseUrl(env)
33
- }).client.GET("/v1/workspaces", { signal })).error) throw new RecipientSessionInvalidError(workspaceRef);
34
- const tokens = await pinnedStorage.getTokens();
35
- if (!tokens) throw new RecipientSessionInvalidError(workspaceRef);
36
- return {
37
- workspace,
38
- accessToken: tokens.accessToken
39
- };
40
- }
41
- //#endregion
42
- export { RecipientSessionInvalidError, resolveRecipientWorkspaceSession };
@@ -1,439 +0,0 @@
1
- import { getAuthFilePath } from "./client.js";
2
- import { sameWorkspaceId } from "../lib/workspace-id.js";
3
- import path from "node:path";
4
- import fs from "node:fs/promises";
5
- import { randomUUID } from "node:crypto";
6
- import { CredentialsStore } from "@prisma/credentials-store";
7
- //#region src/auth/token-storage.ts
8
- const REFRESH_LOCK_RETRY_MS = 100;
9
- const REFRESH_LOCK_STALE_MS = 3e4;
10
- const REFRESH_LOCK_WAIT_TIMEOUT_MS = 25e3;
11
- const EMPTY_AUTH_CONTEXT = {
12
- activeWorkspaceId: null,
13
- workspaces: {}
14
- };
15
- const UNKNOWN_WORKSPACE_NAME = "Unknown workspace";
16
- function getAuthContextFilePath(authFilePath) {
17
- const extension = path.extname(authFilePath);
18
- if (!extension) return `${authFilePath}.context.json`;
19
- return `${authFilePath.slice(0, -extension.length)}.context${extension}`;
20
- }
21
- function findLatestValidTokens(allCredentials) {
22
- for (let i = allCredentials.length - 1; i >= 0; i -= 1) {
23
- const credential = allCredentials[i];
24
- if (!credential) continue;
25
- if (typeof credential.workspaceId !== "string" || credential.workspaceId.length === 0 || typeof credential.token !== "string" || credential.token.length === 0 || typeof credential.refreshToken !== "string" || credential.refreshToken.length === 0) continue;
26
- return {
27
- workspaceId: credential.workspaceId,
28
- accessToken: credential.token,
29
- refreshToken: credential.refreshToken
30
- };
31
- }
32
- return null;
33
- }
34
- function storedCredentialToTokens(credential) {
35
- if (!credential) return null;
36
- if (typeof credential.workspaceId !== "string" || credential.workspaceId.length === 0 || typeof credential.token !== "string" || credential.token.length === 0 || typeof credential.refreshToken !== "string" || credential.refreshToken.length === 0) return null;
37
- return {
38
- workspaceId: credential.workspaceId,
39
- accessToken: credential.token,
40
- refreshToken: credential.refreshToken
41
- };
42
- }
43
- function findTokensForWorkspace(allCredentials, workspaceId) {
44
- return storedCredentialToTokens(allCredentials.find((credential) => credential?.workspaceId === workspaceId)) ?? null;
45
- }
46
- function tokensEqual(a, b) {
47
- return a?.workspaceId === b?.workspaceId && a?.accessToken === b?.accessToken && a?.refreshToken === b?.refreshToken;
48
- }
49
- function sleep(ms, signal) {
50
- signal?.throwIfAborted();
51
- return new Promise((resolve, reject) => {
52
- const onAbort = () => {
53
- clearTimeout(timeout);
54
- reject(signal?.reason);
55
- };
56
- const timeout = setTimeout(() => {
57
- signal?.removeEventListener("abort", onAbort);
58
- resolve();
59
- }, ms);
60
- signal?.addEventListener("abort", onAbort, { once: true });
61
- });
62
- }
63
- var FileTokenStorage = class {
64
- credentialsStore;
65
- authFilePath;
66
- contextFilePath;
67
- lockFilePath;
68
- constructor(env = process.env, signal, options = {}) {
69
- this.signal = signal;
70
- this.options = options;
71
- const authFilePath = getAuthFilePath(env);
72
- this.authFilePath = authFilePath;
73
- this.contextFilePath = getAuthContextFilePath(authFilePath);
74
- this.credentialsStore = new CredentialsStore(authFilePath);
75
- this.lockFilePath = `${authFilePath}.lock`;
76
- }
77
- async getTokens() {
78
- this.signal?.throwIfAborted();
79
- try {
80
- const credentials = await this.readCredentialsFromDisk();
81
- if (this.options.pinnedWorkspaceId) return findTokensForWorkspace(credentials, this.options.pinnedWorkspaceId);
82
- const context = await this.readAuthContext();
83
- if (context.state.activeWorkspaceId) return findTokensForWorkspace(credentials, context.state.activeWorkspaceId);
84
- const latest = findLatestValidTokens(credentials);
85
- if (!latest) return null;
86
- if (!context.exists) {
87
- await this.setActiveWorkspaceId(latest.workspaceId);
88
- return latest;
89
- }
90
- return null;
91
- } catch (_error) {
92
- if (this.signal?.aborted) throw this.signal.reason;
93
- return null;
94
- }
95
- }
96
- async setTokens(tokens) {
97
- if (this.options.lockSetTokens === false) {
98
- await this.setTokensUnlocked(tokens);
99
- return;
100
- }
101
- await this.withRefreshLock(() => this.setTokensUnlocked(tokens));
102
- }
103
- async setTokensUnlocked(tokens) {
104
- this.signal?.throwIfAborted();
105
- await this.credentialsStore.storeCredentials({
106
- workspaceId: tokens.workspaceId,
107
- token: tokens.accessToken,
108
- refreshToken: tokens.refreshToken
109
- });
110
- this.signal?.throwIfAborted();
111
- await this.rememberWorkspaceUnlocked(tokens.workspaceId, {
112
- id: tokens.workspaceId,
113
- name: tokens.workspaceId
114
- });
115
- await this.maybeActivateWorkspaceId(tokens.workspaceId);
116
- }
117
- async clearTokens() {
118
- await this.withRefreshLock(() => this.clearTokensUnlocked());
119
- }
120
- async clearTokensUnlocked() {
121
- this.signal?.throwIfAborted();
122
- await fs.mkdir(path.dirname(this.authFilePath), { recursive: true });
123
- this.signal?.throwIfAborted();
124
- await fs.writeFile(this.authFilePath, `${JSON.stringify({ tokens: [] }, null, 2)}\n`, {
125
- encoding: "utf8",
126
- signal: this.signal
127
- });
128
- await this.clearAuthContext();
129
- await this.credentialsStore.reloadCredentialsFromDisk();
130
- this.signal?.throwIfAborted();
131
- }
132
- async clearTokensIfCurrent(tokens) {
133
- this.signal?.throwIfAborted();
134
- if (!tokensEqual(await this.getTokens(), tokens)) return;
135
- await this.credentialsStore.deleteCredentials(tokens.workspaceId);
136
- await this.removeRememberedWorkspace(tokens.workspaceId, { preserveActivePointer: true });
137
- this.signal?.throwIfAborted();
138
- }
139
- async listWorkspaces() {
140
- this.signal?.throwIfAborted();
141
- const credentials = await this.readCredentialsFromDisk();
142
- const context = await this.ensureMigratedAuthContext(credentials);
143
- return this.workspacesFromState(credentials, context);
144
- }
145
- workspacesFromState(credentials, context) {
146
- return credentials.map((credential) => storedCredentialToTokens(credential)).filter((tokens) => tokens !== null).map((tokens) => {
147
- const cached = context.state.workspaces[tokens.workspaceId];
148
- const id = typeof cached?.id === "string" && cached.id.trim().length > 0 ? cached.id.trim() : tokens.workspaceId;
149
- const name = typeof cached?.name === "string" && cached.name.trim().length > 0 ? workspaceDisplayName(cached.name.trim(), tokens.workspaceId) : UNKNOWN_WORKSPACE_NAME;
150
- const lastSeenAt = typeof cached?.lastSeenAt === "string" && cached.lastSeenAt.trim().length > 0 ? cached.lastSeenAt.trim() : null;
151
- return {
152
- id,
153
- name,
154
- credentialWorkspaceId: tokens.workspaceId,
155
- active: context.state.activeWorkspaceId === tokens.workspaceId,
156
- lastSeenAt
157
- };
158
- });
159
- }
160
- async listWorkspaceTokens() {
161
- this.signal?.throwIfAborted();
162
- return (await this.readCredentialsFromDisk()).map((credential) => storedCredentialToTokens(credential)).filter((tokens) => tokens !== null);
163
- }
164
- async useWorkspace(workspaceRef) {
165
- return this.withRefreshLock(() => this.useWorkspaceUnlocked(workspaceRef));
166
- }
167
- /**
168
- * Resolve a workspace ref (id, credential workspace id, or cached name)
169
- * against the locally stored sessions without changing the active
170
- * workspace. Read-only counterpart of useWorkspace: it reads the auth
171
- * context as-is and never runs the legacy-state migration, so it writes
172
- * nothing.
173
- */
174
- async resolveWorkspace(workspaceRef) {
175
- const ref = workspaceRef.trim();
176
- if (!ref) throw new WorkspaceSelectionError("missing");
177
- this.signal?.throwIfAborted();
178
- const credentials = await this.readCredentialsFromDisk();
179
- const context = await this.readAuthContext();
180
- const matches = this.workspacesFromState(credentials, context).filter((workspace) => workspaceMatchesRef(workspace, ref));
181
- if (matches.length === 0) throw new WorkspaceSelectionError("not-found", ref);
182
- if (matches.length > 1) throw new WorkspaceSelectionError("ambiguous", ref, matches);
183
- return matches[0];
184
- }
185
- async useWorkspaceUnlocked(workspaceRef) {
186
- const ref = workspaceRef.trim();
187
- if (!ref) throw new WorkspaceSelectionError("missing");
188
- const workspaces = await this.listWorkspaces();
189
- const context = await this.readAuthContext();
190
- const previous = workspaces.find((workspace) => workspace.credentialWorkspaceId === context.state.activeWorkspaceId) ?? null;
191
- const matches = workspaces.filter((workspace) => workspaceMatchesRef(workspace, ref));
192
- if (matches.length === 0) throw new WorkspaceSelectionError("not-found", ref);
193
- if (matches.length > 1) throw new WorkspaceSelectionError("ambiguous", ref, matches);
194
- const selected = matches[0];
195
- await this.setActiveWorkspaceId(selected.credentialWorkspaceId);
196
- return {
197
- previous,
198
- selected
199
- };
200
- }
201
- async logoutWorkspace(workspaceRef) {
202
- return this.withRefreshLock(() => this.logoutWorkspaceUnlocked(workspaceRef));
203
- }
204
- async logoutWorkspaceUnlocked(workspaceRef) {
205
- const ref = workspaceRef.trim();
206
- if (!ref) throw new WorkspaceSelectionError("missing");
207
- const workspaces = await this.listWorkspaces();
208
- const context = await this.readAuthContext();
209
- const matches = workspaces.filter((workspace) => workspaceMatchesRef(workspace, ref));
210
- if (matches.length === 0) throw new WorkspaceSelectionError("not-found", ref);
211
- if (matches.length > 1) throw new WorkspaceSelectionError("ambiguous", ref, matches);
212
- const workspace = matches[0];
213
- const wasActive = context.state.activeWorkspaceId === workspace.credentialWorkspaceId;
214
- await this.credentialsStore.deleteCredentials(workspace.credentialWorkspaceId);
215
- this.signal?.throwIfAborted();
216
- const remainingWorkspaces = workspaces.filter((candidate) => candidate.credentialWorkspaceId !== workspace.credentialWorkspaceId);
217
- if (remainingWorkspaces.length === 0) {
218
- await this.clearAuthContext();
219
- return {
220
- workspace,
221
- wasActive,
222
- activeWorkspace: null
223
- };
224
- }
225
- delete context.state.workspaces[workspace.credentialWorkspaceId];
226
- if (wasActive) context.state.activeWorkspaceId = null;
227
- await this.writeAuthContext(context.state);
228
- return {
229
- workspace,
230
- wasActive,
231
- activeWorkspace: context.state.activeWorkspaceId === null ? null : remainingWorkspaces.find((candidate) => candidate.credentialWorkspaceId === context.state.activeWorkspaceId) ?? null
232
- };
233
- }
234
- async rememberWorkspace(credentialWorkspaceId, workspace) {
235
- await this.withRefreshLock(() => this.rememberWorkspaceUnlocked(credentialWorkspaceId, workspace));
236
- }
237
- async rememberWorkspaceUnlocked(credentialWorkspaceId, workspace) {
238
- const context = await this.readAuthContext();
239
- context.state.workspaces[credentialWorkspaceId] = {
240
- id: workspace.id,
241
- name: workspace.name,
242
- lastSeenAt: (/* @__PURE__ */ new Date()).toISOString()
243
- };
244
- await this.writeAuthContext(context.state);
245
- }
246
- async withRefreshLock(fn) {
247
- const lockId = await this.acquireRefreshLock();
248
- try {
249
- return await fn();
250
- } finally {
251
- await this.releaseRefreshLock(lockId);
252
- }
253
- }
254
- async acquireRefreshLock() {
255
- const lockId = randomUUID();
256
- const startedAt = Date.now();
257
- const retryMs = this.options.lockRetryMs ?? REFRESH_LOCK_RETRY_MS;
258
- const waitTimeoutMs = this.options.lockWaitTimeoutMs ?? REFRESH_LOCK_WAIT_TIMEOUT_MS;
259
- this.signal?.throwIfAborted();
260
- await fs.mkdir(path.dirname(this.lockFilePath), { recursive: true });
261
- while (true) {
262
- this.signal?.throwIfAborted();
263
- if (await this.tryCreateRefreshLock(lockId)) return lockId;
264
- if (await this.releaseStaleRefreshLock()) continue;
265
- this.throwIfRefreshLockWaitTimedOut(startedAt, waitTimeoutMs);
266
- await sleep(retryMs, this.signal);
267
- }
268
- }
269
- async tryCreateRefreshLock(lockId) {
270
- let lockFileCreated = false;
271
- try {
272
- const handle = await fs.open(this.lockFilePath, "wx");
273
- lockFileCreated = true;
274
- try {
275
- this.signal?.throwIfAborted();
276
- await handle.writeFile(lockId, { encoding: "utf8" });
277
- this.signal?.throwIfAborted();
278
- } finally {
279
- await handle.close();
280
- }
281
- return true;
282
- } catch (error) {
283
- if (lockFileCreated) await fs.unlink(this.lockFilePath).catch(() => void 0);
284
- if (error.code === "EEXIST") return false;
285
- throw error;
286
- }
287
- }
288
- async releaseStaleRefreshLock() {
289
- const staleLockId = await this.getStaleRefreshLockId();
290
- if (!staleLockId) return false;
291
- await this.releaseRefreshLock(staleLockId);
292
- return true;
293
- }
294
- throwIfRefreshLockWaitTimedOut(startedAt, waitTimeoutMs) {
295
- if (Date.now() - startedAt < waitTimeoutMs) return;
296
- throw new RefreshLockTimeoutError(this.lockFilePath, waitTimeoutMs);
297
- }
298
- async getStaleRefreshLockId() {
299
- this.signal?.throwIfAborted();
300
- const lockId = await fs.readFile(this.lockFilePath, {
301
- encoding: "utf8",
302
- signal: this.signal
303
- }).catch((error) => {
304
- if (this.signal?.aborted) throw error;
305
- return null;
306
- });
307
- if (lockId === null) return null;
308
- this.signal?.throwIfAborted();
309
- const stats = await fs.stat(this.lockFilePath).catch(() => null);
310
- this.signal?.throwIfAborted();
311
- if (!stats) return null;
312
- const staleMs = this.options.lockStaleMs ?? REFRESH_LOCK_STALE_MS;
313
- return Date.now() - stats.mtimeMs > staleMs ? lockId : null;
314
- }
315
- async releaseRefreshLock(lockId) {
316
- if (await fs.readFile(this.lockFilePath, { encoding: "utf8" }).catch(() => null) !== lockId) return;
317
- await fs.unlink(this.lockFilePath).catch(() => {});
318
- }
319
- async readCredentialsFromDisk() {
320
- this.signal?.throwIfAborted();
321
- await this.credentialsStore.reloadCredentialsFromDisk();
322
- this.signal?.throwIfAborted();
323
- return await this.credentialsStore.getCredentials();
324
- }
325
- async ensureMigratedAuthContext(credentials) {
326
- const context = await this.readAuthContext();
327
- if (context.state.activeWorkspaceId || context.exists) return context;
328
- const latest = findLatestValidTokens(credentials);
329
- if (!latest) return context;
330
- context.state.activeWorkspaceId = latest.workspaceId;
331
- context.state.workspaces[latest.workspaceId] ??= {
332
- id: latest.workspaceId,
333
- name: latest.workspaceId,
334
- lastSeenAt: (/* @__PURE__ */ new Date()).toISOString()
335
- };
336
- await this.writeAuthContext(context.state);
337
- return {
338
- exists: true,
339
- state: context.state
340
- };
341
- }
342
- async setActiveWorkspaceId(workspaceId) {
343
- const context = await this.readAuthContext();
344
- context.state.activeWorkspaceId = workspaceId;
345
- context.state.workspaces[workspaceId] ??= {
346
- id: workspaceId,
347
- name: workspaceId,
348
- lastSeenAt: (/* @__PURE__ */ new Date()).toISOString()
349
- };
350
- await this.writeAuthContext(context.state);
351
- }
352
- async maybeActivateWorkspaceId(workspaceId) {
353
- if (this.options.pinnedWorkspaceId) return;
354
- const context = await this.readAuthContext();
355
- if (this.options.activateOnSetTokens === false && context.exists && context.state.activeWorkspaceId && context.state.activeWorkspaceId !== workspaceId) return;
356
- context.state.activeWorkspaceId = workspaceId;
357
- context.state.workspaces[workspaceId] ??= {
358
- id: workspaceId,
359
- name: workspaceId,
360
- lastSeenAt: (/* @__PURE__ */ new Date()).toISOString()
361
- };
362
- await this.writeAuthContext(context.state);
363
- }
364
- async removeRememberedWorkspace(workspaceId, options) {
365
- const context = await this.readAuthContext();
366
- delete context.state.workspaces[workspaceId];
367
- if (!options.preserveActivePointer && context.state.activeWorkspaceId === workspaceId) context.state.activeWorkspaceId = null;
368
- await this.writeAuthContext(context.state);
369
- }
370
- async readAuthContext() {
371
- this.signal?.throwIfAborted();
372
- const raw = await fs.readFile(this.contextFilePath, {
373
- encoding: "utf8",
374
- signal: this.signal
375
- }).catch((error) => {
376
- if (this.signal?.aborted) throw error;
377
- if (error.code === "ENOENT") return null;
378
- throw error;
379
- });
380
- if (raw === null) return {
381
- exists: false,
382
- state: structuredClone(EMPTY_AUTH_CONTEXT)
383
- };
384
- try {
385
- const parsed = JSON.parse(raw);
386
- return {
387
- exists: true,
388
- state: {
389
- activeWorkspaceId: typeof parsed.activeWorkspaceId === "string" && parsed.activeWorkspaceId.trim().length > 0 ? parsed.activeWorkspaceId.trim() : null,
390
- workspaces: parsed.workspaces && typeof parsed.workspaces === "object" && !Array.isArray(parsed.workspaces) ? parsed.workspaces : {}
391
- }
392
- };
393
- } catch {
394
- return {
395
- exists: false,
396
- state: structuredClone(EMPTY_AUTH_CONTEXT)
397
- };
398
- }
399
- }
400
- async writeAuthContext(state) {
401
- this.signal?.throwIfAborted();
402
- await fs.mkdir(path.dirname(this.contextFilePath), { recursive: true });
403
- this.signal?.throwIfAborted();
404
- await fs.writeFile(this.contextFilePath, `${JSON.stringify(state, null, 2)}\n`, {
405
- encoding: "utf8",
406
- signal: this.signal
407
- });
408
- this.signal?.throwIfAborted();
409
- }
410
- async clearAuthContext() {
411
- await fs.unlink(this.contextFilePath).catch((error) => {
412
- if (error.code === "ENOENT") return;
413
- throw error;
414
- });
415
- }
416
- };
417
- var WorkspaceSelectionError = class extends Error {
418
- constructor(reason, workspaceRef, matches = []) {
419
- super(reason);
420
- this.reason = reason;
421
- this.workspaceRef = workspaceRef;
422
- this.matches = matches;
423
- this.name = "WorkspaceSelectionError";
424
- }
425
- };
426
- var RefreshLockTimeoutError = class extends Error {
427
- constructor(lockFilePath, waitTimeoutMs) {
428
- super(`Timed out waiting ${waitTimeoutMs}ms for auth refresh lock at ${lockFilePath}`);
429
- this.name = "RefreshLockTimeoutError";
430
- }
431
- };
432
- function workspaceMatchesRef(workspace, ref) {
433
- return sameWorkspaceId(workspace.credentialWorkspaceId, ref) || sameWorkspaceId(workspace.id, ref) || workspace.name.toLowerCase() === ref.toLowerCase();
434
- }
435
- function workspaceDisplayName(name, credentialWorkspaceId) {
436
- return name === credentialWorkspaceId ? UNKNOWN_WORKSPACE_NAME : name;
437
- }
438
- //#endregion
439
- export { FileTokenStorage, WorkspaceSelectionError };
@@ -1,171 +0,0 @@
1
- import { CLIENT_ID, UNUSED_REDIRECT_URI, getApiBaseUrl } from "./client.js";
2
- import { FileTokenStorage, WorkspaceSelectionError } from "./token-storage.js";
3
- import { readAuthState } from "./operations.js";
4
- import { workspaceAmbiguousError, workspaceNotAuthenticatedError, workspaceSwitchUnavailableError } from "./errors.js";
5
- import { createManagementApiSdk } from "@prisma/management-api-sdk";
6
- import { SERVICE_TOKEN_ENV_VAR } from "@prisma/cli-engine";
7
- //#region src/auth/workspaces.ts
8
- async function listAuthWorkspaces(context) {
9
- const rawServiceToken = context.env[SERVICE_TOKEN_ENV_VAR];
10
- const storage = new FileTokenStorage(context.env, context.signal);
11
- const localWorkspaces = await hydrateLocalAuthWorkspaces(context, storage, await storage.listWorkspaces());
12
- if (rawServiceToken !== void 0) {
13
- const authState = await readAuthState(context.env, context.signal);
14
- return {
15
- authSource: authState.authenticated ? "service_token" : "none",
16
- activeWorkspace: authState.workspace,
17
- workspaces: [...authState.workspace ? [{
18
- ...authState.workspace,
19
- credentialWorkspaceId: null,
20
- active: true,
21
- source: "service_token",
22
- switchable: false,
23
- lastSeenAt: null
24
- }] : [], ...localWorkspaces.map((workspace) => ({
25
- ...toAuthWorkspace(workspace),
26
- credentialWorkspaceId: workspace.credentialWorkspaceId,
27
- active: false,
28
- source: "oauth",
29
- switchable: false,
30
- lastSeenAt: workspace.lastSeenAt
31
- }))]
32
- };
33
- }
34
- const active = localWorkspaces.find((workspace) => workspace.active) ?? null;
35
- return {
36
- authSource: localWorkspaces.length > 0 ? "oauth" : "none",
37
- activeWorkspace: active ? toAuthWorkspace(active) : null,
38
- workspaces: localWorkspaces.map((workspace) => ({
39
- ...toAuthWorkspace(workspace),
40
- credentialWorkspaceId: workspace.credentialWorkspaceId,
41
- active: workspace.active,
42
- source: "oauth",
43
- switchable: true,
44
- lastSeenAt: workspace.lastSeenAt
45
- }))
46
- };
47
- }
48
- async function switchAuthWorkspace(context, workspaceRef) {
49
- if (context.env[SERVICE_TOKEN_ENV_VAR] !== void 0) throw workspaceSwitchUnavailableError();
50
- const storage = new FileTokenStorage(context.env, context.signal);
51
- await hydrateLocalAuthWorkspaces(context, storage, await storage.listWorkspaces());
52
- try {
53
- const result = await storage.useWorkspace(workspaceRef);
54
- return {
55
- previousWorkspace: result.previous ? toAuthWorkspace(result.previous) : null,
56
- workspace: toAuthWorkspace(result.selected)
57
- };
58
- } catch (error) {
59
- if (error instanceof WorkspaceSelectionError) {
60
- if (error.reason === "ambiguous") throw workspaceAmbiguousError(error.workspaceRef ?? workspaceRef, error.matches.map((match) => ({
61
- id: match.id,
62
- name: match.name,
63
- credentialWorkspaceId: match.credentialWorkspaceId
64
- })));
65
- throw workspaceNotAuthenticatedError(error.workspaceRef ?? workspaceRef);
66
- }
67
- throw error;
68
- }
69
- }
70
- async function logoutAuthWorkspace(context, workspaceRef) {
71
- const storage = new FileTokenStorage(context.env, context.signal);
72
- await hydrateLocalAuthWorkspaces(context, storage, await storage.listWorkspaces());
73
- try {
74
- const result = await storage.logoutWorkspace(workspaceRef);
75
- return {
76
- workspace: toAuthWorkspace(result.workspace),
77
- wasActive: result.wasActive,
78
- activeWorkspace: result.activeWorkspace ? toAuthWorkspace(result.activeWorkspace) : null
79
- };
80
- } catch (error) {
81
- if (error instanceof WorkspaceSelectionError) {
82
- if (error.reason === "ambiguous") throw workspaceAmbiguousError(error.workspaceRef ?? workspaceRef, error.matches.map((match) => ({
83
- id: match.id,
84
- name: match.name,
85
- credentialWorkspaceId: match.credentialWorkspaceId
86
- })));
87
- throw workspaceNotAuthenticatedError(error.workspaceRef ?? workspaceRef);
88
- }
89
- throw error;
90
- }
91
- }
92
- async function hydrateLocalAuthWorkspaces(context, storage, workspaces) {
93
- const candidates = workspaces.filter(needsWorkspaceMetadataHydration);
94
- if (candidates.length === 0) return workspaces;
95
- const tokensByCredentialWorkspaceId = new Map((await storage.listWorkspaceTokens()).map((tokens) => [tokens.workspaceId, tokens]));
96
- let nextWorkspaces = workspaces;
97
- for (const workspace of candidates) {
98
- const tokens = tokensByCredentialWorkspaceId.get(workspace.credentialWorkspaceId);
99
- if (!tokens) continue;
100
- const resolved = await resolveOAuthWorkspaceMetadata(context, tokens);
101
- if (!resolved) continue;
102
- await rememberResolvedWorkspaceMetadata(context, storage, tokens, resolved);
103
- nextWorkspaces = nextWorkspaces.map((candidate) => candidate.credentialWorkspaceId === workspace.credentialWorkspaceId ? {
104
- ...candidate,
105
- id: resolved.id,
106
- name: resolved.name,
107
- lastSeenAt: (/* @__PURE__ */ new Date()).toISOString()
108
- } : candidate);
109
- }
110
- return nextWorkspaces;
111
- }
112
- async function rememberResolvedWorkspaceMetadata(context, storage, tokens, resolved) {
113
- try {
114
- await storage.rememberWorkspace(tokens.workspaceId, resolved);
115
- } catch {
116
- context.signal?.throwIfAborted();
117
- }
118
- }
119
- function needsWorkspaceMetadataHydration(workspace) {
120
- return workspace.id === workspace.credentialWorkspaceId || workspace.name === "Unknown workspace" || workspace.name === workspace.credentialWorkspaceId;
121
- }
122
- async function resolveOAuthWorkspaceMetadata(context, tokens) {
123
- const sdk = createManagementApiSdk({
124
- clientId: CLIENT_ID,
125
- redirectUri: UNUSED_REDIRECT_URI,
126
- tokenStorage: createSingleWorkspaceTokenStorage(new FileTokenStorage(context.env, context.signal, { activateOnSetTokens: false }), tokens),
127
- apiBaseUrl: getApiBaseUrl(context.env)
128
- });
129
- try {
130
- const { data } = await sdk.client.GET("/v1/workspaces/{id}", {
131
- params: { path: { id: tokens.workspaceId } },
132
- signal: context.signal
133
- });
134
- const id = stringOrNull(data?.data?.id) ?? tokens.workspaceId;
135
- const name = stringOrNull(data?.data?.name) ?? id;
136
- if (id === tokens.workspaceId && name === tokens.workspaceId) return null;
137
- return {
138
- id,
139
- name
140
- };
141
- } catch {
142
- context.signal?.throwIfAborted();
143
- return null;
144
- }
145
- }
146
- function createSingleWorkspaceTokenStorage(storage, initialTokens) {
147
- let currentTokens = initialTokens;
148
- return {
149
- getTokens: async () => currentTokens,
150
- setTokens: async (tokens) => {
151
- currentTokens = tokens;
152
- await storage.setTokens(tokens);
153
- },
154
- clearTokens: async () => {
155
- const tokens = currentTokens;
156
- currentTokens = null;
157
- if (tokens) await storage.clearTokensIfCurrent(tokens);
158
- }
159
- };
160
- }
161
- function stringOrNull(value) {
162
- return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
163
- }
164
- function toAuthWorkspace(workspace) {
165
- return {
166
- id: workspace.id,
167
- name: workspace.name
168
- };
169
- }
170
- //#endregion
171
- export { listAuthWorkspaces, logoutAuthWorkspace, switchAuthWorkspace };
@@ -1,14 +0,0 @@
1
- //#region src/cli-command.ts
2
- const PRISMA_CLI_PACKAGE_NAME = "@prisma/cli";
3
- const PRISMA_CLI_PACKAGE_SPEC = `${PRISMA_CLI_PACKAGE_NAME}@latest`;
4
- const DEFAULT_PRISMA_CLI_PACKAGE_RUNNER = ["npx", "-y"];
5
- const PRISMA_CLI_BINARY = "prisma-cli";
6
- function formatPrismaCliCommand(args, options = {}) {
7
- return [...getPrismaCliCommandPrefix(options), ...args].join(" ");
8
- }
9
- function getPrismaCliCommandPrefix({ invocation = "package", packageRunner = DEFAULT_PRISMA_CLI_PACKAGE_RUNNER }) {
10
- if (invocation === "binary") return [PRISMA_CLI_BINARY];
11
- return [...packageRunner, PRISMA_CLI_PACKAGE_SPEC];
12
- }
13
- //#endregion
14
- export { DEFAULT_PRISMA_CLI_PACKAGE_RUNNER, PRISMA_CLI_BINARY, PRISMA_CLI_PACKAGE_NAME, PRISMA_CLI_PACKAGE_SPEC, formatPrismaCliCommand };
package/dist/cli-name.js DELETED
@@ -1,12 +0,0 @@
1
- //#region src/cli-name.ts
2
- /**
3
- * The CLI's user-facing identity, in one place. The npm package is
4
- * "@prisma/cli" but the binary on PATH is "prisma-cli" (the S1
5
- * convention) — every user-facing command string and notice consumes
6
- * this constant rather than restating the name.
7
- */
8
- const CLI_NAME = "prisma-cli";
9
- /** The CLI docs page (also the update-check fallback instruction URL). */
10
- const CLI_DOCS_URL = "https://www.prisma.io/docs/orm/tools/prisma-cli";
11
- //#endregion
12
- export { CLI_DOCS_URL, CLI_NAME };