neon-init 0.13.1 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +368 -33
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +15 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +220 -41
- package/dist/index.js.map +1 -1
- package/dist/interactive.d.ts +12 -0
- package/dist/interactive.d.ts.map +1 -0
- package/dist/interactive.js +495 -0
- package/dist/interactive.js.map +1 -0
- package/dist/lib/agents.d.ts +23 -0
- package/dist/lib/agents.d.ts.map +1 -0
- package/dist/lib/agents.js +148 -0
- package/dist/lib/agents.js.map +1 -0
- package/dist/lib/auth.d.ts +10 -3
- package/dist/lib/auth.d.ts.map +1 -1
- package/dist/lib/auth.js +20 -13
- package/dist/lib/auth.js.map +1 -1
- package/dist/lib/bootstrap.d.ts +30 -0
- package/dist/lib/bootstrap.d.ts.map +1 -0
- package/dist/lib/bootstrap.js +61 -0
- package/dist/lib/bootstrap.js.map +1 -0
- package/dist/lib/build-config.d.ts +5 -0
- package/dist/lib/build-config.d.ts.map +1 -0
- package/dist/lib/build-config.js +6 -0
- package/dist/lib/build-config.js.map +1 -0
- package/dist/lib/detect-agent.d.ts +22 -0
- package/dist/lib/detect-agent.d.ts.map +1 -0
- package/dist/lib/detect-agent.js +65 -0
- package/dist/lib/detect-agent.js.map +1 -0
- package/dist/lib/editors.d.ts.map +1 -1
- package/dist/lib/editors.js +1 -2
- package/dist/lib/editors.js.map +1 -1
- package/dist/lib/extension.d.ts +11 -3
- package/dist/lib/extension.d.ts.map +1 -1
- package/dist/lib/extension.js +29 -9
- package/dist/lib/extension.js.map +1 -1
- package/dist/lib/inspect.d.ts +28 -0
- package/dist/lib/inspect.d.ts.map +1 -0
- package/dist/lib/inspect.js +190 -0
- package/dist/lib/inspect.js.map +1 -0
- package/dist/lib/install.d.ts +10 -4
- package/dist/lib/install.d.ts.map +1 -1
- package/dist/lib/install.js +74 -71
- package/dist/lib/install.js.map +1 -1
- package/dist/lib/neonctl.d.ts +32 -0
- package/dist/lib/neonctl.d.ts.map +1 -0
- package/dist/lib/neonctl.js +149 -0
- package/dist/lib/neonctl.js.map +1 -0
- package/dist/lib/phases/auth.d.ts +12 -0
- package/dist/lib/phases/auth.d.ts.map +1 -0
- package/dist/lib/phases/auth.js +188 -0
- package/dist/lib/phases/auth.js.map +1 -0
- package/dist/lib/phases/cleanup.d.ts +12 -0
- package/dist/lib/phases/cleanup.d.ts.map +1 -0
- package/dist/lib/phases/cleanup.js +29 -0
- package/dist/lib/phases/cleanup.js.map +1 -0
- package/dist/lib/phases/db.d.ts +17 -0
- package/dist/lib/phases/db.d.ts.map +1 -0
- package/dist/lib/phases/db.js +258 -0
- package/dist/lib/phases/db.js.map +1 -0
- package/dist/lib/phases/getting-started.d.ts +26 -0
- package/dist/lib/phases/getting-started.d.ts.map +1 -0
- package/dist/lib/phases/getting-started.js +195 -0
- package/dist/lib/phases/getting-started.js.map +1 -0
- package/dist/lib/phases/mcp.d.ts +15 -0
- package/dist/lib/phases/mcp.d.ts.map +1 -0
- package/dist/lib/phases/mcp.js +179 -0
- package/dist/lib/phases/mcp.js.map +1 -0
- package/dist/lib/phases/migrations.d.ts +14 -0
- package/dist/lib/phases/migrations.d.ts.map +1 -0
- package/dist/lib/phases/migrations.js +239 -0
- package/dist/lib/phases/migrations.js.map +1 -0
- package/dist/lib/phases/neon-auth.d.ts +13 -0
- package/dist/lib/phases/neon-auth.d.ts.map +1 -0
- package/dist/lib/phases/neon-auth.js +117 -0
- package/dist/lib/phases/neon-auth.js.map +1 -0
- package/dist/lib/phases/setup.d.ts +41 -0
- package/dist/lib/phases/setup.d.ts.map +1 -0
- package/dist/lib/phases/setup.js +689 -0
- package/dist/lib/phases/setup.js.map +1 -0
- package/dist/lib/phases/skills.d.ts +14 -0
- package/dist/lib/phases/skills.d.ts.map +1 -0
- package/dist/lib/phases/skills.js +80 -0
- package/dist/lib/phases/skills.js.map +1 -0
- package/dist/lib/phases/status.d.ts +10 -0
- package/dist/lib/phases/status.d.ts.map +1 -0
- package/dist/lib/phases/status.js +65 -0
- package/dist/lib/phases/status.js.map +1 -0
- package/dist/lib/resolve-context.d.ts +19 -0
- package/dist/lib/resolve-context.d.ts.map +1 -0
- package/dist/lib/resolve-context.js +112 -0
- package/dist/lib/resolve-context.js.map +1 -0
- package/dist/lib/route-command.d.ts +8 -0
- package/dist/lib/route-command.d.ts.map +1 -0
- package/dist/lib/route-command.js +195 -0
- package/dist/lib/route-command.js.map +1 -0
- package/dist/lib/skills.d.ts +21 -4
- package/dist/lib/skills.d.ts.map +1 -1
- package/dist/lib/skills.js +129 -22
- package/dist/lib/skills.js.map +1 -1
- package/dist/lib/types.d.ts +146 -13
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/lib/types.js +1 -1
- package/dist/lib/vsix.d.ts +15 -0
- package/dist/lib/vsix.d.ts.map +1 -0
- package/dist/lib/vsix.js +91 -0
- package/dist/lib/vsix.js.map +1 -0
- package/dist/v2.d.ts +31 -0
- package/dist/v2.d.ts.map +1 -0
- package/dist/v2.js +147 -0
- package/dist/v2.js.map +1 -0
- package/package.json +9 -4
- package/dist/lib/mcp-config.d.ts +0 -24
- package/dist/lib/mcp-config.d.ts.map +0 -1
- package/dist/lib/mcp-config.js +0 -51
- package/dist/lib/mcp-config.js.map +0 -1
package/dist/lib/install.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"install.js","names":[],"sources":["../../src/lib/install.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"install.js","names":[],"sources":["../../src/lib/install.ts"],"sourcesContent":["import { log, spinner } from \"@clack/prompts\";\nimport { execa } from \"execa\";\nimport { getAddMcpAgentId } from \"./agents.js\";\nimport {\n\ttype AuthOptions,\n\tcreateApiKeyFromNeonctl,\n\tensureNeonctlAuth,\n} from \"./auth.js\";\nimport {\n\tconfigureExtension,\n\tinstallExtension,\n\tusesExtension,\n\twaitForExtensionInstalled,\n} from \"./extension.js\";\nimport type { Editor, InstallStatus } from \"./types.js\";\n\nconst NEON_MCP_SERVER_URL = \"https://mcp.neon.tech/mcp\";\n\n/**\n * Installs Neon MCP Server for a single editor via the add-mcp CLI.\n * Uses API key authentication via the Authorization header.\n */\nasync function installMCPServerViaAddMcp(\n\teditor: Editor,\n\tapiKey: string,\n): Promise<void> {\n\tconst agentId = getAddMcpAgentId(editor);\n\n\tawait execa(\n\t\t\"npx\",\n\t\t[\n\t\t\t\"-y\",\n\t\t\t\"add-mcp\",\n\t\t\tNEON_MCP_SERVER_URL,\n\t\t\t\"--header\",\n\t\t\t`Authorization: Bearer ${apiKey}`,\n\t\t\t\"-g\",\n\t\t\t\"-n\",\n\t\t\t\"Neon\",\n\t\t\t\"-y\",\n\t\t\t\"-a\",\n\t\t\tagentId,\n\t\t],\n\t\t{\n\t\t\tstdio: \"pipe\",\n\t\t\ttimeout: 60000,\n\t\t},\n\t);\n}\n\nexport interface InstallNeonOptions {\n\tjson?: boolean;\n}\n\n/**\n * Installs Neon's Local Connect extension or MCP Server for specific editors.\n * Returns a map of editor → install status and whether auth succeeded.\n */\nexport async function installNeon(\n\tselectedEditors: Editor[],\n\toptions?: InstallNeonOptions,\n): Promise<{ results: Map<Editor, InstallStatus>; authSuccess: boolean }> {\n\tconst quiet = options?.json === true;\n\tconst authOptions: AuthOptions = { json: quiet };\n\tconst results = new Map<Editor, InstallStatus>();\n\n\tconst extensionEditors = selectedEditors.filter(usesExtension);\n\tconst mcpEditors = selectedEditors.filter((e) => !usesExtension(e));\n\n\tif (extensionEditors.length === 0 && mcpEditors.length === 0) {\n\t\treturn { results, authSuccess: false };\n\t}\n\n\tconst authSpinner = quiet ? null : spinner();\n\tauthSpinner?.start(\"Authenticating...\");\n\n\tconst authSuccess = await ensureNeonctlAuth(authOptions);\n\n\tif (!authSuccess) {\n\t\tauthSpinner?.stop(\"Authentication failed\");\n\t\tfor (const editor of selectedEditors) {\n\t\t\tresults.set(editor, \"failed\");\n\t\t}\n\t\treturn { results, authSuccess: false };\n\t}\n\n\tauthSpinner?.stop(\"Authentication successful ✓\");\n\n\tconst apiKey = await createApiKeyFromNeonctl(authOptions);\n\n\tif (!apiKey) {\n\t\tif (!quiet) {\n\t\t\tlog.error(\"Could not create API key after authentication.\");\n\t\t\tlog.info(\n\t\t\t\t\"You can manually create one at: https://console.neon.tech/app/settings/api-keys\",\n\t\t\t);\n\t\t}\n\t\tfor (const editor of selectedEditors) {\n\t\t\tresults.set(editor, \"failed\");\n\t\t}\n\t\treturn { results, authSuccess: true };\n\t}\n\n\tfor (const editor of extensionEditors) {\n\t\tconst installSuccess = await installExtension(editor);\n\n\t\tif (!installSuccess) {\n\t\t\tresults.set(editor, \"failed\");\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst isReady = await waitForExtensionInstalled(editor);\n\t\tif (!isReady) {\n\t\t\tresults.set(editor, \"failed\");\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst configSuccess = await configureExtension(editor, apiKey);\n\n\t\tif (configSuccess) {\n\t\t\tresults.set(editor, \"success\");\n\t\t} else {\n\t\t\tresults.set(editor, \"failed\");\n\t\t}\n\t}\n\n\tif (mcpEditors.length > 0) {\n\t\tconst mcpSpinner = quiet ? null : spinner();\n\t\tmcpSpinner?.start(\"Installing and configuring Neon MCP Server...\");\n\n\t\tlet mcpSuccessCount = 0;\n\t\tfor (const editor of mcpEditors) {\n\t\t\ttry {\n\t\t\t\tawait installMCPServerViaAddMcp(editor, apiKey);\n\t\t\t\tresults.set(editor, \"success\");\n\t\t\t\tmcpSuccessCount++;\n\t\t\t} catch (err) {\n\t\t\t\tresults.set(editor, \"failed\");\n\t\t\t\tif (\n\t\t\t\t\t!quiet &&\n\t\t\t\t\terr &&\n\t\t\t\t\ttypeof err === \"object\" &&\n\t\t\t\t\t\"stderr\" in err &&\n\t\t\t\t\terr.stderr\n\t\t\t\t) {\n\t\t\t\t\tlog.error(\n\t\t\t\t\t\tString(err.stderr).trim() ||\n\t\t\t\t\t\t\t\"failed to install MCP server via add-mcp\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tmcpSpinner?.stop(\n\t\t\tmcpSuccessCount > 0\n\t\t\t\t? \"Neon MCP Server configuration complete ✓\"\n\t\t\t\t: \"Failed to configure Neon MCP Server\",\n\t\t);\n\t}\n\n\treturn { results, authSuccess: true };\n}\n"],"mappings":";;;;;;AAgBA,MAAM,sBAAsB;;;;;AAM5B,eAAe,0BACd,QACA,QACgB;CAChB,MAAM,UAAU,iBAAiB,MAAM;CAEvC,MAAM,MACL,OACA;EACC;EACA;EACA;EACA;EACA,yBAAyB;EACzB;EACA;EACA;EACA;EACA;EACA;CACD,GACA;EACC,OAAO;EACP,SAAS;CACV,CACD;AACD;;;;;AAUA,eAAsB,YACrB,iBACA,SACyE;CACzE,MAAM,QAAQ,SAAS,SAAS;CAChC,MAAM,cAA2B,EAAE,MAAM,MAAM;CAC/C,MAAM,0BAAU,IAAI,IAA2B;CAE/C,MAAM,mBAAmB,gBAAgB,OAAO,aAAa;CAC7D,MAAM,aAAa,gBAAgB,QAAQ,MAAM,CAAC,cAAc,CAAC,CAAC;CAElE,IAAI,iBAAiB,WAAW,KAAK,WAAW,WAAW,GAC1D,OAAO;EAAE;EAAS,aAAa;CAAM;CAGtC,MAAM,cAAc,QAAQ,OAAO,QAAQ;CAC3C,aAAa,MAAM,mBAAmB;CAItC,IAAI,CAAC,MAFqB,kBAAkB,WAAW,GAErC;EACjB,aAAa,KAAK,uBAAuB;EACzC,KAAK,MAAM,UAAU,iBACpB,QAAQ,IAAI,QAAQ,QAAQ;EAE7B,OAAO;GAAE;GAAS,aAAa;EAAM;CACtC;CAEA,aAAa,KAAK,6BAA6B;CAE/C,MAAM,SAAS,MAAM,wBAAwB,WAAW;CAExD,IAAI,CAAC,QAAQ;EACZ,IAAI,CAAC,OAAO;GACX,IAAI,MAAM,gDAAgD;GAC1D,IAAI,KACH,iFACD;EACD;EACA,KAAK,MAAM,UAAU,iBACpB,QAAQ,IAAI,QAAQ,QAAQ;EAE7B,OAAO;GAAE;GAAS,aAAa;EAAK;CACrC;CAEA,KAAK,MAAM,UAAU,kBAAkB;EAGtC,IAAI,CAAC,MAFwB,iBAAiB,MAAM,GAE/B;GACpB,QAAQ,IAAI,QAAQ,QAAQ;GAC5B;EACD;EAGA,IAAI,CAAC,MADiB,0BAA0B,MAAM,GACxC;GACb,QAAQ,IAAI,QAAQ,QAAQ;GAC5B;EACD;EAIA,IAAI,MAFwB,mBAAmB,QAAQ,MAAM,GAG5D,QAAQ,IAAI,QAAQ,SAAS;OAE7B,QAAQ,IAAI,QAAQ,QAAQ;CAE9B;CAEA,IAAI,WAAW,SAAS,GAAG;EAC1B,MAAM,aAAa,QAAQ,OAAO,QAAQ;EAC1C,YAAY,MAAM,+CAA+C;EAEjE,IAAI,kBAAkB;EACtB,KAAK,MAAM,UAAU,YACpB,IAAI;GACH,MAAM,0BAA0B,QAAQ,MAAM;GAC9C,QAAQ,IAAI,QAAQ,SAAS;GAC7B;EACD,SAAS,KAAK;GACb,QAAQ,IAAI,QAAQ,QAAQ;GAC5B,IACC,CAAC,SACD,OACA,OAAO,QAAQ,YACf,YAAY,OACZ,IAAI,QAEJ,IAAI,MACH,OAAO,IAAI,MAAM,CAAC,CAAC,KAAK,KACvB,0CACF;EAEF;EAGD,YAAY,KACX,kBAAkB,IACf,6CACA,qCACJ;CACD;CAEA,OAAO;EAAE;EAAS,aAAa;CAAK;AACrC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
//#region src/lib/neonctl.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Detects which package manager was used to invoke the current process.
|
|
4
|
+
* Reads the `npm_config_user_agent` env var set by npm/pnpm/yarn/bun when
|
|
5
|
+
* they spawn child processes (including via `npx`, `pnpx`, `bunx`, etc.).
|
|
6
|
+
*
|
|
7
|
+
* Falls back to "npm" if detection fails.
|
|
8
|
+
*/
|
|
9
|
+
declare function detectPackageManager(): "npm" | "pnpm" | "yarn" | "bun";
|
|
10
|
+
interface NeonctlStatus {
|
|
11
|
+
installed: boolean;
|
|
12
|
+
currentVersion: string | null;
|
|
13
|
+
latestVersion: string | null;
|
|
14
|
+
needsUpdate: boolean;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Checks whether the neonctl CLI is globally installed and whether it's up to date.
|
|
18
|
+
*/
|
|
19
|
+
declare function checkNeonctl(): Promise<NeonctlStatus>;
|
|
20
|
+
interface EnsureNeonctlResult {
|
|
21
|
+
status: "already_current" | "installed" | "updated" | "failed";
|
|
22
|
+
version?: string;
|
|
23
|
+
error?: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Ensures neonctl is globally installed and up to date.
|
|
27
|
+
* Uses the same package manager that invoked the init command.
|
|
28
|
+
*/
|
|
29
|
+
declare function ensureNeonctl(): Promise<EnsureNeonctlResult>;
|
|
30
|
+
//#endregion
|
|
31
|
+
export { EnsureNeonctlResult, checkNeonctl, detectPackageManager, ensureNeonctl };
|
|
32
|
+
//# sourceMappingURL=neonctl.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"neonctl.d.ts","names":[],"sources":["../../src/lib/neonctl.ts"],"mappings":";;AASA;AAQC;AAkDD;;;;AAA6C,iBA1D7B,oBAAA,CAAA,CA0D6B,EAAA,KAAA,GAAA,MAAA,GAAA,MAAA,GAAA,KAAA;AAiD7C,UA9EU,aAAA,CA8EO;EAUK,SAAA,EAAA,OAAa;EAAA,cAAA,EAAA,MAAA,GAAA,IAAA;eAAY,EAAA,MAAA,GAAA,IAAA;aAAR,EAAA,OAAA;AAAO;;;;iBA3DxB,YAAA,CAAA,GAAgB,QAAQ;UAiD7B,mBAAA;;;;;;;;;iBAUK,aAAA,CAAA,GAAiB,QAAQ"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { execa } from "execa";
|
|
2
|
+
//#region src/lib/neonctl.ts
|
|
3
|
+
/**
|
|
4
|
+
* Detects which package manager was used to invoke the current process.
|
|
5
|
+
* Reads the `npm_config_user_agent` env var set by npm/pnpm/yarn/bun when
|
|
6
|
+
* they spawn child processes (including via `npx`, `pnpx`, `bunx`, etc.).
|
|
7
|
+
*
|
|
8
|
+
* Falls back to "npm" if detection fails.
|
|
9
|
+
*/
|
|
10
|
+
function detectPackageManager() {
|
|
11
|
+
const ua = process.env.npm_config_user_agent;
|
|
12
|
+
if (ua) {
|
|
13
|
+
if (ua.startsWith("pnpm/")) return "pnpm";
|
|
14
|
+
if (ua.startsWith("yarn/")) return "yarn";
|
|
15
|
+
if (ua.startsWith("bun/")) return "bun";
|
|
16
|
+
}
|
|
17
|
+
return "npm";
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Returns the global install command for a given package manager.
|
|
21
|
+
*/
|
|
22
|
+
function globalInstallArgs(pm, pkg) {
|
|
23
|
+
switch (pm) {
|
|
24
|
+
case "pnpm": return {
|
|
25
|
+
command: "pnpm",
|
|
26
|
+
args: [
|
|
27
|
+
"add",
|
|
28
|
+
"-g",
|
|
29
|
+
pkg
|
|
30
|
+
]
|
|
31
|
+
};
|
|
32
|
+
case "yarn": return {
|
|
33
|
+
command: "yarn",
|
|
34
|
+
args: [
|
|
35
|
+
"global",
|
|
36
|
+
"add",
|
|
37
|
+
pkg
|
|
38
|
+
]
|
|
39
|
+
};
|
|
40
|
+
case "bun": return {
|
|
41
|
+
command: "bun",
|
|
42
|
+
args: [
|
|
43
|
+
"add",
|
|
44
|
+
"-g",
|
|
45
|
+
pkg
|
|
46
|
+
]
|
|
47
|
+
};
|
|
48
|
+
default: return {
|
|
49
|
+
command: "npm",
|
|
50
|
+
args: [
|
|
51
|
+
"install",
|
|
52
|
+
"-g",
|
|
53
|
+
pkg
|
|
54
|
+
]
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Gets the currently available neonctl version.
|
|
60
|
+
* Tries the global binary first, then falls back to npx.
|
|
61
|
+
*/
|
|
62
|
+
async function getNeonctlVersion() {
|
|
63
|
+
try {
|
|
64
|
+
const match = (await execa("neonctl", ["--version"], {
|
|
65
|
+
stdio: "pipe",
|
|
66
|
+
timeout: 5e3
|
|
67
|
+
})).stdout.trim().match(/(\d+\.\d+\.\d+)/);
|
|
68
|
+
if (match) return match[1];
|
|
69
|
+
} catch {}
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Checks whether the neonctl CLI is globally installed and whether it's up to date.
|
|
74
|
+
*/
|
|
75
|
+
async function checkNeonctl() {
|
|
76
|
+
const currentVersion = await getNeonctlVersion();
|
|
77
|
+
if (!currentVersion) return {
|
|
78
|
+
installed: false,
|
|
79
|
+
currentVersion: null,
|
|
80
|
+
latestVersion: null,
|
|
81
|
+
needsUpdate: true
|
|
82
|
+
};
|
|
83
|
+
let latestVersion = null;
|
|
84
|
+
try {
|
|
85
|
+
latestVersion = (await execa("npm", [
|
|
86
|
+
"view",
|
|
87
|
+
"neonctl",
|
|
88
|
+
"version"
|
|
89
|
+
], {
|
|
90
|
+
stdio: "pipe",
|
|
91
|
+
timeout: 1e4
|
|
92
|
+
})).stdout.trim();
|
|
93
|
+
} catch {
|
|
94
|
+
return {
|
|
95
|
+
installed: true,
|
|
96
|
+
currentVersion,
|
|
97
|
+
latestVersion: null,
|
|
98
|
+
needsUpdate: false
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
const needsUpdate = currentVersion !== null && latestVersion !== null && currentVersion !== latestVersion && isOlderVersion(currentVersion, latestVersion);
|
|
102
|
+
return {
|
|
103
|
+
installed: true,
|
|
104
|
+
currentVersion,
|
|
105
|
+
latestVersion,
|
|
106
|
+
needsUpdate
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
function isOlderVersion(current, latest) {
|
|
110
|
+
const c = current.split(".").map(Number);
|
|
111
|
+
const l = latest.split(".").map(Number);
|
|
112
|
+
for (let i = 0; i < 3; i++) {
|
|
113
|
+
if ((c[i] ?? 0) < (l[i] ?? 0)) return true;
|
|
114
|
+
if ((c[i] ?? 0) > (l[i] ?? 0)) return false;
|
|
115
|
+
}
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Ensures neonctl is globally installed and up to date.
|
|
120
|
+
* Uses the same package manager that invoked the init command.
|
|
121
|
+
*/
|
|
122
|
+
async function ensureNeonctl() {
|
|
123
|
+
const check = await checkNeonctl();
|
|
124
|
+
if (check.installed && !check.needsUpdate) return {
|
|
125
|
+
status: "already_current",
|
|
126
|
+
version: check.currentVersion ?? void 0
|
|
127
|
+
};
|
|
128
|
+
const { command, args } = globalInstallArgs(detectPackageManager(), "neonctl");
|
|
129
|
+
try {
|
|
130
|
+
await execa(command, args, {
|
|
131
|
+
stdio: "pipe",
|
|
132
|
+
timeout: 6e4
|
|
133
|
+
});
|
|
134
|
+
const version = await getNeonctlVersion();
|
|
135
|
+
return {
|
|
136
|
+
status: check.installed ? "updated" : "installed",
|
|
137
|
+
version: version ?? void 0
|
|
138
|
+
};
|
|
139
|
+
} catch (err) {
|
|
140
|
+
return {
|
|
141
|
+
status: "failed",
|
|
142
|
+
error: err instanceof Error ? err.message : "Unknown error"
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
//#endregion
|
|
147
|
+
export { checkNeonctl, detectPackageManager, ensureNeonctl };
|
|
148
|
+
|
|
149
|
+
//# sourceMappingURL=neonctl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"neonctl.js","names":[],"sources":["../../src/lib/neonctl.ts"],"sourcesContent":["import { execa } from \"execa\";\n\n/**\n * Detects which package manager was used to invoke the current process.\n * Reads the `npm_config_user_agent` env var set by npm/pnpm/yarn/bun when\n * they spawn child processes (including via `npx`, `pnpx`, `bunx`, etc.).\n *\n * Falls back to \"npm\" if detection fails.\n */\nexport function detectPackageManager(): \"npm\" | \"pnpm\" | \"yarn\" | \"bun\" {\n\tconst ua = process.env.npm_config_user_agent;\n\tif (ua) {\n\t\tif (ua.startsWith(\"pnpm/\")) return \"pnpm\";\n\t\tif (ua.startsWith(\"yarn/\")) return \"yarn\";\n\t\tif (ua.startsWith(\"bun/\")) return \"bun\";\n\t}\n\treturn \"npm\";\n}\n\n/**\n * Returns the global install command for a given package manager.\n */\nfunction globalInstallArgs(\n\tpm: \"npm\" | \"pnpm\" | \"yarn\" | \"bun\",\n\tpkg: string,\n): { command: string; args: string[] } {\n\tswitch (pm) {\n\t\tcase \"pnpm\":\n\t\t\treturn { command: \"pnpm\", args: [\"add\", \"-g\", pkg] };\n\t\tcase \"yarn\":\n\t\t\treturn { command: \"yarn\", args: [\"global\", \"add\", pkg] };\n\t\tcase \"bun\":\n\t\t\treturn { command: \"bun\", args: [\"add\", \"-g\", pkg] };\n\t\tdefault:\n\t\t\treturn { command: \"npm\", args: [\"install\", \"-g\", pkg] };\n\t}\n}\n\ninterface NeonctlStatus {\n\tinstalled: boolean;\n\tcurrentVersion: string | null;\n\tlatestVersion: string | null;\n\tneedsUpdate: boolean;\n}\n\n/**\n * Gets the currently available neonctl version.\n * Tries the global binary first, then falls back to npx.\n */\nasync function getNeonctlVersion(): Promise<string | null> {\n\t// Try global binary first (fast path)\n\ttry {\n\t\tconst result = await execa(\"neonctl\", [\"--version\"], {\n\t\t\tstdio: \"pipe\",\n\t\t\ttimeout: 5000,\n\t\t});\n\t\tconst match = result.stdout.trim().match(/(\\d+\\.\\d+\\.\\d+)/);\n\t\tif (match) return match[1];\n\t} catch {\n\t\t// Not globally installed — that's fine\n\t}\n\treturn null;\n}\n\n/**\n * Checks whether the neonctl CLI is globally installed and whether it's up to date.\n */\nexport async function checkNeonctl(): Promise<NeonctlStatus> {\n\tconst currentVersion = await getNeonctlVersion();\n\n\tif (!currentVersion) {\n\t\treturn {\n\t\t\tinstalled: false,\n\t\t\tcurrentVersion: null,\n\t\t\tlatestVersion: null,\n\t\t\tneedsUpdate: true,\n\t\t};\n\t}\n\n\t// Check latest version from npm registry\n\tlet latestVersion: string | null = null;\n\ttry {\n\t\tconst result = await execa(\"npm\", [\"view\", \"neonctl\", \"version\"], {\n\t\t\tstdio: \"pipe\",\n\t\t\ttimeout: 10000,\n\t\t});\n\t\tlatestVersion = result.stdout.trim();\n\t} catch {\n\t\t// Can't determine latest — assume current is fine\n\t\treturn {\n\t\t\tinstalled: true,\n\t\t\tcurrentVersion,\n\t\t\tlatestVersion: null,\n\t\t\tneedsUpdate: false,\n\t\t};\n\t}\n\n\tconst needsUpdate =\n\t\tcurrentVersion !== null &&\n\t\tlatestVersion !== null &&\n\t\tcurrentVersion !== latestVersion &&\n\t\tisOlderVersion(currentVersion, latestVersion);\n\n\treturn { installed: true, currentVersion, latestVersion, needsUpdate };\n}\n\nfunction isOlderVersion(current: string, latest: string): boolean {\n\tconst c = current.split(\".\").map(Number);\n\tconst l = latest.split(\".\").map(Number);\n\tfor (let i = 0; i < 3; i++) {\n\t\tif ((c[i] ?? 0) < (l[i] ?? 0)) return true;\n\t\tif ((c[i] ?? 0) > (l[i] ?? 0)) return false;\n\t}\n\treturn false;\n}\n\nexport interface EnsureNeonctlResult {\n\tstatus: \"already_current\" | \"installed\" | \"updated\" | \"failed\";\n\tversion?: string;\n\terror?: string;\n}\n\n/**\n * Ensures neonctl is globally installed and up to date.\n * Uses the same package manager that invoked the init command.\n */\nexport async function ensureNeonctl(): Promise<EnsureNeonctlResult> {\n\tconst check = await checkNeonctl();\n\n\tif (check.installed && !check.needsUpdate) {\n\t\treturn {\n\t\t\tstatus: \"already_current\",\n\t\t\tversion: check.currentVersion ?? undefined,\n\t\t};\n\t}\n\n\tconst pm = detectPackageManager();\n\tconst { command, args } = globalInstallArgs(pm, \"neonctl\");\n\n\ttry {\n\t\tawait execa(command, args, { stdio: \"pipe\", timeout: 60000 });\n\n\t\t// Verify installation\n\t\tconst version = await getNeonctlVersion();\n\t\treturn {\n\t\t\tstatus: check.installed ? \"updated\" : \"installed\",\n\t\t\tversion: version ?? undefined,\n\t\t};\n\t} catch (err) {\n\t\treturn {\n\t\t\tstatus: \"failed\",\n\t\t\terror: err instanceof Error ? err.message : \"Unknown error\",\n\t\t};\n\t}\n}\n"],"mappings":";;;;;;;;;AASA,SAAgB,uBAAwD;CACvE,MAAM,KAAK,QAAQ,IAAI;CACvB,IAAI,IAAI;EACP,IAAI,GAAG,WAAW,OAAO,GAAG,OAAO;EACnC,IAAI,GAAG,WAAW,OAAO,GAAG,OAAO;EACnC,IAAI,GAAG,WAAW,MAAM,GAAG,OAAO;CACnC;CACA,OAAO;AACR;;;;AAKA,SAAS,kBACR,IACA,KACsC;CACtC,QAAQ,IAAR;EACC,KAAK,QACJ,OAAO;GAAE,SAAS;GAAQ,MAAM;IAAC;IAAO;IAAM;GAAG;EAAE;EACpD,KAAK,QACJ,OAAO;GAAE,SAAS;GAAQ,MAAM;IAAC;IAAU;IAAO;GAAG;EAAE;EACxD,KAAK,OACJ,OAAO;GAAE,SAAS;GAAO,MAAM;IAAC;IAAO;IAAM;GAAG;EAAE;EACnD,SACC,OAAO;GAAE,SAAS;GAAO,MAAM;IAAC;IAAW;IAAM;GAAG;EAAE;CACxD;AACD;;;;;AAaA,eAAe,oBAA4C;CAE1D,IAAI;EAKH,MAAM,SAAQ,MAJO,MAAM,WAAW,CAAC,WAAW,GAAG;GACpD,OAAO;GACP,SAAS;EACV,CAAC,EAAA,CACoB,OAAO,KAAK,CAAC,CAAC,MAAM,iBAAiB;EAC1D,IAAI,OAAO,OAAO,MAAM;CACzB,QAAQ,CAER;CACA,OAAO;AACR;;;;AAKA,eAAsB,eAAuC;CAC5D,MAAM,iBAAiB,MAAM,kBAAkB;CAE/C,IAAI,CAAC,gBACJ,OAAO;EACN,WAAW;EACX,gBAAgB;EAChB,eAAe;EACf,aAAa;CACd;CAID,IAAI,gBAA+B;CACnC,IAAI;EAKH,iBAAgB,MAJK,MAAM,OAAO;GAAC;GAAQ;GAAW;EAAS,GAAG;GACjE,OAAO;GACP,SAAS;EACV,CAAC,EAAA,CACsB,OAAO,KAAK;CACpC,QAAQ;EAEP,OAAO;GACN,WAAW;GACX;GACA,eAAe;GACf,aAAa;EACd;CACD;CAEA,MAAM,cACL,mBAAmB,QACnB,kBAAkB,QAClB,mBAAmB,iBACnB,eAAe,gBAAgB,aAAa;CAE7C,OAAO;EAAE,WAAW;EAAM;EAAgB;EAAe;CAAY;AACtE;AAEA,SAAS,eAAe,SAAiB,QAAyB;CACjE,MAAM,IAAI,QAAQ,MAAM,GAAG,CAAC,CAAC,IAAI,MAAM;CACvC,MAAM,IAAI,OAAO,MAAM,GAAG,CAAC,CAAC,IAAI,MAAM;CACtC,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KAAK;EAC3B,KAAK,EAAE,MAAM,MAAM,EAAE,MAAM,IAAI,OAAO;EACtC,KAAK,EAAE,MAAM,MAAM,EAAE,MAAM,IAAI,OAAO;CACvC;CACA,OAAO;AACR;;;;;AAYA,eAAsB,gBAA8C;CACnE,MAAM,QAAQ,MAAM,aAAa;CAEjC,IAAI,MAAM,aAAa,CAAC,MAAM,aAC7B,OAAO;EACN,QAAQ;EACR,SAAS,MAAM,kBAAkB,KAAA;CAClC;CAID,MAAM,EAAE,SAAS,SAAS,kBADf,qBACkC,GAAG,SAAS;CAEzD,IAAI;EACH,MAAM,MAAM,SAAS,MAAM;GAAE,OAAO;GAAQ,SAAS;EAAM,CAAC;EAG5D,MAAM,UAAU,MAAM,kBAAkB;EACxC,OAAO;GACN,QAAQ,MAAM,YAAY,YAAY;GACtC,SAAS,WAAW,KAAA;EACrB;CACD,SAAS,KAAK;EACb,OAAO;GACN,QAAQ;GACR,OAAO,eAAe,QAAQ,IAAI,UAAU;EAC7C;CACD;AACD"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { PhaseResponse } from "../types.js";
|
|
2
|
+
|
|
3
|
+
//#region src/lib/phases/auth.d.ts
|
|
4
|
+
interface AuthPhaseOptions {
|
|
5
|
+
agent?: string;
|
|
6
|
+
method?: "existing" | "new";
|
|
7
|
+
verify?: boolean;
|
|
8
|
+
}
|
|
9
|
+
declare function handleAuthPhase(options: AuthPhaseOptions): Promise<PhaseResponse>;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { AuthPhaseOptions, handleAuthPhase };
|
|
12
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","names":[],"sources":["../../../src/lib/phases/auth.ts"],"mappings":";;;UASiB,gBAAA;;EAAA,MAAA,CAAA,EAAA,UAAgB,GAAA,KAAA;EAMX,MAAA,CAAA,EAAA,OAAA;;AACZ,iBADY,eAAA,CACZ,OAAA,EAAA,gBAAA,CAAA,EACP,OADO,CACC,aADD,CAAA"}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import { isAuthenticated } from "../auth.js";
|
|
2
|
+
//#region src/lib/phases/auth.ts
|
|
3
|
+
const SIGNUP_COMMANDS = {
|
|
4
|
+
darwin: "open https://console.neon.tech/signup",
|
|
5
|
+
linux: "xdg-open https://console.neon.tech/signup",
|
|
6
|
+
win32: "start https://console.neon.tech/signup"
|
|
7
|
+
};
|
|
8
|
+
async function handleAuthPhase(options) {
|
|
9
|
+
const agentArgs = options.agent ? [
|
|
10
|
+
"--agent",
|
|
11
|
+
options.agent,
|
|
12
|
+
"--json"
|
|
13
|
+
] : ["--json"];
|
|
14
|
+
if (options.verify) {
|
|
15
|
+
if (await isAuthenticated()) return {
|
|
16
|
+
phase: "auth",
|
|
17
|
+
status: "verified",
|
|
18
|
+
nextAction: {
|
|
19
|
+
type: "run_neon_init",
|
|
20
|
+
args: agentArgs
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
return {
|
|
24
|
+
phase: "auth",
|
|
25
|
+
status: "not_authenticated",
|
|
26
|
+
nextAction: {
|
|
27
|
+
type: "run_neon_init",
|
|
28
|
+
args: ["auth", "--json"]
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
if (await isAuthenticated()) return {
|
|
33
|
+
phase: "auth",
|
|
34
|
+
status: "verified",
|
|
35
|
+
nextAction: {
|
|
36
|
+
type: "run_neon_init",
|
|
37
|
+
args: agentArgs
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
if (options.method === "new") return {
|
|
41
|
+
phase: "auth",
|
|
42
|
+
status: "in_progress",
|
|
43
|
+
nextAction: {
|
|
44
|
+
type: "agent_action",
|
|
45
|
+
steps: [{
|
|
46
|
+
id: "open_signup",
|
|
47
|
+
description: "Open the Neon sign-up page in the user's browser",
|
|
48
|
+
command: SIGNUP_COMMANDS[process.platform] ?? SIGNUP_COMMANDS.linux
|
|
49
|
+
}, {
|
|
50
|
+
id: "wait_for_signup",
|
|
51
|
+
description: "Tell the user: 'I've opened the Neon sign-up page. Create your account and verify your email, then let me know when you're ready.'"
|
|
52
|
+
}],
|
|
53
|
+
onComplete: {
|
|
54
|
+
type: "run_neon_init",
|
|
55
|
+
args: [
|
|
56
|
+
"auth",
|
|
57
|
+
"--json",
|
|
58
|
+
"--method",
|
|
59
|
+
"existing"
|
|
60
|
+
]
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
if (options.method === "existing") return {
|
|
65
|
+
phase: "auth",
|
|
66
|
+
status: "in_progress",
|
|
67
|
+
nextAction: {
|
|
68
|
+
type: "run_command",
|
|
69
|
+
command: "CI= npx -y neonctl auth",
|
|
70
|
+
description: "This will open your browser for Neon OAuth sign-in.",
|
|
71
|
+
timeout: 12e4,
|
|
72
|
+
onSuccess: {
|
|
73
|
+
type: "run_neon_init",
|
|
74
|
+
args: [
|
|
75
|
+
"auth",
|
|
76
|
+
"--json",
|
|
77
|
+
"--verify"
|
|
78
|
+
]
|
|
79
|
+
},
|
|
80
|
+
onFailure: {
|
|
81
|
+
"2": {
|
|
82
|
+
type: "ask_user",
|
|
83
|
+
question: "The sign-in timed out. Did you complete the sign-in in your browser?",
|
|
84
|
+
options: ["yes_retry", "need_help"],
|
|
85
|
+
responseMapping: {
|
|
86
|
+
yes_retry: { args: [
|
|
87
|
+
"auth",
|
|
88
|
+
"--json",
|
|
89
|
+
"--method",
|
|
90
|
+
"existing"
|
|
91
|
+
] },
|
|
92
|
+
need_help: { args: [
|
|
93
|
+
"auth",
|
|
94
|
+
"--json",
|
|
95
|
+
"--method",
|
|
96
|
+
"new"
|
|
97
|
+
] }
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
other: {
|
|
101
|
+
type: "run_neon_init",
|
|
102
|
+
args: ["auth", "--json"]
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
return {
|
|
108
|
+
phase: "auth",
|
|
109
|
+
status: "required",
|
|
110
|
+
nextAction: {
|
|
111
|
+
type: "ask_user",
|
|
112
|
+
question: "Do you have an existing Neon account, or do you need to create one?",
|
|
113
|
+
options: [{
|
|
114
|
+
value: "existing_account",
|
|
115
|
+
label: "I have an existing Neon account"
|
|
116
|
+
}, {
|
|
117
|
+
value: "new_account",
|
|
118
|
+
label: "I need to create a new account"
|
|
119
|
+
}],
|
|
120
|
+
context: "Neon is a serverless Postgres provider. A free account is required to continue.",
|
|
121
|
+
responseMapping: {
|
|
122
|
+
existing_account: { action: {
|
|
123
|
+
type: "run_command",
|
|
124
|
+
command: "CI= npx -y neonctl auth",
|
|
125
|
+
description: "This will open your browser for Neon OAuth sign-in.",
|
|
126
|
+
timeout: 12e4,
|
|
127
|
+
onSuccess: {
|
|
128
|
+
type: "run_neon_init",
|
|
129
|
+
args: [
|
|
130
|
+
"auth",
|
|
131
|
+
"--json",
|
|
132
|
+
"--verify"
|
|
133
|
+
]
|
|
134
|
+
},
|
|
135
|
+
onFailure: {
|
|
136
|
+
"2": {
|
|
137
|
+
type: "ask_user",
|
|
138
|
+
question: "The sign-in timed out. Did you complete the sign-in in your browser?",
|
|
139
|
+
options: ["yes_retry", "need_help"],
|
|
140
|
+
responseMapping: {
|
|
141
|
+
yes_retry: { args: [
|
|
142
|
+
"auth",
|
|
143
|
+
"--json",
|
|
144
|
+
"--method",
|
|
145
|
+
"existing"
|
|
146
|
+
] },
|
|
147
|
+
need_help: { args: [
|
|
148
|
+
"auth",
|
|
149
|
+
"--json",
|
|
150
|
+
"--method",
|
|
151
|
+
"new"
|
|
152
|
+
] }
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
other: {
|
|
156
|
+
type: "run_neon_init",
|
|
157
|
+
args: ["auth", "--json"]
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
} },
|
|
161
|
+
new_account: { action: {
|
|
162
|
+
type: "agent_action",
|
|
163
|
+
steps: [{
|
|
164
|
+
id: "open_signup",
|
|
165
|
+
description: "Open the Neon sign-up page in the user's browser",
|
|
166
|
+
command: SIGNUP_COMMANDS[process.platform] ?? SIGNUP_COMMANDS.linux
|
|
167
|
+
}, {
|
|
168
|
+
id: "wait_for_signup",
|
|
169
|
+
description: "Tell the user: 'I've opened the Neon sign-up page. Create your account and verify your email, then let me know when you're ready.'"
|
|
170
|
+
}],
|
|
171
|
+
onComplete: {
|
|
172
|
+
type: "run_neon_init",
|
|
173
|
+
args: [
|
|
174
|
+
"auth",
|
|
175
|
+
"--json",
|
|
176
|
+
"--method",
|
|
177
|
+
"existing"
|
|
178
|
+
]
|
|
179
|
+
}
|
|
180
|
+
} }
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
//#endregion
|
|
186
|
+
export { handleAuthPhase };
|
|
187
|
+
|
|
188
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","names":[],"sources":["../../../src/lib/phases/auth.ts"],"sourcesContent":["import { isAuthenticated } from \"../auth.js\";\nimport type { PhaseResponse } from \"../types.js\";\n\nconst SIGNUP_COMMANDS: Record<string, string> = {\n\tdarwin: \"open https://console.neon.tech/signup\",\n\tlinux: \"xdg-open https://console.neon.tech/signup\",\n\twin32: \"start https://console.neon.tech/signup\",\n};\n\nexport interface AuthPhaseOptions {\n\tagent?: string;\n\tmethod?: \"existing\" | \"new\";\n\tverify?: boolean;\n}\n\nexport async function handleAuthPhase(\n\toptions: AuthPhaseOptions,\n): Promise<PhaseResponse> {\n\tconst agentArgs = options.agent\n\t\t? [\"--agent\", options.agent, \"--json\"]\n\t\t: [\"--json\"];\n\n\t// --verify: just check if credentials exist\n\tif (options.verify) {\n\t\tconst authed = await isAuthenticated();\n\t\tif (authed) {\n\t\t\t// Continue the flow immediately — don't use \"complete\" which\n\t\t\t// causes agents to stop and get distracted by neonctl output.\n\t\t\treturn {\n\t\t\t\tphase: \"auth\",\n\t\t\t\tstatus: \"verified\",\n\t\t\t\tnextAction: {\n\t\t\t\t\ttype: \"run_neon_init\",\n\t\t\t\t\targs: agentArgs,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\tphase: \"auth\",\n\t\t\tstatus: \"not_authenticated\",\n\t\t\tnextAction: {\n\t\t\t\ttype: \"run_neon_init\",\n\t\t\t\targs: [\"auth\", \"--json\"],\n\t\t\t},\n\t\t};\n\t}\n\n\t// Check if already authenticated\n\tconst authed = await isAuthenticated();\n\tif (authed) {\n\t\treturn {\n\t\t\tphase: \"auth\",\n\t\t\tstatus: \"verified\",\n\t\t\tnextAction: {\n\t\t\t\ttype: \"run_neon_init\",\n\t\t\t\targs: agentArgs,\n\t\t\t},\n\t\t};\n\t}\n\n\t// --method new: guide through signup\n\tif (options.method === \"new\") {\n\t\tconst openCmd =\n\t\t\tSIGNUP_COMMANDS[process.platform] ?? SIGNUP_COMMANDS.linux;\n\t\treturn {\n\t\t\tphase: \"auth\",\n\t\t\tstatus: \"in_progress\",\n\t\t\tnextAction: {\n\t\t\t\ttype: \"agent_action\",\n\t\t\t\tsteps: [\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"open_signup\",\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\"Open the Neon sign-up page in the user's browser\",\n\t\t\t\t\t\tcommand: openCmd,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"wait_for_signup\",\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\"Tell the user: 'I've opened the Neon sign-up page. Create your account and verify your email, then let me know when you're ready.'\",\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tonComplete: {\n\t\t\t\t\ttype: \"run_neon_init\",\n\t\t\t\t\targs: [\"auth\", \"--json\", \"--method\", \"existing\"],\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t}\n\n\t// --method existing: run OAuth flow\n\tif (options.method === \"existing\") {\n\t\treturn {\n\t\t\tphase: \"auth\",\n\t\t\tstatus: \"in_progress\",\n\t\t\tnextAction: {\n\t\t\t\ttype: \"run_command\",\n\t\t\t\tcommand: \"CI= npx -y neonctl auth\",\n\t\t\t\tdescription:\n\t\t\t\t\t\"This will open your browser for Neon OAuth sign-in.\",\n\t\t\t\ttimeout: 120000,\n\t\t\t\tonSuccess: {\n\t\t\t\t\ttype: \"run_neon_init\",\n\t\t\t\t\targs: [\"auth\", \"--json\", \"--verify\"],\n\t\t\t\t},\n\t\t\t\tonFailure: {\n\t\t\t\t\t\"2\": {\n\t\t\t\t\t\ttype: \"ask_user\",\n\t\t\t\t\t\tquestion:\n\t\t\t\t\t\t\t\"The sign-in timed out. Did you complete the sign-in in your browser?\",\n\t\t\t\t\t\toptions: [\"yes_retry\", \"need_help\"],\n\t\t\t\t\t\tresponseMapping: {\n\t\t\t\t\t\t\tyes_retry: {\n\t\t\t\t\t\t\t\targs: [\n\t\t\t\t\t\t\t\t\t\"auth\",\n\t\t\t\t\t\t\t\t\t\"--json\",\n\t\t\t\t\t\t\t\t\t\"--method\",\n\t\t\t\t\t\t\t\t\t\"existing\",\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tneed_help: {\n\t\t\t\t\t\t\t\targs: [\"auth\", \"--json\", \"--method\", \"new\"],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tother: {\n\t\t\t\t\t\ttype: \"run_neon_init\",\n\t\t\t\t\t\targs: [\"auth\", \"--json\"],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t}\n\n\t// No method specified: ask the user, then launch OAuth directly for\n\t// \"existing account\" without an intermediate CLI round-trip.\n\tconst openCmd = SIGNUP_COMMANDS[process.platform] ?? SIGNUP_COMMANDS.linux;\n\treturn {\n\t\tphase: \"auth\",\n\t\tstatus: \"required\",\n\t\tnextAction: {\n\t\t\ttype: \"ask_user\",\n\t\t\tquestion:\n\t\t\t\t\"Do you have an existing Neon account, or do you need to create one?\",\n\t\t\toptions: [\n\t\t\t\t{\n\t\t\t\t\tvalue: \"existing_account\",\n\t\t\t\t\tlabel: \"I have an existing Neon account\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tvalue: \"new_account\",\n\t\t\t\t\tlabel: \"I need to create a new account\",\n\t\t\t\t},\n\t\t\t],\n\t\t\tcontext:\n\t\t\t\t\"Neon is a serverless Postgres provider. A free account is required to continue.\",\n\t\t\tresponseMapping: {\n\t\t\t\texisting_account: {\n\t\t\t\t\taction: {\n\t\t\t\t\t\ttype: \"run_command\",\n\t\t\t\t\t\tcommand: \"CI= npx -y neonctl auth\",\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\"This will open your browser for Neon OAuth sign-in.\",\n\t\t\t\t\t\ttimeout: 120000,\n\t\t\t\t\t\tonSuccess: {\n\t\t\t\t\t\t\ttype: \"run_neon_init\",\n\t\t\t\t\t\t\targs: [\"auth\", \"--json\", \"--verify\"],\n\t\t\t\t\t\t},\n\t\t\t\t\t\tonFailure: {\n\t\t\t\t\t\t\t\"2\": {\n\t\t\t\t\t\t\t\ttype: \"ask_user\",\n\t\t\t\t\t\t\t\tquestion:\n\t\t\t\t\t\t\t\t\t\"The sign-in timed out. Did you complete the sign-in in your browser?\",\n\t\t\t\t\t\t\t\toptions: [\"yes_retry\", \"need_help\"],\n\t\t\t\t\t\t\t\tresponseMapping: {\n\t\t\t\t\t\t\t\t\tyes_retry: {\n\t\t\t\t\t\t\t\t\t\targs: [\n\t\t\t\t\t\t\t\t\t\t\t\"auth\",\n\t\t\t\t\t\t\t\t\t\t\t\"--json\",\n\t\t\t\t\t\t\t\t\t\t\t\"--method\",\n\t\t\t\t\t\t\t\t\t\t\t\"existing\",\n\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tneed_help: {\n\t\t\t\t\t\t\t\t\t\targs: [\n\t\t\t\t\t\t\t\t\t\t\t\"auth\",\n\t\t\t\t\t\t\t\t\t\t\t\"--json\",\n\t\t\t\t\t\t\t\t\t\t\t\"--method\",\n\t\t\t\t\t\t\t\t\t\t\t\"new\",\n\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tother: {\n\t\t\t\t\t\t\t\ttype: \"run_neon_init\",\n\t\t\t\t\t\t\t\targs: [\"auth\", \"--json\"],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tnew_account: {\n\t\t\t\t\taction: {\n\t\t\t\t\t\ttype: \"agent_action\",\n\t\t\t\t\t\tsteps: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tid: \"open_signup\",\n\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\"Open the Neon sign-up page in the user's browser\",\n\t\t\t\t\t\t\t\tcommand: openCmd,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tid: \"wait_for_signup\",\n\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\"Tell the user: 'I've opened the Neon sign-up page. Create your account and verify your email, then let me know when you're ready.'\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t\tonComplete: {\n\t\t\t\t\t\t\ttype: \"run_neon_init\",\n\t\t\t\t\t\t\targs: [\"auth\", \"--json\", \"--method\", \"existing\"],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t};\n}\n"],"mappings":";;AAGA,MAAM,kBAA0C;CAC/C,QAAQ;CACR,OAAO;CACP,OAAO;AACR;AAQA,eAAsB,gBACrB,SACyB;CACzB,MAAM,YAAY,QAAQ,QACvB;EAAC;EAAW,QAAQ;EAAO;CAAQ,IACnC,CAAC,QAAQ;CAGZ,IAAI,QAAQ,QAAQ;EAEnB,IAAI,MADiB,gBAAgB,GAIpC,OAAO;GACN,OAAO;GACP,QAAQ;GACR,YAAY;IACX,MAAM;IACN,MAAM;GACP;EACD;EAED,OAAO;GACN,OAAO;GACP,QAAQ;GACR,YAAY;IACX,MAAM;IACN,MAAM,CAAC,QAAQ,QAAQ;GACxB;EACD;CACD;CAIA,IAAI,MADiB,gBAAgB,GAEpC,OAAO;EACN,OAAO;EACP,QAAQ;EACR,YAAY;GACX,MAAM;GACN,MAAM;EACP;CACD;CAID,IAAI,QAAQ,WAAW,OAGtB,OAAO;EACN,OAAO;EACP,QAAQ;EACR,YAAY;GACX,MAAM;GACN,OAAO,CACN;IACC,IAAI;IACJ,aACC;IACD,SAXH,gBAAgB,QAAQ,aAAa,gBAAgB;GAYnD,GACA;IACC,IAAI;IACJ,aACC;GACF,CACD;GACA,YAAY;IACX,MAAM;IACN,MAAM;KAAC;KAAQ;KAAU;KAAY;IAAU;GAChD;EACD;CACD;CAID,IAAI,QAAQ,WAAW,YACtB,OAAO;EACN,OAAO;EACP,QAAQ;EACR,YAAY;GACX,MAAM;GACN,SAAS;GACT,aACC;GACD,SAAS;GACT,WAAW;IACV,MAAM;IACN,MAAM;KAAC;KAAQ;KAAU;IAAU;GACpC;GACA,WAAW;IACV,KAAK;KACJ,MAAM;KACN,UACC;KACD,SAAS,CAAC,aAAa,WAAW;KAClC,iBAAiB;MAChB,WAAW,EACV,MAAM;OACL;OACA;OACA;OACA;MACD,EACD;MACA,WAAW,EACV,MAAM;OAAC;OAAQ;OAAU;OAAY;MAAK,EAC3C;KACD;IACD;IACA,OAAO;KACN,MAAM;KACN,MAAM,CAAC,QAAQ,QAAQ;IACxB;GACD;EACD;CACD;CAMD,OAAO;EACN,OAAO;EACP,QAAQ;EACR,YAAY;GACX,MAAM;GACN,UACC;GACD,SAAS,CACR;IACC,OAAO;IACP,OAAO;GACR,GACA;IACC,OAAO;IACP,OAAO;GACR,CACD;GACA,SACC;GACD,iBAAiB;IAChB,kBAAkB,EACjB,QAAQ;KACP,MAAM;KACN,SAAS;KACT,aACC;KACD,SAAS;KACT,WAAW;MACV,MAAM;MACN,MAAM;OAAC;OAAQ;OAAU;MAAU;KACpC;KACA,WAAW;MACV,KAAK;OACJ,MAAM;OACN,UACC;OACD,SAAS,CAAC,aAAa,WAAW;OAClC,iBAAiB;QAChB,WAAW,EACV,MAAM;SACL;SACA;SACA;SACA;QACD,EACD;QACA,WAAW,EACV,MAAM;SACL;SACA;SACA;SACA;QACD,EACD;OACD;MACD;MACA,OAAO;OACN,MAAM;OACN,MAAM,CAAC,QAAQ,QAAQ;MACxB;KACD;IACD,EACD;IACA,aAAa,EACZ,QAAQ;KACP,MAAM;KACN,OAAO,CACN;MACC,IAAI;MACJ,aACC;MACD,SAxES,gBAAgB,QAAQ,aAAa,gBAAgB;KAyE/D,GACA;MACC,IAAI;MACJ,aACC;KACF,CACD;KACA,YAAY;MACX,MAAM;MACN,MAAM;OAAC;OAAQ;OAAU;OAAY;MAAU;KAChD;IACD,EACD;GACD;EACD;CACD;AACD"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { PhaseResponse } from "../types.js";
|
|
2
|
+
|
|
3
|
+
//#region src/lib/phases/cleanup.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Terminal phase: cleans up ephemeral _init state from .neon and
|
|
7
|
+
* returns a complete message. All feature chains should end here.
|
|
8
|
+
*/
|
|
9
|
+
declare function handleCleanup(): PhaseResponse;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { handleCleanup };
|
|
12
|
+
//# sourceMappingURL=cleanup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cleanup.d.ts","names":[],"sources":["../../../src/lib/phases/cleanup.ts"],"mappings":";;;;;;AAQA;;iBAAgB,aAAA,CAAA,GAAiB"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
//#region src/lib/phases/cleanup.ts
|
|
4
|
+
/**
|
|
5
|
+
* Terminal phase: cleans up ephemeral _init state from .neon and
|
|
6
|
+
* returns a complete message. All feature chains should end here.
|
|
7
|
+
*/
|
|
8
|
+
function handleCleanup() {
|
|
9
|
+
const neonContextPath = resolve(process.cwd(), ".neon");
|
|
10
|
+
if (existsSync(neonContextPath)) try {
|
|
11
|
+
const context = JSON.parse(readFileSync(neonContextPath, "utf-8"));
|
|
12
|
+
if (context._init !== void 0) {
|
|
13
|
+
delete context._init;
|
|
14
|
+
writeFileSync(neonContextPath, `${JSON.stringify(context, null, 2)}\n`);
|
|
15
|
+
}
|
|
16
|
+
} catch {}
|
|
17
|
+
return {
|
|
18
|
+
phase: "setup",
|
|
19
|
+
status: "complete",
|
|
20
|
+
nextAction: {
|
|
21
|
+
type: "complete",
|
|
22
|
+
message: "Neon setup is complete! Your database is connected and your agent has the Neon MCP server and skills available."
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
//#endregion
|
|
27
|
+
export { handleCleanup };
|
|
28
|
+
|
|
29
|
+
//# sourceMappingURL=cleanup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cleanup.js","names":[],"sources":["../../../src/lib/phases/cleanup.ts"],"sourcesContent":["import { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport type { PhaseResponse } from \"../types.js\";\n\n/**\n * Terminal phase: cleans up ephemeral _init state from .neon and\n * returns a complete message. All feature chains should end here.\n */\nexport function handleCleanup(): PhaseResponse {\n\tconst neonContextPath = resolve(process.cwd(), \".neon\");\n\tif (existsSync(neonContextPath)) {\n\t\ttry {\n\t\t\tconst context = JSON.parse(readFileSync(neonContextPath, \"utf-8\"));\n\t\t\tif (context._init !== undefined) {\n\t\t\t\tdelete context._init;\n\t\t\t\twriteFileSync(\n\t\t\t\t\tneonContextPath,\n\t\t\t\t\t`${JSON.stringify(context, null, 2)}\\n`,\n\t\t\t\t);\n\t\t\t}\n\t\t} catch {}\n\t}\n\n\treturn {\n\t\tphase: \"setup\",\n\t\tstatus: \"complete\",\n\t\tnextAction: {\n\t\t\ttype: \"complete\",\n\t\t\tmessage:\n\t\t\t\t\"Neon setup is complete! Your database is connected and your agent has the Neon MCP server and skills available.\",\n\t\t},\n\t};\n}\n"],"mappings":";;;;;;;AAQA,SAAgB,gBAA+B;CAC9C,MAAM,kBAAkB,QAAQ,QAAQ,IAAI,GAAG,OAAO;CACtD,IAAI,WAAW,eAAe,GAC7B,IAAI;EACH,MAAM,UAAU,KAAK,MAAM,aAAa,iBAAiB,OAAO,CAAC;EACjE,IAAI,QAAQ,UAAU,KAAA,GAAW;GAChC,OAAO,QAAQ;GACf,cACC,iBACA,GAAG,KAAK,UAAU,SAAS,MAAM,CAAC,EAAE,GACrC;EACD;CACD,QAAQ,CAAC;CAGV,OAAO;EACN,OAAO;EACP,QAAQ;EACR,YAAY;GACX,MAAM;GACN,SACC;EACF;CACD;AACD"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { PhaseResponse } from "../types.js";
|
|
2
|
+
|
|
3
|
+
//#region src/lib/phases/db.d.ts
|
|
4
|
+
interface DbPhaseOptions {
|
|
5
|
+
agent?: string;
|
|
6
|
+
orgId?: string;
|
|
7
|
+
projectId?: string;
|
|
8
|
+
orgsResult?: string;
|
|
9
|
+
projectsResult?: string;
|
|
10
|
+
framework?: string;
|
|
11
|
+
orm?: string;
|
|
12
|
+
error?: string;
|
|
13
|
+
}
|
|
14
|
+
declare function handleDbPhase(options: DbPhaseOptions): Promise<PhaseResponse>;
|
|
15
|
+
//#endregion
|
|
16
|
+
export { DbPhaseOptions, handleDbPhase };
|
|
17
|
+
//# sourceMappingURL=db.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db.d.ts","names":[],"sources":["../../../src/lib/phases/db.ts"],"mappings":";;;UAeiB,cAAA;;EAAA,KAAA,CAAA,EAAA,MAAA;EAWK,SAAA,CAAA,EAAA,MAAa;EAAA,UAAA,CAAA,EAAA,MAAA;gBACzB,CAAA,EAAA,MAAA;WACC,CAAA,EAAA,MAAA;KAAR,CAAA,EAAA,MAAA;EAAO,KAAA,CAAA,EAAA,MAAA;;iBAFY,aAAA,UACZ,iBACP,QAAQ"}
|