@prisma/cli 3.0.0-dev.95.1 → 3.0.0-dev.97.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.
|
@@ -11,6 +11,7 @@ const EMPTY_AUTH_CONTEXT = {
|
|
|
11
11
|
activeWorkspaceId: null,
|
|
12
12
|
workspaces: {}
|
|
13
13
|
};
|
|
14
|
+
const UNKNOWN_WORKSPACE_NAME = "Unknown workspace";
|
|
14
15
|
function getAuthContextFilePath(authFilePath) {
|
|
15
16
|
const extension = path.extname(authFilePath);
|
|
16
17
|
if (!extension) return `${authFilePath}.context.json`;
|
|
@@ -140,7 +141,7 @@ var FileTokenStorage = class {
|
|
|
140
141
|
return credentials.map((credential) => storedCredentialToTokens(credential)).filter((tokens) => tokens !== null).map((tokens) => {
|
|
141
142
|
const cached = context.state.workspaces[tokens.workspaceId];
|
|
142
143
|
const id = typeof cached?.id === "string" && cached.id.trim().length > 0 ? cached.id.trim() : tokens.workspaceId;
|
|
143
|
-
const name = typeof cached?.name === "string" && cached.name.trim().length > 0 ? cached.name.trim() :
|
|
144
|
+
const name = typeof cached?.name === "string" && cached.name.trim().length > 0 ? workspaceDisplayName(cached.name.trim(), tokens.workspaceId) : UNKNOWN_WORKSPACE_NAME;
|
|
144
145
|
const lastSeenAt = typeof cached?.lastSeenAt === "string" && cached.lastSeenAt.trim().length > 0 ? cached.lastSeenAt.trim() : null;
|
|
145
146
|
return {
|
|
146
147
|
id,
|
|
@@ -151,6 +152,10 @@ var FileTokenStorage = class {
|
|
|
151
152
|
};
|
|
152
153
|
});
|
|
153
154
|
}
|
|
155
|
+
async listWorkspaceTokens() {
|
|
156
|
+
this.signal?.throwIfAborted();
|
|
157
|
+
return (await this.readCredentialsFromDisk()).map((credential) => storedCredentialToTokens(credential)).filter((tokens) => tokens !== null);
|
|
158
|
+
}
|
|
154
159
|
async useWorkspace(workspaceRef) {
|
|
155
160
|
return this.withRefreshLock(() => this.useWorkspaceUnlocked(workspaceRef));
|
|
156
161
|
}
|
|
@@ -406,5 +411,8 @@ function workspaceMatchesRef(workspace, ref) {
|
|
|
406
411
|
function stripWorkspacePrefix(value) {
|
|
407
412
|
return value.startsWith("wksp_") ? value.slice(5) : value;
|
|
408
413
|
}
|
|
414
|
+
function workspaceDisplayName(name, credentialWorkspaceId) {
|
|
415
|
+
return name === credentialWorkspaceId ? UNKNOWN_WORKSPACE_NAME : name;
|
|
416
|
+
}
|
|
409
417
|
//#endregion
|
|
410
418
|
export { FileTokenStorage, WorkspaceSelectionError };
|
package/dist/controllers/auth.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { SERVICE_TOKEN_ENV_VAR } from "../lib/auth/client.js";
|
|
1
|
+
import { CLIENT_ID, SERVICE_TOKEN_ENV_VAR, getApiBaseUrl } from "../lib/auth/client.js";
|
|
2
2
|
import { FileTokenStorage, WorkspaceSelectionError } from "../adapters/token-storage.js";
|
|
3
3
|
import { authRequiredError, usageError, workspaceAmbiguousError, workspaceNotAuthenticatedError, workspaceSwitchUnavailableError } from "../shell/errors.js";
|
|
4
4
|
import { canPrompt } from "../shell/runtime.js";
|
|
@@ -6,6 +6,7 @@ import { performLogin, performLogout, readAuthState } from "../lib/auth/auth-ops
|
|
|
6
6
|
import { createAuthUseCases } from "../use-cases/auth.js";
|
|
7
7
|
import { createCliUseCaseGateways } from "../use-cases/create-cli-gateways.js";
|
|
8
8
|
import { createSelectPromptPort } from "./select-prompt-port.js";
|
|
9
|
+
import { createManagementApiSdk } from "@prisma/management-api-sdk";
|
|
9
10
|
//#region src/controllers/auth.ts
|
|
10
11
|
function isRealMode(context) {
|
|
11
12
|
return !context.runtime.fixturePath && !context.runtime.env.PRISMA_CLI_MOCK_FIXTURE_PATH;
|
|
@@ -77,7 +78,8 @@ async function requireAuthenticatedAuthState(context) {
|
|
|
77
78
|
}
|
|
78
79
|
async function listRealAuthWorkspaces(context) {
|
|
79
80
|
const rawServiceToken = context.runtime.env[SERVICE_TOKEN_ENV_VAR];
|
|
80
|
-
const
|
|
81
|
+
const storage = new FileTokenStorage(context.runtime.env, context.runtime.signal);
|
|
82
|
+
const localWorkspaces = await hydrateLocalAuthWorkspaces(context, storage, await storage.listWorkspaces());
|
|
81
83
|
if (rawServiceToken !== void 0) {
|
|
82
84
|
const authState = await readAuthState(context.runtime.env, context.runtime.signal);
|
|
83
85
|
return {
|
|
@@ -117,6 +119,7 @@ async function listRealAuthWorkspaces(context) {
|
|
|
117
119
|
async function useRealAuthWorkspace(context, workspaceRef) {
|
|
118
120
|
if (context.runtime.env["PRISMA_SERVICE_TOKEN"] !== void 0) throw workspaceSwitchUnavailableError();
|
|
119
121
|
const storage = new FileTokenStorage(context.runtime.env, context.runtime.signal);
|
|
122
|
+
await hydrateLocalAuthWorkspaces(context, storage, await storage.listWorkspaces());
|
|
120
123
|
try {
|
|
121
124
|
const result = await storage.useWorkspace(workspaceRef);
|
|
122
125
|
return {
|
|
@@ -137,6 +140,7 @@ async function useRealAuthWorkspace(context, workspaceRef) {
|
|
|
137
140
|
}
|
|
138
141
|
async function logoutRealAuthWorkspace(context, workspaceRef) {
|
|
139
142
|
const storage = new FileTokenStorage(context.runtime.env, context.runtime.signal);
|
|
143
|
+
await hydrateLocalAuthWorkspaces(context, storage, await storage.listWorkspaces());
|
|
140
144
|
try {
|
|
141
145
|
const result = await storage.logoutWorkspace(workspaceRef);
|
|
142
146
|
return {
|
|
@@ -171,6 +175,78 @@ async function selectWorkspaceSession(context) {
|
|
|
171
175
|
}))
|
|
172
176
|
})).id;
|
|
173
177
|
}
|
|
178
|
+
async function hydrateLocalAuthWorkspaces(context, storage, workspaces) {
|
|
179
|
+
const candidates = workspaces.filter(needsWorkspaceMetadataHydration);
|
|
180
|
+
if (candidates.length === 0) return workspaces;
|
|
181
|
+
const tokensByCredentialWorkspaceId = new Map((await storage.listWorkspaceTokens()).map((tokens) => [tokens.workspaceId, tokens]));
|
|
182
|
+
let nextWorkspaces = workspaces;
|
|
183
|
+
for (const workspace of candidates) {
|
|
184
|
+
const tokens = tokensByCredentialWorkspaceId.get(workspace.credentialWorkspaceId);
|
|
185
|
+
if (!tokens) continue;
|
|
186
|
+
const resolved = await resolveOAuthWorkspaceMetadata(context, tokens);
|
|
187
|
+
if (!resolved) continue;
|
|
188
|
+
await rememberResolvedWorkspaceMetadata(context, storage, tokens, resolved);
|
|
189
|
+
nextWorkspaces = nextWorkspaces.map((candidate) => candidate.credentialWorkspaceId === workspace.credentialWorkspaceId ? {
|
|
190
|
+
...candidate,
|
|
191
|
+
id: resolved.id,
|
|
192
|
+
name: resolved.name,
|
|
193
|
+
lastSeenAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
194
|
+
} : candidate);
|
|
195
|
+
}
|
|
196
|
+
return nextWorkspaces;
|
|
197
|
+
}
|
|
198
|
+
async function rememberResolvedWorkspaceMetadata(context, storage, tokens, resolved) {
|
|
199
|
+
try {
|
|
200
|
+
await storage.rememberWorkspace(tokens.workspaceId, resolved);
|
|
201
|
+
} catch {
|
|
202
|
+
context.runtime.signal?.throwIfAborted();
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
function needsWorkspaceMetadataHydration(workspace) {
|
|
206
|
+
return workspace.id === workspace.credentialWorkspaceId || workspace.name === "Unknown workspace" || workspace.name === workspace.credentialWorkspaceId;
|
|
207
|
+
}
|
|
208
|
+
async function resolveOAuthWorkspaceMetadata(context, tokens) {
|
|
209
|
+
const sdk = createManagementApiSdk({
|
|
210
|
+
clientId: CLIENT_ID,
|
|
211
|
+
redirectUri: "http://localhost:0/auth/callback",
|
|
212
|
+
tokenStorage: createSingleWorkspaceTokenStorage(new FileTokenStorage(context.runtime.env, context.runtime.signal, { activateOnSetTokens: false }), tokens),
|
|
213
|
+
apiBaseUrl: getApiBaseUrl(context.runtime.env)
|
|
214
|
+
});
|
|
215
|
+
try {
|
|
216
|
+
const { data } = await sdk.client.GET("/v1/workspaces/{id}", {
|
|
217
|
+
params: { path: { id: tokens.workspaceId } },
|
|
218
|
+
signal: context.runtime.signal
|
|
219
|
+
});
|
|
220
|
+
const id = stringOrNull(data?.data?.id) ?? tokens.workspaceId;
|
|
221
|
+
const name = stringOrNull(data?.data?.name) ?? id;
|
|
222
|
+
if (id === tokens.workspaceId && name === tokens.workspaceId) return null;
|
|
223
|
+
return {
|
|
224
|
+
id,
|
|
225
|
+
name
|
|
226
|
+
};
|
|
227
|
+
} catch {
|
|
228
|
+
context.runtime.signal?.throwIfAborted();
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
function createSingleWorkspaceTokenStorage(storage, initialTokens) {
|
|
233
|
+
let currentTokens = initialTokens;
|
|
234
|
+
return {
|
|
235
|
+
getTokens: async () => currentTokens,
|
|
236
|
+
setTokens: async (tokens) => {
|
|
237
|
+
currentTokens = tokens;
|
|
238
|
+
await storage.setTokens(tokens);
|
|
239
|
+
},
|
|
240
|
+
clearTokens: async () => {
|
|
241
|
+
const tokens = currentTokens;
|
|
242
|
+
currentTokens = null;
|
|
243
|
+
if (tokens) await storage.clearTokensIfCurrent(tokens);
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
function stringOrNull(value) {
|
|
248
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
|
|
249
|
+
}
|
|
174
250
|
function toAuthWorkspace(workspace) {
|
|
175
251
|
return {
|
|
176
252
|
id: workspace.id,
|