@prisma/cli 3.0.0-dev.97.1 → 8.0.0-rc.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.
Files changed (99) hide show
  1. package/README.md +3 -14
  2. package/dist/adapters/local-state.js +14 -3
  3. package/dist/{lib/auth → auth}/client.js +11 -3
  4. package/dist/auth/errors.js +50 -0
  5. package/dist/{lib/auth → auth}/guard.js +7 -6
  6. package/dist/{lib/auth → auth}/login.js +147 -6
  7. package/dist/{lib/auth/auth-ops.js → auth/operations.js} +63 -13
  8. package/dist/auth/recipient.js +42 -0
  9. package/dist/{adapters → auth}/token-storage.js +28 -7
  10. package/dist/auth/workspaces.js +171 -0
  11. package/dist/cli-command.js +14 -0
  12. package/dist/cli-name.js +12 -0
  13. package/dist/cli.js +1 -1
  14. package/dist/cli2.js +25 -8
  15. package/dist/command-arguments.js +12 -0
  16. package/dist/commands/agent/index.js +60 -0
  17. package/dist/commands/app/index.js +11 -6
  18. package/dist/commands/auth/index.js +2 -3
  19. package/dist/commands/bucket/index.js +123 -0
  20. package/dist/commands/build/index.js +29 -0
  21. package/dist/commands/database/index.js +92 -2
  22. package/dist/commands/feedback/index.js +20 -0
  23. package/dist/commands/git/index.js +1 -1
  24. package/dist/commands/init/index.js +33 -0
  25. package/dist/commands/project/index.js +54 -5
  26. package/dist/controllers/agent-setup.js +52 -0
  27. package/dist/controllers/agent.js +228 -0
  28. package/dist/controllers/app-env-api.js +3 -2
  29. package/dist/controllers/app-env-file.js +1 -1
  30. package/dist/controllers/app-env.js +5 -5
  31. package/dist/controllers/app.js +423 -358
  32. package/dist/controllers/auth.js +62 -254
  33. package/dist/controllers/branch.js +5 -16
  34. package/dist/controllers/bucket.js +184 -0
  35. package/dist/controllers/build.js +88 -0
  36. package/dist/controllers/database.js +230 -85
  37. package/dist/controllers/feedback.js +90 -0
  38. package/dist/controllers/init.js +814 -0
  39. package/dist/controllers/project.js +345 -184
  40. package/dist/controllers/select-prompt-port.js +1 -0
  41. package/dist/{shell/errors.js → errors.js} +8 -40
  42. package/dist/lib/agent/cli-command.js +20 -0
  43. package/dist/lib/agent/constants.js +12 -0
  44. package/dist/lib/agent/package-manager.js +99 -0
  45. package/dist/lib/agent/setup-status.js +83 -0
  46. package/dist/lib/app/app-provider.js +168 -95
  47. package/dist/lib/app/branch-database-deploy.js +70 -42
  48. package/dist/lib/app/branch-database.js +39 -20
  49. package/dist/lib/app/build-settings.js +8 -3
  50. package/dist/lib/app/build.js +16 -14
  51. package/dist/lib/app/bun-project.js +1 -1
  52. package/dist/lib/app/compute-config.js +29 -31
  53. package/dist/lib/app/deploy-plan.js +1 -0
  54. package/dist/lib/app/deploy-progress.js +7 -7
  55. package/dist/lib/app/env-config.js +1 -1
  56. package/dist/lib/app/env-file.js +2 -2
  57. package/dist/lib/app/env-vars.js +1 -1
  58. package/dist/lib/app/local-dev.js +1 -1
  59. package/dist/lib/app/production-deploy-gate.js +3 -2
  60. package/dist/lib/bucket/provider.js +139 -0
  61. package/dist/lib/database/provider.js +235 -17
  62. package/dist/lib/diagnostics.js +2 -1
  63. package/dist/lib/feedback.js +15 -0
  64. package/dist/lib/git/local-branch.js +1 -1
  65. package/dist/lib/project/interactive-setup.js +6 -5
  66. package/dist/lib/project/local-pin.js +1 -1
  67. package/dist/lib/project/provider.js +93 -0
  68. package/dist/lib/project/resolution.js +11 -8
  69. package/dist/lib/project/setup.js +9 -6
  70. package/dist/lib/version.js +3 -2
  71. package/dist/lib/workspace-id.js +18 -0
  72. package/dist/payload-B88Qvzxk-CrtTXSOe.js +34 -0
  73. package/dist/presenters/agent.js +74 -0
  74. package/dist/presenters/app.js +33 -7
  75. package/dist/presenters/auth.js +3 -2
  76. package/dist/presenters/bucket.js +174 -0
  77. package/dist/presenters/database.js +193 -5
  78. package/dist/presenters/feedback.js +26 -0
  79. package/dist/presenters/init.js +30 -0
  80. package/dist/presenters/project.js +98 -4
  81. package/dist/shell/cli-command.js +2 -0
  82. package/dist/shell/command-meta.js +303 -4
  83. package/dist/shell/command-runner.js +13 -6
  84. package/dist/shell/help.js +6 -5
  85. package/dist/shell/output.js +65 -3
  86. package/dist/shell/prompt.js +12 -5
  87. package/dist/shell/runtime.js +4 -21
  88. package/dist/state-dir.js +12 -0
  89. package/dist/{shell/update-check.js → update-check.js} +6 -5
  90. package/dist/v8/cli.js +14699 -0
  91. package/dist/v8/sender.js +192 -0
  92. package/package.json +21 -13
  93. package/dist/adapters/mock-api.js +0 -136
  94. package/dist/lib/app/app-interaction.js +0 -5
  95. package/dist/shell/command-arguments.js +0 -6
  96. package/dist/use-cases/auth.js +0 -145
  97. package/dist/use-cases/branch.js +0 -47
  98. package/dist/use-cases/create-cli-gateways.js +0 -68
  99. package/dist/use-cases/project.js +0 -30
@@ -2,8 +2,8 @@ import { attachCommandDescriptor } from "../../shell/command-meta.js";
2
2
  import { addCompactGlobalFlags, addGlobalFlags } from "../../shell/global-flags.js";
3
3
  import { configureRuntimeCommand } from "../../shell/runtime.js";
4
4
  import { runCommand } from "../../shell/command-runner.js";
5
- import { runDatabaseConnectionCreate, runDatabaseConnectionList, runDatabaseConnectionRemove, runDatabaseCreate, runDatabaseList, runDatabaseRemove, runDatabaseShow } from "../../controllers/database.js";
6
- import { renderDatabaseConnectionCreate, renderDatabaseConnectionCreateStdout, renderDatabaseConnectionList, renderDatabaseConnectionRemove, renderDatabaseCreate, renderDatabaseCreateStdout, renderDatabaseList, renderDatabaseRemove, renderDatabaseShow, serializeDatabaseConnectionCreate, serializeDatabaseConnectionList, serializeDatabaseConnectionRemove, serializeDatabaseCreate, serializeDatabaseList, serializeDatabaseRemove, serializeDatabaseShow } from "../../presenters/database.js";
5
+ import { runDatabaseBackupList, runDatabaseConnectionCreate, runDatabaseConnectionList, runDatabaseConnectionRemove, runDatabaseConnectionRotate, runDatabaseCreate, runDatabaseList, runDatabaseRemove, runDatabaseRestore, runDatabaseShow, runDatabaseUsage } from "../../controllers/database.js";
6
+ import { renderDatabaseBackupList, renderDatabaseConnectionCreate, renderDatabaseConnectionCreateStdout, renderDatabaseConnectionList, renderDatabaseConnectionRemove, renderDatabaseConnectionRotate, renderDatabaseConnectionRotateStdout, renderDatabaseCreate, renderDatabaseCreateStdout, renderDatabaseList, renderDatabaseRemove, renderDatabaseRestore, renderDatabaseShow, renderDatabaseUsage, serializeDatabaseBackupList, serializeDatabaseConnectionCreate, serializeDatabaseConnectionList, serializeDatabaseConnectionRemove, serializeDatabaseConnectionRotate, serializeDatabaseCreate, serializeDatabaseList, serializeDatabaseRemove, serializeDatabaseRestore, serializeDatabaseShow, serializeDatabaseUsage } from "../../presenters/database.js";
7
7
  import { Command, Option } from "commander";
8
8
  //#region src/commands/database/index.ts
9
9
  function createDatabaseCommand(runtime) {
@@ -12,7 +12,10 @@ function createDatabaseCommand(runtime) {
12
12
  database.addCommand(createDatabaseListCommand(runtime));
13
13
  database.addCommand(createDatabaseShowCommand(runtime));
14
14
  database.addCommand(createDatabaseCreateCommand(runtime));
15
+ database.addCommand(createDatabaseUsageCommand(runtime));
16
+ database.addCommand(createDatabaseRestoreCommand(runtime));
15
17
  database.addCommand(createDatabaseRemoveCommand(runtime));
18
+ database.addCommand(createDatabaseBackupCommand(runtime));
16
19
  database.addCommand(createDatabaseConnectionCommand(runtime));
17
20
  return database;
18
21
  }
@@ -75,6 +78,78 @@ function createDatabaseCreateCommand(runtime) {
75
78
  });
76
79
  return command;
77
80
  }
81
+ function createDatabaseUsageCommand(runtime) {
82
+ const command = attachCommandDescriptor(configureRuntimeCommand(new Command("usage"), runtime), "database.usage");
83
+ command.argument("<database>", "Database id or name").addOption(new Option("--from <iso-date>", "Start of the usage period")).addOption(new Option("--to <iso-date>", "End of the usage period"));
84
+ addProjectAndBranchOptions(command);
85
+ addGlobalFlags(command);
86
+ command.action(async (databaseRef, options) => {
87
+ const projectRef = options.project;
88
+ const branchName = options.branch;
89
+ const from = options.from;
90
+ const to = options.to;
91
+ await runCommand(runtime, "database.usage", options, (context) => runDatabaseUsage(context, databaseRef, {
92
+ projectRef,
93
+ branchName,
94
+ from,
95
+ to
96
+ }), {
97
+ renderHuman: (context, descriptor, result) => renderDatabaseUsage(context, descriptor, result),
98
+ renderJson: (result) => serializeDatabaseUsage(result)
99
+ });
100
+ });
101
+ return command;
102
+ }
103
+ function createDatabaseRestoreCommand(runtime) {
104
+ const command = attachCommandDescriptor(configureRuntimeCommand(new Command("restore"), runtime), "database.restore");
105
+ command.argument("<database>", "Target database id or name").addOption(new Option("--backup <backup-id>", "Backup to restore from")).addOption(new Option("--source-database <database>", "Database the backup belongs to (defaults to the target)")).addOption(new Option("--confirm <database-id>", "Exact target database id required to restore"));
106
+ addProjectAndBranchOptions(command);
107
+ addGlobalFlags(command);
108
+ command.action(async (databaseRef, options) => {
109
+ const projectRef = options.project;
110
+ const branchName = options.branch;
111
+ const backupId = options.backup;
112
+ const sourceDatabaseRef = options.sourceDatabase;
113
+ const confirm = options.confirm;
114
+ await runCommand(runtime, "database.restore", options, (context) => runDatabaseRestore(context, databaseRef, {
115
+ projectRef,
116
+ branchName,
117
+ backupId,
118
+ sourceDatabaseRef,
119
+ confirm
120
+ }), {
121
+ renderHuman: (context, descriptor, result) => renderDatabaseRestore(context, descriptor, result),
122
+ renderJson: (result) => serializeDatabaseRestore(result)
123
+ });
124
+ });
125
+ return command;
126
+ }
127
+ function createDatabaseBackupCommand(runtime) {
128
+ const backup = attachCommandDescriptor(configureRuntimeCommand(new Command("backup"), runtime), "database.backup");
129
+ addCompactGlobalFlags(backup);
130
+ backup.addCommand(createDatabaseBackupListCommand(runtime));
131
+ return backup;
132
+ }
133
+ function createDatabaseBackupListCommand(runtime) {
134
+ const command = attachCommandDescriptor(configureRuntimeCommand(new Command("list"), runtime), "database.backup.list");
135
+ command.argument("<database>", "Database id or name").addOption(new Option("--limit <n>", "Maximum number of backups to return"));
136
+ addProjectAndBranchOptions(command);
137
+ addGlobalFlags(command);
138
+ command.action(async (databaseRef, options) => {
139
+ const projectRef = options.project;
140
+ const branchName = options.branch;
141
+ const limit = options.limit;
142
+ await runCommand(runtime, "database.backup.list", options, (context) => runDatabaseBackupList(context, databaseRef, {
143
+ projectRef,
144
+ branchName,
145
+ limit
146
+ }), {
147
+ renderHuman: (context, descriptor, result) => renderDatabaseBackupList(context, descriptor, result),
148
+ renderJson: (result) => serializeDatabaseBackupList(result)
149
+ });
150
+ });
151
+ return command;
152
+ }
78
153
  function createDatabaseRemoveCommand(runtime) {
79
154
  const command = attachCommandDescriptor(configureRuntimeCommand(new Command("remove"), runtime), "database.remove");
80
155
  command.argument("<database>", "Database id or name").addOption(new Option("--confirm <database-id>", "Exact database id required to remove"));
@@ -100,9 +175,24 @@ function createDatabaseConnectionCommand(runtime) {
100
175
  addCompactGlobalFlags(connection);
101
176
  connection.addCommand(createDatabaseConnectionListCommand(runtime));
102
177
  connection.addCommand(createDatabaseConnectionCreateCommand(runtime));
178
+ connection.addCommand(createDatabaseConnectionRotateCommand(runtime));
103
179
  connection.addCommand(createDatabaseConnectionRemoveCommand(runtime));
104
180
  return connection;
105
181
  }
182
+ function createDatabaseConnectionRotateCommand(runtime) {
183
+ const command = attachCommandDescriptor(configureRuntimeCommand(new Command("rotate"), runtime), "database.connection.rotate");
184
+ command.argument("<connection>", "Connection id").addOption(new Option("--confirm <connection-id>", "Exact connection id required to rotate"));
185
+ addGlobalFlags(command);
186
+ command.action(async (connectionRef, options) => {
187
+ const confirm = options.confirm;
188
+ await runCommand(runtime, "database.connection.rotate", options, (context) => runDatabaseConnectionRotate(context, connectionRef, { confirm }), {
189
+ renderStdout: (context, descriptor, result) => renderDatabaseConnectionRotateStdout(context, descriptor, result),
190
+ renderHuman: (context, descriptor, result) => renderDatabaseConnectionRotate(context, descriptor, result),
191
+ renderJson: (result) => serializeDatabaseConnectionRotate(result)
192
+ });
193
+ });
194
+ return command;
195
+ }
106
196
  function createDatabaseConnectionListCommand(runtime) {
107
197
  const command = attachCommandDescriptor(configureRuntimeCommand(new Command("list"), runtime), "database.connection.list");
108
198
  command.argument("<database>", "Database id or name");
@@ -0,0 +1,20 @@
1
+ import { attachCommandDescriptor } from "../../shell/command-meta.js";
2
+ import { addGlobalFlags } from "../../shell/global-flags.js";
3
+ import { configureRuntimeCommand } from "../../shell/runtime.js";
4
+ import { runCommand } from "../../shell/command-runner.js";
5
+ import { runFeedback } from "../../controllers/feedback.js";
6
+ import { renderFeedbackSuccess } from "../../presenters/feedback.js";
7
+ import { Command, Option } from "commander";
8
+ //#region src/commands/feedback/index.ts
9
+ function createFeedbackCommand(runtime) {
10
+ const command = attachCommandDescriptor(configureRuntimeCommand(new Command("feedback"), runtime), "feedback");
11
+ command.argument("<message>", "Feedback text (up to 4000 characters)").addOption(new Option("--email <address>", "Contact email if you want a reply; feedback is anonymous without it"));
12
+ addGlobalFlags(command);
13
+ command.action(async (message, options) => {
14
+ const flags = options;
15
+ await runCommand(runtime, "feedback", options, (context) => runFeedback(context, message, { email: flags.email }), { renderHuman: (context, descriptor, result) => renderFeedbackSuccess(context, descriptor, result) });
16
+ });
17
+ return command;
18
+ }
19
+ //#endregion
20
+ export { createFeedbackCommand };
@@ -1,8 +1,8 @@
1
1
  import { attachCommandDescriptor } from "../../shell/command-meta.js";
2
2
  import { addCompactGlobalFlags, addGlobalFlags } from "../../shell/global-flags.js";
3
3
  import { configureRuntimeCommand } from "../../shell/runtime.js";
4
- import { runGitConnect, runGitDisconnect } from "../../controllers/project.js";
5
4
  import { runCommand } from "../../shell/command-runner.js";
5
+ import { runGitConnect, runGitDisconnect } from "../../controllers/project.js";
6
6
  import { renderGitConnect, renderGitDisconnect } from "../../presenters/project.js";
7
7
  import { Command } from "commander";
8
8
  //#region src/commands/git/index.ts
@@ -0,0 +1,33 @@
1
+ import { attachCommandDescriptor } from "../../shell/command-meta.js";
2
+ import { addGlobalFlags } from "../../shell/global-flags.js";
3
+ import { configureRuntimeCommand } from "../../shell/runtime.js";
4
+ import { runCommand } from "../../shell/command-runner.js";
5
+ import { runInit } from "../../controllers/init.js";
6
+ import { renderInit, serializeInit } from "../../presenters/init.js";
7
+ import { Command, Option } from "commander";
8
+ //#region src/commands/init/index.ts
9
+ function createInitCommand(runtime) {
10
+ const command = attachCommandDescriptor(configureRuntimeCommand(new Command("init"), runtime), "init");
11
+ command.addOption(new Option("--framework <framework>", "Framework override; detected when omitted")).addOption(new Option("--entry <path>", "Source entrypoint for entrypoint frameworks (Bun, Hono)")).addOption(new Option("--http-port <port>", "HTTP port the app listens on")).addOption(new Option("--region <region>", "Region used when deploy creates the app")).addOption(new Option("--name <app-name>", "App name")).addOption(new Option("--link", "Link this directory to a Project")).addOption(new Option("--no-link", "Skip the Project link step")).addOption(new Option("--project <id-or-name>", "Project to link this directory to")).addOption(new Option("--install", "Install @prisma/compute-sdk for config types")).addOption(new Option("--no-install", "Skip the types install step")).addOption(new Option("--format <ts|json>", "Config file format: ts (default) writes prisma.compute.ts, json writes dependency-free prisma.compute.json; --format ts converts an existing prisma.compute.json"));
12
+ addGlobalFlags(command);
13
+ command.action(async (options) => {
14
+ const flags = options;
15
+ await runCommand(runtime, "init", options, (context) => runInit(context, {
16
+ framework: flags.framework,
17
+ entry: flags.entry,
18
+ httpPort: flags.httpPort,
19
+ region: flags.region,
20
+ name: flags.name,
21
+ link: flags.link,
22
+ project: flags.project,
23
+ install: flags.install,
24
+ format: flags.format
25
+ }), {
26
+ renderHuman: (context, descriptor, result) => renderInit(context, descriptor, result),
27
+ renderJson: (result) => serializeInit(result)
28
+ });
29
+ });
30
+ return command;
31
+ }
32
+ //#endregion
33
+ export { createInitCommand };
@@ -1,11 +1,11 @@
1
1
  import { attachCommandDescriptor } from "../../shell/command-meta.js";
2
2
  import { addCompactGlobalFlags, addGlobalFlags } from "../../shell/global-flags.js";
3
3
  import { configureRuntimeCommand } from "../../shell/runtime.js";
4
- import { runProjectCreate, runProjectLink, runProjectList, runProjectShow } from "../../controllers/project.js";
5
4
  import { runCommand } from "../../shell/command-runner.js";
6
- import { renderProjectList, renderProjectSetup, renderProjectShow, serializeProjectList, serializeProjectSetup, serializeProjectShow } from "../../presenters/project.js";
5
+ import { runProjectCreate, runProjectLink, runProjectList, runProjectRemove, runProjectRename, runProjectShow, runProjectTransfer } from "../../controllers/project.js";
6
+ import { renderProjectList, renderProjectRemove, renderProjectRename, renderProjectSetup, renderProjectShow, renderProjectTransfer, serializeProjectList, serializeProjectRemove, serializeProjectRename, serializeProjectSetup, serializeProjectShow, serializeProjectTransfer } from "../../presenters/project.js";
7
7
  import { createEnvCommand } from "../env.js";
8
- import { Command } from "commander";
8
+ import { Command, Option } from "commander";
9
9
  //#region src/commands/project/index.ts
10
10
  function createProjectCommand(runtime) {
11
11
  const project = attachCommandDescriptor(configureRuntimeCommand(new Command("project"), runtime), "project");
@@ -14,15 +14,64 @@ function createProjectCommand(runtime) {
14
14
  project.addCommand(createProjectShowCommand(runtime));
15
15
  project.addCommand(createProjectCreateCommand(runtime));
16
16
  project.addCommand(createProjectLinkCommand(runtime));
17
+ project.addCommand(createProjectRenameCommand(runtime));
18
+ project.addCommand(createProjectRemoveCommand(runtime));
19
+ project.addCommand(createProjectTransferCommand(runtime));
17
20
  project.addCommand(createEnvCommand(runtime));
18
21
  return project;
19
22
  }
23
+ function createProjectRenameCommand(runtime) {
24
+ const command = attachCommandDescriptor(configureRuntimeCommand(new Command("rename"), runtime), "project.rename");
25
+ command.argument("<name>", "New project name").addOption(new Option("--project <id-or-name>", "Project id or name"));
26
+ addGlobalFlags(command);
27
+ command.action(async (name, options) => {
28
+ const projectRef = options.project;
29
+ await runCommand(runtime, "project.rename", options, (context) => runProjectRename(context, name, { project: projectRef }), {
30
+ renderHuman: (context, descriptor, result) => renderProjectRename(context, descriptor, result),
31
+ renderJson: (result) => serializeProjectRename(result)
32
+ });
33
+ });
34
+ return command;
35
+ }
36
+ function createProjectRemoveCommand(runtime) {
37
+ const command = attachCommandDescriptor(configureRuntimeCommand(new Command("remove"), runtime), "project.remove");
38
+ command.argument("<project>", "Project id or name").addOption(new Option("--confirm <project-id>", "Exact project id required to remove"));
39
+ addGlobalFlags(command);
40
+ command.action(async (projectRef, options) => {
41
+ const confirm = options.confirm;
42
+ await runCommand(runtime, "project.remove", options, (context) => runProjectRemove(context, projectRef, { confirm }), {
43
+ renderHuman: (context, descriptor, result) => renderProjectRemove(context, descriptor, result),
44
+ renderJson: (result) => serializeProjectRemove(result)
45
+ });
46
+ });
47
+ return command;
48
+ }
49
+ function createProjectTransferCommand(runtime) {
50
+ const command = attachCommandDescriptor(configureRuntimeCommand(new Command("transfer"), runtime), "project.transfer");
51
+ command.argument("<project>", "Project id or name").addOption(new Option("--to-workspace <id-or-name>", "Locally authenticated workspace to receive the project")).addOption(new Option("--recipient-token <token>", "Access token for the receiving workspace")).addOption(new Option("--confirm <project-id>", "Exact project id required to transfer"));
52
+ addGlobalFlags(command);
53
+ command.action(async (projectRef, options) => {
54
+ const toWorkspace = options.toWorkspace;
55
+ const recipientToken = options.recipientToken;
56
+ const confirm = options.confirm;
57
+ await runCommand(runtime, "project.transfer", options, (context) => runProjectTransfer(context, projectRef, {
58
+ toWorkspace,
59
+ recipientToken,
60
+ confirm
61
+ }), {
62
+ renderHuman: (context, descriptor, result) => renderProjectTransfer(context, descriptor, result),
63
+ renderJson: (result) => serializeProjectTransfer(result)
64
+ });
65
+ });
66
+ return command;
67
+ }
20
68
  function createProjectCreateCommand(runtime) {
21
69
  const command = attachCommandDescriptor(configureRuntimeCommand(new Command("create"), runtime), "project.create");
22
- command.argument("<name>", "Project name");
70
+ command.argument("<name>", "Project name").addOption(new Option("--region <region>", "Prisma Compute region id"));
23
71
  addGlobalFlags(command);
24
72
  command.action(async (name, options) => {
25
- await runCommand(runtime, "project.create", options, (context) => runProjectCreate(context, String(name)), {
73
+ const region = options.region;
74
+ await runCommand(runtime, "project.create", options, (context) => runProjectCreate(context, String(name), { region }), {
26
75
  renderHuman: (context, descriptor, result) => renderProjectSetup(context, descriptor, result),
27
76
  renderJson: (result) => serializeProjectSetup(result)
28
77
  });
@@ -0,0 +1,52 @@
1
+ import { resolvePrismaCliPackageCommand } from "../lib/agent/cli-command.js";
2
+ import { PRISMA_AGENT_INSTALL_ARGS, PRISMA_COMPUTE_AGENT_SKILL } from "../lib/agent/constants.js";
3
+ import { readPrismaAgentSetupStatus, shouldOfferPrismaAgentSetup } from "../lib/agent/setup-status.js";
4
+ import { runAgentInstall } from "./agent.js";
5
+ import { renderSummaryLine } from "../shell/ui.js";
6
+ import { canPrompt } from "../shell/runtime.js";
7
+ import { confirmPrompt } from "../shell/prompt.js";
8
+ //#region src/controllers/agent-setup.ts
9
+ /**
10
+ * One-time interactive offer to install the Prisma Compute skill for the
11
+ * project. Shared by the commands that establish a project setup (init,
12
+ * deploy); the answer is remembered, so whichever command runs first asks.
13
+ * Returns warnings; a failed install must not fail the calling command.
14
+ */
15
+ async function maybePromptForAgentSetup(context, projectDir) {
16
+ if (!canPrompt(context) || context.flags.yes || context.flags.quiet) return [];
17
+ if (!shouldOfferPrismaAgentSetup(await readPrismaAgentSetupStatus({
18
+ cwd: projectDir,
19
+ stateStore: context.stateStore,
20
+ signal: context.runtime.signal,
21
+ requiredSkill: "prisma-compute"
22
+ }))) return [];
23
+ if (!await confirmPrompt({
24
+ input: context.runtime.stdin,
25
+ output: context.runtime.stderr,
26
+ signal: context.runtime.signal,
27
+ message: "Install the Prisma Compute skill for this project?",
28
+ initialValue: true
29
+ })) {
30
+ await context.stateStore.setAgentSetupPromptDismissedAt((/* @__PURE__ */ new Date()).toISOString());
31
+ return [];
32
+ }
33
+ try {
34
+ await runAgentInstall(context, { skill: [PRISMA_COMPUTE_AGENT_SKILL] }, "install", { cwd: projectDir });
35
+ if (!context.flags.quiet && !context.flags.json) context.output.stderr.write(`${renderSummaryLine(context.ui, "success", "Installed the Prisma Compute skill for this project.")}\n\n`);
36
+ return [];
37
+ } catch (error) {
38
+ const message = error instanceof Error ? error.message : "Prisma skill install failed.";
39
+ if (!context.flags.quiet && !context.flags.json) context.output.stderr.write(`${renderSummaryLine(context.ui, "warning", `Skipped Prisma skill install: ${message}`)}\n\n`);
40
+ return [`The Prisma Compute skill was not installed. Run ${await resolvePrismaCliPackageCommand({
41
+ cwd: projectDir,
42
+ signal: context.runtime.signal,
43
+ args: [
44
+ ...PRISMA_AGENT_INSTALL_ARGS,
45
+ "--skill",
46
+ PRISMA_COMPUTE_AGENT_SKILL
47
+ ]
48
+ })} to try again.`];
49
+ }
50
+ }
51
+ //#endregion
52
+ export { maybePromptForAgentSetup };
@@ -0,0 +1,228 @@
1
+ import { resolveSkillsPackageRunner } from "../lib/agent/package-manager.js";
2
+ import { resolvePrismaCliPackageCommand } from "../lib/agent/cli-command.js";
3
+ import { DEFAULT_PRISMA_AGENT_SKILLS, DEFAULT_PRISMA_AGENT_TARGETS, PRISMA_AGENT_INSTALL_ARGS, PRISMA_AGENT_STATUS_ARGS, PRISMA_SKILLS_SOURCE, SKILLS_CLI_PACKAGE } from "../lib/agent/constants.js";
4
+ import { readPrismaAgentSetupStatus, resolvePrismaAgentSetupCwd } from "../lib/agent/setup-status.js";
5
+ import { formatShellCommand } from "../command-arguments.js";
6
+ import { CliError } from "../errors.js";
7
+ import { execa } from "execa";
8
+ //#region src/controllers/agent.ts
9
+ async function runAgentInstall(context, options, operation = "install", runOptions = {}) {
10
+ const dryRun = options.dryRun === true;
11
+ const cwd = await resolvePrismaAgentSetupCwd({
12
+ cwd: runOptions.cwd ?? context.runtime.cwd,
13
+ signal: context.runtime.signal
14
+ });
15
+ const skills = await installSkills(context, {
16
+ command: await buildSkillsInstallCommand(context, options, cwd),
17
+ cwd,
18
+ dryRun
19
+ });
20
+ const nextSteps = await resolveAgentInstallNextSteps(context, {
21
+ cwd,
22
+ dryRun,
23
+ global: options.global === true
24
+ });
25
+ return {
26
+ command: `agent.${operation}`,
27
+ result: {
28
+ operation,
29
+ skills
30
+ },
31
+ warnings: [],
32
+ nextSteps
33
+ };
34
+ }
35
+ async function resolveAgentInstallNextSteps(context, options) {
36
+ if (options.dryRun) return [];
37
+ return [`Run ${await resolvePrismaCliPackageCommand({
38
+ cwd: options.cwd,
39
+ signal: context.runtime.signal,
40
+ args: options.global ? [...PRISMA_AGENT_STATUS_ARGS, "--global"] : PRISMA_AGENT_STATUS_ARGS
41
+ })} to verify the installed Prisma skills.`];
42
+ }
43
+ async function runAgentStatus(context, options = {}) {
44
+ const statusScope = options.global ? "global" : "project";
45
+ const cwd = await resolvePrismaAgentSetupCwd({
46
+ cwd: context.runtime.cwd,
47
+ signal: context.runtime.signal
48
+ });
49
+ const status = await readPrismaAgentSetupStatus({
50
+ cwd,
51
+ stateStore: context.stateStore,
52
+ signal: context.runtime.signal
53
+ });
54
+ const installCommand = await resolvePrismaCliPackageCommand({
55
+ cwd,
56
+ signal: context.runtime.signal,
57
+ args: options.global ? [...PRISMA_AGENT_INSTALL_ARGS, "--global"] : PRISMA_AGENT_INSTALL_ARGS
58
+ });
59
+ const skillsList = await listInstalledPrismaSkills(context, cwd, statusScope);
60
+ const skillsInstalled = skillsList.status === "ok" ? skillsList.skills.length > 0 : statusScope === "project" && status.skillsInstalled;
61
+ const warnings = skillsList.status === "ok" ? [] : [statusScope === "project" ? `Could not read installed skills with ${formatShellCommand(skillsList.command)}: ${skillsList.message}. Falling back to ${status.skillsLockPath}.` : `Could not read globally installed skills with ${formatShellCommand(skillsList.command)}: ${skillsList.message}.`];
62
+ const statusSource = resolveStatusSource(skillsList, statusScope);
63
+ return {
64
+ command: "agent.status",
65
+ result: {
66
+ skills: skillsList.status === "ok" ? skillsList.skills : [],
67
+ skillsListCommand: skillsList.command,
68
+ statusScope,
69
+ skillsLockPath: status.skillsLockPath,
70
+ skillsLockInstalled: status.skillsInstalled,
71
+ skillsInstalled,
72
+ statusSource,
73
+ promptDismissedAt: status.promptDismissedAt
74
+ },
75
+ warnings,
76
+ nextSteps: skillsInstalled ? [] : [`Run ${installCommand} to install or refresh Prisma skills.`]
77
+ };
78
+ }
79
+ async function buildSkillsInstallCommand(context, options, cwd) {
80
+ const command = [
81
+ ...await resolveSkillsPackageRunner({
82
+ cwd,
83
+ signal: context.runtime.signal
84
+ }),
85
+ SKILLS_CLI_PACKAGE,
86
+ "add",
87
+ PRISMA_SKILLS_SOURCE
88
+ ];
89
+ const skills = options.skill && options.skill.length > 0 ? options.skill : DEFAULT_PRISMA_AGENT_SKILLS;
90
+ const agents = resolveTargetAgents(options);
91
+ for (const skill of skills) command.push("--skill", skill);
92
+ for (const agent of agents) command.push("--agent", agent);
93
+ if (options.global) command.push("--global");
94
+ if (options.copy || process.platform === "win32") command.push("--copy");
95
+ command.push("--yes");
96
+ return command;
97
+ }
98
+ function resolveTargetAgents(options) {
99
+ if (options.allAgents) return ["*"];
100
+ if (options.agent && options.agent.length > 0) return options.agent;
101
+ return DEFAULT_PRISMA_AGENT_TARGETS;
102
+ }
103
+ async function installSkills(context, options) {
104
+ if (options.dryRun) return {
105
+ status: "would-install",
106
+ command: options.command
107
+ };
108
+ await runChildProcess(context, options.command, options.cwd);
109
+ return {
110
+ status: "installed",
111
+ command: options.command
112
+ };
113
+ }
114
+ async function listInstalledPrismaSkills(context, cwd, scope) {
115
+ const command = [
116
+ ...await resolveSkillsPackageRunner({
117
+ cwd,
118
+ signal: context.runtime.signal
119
+ }),
120
+ SKILLS_CLI_PACKAGE,
121
+ "list",
122
+ ...scope === "global" ? ["-g"] : [],
123
+ "--json"
124
+ ];
125
+ try {
126
+ const { stdout } = await runChildProcessCapture(context, command, cwd);
127
+ return {
128
+ status: "ok",
129
+ command,
130
+ skills: parseSkillsListOutput(stdout).filter((skill) => isPrismaSkillName(skill.name))
131
+ };
132
+ } catch (error) {
133
+ if (isAbortError(error) || context.runtime.signal.aborted) throw error;
134
+ return {
135
+ status: "failed",
136
+ command,
137
+ message: error instanceof Error ? error.message : String(error)
138
+ };
139
+ }
140
+ }
141
+ async function runChildProcess(context, command, cwd) {
142
+ const [executable, args] = splitCommand(command);
143
+ try {
144
+ await execa(executable, args, {
145
+ cwd,
146
+ env: context.runtime.env,
147
+ cancelSignal: context.runtime.signal,
148
+ stdin: "ignore"
149
+ });
150
+ } catch (error) {
151
+ if (isAbortError(error)) throw error;
152
+ throw skillsInstallFailed(command, exitCodeFromError(error), error);
153
+ }
154
+ }
155
+ async function runChildProcessCapture(context, command, cwd) {
156
+ const [executable, args] = splitCommand(command);
157
+ const result = await execa(executable, args, {
158
+ cwd,
159
+ env: context.runtime.env,
160
+ cancelSignal: context.runtime.signal,
161
+ stdin: "ignore"
162
+ });
163
+ return {
164
+ stdout: result.stdout ?? "",
165
+ stderr: result.stderr ?? ""
166
+ };
167
+ }
168
+ function splitCommand(command) {
169
+ const [executable, ...args] = command;
170
+ if (!executable) throw new Error("Cannot run an empty command.");
171
+ return [executable, args];
172
+ }
173
+ function isAbortError(error) {
174
+ return error instanceof Error && error.name === "AbortError" || isObject(error) && error.isCanceled === true;
175
+ }
176
+ function exitCodeFromError(error) {
177
+ if (!isObject(error) || typeof error.exitCode !== "number") return null;
178
+ return error.exitCode;
179
+ }
180
+ function isObject(value) {
181
+ return typeof value === "object" && value !== null;
182
+ }
183
+ function resolveStatusSource(skillsList, statusScope) {
184
+ if (skillsList.status === "ok") return "skills-cli";
185
+ return statusScope === "project" ? "skills-lock" : "unavailable";
186
+ }
187
+ function parseSkillsListOutput(output) {
188
+ const parsed = JSON.parse(output);
189
+ if (!Array.isArray(parsed)) throw new Error("skills list did not return a JSON array");
190
+ return parsed.flatMap((item) => {
191
+ const skill = parseInstalledSkill(item);
192
+ return skill ? [skill] : [];
193
+ });
194
+ }
195
+ function parseInstalledSkill(value) {
196
+ if (typeof value !== "object" || value === null) return null;
197
+ const candidate = value;
198
+ if (typeof candidate.name !== "string" || typeof candidate.path !== "string" || typeof candidate.scope !== "string" || !Array.isArray(candidate.agents)) return null;
199
+ return {
200
+ name: candidate.name,
201
+ path: candidate.path,
202
+ scope: candidate.scope,
203
+ agents: candidate.agents.filter((agent) => typeof agent === "string")
204
+ };
205
+ }
206
+ function isPrismaSkillName(name) {
207
+ return name === "prisma" || name.startsWith("prisma-");
208
+ }
209
+ function skillsInstallFailed(command, code, error) {
210
+ const commandText = formatShellCommand(command);
211
+ return new CliError({
212
+ code: "AGENT_SKILLS_INSTALL_FAILED",
213
+ domain: "cli",
214
+ summary: "Prisma skills install failed",
215
+ why: `The skills installer exited with code ${code ?? "unknown"}.`,
216
+ fix: "Run the command below to retry the installer directly.",
217
+ debug: formatErrorDebug(error),
218
+ exitCode: 1,
219
+ nextSteps: [commandText]
220
+ });
221
+ }
222
+ function formatErrorDebug(error) {
223
+ if (error instanceof Error) return error.stack ?? error.message;
224
+ if (error === void 0) return;
225
+ return String(error);
226
+ }
227
+ //#endregion
228
+ export { runAgentInstall, runAgentStatus };
@@ -1,11 +1,12 @@
1
- import { CliError, authRequiredError } from "../shell/errors.js";
1
+ import { CliError, authRequiredError } from "../errors.js";
2
2
  //#region src/controllers/app-env-api.ts
3
3
  async function findVariableByNaturalKey(client, projectId, key, resolved, signal) {
4
4
  const { data, error, response } = await client.GET("/v1/environment-variables", {
5
5
  params: { query: {
6
6
  projectId,
7
7
  class: resolved.apiTarget.class,
8
- key
8
+ key,
9
+ ...resolved.apiTarget.branchId !== null ? { branchId: resolved.apiTarget.branchId } : {}
9
10
  } },
10
11
  signal
11
12
  });
@@ -1,4 +1,4 @@
1
- import { CliError } from "../shell/errors.js";
1
+ import { CliError } from "../errors.js";
2
2
  import { formatScopeLabel } from "../lib/app/env-config.js";
3
3
  import { apiCallError, findVariableByNaturalKey, toMetadata } from "./app-env-api.js";
4
4
  //#region src/controllers/app-env-file.ts
@@ -1,9 +1,9 @@
1
- import { CliError, authRequiredError, usageError, workspaceRequiredError } from "../shell/errors.js";
1
+ import { CliError, authRequiredError, usageError, workspaceRequiredError } from "../errors.js";
2
+ import { authenticatedManagementApiClient } from "../auth/guard.js";
2
3
  import { formatScopeLabel, parseKeyValuePositional, resolveEnvScope } from "../lib/app/env-config.js";
3
4
  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
5
  import { readLocalGitBranch } from "../lib/git/local-branch.js";
6
+ import { projectResolutionErrorToCliError, resolveProjectTarget } from "../lib/project/resolution.js";
7
7
  import { requireAuthenticatedAuthState } from "./auth.js";
8
8
  import { listRealWorkspaceProjects } from "./project.js";
9
9
  import { apiCallError, findVariableByNaturalKey, toMetadata } from "./app-env-api.js";
@@ -202,7 +202,7 @@ async function runEnvRemove(context, key, flags) {
202
202
  }
203
203
  async function requireClientAndProject(context, explicitProject, commandName) {
204
204
  const authState = await requireAuthenticatedAuthState(context);
205
- const client = await requireComputeAuth(context.runtime.env, context.runtime.signal);
205
+ const client = await authenticatedManagementApiClient(context.runtime.env, context.runtime.signal);
206
206
  if (!client) throw authRequiredError(["prisma-cli auth login"]);
207
207
  const workspace = authState.workspace;
208
208
  if (!workspace) throw workspaceRequiredError();
@@ -210,7 +210,7 @@ async function requireClientAndProject(context, explicitProject, commandName) {
210
210
  context,
211
211
  workspace,
212
212
  explicitProject,
213
- listProjects: () => listRealWorkspaceProjects(client, workspace, context.runtime.signal),
213
+ listProjects: () => listRealWorkspaceProjects(client, context.runtime.signal),
214
214
  commandName
215
215
  });
216
216
  if (targetResult.isErr()) throw projectResolutionErrorToCliError(targetResult.error);