@prisma/cli 3.0.0-dev.99.1 → 8.0.0-rc.10-dev.80

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 (86) hide show
  1. package/README.md +26 -28
  2. package/dist/cli.js +14551 -16
  3. package/dist/payload-B88Qvzxk-CrtTXSOe.js +34 -0
  4. package/dist/sender.js +192 -0
  5. package/package.json +26 -19
  6. package/dist/adapters/git.js +0 -54
  7. package/dist/adapters/local-state.js +0 -144
  8. package/dist/adapters/mock-api.js +0 -136
  9. package/dist/adapters/token-storage.js +0 -418
  10. package/dist/cli2.js +0 -119
  11. package/dist/commands/app/index.js +0 -345
  12. package/dist/commands/auth/index.js +0 -96
  13. package/dist/commands/branch/index.js +0 -27
  14. package/dist/commands/database/index.js +0 -159
  15. package/dist/commands/env.js +0 -99
  16. package/dist/commands/git/index.js +0 -36
  17. package/dist/commands/project/index.js +0 -69
  18. package/dist/commands/version/index.js +0 -18
  19. package/dist/controllers/app-env-api.js +0 -54
  20. package/dist/controllers/app-env-file.js +0 -181
  21. package/dist/controllers/app-env.js +0 -502
  22. package/dist/controllers/app.js +0 -2443
  23. package/dist/controllers/auth.js +0 -316
  24. package/dist/controllers/branch.js +0 -103
  25. package/dist/controllers/database.js +0 -318
  26. package/dist/controllers/project.js +0 -731
  27. package/dist/controllers/select-prompt-port.js +0 -12
  28. package/dist/controllers/version.js +0 -12
  29. package/dist/lib/app/app-interaction.js +0 -5
  30. package/dist/lib/app/app-provider.js +0 -544
  31. package/dist/lib/app/branch-database-api.js +0 -102
  32. package/dist/lib/app/branch-database-deploy.js +0 -325
  33. package/dist/lib/app/branch-database.js +0 -215
  34. package/dist/lib/app/build-settings.js +0 -93
  35. package/dist/lib/app/build.js +0 -80
  36. package/dist/lib/app/bun-project.js +0 -45
  37. package/dist/lib/app/compute-config.js +0 -147
  38. package/dist/lib/app/deploy-output.js +0 -24
  39. package/dist/lib/app/deploy-plan.js +0 -58
  40. package/dist/lib/app/deploy-progress.js +0 -100
  41. package/dist/lib/app/domain-guidance.js +0 -14
  42. package/dist/lib/app/env-config.js +0 -67
  43. package/dist/lib/app/env-file.js +0 -82
  44. package/dist/lib/app/env-vars.js +0 -50
  45. package/dist/lib/app/local-dev.js +0 -109
  46. package/dist/lib/app/production-deploy-gate.js +0 -161
  47. package/dist/lib/app/read-branch.js +0 -30
  48. package/dist/lib/auth/auth-ops.js +0 -158
  49. package/dist/lib/auth/client.js +0 -22
  50. package/dist/lib/auth/guard.js +0 -38
  51. package/dist/lib/auth/login.js +0 -330
  52. package/dist/lib/database/provider.js +0 -167
  53. package/dist/lib/diagnostics.js +0 -15
  54. package/dist/lib/fs/home-path.js +0 -24
  55. package/dist/lib/git/local-branch.js +0 -53
  56. package/dist/lib/git/local-status.js +0 -57
  57. package/dist/lib/project/interactive-setup.js +0 -56
  58. package/dist/lib/project/local-pin.js +0 -200
  59. package/dist/lib/project/resolution.js +0 -386
  60. package/dist/lib/project/setup.js +0 -135
  61. package/dist/lib/version.js +0 -55
  62. package/dist/output/patterns.js +0 -90
  63. package/dist/presenters/app-env.js +0 -265
  64. package/dist/presenters/app.js +0 -646
  65. package/dist/presenters/auth.js +0 -183
  66. package/dist/presenters/branch.js +0 -46
  67. package/dist/presenters/database.js +0 -274
  68. package/dist/presenters/project.js +0 -174
  69. package/dist/presenters/verbose-context.js +0 -64
  70. package/dist/presenters/version.js +0 -29
  71. package/dist/shell/command-arguments.js +0 -6
  72. package/dist/shell/command-meta.js +0 -622
  73. package/dist/shell/command-runner.js +0 -112
  74. package/dist/shell/diagnostics-output.js +0 -57
  75. package/dist/shell/errors.js +0 -134
  76. package/dist/shell/global-flags.js +0 -37
  77. package/dist/shell/help.js +0 -89
  78. package/dist/shell/output.js +0 -82
  79. package/dist/shell/prompt.js +0 -41
  80. package/dist/shell/runtime.js +0 -55
  81. package/dist/shell/ui.js +0 -116
  82. package/dist/shell/update-check.js +0 -247
  83. package/dist/use-cases/auth.js +0 -145
  84. package/dist/use-cases/branch.js +0 -47
  85. package/dist/use-cases/create-cli-gateways.js +0 -68
  86. package/dist/use-cases/project.js +0 -30
package/dist/shell/ui.js DELETED
@@ -1,116 +0,0 @@
1
- import { createColors } from "colorette";
2
- import stringWidth from "string-width";
3
- import stripAnsi from "strip-ansi";
4
- import wrapAnsi from "wrap-ansi";
5
- //#region src/shell/ui.ts
6
- const URL_CREDENTIALS_PATTERN = /:\/\/[^:@/\s]+:[^@/\s]+@/g;
7
- const DEFAULT_WIDTH = 80;
8
- function createShellUi(runtime, flags) {
9
- const isTTY = Boolean(runtime.stderr.isTTY);
10
- const colorEnabled = resolveColorEnabled(runtime, flags, isTTY);
11
- const colors = createColors({ useColor: colorEnabled });
12
- return {
13
- isTTY,
14
- colorEnabled,
15
- width: runtime.stderr.columns && runtime.stderr.columns > 0 ? runtime.stderr.columns : DEFAULT_WIDTH,
16
- quiet: flags.quiet,
17
- verbose: flags.verbose,
18
- trace: flags.trace,
19
- accent: (text) => colors.cyan(text),
20
- success: (text) => colors.greenBright(text),
21
- error: (text) => colors.redBright(text),
22
- warning: (text) => colors.yellow(text),
23
- info: (text) => colors.blue(text),
24
- link: (text) => colors.blue(text),
25
- dim: (text) => colors.dim(text),
26
- strong: (text) => colors.bold(text)
27
- };
28
- }
29
- function renderCommandHeader(ui, options) {
30
- if (!ui.isTTY) return [];
31
- const rows = options.rows ?? [];
32
- const lines = [`${ui.strong(options.commandLabel)} ${ui.dim("→")} ${ui.dim(options.description)}`, ""];
33
- const rail = ui.dim("│");
34
- const keyWidth = rows.length > 0 ? Math.max(...rows.map((row) => stringWidth(`${row.key}:`)), stringWidth("Read more")) : stringWidth("Read more");
35
- for (const row of rows) lines.push(`${rail} ${ui.accent(padDisplay(`${row.key}:`, keyWidth))} ${formatHeaderValue(ui, row)}`);
36
- if (rows.length > 0 || options.docsPath) lines.push(rail);
37
- if (options.docsPath) lines.push(`${rail} ${ui.accent(padDisplay("Read more", keyWidth))} ${ui.link(options.docsPath)}`);
38
- lines.push("");
39
- return lines;
40
- }
41
- function renderSummaryLine(ui, status, text) {
42
- return `${status === "success" ? ui.success("✔") : status === "error" ? ui.error("✘") : status === "warning" ? ui.warning("⚠") : ui.info("ℹ")} ${text}`;
43
- }
44
- function renderNextSteps(steps) {
45
- if (steps.length === 0) return [];
46
- return [
47
- "",
48
- steps.length === 1 ? "Next step:" : "Next steps:",
49
- ...steps.map((step) => `- ${step}`)
50
- ];
51
- }
52
- function renderVerboseBlock(ui, rows, options = {}) {
53
- if (!ui.verbose || rows.length === 0) return [];
54
- const title = options.title ?? "Details";
55
- const keyWidth = Math.max(...rows.map((row) => stringWidth(`${row.key}:`)));
56
- const rail = ui.dim("│");
57
- return [
58
- "",
59
- `${ui.dim(title)}:`,
60
- ...rows.map((row) => `${rail} ${ui.accent(padDisplay(`${row.key}:`, keyWidth))} ${formatVerboseValue(ui, row)}`)
61
- ];
62
- }
63
- function formatColumns(columns, widths) {
64
- return columns.map((value, index) => padDisplay(value, widths[index])).join(" ").trimEnd();
65
- }
66
- function wrapText(text, width, indent = "") {
67
- return wrapAnsi(text, width, {
68
- hard: false,
69
- trim: false
70
- }).split("\n").map((line, index) => index === 0 ? line : `${indent}${line}`);
71
- }
72
- function padDisplay(text, width) {
73
- const padding = Math.max(width - stringWidth(stripAnsi(text)), 0);
74
- return `${text}${" ".repeat(padding)}`;
75
- }
76
- function maskValue(value) {
77
- return maskEmailLocalParts(value).replace(URL_CREDENTIALS_PATTERN, "://****:****@");
78
- }
79
- function maskEmailLocalParts(value) {
80
- let masked = "";
81
- let segmentStart = 0;
82
- for (let index = 0; index < value.length; index += 1) {
83
- if (value[index] !== "@") continue;
84
- let localStart = index;
85
- while (localStart > segmentStart && isEmailLocalPartChar(value[localStart - 1])) localStart -= 1;
86
- if (localStart === index) continue;
87
- masked += `${value.slice(segmentStart, localStart)}****@`;
88
- segmentStart = index + 1;
89
- }
90
- return masked + value.slice(segmentStart);
91
- }
92
- function isEmailLocalPartChar(char) {
93
- return char >= "A" && char <= "Z" || char >= "a" && char <= "z" || char >= "0" && char <= "9" || char === "!" || char === "#" || char === "$" || char === "." || char === "&" || char === "'" || char === "*" || char === "%" || char === "+" || char === "-" || char === "/" || char === "=" || char === "?" || char === "^" || char === "_" || char === "`" || char === "{" || char === "|" || char === "}" || char === "~";
94
- }
95
- function resolveColorEnabled(runtime, flags, isTTY) {
96
- if (flags.color === true) return true;
97
- if (flags.color === false) return false;
98
- if (runtime.env.NO_COLOR !== void 0) return false;
99
- return isTTY;
100
- }
101
- function formatHeaderValue(ui, row) {
102
- const value = row.sensitive ? maskValue(row.value) : row.value;
103
- if (row.tone === "dim") return ui.dim(value);
104
- if (row.tone === "link") return ui.link(value);
105
- return value;
106
- }
107
- function formatVerboseValue(ui, row) {
108
- const value = row.sensitive ? maskValue(row.value) : row.value;
109
- if (row.tone === "dim") return ui.dim(value);
110
- if (row.tone === "success") return ui.success(value);
111
- if (row.tone === "warning") return ui.warning(value);
112
- if (row.tone === "link") return ui.link(value);
113
- return value;
114
- }
115
- //#endregion
116
- export { createShellUi, formatColumns, maskValue, padDisplay, renderCommandHeader, renderNextSteps, renderSummaryLine, renderVerboseBlock, wrapText };
@@ -1,247 +0,0 @@
1
- import { getCliName, getCliVersion } from "../lib/version.js";
2
- import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
3
- import path from "node:path";
4
- import { randomUUID } from "node:crypto";
5
- import os from "node:os";
6
- import { spawn } from "node:child_process";
7
- //#region src/shell/update-check.ts
8
- const UPDATE_CHECK_FILE_NAME = "update-check.json";
9
- const FALLBACK_INSTALL_DOCS_URL = "https://www.prisma.io/docs/orm/tools/prisma-cli";
10
- const NOTIFICATION_INTERVAL_MS = 1440 * 60 * 1e3;
11
- const REGISTRY_URL = "https://registry.npmjs.org/@prisma%2fcli";
12
- const REGISTRY_TIMEOUT_MS = 3e3;
13
- var UpdateCheckStore = class {
14
- filePath;
15
- constructor(cacheDir) {
16
- this.filePath = path.join(cacheDir, UPDATE_CHECK_FILE_NAME);
17
- }
18
- async read() {
19
- try {
20
- return JSON.parse(await readFile(this.filePath, "utf8"));
21
- } catch (error) {
22
- if (isUnreadableCacheError(error)) return null;
23
- throw error;
24
- }
25
- }
26
- async write(state) {
27
- const dir = path.dirname(this.filePath);
28
- const tempPath = path.join(dir, `${UPDATE_CHECK_FILE_NAME}.${process.pid}.${randomUUID()}.tmp`);
29
- await mkdir(dir, { recursive: true });
30
- await writeFile(tempPath, `${JSON.stringify(state, null, 2)}\n`, "utf8");
31
- await rename(tempPath, this.filePath);
32
- }
33
- };
34
- async function maybeWriteCachedUpdateNotification(runtime) {
35
- if (!canRunUpdateCheck(runtime)) return;
36
- try {
37
- const cacheDir = resolveUpdateCheckCacheDir(runtime);
38
- const store = new UpdateCheckStore(cacheDir);
39
- const state = await store.read();
40
- const latestVersion = state?.latestVersion;
41
- if (latestVersion && isInstalledVersionStale(getCliVersion(), latestVersion) && shouldNotify(state)) {
42
- runtime.stderr.write(renderUpdateNotification(latestVersion, selectUpdateInstruction(runtime.env)));
43
- await store.write({
44
- ...state,
45
- packageName: "@prisma/cli",
46
- installedVersion: getCliVersion(),
47
- notifiedAt: (/* @__PURE__ */ new Date()).toISOString()
48
- });
49
- }
50
- await scheduleRemoteDiscovery(runtime, store, state, cacheDir);
51
- } catch {
52
- return;
53
- }
54
- }
55
- async function runUpdateDiscovery(options) {
56
- try {
57
- const latestVersion = await fetchLatestVersion(options.registryUrl ?? REGISTRY_URL, options.fetchImpl ?? fetch);
58
- if (!latestVersion) return;
59
- const store = new UpdateCheckStore(options.cacheDir);
60
- const previousState = await store.read();
61
- await store.write({
62
- ...previousState,
63
- packageName: "@prisma/cli",
64
- installedVersion: options.installedVersion,
65
- latestVersion,
66
- checkedAt: (options.now ?? /* @__PURE__ */ new Date()).toISOString()
67
- });
68
- } catch {
69
- return;
70
- }
71
- }
72
- function isUnreadableCacheError(error) {
73
- const code = error.code;
74
- return code === "ENOENT" || code === "EACCES" || code === "EPERM" || error instanceof SyntaxError;
75
- }
76
- async function runUpdateDiscoveryWorker(env = process.env) {
77
- const cacheDir = env.PRISMA_CLI_UPDATE_CHECK_DIR;
78
- const installedVersion = env.PRISMA_CLI_UPDATE_CHECK_INSTALLED_VERSION;
79
- if (!cacheDir || !installedVersion) return;
80
- await runUpdateDiscovery({
81
- cacheDir,
82
- installedVersion,
83
- registryUrl: env.PRISMA_CLI_UPDATE_CHECK_REGISTRY_URL
84
- });
85
- }
86
- function canRunUpdateCheck(runtime) {
87
- if (runtime.env.NO_UPDATE_NOTIFIER !== void 0) return false;
88
- if (isTestRuntime(runtime.env) && runtime.env.PRISMA_CLI_TEST_ENABLE_UPDATE_CHECK !== "1") return false;
89
- if (runtime.env.CI || runtime.env.GITHUB_ACTIONS) return false;
90
- if (!runtime.stderr.isTTY) return false;
91
- if (runtime.argv.includes("--json") || runtime.argv.includes("--quiet") || runtime.argv.includes("-q")) return false;
92
- if (runtime.argv.includes("--version")) return false;
93
- return true;
94
- }
95
- function shouldNotify(state) {
96
- return !state.notifiedAt || isAtLeastIntervalAgo(state.notifiedAt);
97
- }
98
- async function scheduleRemoteDiscovery(runtime, store, state, cacheDir) {
99
- if (state?.checkedAt && !isAtLeastIntervalAgo(state.checkedAt)) return;
100
- const checkedAt = (/* @__PURE__ */ new Date()).toISOString();
101
- await store.write({
102
- ...state,
103
- packageName: "@prisma/cli",
104
- installedVersion: getCliVersion(),
105
- checkedAt
106
- });
107
- if (isTestRuntime(runtime.env)) return;
108
- const entrypoint = process.argv[1];
109
- if (!entrypoint) return;
110
- spawn(process.execPath, [entrypoint], {
111
- detached: true,
112
- stdio: "ignore",
113
- env: {
114
- ...process.env,
115
- PRISMA_CLI_RUN_UPDATE_CHECK_WORKER: "1",
116
- PRISMA_CLI_UPDATE_CHECK_DIR: cacheDir,
117
- PRISMA_CLI_UPDATE_CHECK_INSTALLED_VERSION: getCliVersion(),
118
- PRISMA_CLI_UPDATE_CHECK_REGISTRY_URL: runtime.env.PRISMA_CLI_UPDATE_CHECK_REGISTRY_URL ?? REGISTRY_URL
119
- }
120
- }).unref();
121
- }
122
- function selectUpdateInstruction(env, processArgv = process.argv) {
123
- const entrypoint = (processArgv[1] ?? "").replace(/\\/g, "/").toLowerCase();
124
- const userAgent = env.npm_config_user_agent?.toLowerCase() ?? "";
125
- if (isEphemeralInvocation(entrypoint, env.npm_lifecycle_event?.toLowerCase() ?? "")) return docsInstruction();
126
- if (entrypoint.includes("/node_modules/.bin/")) {
127
- if (userAgent.startsWith("pnpm")) return commandInstruction("pnpm add -D @prisma/cli@latest");
128
- if (userAgent.startsWith("bun")) return commandInstruction("bun add -d @prisma/cli@latest");
129
- if (userAgent.startsWith("npm")) return commandInstruction("npm install --save-dev @prisma/cli@latest");
130
- }
131
- if (env.npm_config_global === "true" || isLikelyGlobalNpmEntrypoint(entrypoint)) return commandInstruction("npm install --global @prisma/cli@latest");
132
- return docsInstruction();
133
- }
134
- function renderUpdateNotification(latestVersion, instruction) {
135
- return [
136
- `Update available: ${getCliName()} ${getCliVersion()} -> ${latestVersion}`,
137
- renderUpdateInstruction(instruction),
138
- ""
139
- ].join("\n");
140
- }
141
- function renderUpdateInstruction(instruction) {
142
- if (instruction.type === "command") return `Run ${instruction.value} to update.`;
143
- return `See ${instruction.value} for update instructions.`;
144
- }
145
- function isEphemeralInvocation(entrypoint, lifecycle) {
146
- return lifecycle === "npx" || lifecycle === "pnpx" || entrypoint.includes("/_npx/") || entrypoint.includes("/.bun/");
147
- }
148
- function isLikelyGlobalNpmEntrypoint(entrypoint) {
149
- return /\/npm\/prisma-cli(\.cmd|\.exe)?$/.test(entrypoint) || /\/npm-global\/bin\/prisma-cli$/.test(entrypoint);
150
- }
151
- function commandInstruction(value) {
152
- return {
153
- type: "command",
154
- value
155
- };
156
- }
157
- function docsInstruction() {
158
- return {
159
- type: "docs",
160
- value: FALLBACK_INSTALL_DOCS_URL
161
- };
162
- }
163
- function resolveUpdateCheckCacheDir(runtime) {
164
- const configured = runtime.env.PRISMA_CLI_UPDATE_CHECK_DIR;
165
- if (configured?.trim()) return path.resolve(configured);
166
- if (process.platform === "darwin") return path.join(os.homedir(), "Library", "Caches", "prisma-cli");
167
- if (process.platform === "win32") {
168
- const localAppData = runtime.env.LOCALAPPDATA ?? path.join(os.homedir(), "AppData", "Local");
169
- return path.join(localAppData, "prisma-cli", "cache");
170
- }
171
- const xdgCacheHome = runtime.env.XDG_CACHE_HOME ?? path.join(os.homedir(), ".cache");
172
- return path.join(xdgCacheHome, "prisma-cli");
173
- }
174
- function isTestRuntime(env) {
175
- return env.VITEST !== void 0 || env.NODE_ENV === "test";
176
- }
177
- function isAtLeastIntervalAgo(value) {
178
- const timestamp = Date.parse(value);
179
- return Number.isNaN(timestamp) || Date.now() - timestamp >= NOTIFICATION_INTERVAL_MS;
180
- }
181
- function isInstalledVersionStale(installedVersion, latestVersion) {
182
- const installed = parseVersion(installedVersion);
183
- const latest = parseVersion(latestVersion);
184
- if (!installed || !latest) return false;
185
- return compareVersions(installed, latest) < 0;
186
- }
187
- function parseVersion(version) {
188
- const match = /^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?$/.exec(version);
189
- if (!match) return null;
190
- return {
191
- major: Number(match[1]),
192
- minor: Number(match[2]),
193
- patch: Number(match[3]),
194
- prerelease: match[4]?.split(".") ?? []
195
- };
196
- }
197
- function compareVersions(left, right) {
198
- for (const key of [
199
- "major",
200
- "minor",
201
- "patch"
202
- ]) {
203
- const diff = left[key] - right[key];
204
- if (diff !== 0) return diff;
205
- }
206
- return comparePrerelease(left.prerelease, right.prerelease);
207
- }
208
- function comparePrerelease(left, right) {
209
- if (left.length === 0 && right.length === 0) return 0;
210
- if (left.length === 0) return 1;
211
- if (right.length === 0) return -1;
212
- const count = Math.max(left.length, right.length);
213
- for (let index = 0; index < count; index += 1) {
214
- const leftPart = left[index];
215
- const rightPart = right[index];
216
- if (leftPart === void 0) return -1;
217
- if (rightPart === void 0) return 1;
218
- const diff = comparePrereleasePart(leftPart, rightPart);
219
- if (diff !== 0) return diff;
220
- }
221
- return 0;
222
- }
223
- function comparePrereleasePart(left, right) {
224
- const leftNumber = /^\d+$/.test(left) ? Number(left) : null;
225
- const rightNumber = /^\d+$/.test(right) ? Number(right) : null;
226
- if (leftNumber !== null && rightNumber !== null) return leftNumber - rightNumber;
227
- if (leftNumber !== null) return -1;
228
- if (rightNumber !== null) return 1;
229
- return left.localeCompare(right);
230
- }
231
- async function fetchLatestVersion(registryUrl, fetchImpl) {
232
- const controller = new AbortController();
233
- const timeout = setTimeout(() => controller.abort(), REGISTRY_TIMEOUT_MS);
234
- try {
235
- const response = await fetchImpl(registryUrl, {
236
- signal: controller.signal,
237
- headers: { accept: "application/json" }
238
- });
239
- if (!response.ok) return null;
240
- const latest = (await response.json())["dist-tags"]?.latest;
241
- return typeof latest === "string" ? latest : null;
242
- } finally {
243
- clearTimeout(timeout);
244
- }
245
- }
246
- //#endregion
247
- export { maybeWriteCachedUpdateNotification, runUpdateDiscoveryWorker };
@@ -1,145 +0,0 @@
1
- import { authRequiredError, usageError, workspaceAmbiguousError, workspaceNotAuthenticatedError } from "../shell/errors.js";
2
- //#region src/use-cases/auth.ts
3
- function createAuthUseCases(dependencies) {
4
- return {
5
- whoami: () => resolveCurrentAuthState(dependencies),
6
- login: async (selection) => {
7
- await dependencies.sessionGateway.writeAuthSession({
8
- provider: selection.provider,
9
- userId: selection.userId,
10
- workspaceId: selection.workspaceId
11
- });
12
- return resolveCurrentAuthState(dependencies);
13
- },
14
- logout: async () => {
15
- await dependencies.sessionGateway.clearAuthSession();
16
- return resolveCurrentAuthState(dependencies);
17
- },
18
- listWorkspaces: async () => {
19
- const session = await dependencies.sessionGateway.readAuthSession();
20
- if (!session) return {
21
- authSource: "none",
22
- activeWorkspace: null,
23
- workspaces: []
24
- };
25
- const workspaces = dependencies.identityGateway.listUserWorkspaces(session.userId);
26
- return {
27
- authSource: "oauth",
28
- activeWorkspace: workspaces.find((workspace) => workspace.id === session.workspaceId) ?? null,
29
- workspaces: workspaces.map((workspace) => ({
30
- ...workspace,
31
- credentialWorkspaceId: workspace.id,
32
- active: workspace.id === session.workspaceId,
33
- source: "oauth",
34
- switchable: true,
35
- lastSeenAt: null
36
- }))
37
- };
38
- },
39
- useWorkspace: async (workspaceRef) => {
40
- const session = await dependencies.sessionGateway.readAuthSession();
41
- if (!session) throw authRequiredError(["prisma-cli auth login"]);
42
- const ref = workspaceRef.trim();
43
- const matches = dependencies.identityGateway.listUserWorkspaces(session.userId).filter((workspace) => workspaceMatchesRef(workspace, ref));
44
- if (matches.length === 0) throw workspaceNotAuthenticatedError(workspaceRef);
45
- if (matches.length > 1) throw workspaceAmbiguousError(workspaceRef, matches.map((workspace) => ({
46
- id: workspace.id,
47
- name: workspace.name,
48
- credentialWorkspaceId: workspace.id
49
- })));
50
- const selected = matches[0];
51
- const previousWorkspace = dependencies.identityGateway.getWorkspace(session.workspaceId) ?? null;
52
- await dependencies.sessionGateway.writeAuthSession({
53
- ...session,
54
- workspaceId: selected.id
55
- });
56
- return {
57
- previousWorkspace,
58
- workspace: selected
59
- };
60
- },
61
- logoutWorkspace: async (workspaceRef) => {
62
- const session = await dependencies.sessionGateway.readAuthSession();
63
- if (!session) throw workspaceNotAuthenticatedError(workspaceRef);
64
- const ref = workspaceRef.trim();
65
- const matches = dependencies.identityGateway.listUserWorkspaces(session.userId).filter((workspace) => workspaceMatchesRef(workspace, ref));
66
- if (matches.length === 0) throw workspaceNotAuthenticatedError(workspaceRef);
67
- if (matches.length > 1) throw workspaceAmbiguousError(workspaceRef, matches.map((workspace) => ({
68
- id: workspace.id,
69
- name: workspace.name,
70
- credentialWorkspaceId: workspace.id
71
- })));
72
- const workspace = matches[0];
73
- const wasActive = workspace.id === session.workspaceId;
74
- const activeWorkspace = wasActive ? null : dependencies.identityGateway.getWorkspace(session.workspaceId) ?? null;
75
- if (wasActive) await dependencies.sessionGateway.clearAuthSession();
76
- return {
77
- workspace,
78
- wasActive,
79
- activeWorkspace
80
- };
81
- },
82
- listProviders: async () => dependencies.identityGateway.listProviders(),
83
- resolveProvider: async (providerId) => {
84
- const provider = dependencies.identityGateway.getProvider(providerId);
85
- if (!provider) throw usageError("Login requires a valid mock provider", `The mock provider "${providerId}" does not exist.`, "Use --provider github or --provider google.", ["prisma-cli auth login"], "auth");
86
- return provider;
87
- },
88
- listUsersForProvider: async (providerId) => {
89
- const users = dependencies.identityGateway.listUsersForProvider(providerId);
90
- if (users.length === 0) throw usageError("Login requires a valid mock user", `No mock users support provider "${providerId}".`, "Update the fixture data or choose a different provider.", ["prisma-cli auth login"], "auth");
91
- return users;
92
- },
93
- resolveUserForProvider: async (providerId, userId) => {
94
- const user = dependencies.identityGateway.getUserForProvider(providerId, userId);
95
- if (!user) throw usageError("Login requires a valid mock user", `The mock user "${userId}" is not available for provider "${providerId}".`, "Choose a user that supports the selected provider.", ["prisma-cli auth login"], "auth");
96
- return user;
97
- },
98
- listWorkspacesForUser: async (userId) => dependencies.identityGateway.listUserWorkspaces(userId),
99
- resolveWorkspaceForUser: async (userId, workspaceId) => {
100
- const workspace = dependencies.identityGateway.getUserWorkspace(userId, workspaceId);
101
- if (!workspace) throw usageError("Login requires a valid mock workspace", `The mock workspace "${workspaceId}" is not available for the selected user.`, "Choose a workspace that the selected user can access.", ["prisma-cli auth login"], "auth");
102
- return workspace;
103
- }
104
- };
105
- }
106
- function workspaceMatchesRef(workspace, ref) {
107
- return workspace.id === ref || workspace.name.toLowerCase() === ref.toLowerCase();
108
- }
109
- async function resolveCurrentAuthState(dependencies) {
110
- const session = await dependencies.sessionGateway.readAuthSession();
111
- if (!session) return {
112
- authenticated: false,
113
- provider: null,
114
- user: null,
115
- workspace: null,
116
- credential: null
117
- };
118
- const provider = dependencies.identityGateway.getProvider(session.provider);
119
- const user = dependencies.identityGateway.getUser(session.userId);
120
- const workspace = dependencies.identityGateway.getWorkspace(session.workspaceId);
121
- if (!provider || !user || !workspace) return {
122
- authenticated: false,
123
- provider: null,
124
- user: null,
125
- workspace: null,
126
- credential: null
127
- };
128
- return {
129
- authenticated: true,
130
- provider: provider.id,
131
- user: {
132
- id: user.id,
133
- email: user.email,
134
- name: user.name
135
- },
136
- workspace,
137
- credential: {
138
- type: "oauth",
139
- id: null,
140
- name: null
141
- }
142
- };
143
- }
144
- //#endregion
145
- export { createAuthUseCases };
@@ -1,47 +0,0 @@
1
- //#region src/use-cases/branch.ts
2
- function createBranchUseCases(dependencies) {
3
- return { list: async () => {
4
- const projectId = await dependencies.projectStateGateway.readRememberedProjectId();
5
- if (!projectId) return {
6
- projectId: "",
7
- projectName: "not resolved",
8
- branches: []
9
- };
10
- const remoteBranches = await listRemoteBranches(dependencies.branchGateway, projectId);
11
- return {
12
- projectId,
13
- projectName: resolveProjectName(dependencies.projectGateway, projectId) ?? "not resolved",
14
- branches: buildBranchSummaries(remoteBranches)
15
- };
16
- } };
17
- }
18
- function resolveProjectName(projectGateway, projectId) {
19
- if (!projectId) return null;
20
- return projectGateway.getProject(projectId)?.name ?? null;
21
- }
22
- async function listRemoteBranches(branchGateway, projectId) {
23
- if (!projectId) return [];
24
- return branchGateway.listBranchesForProject(projectId);
25
- }
26
- function buildBranchSummaries(remoteBranches) {
27
- return sortBranches(remoteBranches.map((branch) => ({
28
- id: branch.id,
29
- name: branch.name,
30
- role: branch.role,
31
- envMap: branch.role
32
- })));
33
- }
34
- function sortBranches(branches) {
35
- return branches.slice().sort((left, right) => {
36
- const leftRank = branchOrder(left);
37
- const rightRank = branchOrder(right);
38
- if (leftRank !== rightRank) return leftRank - rightRank;
39
- return left.name.localeCompare(right.name);
40
- });
41
- }
42
- function branchOrder(branch) {
43
- if (branch.role === "production") return 0;
44
- return 1;
45
- }
46
- //#endregion
47
- export { createBranchUseCases };
@@ -1,68 +0,0 @@
1
- //#region src/use-cases/create-cli-gateways.ts
2
- function createCliUseCaseGateways(context) {
3
- return {
4
- identityGateway: {
5
- listProviders: () => context.api.listProviders(),
6
- getProvider: (providerId) => context.api.getProvider(providerId),
7
- listUsersForProvider: (providerId) => context.api.listUsersForProvider(providerId).map(toAuthUser),
8
- getUser: (userId) => {
9
- const user = context.api.getUser(userId);
10
- return user ? toAuthUser(user) : void 0;
11
- },
12
- getUserForProvider: (providerId, userId) => {
13
- const user = context.api.getUserForProvider(providerId, userId);
14
- return user ? toAuthUser(user) : void 0;
15
- },
16
- listUserWorkspaces: (userId) => context.api.listUserWorkspaces(userId).map(toAuthWorkspace),
17
- getWorkspace: (workspaceId) => {
18
- const workspace = context.api.getWorkspace(workspaceId);
19
- return workspace ? toAuthWorkspace(workspace) : void 0;
20
- },
21
- getUserWorkspace: (userId, workspaceId) => {
22
- const workspace = context.api.getUserWorkspace(userId, workspaceId);
23
- return workspace ? toAuthWorkspace(workspace) : void 0;
24
- }
25
- },
26
- projectGateway: {
27
- listProjectsForWorkspace: (workspaceId) => context.api.listProjectsForWorkspace(workspaceId),
28
- getProject: (projectId) => context.api.getProject(projectId),
29
- getProjectForWorkspace: (workspaceId, projectId) => context.api.getProjectForWorkspace(workspaceId, projectId)
30
- },
31
- branchGateway: {
32
- listBranchesForProject: (projectId) => context.api.listBranchesForProject(projectId),
33
- getBranchForProject: (projectId, name) => {
34
- return context.api.getBranchForProject(projectId, name);
35
- },
36
- getDeployment: (deploymentId) => context.api.getDeployment(deploymentId)
37
- },
38
- projectStateGateway: { readRememberedProjectId: async () => {
39
- return (await context.stateStore.readLastResolvedProject())?.id ?? null;
40
- } },
41
- sessionGateway: {
42
- readAuthSession: async () => {
43
- return (await context.stateStore.read()).auth;
44
- },
45
- writeAuthSession: async (session) => {
46
- await context.stateStore.setAuthSession(session);
47
- },
48
- clearAuthSession: async () => {
49
- await context.stateStore.clearAuthSession();
50
- }
51
- }
52
- };
53
- }
54
- function toAuthUser(user) {
55
- return {
56
- id: user.id,
57
- name: user.name,
58
- email: user.email
59
- };
60
- }
61
- function toAuthWorkspace(workspace) {
62
- return {
63
- id: workspace.id,
64
- name: workspace.name
65
- };
66
- }
67
- //#endregion
68
- export { createCliUseCaseGateways };
@@ -1,30 +0,0 @@
1
- import { authRequiredError } from "../shell/errors.js";
2
- //#region src/use-cases/project.ts
3
- function createProjectUseCases(dependencies) {
4
- return {
5
- list: async (authState) => {
6
- const workspace = requireWorkspace(authState);
7
- return {
8
- workspace,
9
- projects: listSortedWorkspaceProjects(dependencies.projectGateway, workspace.id).map(toProjectSummary)
10
- };
11
- },
12
- listProjectsForWorkspace: async (workspaceId) => listSortedWorkspaceProjects(dependencies.projectGateway, workspaceId).map(toProjectSummary)
13
- };
14
- }
15
- function requireWorkspace(authState) {
16
- if (!authState.authenticated || !authState.workspace) throw authRequiredError();
17
- return authState.workspace;
18
- }
19
- function listSortedWorkspaceProjects(projectGateway, workspaceId) {
20
- return projectGateway.listProjectsForWorkspace(workspaceId).slice().sort((left, right) => left.name.localeCompare(right.name) || left.id.localeCompare(right.id));
21
- }
22
- function toProjectSummary(project) {
23
- return {
24
- id: project.id,
25
- name: project.name,
26
- ...project.url ? { url: project.url } : {}
27
- };
28
- }
29
- //#endregion
30
- export { createProjectUseCases };