neon-init 0.20.0 → 0.20.2
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.
- package/README.md +1 -1
- package/dist/cli.js +2 -2
- package/dist/cli.js.map +1 -1
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/dist/interactive.js +8 -8
- package/dist/interactive.js.map +1 -1
- package/dist/lib/auth.js +2 -2
- package/dist/lib/auth.js.map +1 -1
- package/dist/lib/enrich-output.d.ts +1 -1
- package/dist/lib/enrich-output.js +4 -4
- package/dist/lib/enrich-output.js.map +1 -1
- package/dist/lib/neonctl.d.ts +5 -3
- package/dist/lib/neonctl.d.ts.map +1 -1
- package/dist/lib/neonctl.js +6 -4
- package/dist/lib/neonctl.js.map +1 -1
- package/dist/lib/phases/getting-started.d.ts +1 -1
- package/dist/lib/phases/getting-started.js +5 -5
- package/dist/lib/phases/getting-started.js.map +1 -1
- package/dist/lib/phases/neon-auth.js +1 -1
- package/dist/lib/phases/neon-auth.js.map +1 -1
- package/dist/lib/phases/setup.js +6 -6
- package/dist/lib/phases/setup.js.map +1 -1
- package/dist/lib/phases/status.js +4 -4
- package/dist/lib/phases/status.js.map +1 -1
- package/dist/lib/skills.js +2 -1
- package/dist/lib/skills.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -53,7 +53,7 @@ Then:
|
|
|
53
53
|
|
|
54
54
|
The tool automatically detects which editors are installed on your system and you'll be prompted to choose which one(s) to configure.
|
|
55
55
|
|
|
56
|
-
**Authentication:** Uses OAuth via `
|
|
56
|
+
**Authentication:** Uses OAuth via the Neon CLI (`neon`) and creates an API key for you - opens your browser, no manual API keys needed.
|
|
57
57
|
|
|
58
58
|
**Agent Guidelines:** The Neon MCP Server includes built-in agent guidelines as an MCP resource. Your AI assistant will automatically have access to:
|
|
59
59
|
|
package/dist/cli.js
CHANGED
|
@@ -325,10 +325,10 @@ yargs(hideBin(process.argv)).scriptName("neon-init").usage("$0 [command] [option
|
|
|
325
325
|
description: "Pre-select a Neon project."
|
|
326
326
|
}).option("orgs-result", {
|
|
327
327
|
type: "string",
|
|
328
|
-
description: "JSON output from
|
|
328
|
+
description: "JSON output from neon orgs list (agent passes back)."
|
|
329
329
|
}).option("projects-result", {
|
|
330
330
|
type: "string",
|
|
331
|
-
description: "JSON output from
|
|
331
|
+
description: "JSON output from neon projects list (agent passes back)."
|
|
332
332
|
}).option("framework", {
|
|
333
333
|
type: "string",
|
|
334
334
|
description: "Framework detected by agent."
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","names":[],"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport yargs from \"yargs\";\nimport { hideBin } from \"yargs/helpers\";\nimport { interactiveInit } from \"./interactive.js\";\nimport { detectAgent } from \"./lib/detect-agent.js\";\nimport { handleAuthPhase } from \"./lib/phases/auth.js\";\nimport { handleDbPhase } from \"./lib/phases/db.js\";\nimport { handleGettingStartedPhase } from \"./lib/phases/getting-started.js\";\nimport { handleMcpPhase } from \"./lib/phases/mcp.js\";\nimport { handleMigrationsPhase } from \"./lib/phases/migrations.js\";\nimport { handleNeonAuthPhase } from \"./lib/phases/neon-auth.js\";\nimport { handleSetupPhase } from \"./lib/phases/setup.js\";\nimport { handleSkillsPhase } from \"./lib/phases/skills.js\";\nimport { handleStatusPhase } from \"./lib/phases/status.js\";\nimport { orchestrate } from \"./v2.js\";\n\n// ---------------------------------------------------------------------------\n// Shared options\n// ---------------------------------------------------------------------------\n\nconst jsonOption = {\n\tjson: {\n\t\ttype: \"boolean\" as const,\n\t\tdefault: false,\n\t\tdescription:\n\t\t\t\"Output structured JSON for agent consumption. Suppresses interactive UI.\",\n\t},\n};\n\nconst agentOption = {\n\tagent: {\n\t\talias: \"a\",\n\t\ttype: \"boolean\" as const,\n\t\tdefault: false,\n\t\tdescription: \"Enable agent/JSON mode (agent type is auto-detected).\",\n\t},\n};\n\n// ---------------------------------------------------------------------------\n// Output helper\n// ---------------------------------------------------------------------------\n\nimport { enrichResponse } from \"./lib/enrich-output.js\";\n\nfunction outputJson(data: unknown): void {\n\tconsole.log(JSON.stringify(enrichResponse(data), null, 2));\n}\n\n/**\n * Resolve the agent ID from the environment.\n */\nfunction resolveAgent(): string | undefined {\n\treturn detectAgent() ?? undefined;\n}\n\n/**\n * Detects if an AI agent is invoking the CLI programmatically.\n *\n * Agent-specific env vars (CLAUDECODE, CODEX, CLINE) are unambiguous.\n * For IDE-based agents (Cursor, VS Code, Windsurf), we require non-TTY\n * stdin to distinguish \"agent spawned this\" from \"human typed this in\n * the IDE's integrated terminal\".\n */\nfunction detectAgentInvocation(): string | null {\n\tconst env = process.env;\n\n\t// Agent-specific env vars (always definitive, regardless of TTY)\n\tif (\n\t\tenv.CLAUDECODE === \"1\" ||\n\t\tenv.CLAUDE_CODE === \"1\" ||\n\t\tenv.CLAUDE_CLI === \"1\"\n\t)\n\t\treturn \"claude-code\";\n\tif (env.CODEX === \"1\") return \"codex\";\n\tif (env.CLINE === \"1\") return \"cline\";\n\n\t// IDE detected + non-interactive stdin = agent spawned us\n\t// (a human typing in the same terminal would have isTTY=true)\n\tif (!process.stdin.isTTY) {\n\t\treturn detectAgent();\n\t}\n\n\treturn null;\n}\n\n// ---------------------------------------------------------------------------\n// CLI definition\n// ---------------------------------------------------------------------------\n\nconst cli = yargs(hideBin(process.argv))\n\t.scriptName(\"neon-init\")\n\t.usage(\"$0 [command] [options]\")\n\n\t// -----------------------------------------------------------------------\n\t// Default command: orchestrator (v2 json) or v1 interactive\n\t// -----------------------------------------------------------------------\n\t.command(\n\t\t\"$0\",\n\t\t\"Initialize Neon for your project\",\n\t\t(y) =>\n\t\t\ty\n\t\t\t\t.options(jsonOption)\n\t\t\t\t.options(agentOption)\n\t\t\t\t.option(\"data\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t'JSON object with a \"step\" field to route to a specific phase (auth, db, setup, getting-started, mcp, skills, migrations, neon-auth, status, finalize) and phase-specific options.',\n\t\t\t\t})\n\t\t\t\t.option(\"skip-migrations\", {\n\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\tdefault: false,\n\t\t\t\t\tdescription: \"Skip the migrations phase.\",\n\t\t\t\t})\n\t\t\t\t.option(\"preview\", {\n\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\tdefault: false,\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Enable preview features (e.g. project bootstrapping from templates).\",\n\t\t\t\t}),\n\t\tasync (argv) => {\n\t\t\tconst detectedAgent = detectAgentInvocation();\n\t\t\tconst agent = resolveAgent();\n\t\t\tconst jsonMode = argv.json || argv.agent || detectedAgent !== null;\n\n\t\t\t// --data with a \"step\" field routes to the appropriate phase\n\t\t\tif (argv.data && jsonMode) {\n\t\t\t\tconst { routeDataStep } = await import(\n\t\t\t\t\t\"./lib/route-command.js\"\n\t\t\t\t);\n\t\t\t\tlet data: Record<string, unknown>;\n\t\t\t\ttry {\n\t\t\t\t\tdata = JSON.parse(argv.data);\n\t\t\t\t} catch {\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t\"Invalid JSON in --data flag. Expected a JSON object.\",\n\t\t\t\t\t);\n\t\t\t\t\tprocess.exit(1);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (typeof data.step === \"string\") {\n\t\t\t\t\tconst result = await routeDataStep(data, agent);\n\t\t\t\t\toutputJson(result);\n\t\t\t\t\tprocess.exit(0);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// --data with a \"step\" field routes to the appropriate phase\n\t\t\tif (argv.data && jsonMode) {\n\t\t\t\tconst { routeDataStep } = await import(\n\t\t\t\t\t\"./lib/route-command.js\"\n\t\t\t\t);\n\t\t\t\tlet data: Record<string, unknown>;\n\t\t\t\ttry {\n\t\t\t\t\tdata = JSON.parse(argv.data);\n\t\t\t\t} catch {\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t\"Invalid JSON in --data flag. Expected a JSON object.\",\n\t\t\t\t\t);\n\t\t\t\t\tprocess.exit(1);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (typeof data.step === \"string\") {\n\t\t\t\t\tconst result = await routeDataStep(data, agent);\n\t\t\t\t\toutputJson(result);\n\t\t\t\t\tprocess.exit(0);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (jsonMode) {\n\t\t\t\t// v2: agent-driven state machine\n\t\t\t\tconst result = await orchestrate({\n\t\t\t\t\tagent,\n\t\t\t\t\tskipMigrations: argv.skipMigrations,\n\t\t\t\t\tpreview: argv.preview,\n\t\t\t\t});\n\t\t\t\toutputJson(result);\n\t\t\t\tprocess.exit(0);\n\t\t\t}\n\n\t\t\t// v2 interactive mode — same phase logic, driven by terminal prompts\n\t\t\tawait interactiveInit({ preview: argv.preview });\n\t\t\tprocess.exit(0);\n\t\t},\n\t)\n\n\t// -----------------------------------------------------------------------\n\t// auth\n\t// -----------------------------------------------------------------------\n\t.command(\n\t\t\"auth\",\n\t\t\"Manage Neon platform authentication\",\n\t\t(y) =>\n\t\t\ty\n\t\t\t\t.options(jsonOption)\n\t\t\t\t.options(agentOption)\n\t\t\t\t.option(\"method\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tchoices: [\"existing\", \"new\"] as const,\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t'Auth method: \"existing\" for OAuth sign-in, \"new\" for sign-up flow.',\n\t\t\t\t})\n\t\t\t\t.option(\"verify\", {\n\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\tdefault: false,\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Just check if authentication is valid, don't initiate a flow.\",\n\t\t\t\t}),\n\t\tasync (argv) => {\n\t\t\tconst result = await handleAuthPhase({\n\t\t\t\tagent: resolveAgent(),\n\t\t\t\tmethod: argv.method as \"existing\" | \"new\" | undefined,\n\t\t\t\tverify: argv.verify,\n\t\t\t});\n\t\t\toutputJson(result);\n\t\t\tprocess.exit(0);\n\t\t},\n\t)\n\n\t// -----------------------------------------------------------------------\n\t// mcp\n\t// -----------------------------------------------------------------------\n\t.command(\n\t\t\"mcp\",\n\t\t\"Manage the Neon MCP server\",\n\t\t(y) =>\n\t\t\ty\n\t\t\t\t.options(jsonOption)\n\t\t\t\t.options(agentOption)\n\t\t\t\t.option(\"status\", {\n\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\tdefault: false,\n\t\t\t\t\tdescription: \"Check if the MCP server is configured.\",\n\t\t\t\t})\n\t\t\t\t.option(\"install\", {\n\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\tdefault: false,\n\t\t\t\t\tdescription: \"Install or update the MCP server.\",\n\t\t\t\t})\n\t\t\t\t.option(\"update\", {\n\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\tdefault: false,\n\t\t\t\t\tdescription: \"Alias for --install.\",\n\t\t\t\t})\n\t\t\t\t.option(\"scope\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tchoices: [\"global\", \"project\"] as const,\n\t\t\t\t\tdefault: \"global\",\n\t\t\t\t\tdescription: \"Where to configure the MCP server.\",\n\t\t\t\t})\n\t\t\t\t.option(\"mcp-configured\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Agent reports MCP detection result (true|false).\",\n\t\t\t\t}),\n\t\tasync (argv) => {\n\t\t\tlet mcpConfigured: boolean | null = null;\n\t\t\tif (argv.mcpConfigured === \"true\") mcpConfigured = true;\n\t\t\telse if (argv.mcpConfigured === \"false\") mcpConfigured = false;\n\n\t\t\tconst result = await handleMcpPhase({\n\t\t\t\tagent: resolveAgent(),\n\t\t\t\tstatus: argv.status,\n\t\t\t\tinstall: argv.install || argv.update,\n\t\t\t\tscope: argv.scope as \"global\" | \"project\",\n\t\t\t\tmcpConfigured,\n\t\t\t});\n\t\t\toutputJson(result);\n\t\t\tprocess.exit(0);\n\t\t},\n\t)\n\n\t// -----------------------------------------------------------------------\n\t// skills\n\t// -----------------------------------------------------------------------\n\t.command(\n\t\t\"skills\",\n\t\t\"Manage Neon agent skills\",\n\t\t(y) =>\n\t\t\ty\n\t\t\t\t.options(jsonOption)\n\t\t\t\t.options(agentOption)\n\t\t\t\t.option(\"status\", {\n\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\tdefault: false,\n\t\t\t\t\tdescription: \"Check if skills are installed.\",\n\t\t\t\t})\n\t\t\t\t.option(\"install\", {\n\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\tdefault: false,\n\t\t\t\t\tdescription: \"Install agent skills.\",\n\t\t\t\t})\n\t\t\t\t.option(\"update\", {\n\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\tdefault: false,\n\t\t\t\t\tdescription: \"Update agent skills to latest.\",\n\t\t\t\t}),\n\t\tasync (argv) => {\n\t\t\tconst result = await handleSkillsPhase({\n\t\t\t\tagent: resolveAgent(),\n\t\t\t\tstatus: argv.status,\n\t\t\t\tinstall: argv.install,\n\t\t\t\tupdate: argv.update,\n\t\t\t});\n\t\t\toutputJson(result);\n\t\t\tprocess.exit(0);\n\t\t},\n\t)\n\n\t// -----------------------------------------------------------------------\n\t// setup (comprehensive inspection + batched install)\n\t// -----------------------------------------------------------------------\n\t.command(\n\t\t\"setup\",\n\t\t\"Inspect project and batch-install Neon tooling (MCP, skills, extension)\",\n\t\t(y) =>\n\t\t\ty\n\t\t\t\t.options(jsonOption)\n\t\t\t\t.options(agentOption)\n\t\t\t\t.option(\"data\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"JSON object with inspection results and user preferences (replaces individual flags).\",\n\t\t\t\t})\n\t\t\t\t.option(\"mcp-configured\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Agent reports MCP detection result (true|false).\",\n\t\t\t\t})\n\t\t\t\t.option(\"connection-string\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Agent reports if a connection string was found (true|false).\",\n\t\t\t\t})\n\t\t\t\t.option(\"connection-params\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"JSON with connection parameters found by agent.\",\n\t\t\t\t})\n\t\t\t\t.option(\"framework\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription: \"Framework detected by agent.\",\n\t\t\t\t})\n\t\t\t\t.option(\"orm\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription: \"ORM detected by agent.\",\n\t\t\t\t})\n\t\t\t\t.option(\"migration-tool\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Migration tool detected by agent (prisma|drizzle|knex|none).\",\n\t\t\t\t})\n\t\t\t\t.option(\"migration-dir\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription: \"Migration directory detected by agent.\",\n\t\t\t\t})\n\t\t\t\t.option(\"is-vscode-ide\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Agent reports if user is in a VS Code-based IDE (true|false).\",\n\t\t\t\t})\n\t\t\t\t.option(\"mode\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tchoices: [\"defaults\", \"customize\"] as const,\n\t\t\t\t\tdescription: \"Installation mode chosen by user.\",\n\t\t\t\t})\n\t\t\t\t.option(\"mcp-scope\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tchoices: [\"global\", \"project\"] as const,\n\t\t\t\t\tdescription: \"Where to install MCP server.\",\n\t\t\t\t})\n\t\t\t\t.option(\"skills-scope\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tchoices: [\"global\", \"project\"] as const,\n\t\t\t\t\tdescription: \"Where to install skills.\",\n\t\t\t\t})\n\t\t\t\t.option(\"install-extension\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Whether to install VS Code extension (true|false).\",\n\t\t\t\t})\n\t\t\t\t.option(\"execute\", {\n\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\tdefault: false,\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Execute the batched installation with given options.\",\n\t\t\t\t}),\n\t\tasync (argv) => {\n\t\t\t// --data JSON path: parse and pass directly to handleSetupPhase\n\t\t\tif (argv.data) {\n\t\t\t\tlet data: Record<string, unknown>;\n\t\t\t\ttry {\n\t\t\t\t\tdata = JSON.parse(argv.data);\n\t\t\t\t} catch {\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t\"Invalid JSON in --data flag. Expected a JSON object.\",\n\t\t\t\t\t);\n\t\t\t\t\tprocess.exit(1);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Normalize string booleans from preference answers (e.g. \"true\" → true)\n\t\t\t\tfor (const key of [\n\t\t\t\t\t\"mcpConfigured\",\n\t\t\t\t\t\"connectionString\",\n\t\t\t\t\t\"isVscodeIde\",\n\t\t\t\t\t\"installExtension\",\n\t\t\t\t\t\"execute\",\n\t\t\t\t]) {\n\t\t\t\t\tif (data[key] === \"true\") data[key] = true;\n\t\t\t\t\telse if (data[key] === \"false\") data[key] = false;\n\t\t\t\t}\n\n\t\t\t\tconst result = await handleSetupPhase({\n\t\t\t\t\tagent: resolveAgent(),\n\t\t\t\t\t...data,\n\t\t\t\t} as import(\"./lib/phases/setup.js\").SetupPhaseOptions);\n\t\t\t\toutputJson(result);\n\t\t\t\tprocess.exit(0);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Legacy individual flags path\n\t\t\tlet mcpConfigured: boolean | null = null;\n\t\t\tif (argv.mcpConfigured === \"true\") mcpConfigured = true;\n\t\t\telse if (argv.mcpConfigured === \"false\") mcpConfigured = false;\n\n\t\t\tlet connectionString: boolean | null = null;\n\t\t\tif (argv.connectionString === \"true\") connectionString = true;\n\t\t\telse if (argv.connectionString === \"false\")\n\t\t\t\tconnectionString = false;\n\n\t\t\tlet isVscodeIde: boolean | null = null;\n\t\t\tif (argv.isVscodeIde === \"true\") isVscodeIde = true;\n\t\t\telse if (argv.isVscodeIde === \"false\") isVscodeIde = false;\n\n\t\t\tconst result = await handleSetupPhase({\n\t\t\t\tagent: resolveAgent(),\n\t\t\t\tmcpConfigured,\n\t\t\t\tconnectionString,\n\t\t\t\tconnectionParams: argv.connectionParams,\n\t\t\t\tframework: argv.framework,\n\t\t\t\torm: argv.orm,\n\t\t\t\tmigrationTool: argv.migrationTool,\n\t\t\t\tmigrationDir: argv.migrationDir,\n\t\t\t\tisVscodeIde,\n\t\t\t\tmode: argv.mode as \"defaults\" | \"customize\" | undefined,\n\t\t\t\tmcpScope: argv.mcpScope as \"global\" | \"project\" | undefined,\n\t\t\t\tskillsScope: argv.skillsScope as\n\t\t\t\t\t| \"global\"\n\t\t\t\t\t| \"project\"\n\t\t\t\t\t| undefined,\n\t\t\t\tinstallExtension: argv.installExtension === \"true\",\n\t\t\t\texecute: argv.execute,\n\t\t\t});\n\t\t\toutputJson(result);\n\t\t\tprocess.exit(0);\n\t\t},\n\t)\n\n\t// -----------------------------------------------------------------------\n\t// getting-started\n\t// -----------------------------------------------------------------------\n\t.command(\n\t\t\"getting-started\",\n\t\t\"Start the Get Started with Neon workflow\",\n\t\t(y) =>\n\t\t\ty\n\t\t\t\t.options(jsonOption)\n\t\t\t\t.options(agentOption)\n\t\t\t\t.option(\"data\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"JSON object with project context (hasConnectionString, framework, orm, migrationTool, migrationDir).\",\n\t\t\t\t})\n\t\t\t\t.option(\"has-connection-string\", {\n\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\tdefault: false,\n\t\t\t\t\tdescription: \"Whether a connection string was found.\",\n\t\t\t\t})\n\t\t\t\t.option(\"framework\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription: \"Framework detected by agent.\",\n\t\t\t\t})\n\t\t\t\t.option(\"orm\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription: \"ORM detected by agent.\",\n\t\t\t\t})\n\t\t\t\t.option(\"migration-tool\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription: \"Migration tool in use.\",\n\t\t\t\t})\n\t\t\t\t.option(\"migration-dir\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription: \"Migration directory path.\",\n\t\t\t\t}),\n\t\tasync (argv) => {\n\t\t\tif (argv.data) {\n\t\t\t\tlet data: Record<string, unknown>;\n\t\t\t\ttry {\n\t\t\t\t\tdata = JSON.parse(argv.data);\n\t\t\t\t} catch {\n\t\t\t\t\tconsole.error(\"Invalid JSON in --data flag.\");\n\t\t\t\t\tprocess.exit(1);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst result = await handleGettingStartedPhase({\n\t\t\t\t\tagent: resolveAgent(),\n\t\t\t\t\t...data,\n\t\t\t\t} as import(\"./lib/phases/getting-started.js\").GettingStartedPhaseOptions);\n\t\t\t\toutputJson(result);\n\t\t\t\tprocess.exit(0);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst result = await handleGettingStartedPhase({\n\t\t\t\tagent: resolveAgent(),\n\t\t\t\thasConnectionString: argv.hasConnectionString,\n\t\t\t\tframework: argv.framework,\n\t\t\t\torm: argv.orm,\n\t\t\t\tmigrationTool: argv.migrationTool,\n\t\t\t\tmigrationDir: argv.migrationDir,\n\t\t\t});\n\t\t\toutputJson(result);\n\t\t\tprocess.exit(0);\n\t\t},\n\t)\n\n\t// -----------------------------------------------------------------------\n\t// db\n\t// -----------------------------------------------------------------------\n\t.command(\n\t\t\"db\",\n\t\t\"Set up a Neon database project\",\n\t\t(y) =>\n\t\t\ty\n\t\t\t\t.options(jsonOption)\n\t\t\t\t.options(agentOption)\n\t\t\t\t.option(\"org-id\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription: \"Pre-select a Neon organization.\",\n\t\t\t\t})\n\t\t\t\t.option(\"project-id\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription: \"Pre-select a Neon project.\",\n\t\t\t\t})\n\t\t\t\t.option(\"orgs-result\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"JSON output from neonctl orgs list (agent passes back).\",\n\t\t\t\t})\n\t\t\t\t.option(\"projects-result\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"JSON output from neonctl projects list (agent passes back).\",\n\t\t\t\t})\n\t\t\t\t.option(\"framework\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription: \"Framework detected by agent.\",\n\t\t\t\t})\n\t\t\t\t.option(\"orm\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription: \"ORM detected by agent.\",\n\t\t\t\t})\n\t\t\t\t.option(\"error\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription: \"Error from a previous step.\",\n\t\t\t\t}),\n\t\tasync (argv) => {\n\t\t\tconst result = await handleDbPhase({\n\t\t\t\tagent: resolveAgent(),\n\t\t\t\torgId: argv.orgId,\n\t\t\t\tprojectId: argv.projectId,\n\t\t\t\torgsResult: argv.orgsResult,\n\t\t\t\tprojectsResult: argv.projectsResult,\n\t\t\t\tframework: argv.framework,\n\t\t\t\torm: argv.orm,\n\t\t\t\terror: argv.error,\n\t\t\t});\n\t\t\toutputJson(result);\n\t\t\tprocess.exit(0);\n\t\t},\n\t)\n\n\t// -----------------------------------------------------------------------\n\t// neon-auth\n\t// -----------------------------------------------------------------------\n\t.command(\n\t\t\"neon-auth\",\n\t\t\"Set up Neon Auth (user authentication for your app)\",\n\t\t(y) =>\n\t\t\ty\n\t\t\t\t.options(jsonOption)\n\t\t\t\t.options(agentOption)\n\t\t\t\t.option(\"setup\", {\n\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\tdefault: false,\n\t\t\t\t\tdescription: \"Begin the Neon Auth setup flow.\",\n\t\t\t\t})\n\t\t\t\t.option(\"info\", {\n\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\tdefault: false,\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Return information about Neon Auth without setting it up.\",\n\t\t\t\t})\n\t\t\t\t.option(\"project-id\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription: \"Neon project ID to configure.\",\n\t\t\t\t}),\n\t\tasync (argv) => {\n\t\t\tconst result = await handleNeonAuthPhase({\n\t\t\t\tagent: resolveAgent(),\n\t\t\t\tsetup: argv.setup,\n\t\t\t\tinfo: argv.info,\n\t\t\t\tprojectId: argv.projectId,\n\t\t\t});\n\t\t\toutputJson(result);\n\t\t\tprocess.exit(0);\n\t\t},\n\t)\n\n\t// -----------------------------------------------------------------------\n\t// migrations\n\t// -----------------------------------------------------------------------\n\t.command(\n\t\t\"migrations\",\n\t\t\"Detect and manage database migrations\",\n\t\t(y) =>\n\t\t\ty\n\t\t\t\t.options(jsonOption)\n\t\t\t\t.options(agentOption)\n\t\t\t\t.option(\"tool\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Migration tool detected by agent (prisma|drizzle|knex|none).\",\n\t\t\t\t})\n\t\t\t\t.option(\"migration-dir\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription: \"Migration directory detected by agent.\",\n\t\t\t\t})\n\t\t\t\t.option(\"scaffold\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tchoices: [\"prisma\", \"drizzle\"] as const,\n\t\t\t\t\tdescription: \"Scaffold a new migration setup.\",\n\t\t\t\t})\n\t\t\t\t.option(\"apply\", {\n\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\tdefault: false,\n\t\t\t\t\tdescription: \"Apply pending migrations.\",\n\t\t\t\t}),\n\t\tasync (argv) => {\n\t\t\tconst result = await handleMigrationsPhase({\n\t\t\t\tagent: resolveAgent(),\n\t\t\t\ttool: argv.tool,\n\t\t\t\tmigrationDir: argv.migrationDir,\n\t\t\t\tscaffold: argv.scaffold as \"prisma\" | \"drizzle\" | undefined,\n\t\t\t\tapply: argv.apply,\n\t\t\t});\n\t\t\toutputJson(result);\n\t\t\tprocess.exit(0);\n\t\t},\n\t)\n\n\t// -----------------------------------------------------------------------\n\t// finalize (internal — called at the end of feature chains)\n\t// -----------------------------------------------------------------------\n\t.command(\n\t\t\"finalize\",\n\t\tfalse, // hidden from help\n\t\t(y) => y.options(jsonOption).options(agentOption),\n\t\tasync () => {\n\t\t\tconst { handleCleanup } = await import(\"./lib/phases/cleanup.js\");\n\t\t\tconst result = handleCleanup();\n\t\t\toutputJson(result);\n\t\t\tprocess.exit(0);\n\t\t},\n\t)\n\n\t// -----------------------------------------------------------------------\n\t// status\n\t// -----------------------------------------------------------------------\n\t.command(\n\t\t\"status\",\n\t\t\"Check the status of your Neon setup\",\n\t\t(y) => y.options(jsonOption).options(agentOption),\n\t\tasync (_argv) => {\n\t\t\tconst result = await handleStatusPhase({\n\t\t\t\tagent: resolveAgent(),\n\t\t\t});\n\t\t\toutputJson(result);\n\t\t\tprocess.exit(0);\n\t\t},\n\t)\n\n\t.help()\n\t.strict();\n\n// Parse and execute\ncli.parse();\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cli.js","names":[],"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport yargs from \"yargs\";\nimport { hideBin } from \"yargs/helpers\";\nimport { interactiveInit } from \"./interactive.js\";\nimport { detectAgent } from \"./lib/detect-agent.js\";\nimport { handleAuthPhase } from \"./lib/phases/auth.js\";\nimport { handleDbPhase } from \"./lib/phases/db.js\";\nimport { handleGettingStartedPhase } from \"./lib/phases/getting-started.js\";\nimport { handleMcpPhase } from \"./lib/phases/mcp.js\";\nimport { handleMigrationsPhase } from \"./lib/phases/migrations.js\";\nimport { handleNeonAuthPhase } from \"./lib/phases/neon-auth.js\";\nimport { handleSetupPhase } from \"./lib/phases/setup.js\";\nimport { handleSkillsPhase } from \"./lib/phases/skills.js\";\nimport { handleStatusPhase } from \"./lib/phases/status.js\";\nimport { orchestrate } from \"./v2.js\";\n\n// ---------------------------------------------------------------------------\n// Shared options\n// ---------------------------------------------------------------------------\n\nconst jsonOption = {\n\tjson: {\n\t\ttype: \"boolean\" as const,\n\t\tdefault: false,\n\t\tdescription:\n\t\t\t\"Output structured JSON for agent consumption. Suppresses interactive UI.\",\n\t},\n};\n\nconst agentOption = {\n\tagent: {\n\t\talias: \"a\",\n\t\ttype: \"boolean\" as const,\n\t\tdefault: false,\n\t\tdescription: \"Enable agent/JSON mode (agent type is auto-detected).\",\n\t},\n};\n\n// ---------------------------------------------------------------------------\n// Output helper\n// ---------------------------------------------------------------------------\n\nimport { enrichResponse } from \"./lib/enrich-output.js\";\n\nfunction outputJson(data: unknown): void {\n\tconsole.log(JSON.stringify(enrichResponse(data), null, 2));\n}\n\n/**\n * Resolve the agent ID from the environment.\n */\nfunction resolveAgent(): string | undefined {\n\treturn detectAgent() ?? undefined;\n}\n\n/**\n * Detects if an AI agent is invoking the CLI programmatically.\n *\n * Agent-specific env vars (CLAUDECODE, CODEX, CLINE) are unambiguous.\n * For IDE-based agents (Cursor, VS Code, Windsurf), we require non-TTY\n * stdin to distinguish \"agent spawned this\" from \"human typed this in\n * the IDE's integrated terminal\".\n */\nfunction detectAgentInvocation(): string | null {\n\tconst env = process.env;\n\n\t// Agent-specific env vars (always definitive, regardless of TTY)\n\tif (\n\t\tenv.CLAUDECODE === \"1\" ||\n\t\tenv.CLAUDE_CODE === \"1\" ||\n\t\tenv.CLAUDE_CLI === \"1\"\n\t)\n\t\treturn \"claude-code\";\n\tif (env.CODEX === \"1\") return \"codex\";\n\tif (env.CLINE === \"1\") return \"cline\";\n\n\t// IDE detected + non-interactive stdin = agent spawned us\n\t// (a human typing in the same terminal would have isTTY=true)\n\tif (!process.stdin.isTTY) {\n\t\treturn detectAgent();\n\t}\n\n\treturn null;\n}\n\n// ---------------------------------------------------------------------------\n// CLI definition\n// ---------------------------------------------------------------------------\n\nconst cli = yargs(hideBin(process.argv))\n\t.scriptName(\"neon-init\")\n\t.usage(\"$0 [command] [options]\")\n\n\t// -----------------------------------------------------------------------\n\t// Default command: orchestrator (v2 json) or v1 interactive\n\t// -----------------------------------------------------------------------\n\t.command(\n\t\t\"$0\",\n\t\t\"Initialize Neon for your project\",\n\t\t(y) =>\n\t\t\ty\n\t\t\t\t.options(jsonOption)\n\t\t\t\t.options(agentOption)\n\t\t\t\t.option(\"data\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t'JSON object with a \"step\" field to route to a specific phase (auth, db, setup, getting-started, mcp, skills, migrations, neon-auth, status, finalize) and phase-specific options.',\n\t\t\t\t})\n\t\t\t\t.option(\"skip-migrations\", {\n\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\tdefault: false,\n\t\t\t\t\tdescription: \"Skip the migrations phase.\",\n\t\t\t\t})\n\t\t\t\t.option(\"preview\", {\n\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\tdefault: false,\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Enable preview features (e.g. project bootstrapping from templates).\",\n\t\t\t\t}),\n\t\tasync (argv) => {\n\t\t\tconst detectedAgent = detectAgentInvocation();\n\t\t\tconst agent = resolveAgent();\n\t\t\tconst jsonMode = argv.json || argv.agent || detectedAgent !== null;\n\n\t\t\t// --data with a \"step\" field routes to the appropriate phase\n\t\t\tif (argv.data && jsonMode) {\n\t\t\t\tconst { routeDataStep } = await import(\n\t\t\t\t\t\"./lib/route-command.js\"\n\t\t\t\t);\n\t\t\t\tlet data: Record<string, unknown>;\n\t\t\t\ttry {\n\t\t\t\t\tdata = JSON.parse(argv.data);\n\t\t\t\t} catch {\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t\"Invalid JSON in --data flag. Expected a JSON object.\",\n\t\t\t\t\t);\n\t\t\t\t\tprocess.exit(1);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (typeof data.step === \"string\") {\n\t\t\t\t\tconst result = await routeDataStep(data, agent);\n\t\t\t\t\toutputJson(result);\n\t\t\t\t\tprocess.exit(0);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// --data with a \"step\" field routes to the appropriate phase\n\t\t\tif (argv.data && jsonMode) {\n\t\t\t\tconst { routeDataStep } = await import(\n\t\t\t\t\t\"./lib/route-command.js\"\n\t\t\t\t);\n\t\t\t\tlet data: Record<string, unknown>;\n\t\t\t\ttry {\n\t\t\t\t\tdata = JSON.parse(argv.data);\n\t\t\t\t} catch {\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t\"Invalid JSON in --data flag. Expected a JSON object.\",\n\t\t\t\t\t);\n\t\t\t\t\tprocess.exit(1);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (typeof data.step === \"string\") {\n\t\t\t\t\tconst result = await routeDataStep(data, agent);\n\t\t\t\t\toutputJson(result);\n\t\t\t\t\tprocess.exit(0);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (jsonMode) {\n\t\t\t\t// v2: agent-driven state machine\n\t\t\t\tconst result = await orchestrate({\n\t\t\t\t\tagent,\n\t\t\t\t\tskipMigrations: argv.skipMigrations,\n\t\t\t\t\tpreview: argv.preview,\n\t\t\t\t});\n\t\t\t\toutputJson(result);\n\t\t\t\tprocess.exit(0);\n\t\t\t}\n\n\t\t\t// v2 interactive mode — same phase logic, driven by terminal prompts\n\t\t\tawait interactiveInit({ preview: argv.preview });\n\t\t\tprocess.exit(0);\n\t\t},\n\t)\n\n\t// -----------------------------------------------------------------------\n\t// auth\n\t// -----------------------------------------------------------------------\n\t.command(\n\t\t\"auth\",\n\t\t\"Manage Neon platform authentication\",\n\t\t(y) =>\n\t\t\ty\n\t\t\t\t.options(jsonOption)\n\t\t\t\t.options(agentOption)\n\t\t\t\t.option(\"method\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tchoices: [\"existing\", \"new\"] as const,\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t'Auth method: \"existing\" for OAuth sign-in, \"new\" for sign-up flow.',\n\t\t\t\t})\n\t\t\t\t.option(\"verify\", {\n\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\tdefault: false,\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Just check if authentication is valid, don't initiate a flow.\",\n\t\t\t\t}),\n\t\tasync (argv) => {\n\t\t\tconst result = await handleAuthPhase({\n\t\t\t\tagent: resolveAgent(),\n\t\t\t\tmethod: argv.method as \"existing\" | \"new\" | undefined,\n\t\t\t\tverify: argv.verify,\n\t\t\t});\n\t\t\toutputJson(result);\n\t\t\tprocess.exit(0);\n\t\t},\n\t)\n\n\t// -----------------------------------------------------------------------\n\t// mcp\n\t// -----------------------------------------------------------------------\n\t.command(\n\t\t\"mcp\",\n\t\t\"Manage the Neon MCP server\",\n\t\t(y) =>\n\t\t\ty\n\t\t\t\t.options(jsonOption)\n\t\t\t\t.options(agentOption)\n\t\t\t\t.option(\"status\", {\n\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\tdefault: false,\n\t\t\t\t\tdescription: \"Check if the MCP server is configured.\",\n\t\t\t\t})\n\t\t\t\t.option(\"install\", {\n\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\tdefault: false,\n\t\t\t\t\tdescription: \"Install or update the MCP server.\",\n\t\t\t\t})\n\t\t\t\t.option(\"update\", {\n\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\tdefault: false,\n\t\t\t\t\tdescription: \"Alias for --install.\",\n\t\t\t\t})\n\t\t\t\t.option(\"scope\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tchoices: [\"global\", \"project\"] as const,\n\t\t\t\t\tdefault: \"global\",\n\t\t\t\t\tdescription: \"Where to configure the MCP server.\",\n\t\t\t\t})\n\t\t\t\t.option(\"mcp-configured\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Agent reports MCP detection result (true|false).\",\n\t\t\t\t}),\n\t\tasync (argv) => {\n\t\t\tlet mcpConfigured: boolean | null = null;\n\t\t\tif (argv.mcpConfigured === \"true\") mcpConfigured = true;\n\t\t\telse if (argv.mcpConfigured === \"false\") mcpConfigured = false;\n\n\t\t\tconst result = await handleMcpPhase({\n\t\t\t\tagent: resolveAgent(),\n\t\t\t\tstatus: argv.status,\n\t\t\t\tinstall: argv.install || argv.update,\n\t\t\t\tscope: argv.scope as \"global\" | \"project\",\n\t\t\t\tmcpConfigured,\n\t\t\t});\n\t\t\toutputJson(result);\n\t\t\tprocess.exit(0);\n\t\t},\n\t)\n\n\t// -----------------------------------------------------------------------\n\t// skills\n\t// -----------------------------------------------------------------------\n\t.command(\n\t\t\"skills\",\n\t\t\"Manage Neon agent skills\",\n\t\t(y) =>\n\t\t\ty\n\t\t\t\t.options(jsonOption)\n\t\t\t\t.options(agentOption)\n\t\t\t\t.option(\"status\", {\n\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\tdefault: false,\n\t\t\t\t\tdescription: \"Check if skills are installed.\",\n\t\t\t\t})\n\t\t\t\t.option(\"install\", {\n\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\tdefault: false,\n\t\t\t\t\tdescription: \"Install agent skills.\",\n\t\t\t\t})\n\t\t\t\t.option(\"update\", {\n\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\tdefault: false,\n\t\t\t\t\tdescription: \"Update agent skills to latest.\",\n\t\t\t\t}),\n\t\tasync (argv) => {\n\t\t\tconst result = await handleSkillsPhase({\n\t\t\t\tagent: resolveAgent(),\n\t\t\t\tstatus: argv.status,\n\t\t\t\tinstall: argv.install,\n\t\t\t\tupdate: argv.update,\n\t\t\t});\n\t\t\toutputJson(result);\n\t\t\tprocess.exit(0);\n\t\t},\n\t)\n\n\t// -----------------------------------------------------------------------\n\t// setup (comprehensive inspection + batched install)\n\t// -----------------------------------------------------------------------\n\t.command(\n\t\t\"setup\",\n\t\t\"Inspect project and batch-install Neon tooling (MCP, skills, extension)\",\n\t\t(y) =>\n\t\t\ty\n\t\t\t\t.options(jsonOption)\n\t\t\t\t.options(agentOption)\n\t\t\t\t.option(\"data\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"JSON object with inspection results and user preferences (replaces individual flags).\",\n\t\t\t\t})\n\t\t\t\t.option(\"mcp-configured\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Agent reports MCP detection result (true|false).\",\n\t\t\t\t})\n\t\t\t\t.option(\"connection-string\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Agent reports if a connection string was found (true|false).\",\n\t\t\t\t})\n\t\t\t\t.option(\"connection-params\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"JSON with connection parameters found by agent.\",\n\t\t\t\t})\n\t\t\t\t.option(\"framework\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription: \"Framework detected by agent.\",\n\t\t\t\t})\n\t\t\t\t.option(\"orm\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription: \"ORM detected by agent.\",\n\t\t\t\t})\n\t\t\t\t.option(\"migration-tool\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Migration tool detected by agent (prisma|drizzle|knex|none).\",\n\t\t\t\t})\n\t\t\t\t.option(\"migration-dir\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription: \"Migration directory detected by agent.\",\n\t\t\t\t})\n\t\t\t\t.option(\"is-vscode-ide\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Agent reports if user is in a VS Code-based IDE (true|false).\",\n\t\t\t\t})\n\t\t\t\t.option(\"mode\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tchoices: [\"defaults\", \"customize\"] as const,\n\t\t\t\t\tdescription: \"Installation mode chosen by user.\",\n\t\t\t\t})\n\t\t\t\t.option(\"mcp-scope\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tchoices: [\"global\", \"project\"] as const,\n\t\t\t\t\tdescription: \"Where to install MCP server.\",\n\t\t\t\t})\n\t\t\t\t.option(\"skills-scope\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tchoices: [\"global\", \"project\"] as const,\n\t\t\t\t\tdescription: \"Where to install skills.\",\n\t\t\t\t})\n\t\t\t\t.option(\"install-extension\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Whether to install VS Code extension (true|false).\",\n\t\t\t\t})\n\t\t\t\t.option(\"execute\", {\n\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\tdefault: false,\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Execute the batched installation with given options.\",\n\t\t\t\t}),\n\t\tasync (argv) => {\n\t\t\t// --data JSON path: parse and pass directly to handleSetupPhase\n\t\t\tif (argv.data) {\n\t\t\t\tlet data: Record<string, unknown>;\n\t\t\t\ttry {\n\t\t\t\t\tdata = JSON.parse(argv.data);\n\t\t\t\t} catch {\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t\"Invalid JSON in --data flag. Expected a JSON object.\",\n\t\t\t\t\t);\n\t\t\t\t\tprocess.exit(1);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Normalize string booleans from preference answers (e.g. \"true\" → true)\n\t\t\t\tfor (const key of [\n\t\t\t\t\t\"mcpConfigured\",\n\t\t\t\t\t\"connectionString\",\n\t\t\t\t\t\"isVscodeIde\",\n\t\t\t\t\t\"installExtension\",\n\t\t\t\t\t\"execute\",\n\t\t\t\t]) {\n\t\t\t\t\tif (data[key] === \"true\") data[key] = true;\n\t\t\t\t\telse if (data[key] === \"false\") data[key] = false;\n\t\t\t\t}\n\n\t\t\t\tconst result = await handleSetupPhase({\n\t\t\t\t\tagent: resolveAgent(),\n\t\t\t\t\t...data,\n\t\t\t\t} as import(\"./lib/phases/setup.js\").SetupPhaseOptions);\n\t\t\t\toutputJson(result);\n\t\t\t\tprocess.exit(0);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Legacy individual flags path\n\t\t\tlet mcpConfigured: boolean | null = null;\n\t\t\tif (argv.mcpConfigured === \"true\") mcpConfigured = true;\n\t\t\telse if (argv.mcpConfigured === \"false\") mcpConfigured = false;\n\n\t\t\tlet connectionString: boolean | null = null;\n\t\t\tif (argv.connectionString === \"true\") connectionString = true;\n\t\t\telse if (argv.connectionString === \"false\")\n\t\t\t\tconnectionString = false;\n\n\t\t\tlet isVscodeIde: boolean | null = null;\n\t\t\tif (argv.isVscodeIde === \"true\") isVscodeIde = true;\n\t\t\telse if (argv.isVscodeIde === \"false\") isVscodeIde = false;\n\n\t\t\tconst result = await handleSetupPhase({\n\t\t\t\tagent: resolveAgent(),\n\t\t\t\tmcpConfigured,\n\t\t\t\tconnectionString,\n\t\t\t\tconnectionParams: argv.connectionParams,\n\t\t\t\tframework: argv.framework,\n\t\t\t\torm: argv.orm,\n\t\t\t\tmigrationTool: argv.migrationTool,\n\t\t\t\tmigrationDir: argv.migrationDir,\n\t\t\t\tisVscodeIde,\n\t\t\t\tmode: argv.mode as \"defaults\" | \"customize\" | undefined,\n\t\t\t\tmcpScope: argv.mcpScope as \"global\" | \"project\" | undefined,\n\t\t\t\tskillsScope: argv.skillsScope as\n\t\t\t\t\t| \"global\"\n\t\t\t\t\t| \"project\"\n\t\t\t\t\t| undefined,\n\t\t\t\tinstallExtension: argv.installExtension === \"true\",\n\t\t\t\texecute: argv.execute,\n\t\t\t});\n\t\t\toutputJson(result);\n\t\t\tprocess.exit(0);\n\t\t},\n\t)\n\n\t// -----------------------------------------------------------------------\n\t// getting-started\n\t// -----------------------------------------------------------------------\n\t.command(\n\t\t\"getting-started\",\n\t\t\"Start the Get Started with Neon workflow\",\n\t\t(y) =>\n\t\t\ty\n\t\t\t\t.options(jsonOption)\n\t\t\t\t.options(agentOption)\n\t\t\t\t.option(\"data\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"JSON object with project context (hasConnectionString, framework, orm, migrationTool, migrationDir).\",\n\t\t\t\t})\n\t\t\t\t.option(\"has-connection-string\", {\n\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\tdefault: false,\n\t\t\t\t\tdescription: \"Whether a connection string was found.\",\n\t\t\t\t})\n\t\t\t\t.option(\"framework\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription: \"Framework detected by agent.\",\n\t\t\t\t})\n\t\t\t\t.option(\"orm\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription: \"ORM detected by agent.\",\n\t\t\t\t})\n\t\t\t\t.option(\"migration-tool\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription: \"Migration tool in use.\",\n\t\t\t\t})\n\t\t\t\t.option(\"migration-dir\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription: \"Migration directory path.\",\n\t\t\t\t}),\n\t\tasync (argv) => {\n\t\t\tif (argv.data) {\n\t\t\t\tlet data: Record<string, unknown>;\n\t\t\t\ttry {\n\t\t\t\t\tdata = JSON.parse(argv.data);\n\t\t\t\t} catch {\n\t\t\t\t\tconsole.error(\"Invalid JSON in --data flag.\");\n\t\t\t\t\tprocess.exit(1);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst result = await handleGettingStartedPhase({\n\t\t\t\t\tagent: resolveAgent(),\n\t\t\t\t\t...data,\n\t\t\t\t} as import(\"./lib/phases/getting-started.js\").GettingStartedPhaseOptions);\n\t\t\t\toutputJson(result);\n\t\t\t\tprocess.exit(0);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst result = await handleGettingStartedPhase({\n\t\t\t\tagent: resolveAgent(),\n\t\t\t\thasConnectionString: argv.hasConnectionString,\n\t\t\t\tframework: argv.framework,\n\t\t\t\torm: argv.orm,\n\t\t\t\tmigrationTool: argv.migrationTool,\n\t\t\t\tmigrationDir: argv.migrationDir,\n\t\t\t});\n\t\t\toutputJson(result);\n\t\t\tprocess.exit(0);\n\t\t},\n\t)\n\n\t// -----------------------------------------------------------------------\n\t// db\n\t// -----------------------------------------------------------------------\n\t.command(\n\t\t\"db\",\n\t\t\"Set up a Neon database project\",\n\t\t(y) =>\n\t\t\ty\n\t\t\t\t.options(jsonOption)\n\t\t\t\t.options(agentOption)\n\t\t\t\t.option(\"org-id\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription: \"Pre-select a Neon organization.\",\n\t\t\t\t})\n\t\t\t\t.option(\"project-id\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription: \"Pre-select a Neon project.\",\n\t\t\t\t})\n\t\t\t\t.option(\"orgs-result\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"JSON output from neon orgs list (agent passes back).\",\n\t\t\t\t})\n\t\t\t\t.option(\"projects-result\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"JSON output from neon projects list (agent passes back).\",\n\t\t\t\t})\n\t\t\t\t.option(\"framework\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription: \"Framework detected by agent.\",\n\t\t\t\t})\n\t\t\t\t.option(\"orm\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription: \"ORM detected by agent.\",\n\t\t\t\t})\n\t\t\t\t.option(\"error\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription: \"Error from a previous step.\",\n\t\t\t\t}),\n\t\tasync (argv) => {\n\t\t\tconst result = await handleDbPhase({\n\t\t\t\tagent: resolveAgent(),\n\t\t\t\torgId: argv.orgId,\n\t\t\t\tprojectId: argv.projectId,\n\t\t\t\torgsResult: argv.orgsResult,\n\t\t\t\tprojectsResult: argv.projectsResult,\n\t\t\t\tframework: argv.framework,\n\t\t\t\torm: argv.orm,\n\t\t\t\terror: argv.error,\n\t\t\t});\n\t\t\toutputJson(result);\n\t\t\tprocess.exit(0);\n\t\t},\n\t)\n\n\t// -----------------------------------------------------------------------\n\t// neon-auth\n\t// -----------------------------------------------------------------------\n\t.command(\n\t\t\"neon-auth\",\n\t\t\"Set up Neon Auth (user authentication for your app)\",\n\t\t(y) =>\n\t\t\ty\n\t\t\t\t.options(jsonOption)\n\t\t\t\t.options(agentOption)\n\t\t\t\t.option(\"setup\", {\n\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\tdefault: false,\n\t\t\t\t\tdescription: \"Begin the Neon Auth setup flow.\",\n\t\t\t\t})\n\t\t\t\t.option(\"info\", {\n\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\tdefault: false,\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Return information about Neon Auth without setting it up.\",\n\t\t\t\t})\n\t\t\t\t.option(\"project-id\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription: \"Neon project ID to configure.\",\n\t\t\t\t}),\n\t\tasync (argv) => {\n\t\t\tconst result = await handleNeonAuthPhase({\n\t\t\t\tagent: resolveAgent(),\n\t\t\t\tsetup: argv.setup,\n\t\t\t\tinfo: argv.info,\n\t\t\t\tprojectId: argv.projectId,\n\t\t\t});\n\t\t\toutputJson(result);\n\t\t\tprocess.exit(0);\n\t\t},\n\t)\n\n\t// -----------------------------------------------------------------------\n\t// migrations\n\t// -----------------------------------------------------------------------\n\t.command(\n\t\t\"migrations\",\n\t\t\"Detect and manage database migrations\",\n\t\t(y) =>\n\t\t\ty\n\t\t\t\t.options(jsonOption)\n\t\t\t\t.options(agentOption)\n\t\t\t\t.option(\"tool\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Migration tool detected by agent (prisma|drizzle|knex|none).\",\n\t\t\t\t})\n\t\t\t\t.option(\"migration-dir\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription: \"Migration directory detected by agent.\",\n\t\t\t\t})\n\t\t\t\t.option(\"scaffold\", {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tchoices: [\"prisma\", \"drizzle\"] as const,\n\t\t\t\t\tdescription: \"Scaffold a new migration setup.\",\n\t\t\t\t})\n\t\t\t\t.option(\"apply\", {\n\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\tdefault: false,\n\t\t\t\t\tdescription: \"Apply pending migrations.\",\n\t\t\t\t}),\n\t\tasync (argv) => {\n\t\t\tconst result = await handleMigrationsPhase({\n\t\t\t\tagent: resolveAgent(),\n\t\t\t\ttool: argv.tool,\n\t\t\t\tmigrationDir: argv.migrationDir,\n\t\t\t\tscaffold: argv.scaffold as \"prisma\" | \"drizzle\" | undefined,\n\t\t\t\tapply: argv.apply,\n\t\t\t});\n\t\t\toutputJson(result);\n\t\t\tprocess.exit(0);\n\t\t},\n\t)\n\n\t// -----------------------------------------------------------------------\n\t// finalize (internal — called at the end of feature chains)\n\t// -----------------------------------------------------------------------\n\t.command(\n\t\t\"finalize\",\n\t\tfalse, // hidden from help\n\t\t(y) => y.options(jsonOption).options(agentOption),\n\t\tasync () => {\n\t\t\tconst { handleCleanup } = await import(\"./lib/phases/cleanup.js\");\n\t\t\tconst result = handleCleanup();\n\t\t\toutputJson(result);\n\t\t\tprocess.exit(0);\n\t\t},\n\t)\n\n\t// -----------------------------------------------------------------------\n\t// status\n\t// -----------------------------------------------------------------------\n\t.command(\n\t\t\"status\",\n\t\t\"Check the status of your Neon setup\",\n\t\t(y) => y.options(jsonOption).options(agentOption),\n\t\tasync (_argv) => {\n\t\t\tconst result = await handleStatusPhase({\n\t\t\t\tagent: resolveAgent(),\n\t\t\t});\n\t\t\toutputJson(result);\n\t\t\tprocess.exit(0);\n\t\t},\n\t)\n\n\t.help()\n\t.strict();\n\n// Parse and execute\ncli.parse();\n"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -21,7 +21,7 @@ import { intro, isCancel, log, multiselect, note, outro } from "@clack/prompts";
|
|
|
21
21
|
import { bold, cyan } from "yoctocolors";
|
|
22
22
|
//#region src/index.ts
|
|
23
23
|
function getNeonctlCommands() {
|
|
24
|
-
const base = "npx
|
|
24
|
+
const base = "npx neon";
|
|
25
25
|
return {
|
|
26
26
|
listOrgs: `${base} orgs list --output json`,
|
|
27
27
|
listProjects: `${base} projects list --output json`,
|
|
@@ -35,8 +35,8 @@ function getAuthInstructions() {
|
|
|
35
35
|
return [
|
|
36
36
|
"YOU (the agent) must handle authentication. Do NOT ask the user to run commands themselves.",
|
|
37
37
|
"Do NOT write wrapper scripts (Python, shell, etc.) — use simple shell commands only.",
|
|
38
|
-
"IMPORTANT: Unset the CI environment variable for all
|
|
39
|
-
"otherwise
|
|
38
|
+
"IMPORTANT: Unset the CI environment variable for all neon commands below,",
|
|
39
|
+
"otherwise the Neon CLI will refuse to open the browser.",
|
|
40
40
|
"",
|
|
41
41
|
"Step 1: Ask the user: \"Do you already have a Neon account, or do you need to create one?\"",
|
|
42
42
|
"",
|
|
@@ -63,7 +63,7 @@ function getAuthInstructions() {
|
|
|
63
63
|
"=== AFTER SUCCESSFUL AUTH ===",
|
|
64
64
|
`Step 5: Verify by running: ${cmd} me`,
|
|
65
65
|
" This should print the user's account info and exit with code 0.",
|
|
66
|
-
"Step 6: Re-run
|
|
66
|
+
"Step 6: Re-run neon init with the same --agent and --json flags to complete setup."
|
|
67
67
|
].join("\n");
|
|
68
68
|
}
|
|
69
69
|
function buildAgentInstructions(refs) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import { intro, isCancel, log, multiselect, note, outro } from \"@clack/prompts\";\nimport { bold, cyan } from \"yoctocolors\";\nimport { ALL_CONFIGURABLE_AGENTS } from \"./lib/agents.js\";\nimport { isAuthenticated } from \"./lib/auth.js\";\nimport { detectAvailableEditors } from \"./lib/editors.js\";\nimport { usesExtension } from \"./lib/extension.js\";\nimport { installNeon } from \"./lib/install.js\";\nimport { neonctlCmd } from \"./lib/neonctl.js\";\nimport {\n\tfetchSkillContent,\n\tinstallAgentSkills,\n\tSKILL_REFERENCE_URLS,\n} from \"./lib/skills.js\";\nimport type { Editor, InitResult } from \"./lib/types.js\";\n\nexport type { InteractiveInitOptions } from \"./interactive.js\";\nexport { interactiveInit } from \"./interactive.js\";\nexport { detectAgent } from \"./lib/detect-agent.js\";\nexport { enrichResponse } from \"./lib/enrich-output.js\";\nexport { handleAuthPhase } from \"./lib/phases/auth.js\";\nexport { handleDbPhase } from \"./lib/phases/db.js\";\nexport { handleMcpPhase } from \"./lib/phases/mcp.js\";\nexport { handleMigrationsPhase } from \"./lib/phases/migrations.js\";\nexport { handleNeonAuthPhase } from \"./lib/phases/neon-auth.js\";\nexport { handleSkillsPhase } from \"./lib/phases/skills.js\";\nexport { handleStatusPhase } from \"./lib/phases/status.js\";\nexport { routeDataStep } from \"./lib/route-command.js\";\n// v2 exports\nexport type {\n\tAgentActionAction,\n\tAgentCheck,\n\tAgentCheckAction,\n\tAgentStep,\n\tAskUserAction,\n\tCompleteAction,\n\tInitResult,\n\tNextAction,\n\tPhase,\n\tPhaseResponse,\n\tRestartRequiredAction,\n\tRunCommandAction,\n\tRunNeonInitAction,\n\tStatusResponse,\n} from \"./lib/types.js\";\nexport type { OrchestratorOptions } from \"./v2.js\";\nexport { orchestrate } from \"./v2.js\";\n\nexport interface InitOptions {\n\t/** When set, configures only this agent and skips the editor selection prompt. */\n\tagent?: Editor;\n\t/** When true, suppresses interactive UI and returns structured JSON-friendly output. */\n\tjson?: boolean;\n}\n\nfunction getNeonctlCommands() {\n\tconst base = \"npx neonctl\";\n\treturn {\n\t\tlistOrgs: `${base} orgs list --output json`,\n\t\tlistProjects: `${base} projects list --output json`,\n\t\tcreateProject: `${base} projects create --name <project-name> --output json`,\n\t\tgetConnectionString: `${base} connection-string --project-id <project-id>`,\n\t};\n}\n\nfunction getAuthInstructions(): string {\n\tconst cmd = neonctlCmd();\n\tconst signupUrl = process.env.NEON_API_HOST\n\t\t? `${new URL(process.env.NEON_API_HOST).origin}/signup`\n\t\t: \"https://console.neon.tech/signup\";\n\treturn [\n\t\t\"YOU (the agent) must handle authentication. Do NOT ask the user to run commands themselves.\",\n\t\t\"Do NOT write wrapper scripts (Python, shell, etc.) — use simple shell commands only.\",\n\t\t\"IMPORTANT: Unset the CI environment variable for all neonctl commands below,\",\n\t\t\"otherwise neonctl will refuse to open the browser.\",\n\t\t\"\",\n\t\t'Step 1: Ask the user: \"Do you already have a Neon account, or do you need to create one?\"',\n\t\t\"\",\n\t\t\"=== NEW ACCOUNT (sign up) ===\",\n\t\t\"Step 2a: Open the Neon sign-up page in the user's browser:\",\n\t\t` On macOS: open ${signupUrl}`,\n\t\t` On Linux: xdg-open ${signupUrl}`,\n\t\t\"Step 3a: Tell the user: \\\"I've opened the Neon sign-up page in your browser.\",\n\t\t\" Create your account, then check your email for a verification link and click it.\",\n\t\t' Let me know when you have finished signing up and verifying your email.\"',\n\t\t\"Step 4a: Once the user confirms, run the OAuth login:\",\n\t\t` ${cmd} auth`,\n\t\t\" This opens a second browser tab for OAuth authorization. The user approves access.\",\n\t\t\" If exit code 0: authentication succeeded.\",\n\t\t\" If exit code 2 (timeout): ask the user to confirm they finished sign-up and\",\n\t\t\" email verification, then retry the same command.\",\n\t\t\"\",\n\t\t\"=== EXISTING ACCOUNT (sign in) ===\",\n\t\t`Step 2b: Execute: ${cmd} auth`,\n\t\t\" This opens the OAuth login page directly. Sign-in is fast (60-second timeout).\",\n\t\t\" If exit code 0: authentication succeeded.\",\n\t\t\" If exit code 2 (timeout): ask the user to confirm they completed sign-in, then retry.\",\n\t\t\"\",\n\t\t\"=== AFTER SUCCESSFUL AUTH ===\",\n\t\t`Step 5: Verify by running: ${cmd} me`,\n\t\t\" This should print the user's account info and exit with code 0.\",\n\t\t\"Step 6: Re-run neonctl init with the same --agent and --json flags to complete setup.\",\n\t].join(\"\\n\");\n}\n\nfunction buildAgentInstructions(refs: Record<string, string>): string {\n\treturn [\n\t\t\"IMPORTANT: Follow these steps to set up the Neon project. Do NOT skip steps.\",\n\t\t\"\",\n\t\t\"CRITICAL — SKILL REFERENCES: The URLs in skills.references are authoritative\",\n\t\t\"implementation guides with exact import paths, component patterns, route structures,\",\n\t\t\"and common mistakes to avoid. You MUST fetch and read the relevant skill reference\",\n\t\t\"URL BEFORE writing any code that uses that Neon feature. Do NOT rely on general\",\n\t\t\"documentation pages (e.g. /docs/guides/*) or guess at import paths — the skill\",\n\t\t\"references are more accurate, complete, and agent-optimized.\",\n\t\t\"\",\n\t\t`1. List organizations: ${getNeonctlCommands().listOrgs}`,\n\t\t\" - If one org, use it. If multiple, ask the user which to use.\",\n\t\t`2. List projects: ${getNeonctlCommands().listProjects} (add --org-id <org-id>)`,\n\t\t\" - No projects: ask if they want to create a new one.\",\n\t\t\" - One project: ask if they want to use it or create new.\",\n\t\t\" - Multiple: let the user choose.\",\n\t\t`3. Create project if needed: ${getNeonctlCommands().createProject} (add --org-id <org-id>)`,\n\t\t`4. Get connection string: ${getNeonctlCommands().getConnectionString}`,\n\t\t\"5. Store in .env as DATABASE_URL (append, don't overwrite existing .env).\",\n\t\t\"6. For apps with user login/auth: STOP. Before writing any auth code, fetch and\",\n\t\t` read this skill reference: ${refs.neonAuth ?? \"\"}`,\n\t\t\" It contains the exact packages, imports, component layout, route patterns,\",\n\t\t\" environment variables, and common mistakes. Follow it precisely.\",\n\t\t`7. For connection method/driver, fetch and read: ${refs.connectionMethods ?? \"\"}`,\n\t\t\"8. Refer to skills.gettingStarted for the full setup guide with additional details.\",\n\t\t\"\",\n\t\t\"Do NOT auto-create a project without asking the user first.\",\n\t].join(\"\\n\");\n}\n\n/**\n * Initialize Neon projects with MCP Server\n */\nexport async function init(options?: InitOptions): Promise<InitResult> {\n\tconst jsonMode = options?.json === true;\n\n\tconst makeFailedResult = (auth: boolean): InitResult => ({\n\t\tsuccess: false,\n\t\tauth,\n\t\teditors: [],\n\t\tskills: {\n\t\t\tinstalled: false,\n\t\t\tgettingStarted: null,\n\t\t\treferences: {},\n\t\t},\n\t\tneonctl: {\n\t\t\tauthenticated: auth,\n\t\t\tcommands: { ...getNeonctlCommands() },\n\t\t},\n\t\tmcpServer: {\n\t\t\tconfigured: false,\n\t\t\trequiresRestart: false,\n\t\t},\n\t});\n\n\tif (!jsonMode) {\n\t\tif (options?.agent !== undefined) {\n\t\t\tif (usesExtension(options.agent)) {\n\t\t\t\tintro(\n\t\t\t\t\t`Adding Neon extension (includes MCP server) and agent skills for ${options.agent}`,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tintro(\n\t\t\t\t\t`Adding Neon MCP server and agent skills for ${options.agent}`,\n\t\t\t\t);\n\t\t\t}\n\t\t} else {\n\t\t\tintro(\n\t\t\t\t\"Adding Neon MCP server, extension (for VS Code and Cursor) and agent skills\",\n\t\t\t);\n\t\t}\n\t}\n\n\tconst homeDir = process.env.HOME || process.env.USERPROFILE;\n\tif (!homeDir) {\n\t\tif (!jsonMode) {\n\t\t\tlog.error(\"Could not determine home directory\");\n\t\t\toutro(\"📣 Is this unexpected? Email us at feedback@neon.tech\");\n\t\t}\n\t\treturn makeFailedResult(false);\n\t}\n\n\tlet selectedEditors: Editor[];\n\n\tif (options?.agent !== undefined) {\n\t\tselectedEditors = [options.agent];\n\t} else {\n\t\tif (jsonMode) {\n\t\t\treturn makeFailedResult(false);\n\t\t}\n\n\t\tconst availableEditors = await detectAvailableEditors(homeDir);\n\n\t\tconst response = await multiselect({\n\t\t\tmessage:\n\t\t\t\t\"Which editor(s) would you like to configure? (Space to toggle each option, Enter to confirm your selection)\",\n\t\t\toptions: ALL_CONFIGURABLE_AGENTS.map((agent) => ({\n\t\t\t\tvalue: agent.editor,\n\t\t\t\tlabel: agent.editor,\n\t\t\t\thint: agent.hint,\n\t\t\t})),\n\t\t\tinitialValues: availableEditors,\n\t\t\trequired: true,\n\t\t});\n\n\t\tif (isCancel(response)) {\n\t\t\toutro(\"Installation cancelled\");\n\t\t\treturn makeFailedResult(false);\n\t\t}\n\n\t\tselectedEditors = response as Editor[];\n\t}\n\n\tif (selectedEditors.length === 0) {\n\t\tif (!jsonMode) {\n\t\t\tlog.warn(\"No editors selected.\");\n\t\t\toutro(\"Installation cancelled\");\n\t\t}\n\t\treturn makeFailedResult(false);\n\t}\n\n\t// In JSON mode, check for existing credentials before attempting OAuth.\n\t// neonctl's OAuth has a 60s timeout and email verification breaks the redirect,\n\t// so we let the agent handle auth as a separate step.\n\tif (jsonMode) {\n\t\tconst hasCredentials = await isAuthenticated();\n\t\tif (!hasCredentials) {\n\t\t\tconst { gettingStarted: _gs, ...otherRefs } = SKILL_REFERENCE_URLS;\n\t\t\tconst gettingStartedContent = await fetchSkillContent();\n\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\tauth: false,\n\t\t\t\tauthRequired: true,\n\t\t\t\tauthInstructions: getAuthInstructions(),\n\t\t\t\teditors: [],\n\t\t\t\tskills: {\n\t\t\t\t\tinstalled: false,\n\t\t\t\t\tgettingStarted: gettingStartedContent,\n\t\t\t\t\treferences: otherRefs,\n\t\t\t\t},\n\t\t\t\tneonctl: {\n\t\t\t\t\tauthenticated: false,\n\t\t\t\t\tcommands: { ...getNeonctlCommands() },\n\t\t\t\t},\n\t\t\t\tmcpServer: {\n\t\t\t\t\tconfigured: false,\n\t\t\t\t\trequiresRestart: false,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t}\n\n\tconst { results, authSuccess } = await installNeon(selectedEditors, {\n\t\tjson: jsonMode,\n\t});\n\n\tconst successful: Editor[] = [];\n\tconst failed: Editor[] = [];\n\n\tfor (const [editor, status] of results.entries()) {\n\t\tif (status === \"success\") {\n\t\t\tsuccessful.push(editor);\n\t\t} else {\n\t\t\tfailed.push(editor);\n\t\t}\n\t}\n\n\tlet skillsInstalled = false;\n\tif (successful.length > 0) {\n\t\tskillsInstalled = await installAgentSkills(successful, {\n\t\t\tjson: jsonMode,\n\t\t});\n\t}\n\n\t// Build the editors array for InitResult\n\tconst editorsResult: InitResult[\"editors\"] = [];\n\tfor (const [editor, status] of results.entries()) {\n\t\teditorsResult.push({\n\t\t\teditor,\n\t\t\tstatus,\n\t\t\ttype: usesExtension(editor) ? \"extension\" : \"mcp\",\n\t\t});\n\t}\n\n\tconst mcpConfigured = successful.some((e) => !usesExtension(e));\n\n\tif (jsonMode) {\n\t\tconst { gettingStarted: _gs, ...otherRefs } = SKILL_REFERENCE_URLS;\n\n\t\tconst gettingStartedContent = await fetchSkillContent();\n\n\t\treturn {\n\t\t\tsuccess: successful.length > 0,\n\t\t\tauth: authSuccess,\n\t\t\tagentInstructions: buildAgentInstructions(otherRefs),\n\t\t\teditors: editorsResult,\n\t\t\tskills: {\n\t\t\t\tinstalled: skillsInstalled,\n\t\t\t\tgettingStarted: gettingStartedContent,\n\t\t\t\treferences: otherRefs,\n\t\t\t},\n\t\t\tneonctl: {\n\t\t\t\tauthenticated: authSuccess,\n\t\t\t\tcommands: { ...getNeonctlCommands() },\n\t\t\t},\n\t\t\tmcpServer: {\n\t\t\t\tconfigured: mcpConfigured,\n\t\t\t\trequiresRestart: mcpConfigured,\n\t\t\t},\n\t\t};\n\t}\n\n\t// Interactive UI output (non-json mode)\n\tconst extensionEditors = successful.filter(usesExtension);\n\tconst mcpEditors = successful.filter((e) => !usesExtension(e));\n\tconst failedExtensionEditors = failed.filter(usesExtension);\n\tconst failedMcpEditors = failed.filter((e) => !usesExtension(e));\n\n\tif (extensionEditors.length > 0) {\n\t\tconst extSuccessList = extensionEditors.join(\" / \");\n\t\tlog.step(\n\t\t\t`Neon Local Connect extension installed for ${extSuccessList}.\\n`,\n\t\t);\n\t}\n\n\tif (mcpEditors.length > 0) {\n\t\tconst mcpSuccessList = mcpEditors.join(\" / \");\n\t\tlog.step(\n\t\t\t`Neon MCP Server is now ready to use with ${mcpSuccessList}.\\n`,\n\t\t);\n\t}\n\n\tif (failedExtensionEditors.length > 0) {\n\t\tlog.info(\n\t\t\t\"Failed to install extension. For the best local development experience, install Neon Local Connect manually:\",\n\t\t);\n\t\tfor (const editor of failedExtensionEditors) {\n\t\t\tif (editor === \"VS Code\") {\n\t\t\t\tlog.info(\n\t\t\t\t\t\" • VS Code: https://marketplace.visualstudio.com/items?itemName=databricks.neon-local-connect\",\n\t\t\t\t);\n\t\t\t} else if (editor === \"Cursor\") {\n\t\t\t\tlog.info(\n\t\t\t\t\t\" • Cursor: https://open-vsx.org/extension/databricks/neon-local-connect\",\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (failedMcpEditors.length > 0) {\n\t\tlog.error(\n\t\t\t`Failed to configure MCP Server for ${failedMcpEditors.join(\" / \")}`,\n\t\t);\n\t\tlog.info(\n\t\t\t\"You can manually configure the MCP server by running: npx add-mcp https://mcp.neon.tech/mcp\",\n\t\t);\n\t}\n\n\tif (successful.length === 0) {\n\t\toutro(\n\t\t\t\"Installation cancelled or failed. Please check the output above and try again.\",\n\t\t);\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\tauth: authSuccess,\n\t\t\teditors: editorsResult,\n\t\t\tskills: { installed: false, gettingStarted: null, references: {} },\n\t\t\tneonctl: {\n\t\t\t\tauthenticated: authSuccess,\n\t\t\t\tcommands: { ...getNeonctlCommands() },\n\t\t\t},\n\t\t\tmcpServer: { configured: false, requiresRestart: false },\n\t\t};\n\t}\n\n\tif (extensionEditors.length > 0 && mcpEditors.length === 0) {\n\t\tconst extSuccessList = extensionEditors.join(\" / \");\n\t\tnote(\n\t\t\t`\\x1b[0mRestart ${extSuccessList}, open the Neon extension and type in \"${bold(cyan(\"Get started with Neon\"))}\\x1b[0m\" in your agent chat`,\n\t\t\t\"What's next?\",\n\t\t);\n\t} else if (mcpEditors.length > 0 && extensionEditors.length === 0) {\n\t\tconst mcpSuccessList = mcpEditors.join(\" / \");\n\t\tnote(\n\t\t\t`\\x1b[0mRestart ${mcpSuccessList} and type in \"${bold(cyan(\"Get started with Neon\"))}\\x1b[0m\" in the chat`,\n\t\t\t\"What's next?\",\n\t\t);\n\t} else {\n\t\tnote(\n\t\t\t`\\x1b[0mFor ${extensionEditors.join(\" / \")}: Restart, open the Neon extension and type in \"${bold(cyan(\"Get started with Neon\"))}\\x1b[0m\" in your agent chat\\n\\x1b[0mFor ${mcpEditors.join(\" / \")}: Restart and type in \"${bold(cyan(\"Get started with Neon\"))}\\x1b[0m\" in the chat`,\n\t\t\t\"What's next?\",\n\t\t);\n\t}\n\n\toutro(\"Have feedback? Email us at feedback@neon.tech\");\n\n\treturn {\n\t\tsuccess: true,\n\t\tauth: authSuccess,\n\t\teditors: editorsResult,\n\t\tskills: {\n\t\t\tinstalled: skillsInstalled,\n\t\t\tgettingStarted: null,\n\t\t\treferences: {},\n\t\t},\n\t\tneonctl: {\n\t\t\tauthenticated: authSuccess,\n\t\t\tcommands: { ...getNeonctlCommands() },\n\t\t},\n\t\tmcpServer: {\n\t\t\tconfigured: mcpConfigured,\n\t\t\trequiresRestart: mcpConfigured,\n\t\t},\n\t};\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAsDA,SAAS,qBAAqB;CAC7B,MAAM,OAAO;CACb,OAAO;EACN,UAAU,GAAG,KAAK;EAClB,cAAc,GAAG,KAAK;EACtB,eAAe,GAAG,KAAK;EACvB,qBAAqB,GAAG,KAAK;CAC9B;AACD;AAEA,SAAS,sBAA8B;CACtC,MAAM,MAAM,WAAW;CACvB,MAAM,YAAY,QAAQ,IAAI,gBAC3B,GAAG,IAAI,IAAI,QAAQ,IAAI,aAAa,CAAC,CAAC,OAAO,WAC7C;CACH,OAAO;EACN;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,qBAAqB;EACrB,yBAAyB;EACzB;EACA;EACA;EACA;EACA,MAAM,IAAI;EACV;EACA;EACA;EACA;EACA;EACA;EACA,qBAAqB,IAAI;EACzB;EACA;EACA;EACA;EACA;EACA,8BAA8B,IAAI;EAClC;EACA;CACD,CAAC,CAAC,KAAK,IAAI;AACZ;AAEA,SAAS,uBAAuB,MAAsC;CACrE,OAAO;EACN;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,0BAA0B,mBAAmB,CAAC,CAAC;EAC/C;EACA,qBAAqB,mBAAmB,CAAC,CAAC,aAAa;EACvD;EACA;EACA;EACA,gCAAgC,mBAAmB,CAAC,CAAC,cAAc;EACnE,6BAA6B,mBAAmB,CAAC,CAAC;EAClD;EACA;EACA,iCAAiC,KAAK,YAAY;EAClD;EACA;EACA,oDAAoD,KAAK,qBAAqB;EAC9E;EACA;EACA;CACD,CAAC,CAAC,KAAK,IAAI;AACZ;;;;AAKA,eAAsB,KAAK,SAA4C;CACtE,MAAM,WAAW,SAAS,SAAS;CAEnC,MAAM,oBAAoB,UAA+B;EACxD,SAAS;EACT;EACA,SAAS,CAAC;EACV,QAAQ;GACP,WAAW;GACX,gBAAgB;GAChB,YAAY,CAAC;EACd;EACA,SAAS;GACR,eAAe;GACf,UAAU,EAAE,GAAG,mBAAmB,EAAE;EACrC;EACA,WAAW;GACV,YAAY;GACZ,iBAAiB;EAClB;CACD;CAEA,IAAI,CAAC,UACJ,IAAI,SAAS,UAAU,KAAA,GACtB,IAAI,cAAc,QAAQ,KAAK,GAC9B,MACC,oEAAoE,QAAQ,OAC7E;MAEA,MACC,+CAA+C,QAAQ,OACxD;MAGD,MACC,6EACD;CAIF,MAAM,UAAU,QAAQ,IAAI,QAAQ,QAAQ,IAAI;CAChD,IAAI,CAAC,SAAS;EACb,IAAI,CAAC,UAAU;GACd,IAAI,MAAM,oCAAoC;GAC9C,MAAM,uDAAuD;EAC9D;EACA,OAAO,iBAAiB,KAAK;CAC9B;CAEA,IAAI;CAEJ,IAAI,SAAS,UAAU,KAAA,GACtB,kBAAkB,CAAC,QAAQ,KAAK;MAC1B;EACN,IAAI,UACH,OAAO,iBAAiB,KAAK;EAG9B,MAAM,mBAAmB,MAAM,uBAAuB,OAAO;EAE7D,MAAM,WAAW,MAAM,YAAY;GAClC,SACC;GACD,SAAS,wBAAwB,KAAK,WAAW;IAChD,OAAO,MAAM;IACb,OAAO,MAAM;IACb,MAAM,MAAM;GACb,EAAE;GACF,eAAe;GACf,UAAU;EACX,CAAC;EAED,IAAI,SAAS,QAAQ,GAAG;GACvB,MAAM,wBAAwB;GAC9B,OAAO,iBAAiB,KAAK;EAC9B;EAEA,kBAAkB;CACnB;CAEA,IAAI,gBAAgB,WAAW,GAAG;EACjC,IAAI,CAAC,UAAU;GACd,IAAI,KAAK,sBAAsB;GAC/B,MAAM,wBAAwB;EAC/B;EACA,OAAO,iBAAiB,KAAK;CAC9B;CAKA,IAAI;MAEC,CAAC,MADwB,gBAAgB,GACxB;GACpB,MAAM,EAAE,gBAAgB,KAAK,GAAG,cAAc;GAC9C,MAAM,wBAAwB,MAAM,kBAAkB;GAEtD,OAAO;IACN,SAAS;IACT,MAAM;IACN,cAAc;IACd,kBAAkB,oBAAoB;IACtC,SAAS,CAAC;IACV,QAAQ;KACP,WAAW;KACX,gBAAgB;KAChB,YAAY;IACb;IACA,SAAS;KACR,eAAe;KACf,UAAU,EAAE,GAAG,mBAAmB,EAAE;IACrC;IACA,WAAW;KACV,YAAY;KACZ,iBAAiB;IAClB;GACD;EACD;;CAGD,MAAM,EAAE,SAAS,gBAAgB,MAAM,YAAY,iBAAiB,EACnE,MAAM,SACP,CAAC;CAED,MAAM,aAAuB,CAAC;CAC9B,MAAM,SAAmB,CAAC;CAE1B,KAAK,MAAM,CAAC,QAAQ,WAAW,QAAQ,QAAQ,GAC9C,IAAI,WAAW,WACd,WAAW,KAAK,MAAM;MAEtB,OAAO,KAAK,MAAM;CAIpB,IAAI,kBAAkB;CACtB,IAAI,WAAW,SAAS,GACvB,kBAAkB,MAAM,mBAAmB,YAAY,EACtD,MAAM,SACP,CAAC;CAIF,MAAM,gBAAuC,CAAC;CAC9C,KAAK,MAAM,CAAC,QAAQ,WAAW,QAAQ,QAAQ,GAC9C,cAAc,KAAK;EAClB;EACA;EACA,MAAM,cAAc,MAAM,IAAI,cAAc;CAC7C,CAAC;CAGF,MAAM,gBAAgB,WAAW,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;CAE9D,IAAI,UAAU;EACb,MAAM,EAAE,gBAAgB,KAAK,GAAG,cAAc;EAE9C,MAAM,wBAAwB,MAAM,kBAAkB;EAEtD,OAAO;GACN,SAAS,WAAW,SAAS;GAC7B,MAAM;GACN,mBAAmB,uBAAuB,SAAS;GACnD,SAAS;GACT,QAAQ;IACP,WAAW;IACX,gBAAgB;IAChB,YAAY;GACb;GACA,SAAS;IACR,eAAe;IACf,UAAU,EAAE,GAAG,mBAAmB,EAAE;GACrC;GACA,WAAW;IACV,YAAY;IACZ,iBAAiB;GAClB;EACD;CACD;CAGA,MAAM,mBAAmB,WAAW,OAAO,aAAa;CACxD,MAAM,aAAa,WAAW,QAAQ,MAAM,CAAC,cAAc,CAAC,CAAC;CAC7D,MAAM,yBAAyB,OAAO,OAAO,aAAa;CAC1D,MAAM,mBAAmB,OAAO,QAAQ,MAAM,CAAC,cAAc,CAAC,CAAC;CAE/D,IAAI,iBAAiB,SAAS,GAAG;EAChC,MAAM,iBAAiB,iBAAiB,KAAK,KAAK;EAClD,IAAI,KACH,8CAA8C,eAAe,IAC9D;CACD;CAEA,IAAI,WAAW,SAAS,GAAG;EAC1B,MAAM,iBAAiB,WAAW,KAAK,KAAK;EAC5C,IAAI,KACH,4CAA4C,eAAe,IAC5D;CACD;CAEA,IAAI,uBAAuB,SAAS,GAAG;EACtC,IAAI,KACH,8GACD;EACA,KAAK,MAAM,UAAU,wBACpB,IAAI,WAAW,WACd,IAAI,KACH,gGACD;OACM,IAAI,WAAW,UACrB,IAAI,KACH,0EACD;CAGH;CAEA,IAAI,iBAAiB,SAAS,GAAG;EAChC,IAAI,MACH,sCAAsC,iBAAiB,KAAK,KAAK,GAClE;EACA,IAAI,KACH,6FACD;CACD;CAEA,IAAI,WAAW,WAAW,GAAG;EAC5B,MACC,gFACD;EACA,OAAO;GACN,SAAS;GACT,MAAM;GACN,SAAS;GACT,QAAQ;IAAE,WAAW;IAAO,gBAAgB;IAAM,YAAY,CAAC;GAAE;GACjE,SAAS;IACR,eAAe;IACf,UAAU,EAAE,GAAG,mBAAmB,EAAE;GACrC;GACA,WAAW;IAAE,YAAY;IAAO,iBAAiB;GAAM;EACxD;CACD;CAEA,IAAI,iBAAiB,SAAS,KAAK,WAAW,WAAW,GAExD,KACC,kBAFsB,iBAAiB,KAAK,KAEb,EAAE,yCAAyC,KAAK,KAAK,uBAAuB,CAAC,EAAE,8BAC9G,cACD;MACM,IAAI,WAAW,SAAS,KAAK,iBAAiB,WAAW,GAE/D,KACC,kBAFsB,WAAW,KAAK,KAEP,EAAE,gBAAgB,KAAK,KAAK,uBAAuB,CAAC,EAAE,uBACrF,cACD;MAEA,KACC,cAAc,iBAAiB,KAAK,KAAK,EAAE,kDAAkD,KAAK,KAAK,uBAAuB,CAAC,EAAE,0CAA0C,WAAW,KAAK,KAAK,EAAE,yBAAyB,KAAK,KAAK,uBAAuB,CAAC,EAAE,uBAC/P,cACD;CAGD,MAAM,+CAA+C;CAErD,OAAO;EACN,SAAS;EACT,MAAM;EACN,SAAS;EACT,QAAQ;GACP,WAAW;GACX,gBAAgB;GAChB,YAAY,CAAC;EACd;EACA,SAAS;GACR,eAAe;GACf,UAAU,EAAE,GAAG,mBAAmB,EAAE;EACrC;EACA,WAAW;GACV,YAAY;GACZ,iBAAiB;EAClB;CACD;AACD"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import { intro, isCancel, log, multiselect, note, outro } from \"@clack/prompts\";\nimport { bold, cyan } from \"yoctocolors\";\nimport { ALL_CONFIGURABLE_AGENTS } from \"./lib/agents.js\";\nimport { isAuthenticated } from \"./lib/auth.js\";\nimport { detectAvailableEditors } from \"./lib/editors.js\";\nimport { usesExtension } from \"./lib/extension.js\";\nimport { installNeon } from \"./lib/install.js\";\nimport { neonctlCmd } from \"./lib/neonctl.js\";\nimport {\n\tfetchSkillContent,\n\tinstallAgentSkills,\n\tSKILL_REFERENCE_URLS,\n} from \"./lib/skills.js\";\nimport type { Editor, InitResult } from \"./lib/types.js\";\n\nexport type { InteractiveInitOptions } from \"./interactive.js\";\nexport { interactiveInit } from \"./interactive.js\";\nexport { detectAgent } from \"./lib/detect-agent.js\";\nexport { enrichResponse } from \"./lib/enrich-output.js\";\nexport { handleAuthPhase } from \"./lib/phases/auth.js\";\nexport { handleDbPhase } from \"./lib/phases/db.js\";\nexport { handleMcpPhase } from \"./lib/phases/mcp.js\";\nexport { handleMigrationsPhase } from \"./lib/phases/migrations.js\";\nexport { handleNeonAuthPhase } from \"./lib/phases/neon-auth.js\";\nexport { handleSkillsPhase } from \"./lib/phases/skills.js\";\nexport { handleStatusPhase } from \"./lib/phases/status.js\";\nexport { routeDataStep } from \"./lib/route-command.js\";\n// v2 exports\nexport type {\n\tAgentActionAction,\n\tAgentCheck,\n\tAgentCheckAction,\n\tAgentStep,\n\tAskUserAction,\n\tCompleteAction,\n\tInitResult,\n\tNextAction,\n\tPhase,\n\tPhaseResponse,\n\tRestartRequiredAction,\n\tRunCommandAction,\n\tRunNeonInitAction,\n\tStatusResponse,\n} from \"./lib/types.js\";\nexport type { OrchestratorOptions } from \"./v2.js\";\nexport { orchestrate } from \"./v2.js\";\n\nexport interface InitOptions {\n\t/** When set, configures only this agent and skips the editor selection prompt. */\n\tagent?: Editor;\n\t/** When true, suppresses interactive UI and returns structured JSON-friendly output. */\n\tjson?: boolean;\n}\n\nfunction getNeonctlCommands() {\n\tconst base = \"npx neon\";\n\treturn {\n\t\tlistOrgs: `${base} orgs list --output json`,\n\t\tlistProjects: `${base} projects list --output json`,\n\t\tcreateProject: `${base} projects create --name <project-name> --output json`,\n\t\tgetConnectionString: `${base} connection-string --project-id <project-id>`,\n\t};\n}\n\nfunction getAuthInstructions(): string {\n\tconst cmd = neonctlCmd();\n\tconst signupUrl = process.env.NEON_API_HOST\n\t\t? `${new URL(process.env.NEON_API_HOST).origin}/signup`\n\t\t: \"https://console.neon.tech/signup\";\n\treturn [\n\t\t\"YOU (the agent) must handle authentication. Do NOT ask the user to run commands themselves.\",\n\t\t\"Do NOT write wrapper scripts (Python, shell, etc.) — use simple shell commands only.\",\n\t\t\"IMPORTANT: Unset the CI environment variable for all neon commands below,\",\n\t\t\"otherwise the Neon CLI will refuse to open the browser.\",\n\t\t\"\",\n\t\t'Step 1: Ask the user: \"Do you already have a Neon account, or do you need to create one?\"',\n\t\t\"\",\n\t\t\"=== NEW ACCOUNT (sign up) ===\",\n\t\t\"Step 2a: Open the Neon sign-up page in the user's browser:\",\n\t\t` On macOS: open ${signupUrl}`,\n\t\t` On Linux: xdg-open ${signupUrl}`,\n\t\t\"Step 3a: Tell the user: \\\"I've opened the Neon sign-up page in your browser.\",\n\t\t\" Create your account, then check your email for a verification link and click it.\",\n\t\t' Let me know when you have finished signing up and verifying your email.\"',\n\t\t\"Step 4a: Once the user confirms, run the OAuth login:\",\n\t\t` ${cmd} auth`,\n\t\t\" This opens a second browser tab for OAuth authorization. The user approves access.\",\n\t\t\" If exit code 0: authentication succeeded.\",\n\t\t\" If exit code 2 (timeout): ask the user to confirm they finished sign-up and\",\n\t\t\" email verification, then retry the same command.\",\n\t\t\"\",\n\t\t\"=== EXISTING ACCOUNT (sign in) ===\",\n\t\t`Step 2b: Execute: ${cmd} auth`,\n\t\t\" This opens the OAuth login page directly. Sign-in is fast (60-second timeout).\",\n\t\t\" If exit code 0: authentication succeeded.\",\n\t\t\" If exit code 2 (timeout): ask the user to confirm they completed sign-in, then retry.\",\n\t\t\"\",\n\t\t\"=== AFTER SUCCESSFUL AUTH ===\",\n\t\t`Step 5: Verify by running: ${cmd} me`,\n\t\t\" This should print the user's account info and exit with code 0.\",\n\t\t\"Step 6: Re-run neon init with the same --agent and --json flags to complete setup.\",\n\t].join(\"\\n\");\n}\n\nfunction buildAgentInstructions(refs: Record<string, string>): string {\n\treturn [\n\t\t\"IMPORTANT: Follow these steps to set up the Neon project. Do NOT skip steps.\",\n\t\t\"\",\n\t\t\"CRITICAL — SKILL REFERENCES: The URLs in skills.references are authoritative\",\n\t\t\"implementation guides with exact import paths, component patterns, route structures,\",\n\t\t\"and common mistakes to avoid. You MUST fetch and read the relevant skill reference\",\n\t\t\"URL BEFORE writing any code that uses that Neon feature. Do NOT rely on general\",\n\t\t\"documentation pages (e.g. /docs/guides/*) or guess at import paths — the skill\",\n\t\t\"references are more accurate, complete, and agent-optimized.\",\n\t\t\"\",\n\t\t`1. List organizations: ${getNeonctlCommands().listOrgs}`,\n\t\t\" - If one org, use it. If multiple, ask the user which to use.\",\n\t\t`2. List projects: ${getNeonctlCommands().listProjects} (add --org-id <org-id>)`,\n\t\t\" - No projects: ask if they want to create a new one.\",\n\t\t\" - One project: ask if they want to use it or create new.\",\n\t\t\" - Multiple: let the user choose.\",\n\t\t`3. Create project if needed: ${getNeonctlCommands().createProject} (add --org-id <org-id>)`,\n\t\t`4. Get connection string: ${getNeonctlCommands().getConnectionString}`,\n\t\t\"5. Store in .env as DATABASE_URL (append, don't overwrite existing .env).\",\n\t\t\"6. For apps with user login/auth: STOP. Before writing any auth code, fetch and\",\n\t\t` read this skill reference: ${refs.neonAuth ?? \"\"}`,\n\t\t\" It contains the exact packages, imports, component layout, route patterns,\",\n\t\t\" environment variables, and common mistakes. Follow it precisely.\",\n\t\t`7. For connection method/driver, fetch and read: ${refs.connectionMethods ?? \"\"}`,\n\t\t\"8. Refer to skills.gettingStarted for the full setup guide with additional details.\",\n\t\t\"\",\n\t\t\"Do NOT auto-create a project without asking the user first.\",\n\t].join(\"\\n\");\n}\n\n/**\n * Initialize Neon projects with MCP Server\n */\nexport async function init(options?: InitOptions): Promise<InitResult> {\n\tconst jsonMode = options?.json === true;\n\n\tconst makeFailedResult = (auth: boolean): InitResult => ({\n\t\tsuccess: false,\n\t\tauth,\n\t\teditors: [],\n\t\tskills: {\n\t\t\tinstalled: false,\n\t\t\tgettingStarted: null,\n\t\t\treferences: {},\n\t\t},\n\t\tneonctl: {\n\t\t\tauthenticated: auth,\n\t\t\tcommands: { ...getNeonctlCommands() },\n\t\t},\n\t\tmcpServer: {\n\t\t\tconfigured: false,\n\t\t\trequiresRestart: false,\n\t\t},\n\t});\n\n\tif (!jsonMode) {\n\t\tif (options?.agent !== undefined) {\n\t\t\tif (usesExtension(options.agent)) {\n\t\t\t\tintro(\n\t\t\t\t\t`Adding Neon extension (includes MCP server) and agent skills for ${options.agent}`,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tintro(\n\t\t\t\t\t`Adding Neon MCP server and agent skills for ${options.agent}`,\n\t\t\t\t);\n\t\t\t}\n\t\t} else {\n\t\t\tintro(\n\t\t\t\t\"Adding Neon MCP server, extension (for VS Code and Cursor) and agent skills\",\n\t\t\t);\n\t\t}\n\t}\n\n\tconst homeDir = process.env.HOME || process.env.USERPROFILE;\n\tif (!homeDir) {\n\t\tif (!jsonMode) {\n\t\t\tlog.error(\"Could not determine home directory\");\n\t\t\toutro(\"📣 Is this unexpected? Email us at feedback@neon.tech\");\n\t\t}\n\t\treturn makeFailedResult(false);\n\t}\n\n\tlet selectedEditors: Editor[];\n\n\tif (options?.agent !== undefined) {\n\t\tselectedEditors = [options.agent];\n\t} else {\n\t\tif (jsonMode) {\n\t\t\treturn makeFailedResult(false);\n\t\t}\n\n\t\tconst availableEditors = await detectAvailableEditors(homeDir);\n\n\t\tconst response = await multiselect({\n\t\t\tmessage:\n\t\t\t\t\"Which editor(s) would you like to configure? (Space to toggle each option, Enter to confirm your selection)\",\n\t\t\toptions: ALL_CONFIGURABLE_AGENTS.map((agent) => ({\n\t\t\t\tvalue: agent.editor,\n\t\t\t\tlabel: agent.editor,\n\t\t\t\thint: agent.hint,\n\t\t\t})),\n\t\t\tinitialValues: availableEditors,\n\t\t\trequired: true,\n\t\t});\n\n\t\tif (isCancel(response)) {\n\t\t\toutro(\"Installation cancelled\");\n\t\t\treturn makeFailedResult(false);\n\t\t}\n\n\t\tselectedEditors = response as Editor[];\n\t}\n\n\tif (selectedEditors.length === 0) {\n\t\tif (!jsonMode) {\n\t\t\tlog.warn(\"No editors selected.\");\n\t\t\toutro(\"Installation cancelled\");\n\t\t}\n\t\treturn makeFailedResult(false);\n\t}\n\n\t// In JSON mode, check for existing credentials before attempting OAuth.\n\t// neonctl's OAuth has a 60s timeout and email verification breaks the redirect,\n\t// so we let the agent handle auth as a separate step.\n\tif (jsonMode) {\n\t\tconst hasCredentials = await isAuthenticated();\n\t\tif (!hasCredentials) {\n\t\t\tconst { gettingStarted: _gs, ...otherRefs } = SKILL_REFERENCE_URLS;\n\t\t\tconst gettingStartedContent = await fetchSkillContent();\n\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\tauth: false,\n\t\t\t\tauthRequired: true,\n\t\t\t\tauthInstructions: getAuthInstructions(),\n\t\t\t\teditors: [],\n\t\t\t\tskills: {\n\t\t\t\t\tinstalled: false,\n\t\t\t\t\tgettingStarted: gettingStartedContent,\n\t\t\t\t\treferences: otherRefs,\n\t\t\t\t},\n\t\t\t\tneonctl: {\n\t\t\t\t\tauthenticated: false,\n\t\t\t\t\tcommands: { ...getNeonctlCommands() },\n\t\t\t\t},\n\t\t\t\tmcpServer: {\n\t\t\t\t\tconfigured: false,\n\t\t\t\t\trequiresRestart: false,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t}\n\n\tconst { results, authSuccess } = await installNeon(selectedEditors, {\n\t\tjson: jsonMode,\n\t});\n\n\tconst successful: Editor[] = [];\n\tconst failed: Editor[] = [];\n\n\tfor (const [editor, status] of results.entries()) {\n\t\tif (status === \"success\") {\n\t\t\tsuccessful.push(editor);\n\t\t} else {\n\t\t\tfailed.push(editor);\n\t\t}\n\t}\n\n\tlet skillsInstalled = false;\n\tif (successful.length > 0) {\n\t\tskillsInstalled = await installAgentSkills(successful, {\n\t\t\tjson: jsonMode,\n\t\t});\n\t}\n\n\t// Build the editors array for InitResult\n\tconst editorsResult: InitResult[\"editors\"] = [];\n\tfor (const [editor, status] of results.entries()) {\n\t\teditorsResult.push({\n\t\t\teditor,\n\t\t\tstatus,\n\t\t\ttype: usesExtension(editor) ? \"extension\" : \"mcp\",\n\t\t});\n\t}\n\n\tconst mcpConfigured = successful.some((e) => !usesExtension(e));\n\n\tif (jsonMode) {\n\t\tconst { gettingStarted: _gs, ...otherRefs } = SKILL_REFERENCE_URLS;\n\n\t\tconst gettingStartedContent = await fetchSkillContent();\n\n\t\treturn {\n\t\t\tsuccess: successful.length > 0,\n\t\t\tauth: authSuccess,\n\t\t\tagentInstructions: buildAgentInstructions(otherRefs),\n\t\t\teditors: editorsResult,\n\t\t\tskills: {\n\t\t\t\tinstalled: skillsInstalled,\n\t\t\t\tgettingStarted: gettingStartedContent,\n\t\t\t\treferences: otherRefs,\n\t\t\t},\n\t\t\tneonctl: {\n\t\t\t\tauthenticated: authSuccess,\n\t\t\t\tcommands: { ...getNeonctlCommands() },\n\t\t\t},\n\t\t\tmcpServer: {\n\t\t\t\tconfigured: mcpConfigured,\n\t\t\t\trequiresRestart: mcpConfigured,\n\t\t\t},\n\t\t};\n\t}\n\n\t// Interactive UI output (non-json mode)\n\tconst extensionEditors = successful.filter(usesExtension);\n\tconst mcpEditors = successful.filter((e) => !usesExtension(e));\n\tconst failedExtensionEditors = failed.filter(usesExtension);\n\tconst failedMcpEditors = failed.filter((e) => !usesExtension(e));\n\n\tif (extensionEditors.length > 0) {\n\t\tconst extSuccessList = extensionEditors.join(\" / \");\n\t\tlog.step(\n\t\t\t`Neon Local Connect extension installed for ${extSuccessList}.\\n`,\n\t\t);\n\t}\n\n\tif (mcpEditors.length > 0) {\n\t\tconst mcpSuccessList = mcpEditors.join(\" / \");\n\t\tlog.step(\n\t\t\t`Neon MCP Server is now ready to use with ${mcpSuccessList}.\\n`,\n\t\t);\n\t}\n\n\tif (failedExtensionEditors.length > 0) {\n\t\tlog.info(\n\t\t\t\"Failed to install extension. For the best local development experience, install Neon Local Connect manually:\",\n\t\t);\n\t\tfor (const editor of failedExtensionEditors) {\n\t\t\tif (editor === \"VS Code\") {\n\t\t\t\tlog.info(\n\t\t\t\t\t\" • VS Code: https://marketplace.visualstudio.com/items?itemName=databricks.neon-local-connect\",\n\t\t\t\t);\n\t\t\t} else if (editor === \"Cursor\") {\n\t\t\t\tlog.info(\n\t\t\t\t\t\" • Cursor: https://open-vsx.org/extension/databricks/neon-local-connect\",\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (failedMcpEditors.length > 0) {\n\t\tlog.error(\n\t\t\t`Failed to configure MCP Server for ${failedMcpEditors.join(\" / \")}`,\n\t\t);\n\t\tlog.info(\n\t\t\t\"You can manually configure the MCP server by running: npx add-mcp https://mcp.neon.tech/mcp\",\n\t\t);\n\t}\n\n\tif (successful.length === 0) {\n\t\toutro(\n\t\t\t\"Installation cancelled or failed. Please check the output above and try again.\",\n\t\t);\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\tauth: authSuccess,\n\t\t\teditors: editorsResult,\n\t\t\tskills: { installed: false, gettingStarted: null, references: {} },\n\t\t\tneonctl: {\n\t\t\t\tauthenticated: authSuccess,\n\t\t\t\tcommands: { ...getNeonctlCommands() },\n\t\t\t},\n\t\t\tmcpServer: { configured: false, requiresRestart: false },\n\t\t};\n\t}\n\n\tif (extensionEditors.length > 0 && mcpEditors.length === 0) {\n\t\tconst extSuccessList = extensionEditors.join(\" / \");\n\t\tnote(\n\t\t\t`\\x1b[0mRestart ${extSuccessList}, open the Neon extension and type in \"${bold(cyan(\"Get started with Neon\"))}\\x1b[0m\" in your agent chat`,\n\t\t\t\"What's next?\",\n\t\t);\n\t} else if (mcpEditors.length > 0 && extensionEditors.length === 0) {\n\t\tconst mcpSuccessList = mcpEditors.join(\" / \");\n\t\tnote(\n\t\t\t`\\x1b[0mRestart ${mcpSuccessList} and type in \"${bold(cyan(\"Get started with Neon\"))}\\x1b[0m\" in the chat`,\n\t\t\t\"What's next?\",\n\t\t);\n\t} else {\n\t\tnote(\n\t\t\t`\\x1b[0mFor ${extensionEditors.join(\" / \")}: Restart, open the Neon extension and type in \"${bold(cyan(\"Get started with Neon\"))}\\x1b[0m\" in your agent chat\\n\\x1b[0mFor ${mcpEditors.join(\" / \")}: Restart and type in \"${bold(cyan(\"Get started with Neon\"))}\\x1b[0m\" in the chat`,\n\t\t\t\"What's next?\",\n\t\t);\n\t}\n\n\toutro(\"Have feedback? Email us at feedback@neon.tech\");\n\n\treturn {\n\t\tsuccess: true,\n\t\tauth: authSuccess,\n\t\teditors: editorsResult,\n\t\tskills: {\n\t\t\tinstalled: skillsInstalled,\n\t\t\tgettingStarted: null,\n\t\t\treferences: {},\n\t\t},\n\t\tneonctl: {\n\t\t\tauthenticated: authSuccess,\n\t\t\tcommands: { ...getNeonctlCommands() },\n\t\t},\n\t\tmcpServer: {\n\t\t\tconfigured: mcpConfigured,\n\t\t\trequiresRestart: mcpConfigured,\n\t\t},\n\t};\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAsDA,SAAS,qBAAqB;CAC7B,MAAM,OAAO;CACb,OAAO;EACN,UAAU,GAAG,KAAK;EAClB,cAAc,GAAG,KAAK;EACtB,eAAe,GAAG,KAAK;EACvB,qBAAqB,GAAG,KAAK;CAC9B;AACD;AAEA,SAAS,sBAA8B;CACtC,MAAM,MAAM,WAAW;CACvB,MAAM,YAAY,QAAQ,IAAI,gBAC3B,GAAG,IAAI,IAAI,QAAQ,IAAI,aAAa,CAAC,CAAC,OAAO,WAC7C;CACH,OAAO;EACN;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,qBAAqB;EACrB,yBAAyB;EACzB;EACA;EACA;EACA;EACA,MAAM,IAAI;EACV;EACA;EACA;EACA;EACA;EACA;EACA,qBAAqB,IAAI;EACzB;EACA;EACA;EACA;EACA;EACA,8BAA8B,IAAI;EAClC;EACA;CACD,CAAC,CAAC,KAAK,IAAI;AACZ;AAEA,SAAS,uBAAuB,MAAsC;CACrE,OAAO;EACN;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,0BAA0B,mBAAmB,CAAC,CAAC;EAC/C;EACA,qBAAqB,mBAAmB,CAAC,CAAC,aAAa;EACvD;EACA;EACA;EACA,gCAAgC,mBAAmB,CAAC,CAAC,cAAc;EACnE,6BAA6B,mBAAmB,CAAC,CAAC;EAClD;EACA;EACA,iCAAiC,KAAK,YAAY;EAClD;EACA;EACA,oDAAoD,KAAK,qBAAqB;EAC9E;EACA;EACA;CACD,CAAC,CAAC,KAAK,IAAI;AACZ;;;;AAKA,eAAsB,KAAK,SAA4C;CACtE,MAAM,WAAW,SAAS,SAAS;CAEnC,MAAM,oBAAoB,UAA+B;EACxD,SAAS;EACT;EACA,SAAS,CAAC;EACV,QAAQ;GACP,WAAW;GACX,gBAAgB;GAChB,YAAY,CAAC;EACd;EACA,SAAS;GACR,eAAe;GACf,UAAU,EAAE,GAAG,mBAAmB,EAAE;EACrC;EACA,WAAW;GACV,YAAY;GACZ,iBAAiB;EAClB;CACD;CAEA,IAAI,CAAC,UACJ,IAAI,SAAS,UAAU,KAAA,GACtB,IAAI,cAAc,QAAQ,KAAK,GAC9B,MACC,oEAAoE,QAAQ,OAC7E;MAEA,MACC,+CAA+C,QAAQ,OACxD;MAGD,MACC,6EACD;CAIF,MAAM,UAAU,QAAQ,IAAI,QAAQ,QAAQ,IAAI;CAChD,IAAI,CAAC,SAAS;EACb,IAAI,CAAC,UAAU;GACd,IAAI,MAAM,oCAAoC;GAC9C,MAAM,uDAAuD;EAC9D;EACA,OAAO,iBAAiB,KAAK;CAC9B;CAEA,IAAI;CAEJ,IAAI,SAAS,UAAU,KAAA,GACtB,kBAAkB,CAAC,QAAQ,KAAK;MAC1B;EACN,IAAI,UACH,OAAO,iBAAiB,KAAK;EAG9B,MAAM,mBAAmB,MAAM,uBAAuB,OAAO;EAE7D,MAAM,WAAW,MAAM,YAAY;GAClC,SACC;GACD,SAAS,wBAAwB,KAAK,WAAW;IAChD,OAAO,MAAM;IACb,OAAO,MAAM;IACb,MAAM,MAAM;GACb,EAAE;GACF,eAAe;GACf,UAAU;EACX,CAAC;EAED,IAAI,SAAS,QAAQ,GAAG;GACvB,MAAM,wBAAwB;GAC9B,OAAO,iBAAiB,KAAK;EAC9B;EAEA,kBAAkB;CACnB;CAEA,IAAI,gBAAgB,WAAW,GAAG;EACjC,IAAI,CAAC,UAAU;GACd,IAAI,KAAK,sBAAsB;GAC/B,MAAM,wBAAwB;EAC/B;EACA,OAAO,iBAAiB,KAAK;CAC9B;CAKA,IAAI;MAEC,CAAC,MADwB,gBAAgB,GACxB;GACpB,MAAM,EAAE,gBAAgB,KAAK,GAAG,cAAc;GAC9C,MAAM,wBAAwB,MAAM,kBAAkB;GAEtD,OAAO;IACN,SAAS;IACT,MAAM;IACN,cAAc;IACd,kBAAkB,oBAAoB;IACtC,SAAS,CAAC;IACV,QAAQ;KACP,WAAW;KACX,gBAAgB;KAChB,YAAY;IACb;IACA,SAAS;KACR,eAAe;KACf,UAAU,EAAE,GAAG,mBAAmB,EAAE;IACrC;IACA,WAAW;KACV,YAAY;KACZ,iBAAiB;IAClB;GACD;EACD;;CAGD,MAAM,EAAE,SAAS,gBAAgB,MAAM,YAAY,iBAAiB,EACnE,MAAM,SACP,CAAC;CAED,MAAM,aAAuB,CAAC;CAC9B,MAAM,SAAmB,CAAC;CAE1B,KAAK,MAAM,CAAC,QAAQ,WAAW,QAAQ,QAAQ,GAC9C,IAAI,WAAW,WACd,WAAW,KAAK,MAAM;MAEtB,OAAO,KAAK,MAAM;CAIpB,IAAI,kBAAkB;CACtB,IAAI,WAAW,SAAS,GACvB,kBAAkB,MAAM,mBAAmB,YAAY,EACtD,MAAM,SACP,CAAC;CAIF,MAAM,gBAAuC,CAAC;CAC9C,KAAK,MAAM,CAAC,QAAQ,WAAW,QAAQ,QAAQ,GAC9C,cAAc,KAAK;EAClB;EACA;EACA,MAAM,cAAc,MAAM,IAAI,cAAc;CAC7C,CAAC;CAGF,MAAM,gBAAgB,WAAW,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;CAE9D,IAAI,UAAU;EACb,MAAM,EAAE,gBAAgB,KAAK,GAAG,cAAc;EAE9C,MAAM,wBAAwB,MAAM,kBAAkB;EAEtD,OAAO;GACN,SAAS,WAAW,SAAS;GAC7B,MAAM;GACN,mBAAmB,uBAAuB,SAAS;GACnD,SAAS;GACT,QAAQ;IACP,WAAW;IACX,gBAAgB;IAChB,YAAY;GACb;GACA,SAAS;IACR,eAAe;IACf,UAAU,EAAE,GAAG,mBAAmB,EAAE;GACrC;GACA,WAAW;IACV,YAAY;IACZ,iBAAiB;GAClB;EACD;CACD;CAGA,MAAM,mBAAmB,WAAW,OAAO,aAAa;CACxD,MAAM,aAAa,WAAW,QAAQ,MAAM,CAAC,cAAc,CAAC,CAAC;CAC7D,MAAM,yBAAyB,OAAO,OAAO,aAAa;CAC1D,MAAM,mBAAmB,OAAO,QAAQ,MAAM,CAAC,cAAc,CAAC,CAAC;CAE/D,IAAI,iBAAiB,SAAS,GAAG;EAChC,MAAM,iBAAiB,iBAAiB,KAAK,KAAK;EAClD,IAAI,KACH,8CAA8C,eAAe,IAC9D;CACD;CAEA,IAAI,WAAW,SAAS,GAAG;EAC1B,MAAM,iBAAiB,WAAW,KAAK,KAAK;EAC5C,IAAI,KACH,4CAA4C,eAAe,IAC5D;CACD;CAEA,IAAI,uBAAuB,SAAS,GAAG;EACtC,IAAI,KACH,8GACD;EACA,KAAK,MAAM,UAAU,wBACpB,IAAI,WAAW,WACd,IAAI,KACH,gGACD;OACM,IAAI,WAAW,UACrB,IAAI,KACH,0EACD;CAGH;CAEA,IAAI,iBAAiB,SAAS,GAAG;EAChC,IAAI,MACH,sCAAsC,iBAAiB,KAAK,KAAK,GAClE;EACA,IAAI,KACH,6FACD;CACD;CAEA,IAAI,WAAW,WAAW,GAAG;EAC5B,MACC,gFACD;EACA,OAAO;GACN,SAAS;GACT,MAAM;GACN,SAAS;GACT,QAAQ;IAAE,WAAW;IAAO,gBAAgB;IAAM,YAAY,CAAC;GAAE;GACjE,SAAS;IACR,eAAe;IACf,UAAU,EAAE,GAAG,mBAAmB,EAAE;GACrC;GACA,WAAW;IAAE,YAAY;IAAO,iBAAiB;GAAM;EACxD;CACD;CAEA,IAAI,iBAAiB,SAAS,KAAK,WAAW,WAAW,GAExD,KACC,kBAFsB,iBAAiB,KAAK,KAEb,EAAE,yCAAyC,KAAK,KAAK,uBAAuB,CAAC,EAAE,8BAC9G,cACD;MACM,IAAI,WAAW,SAAS,KAAK,iBAAiB,WAAW,GAE/D,KACC,kBAFsB,WAAW,KAAK,KAEP,EAAE,gBAAgB,KAAK,KAAK,uBAAuB,CAAC,EAAE,uBACrF,cACD;MAEA,KACC,cAAc,iBAAiB,KAAK,KAAK,EAAE,kDAAkD,KAAK,KAAK,uBAAuB,CAAC,EAAE,0CAA0C,WAAW,KAAK,KAAK,EAAE,yBAAyB,KAAK,KAAK,uBAAuB,CAAC,EAAE,uBAC/P,cACD;CAGD,MAAM,+CAA+C;CAErD,OAAO;EACN,SAAS;EACT,MAAM;EACN,SAAS;EACT,QAAQ;GACP,WAAW;GACX,gBAAgB;GAChB,YAAY,CAAC;EACd;EACA,SAAS;GACR,eAAe;GACf,UAAU,EAAE,GAAG,mBAAmB,EAAE;EACrC;EACA,WAAW;GACV,YAAY;GACZ,iBAAiB;EAClB;CACD;AACD"}
|
package/dist/interactive.js
CHANGED
|
@@ -264,7 +264,7 @@ async function interactiveInitInner(options) {
|
|
|
264
264
|
initialValue: "no"
|
|
265
265
|
});
|
|
266
266
|
if (isCancel(authResult) || authResult === "no") {
|
|
267
|
-
outro(dim(`Your project is configured with Neon. You can set up Neon Auth later by having your agent run:
|
|
267
|
+
outro(dim(`Your project is configured with Neon. You can set up Neon Auth later by having your agent run: neon init --agent --data '{"step":"neon-auth"}'`));
|
|
268
268
|
return;
|
|
269
269
|
}
|
|
270
270
|
let projectId = null;
|
|
@@ -442,21 +442,21 @@ async function interactiveInitInner(options) {
|
|
|
442
442
|
authS.stop("Authenticated.");
|
|
443
443
|
}
|
|
444
444
|
const nctlS = spinner();
|
|
445
|
-
nctlS.start("Checking
|
|
445
|
+
nctlS.start("Checking Neon CLI...");
|
|
446
446
|
const nctlResult = await ensureNeonctl();
|
|
447
447
|
switch (nctlResult.status) {
|
|
448
448
|
case "already_current":
|
|
449
|
-
nctlS.stop(dim(`
|
|
449
|
+
nctlS.stop(dim(`Neon CLI is up to date (v${nctlResult.version}) ✓`));
|
|
450
450
|
break;
|
|
451
451
|
case "installed":
|
|
452
|
-
nctlS.stop(dim(`Installed
|
|
452
|
+
nctlS.stop(dim(`Installed Neon CLI (v${nctlResult.version}) ✓`));
|
|
453
453
|
break;
|
|
454
454
|
case "updated":
|
|
455
|
-
nctlS.stop(dim(`Updated
|
|
455
|
+
nctlS.stop(dim(`Updated Neon CLI to v${nctlResult.version} ✓`));
|
|
456
456
|
break;
|
|
457
457
|
case "failed":
|
|
458
|
-
nctlS.stop("Failed to install
|
|
459
|
-
log.warn("
|
|
458
|
+
nctlS.stop("Failed to install Neon CLI");
|
|
459
|
+
log.warn("The Neon CLI could not be installed automatically. The setup will continue using npx.");
|
|
460
460
|
break;
|
|
461
461
|
}
|
|
462
462
|
for (const editor of selectedEditors) {
|
|
@@ -509,7 +509,7 @@ async function interactiveInitInner(options) {
|
|
|
509
509
|
if (inspection.migrationDir && inspection.migrationDir !== "none") gettingStartedData.migrationDir = inspection.migrationDir;
|
|
510
510
|
if (selectedFeatures.length > 0) gettingStartedData.features = selectedFeatures;
|
|
511
511
|
if (options.preview) gettingStartedData.preview = true;
|
|
512
|
-
const cmd = `
|
|
512
|
+
const cmd = `neon init --agent --data '${JSON.stringify({
|
|
513
513
|
step: "getting-started",
|
|
514
514
|
...gettingStartedData
|
|
515
515
|
})}'`;
|
package/dist/interactive.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interactive.js","names":[],"sources":["../src/interactive.ts"],"sourcesContent":["/**\n * Interactive v2 CLI — purpose-built guided flow for humans.\n * Uses the same underlying install functions but with a clean clack-based UX.\n */\n\nimport { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { SelectPrompt } from \"@clack/core\";\nimport {\n\tconfirm,\n\tisCancel,\n\tlog,\n\tmultiselect,\n\toutro,\n\tselect,\n\tspinner,\n} from \"@clack/prompts\";\nimport { execa } from \"execa\";\nimport { bold, dim, gray, italic } from \"yoctocolors\";\nimport { ALL_CONFIGURABLE_AGENTS, getAddMcpAgentId } from \"./lib/agents.js\";\nimport { ensureNeonctlAuth, isAuthenticated } from \"./lib/auth.js\";\nimport {\n\ttype BootstrapTemplate,\n\tFALLBACK_TEMPLATES,\n\tfetchTemplates,\n\ttype NeonFeature,\n\tscaffoldTemplate,\n} from \"./lib/bootstrap.js\";\nimport { detectAgent, detectIde } from \"./lib/detect-agent.js\";\nimport { detectAvailableEditors } from \"./lib/editors.js\";\nimport {\n\tinstallExtension,\n\tisExtensionInstalled,\n\tusesExtension,\n} from \"./lib/extension.js\";\nimport { inspectProject } from \"./lib/inspect.js\";\nimport { ensureNeonctl } from \"./lib/neonctl.js\";\nimport { ensureSkillsUpToDate, installAgentSkills } from \"./lib/skills.js\";\nimport type { Editor } from \"./lib/types.js\";\n\nfunction wordWrap(text: string, width: number): string {\n\treturn text\n\t\t.split(\"\\n\")\n\t\t.map((line) => {\n\t\t\tif (line.length <= width) return line;\n\t\t\tconst words = line.split(\" \");\n\t\t\tconst lines: string[] = [];\n\t\t\tlet current = \"\";\n\t\t\tfor (const word of words) {\n\t\t\t\tif (\n\t\t\t\t\tcurrent.length + word.length + 1 > width &&\n\t\t\t\t\tcurrent.length > 0\n\t\t\t\t) {\n\t\t\t\t\tlines.push(current);\n\t\t\t\t\tcurrent = word;\n\t\t\t\t} else {\n\t\t\t\t\tcurrent = current.length > 0 ? `${current} ${word}` : word;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (current.length > 0) lines.push(current);\n\t\t\treturn lines.join(\"\\n\");\n\t\t})\n\t\t.join(\"\\n\");\n}\n\n// Patch picocolors (used by @clack/prompts) to use Neon green instead of cyan/magenta.\n// clack hardcodes picocolors.cyan() with no theme API, so this is the least invasive override.\nimport picocolors from \"picocolors\";\n\nconst neonGreenFn = (s: string) => `\\x1b[38;2;75;181;120m${s}\\x1b[39m`;\nconst originalCyan = picocolors.cyan;\nconst originalMagenta = picocolors.magenta;\n\nfunction patchClackColors(): () => void {\n\tconst pc = picocolors as unknown as Record<string, unknown>;\n\tpc.cyan = neonGreenFn;\n\tpc.magenta = neonGreenFn;\n\treturn () => {\n\t\tpc.cyan = originalCyan;\n\t\tpc.magenta = originalMagenta;\n\t};\n}\n\n// clack box-drawing glyphs, mirrored from @clack/prompts so our custom\n// template picker lines up with every other step in the flow.\nconst S_BAR = \"│\";\nconst S_BAR_END = \"└\";\nconst S_STEP_ACTIVE = \"◆\";\nconst S_STEP_SUBMIT = \"◇\";\nconst S_STEP_CANCEL = \"■\";\nconst S_RADIO_ACTIVE = \"●\";\nconst S_RADIO_INACTIVE = \"○\";\n\ninterface TemplateOption {\n\tvalue: string;\n\tlabel: string;\n\ttools?: string[];\n\tdescription?: string;\n}\n\nconst SENTINEL_NONE = \"none\";\n\n/**\n * Bespoke template picker built on @clack/core's `SelectPrompt`.\n *\n * The stock `@clack/prompts` `select` can only render an option on a single\n * line (title + a parenthesized hint on the focused row), which can't express\n * what we want here: a clean title-only list, and a focused row that expands to\n * `Title (tools)` with the description on its own italic line beneath. Driving\n * the core prompt directly lets us own the frame, so we emit a second\n * gutter-aligned line for the active option only.\n */\nasync function selectTemplate(\n\ttemplates: BootstrapTemplate[],\n\tmessage: string,\n): Promise<string | symbol> {\n\tconst options: TemplateOption[] = [\n\t\t...templates.map((t) => ({\n\t\t\tvalue: t.id,\n\t\t\tlabel: t.title,\n\t\t\ttools: t.tools,\n\t\t\tdescription: t.description,\n\t\t})),\n\t\t{\n\t\t\tvalue: SENTINEL_NONE,\n\t\t\tlabel: \"No thanks — continue without scaffolding\",\n\t\t},\n\t];\n\n\tconst green = neonGreenFn;\n\t// Title sits at column 6 (\"│ ● \"), so wrapped description lines indent four\n\t// spaces past the gutter to line up under it.\n\tconst descIndent = \" \";\n\tconst descWidth = Math.max(24, (process.stdout.columns || 80) - 8);\n\n\tconst renderActive = (option: TemplateOption): string => {\n\t\tconst tools =\n\t\t\toption.tools && option.tools.length > 0\n\t\t\t\t? ` ${dim(`(${option.tools.join(\", \")})`)}`\n\t\t\t\t: \"\";\n\t\tconst head = `${green(S_RADIO_ACTIVE)} ${option.label}${tools}`;\n\t\tif (!option.description) return head;\n\t\tconst body = wordWrap(option.description, descWidth)\n\t\t\t.split(\"\\n\")\n\t\t\t.map((line) => `${green(S_BAR)}${descIndent}${italic(dim(line))}`)\n\t\t\t.join(\"\\n\");\n\t\treturn `${head}\\n${body}`;\n\t};\n\n\tconst prompt = new SelectPrompt<TemplateOption>({\n\t\toptions,\n\t\tinitialValue: options[0]?.value,\n\t\trender() {\n\t\t\tconst active = this.options[this.cursor];\n\t\t\tconst heading = (symbol: string) =>\n\t\t\t\t`${gray(S_BAR)}\\n${symbol} ${message}\\n`;\n\n\t\t\tif (this.state === \"submit\") {\n\t\t\t\treturn `${heading(green(S_STEP_SUBMIT))}${gray(S_BAR)} ${dim(\n\t\t\t\t\tactive?.label ?? \"\",\n\t\t\t\t)}`;\n\t\t\t}\n\t\t\tif (this.state === \"cancel\") {\n\t\t\t\treturn `${heading(green(S_STEP_CANCEL))}${gray(S_BAR)} ${dim(\n\t\t\t\t\tactive?.label ?? \"\",\n\t\t\t\t)}\\n${gray(S_BAR)}`;\n\t\t\t}\n\n\t\t\tconst body = this.options\n\t\t\t\t.map((option) =>\n\t\t\t\t\toption === active\n\t\t\t\t\t\t? renderActive(option)\n\t\t\t\t\t\t: `${dim(S_RADIO_INACTIVE)} ${dim(option.label)}`,\n\t\t\t\t)\n\t\t\t\t.join(`\\n${green(S_BAR)} `);\n\t\t\treturn `${heading(green(S_STEP_ACTIVE))}${green(S_BAR)} ${body}\\n${green(\n\t\t\t\tS_BAR_END,\n\t\t\t)}\\n`;\n\t\t},\n\t});\n\n\treturn prompt.prompt();\n}\n\nexport interface InteractiveInitOptions {\n\tpreview?: boolean;\n}\n\nexport async function interactiveInit(\n\toptions: InteractiveInitOptions = {},\n): Promise<void> {\n\tconst restoreColors = patchClackColors();\n\ttry {\n\t\tawait interactiveInitInner(options);\n\t} finally {\n\t\trestoreColors();\n\t}\n}\n\nasync function interactiveInitInner(\n\toptions: InteractiveInitOptions,\n): Promise<void> {\n\tconsole.log();\n\tconsole.log(\n\t\t\"\\x1b[38;2;75;181;120m\" +\n\t\t\t[\n\t\t\t\t\" ██╗ ██╗██████╗ ██████╗ ██╗ ██╗\",\n\t\t\t\t\" ███╗ ██║██╔═══╝ ██╔═══██╗███╗ ██║\",\n\t\t\t\t\" ████╗██║██████╗ ██║ ██║████╗██║\",\n\t\t\t\t\" ██╔████║██╔═══╝ ██║ ██║██╔████║\",\n\t\t\t\t\" ██║╚███║██████╗ ╚██████╔╝██║╚███║\",\n\t\t\t\t\" ╚═╝ ╚══╝╚═════╝ ╚═════╝ ╚═╝ ╚══╝\",\n\t\t\t].join(\"\\n\") +\n\t\t\t\"\\x1b[0m\",\n\t);\n\tconsole.log(\n\t\tdim(\n\t\t\twordWrap(\n\t\t\t\t\"\\nLet's get your project set up with Neon. We'll install the MCP server, agent skills, and IDE extension, then connect your app to a database.\\n\",\n\t\t\t\tprocess.stdout.columns || 80,\n\t\t\t),\n\t\t),\n\t);\n\n\tconst detectedAgentId = detectAgent();\n\tconst detectedEditor = detectedAgentId\n\t\t? agentIdToEditor(detectedAgentId)\n\t\t: null;\n\n\t// -----------------------------------------------------------------------\n\t// Step 1: Inspect what's already in place\n\t// -----------------------------------------------------------------------\n\tconst inspectSpinner = spinner();\n\tinspectSpinner.start(\"Checking existing configuration...\");\n\tconst inspection = await inspectProject([\n\t\t{ id: \"has_app\", description: \"\", lookFor: [] },\n\t\t{ id: \"mcp_server\", description: \"\", lookFor: [] },\n\t\t{ id: \"skills\", description: \"\", lookFor: [] },\n\t\t{ id: \"connection_string\", description: \"\", lookFor: [] },\n\t\t{ id: \"project_stack\", description: \"\", lookFor: [] },\n\t\t{ id: \"migrations\", description: \"\", lookFor: [] },\n\t\t{ id: \"ide_type\", description: \"\", lookFor: [] },\n\t]);\n\tinspectSpinner.stop(dim(\"Configuration checked ✓\"));\n\n\tconst hasApp = inspection.hasApp === true;\n\tlet selectedFeatures: NeonFeature[] = [];\n\tlet selectedTemplate: BootstrapTemplate | null = null;\n\n\t// Preview mode: bootstrap from template if no app detected\n\tif (options.preview && !hasApp) {\n\t\tlet templates = FALLBACK_TEMPLATES;\n\t\ttry {\n\t\t\tconst fetched = await fetchTemplates();\n\t\t\tif (fetched && fetched.length > 0) templates = fetched;\n\t\t} catch {}\n\n\t\tconst templateResult = await selectTemplate(\n\t\t\ttemplates,\n\t\t\t\"No application detected. Would you like to scaffold a new project from a template?\",\n\t\t);\n\t\tif (isCancel(templateResult)) {\n\t\t\toutro(\"Setup cancelled.\");\n\t\t\treturn;\n\t\t}\n\t\tif (templateResult !== \"none\") {\n\t\t\tselectedTemplate =\n\t\t\t\ttemplates.find((t) => t.id === templateResult) ?? null;\n\t\t\tif (selectedTemplate) {\n\t\t\t\tselectedFeatures = selectedTemplate.requires;\n\t\t\t\tconst bootstrapS = spinner();\n\t\t\t\tbootstrapS.start(\n\t\t\t\t\t`Scaffolding project from template \"${selectedTemplate.title}\"...`,\n\t\t\t\t);\n\t\t\t\ttry {\n\t\t\t\t\tawait scaffoldTemplate(selectedTemplate, \".\", {\n\t\t\t\t\t\tonWarn: (message) => log.warn(message),\n\t\t\t\t\t});\n\t\t\t\t\tbootstrapS.stop(\n\t\t\t\t\t\tdim(\n\t\t\t\t\t\t\t`Scaffolded project from \"${selectedTemplate.title}\" ✓`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconst msg =\n\t\t\t\t\t\terr instanceof Error ? err.message : \"Unknown error\";\n\t\t\t\t\tbootstrapS.stop(\"Failed to scaffold project\");\n\t\t\t\t\tlog.error(msg);\n\t\t\t\t\toutro(\"Setup failed.\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// For brownfield flows (existing app), ask which features to enable\n\tif (!selectedTemplate && hasApp) {\n\t\tconst featuresResult = await select({\n\t\t\tmessage:\n\t\t\t\t\"Which Neon features would you like to enable for this project?\",\n\t\t\toptions: [\n\t\t\t\t{ value: \"database\", label: \"Database\" },\n\t\t\t\t{\n\t\t\t\t\tvalue: \"database,auth\",\n\t\t\t\t\tlabel: \"Database + Neon Auth (adds authentication via Neon)\",\n\t\t\t\t},\n\t\t\t],\n\t\t\tinitialValue: \"database\",\n\t\t});\n\t\tif (isCancel(featuresResult)) {\n\t\t\toutro(\"Setup cancelled.\");\n\t\t\treturn;\n\t\t}\n\t\tselectedFeatures = (featuresResult as string).split(\n\t\t\t\",\",\n\t\t) as NeonFeature[];\n\t}\n\n\t// Write _init metadata to .neon\n\tif (selectedFeatures.length > 0) {\n\t\tconst neonPath = resolve(process.cwd(), \".neon\");\n\t\tlet existing: Record<string, unknown> = {};\n\t\tif (existsSync(neonPath)) {\n\t\t\ttry {\n\t\t\t\texisting = JSON.parse(readFileSync(neonPath, \"utf-8\"));\n\t\t\t} catch {}\n\t\t}\n\t\texisting._init = { features: selectedFeatures };\n\t\twriteFileSync(neonPath, `${JSON.stringify(existing, null, 2)}\\n`);\n\t}\n\n\tconst mcpAlready = inspection.mcpConfigured === true;\n\t// If we bootstrapped, skills come from the template\n\tconst skillsAlready =\n\t\tinspection.skillsInstalled === true || selectedTemplate !== null;\n\tconst hasNeonConnection = inspection.connectionString === true;\n\tlet needsMcp = !mcpAlready;\n\tconst needsSkills = !skillsAlready;\n\tconst needsInstall = needsMcp || needsSkills;\n\n\t// Check if .neon context file exists\n\tconst neonContextPath = resolve(process.cwd(), \".neon\");\n\tconst hasNeonContext =\n\t\texistsSync(neonContextPath) &&\n\t\t(() => {\n\t\t\ttry {\n\t\t\t\tconst content = JSON.parse(\n\t\t\t\t\treadFileSync(neonContextPath, \"utf-8\"),\n\t\t\t\t);\n\t\t\t\treturn !!content.projectId;\n\t\t\t} catch {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t})();\n\n\t// Check if Neon Auth is configured\n\tconst hasNeonAuth = (() => {\n\t\tfor (const envFile of [\".env\", \".env.local\"]) {\n\t\t\tconst envPath = resolve(process.cwd(), envFile);\n\t\t\tif (existsSync(envPath)) {\n\t\t\t\ttry {\n\t\t\t\t\tconst content = readFileSync(envPath, \"utf-8\");\n\t\t\t\t\tif (/^NEON_AUTH_/m.test(content)) return true;\n\t\t\t\t} catch {}\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t})();\n\n\t// Check if extension is installed for the detected editor\n\tlet extensionAlready = false;\n\tif (detectedEditor && usesExtension(detectedEditor)) {\n\t\textensionAlready = await isExtensionInstalled(detectedEditor);\n\t}\n\n\t// If tooling + database are configured, check if there's anything left to do\n\tif (mcpAlready && skillsAlready && hasNeonConnection && hasNeonContext) {\n\t\tlog.step(\n\t\t\tdim(\n\t\t\t\t`Neon MCP server already configured (${inspection.mcpScope || \"detected\"}) ✓`,\n\t\t\t),\n\t\t);\n\t\tlog.step(\n\t\t\tdim(\n\t\t\t\t`Neon agent skills already installed (${inspection.skillsScope || \"detected\"}) ✓`,\n\t\t\t),\n\t\t);\n\t\tif (extensionAlready)\n\t\t\tlog.step(dim(\"Neon editor extension installed ✓\"));\n\t\tlog.step(dim(\"Neon database connected ✓\"));\n\n\t\tif (hasNeonAuth) {\n\t\t\tlog.step(dim(\"Neon Auth configured ✓\"));\n\t\t\toutro(\n\t\t\t\tdim(\n\t\t\t\t\t\"Your project is fully configured with Neon. Nothing to do.\",\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\t// Neon Auth not configured — ask if they want it\n\t\tconst authResult = await select({\n\t\t\tmessage:\n\t\t\t\t\"Would you like to set up Neon Auth for user authentication?\",\n\t\t\toptions: [\n\t\t\t\t{ value: \"yes\", label: \"Yes, set up Neon Auth\" },\n\t\t\t\t{ value: \"no\", label: \"No, skip for now\" },\n\t\t\t],\n\t\t\tinitialValue: \"no\",\n\t\t});\n\n\t\tif (isCancel(authResult) || authResult === \"no\") {\n\t\t\toutro(\n\t\t\t\tdim(\n\t\t\t\t\t`Your project is configured with Neon. You can set up Neon Auth later by having your agent run: neonctl init --agent --data '{\"step\":\"neon-auth\"}'`,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\t// Read .neon for project context\n\t\tlet projectId: string | null = null;\n\t\ttry {\n\t\t\tconst neonCtx = JSON.parse(readFileSync(neonContextPath, \"utf-8\"));\n\t\t\tprojectId = neonCtx.projectId ?? null;\n\t\t} catch {}\n\n\t\tlog.step(\"Next steps\");\n\t\tconst promptLines = [\"Set up Neon Auth for this project.\"];\n\t\tif (projectId) promptLines.push(`Project ID: ${projectId}.`);\n\t\tlog.message(dim(\"Copy the following into your agent chat:\"));\n\t\tlog.message(\n\t\t\tpromptLines.map((line) => bold(neonGreenFn(line))).join(\"\\n\"),\n\t\t);\n\t\toutro(dim(\"Have feedback? Email us at feedback@neon.tech\"));\n\t\treturn;\n\t}\n\n\t// Log what's already in place\n\tif (mcpAlready)\n\t\tlog.step(\n\t\t\tdim(\n\t\t\t\t`Neon MCP server already configured (${inspection.mcpScope || \"detected\"}) ✓`,\n\t\t\t),\n\t\t);\n\tif (skillsAlready)\n\t\tlog.step(\n\t\t\tdim(\n\t\t\t\t`Neon agent skills already installed (${inspection.skillsScope || \"detected\"}) ✓`,\n\t\t\t),\n\t\t);\n\n\t// -----------------------------------------------------------------------\n\t// Step 3–5: Install what's missing (skip entirely if everything is configured)\n\t// -----------------------------------------------------------------------\n\tif (needsInstall) {\n\t\tconst homeDir = process.env.HOME || process.env.USERPROFILE;\n\t\tif (!homeDir) {\n\t\t\tlog.error(\"Could not determine home directory.\");\n\t\t\toutro(\"Setup failed.\");\n\t\t\treturn;\n\t\t}\n\n\t\tlet selectedEditors: Editor[];\n\t\tif (detectedEditor) {\n\t\t\tselectedEditors = [detectedEditor];\n\t\t} else {\n\t\t\tconst availableEditors = await detectAvailableEditors(homeDir);\n\t\t\tconst editorResponse = await multiselect({\n\t\t\t\tmessage: \"Which editor(s) would you like to configure?\",\n\t\t\t\toptions: ALL_CONFIGURABLE_AGENTS.map((agent) => ({\n\t\t\t\t\tvalue: agent.editor,\n\t\t\t\t\tlabel: agent.editor,\n\t\t\t\t\thint: agent.hint,\n\t\t\t\t})),\n\t\t\t\tinitialValues: availableEditors,\n\t\t\t\trequired: true,\n\t\t\t});\n\t\t\tif (isCancel(editorResponse)) {\n\t\t\t\toutro(\"Setup cancelled.\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tselectedEditors = editorResponse as Editor[];\n\t\t\tif (selectedEditors.length === 0) {\n\t\t\t\tlog.warn(\"No editors selected.\");\n\t\t\t\toutro(\"Setup cancelled.\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// Check extension status\n\t\tconst vscodeEditors = selectedEditors.filter(usesExtension);\n\t\tlet extensionAlreadyInstalled = false;\n\t\tif (vscodeEditors.length > 0) {\n\t\t\tconst checks = await Promise.all(\n\t\t\t\tvscodeEditors.map((e) => isExtensionInstalled(e)),\n\t\t\t);\n\t\t\textensionAlreadyInstalled = checks.every(Boolean);\n\t\t\tif (extensionAlreadyInstalled) {\n\t\t\t\tlog.step(dim(\"Neon editor extension already installed ✓\"));\n\t\t\t}\n\t\t}\n\t\tlet doInstallExtension =\n\t\t\tvscodeEditors.length > 0 && !extensionAlreadyInstalled;\n\n\t\t// Build hint showing only what needs installing\n\t\tconst hintParts: string[] = [];\n\t\tif (needsMcp) hintParts.push(\"MCP server (global)\");\n\t\tif (needsSkills) hintParts.push(\"agent skills (project)\");\n\t\tif (doInstallExtension) hintParts.push(\"editor extension\");\n\n\t\t// Installation preferences\n\t\tlet mcpScope: \"global\" | \"project\" | \"none\" = \"global\";\n\t\tlet skillsScope: \"global\" | \"project\" = \"project\";\n\n\t\tlet modeResult: string;\n\t\twhile (true) {\n\t\t\tconst editorName = selectedEditors.join(\", \");\n\t\t\tconst result = await select({\n\t\t\t\tmessage: `Configure ${editorName} for Neon:`,\n\t\t\t\toptions: [\n\t\t\t\t\t{\n\t\t\t\t\t\tvalue: \"defaults\",\n\t\t\t\t\t\tlabel: \"Install with defaults\",\n\t\t\t\t\t\thint: hintParts.join(\", \"),\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tvalue: \"customize\",\n\t\t\t\t\t\tlabel: \"Customize installation\",\n\t\t\t\t\t\thint: \"choose scopes and options\",\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tvalue: \"change_editor\",\n\t\t\t\t\t\tlabel: \"Configure a different editor\",\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tinitialValue: \"defaults\",\n\t\t\t});\n\n\t\t\tif (isCancel(result)) {\n\t\t\t\toutro(\"Setup cancelled.\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (result === \"change_editor\") {\n\t\t\t\tconst availableEditors = await detectAvailableEditors(homeDir);\n\t\t\t\tconst editorResponse = await multiselect({\n\t\t\t\t\tmessage: \"Which editor(s) would you like to configure?\",\n\t\t\t\t\toptions: ALL_CONFIGURABLE_AGENTS.map((agent) => ({\n\t\t\t\t\t\tvalue: agent.editor,\n\t\t\t\t\t\tlabel: agent.editor,\n\t\t\t\t\t\thint: agent.hint,\n\t\t\t\t\t})),\n\t\t\t\t\tinitialValues: availableEditors,\n\t\t\t\t\trequired: true,\n\t\t\t\t});\n\t\t\t\tif (isCancel(editorResponse)) {\n\t\t\t\t\toutro(\"Setup cancelled.\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tselectedEditors = editorResponse as Editor[];\n\t\t\t\tif (selectedEditors.length === 0) {\n\t\t\t\t\toutro(\"Setup cancelled.\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tmodeResult = result as string;\n\t\t\tbreak;\n\t\t}\n\n\t\tif (modeResult === \"customize\") {\n\t\t\tif (needsMcp) {\n\t\t\t\tconst scopeResult = await select({\n\t\t\t\t\tmessage: \"Where should the Neon MCP server be configured?\",\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tvalue: \"global\",\n\t\t\t\t\t\t\tlabel: \"Global (available in all projects)\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tvalue: \"project\",\n\t\t\t\t\t\t\tlabel: \"Project-level (this project only)\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tvalue: \"none\",\n\t\t\t\t\t\t\tlabel: \"Skip — do not install the MCP server\",\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t});\n\t\t\t\tif (isCancel(scopeResult)) {\n\t\t\t\t\toutro(\"Setup cancelled.\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tmcpScope = scopeResult as \"global\" | \"project\" | \"none\";\n\t\t\t\tif (mcpScope === \"none\") needsMcp = false;\n\t\t\t}\n\n\t\t\tif (needsSkills) {\n\t\t\t\tconst skillsScopeResult = await select({\n\t\t\t\t\tmessage: \"Where should Neon agent skills be installed?\",\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tvalue: \"global\",\n\t\t\t\t\t\t\tlabel: \"Global (available in all projects)\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tvalue: \"project\",\n\t\t\t\t\t\t\tlabel: \"Project-level (this project only)\",\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tinitialValue: \"project\",\n\t\t\t\t});\n\t\t\t\tif (isCancel(skillsScopeResult)) {\n\t\t\t\t\toutro(\"Setup cancelled.\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tskillsScope = skillsScopeResult as \"global\" | \"project\";\n\t\t\t}\n\n\t\t\tif (doInstallExtension) {\n\t\t\t\tconst extResult = await confirm({\n\t\t\t\t\tmessage: `Install the Neon extension for ${vscodeEditors.join(\", \")}?`,\n\t\t\t\t});\n\t\t\t\tif (isCancel(extResult)) {\n\t\t\t\t\toutro(\"Setup cancelled.\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tdoInstallExtension = extResult;\n\t\t\t}\n\t\t}\n\n\t\t// Auth check before install\n\t\tconst installAuthed = await isAuthenticated();\n\t\tif (!installAuthed) {\n\t\t\tconst authS = spinner();\n\t\t\tauthS.start(\"Authenticating with Neon...\");\n\t\t\tconst authSuccess = await ensureNeonctlAuth();\n\t\t\tif (!authSuccess) {\n\t\t\t\tauthS.stop(\"Authentication failed.\");\n\t\t\t\toutro(\"Run neon-init again after signing in.\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tauthS.stop(\"Authenticated.\");\n\t\t}\n\n\t\t// Ensure neonctl CLI is installed and up to date\n\t\tconst nctlS = spinner();\n\t\tnctlS.start(\"Checking neonctl CLI...\");\n\t\tconst nctlResult = await ensureNeonctl();\n\t\tswitch (nctlResult.status) {\n\t\t\tcase \"already_current\":\n\t\t\t\tnctlS.stop(\n\t\t\t\t\tdim(`neonctl CLI is up to date (v${nctlResult.version}) ✓`),\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"installed\":\n\t\t\t\tnctlS.stop(\n\t\t\t\t\tdim(`Installed neonctl CLI (v${nctlResult.version}) ✓`),\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"updated\":\n\t\t\t\tnctlS.stop(\n\t\t\t\t\tdim(`Updated neonctl CLI to v${nctlResult.version} ✓`),\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"failed\":\n\t\t\t\tnctlS.stop(\"Failed to install neonctl CLI\");\n\t\t\t\tlog.warn(\n\t\t\t\t\t\"neonctl could not be installed automatically. The setup will continue using npx.\",\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t}\n\n\t\t// Install only what's missing\n\t\tfor (const editor of selectedEditors) {\n\t\t\tif (needsMcp) {\n\t\t\t\tconst mcpAgentId = getAddMcpAgentId(editor);\n\t\t\t\tconst mcpArgs = [\n\t\t\t\t\t\"-y\",\n\t\t\t\t\t\"add-mcp\",\n\t\t\t\t\t\"https://mcp.neon.tech/mcp\",\n\t\t\t\t\t\"-n\",\n\t\t\t\t\t\"Neon\",\n\t\t\t\t\t\"-y\",\n\t\t\t\t\t\"-a\",\n\t\t\t\t\tmcpAgentId,\n\t\t\t\t];\n\t\t\t\tif (mcpScope === \"global\") mcpArgs.splice(5, 0, \"-g\");\n\n\t\t\t\tconst mcpS = spinner();\n\t\t\t\tmcpS.start(`Installing Neon MCP server for ${editor}...`);\n\t\t\t\ttry {\n\t\t\t\t\tawait execa(\"npx\", mcpArgs, {\n\t\t\t\t\t\tstdio: \"pipe\",\n\t\t\t\t\t\ttimeout: 60000,\n\t\t\t\t\t});\n\t\t\t\t\tmcpS.stop(\n\t\t\t\t\t\tdim(\n\t\t\t\t\t\t\t`Neon MCP server configured for ${editor} (${mcpScope}) ✓`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconst msg =\n\t\t\t\t\t\terr instanceof Error ? err.message : \"Unknown error\";\n\t\t\t\t\tmcpS.stop(`Failed to configure MCP server for ${editor}`);\n\t\t\t\t\tlog.error(msg);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (needsSkills) {\n\t\t\t\tawait installAgentSkills([editor], {\n\t\t\t\t\tscope: skillsScope,\n\t\t\t\t\tpreview: options.preview,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (doInstallExtension && usesExtension(editor)) {\n\t\t\t\tconst extS = spinner();\n\t\t\t\textS.start(`Installing Neon extension for ${editor}...`);\n\t\t\t\tconst extOk = await installExtension(editor);\n\t\t\t\tif (extOk) {\n\t\t\t\t\textS.stop(dim(`Neon extension installed for ${editor} ✓`));\n\t\t\t\t} else {\n\t\t\t\t\textS.stop(\n\t\t\t\t\t\t`Extension install failed — install manually from the extensions panel.`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Ensure all required skills are present (fills in any missing ones).\n\t// detectAgent() returns null in a human terminal (TTY), so fall back\n\t// to IDE detection which works regardless of TTY.\n\tconst ide = detectIde();\n\tconst agentForSkills =\n\t\tdetectAgent() ??\n\t\t(ide === \"Cursor\"\n\t\t\t? \"cursor\"\n\t\t\t: ide === \"VS Code\"\n\t\t\t\t? \"vscode\"\n\t\t\t\t: ide === \"Windsurf\"\n\t\t\t\t\t? \"windsurf\"\n\t\t\t\t\t: null);\n\tif (agentForSkills) {\n\t\tconst detectedSkillsScope =\n\t\t\tinspection.skillsScope === \"global\" ? \"global\" : undefined;\n\t\tawait ensureSkillsUpToDate(\n\t\t\tagentForSkills,\n\t\t\tdetectedSkillsScope,\n\t\t\toptions.preview,\n\t\t);\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Step 6: Done — build prompt for the agent to continue\n\t// -----------------------------------------------------------------------\n\n\t// Build the getting-started data payload (same as agent mode)\n\tconst gettingStartedData: Record<string, unknown> = {};\n\tif (hasNeonConnection) gettingStartedData.hasConnectionString = true;\n\tif (inspection.framework && inspection.framework !== \"none\")\n\t\tgettingStartedData.framework = inspection.framework;\n\tif (inspection.orm && inspection.orm !== \"none\")\n\t\tgettingStartedData.orm = inspection.orm;\n\tif (inspection.migrationTool && inspection.migrationTool !== \"none\")\n\t\tgettingStartedData.migrationTool = inspection.migrationTool;\n\tif (inspection.migrationDir && inspection.migrationDir !== \"none\")\n\t\tgettingStartedData.migrationDir = inspection.migrationDir;\n\tif (selectedFeatures.length > 0)\n\t\tgettingStartedData.features = selectedFeatures;\n\tif (options.preview) gettingStartedData.preview = true;\n\n\t// Build a prompt for the user to paste into their agent chat\n\tconst cmd = `neonctl init --agent --data '${JSON.stringify({ step: \"getting-started\", ...gettingStartedData })}'`;\n\t// Account for clack's \"│ \" prefix (3 chars) when wrapping\n\tconst cols = (process.stdout.columns || 80) - 3;\n\tconst promptText = `To finish setting up Neon using Neon's agent-guided onboarding experience, have your agent run this shell command: ${cmd}`;\n\n\tlog.step(\"Next steps\");\n\tlog.message(dim(\"Copy the following into your agent chat:\"));\n\tlog.message(\n\t\twordWrap(promptText, cols)\n\t\t\t.split(\"\\n\")\n\t\t\t.map((line) => bold(neonGreenFn(line)))\n\t\t\t.join(\"\\n\"),\n\t);\n\toutro(dim(\"Have feedback? Email us at feedback@neon.tech\"));\n}\n\nfunction agentIdToEditor(agentId: string): Editor | null {\n\tswitch (agentId) {\n\t\tcase \"cursor\":\n\t\t\treturn \"Cursor\";\n\t\tcase \"vscode\":\n\t\t\treturn \"VS Code\";\n\t\tcase \"claude-code\":\n\t\t\treturn \"Claude CLI\";\n\t\tcase \"windsurf\":\n\t\t\t// Windsurf not in Editor type yet — fall back to prompt\n\t\t\treturn null;\n\t\tcase \"codex\":\n\t\t\treturn \"Codex\";\n\t\tcase \"cline\":\n\t\t\treturn \"Cline\";\n\t\tdefault:\n\t\t\treturn null;\n\t}\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"interactive.js","names":[],"sources":["../src/interactive.ts"],"sourcesContent":["/**\n * Interactive v2 CLI — purpose-built guided flow for humans.\n * Uses the same underlying install functions but with a clean clack-based UX.\n */\n\nimport { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { SelectPrompt } from \"@clack/core\";\nimport {\n\tconfirm,\n\tisCancel,\n\tlog,\n\tmultiselect,\n\toutro,\n\tselect,\n\tspinner,\n} from \"@clack/prompts\";\nimport { execa } from \"execa\";\nimport { bold, dim, gray, italic } from \"yoctocolors\";\nimport { ALL_CONFIGURABLE_AGENTS, getAddMcpAgentId } from \"./lib/agents.js\";\nimport { ensureNeonctlAuth, isAuthenticated } from \"./lib/auth.js\";\nimport {\n\ttype BootstrapTemplate,\n\tFALLBACK_TEMPLATES,\n\tfetchTemplates,\n\ttype NeonFeature,\n\tscaffoldTemplate,\n} from \"./lib/bootstrap.js\";\nimport { detectAgent, detectIde } from \"./lib/detect-agent.js\";\nimport { detectAvailableEditors } from \"./lib/editors.js\";\nimport {\n\tinstallExtension,\n\tisExtensionInstalled,\n\tusesExtension,\n} from \"./lib/extension.js\";\nimport { inspectProject } from \"./lib/inspect.js\";\nimport { ensureNeonctl } from \"./lib/neonctl.js\";\nimport { ensureSkillsUpToDate, installAgentSkills } from \"./lib/skills.js\";\nimport type { Editor } from \"./lib/types.js\";\n\nfunction wordWrap(text: string, width: number): string {\n\treturn text\n\t\t.split(\"\\n\")\n\t\t.map((line) => {\n\t\t\tif (line.length <= width) return line;\n\t\t\tconst words = line.split(\" \");\n\t\t\tconst lines: string[] = [];\n\t\t\tlet current = \"\";\n\t\t\tfor (const word of words) {\n\t\t\t\tif (\n\t\t\t\t\tcurrent.length + word.length + 1 > width &&\n\t\t\t\t\tcurrent.length > 0\n\t\t\t\t) {\n\t\t\t\t\tlines.push(current);\n\t\t\t\t\tcurrent = word;\n\t\t\t\t} else {\n\t\t\t\t\tcurrent = current.length > 0 ? `${current} ${word}` : word;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (current.length > 0) lines.push(current);\n\t\t\treturn lines.join(\"\\n\");\n\t\t})\n\t\t.join(\"\\n\");\n}\n\n// Patch picocolors (used by @clack/prompts) to use Neon green instead of cyan/magenta.\n// clack hardcodes picocolors.cyan() with no theme API, so this is the least invasive override.\nimport picocolors from \"picocolors\";\n\nconst neonGreenFn = (s: string) => `\\x1b[38;2;75;181;120m${s}\\x1b[39m`;\nconst originalCyan = picocolors.cyan;\nconst originalMagenta = picocolors.magenta;\n\nfunction patchClackColors(): () => void {\n\tconst pc = picocolors as unknown as Record<string, unknown>;\n\tpc.cyan = neonGreenFn;\n\tpc.magenta = neonGreenFn;\n\treturn () => {\n\t\tpc.cyan = originalCyan;\n\t\tpc.magenta = originalMagenta;\n\t};\n}\n\n// clack box-drawing glyphs, mirrored from @clack/prompts so our custom\n// template picker lines up with every other step in the flow.\nconst S_BAR = \"│\";\nconst S_BAR_END = \"└\";\nconst S_STEP_ACTIVE = \"◆\";\nconst S_STEP_SUBMIT = \"◇\";\nconst S_STEP_CANCEL = \"■\";\nconst S_RADIO_ACTIVE = \"●\";\nconst S_RADIO_INACTIVE = \"○\";\n\ninterface TemplateOption {\n\tvalue: string;\n\tlabel: string;\n\ttools?: string[];\n\tdescription?: string;\n}\n\nconst SENTINEL_NONE = \"none\";\n\n/**\n * Bespoke template picker built on @clack/core's `SelectPrompt`.\n *\n * The stock `@clack/prompts` `select` can only render an option on a single\n * line (title + a parenthesized hint on the focused row), which can't express\n * what we want here: a clean title-only list, and a focused row that expands to\n * `Title (tools)` with the description on its own italic line beneath. Driving\n * the core prompt directly lets us own the frame, so we emit a second\n * gutter-aligned line for the active option only.\n */\nasync function selectTemplate(\n\ttemplates: BootstrapTemplate[],\n\tmessage: string,\n): Promise<string | symbol> {\n\tconst options: TemplateOption[] = [\n\t\t...templates.map((t) => ({\n\t\t\tvalue: t.id,\n\t\t\tlabel: t.title,\n\t\t\ttools: t.tools,\n\t\t\tdescription: t.description,\n\t\t})),\n\t\t{\n\t\t\tvalue: SENTINEL_NONE,\n\t\t\tlabel: \"No thanks — continue without scaffolding\",\n\t\t},\n\t];\n\n\tconst green = neonGreenFn;\n\t// Title sits at column 6 (\"│ ● \"), so wrapped description lines indent four\n\t// spaces past the gutter to line up under it.\n\tconst descIndent = \" \";\n\tconst descWidth = Math.max(24, (process.stdout.columns || 80) - 8);\n\n\tconst renderActive = (option: TemplateOption): string => {\n\t\tconst tools =\n\t\t\toption.tools && option.tools.length > 0\n\t\t\t\t? ` ${dim(`(${option.tools.join(\", \")})`)}`\n\t\t\t\t: \"\";\n\t\tconst head = `${green(S_RADIO_ACTIVE)} ${option.label}${tools}`;\n\t\tif (!option.description) return head;\n\t\tconst body = wordWrap(option.description, descWidth)\n\t\t\t.split(\"\\n\")\n\t\t\t.map((line) => `${green(S_BAR)}${descIndent}${italic(dim(line))}`)\n\t\t\t.join(\"\\n\");\n\t\treturn `${head}\\n${body}`;\n\t};\n\n\tconst prompt = new SelectPrompt<TemplateOption>({\n\t\toptions,\n\t\tinitialValue: options[0]?.value,\n\t\trender() {\n\t\t\tconst active = this.options[this.cursor];\n\t\t\tconst heading = (symbol: string) =>\n\t\t\t\t`${gray(S_BAR)}\\n${symbol} ${message}\\n`;\n\n\t\t\tif (this.state === \"submit\") {\n\t\t\t\treturn `${heading(green(S_STEP_SUBMIT))}${gray(S_BAR)} ${dim(\n\t\t\t\t\tactive?.label ?? \"\",\n\t\t\t\t)}`;\n\t\t\t}\n\t\t\tif (this.state === \"cancel\") {\n\t\t\t\treturn `${heading(green(S_STEP_CANCEL))}${gray(S_BAR)} ${dim(\n\t\t\t\t\tactive?.label ?? \"\",\n\t\t\t\t)}\\n${gray(S_BAR)}`;\n\t\t\t}\n\n\t\t\tconst body = this.options\n\t\t\t\t.map((option) =>\n\t\t\t\t\toption === active\n\t\t\t\t\t\t? renderActive(option)\n\t\t\t\t\t\t: `${dim(S_RADIO_INACTIVE)} ${dim(option.label)}`,\n\t\t\t\t)\n\t\t\t\t.join(`\\n${green(S_BAR)} `);\n\t\t\treturn `${heading(green(S_STEP_ACTIVE))}${green(S_BAR)} ${body}\\n${green(\n\t\t\t\tS_BAR_END,\n\t\t\t)}\\n`;\n\t\t},\n\t});\n\n\treturn prompt.prompt();\n}\n\nexport interface InteractiveInitOptions {\n\tpreview?: boolean;\n}\n\nexport async function interactiveInit(\n\toptions: InteractiveInitOptions = {},\n): Promise<void> {\n\tconst restoreColors = patchClackColors();\n\ttry {\n\t\tawait interactiveInitInner(options);\n\t} finally {\n\t\trestoreColors();\n\t}\n}\n\nasync function interactiveInitInner(\n\toptions: InteractiveInitOptions,\n): Promise<void> {\n\tconsole.log();\n\tconsole.log(\n\t\t\"\\x1b[38;2;75;181;120m\" +\n\t\t\t[\n\t\t\t\t\" ██╗ ██╗██████╗ ██████╗ ██╗ ██╗\",\n\t\t\t\t\" ███╗ ██║██╔═══╝ ██╔═══██╗███╗ ██║\",\n\t\t\t\t\" ████╗██║██████╗ ██║ ██║████╗██║\",\n\t\t\t\t\" ██╔████║██╔═══╝ ██║ ██║██╔████║\",\n\t\t\t\t\" ██║╚███║██████╗ ╚██████╔╝██║╚███║\",\n\t\t\t\t\" ╚═╝ ╚══╝╚═════╝ ╚═════╝ ╚═╝ ╚══╝\",\n\t\t\t].join(\"\\n\") +\n\t\t\t\"\\x1b[0m\",\n\t);\n\tconsole.log(\n\t\tdim(\n\t\t\twordWrap(\n\t\t\t\t\"\\nLet's get your project set up with Neon. We'll install the MCP server, agent skills, and IDE extension, then connect your app to a database.\\n\",\n\t\t\t\tprocess.stdout.columns || 80,\n\t\t\t),\n\t\t),\n\t);\n\n\tconst detectedAgentId = detectAgent();\n\tconst detectedEditor = detectedAgentId\n\t\t? agentIdToEditor(detectedAgentId)\n\t\t: null;\n\n\t// -----------------------------------------------------------------------\n\t// Step 1: Inspect what's already in place\n\t// -----------------------------------------------------------------------\n\tconst inspectSpinner = spinner();\n\tinspectSpinner.start(\"Checking existing configuration...\");\n\tconst inspection = await inspectProject([\n\t\t{ id: \"has_app\", description: \"\", lookFor: [] },\n\t\t{ id: \"mcp_server\", description: \"\", lookFor: [] },\n\t\t{ id: \"skills\", description: \"\", lookFor: [] },\n\t\t{ id: \"connection_string\", description: \"\", lookFor: [] },\n\t\t{ id: \"project_stack\", description: \"\", lookFor: [] },\n\t\t{ id: \"migrations\", description: \"\", lookFor: [] },\n\t\t{ id: \"ide_type\", description: \"\", lookFor: [] },\n\t]);\n\tinspectSpinner.stop(dim(\"Configuration checked ✓\"));\n\n\tconst hasApp = inspection.hasApp === true;\n\tlet selectedFeatures: NeonFeature[] = [];\n\tlet selectedTemplate: BootstrapTemplate | null = null;\n\n\t// Preview mode: bootstrap from template if no app detected\n\tif (options.preview && !hasApp) {\n\t\tlet templates = FALLBACK_TEMPLATES;\n\t\ttry {\n\t\t\tconst fetched = await fetchTemplates();\n\t\t\tif (fetched && fetched.length > 0) templates = fetched;\n\t\t} catch {}\n\n\t\tconst templateResult = await selectTemplate(\n\t\t\ttemplates,\n\t\t\t\"No application detected. Would you like to scaffold a new project from a template?\",\n\t\t);\n\t\tif (isCancel(templateResult)) {\n\t\t\toutro(\"Setup cancelled.\");\n\t\t\treturn;\n\t\t}\n\t\tif (templateResult !== \"none\") {\n\t\t\tselectedTemplate =\n\t\t\t\ttemplates.find((t) => t.id === templateResult) ?? null;\n\t\t\tif (selectedTemplate) {\n\t\t\t\tselectedFeatures = selectedTemplate.requires;\n\t\t\t\tconst bootstrapS = spinner();\n\t\t\t\tbootstrapS.start(\n\t\t\t\t\t`Scaffolding project from template \"${selectedTemplate.title}\"...`,\n\t\t\t\t);\n\t\t\t\ttry {\n\t\t\t\t\tawait scaffoldTemplate(selectedTemplate, \".\", {\n\t\t\t\t\t\tonWarn: (message) => log.warn(message),\n\t\t\t\t\t});\n\t\t\t\t\tbootstrapS.stop(\n\t\t\t\t\t\tdim(\n\t\t\t\t\t\t\t`Scaffolded project from \"${selectedTemplate.title}\" ✓`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconst msg =\n\t\t\t\t\t\terr instanceof Error ? err.message : \"Unknown error\";\n\t\t\t\t\tbootstrapS.stop(\"Failed to scaffold project\");\n\t\t\t\t\tlog.error(msg);\n\t\t\t\t\toutro(\"Setup failed.\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// For brownfield flows (existing app), ask which features to enable\n\tif (!selectedTemplate && hasApp) {\n\t\tconst featuresResult = await select({\n\t\t\tmessage:\n\t\t\t\t\"Which Neon features would you like to enable for this project?\",\n\t\t\toptions: [\n\t\t\t\t{ value: \"database\", label: \"Database\" },\n\t\t\t\t{\n\t\t\t\t\tvalue: \"database,auth\",\n\t\t\t\t\tlabel: \"Database + Neon Auth (adds authentication via Neon)\",\n\t\t\t\t},\n\t\t\t],\n\t\t\tinitialValue: \"database\",\n\t\t});\n\t\tif (isCancel(featuresResult)) {\n\t\t\toutro(\"Setup cancelled.\");\n\t\t\treturn;\n\t\t}\n\t\tselectedFeatures = (featuresResult as string).split(\n\t\t\t\",\",\n\t\t) as NeonFeature[];\n\t}\n\n\t// Write _init metadata to .neon\n\tif (selectedFeatures.length > 0) {\n\t\tconst neonPath = resolve(process.cwd(), \".neon\");\n\t\tlet existing: Record<string, unknown> = {};\n\t\tif (existsSync(neonPath)) {\n\t\t\ttry {\n\t\t\t\texisting = JSON.parse(readFileSync(neonPath, \"utf-8\"));\n\t\t\t} catch {}\n\t\t}\n\t\texisting._init = { features: selectedFeatures };\n\t\twriteFileSync(neonPath, `${JSON.stringify(existing, null, 2)}\\n`);\n\t}\n\n\tconst mcpAlready = inspection.mcpConfigured === true;\n\t// If we bootstrapped, skills come from the template\n\tconst skillsAlready =\n\t\tinspection.skillsInstalled === true || selectedTemplate !== null;\n\tconst hasNeonConnection = inspection.connectionString === true;\n\tlet needsMcp = !mcpAlready;\n\tconst needsSkills = !skillsAlready;\n\tconst needsInstall = needsMcp || needsSkills;\n\n\t// Check if .neon context file exists\n\tconst neonContextPath = resolve(process.cwd(), \".neon\");\n\tconst hasNeonContext =\n\t\texistsSync(neonContextPath) &&\n\t\t(() => {\n\t\t\ttry {\n\t\t\t\tconst content = JSON.parse(\n\t\t\t\t\treadFileSync(neonContextPath, \"utf-8\"),\n\t\t\t\t);\n\t\t\t\treturn !!content.projectId;\n\t\t\t} catch {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t})();\n\n\t// Check if Neon Auth is configured\n\tconst hasNeonAuth = (() => {\n\t\tfor (const envFile of [\".env\", \".env.local\"]) {\n\t\t\tconst envPath = resolve(process.cwd(), envFile);\n\t\t\tif (existsSync(envPath)) {\n\t\t\t\ttry {\n\t\t\t\t\tconst content = readFileSync(envPath, \"utf-8\");\n\t\t\t\t\tif (/^NEON_AUTH_/m.test(content)) return true;\n\t\t\t\t} catch {}\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t})();\n\n\t// Check if extension is installed for the detected editor\n\tlet extensionAlready = false;\n\tif (detectedEditor && usesExtension(detectedEditor)) {\n\t\textensionAlready = await isExtensionInstalled(detectedEditor);\n\t}\n\n\t// If tooling + database are configured, check if there's anything left to do\n\tif (mcpAlready && skillsAlready && hasNeonConnection && hasNeonContext) {\n\t\tlog.step(\n\t\t\tdim(\n\t\t\t\t`Neon MCP server already configured (${inspection.mcpScope || \"detected\"}) ✓`,\n\t\t\t),\n\t\t);\n\t\tlog.step(\n\t\t\tdim(\n\t\t\t\t`Neon agent skills already installed (${inspection.skillsScope || \"detected\"}) ✓`,\n\t\t\t),\n\t\t);\n\t\tif (extensionAlready)\n\t\t\tlog.step(dim(\"Neon editor extension installed ✓\"));\n\t\tlog.step(dim(\"Neon database connected ✓\"));\n\n\t\tif (hasNeonAuth) {\n\t\t\tlog.step(dim(\"Neon Auth configured ✓\"));\n\t\t\toutro(\n\t\t\t\tdim(\n\t\t\t\t\t\"Your project is fully configured with Neon. Nothing to do.\",\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\t// Neon Auth not configured — ask if they want it\n\t\tconst authResult = await select({\n\t\t\tmessage:\n\t\t\t\t\"Would you like to set up Neon Auth for user authentication?\",\n\t\t\toptions: [\n\t\t\t\t{ value: \"yes\", label: \"Yes, set up Neon Auth\" },\n\t\t\t\t{ value: \"no\", label: \"No, skip for now\" },\n\t\t\t],\n\t\t\tinitialValue: \"no\",\n\t\t});\n\n\t\tif (isCancel(authResult) || authResult === \"no\") {\n\t\t\toutro(\n\t\t\t\tdim(\n\t\t\t\t\t`Your project is configured with Neon. You can set up Neon Auth later by having your agent run: neon init --agent --data '{\"step\":\"neon-auth\"}'`,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\t// Read .neon for project context\n\t\tlet projectId: string | null = null;\n\t\ttry {\n\t\t\tconst neonCtx = JSON.parse(readFileSync(neonContextPath, \"utf-8\"));\n\t\t\tprojectId = neonCtx.projectId ?? null;\n\t\t} catch {}\n\n\t\tlog.step(\"Next steps\");\n\t\tconst promptLines = [\"Set up Neon Auth for this project.\"];\n\t\tif (projectId) promptLines.push(`Project ID: ${projectId}.`);\n\t\tlog.message(dim(\"Copy the following into your agent chat:\"));\n\t\tlog.message(\n\t\t\tpromptLines.map((line) => bold(neonGreenFn(line))).join(\"\\n\"),\n\t\t);\n\t\toutro(dim(\"Have feedback? Email us at feedback@neon.tech\"));\n\t\treturn;\n\t}\n\n\t// Log what's already in place\n\tif (mcpAlready)\n\t\tlog.step(\n\t\t\tdim(\n\t\t\t\t`Neon MCP server already configured (${inspection.mcpScope || \"detected\"}) ✓`,\n\t\t\t),\n\t\t);\n\tif (skillsAlready)\n\t\tlog.step(\n\t\t\tdim(\n\t\t\t\t`Neon agent skills already installed (${inspection.skillsScope || \"detected\"}) ✓`,\n\t\t\t),\n\t\t);\n\n\t// -----------------------------------------------------------------------\n\t// Step 3–5: Install what's missing (skip entirely if everything is configured)\n\t// -----------------------------------------------------------------------\n\tif (needsInstall) {\n\t\tconst homeDir = process.env.HOME || process.env.USERPROFILE;\n\t\tif (!homeDir) {\n\t\t\tlog.error(\"Could not determine home directory.\");\n\t\t\toutro(\"Setup failed.\");\n\t\t\treturn;\n\t\t}\n\n\t\tlet selectedEditors: Editor[];\n\t\tif (detectedEditor) {\n\t\t\tselectedEditors = [detectedEditor];\n\t\t} else {\n\t\t\tconst availableEditors = await detectAvailableEditors(homeDir);\n\t\t\tconst editorResponse = await multiselect({\n\t\t\t\tmessage: \"Which editor(s) would you like to configure?\",\n\t\t\t\toptions: ALL_CONFIGURABLE_AGENTS.map((agent) => ({\n\t\t\t\t\tvalue: agent.editor,\n\t\t\t\t\tlabel: agent.editor,\n\t\t\t\t\thint: agent.hint,\n\t\t\t\t})),\n\t\t\t\tinitialValues: availableEditors,\n\t\t\t\trequired: true,\n\t\t\t});\n\t\t\tif (isCancel(editorResponse)) {\n\t\t\t\toutro(\"Setup cancelled.\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tselectedEditors = editorResponse as Editor[];\n\t\t\tif (selectedEditors.length === 0) {\n\t\t\t\tlog.warn(\"No editors selected.\");\n\t\t\t\toutro(\"Setup cancelled.\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// Check extension status\n\t\tconst vscodeEditors = selectedEditors.filter(usesExtension);\n\t\tlet extensionAlreadyInstalled = false;\n\t\tif (vscodeEditors.length > 0) {\n\t\t\tconst checks = await Promise.all(\n\t\t\t\tvscodeEditors.map((e) => isExtensionInstalled(e)),\n\t\t\t);\n\t\t\textensionAlreadyInstalled = checks.every(Boolean);\n\t\t\tif (extensionAlreadyInstalled) {\n\t\t\t\tlog.step(dim(\"Neon editor extension already installed ✓\"));\n\t\t\t}\n\t\t}\n\t\tlet doInstallExtension =\n\t\t\tvscodeEditors.length > 0 && !extensionAlreadyInstalled;\n\n\t\t// Build hint showing only what needs installing\n\t\tconst hintParts: string[] = [];\n\t\tif (needsMcp) hintParts.push(\"MCP server (global)\");\n\t\tif (needsSkills) hintParts.push(\"agent skills (project)\");\n\t\tif (doInstallExtension) hintParts.push(\"editor extension\");\n\n\t\t// Installation preferences\n\t\tlet mcpScope: \"global\" | \"project\" | \"none\" = \"global\";\n\t\tlet skillsScope: \"global\" | \"project\" = \"project\";\n\n\t\tlet modeResult: string;\n\t\twhile (true) {\n\t\t\tconst editorName = selectedEditors.join(\", \");\n\t\t\tconst result = await select({\n\t\t\t\tmessage: `Configure ${editorName} for Neon:`,\n\t\t\t\toptions: [\n\t\t\t\t\t{\n\t\t\t\t\t\tvalue: \"defaults\",\n\t\t\t\t\t\tlabel: \"Install with defaults\",\n\t\t\t\t\t\thint: hintParts.join(\", \"),\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tvalue: \"customize\",\n\t\t\t\t\t\tlabel: \"Customize installation\",\n\t\t\t\t\t\thint: \"choose scopes and options\",\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tvalue: \"change_editor\",\n\t\t\t\t\t\tlabel: \"Configure a different editor\",\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tinitialValue: \"defaults\",\n\t\t\t});\n\n\t\t\tif (isCancel(result)) {\n\t\t\t\toutro(\"Setup cancelled.\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (result === \"change_editor\") {\n\t\t\t\tconst availableEditors = await detectAvailableEditors(homeDir);\n\t\t\t\tconst editorResponse = await multiselect({\n\t\t\t\t\tmessage: \"Which editor(s) would you like to configure?\",\n\t\t\t\t\toptions: ALL_CONFIGURABLE_AGENTS.map((agent) => ({\n\t\t\t\t\t\tvalue: agent.editor,\n\t\t\t\t\t\tlabel: agent.editor,\n\t\t\t\t\t\thint: agent.hint,\n\t\t\t\t\t})),\n\t\t\t\t\tinitialValues: availableEditors,\n\t\t\t\t\trequired: true,\n\t\t\t\t});\n\t\t\t\tif (isCancel(editorResponse)) {\n\t\t\t\t\toutro(\"Setup cancelled.\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tselectedEditors = editorResponse as Editor[];\n\t\t\t\tif (selectedEditors.length === 0) {\n\t\t\t\t\toutro(\"Setup cancelled.\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tmodeResult = result as string;\n\t\t\tbreak;\n\t\t}\n\n\t\tif (modeResult === \"customize\") {\n\t\t\tif (needsMcp) {\n\t\t\t\tconst scopeResult = await select({\n\t\t\t\t\tmessage: \"Where should the Neon MCP server be configured?\",\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tvalue: \"global\",\n\t\t\t\t\t\t\tlabel: \"Global (available in all projects)\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tvalue: \"project\",\n\t\t\t\t\t\t\tlabel: \"Project-level (this project only)\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tvalue: \"none\",\n\t\t\t\t\t\t\tlabel: \"Skip — do not install the MCP server\",\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t});\n\t\t\t\tif (isCancel(scopeResult)) {\n\t\t\t\t\toutro(\"Setup cancelled.\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tmcpScope = scopeResult as \"global\" | \"project\" | \"none\";\n\t\t\t\tif (mcpScope === \"none\") needsMcp = false;\n\t\t\t}\n\n\t\t\tif (needsSkills) {\n\t\t\t\tconst skillsScopeResult = await select({\n\t\t\t\t\tmessage: \"Where should Neon agent skills be installed?\",\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tvalue: \"global\",\n\t\t\t\t\t\t\tlabel: \"Global (available in all projects)\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tvalue: \"project\",\n\t\t\t\t\t\t\tlabel: \"Project-level (this project only)\",\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tinitialValue: \"project\",\n\t\t\t\t});\n\t\t\t\tif (isCancel(skillsScopeResult)) {\n\t\t\t\t\toutro(\"Setup cancelled.\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tskillsScope = skillsScopeResult as \"global\" | \"project\";\n\t\t\t}\n\n\t\t\tif (doInstallExtension) {\n\t\t\t\tconst extResult = await confirm({\n\t\t\t\t\tmessage: `Install the Neon extension for ${vscodeEditors.join(\", \")}?`,\n\t\t\t\t});\n\t\t\t\tif (isCancel(extResult)) {\n\t\t\t\t\toutro(\"Setup cancelled.\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tdoInstallExtension = extResult;\n\t\t\t}\n\t\t}\n\n\t\t// Auth check before install\n\t\tconst installAuthed = await isAuthenticated();\n\t\tif (!installAuthed) {\n\t\t\tconst authS = spinner();\n\t\t\tauthS.start(\"Authenticating with Neon...\");\n\t\t\tconst authSuccess = await ensureNeonctlAuth();\n\t\t\tif (!authSuccess) {\n\t\t\t\tauthS.stop(\"Authentication failed.\");\n\t\t\t\toutro(\"Run neon-init again after signing in.\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tauthS.stop(\"Authenticated.\");\n\t\t}\n\n\t\t// Ensure the Neon CLI is installed and up to date\n\t\tconst nctlS = spinner();\n\t\tnctlS.start(\"Checking Neon CLI...\");\n\t\tconst nctlResult = await ensureNeonctl();\n\t\tswitch (nctlResult.status) {\n\t\t\tcase \"already_current\":\n\t\t\t\tnctlS.stop(\n\t\t\t\t\tdim(`Neon CLI is up to date (v${nctlResult.version}) ✓`),\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"installed\":\n\t\t\t\tnctlS.stop(\n\t\t\t\t\tdim(`Installed Neon CLI (v${nctlResult.version}) ✓`),\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"updated\":\n\t\t\t\tnctlS.stop(dim(`Updated Neon CLI to v${nctlResult.version} ✓`));\n\t\t\t\tbreak;\n\t\t\tcase \"failed\":\n\t\t\t\tnctlS.stop(\"Failed to install Neon CLI\");\n\t\t\t\tlog.warn(\n\t\t\t\t\t\"The Neon CLI could not be installed automatically. The setup will continue using npx.\",\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t}\n\n\t\t// Install only what's missing\n\t\tfor (const editor of selectedEditors) {\n\t\t\tif (needsMcp) {\n\t\t\t\tconst mcpAgentId = getAddMcpAgentId(editor);\n\t\t\t\tconst mcpArgs = [\n\t\t\t\t\t\"-y\",\n\t\t\t\t\t\"add-mcp\",\n\t\t\t\t\t\"https://mcp.neon.tech/mcp\",\n\t\t\t\t\t\"-n\",\n\t\t\t\t\t\"Neon\",\n\t\t\t\t\t\"-y\",\n\t\t\t\t\t\"-a\",\n\t\t\t\t\tmcpAgentId,\n\t\t\t\t];\n\t\t\t\tif (mcpScope === \"global\") mcpArgs.splice(5, 0, \"-g\");\n\n\t\t\t\tconst mcpS = spinner();\n\t\t\t\tmcpS.start(`Installing Neon MCP server for ${editor}...`);\n\t\t\t\ttry {\n\t\t\t\t\tawait execa(\"npx\", mcpArgs, {\n\t\t\t\t\t\tstdio: \"pipe\",\n\t\t\t\t\t\ttimeout: 60000,\n\t\t\t\t\t});\n\t\t\t\t\tmcpS.stop(\n\t\t\t\t\t\tdim(\n\t\t\t\t\t\t\t`Neon MCP server configured for ${editor} (${mcpScope}) ✓`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconst msg =\n\t\t\t\t\t\terr instanceof Error ? err.message : \"Unknown error\";\n\t\t\t\t\tmcpS.stop(`Failed to configure MCP server for ${editor}`);\n\t\t\t\t\tlog.error(msg);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (needsSkills) {\n\t\t\t\tawait installAgentSkills([editor], {\n\t\t\t\t\tscope: skillsScope,\n\t\t\t\t\tpreview: options.preview,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (doInstallExtension && usesExtension(editor)) {\n\t\t\t\tconst extS = spinner();\n\t\t\t\textS.start(`Installing Neon extension for ${editor}...`);\n\t\t\t\tconst extOk = await installExtension(editor);\n\t\t\t\tif (extOk) {\n\t\t\t\t\textS.stop(dim(`Neon extension installed for ${editor} ✓`));\n\t\t\t\t} else {\n\t\t\t\t\textS.stop(\n\t\t\t\t\t\t`Extension install failed — install manually from the extensions panel.`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Ensure all required skills are present (fills in any missing ones).\n\t// detectAgent() returns null in a human terminal (TTY), so fall back\n\t// to IDE detection which works regardless of TTY.\n\tconst ide = detectIde();\n\tconst agentForSkills =\n\t\tdetectAgent() ??\n\t\t(ide === \"Cursor\"\n\t\t\t? \"cursor\"\n\t\t\t: ide === \"VS Code\"\n\t\t\t\t? \"vscode\"\n\t\t\t\t: ide === \"Windsurf\"\n\t\t\t\t\t? \"windsurf\"\n\t\t\t\t\t: null);\n\tif (agentForSkills) {\n\t\tconst detectedSkillsScope =\n\t\t\tinspection.skillsScope === \"global\" ? \"global\" : undefined;\n\t\tawait ensureSkillsUpToDate(\n\t\t\tagentForSkills,\n\t\t\tdetectedSkillsScope,\n\t\t\toptions.preview,\n\t\t);\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Step 6: Done — build prompt for the agent to continue\n\t// -----------------------------------------------------------------------\n\n\t// Build the getting-started data payload (same as agent mode)\n\tconst gettingStartedData: Record<string, unknown> = {};\n\tif (hasNeonConnection) gettingStartedData.hasConnectionString = true;\n\tif (inspection.framework && inspection.framework !== \"none\")\n\t\tgettingStartedData.framework = inspection.framework;\n\tif (inspection.orm && inspection.orm !== \"none\")\n\t\tgettingStartedData.orm = inspection.orm;\n\tif (inspection.migrationTool && inspection.migrationTool !== \"none\")\n\t\tgettingStartedData.migrationTool = inspection.migrationTool;\n\tif (inspection.migrationDir && inspection.migrationDir !== \"none\")\n\t\tgettingStartedData.migrationDir = inspection.migrationDir;\n\tif (selectedFeatures.length > 0)\n\t\tgettingStartedData.features = selectedFeatures;\n\tif (options.preview) gettingStartedData.preview = true;\n\n\t// Build a prompt for the user to paste into their agent chat\n\tconst cmd = `neon init --agent --data '${JSON.stringify({ step: \"getting-started\", ...gettingStartedData })}'`;\n\t// Account for clack's \"│ \" prefix (3 chars) when wrapping\n\tconst cols = (process.stdout.columns || 80) - 3;\n\tconst promptText = `To finish setting up Neon using Neon's agent-guided onboarding experience, have your agent run this shell command: ${cmd}`;\n\n\tlog.step(\"Next steps\");\n\tlog.message(dim(\"Copy the following into your agent chat:\"));\n\tlog.message(\n\t\twordWrap(promptText, cols)\n\t\t\t.split(\"\\n\")\n\t\t\t.map((line) => bold(neonGreenFn(line)))\n\t\t\t.join(\"\\n\"),\n\t);\n\toutro(dim(\"Have feedback? Email us at feedback@neon.tech\"));\n}\n\nfunction agentIdToEditor(agentId: string): Editor | null {\n\tswitch (agentId) {\n\t\tcase \"cursor\":\n\t\t\treturn \"Cursor\";\n\t\tcase \"vscode\":\n\t\t\treturn \"VS Code\";\n\t\tcase \"claude-code\":\n\t\t\treturn \"Claude CLI\";\n\t\tcase \"windsurf\":\n\t\t\t// Windsurf not in Editor type yet — fall back to prompt\n\t\t\treturn null;\n\t\tcase \"codex\":\n\t\t\treturn \"Codex\";\n\t\tcase \"cline\":\n\t\t\treturn \"Cline\";\n\t\tdefault:\n\t\t\treturn null;\n\t}\n}\n"],"mappings":"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"}
|
package/dist/lib/auth.js
CHANGED
|
@@ -25,7 +25,7 @@ async function ensureNeonctlAuth(options) {
|
|
|
25
25
|
return true;
|
|
26
26
|
} catch (error) {
|
|
27
27
|
const msg = error instanceof Error ? error.message : "Unknown error";
|
|
28
|
-
if (!quiet) if (msg.includes("interactive auth") || msg.includes("CI")) log.error("Auth requires an interactive terminal. Run
|
|
28
|
+
if (!quiet) if (msg.includes("interactive auth") || msg.includes("CI")) log.error("Auth requires an interactive terminal. Run neon init in your system terminal (outside the chat) to sign in.");
|
|
29
29
|
else log.error(`Authentication failed: ${msg}`);
|
|
30
30
|
return false;
|
|
31
31
|
}
|
|
@@ -58,7 +58,7 @@ async function createApiKeyFromNeonctl(options) {
|
|
|
58
58
|
try {
|
|
59
59
|
const accessToken = await getNeonctlAccessToken();
|
|
60
60
|
if (!accessToken) {
|
|
61
|
-
if (!quiet) log.error("Could not find OAuth token from
|
|
61
|
+
if (!quiet) log.error("Could not find OAuth token from the Neon CLI");
|
|
62
62
|
return null;
|
|
63
63
|
}
|
|
64
64
|
const keyName = `neonctl-init-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, -5)}`;
|