neon 4.7.0 → 4.9.0

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 (58) hide show
  1. package/README.md +49 -59
  2. package/dist/_chunks/{auth_selection-ktL6uoEe.js → auth_selection-pitMFzDe.js} +1 -1
  3. package/dist/_chunks/{credential_io-B1JxWELN.js → credential_io-YeAxg9Xn.js} +2 -2
  4. package/dist/_chunks/{paths-g3DRqJiD.js → paths-DMq0Lt7a.js} +1 -1
  5. package/dist/_chunks/{profiles-D95AeZ5v.js → profiles-CvnFEQyd.js} +1 -1
  6. package/dist/analytics.js +2 -2
  7. package/dist/auth_context.js +1 -1
  8. package/dist/commands/auth.js +12 -9
  9. package/dist/commands/bootstrap.js +72 -43
  10. package/dist/commands/branches.js +29 -14
  11. package/dist/commands/claim.js +1 -1
  12. package/dist/commands/init.js +80 -79
  13. package/dist/commands/link.js +78 -63
  14. package/dist/commands/mcp.js +1 -1
  15. package/dist/commands/plugins.js +4 -4
  16. package/dist/commands/profile.js +4 -4
  17. package/dist/commands/projects.js +17 -6
  18. package/dist/commands/skills.js +1 -1
  19. package/dist/config.js +1 -1
  20. package/dist/credential_io.js +1 -1
  21. package/dist/index.js +1 -1
  22. package/dist/init/child.js +36 -0
  23. package/dist/init/plan.js +47 -0
  24. package/dist/init/tooling.js +43 -0
  25. package/dist/init/wizard.js +42 -0
  26. package/dist/mcp/targets.js +1 -1
  27. package/dist/plugins/plan.js +1 -1
  28. package/dist/plugins/targets.js +5 -1
  29. package/dist/retire_credential.js +1 -1
  30. package/dist/utils/middlewares.js +1 -1
  31. package/dist/utils/package_manager.js +10 -5
  32. package/package.json +15 -16
  33. package/dist/init/auth.js +0 -53
  34. package/dist/init/build_config.js +0 -4
  35. package/dist/init/detect_agent.js +0 -63
  36. package/dist/init/editors.js +0 -19
  37. package/dist/init/enrich_output.js +0 -61
  38. package/dist/init/extension.js +0 -154
  39. package/dist/init/inspect.js +0 -249
  40. package/dist/init/interactive.js +0 -529
  41. package/dist/init/neonctl.js +0 -139
  42. package/dist/init/orchestrate.js +0 -189
  43. package/dist/init/phases/auth.js +0 -195
  44. package/dist/init/phases/cleanup.js +0 -27
  45. package/dist/init/phases/db.js +0 -257
  46. package/dist/init/phases/getting_started.js +0 -218
  47. package/dist/init/phases/mcp.js +0 -219
  48. package/dist/init/phases/migrations.js +0 -250
  49. package/dist/init/phases/neon_auth.js +0 -116
  50. package/dist/init/phases/setup.js +0 -582
  51. package/dist/init/phases/skills.js +0 -86
  52. package/dist/init/phases/status.js +0 -82
  53. package/dist/init/profile_cli.js +0 -56
  54. package/dist/init/resolve_context.js +0 -105
  55. package/dist/init/route_command.js +0 -93
  56. package/dist/init/skills.js +0 -206
  57. package/dist/init/types.js +0 -1
  58. package/dist/init/vsix.js +0 -89
@@ -1,189 +0,0 @@
1
- import { tryResolveAddMcpAgentId } from "../mcp/agents.js";
2
- import { supportsSkills } from "./agents.js";
3
- import { isAuthenticated } from "./auth.js";
4
- import { inspectProject } from "./inspect.js";
5
- import { getSkillList, missingSkillsForAgent, skillsInstalledForAgent } from "./skills.js";
6
- import { handleAuthPhase } from "./phases/auth.js";
7
- import { handleGettingStartedPhase } from "./phases/getting_started.js";
8
- import { handleMigrationsPhase } from "./phases/migrations.js";
9
- import { handleNeonAuthPhase } from "./phases/neon_auth.js";
10
- import { handleSetupPhase } from "./phases/setup.js";
11
- import { resolveNeonContext } from "./resolve_context.js";
12
- import { existsSync, readFileSync, writeFileSync } from "node:fs";
13
- import { resolve } from "node:path";
14
- //#region src/init/orchestrate.ts
15
- /**
16
- * v2 orchestrator: checks phases in order and returns the first that needs attention.
17
- *
18
- * Phase order:
19
- * auth -> setup (if tooling not installed)
20
- * -> getting-started (if tooling installed but no Neon connection string)
21
- * -> resolve .neon context (if connection string exists but no .neon file)
22
- * -> neon_auth (optional) -> complete
23
- *
24
- * Each call is stateless — it re-checks everything from the file system and credentials.
25
- *
26
- * The orchestrator uses filesystem inspection to decide what to do:
27
- * - No app detected → bootstrap phase (scaffold from template)
28
- * - MCP not configured → full setup flow (inspect → install → getting-started)
29
- * - MCP configured, no connection string → skip install, go to getting-started
30
- * - MCP configured + connection string → fall through to neon-auth/migrations/complete
31
- */
32
- async function orchestrate(options) {
33
- if (!await isAuthenticated()) return handleAuthPhase({ agent: options.agent });
34
- const cwd = process.cwd();
35
- const inspection = await inspectProject([
36
- {
37
- id: "has_app",
38
- description: "",
39
- lookFor: []
40
- },
41
- {
42
- id: "mcp_server",
43
- description: "",
44
- lookFor: []
45
- },
46
- {
47
- id: "skills",
48
- description: "",
49
- lookFor: []
50
- },
51
- {
52
- id: "connection_string",
53
- description: "",
54
- lookFor: []
55
- },
56
- {
57
- id: "project_stack",
58
- description: "",
59
- lookFor: []
60
- },
61
- {
62
- id: "migrations",
63
- description: "",
64
- lookFor: []
65
- }
66
- ]);
67
- const hasApp = options.preview ? inspection.hasApp === true : true;
68
- const requestedAgent = options.agent ? tryResolveAddMcpAgentId(options.agent) : void 0;
69
- let skillsInstalled = inspection.skillsInstalled;
70
- if (options.preview && requestedAgent && supportsSkills(requestedAgent)) {
71
- const missing = missingSkillsForAgent(requestedAgent, {
72
- cwd,
73
- preview: true
74
- });
75
- const required = getSkillList(true);
76
- if (missing.length > 0) {
77
- skillsInstalled = false;
78
- if (missing.length < required.length) inspection.skillsScope = `${inspection.skillsScope && !String(inspection.skillsScope).includes("partial") ? inspection.skillsScope : "project"}-partial`;
79
- }
80
- } else if (options.preview && skillsInstalled && inspection.skillsScope) {
81
- const previewSkills = getSkillList(true);
82
- const { existsSync: exists } = await import("node:fs");
83
- const { resolve: resolvePath } = await import("node:path");
84
- const home = process.env.HOME || process.env.USERPROFILE || "";
85
- const dirs = inspection.skillsScope === "project" ? [
86
- resolvePath(cwd, ".cursor", "skills"),
87
- resolvePath(cwd, ".claude", "skills"),
88
- resolvePath(cwd, ".agents", "skills")
89
- ] : [
90
- resolvePath(home, ".cursor", "skills"),
91
- resolvePath(home, ".claude", "skills"),
92
- resolvePath(home, ".agents", "skills")
93
- ];
94
- if (!previewSkills.every((skill) => dirs.some((dir) => exists(resolvePath(dir, skill, "SKILL.md"))))) {
95
- skillsInstalled = false;
96
- inspection.skillsScope = `${inspection.skillsScope}-partial`;
97
- }
98
- }
99
- const mcpForThisAgent = requestedAgent ? (inspection.mcpAgents ?? []).some((hit) => hit.agent === requestedAgent) : inspection.mcpConfigured === true;
100
- const skillsReady = requestedAgent && !supportsSkills(requestedAgent) ? true : requestedAgent ? skillsInstalledForAgent(requestedAgent, cwd, options.preview) : skillsInstalled === true;
101
- const toolingInstalled = mcpForThisAgent && skillsReady;
102
- const hasNeonConnection = inspection.connectionString === true;
103
- if (!hasApp || !toolingInstalled) {
104
- cleanupInitState(resolve(cwd, ".neon"));
105
- return handleSetupPhase({
106
- agent: options.agent,
107
- preview: options.preview,
108
- hasApp,
109
- mcpConfigured: requestedAgent ? mcpForThisAgent : inspection.mcpConfigured ?? null,
110
- mcpScope: inspection.mcpScope || void 0,
111
- skillsInstalled: requestedAgent ? skillsReady : skillsInstalled ?? null,
112
- skillsScope: inspection.skillsScope || void 0
113
- });
114
- }
115
- const neonContextPath = resolve(cwd, ".neon");
116
- const neonContext = readNeonContext(neonContextPath);
117
- const initState = typeof neonContext._init === "object" && neonContext._init !== null ? neonContext._init : {};
118
- const features = Array.isArray(initState.features) ? initState.features : [];
119
- if (!hasNeonConnection) return handleGettingStartedPhase({
120
- agent: options.agent,
121
- cwd,
122
- hasConnectionString: false,
123
- framework: inspection.framework,
124
- orm: inspection.orm,
125
- migrationTool: inspection.migrationTool,
126
- migrationDir: inspection.migrationDir,
127
- features,
128
- preview: options.preview
129
- });
130
- if (!neonContext.projectId) try {
131
- const resolved = await resolveNeonContext(cwd);
132
- if (resolved) {
133
- const merged = { ...neonContext };
134
- if (resolved.orgId) merged.orgId = resolved.orgId;
135
- if (resolved.projectId) merged.projectId = resolved.projectId;
136
- writeFileSync(neonContextPath, `${JSON.stringify(merged, null, 2)}\n`);
137
- }
138
- } catch {}
139
- if (features.includes("auth")) {
140
- if (!checkNeonAuth(cwd)) return handleNeonAuthPhase({
141
- agent: options.agent,
142
- setup: true
143
- });
144
- }
145
- if (!options.skipMigrations) return handleMigrationsPhase({
146
- agent: options.agent,
147
- cwd
148
- });
149
- cleanupInitState(neonContextPath);
150
- return {
151
- phase: "setup",
152
- status: "complete",
153
- nextAction: {
154
- type: "complete",
155
- message: requestedAgent && !supportsSkills(requestedAgent) ? "Neon setup is complete. Your database is configured and your agent has the Neon MCP server available." : "Neon setup is complete. Your database is configured and your agent has the Neon MCP server and skills available."
156
- }
157
- };
158
- }
159
- /** Remove the ephemeral _init key from .neon, preserving other fields. */
160
- function cleanupInitState(neonContextPath) {
161
- if (!existsSync(neonContextPath)) return;
162
- try {
163
- const context = JSON.parse(readFileSync(neonContextPath, "utf-8"));
164
- if (context._init !== void 0) {
165
- delete context._init;
166
- writeFileSync(neonContextPath, `${JSON.stringify(context, null, 2)}\n`);
167
- }
168
- } catch {}
169
- }
170
- function readNeonContext(neonContextPath) {
171
- if (!existsSync(neonContextPath)) return {};
172
- try {
173
- return JSON.parse(readFileSync(neonContextPath, "utf-8"));
174
- } catch {
175
- return {};
176
- }
177
- }
178
- function checkNeonAuth(cwd) {
179
- const envPath = resolve(cwd, ".env");
180
- if (!existsSync(envPath)) return false;
181
- try {
182
- const content = readFileSync(envPath, "utf-8");
183
- return /^NEON_AUTH_/m.test(content);
184
- } catch {
185
- return false;
186
- }
187
- }
188
- //#endregion
189
- export { orchestrate };
@@ -1,195 +0,0 @@
1
- import { isAuthenticated } from "../auth.js";
2
- import { neonctlCmd } from "../neonctl.js";
3
- //#region src/init/phases/auth.ts
4
- function getSignupUrl() {
5
- return process.env.NEON_API_HOST ? `${new URL(process.env.NEON_API_HOST).origin}/signup` : "https://console.neon.tech/signup";
6
- }
7
- function getSignupCommands() {
8
- const url = getSignupUrl();
9
- return {
10
- darwin: `open ${url}`,
11
- linux: `xdg-open ${url}`,
12
- win32: `start ${url}`
13
- };
14
- }
15
- async function handleAuthPhase(options) {
16
- const agentArgs = options.agent ? [
17
- "--agent",
18
- options.agent,
19
- "--json"
20
- ] : ["--json"];
21
- if (options.verify) {
22
- if (await isAuthenticated()) return {
23
- phase: "auth",
24
- status: "verified",
25
- nextAction: {
26
- type: "run_neon_init",
27
- args: agentArgs
28
- }
29
- };
30
- return {
31
- phase: "auth",
32
- status: "not_authenticated",
33
- nextAction: {
34
- type: "run_neon_init",
35
- args: ["auth", "--json"]
36
- }
37
- };
38
- }
39
- if (await isAuthenticated()) return {
40
- phase: "auth",
41
- status: "verified",
42
- nextAction: {
43
- type: "run_neon_init",
44
- args: agentArgs
45
- }
46
- };
47
- if (options.method === "new") return {
48
- phase: "auth",
49
- status: "in_progress",
50
- nextAction: {
51
- type: "agent_action",
52
- steps: [{
53
- id: "open_signup",
54
- description: "Open the Neon sign-up page in the user's browser",
55
- command: getSignupCommands()[process.platform] ?? getSignupCommands().linux
56
- }, {
57
- id: "wait_for_signup",
58
- description: "Tell the user: 'I've opened the Neon sign-up page. Create your account and verify your email, then let me know when you're ready.'"
59
- }],
60
- onComplete: {
61
- type: "run_neon_init",
62
- args: [
63
- "auth",
64
- "--json",
65
- "--method",
66
- "existing"
67
- ]
68
- }
69
- }
70
- };
71
- if (options.method === "existing") return {
72
- phase: "auth",
73
- status: "in_progress",
74
- nextAction: {
75
- type: "run_command",
76
- command: `${neonctlCmd()} auth`,
77
- description: "This will open your browser for Neon OAuth sign-in.",
78
- timeout: 12e4,
79
- onSuccess: {
80
- type: "run_neon_init",
81
- args: [
82
- "auth",
83
- "--json",
84
- "--verify"
85
- ]
86
- },
87
- onFailure: {
88
- "2": {
89
- type: "ask_user",
90
- question: "The sign-in timed out. Did you complete the sign-in in your browser?",
91
- options: ["yes_retry", "need_help"],
92
- responseMapping: {
93
- yes_retry: { args: [
94
- "auth",
95
- "--json",
96
- "--method",
97
- "existing"
98
- ] },
99
- need_help: { args: [
100
- "auth",
101
- "--json",
102
- "--method",
103
- "new"
104
- ] }
105
- }
106
- },
107
- other: {
108
- type: "run_neon_init",
109
- args: ["auth", "--json"]
110
- }
111
- }
112
- }
113
- };
114
- const openCmd = getSignupCommands()[process.platform] ?? getSignupCommands().linux;
115
- return {
116
- phase: "auth",
117
- status: "required",
118
- nextAction: {
119
- type: "ask_user",
120
- instructions: "IMPORTANT: You MUST present this question to the user and WAIT for their response before proceeding. Do NOT assume the answer or auto-select an option. The user's answer determines the next step.",
121
- question: "Do you have an existing Neon account, or do you need to create one?",
122
- options: [{
123
- value: "existing_account",
124
- label: "I have an existing Neon account"
125
- }, {
126
- value: "new_account",
127
- label: "I need to create a new account"
128
- }],
129
- context: "Neon is a complete set of cloud backend primitives built around Lakebase Postgres. A free account is required to continue.",
130
- responseMapping: {
131
- existing_account: { action: {
132
- type: "run_command",
133
- command: `${neonctlCmd()} auth`,
134
- description: "This will open your browser for Neon OAuth sign-in.",
135
- timeout: 12e4,
136
- onSuccess: {
137
- type: "run_neon_init",
138
- args: [
139
- "auth",
140
- "--json",
141
- "--verify"
142
- ]
143
- },
144
- onFailure: {
145
- "2": {
146
- type: "ask_user",
147
- question: "The sign-in timed out. Did you complete the sign-in in your browser?",
148
- options: ["yes_retry", "need_help"],
149
- responseMapping: {
150
- yes_retry: { args: [
151
- "auth",
152
- "--json",
153
- "--method",
154
- "existing"
155
- ] },
156
- need_help: { args: [
157
- "auth",
158
- "--json",
159
- "--method",
160
- "new"
161
- ] }
162
- }
163
- },
164
- other: {
165
- type: "run_neon_init",
166
- args: ["auth", "--json"]
167
- }
168
- }
169
- } },
170
- new_account: { action: {
171
- type: "agent_action",
172
- steps: [{
173
- id: "open_signup",
174
- description: "Open the Neon sign-up page in the user's browser",
175
- command: openCmd
176
- }, {
177
- id: "wait_for_signup",
178
- description: "Tell the user: 'I've opened the Neon sign-up page. Create your account and verify your email, then let me know when you're ready.'"
179
- }],
180
- onComplete: {
181
- type: "run_neon_init",
182
- args: [
183
- "auth",
184
- "--json",
185
- "--method",
186
- "existing"
187
- ]
188
- }
189
- } }
190
- }
191
- }
192
- };
193
- }
194
- //#endregion
195
- export { handleAuthPhase };
@@ -1,27 +0,0 @@
1
- import { existsSync, readFileSync, writeFileSync } from "node:fs";
2
- import { resolve } from "node:path";
3
- //#region src/init/phases/cleanup.ts
4
- /**
5
- * Terminal phase: cleans up ephemeral _init state from .neon and
6
- * returns a complete message. All feature chains should end here.
7
- */
8
- function handleCleanup() {
9
- const neonContextPath = resolve(process.cwd(), ".neon");
10
- if (existsSync(neonContextPath)) try {
11
- const context = JSON.parse(readFileSync(neonContextPath, "utf-8"));
12
- if (context._init !== void 0) {
13
- delete context._init;
14
- writeFileSync(neonContextPath, `${JSON.stringify(context, null, 2)}\n`);
15
- }
16
- } catch {}
17
- return {
18
- phase: "setup",
19
- status: "complete",
20
- nextAction: {
21
- type: "complete",
22
- message: "Neon setup is complete! Your database is connected and your agent has the Neon MCP server and skills available."
23
- }
24
- };
25
- }
26
- //#endregion
27
- export { handleCleanup };
@@ -1,257 +0,0 @@
1
- import { neonctlCmd } from "../neonctl.js";
2
- import { SKILL_REFERENCE_URLS } from "../skills.js";
3
- //#region src/init/phases/db.ts
4
- /**
5
- * Validates that an ID contains only safe characters for shell interpolation.
6
- * Neon org/project IDs are typically UUIDs or slug-like strings.
7
- */
8
- function assertSafeId(value, label) {
9
- if (!/^[\w.:-]+$/.test(value)) throw new Error(`Invalid ${label}: "${value}". Expected alphanumeric, hyphens, underscores, dots, or colons.`);
10
- }
11
- async function handleDbPhase(options) {
12
- const agentArgs = options.agent ? [
13
- "--agent",
14
- options.agent,
15
- "--json"
16
- ] : ["--json"];
17
- if (options.projectId) assertSafeId(options.projectId, "project ID");
18
- if (options.orgId) assertSafeId(options.orgId, "org ID");
19
- if (options.error) return {
20
- phase: "db",
21
- status: "error",
22
- error: options.error,
23
- nextAction: {
24
- type: "ask_user",
25
- question: `An error occurred during database setup: ${options.error}. Would you like to try again or skip this step?`,
26
- options: [{
27
- value: "retry",
28
- label: "Try again"
29
- }, {
30
- value: "skip",
31
- label: "Skip database setup"
32
- }],
33
- responseMapping: {
34
- retry: { args: ["db", "--json"] },
35
- skip: { args: agentArgs }
36
- }
37
- }
38
- };
39
- if (options.projectId) return {
40
- phase: "db",
41
- status: "project_ready",
42
- project: { id: options.projectId },
43
- nextAction: {
44
- type: "agent_action",
45
- prerequisite: SKILL_REFERENCE_URLS.connectionMethods,
46
- steps: [
47
- {
48
- id: "get_connection_string",
49
- description: "Get the database connection string",
50
- command: `${neonctlCmd()} connection-string --project-id ${options.projectId}`
51
- },
52
- {
53
- id: "store_env",
54
- description: "Append DATABASE_URL=<connection_string> to .env. Create .env if it doesn't exist. Do NOT overwrite existing entries. Ensure .env is in .gitignore."
55
- },
56
- {
57
- id: "detect_framework",
58
- description: "Examine the project to determine the framework (Next.js, Remix, Express, etc.) and ORM (Prisma, Drizzle, raw SQL) in use."
59
- }
60
- ],
61
- onComplete: {
62
- type: "run_neon_init",
63
- args: agentArgs
64
- }
65
- }
66
- };
67
- if (options.projectsResult) {
68
- let projects;
69
- try {
70
- const parsed = JSON.parse(options.projectsResult);
71
- projects = Array.isArray(parsed.projects) ? parsed.projects : Array.isArray(parsed) ? parsed : [];
72
- } catch {
73
- projects = [];
74
- }
75
- const orgIdArgs = options.orgId ? ["--org-id", options.orgId] : [];
76
- if (projects.length === 0) return {
77
- phase: "db",
78
- status: "no_projects",
79
- nextAction: {
80
- type: "ask_user",
81
- question: "You don't have any Neon projects yet. What would you like to name your new project?",
82
- options: [{
83
- value: "create",
84
- label: "Create a new project (provide a name)"
85
- }],
86
- context: `The agent should ask the user for a project name, then run: ${neonctlCmd()} projects create --name <name> --output json` + (options.orgId ? ` --org-id ${options.orgId}` : "") + " and pass the result back.",
87
- responseMapping: { create: { args: [
88
- "db",
89
- "--json",
90
- ...orgIdArgs,
91
- "--project-id",
92
- "<created-project-id>"
93
- ] } }
94
- }
95
- };
96
- const projectOptions = projects.map((p) => ({
97
- value: p.id,
98
- label: `${p.name} (${p.id})`
99
- }));
100
- projectOptions.push({
101
- value: "create_new",
102
- label: "Create a new project"
103
- });
104
- const responseMapping = {};
105
- for (const p of projects) responseMapping[p.id] = { args: [
106
- "db",
107
- "--json",
108
- ...orgIdArgs,
109
- "--project-id",
110
- p.id
111
- ] };
112
- responseMapping.create_new = { args: [
113
- "db",
114
- "--json",
115
- ...orgIdArgs,
116
- "--project-id",
117
- "<created-project-id>"
118
- ] };
119
- return {
120
- phase: "db",
121
- status: "select_project",
122
- nextAction: {
123
- type: "ask_user",
124
- question: "Which Neon project would you like to use?",
125
- options: projectOptions,
126
- context: `If the user wants to create a new project, ask for a name then run: ${neonctlCmd()} projects create --name <name> --output json and use the returned project id.`,
127
- responseMapping
128
- }
129
- };
130
- }
131
- if (options.orgsResult) {
132
- let orgs;
133
- try {
134
- const parsed = JSON.parse(options.orgsResult);
135
- orgs = Array.isArray(parsed.organizations) ? parsed.organizations : Array.isArray(parsed) ? parsed : [];
136
- } catch {
137
- orgs = [];
138
- }
139
- const orgId = options.orgId ?? (orgs.length === 1 ? orgs[0].id : null);
140
- if (orgId) {
141
- assertSafeId(orgId, "org ID");
142
- return {
143
- phase: "db",
144
- status: "org_selected",
145
- org: { id: orgId },
146
- nextAction: {
147
- type: "run_command",
148
- command: `${neonctlCmd()} projects list --org-id ${orgId} --output json`,
149
- description: "Listing Neon projects.",
150
- timeout: 3e4,
151
- onSuccess: {
152
- type: "run_neon_init",
153
- args: [
154
- "db",
155
- "--json",
156
- "--org-id",
157
- orgId,
158
- "--projects-result",
159
- "<stdout>"
160
- ]
161
- },
162
- onFailure: { other: {
163
- type: "run_neon_init",
164
- args: [
165
- "db",
166
- "--json",
167
- "--error",
168
- "projects-list-failed"
169
- ]
170
- } }
171
- }
172
- };
173
- }
174
- const orgOptions = orgs.map((o) => ({
175
- value: o.id,
176
- label: `${o.name} (${o.id})`
177
- }));
178
- const responseMapping = {};
179
- for (const o of orgs) responseMapping[o.id] = { args: [
180
- "db",
181
- "--json",
182
- "--org-id",
183
- o.id
184
- ] };
185
- return {
186
- phase: "db",
187
- status: "select_org",
188
- nextAction: {
189
- type: "ask_user",
190
- question: "Which Neon organization would you like to use?",
191
- options: orgOptions,
192
- responseMapping
193
- }
194
- };
195
- }
196
- if (options.orgId) return {
197
- phase: "db",
198
- status: "org_selected",
199
- org: { id: options.orgId },
200
- nextAction: {
201
- type: "run_command",
202
- command: `${neonctlCmd()} projects list --org-id ${options.orgId} --output json`,
203
- description: "Listing Neon projects.",
204
- timeout: 3e4,
205
- onSuccess: {
206
- type: "run_neon_init",
207
- args: [
208
- "db",
209
- "--json",
210
- "--org-id",
211
- options.orgId,
212
- "--projects-result",
213
- "<stdout>"
214
- ]
215
- },
216
- onFailure: { other: {
217
- type: "run_neon_init",
218
- args: [
219
- "db",
220
- "--json",
221
- "--error",
222
- "projects-list-failed"
223
- ]
224
- } }
225
- }
226
- };
227
- return {
228
- phase: "db",
229
- status: "ready",
230
- nextAction: {
231
- type: "run_command",
232
- command: `${neonctlCmd()} orgs list --output json`,
233
- description: "Listing your Neon organizations.",
234
- timeout: 3e4,
235
- onSuccess: {
236
- type: "run_neon_init",
237
- args: [
238
- "db",
239
- "--json",
240
- "--orgs-result",
241
- "<stdout>"
242
- ]
243
- },
244
- onFailure: { other: {
245
- type: "run_neon_init",
246
- args: [
247
- "db",
248
- "--json",
249
- "--error",
250
- "orgs-list-failed"
251
- ]
252
- } }
253
- }
254
- };
255
- }
256
- //#endregion
257
- export { handleDbPhase };