@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
@@ -1,502 +0,0 @@
1
- import { CliError, authRequiredError, usageError, workspaceRequiredError } from "../shell/errors.js";
2
- import { formatScopeLabel, parseKeyValuePositional, resolveEnvScope } from "../lib/app/env-config.js";
3
- import { readEnvFileAssignments } from "../lib/app/env-file.js";
4
- import { projectResolutionErrorToCliError, resolveProjectTarget } from "../lib/project/resolution.js";
5
- import { requireComputeAuth } from "../lib/auth/guard.js";
6
- import { readLocalGitBranch } from "../lib/git/local-branch.js";
7
- import { requireAuthenticatedAuthState } from "./auth.js";
8
- import { listRealWorkspaceProjects } from "./project.js";
9
- import { apiCallError, findVariableByNaturalKey, toMetadata } from "./app-env-api.js";
10
- import { runEnvAddFile, runEnvUpdateFile } from "./app-env-file.js";
11
- //#region src/controllers/app-env.ts
12
- async function runEnvAdd(context, rawAssignment, flags) {
13
- const source = resolveEnvWriteSource(rawAssignment, flags.filePath, "add");
14
- const scope = resolveEnvScope(flags, {
15
- requireExplicit: true,
16
- command: "add"
17
- });
18
- if (!scope) throw usageError(`prisma-cli project env add requires --role or --branch`, "Writing without an explicit scope is rejected.", "Pass --role production, --role preview, or --branch <git-name>.", ["prisma-cli project env add KEY=value --role production"], "app");
19
- const input = await resolveEnvWriteInput(context, source, "add");
20
- const { client, projectId, verboseContext } = await requireClientAndProject(context, flags.projectRef, "project env add");
21
- const resolved = await resolveScopeToApi(client, projectId, scope, {
22
- createBranchIfMissing: true,
23
- signal: context.runtime.signal
24
- });
25
- if (input.kind === "file") return runEnvAddFile(context, client, projectId, resolved, input.filePath, input.assignments, verboseContext);
26
- if (await findVariableByNaturalKey(client, projectId, input.key, resolved, context.runtime.signal)) throw new CliError({
27
- code: "ENV_VARIABLE_ALREADY_EXISTS",
28
- domain: "app",
29
- summary: `Variable "${input.key}" already exists in ${formatScopeLabel(scope)}`,
30
- why: "A variable with this key already exists in the targeted scope.",
31
- fix: "Use `prisma-cli project env update` to change an existing variable's value.",
32
- exitCode: 1,
33
- nextSteps: [`prisma-cli project env update ${input.key}=<new-value> ${formatScopeFlag(scope)}`]
34
- });
35
- const warnings = scope.kind === "branch" && !await findVariableByNaturalKey(client, projectId, input.key, {
36
- descriptor: {
37
- kind: "role",
38
- role: "preview"
39
- },
40
- apiTarget: {
41
- class: "preview",
42
- branchId: null
43
- }
44
- }, context.runtime.signal) ? [`Variable "${input.key}" does not exist in preview. It will only exist on ${formatScopeLabel(scope)}.`] : [];
45
- const { data, error, response } = await client.POST("/v1/environment-variables", {
46
- body: {
47
- projectId,
48
- class: resolved.apiTarget.class,
49
- ...resolved.apiTarget.branchId !== null ? { branchId: resolved.apiTarget.branchId } : {},
50
- key: input.key,
51
- value: input.value
52
- },
53
- signal: context.runtime.signal
54
- });
55
- if (error || !data) throw apiCallError(`Failed to add ${input.key}`, response, error);
56
- return {
57
- command: "project.env.add",
58
- result: {
59
- projectId,
60
- verboseContext,
61
- scope: resolved.descriptor,
62
- variable: toMetadata(data.data, resolved.descriptor)
63
- },
64
- warnings,
65
- nextSteps: []
66
- };
67
- }
68
- async function runEnvUpdate(context, rawAssignment, flags) {
69
- const source = resolveEnvWriteSource(rawAssignment, flags.filePath, "update");
70
- const scope = resolveEnvScope(flags, {
71
- requireExplicit: true,
72
- command: "update"
73
- });
74
- if (!scope) throw usageError(`prisma-cli project env update requires --role or --branch`, "Writing without an explicit scope is rejected.", "Pass --role production, --role preview, or --branch <git-name>.", ["prisma-cli project env update KEY=value --role production"], "app");
75
- const input = await resolveEnvWriteInput(context, source, "update");
76
- const { client, projectId, verboseContext } = await requireClientAndProject(context, flags.projectRef, "project env update");
77
- const resolved = await resolveScopeToApi(client, projectId, scope, {
78
- createBranchIfMissing: false,
79
- signal: context.runtime.signal
80
- });
81
- if (input.kind === "file") return runEnvUpdateFile(context, client, projectId, resolved, input.filePath, input.assignments, verboseContext);
82
- const existing = await findVariableByNaturalKey(client, projectId, input.key, resolved, context.runtime.signal);
83
- if (!existing) throw new CliError({
84
- code: "ENV_VARIABLE_NOT_FOUND",
85
- domain: "app",
86
- summary: `Variable "${input.key}" not found in ${formatScopeLabel(scope)}`,
87
- why: "No variable with this key exists in the targeted scope.",
88
- fix: "Use `prisma-cli project env add` to create a new variable.",
89
- exitCode: 1,
90
- nextSteps: [`prisma-cli project env add ${input.key}=<value> ${formatScopeFlag(scope)}`]
91
- });
92
- const { data, error, response } = await client.PATCH("/v1/environment-variables/{envVarId}", {
93
- params: { path: { envVarId: existing.id } },
94
- body: { value: input.value },
95
- signal: context.runtime.signal
96
- });
97
- if (error || !data) throw apiCallError(`Failed to update value for ${input.key}`, response, error);
98
- return {
99
- command: "project.env.update",
100
- result: {
101
- projectId,
102
- verboseContext,
103
- scope: resolved.descriptor,
104
- variable: toMetadata(data.data, resolved.descriptor)
105
- },
106
- warnings: [],
107
- nextSteps: []
108
- };
109
- }
110
- function resolveEnvWriteSource(rawAssignment, filePath, command) {
111
- if (filePath !== void 0 && rawAssignment !== void 0) throw usageError(`prisma-cli project env ${command} accepts either KEY=VALUE or --file`, "The command received both a positional assignment and a dotenv file path.", "Pass one input source.", [`prisma-cli project env ${command} KEY=value --role preview`, `prisma-cli project env ${command} --file .env --role preview`], "app");
112
- if (filePath !== void 0) {
113
- if (filePath.length === 0) throw usageError(`prisma-cli project env ${command} --file requires a path`, "The --file flag was passed without a file path.", "Pass a readable dotenv file path.", [`prisma-cli project env ${command} --file .env --role preview`], "app");
114
- return {
115
- kind: "file",
116
- filePath
117
- };
118
- }
119
- if (rawAssignment === void 0) throw usageError(`prisma-cli project env ${command} requires KEY=VALUE or --file`, "No environment variable input was supplied.", "Pass a single KEY=VALUE assignment or a dotenv file path.", [`prisma-cli project env ${command} KEY=value --role preview`, `prisma-cli project env ${command} --file .env --role preview`], "app");
120
- return {
121
- kind: "single",
122
- rawAssignment
123
- };
124
- }
125
- async function resolveEnvWriteInput(context, source, command) {
126
- if (source.kind === "file") return {
127
- kind: "file",
128
- filePath: source.filePath,
129
- assignments: await readEnvFileAssignments(context.runtime.cwd, source.filePath, command)
130
- };
131
- return {
132
- kind: "single",
133
- ...parseKeyValuePositional(source.rawAssignment, command, context.runtime.env)
134
- };
135
- }
136
- async function runEnvList(context, flags) {
137
- const explicit = resolveEnvScope(flags, {
138
- requireExplicit: false,
139
- command: "list"
140
- });
141
- const { client, projectId, verboseContext } = await requireClientAndProject(context, flags.projectRef, "project env list");
142
- const resolved = await resolveListScopeToApi(client, projectId, explicit ?? void 0, {
143
- cwd: context.runtime.cwd,
144
- signal: context.runtime.signal
145
- });
146
- const variables = resolved.kind === "scoped" ? await listVariables(client, projectId, {
147
- scope: resolved.addScope,
148
- descriptor: resolved.descriptor,
149
- apiTarget: resolved.apiTarget
150
- }, context.runtime.signal) : await listOverviewVariables(client, projectId, context.runtime.signal);
151
- return {
152
- command: "project.env.list",
153
- result: {
154
- projectId,
155
- verboseContext,
156
- scope: resolved.descriptor,
157
- target: resolved.target,
158
- variables: variables.map((row) => toMetadata(row, resolved.descriptor))
159
- },
160
- warnings: [],
161
- nextSteps: variables.length === 0 ? [`prisma-cli project env add KEY=value ${formatScopeFlag(resolved.addScope)}`] : []
162
- };
163
- }
164
- async function runEnvRemove(context, key, flags) {
165
- if (!key) throw usageError("prisma-cli project env remove requires KEY", "No KEY positional argument was supplied.", "Pass the variable name to remove, e.g. STRIPE_KEY.", ["prisma-cli project env remove STRIPE_KEY --role production"], "app");
166
- const scope = resolveEnvScope(flags, {
167
- requireExplicit: true,
168
- command: "remove"
169
- });
170
- if (!scope) throw usageError("prisma-cli project env remove requires --role or --branch", "Writing without an explicit scope is rejected.", "Pass --role production, --role preview, or --branch <git-name>.", [`prisma-cli project env remove ${key} --role production`], "app");
171
- const { client, projectId, verboseContext } = await requireClientAndProject(context, flags.projectRef, "project env remove");
172
- const resolved = await resolveScopeToApi(client, projectId, scope, {
173
- createBranchIfMissing: false,
174
- signal: context.runtime.signal
175
- });
176
- const existing = await findVariableByNaturalKey(client, projectId, key, resolved, context.runtime.signal);
177
- if (!existing) throw new CliError({
178
- code: "ENV_VARIABLE_NOT_FOUND",
179
- domain: "app",
180
- summary: `Variable "${key}" not found in ${formatScopeLabel(scope)}`,
181
- why: "No variable with this key exists in the targeted scope, so there is nothing to remove.",
182
- fix: "Run prisma-cli project env list with the same scope to see the available variables.",
183
- exitCode: 1,
184
- nextSteps: [`prisma-cli project env list ${formatScopeFlag(scope)}`]
185
- });
186
- const { error, response } = await client.DELETE("/v1/environment-variables/{envVarId}", {
187
- params: { path: { envVarId: existing.id } },
188
- signal: context.runtime.signal
189
- });
190
- if (error) throw apiCallError(`Failed to remove ${key}`, response, error);
191
- return {
192
- command: "project.env.remove",
193
- result: {
194
- projectId,
195
- verboseContext,
196
- scope: resolved.descriptor,
197
- key
198
- },
199
- warnings: [],
200
- nextSteps: []
201
- };
202
- }
203
- async function requireClientAndProject(context, explicitProject, commandName) {
204
- const authState = await requireAuthenticatedAuthState(context);
205
- const client = await requireComputeAuth(context.runtime.env, context.runtime.signal);
206
- if (!client) throw authRequiredError(["prisma-cli auth login"]);
207
- const workspace = authState.workspace;
208
- if (!workspace) throw workspaceRequiredError();
209
- const targetResult = await resolveProjectTarget({
210
- context,
211
- workspace,
212
- explicitProject,
213
- listProjects: () => listRealWorkspaceProjects(client, workspace, context.runtime.signal),
214
- commandName
215
- });
216
- if (targetResult.isErr()) throw projectResolutionErrorToCliError(targetResult.error);
217
- const target = targetResult.value;
218
- return {
219
- client,
220
- projectId: target.project.id,
221
- verboseContext: {
222
- workspace,
223
- project: target.project,
224
- resolution: target.resolution
225
- }
226
- };
227
- }
228
- async function resolveScopeToApi(client, projectId, scope, options) {
229
- if (scope.kind === "role") return {
230
- scope,
231
- descriptor: {
232
- kind: "role",
233
- role: scope.role
234
- },
235
- apiTarget: {
236
- class: scope.role,
237
- branchId: null
238
- }
239
- };
240
- const branch = options.createBranchIfMissing ? await resolveOrCreateBranch(client, projectId, scope.branchName, options.signal) : await resolveExistingBranch(client, projectId, scope.branchName, options.signal);
241
- if (branch.role === "production") throw new CliError({
242
- code: "ENV_BRANCH_SCOPE_IS_PRODUCTION",
243
- domain: "app",
244
- summary: `Branch "${scope.branchName}" is the production branch`,
245
- why: "Production variables are project-level only; branch overrides apply to preview branches.",
246
- fix: "Use --role production for the production branch.",
247
- exitCode: 1,
248
- nextSteps: ["prisma-cli project env list --role production"]
249
- });
250
- return {
251
- scope,
252
- descriptor: {
253
- kind: "branch",
254
- branchName: branch.gitName,
255
- branchId: branch.id
256
- },
257
- apiTarget: {
258
- class: "preview",
259
- branchId: branch.id
260
- }
261
- };
262
- }
263
- async function resolveListScopeToApi(client, projectId, explicit, options) {
264
- if (explicit) {
265
- const resolved = await resolveScopeToApi(client, projectId, explicit, {
266
- createBranchIfMissing: false,
267
- signal: options.signal
268
- });
269
- return {
270
- kind: "scoped",
271
- descriptor: resolved.descriptor,
272
- target: targetFromExplicitScope(resolved.descriptor),
273
- apiTarget: resolved.apiTarget,
274
- addScope: resolved.scope
275
- };
276
- }
277
- const gitBranch = await readLocalGitBranch(options.cwd, options.signal);
278
- if (gitBranch) {
279
- const branch = (await listBranchesByName(client, projectId, gitBranch, options.signal))[0];
280
- if (!branch) return {
281
- kind: "scoped",
282
- descriptor: {
283
- kind: "role",
284
- role: "preview"
285
- },
286
- target: {
287
- source: "local-git",
288
- branchName: gitBranch,
289
- branchExists: false,
290
- envMap: "preview"
291
- },
292
- apiTarget: {
293
- class: "preview",
294
- branchId: null
295
- },
296
- addScope: {
297
- kind: "branch",
298
- branchName: gitBranch
299
- }
300
- };
301
- if (branch.role === "production") return {
302
- kind: "scoped",
303
- descriptor: {
304
- kind: "role",
305
- role: "production"
306
- },
307
- target: {
308
- source: "local-git",
309
- branchName: branch.gitName,
310
- branchId: branch.id,
311
- branchRole: branch.role,
312
- branchExists: true,
313
- envMap: "production"
314
- },
315
- apiTarget: {
316
- class: "production",
317
- branchId: null
318
- },
319
- addScope: {
320
- kind: "role",
321
- role: "production"
322
- }
323
- };
324
- return {
325
- kind: "scoped",
326
- descriptor: {
327
- kind: "branch",
328
- branchName: branch.gitName,
329
- branchId: branch.id
330
- },
331
- target: {
332
- source: "local-git",
333
- branchName: branch.gitName,
334
- branchId: branch.id,
335
- branchRole: branch.role,
336
- branchExists: true,
337
- envMap: "preview"
338
- },
339
- apiTarget: {
340
- class: "preview",
341
- branchId: branch.id
342
- },
343
- addScope: {
344
- kind: "branch",
345
- branchName: branch.gitName
346
- }
347
- };
348
- }
349
- return {
350
- kind: "overview",
351
- descriptor: { kind: "overview" },
352
- target: {
353
- source: "overview",
354
- envMap: "overview"
355
- },
356
- addScope: {
357
- kind: "role",
358
- role: "preview"
359
- }
360
- };
361
- }
362
- function targetFromExplicitScope(scope) {
363
- if (scope.kind === "branch") return {
364
- source: "explicit",
365
- branchName: scope.branchName,
366
- branchId: scope.branchId,
367
- branchRole: "preview",
368
- branchExists: true,
369
- envMap: "preview"
370
- };
371
- if (scope.kind === "role") return {
372
- source: "explicit",
373
- envMap: scope.role
374
- };
375
- return {
376
- source: "overview",
377
- envMap: "overview"
378
- };
379
- }
380
- function formatScopeFlag(scope) {
381
- if (scope.kind === "role") return `--role ${scope.role}`;
382
- return `--branch ${scope.branchName}`;
383
- }
384
- async function listBranchesByName(client, projectId, branchName, signal) {
385
- const { data, error, response } = await client.GET("/v1/projects/{projectId}/branches", {
386
- params: {
387
- path: { projectId },
388
- query: { gitName: branchName }
389
- },
390
- signal
391
- });
392
- if (error || !data) throw apiCallError(`Failed to resolve branch "${branchName}"`, response, error);
393
- return data.data;
394
- }
395
- async function resolveExistingBranch(client, projectId, branchName, signal) {
396
- const branch = (await listBranchesByName(client, projectId, branchName, signal))[0];
397
- if (!branch) throw new CliError({
398
- code: "ENV_BRANCH_NOT_FOUND",
399
- domain: "app",
400
- summary: `Branch "${branchName}" not found`,
401
- why: "Branch update, list, and remove commands only target existing preview branches.",
402
- fix: "Create the branch by deploying it, or use `project env add --branch` to create its first override.",
403
- exitCode: 1,
404
- nextSteps: [`prisma-cli project env add KEY=value --branch ${branchName}`]
405
- });
406
- return branch;
407
- }
408
- async function resolveOrCreateBranch(client, projectId, branchName, signal) {
409
- const existing = (await listBranchesByName(client, projectId, branchName, signal))[0];
410
- if (existing) return existing;
411
- if (!await projectHasDefaultBranch(client, projectId, signal)) throw new CliError({
412
- code: "ENV_BRANCH_CREATE_REQUIRES_DEFAULT_BRANCH",
413
- domain: "app",
414
- summary: `Cannot create branch "${branchName}" from project env`,
415
- why: "Creating the first branch would make it the project default, but branch overrides are preview-only.",
416
- fix: "Create or deploy the default branch first, then add the branch override.",
417
- exitCode: 1,
418
- nextSteps: ["prisma-cli app deploy --branch main"]
419
- });
420
- const { data, error, response } = await client.POST("/v1/projects/{projectId}/branches", {
421
- params: { path: { projectId } },
422
- body: {
423
- gitName: branchName,
424
- isDefault: false
425
- },
426
- signal
427
- });
428
- if (error || !data) {
429
- if (response?.status === 409) {
430
- const raced = (await listBranchesByName(client, projectId, branchName, signal))[0];
431
- if (raced) return raced;
432
- }
433
- throw apiCallError(`Failed to create branch "${branchName}"`, response, error);
434
- }
435
- return data.data;
436
- }
437
- async function projectHasDefaultBranch(client, projectId, signal) {
438
- let cursor;
439
- while (true) {
440
- const query = {};
441
- if (cursor !== void 0) query.cursor = cursor;
442
- const result = await client.GET("/v1/projects/{projectId}/branches", {
443
- params: {
444
- path: { projectId },
445
- query
446
- },
447
- signal
448
- });
449
- if (result.error || !result.data) throw apiCallError("Failed to check project default branch", result.response, result.error);
450
- if (result.data.data.some((branch) => branch.isDefault)) return true;
451
- if (!result.data.pagination.hasMore || !result.data.pagination.nextCursor) return false;
452
- cursor = result.data.pagination.nextCursor;
453
- }
454
- }
455
- async function listVariables(client, projectId, resolved, signal) {
456
- return materializeEffectiveRows(await collectEnvironmentVariables(client, projectId, signal, {
457
- className: resolved.apiTarget.class,
458
- filter: (row) => rowMatchesScope(row, resolved)
459
- }), resolved);
460
- }
461
- async function listOverviewVariables(client, projectId, signal) {
462
- return (await collectEnvironmentVariables(client, projectId, signal, { filter: (row) => row.branchId === null && (row.class === "production" || row.class === "preview") })).sort((left, right) => {
463
- const roleOrder = roleSortOrder(left.class) - roleSortOrder(right.class);
464
- return roleOrder !== 0 ? roleOrder : left.key.localeCompare(right.key);
465
- });
466
- }
467
- async function collectEnvironmentVariables(client, projectId, signal, options) {
468
- const collected = [];
469
- let cursor;
470
- while (true) {
471
- const query = { projectId };
472
- if (options.className !== void 0) query.class = options.className;
473
- if (cursor !== void 0) query.cursor = cursor;
474
- const result = await client.GET("/v1/environment-variables", {
475
- params: { query },
476
- signal
477
- });
478
- if (result.error || !result.data) throw apiCallError(`Failed to list environment variables`, result.response, result.error);
479
- const page = result.data.data.filter(options.filter);
480
- collected.push(...page);
481
- if (!result.data.pagination.hasMore || !result.data.pagination.nextCursor) break;
482
- cursor = result.data.pagination.nextCursor;
483
- }
484
- return collected;
485
- }
486
- function roleSortOrder(role) {
487
- return role === "production" ? 0 : 1;
488
- }
489
- function rowMatchesScope(row, resolved) {
490
- if (row.class !== resolved.apiTarget.class) return false;
491
- if (resolved.apiTarget.branchId === null) return row.branchId === null;
492
- return row.branchId === null || row.branchId === resolved.apiTarget.branchId;
493
- }
494
- function materializeEffectiveRows(rows, resolved) {
495
- if (resolved.apiTarget.branchId === null) return rows;
496
- const byKey = /* @__PURE__ */ new Map();
497
- for (const row of rows) if (row.branchId === null && !byKey.has(row.key)) byKey.set(row.key, row);
498
- for (const row of rows) if (row.branchId === resolved.apiTarget.branchId) byKey.set(row.key, row);
499
- return [...byKey.values()].sort((left, right) => left.key.localeCompare(right.key));
500
- }
501
- //#endregion
502
- export { runEnvAdd, runEnvList, runEnvRemove, runEnvUpdate };