neon-init 0.12.1 → 0.13.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.d.ts +0 -1
- package/dist/cli.js +35 -1
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +8 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +36 -32
- package/dist/index.js.map +1 -1
- package/dist/lib/auth.d.ts.map +1 -1
- package/dist/lib/auth.js +11 -2
- package/dist/lib/auth.js.map +1 -1
- package/package.json +3 -1
package/dist/cli.d.ts
CHANGED
package/dist/cli.js
CHANGED
|
@@ -1,8 +1,42 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { init } from "./index.js";
|
|
3
|
+
import yargs from "yargs";
|
|
4
|
+
import { hideBin } from "yargs/helpers";
|
|
3
5
|
|
|
4
6
|
//#region src/cli.ts
|
|
5
|
-
|
|
7
|
+
const AGENT_FLAG_VALUES = [
|
|
8
|
+
"cursor",
|
|
9
|
+
"copilot",
|
|
10
|
+
"code"
|
|
11
|
+
];
|
|
12
|
+
function parseAgentToEditor(value) {
|
|
13
|
+
switch (value.trim().toLowerCase()) {
|
|
14
|
+
case "cursor": return "Cursor";
|
|
15
|
+
case "github-copilot":
|
|
16
|
+
case "copilot":
|
|
17
|
+
case "vs code":
|
|
18
|
+
case "vscode":
|
|
19
|
+
case "vs-code": return "VS Code";
|
|
20
|
+
case "claude-code":
|
|
21
|
+
case "claude cli":
|
|
22
|
+
case "claude-cli":
|
|
23
|
+
case "claude": return "Claude CLI";
|
|
24
|
+
default: return null;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const agentArg = yargs(hideBin(process.argv)).scriptName("neon-init").option("agent", {
|
|
28
|
+
alias: "a",
|
|
29
|
+
type: "string",
|
|
30
|
+
description: "Agent to configure (cursor, copilot, code)."
|
|
31
|
+
}).help().parseSync().agent;
|
|
32
|
+
if (agentArg !== void 0) {
|
|
33
|
+
const editor = parseAgentToEditor(agentArg);
|
|
34
|
+
if (editor === null) {
|
|
35
|
+
console.error(`Invalid --agent value: "${agentArg}". Supported: ${AGENT_FLAG_VALUES.join(", ")}`);
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
await init({ agent: editor });
|
|
39
|
+
} else await init();
|
|
6
40
|
|
|
7
41
|
//#endregion
|
|
8
42
|
export { };
|
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 { init } from \"./index.js\";\n\
|
|
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 { init } from \"./index.js\";\nimport type { Editor } from \"./lib/types.js\";\n\nconst AGENT_FLAG_VALUES = [\"cursor\", \"copilot\", \"code\"] as const;\n\nfunction parseAgentToEditor(value: string): Editor | null {\n\tconst normalized = value.trim().toLowerCase();\n\tswitch (normalized) {\n\t\tcase \"cursor\":\n\t\t\treturn \"Cursor\";\n\t\tcase \"github-copilot\":\n\t\tcase \"copilot\":\n\t\tcase \"vs code\":\n\t\tcase \"vscode\":\n\t\tcase \"vs-code\":\n\t\t\treturn \"VS Code\";\n\t\tcase \"claude-code\":\n\t\tcase \"claude cli\":\n\t\tcase \"claude-cli\":\n\t\tcase \"claude\":\n\t\t\treturn \"Claude CLI\";\n\t\tdefault:\n\t\t\treturn null;\n\t}\n}\n\nconst argv = yargs(hideBin(process.argv))\n\t.scriptName(\"neon-init\")\n\t.option(\"agent\", {\n\t\talias: \"a\",\n\t\ttype: \"string\",\n\t\tdescription: \"Agent to configure (cursor, copilot, code).\",\n\t})\n\t.help()\n\t.parseSync();\n\nconst agentArg = argv.agent;\nif (agentArg !== undefined) {\n\tconst editor = parseAgentToEditor(agentArg);\n\tif (editor === null) {\n\t\tconsole.error(\n\t\t\t`Invalid --agent value: \"${agentArg}\". Supported: ${AGENT_FLAG_VALUES.join(\", \")}`,\n\t\t);\n\t\tprocess.exit(1);\n\t}\n\tawait init({ agent: editor });\n} else {\n\tawait init();\n}\n"],"mappings":";;;;;;AAOA,MAAM,oBAAoB;CAAC;CAAU;CAAW;CAAO;AAEvD,SAAS,mBAAmB,OAA8B;AAEzD,SADmB,MAAM,MAAM,CAAC,aAAa,EAC7C;EACC,KAAK,SACJ,QAAO;EACR,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK,UACJ,QAAO;EACR,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK,SACJ,QAAO;EACR,QACC,QAAO;;;AAcV,MAAM,WAVO,MAAM,QAAQ,QAAQ,KAAK,CAAC,CACvC,WAAW,YAAY,CACvB,OAAO,SAAS;CAChB,OAAO;CACP,MAAM;CACN,aAAa;CACb,CAAC,CACD,MAAM,CACN,WAAW,CAES;AACtB,IAAI,aAAa,QAAW;CAC3B,MAAM,SAAS,mBAAmB,SAAS;AAC3C,KAAI,WAAW,MAAM;AACpB,UAAQ,MACP,2BAA2B,SAAS,gBAAgB,kBAAkB,KAAK,KAAK,GAChF;AACD,UAAQ,KAAK,EAAE;;AAEhB,OAAM,KAAK,EAAE,OAAO,QAAQ,CAAC;MAE7B,OAAM,MAAM"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
|
+
import { Editor } from "./lib/types.js";
|
|
2
|
+
|
|
1
3
|
//#region src/index.d.ts
|
|
4
|
+
interface InitOptions {
|
|
5
|
+
/** When set, configures only this agent and skips the editor selection prompt. */
|
|
6
|
+
agent?: Editor;
|
|
7
|
+
}
|
|
2
8
|
/**
|
|
3
9
|
* Initialize Neon projects with MCP Server
|
|
4
10
|
*/
|
|
5
|
-
declare function init(): Promise<void>;
|
|
11
|
+
declare function init(options?: InitOptions): Promise<void>;
|
|
6
12
|
//#endregion
|
|
7
|
-
export { init };
|
|
13
|
+
export { InitOptions, init };
|
|
8
14
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"sourcesContent":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"sourcesContent":[],"mappings":";;;UAgBiB,WAAA;;EAAA,KAAA,CAAA,EAER,MAFmB;AAQ5B;;;;AAA0D,iBAApC,IAAA,CAAoC,OAAA,CAAA,EAArB,WAAqB,CAAA,EAAP,OAAO,CAAA,IAAA,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -9,8 +9,8 @@ import { bold, cyan } from "yoctocolors";
|
|
|
9
9
|
/**
|
|
10
10
|
* Initialize Neon projects with MCP Server
|
|
11
11
|
*/
|
|
12
|
-
async function init() {
|
|
13
|
-
intro("Adding Neon
|
|
12
|
+
async function init(options) {
|
|
13
|
+
intro("Adding Neon MCP server, extension (for VS Code and Cursor) and agent skills");
|
|
14
14
|
const homeDir = process.env.HOME || process.env.USERPROFILE;
|
|
15
15
|
if (!homeDir) {
|
|
16
16
|
log.error("Could not determine home directory");
|
|
@@ -18,41 +18,45 @@ async function init() {
|
|
|
18
18
|
process.exit(1);
|
|
19
19
|
}
|
|
20
20
|
const workspaceDir = process.cwd();
|
|
21
|
-
|
|
22
|
-
if (
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
21
|
+
let selectedEditors;
|
|
22
|
+
if (options?.agent !== void 0) selectedEditors = [options.agent];
|
|
23
|
+
else {
|
|
24
|
+
const availableEditors = await detectAvailableEditors(homeDir);
|
|
25
|
+
if (availableEditors.length === 0) {
|
|
26
|
+
log.warn("No supported editors detected on your system.");
|
|
27
|
+
log.info("Supported editors:");
|
|
28
|
+
log.info(" • VS Code (with Neon Local Connect extension)");
|
|
29
|
+
log.info(" • Cursor (with Neon Local Connect extension)");
|
|
30
|
+
log.info(" • Claude CLI (with MCP Server)");
|
|
31
|
+
const continueAnyway = await confirm({
|
|
32
|
+
message: "Would you like to configure Neon anyway? (You can manually select your editor)",
|
|
33
|
+
initialValue: true
|
|
34
|
+
});
|
|
35
|
+
if (isCancel(continueAnyway) || !continueAnyway) {
|
|
36
|
+
outro("Installation cancelled");
|
|
37
|
+
process.exit(0);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const response = await multiselect({
|
|
41
|
+
message: "Which editor(s) would you like to configure? (Space to toggle each option, Enter to confirm your selection)",
|
|
42
|
+
options: [
|
|
43
|
+
"Cursor",
|
|
44
|
+
"VS Code",
|
|
45
|
+
"Claude CLI"
|
|
46
|
+
].map((editor) => ({
|
|
47
|
+
value: editor,
|
|
48
|
+
label: editor,
|
|
49
|
+
hint: editor === "Claude CLI" ? "MCP Server" : "Neon Local Connect extension"
|
|
50
|
+
})),
|
|
51
|
+
initialValues: availableEditors,
|
|
52
|
+
required: true
|
|
31
53
|
});
|
|
32
|
-
if (isCancel(
|
|
54
|
+
if (isCancel(response)) {
|
|
33
55
|
outro("Installation cancelled");
|
|
34
56
|
process.exit(0);
|
|
35
57
|
}
|
|
58
|
+
selectedEditors = response;
|
|
36
59
|
}
|
|
37
|
-
const response = await multiselect({
|
|
38
|
-
message: "Which editor(s) would you like to configure? (Space to toggle each option, Enter to confirm your selection)",
|
|
39
|
-
options: [
|
|
40
|
-
"Cursor",
|
|
41
|
-
"VS Code",
|
|
42
|
-
"Claude CLI"
|
|
43
|
-
].map((editor) => ({
|
|
44
|
-
value: editor,
|
|
45
|
-
label: editor,
|
|
46
|
-
hint: editor === "Claude CLI" ? "MCP Server" : "Neon Local Connect extension"
|
|
47
|
-
})),
|
|
48
|
-
initialValues: availableEditors,
|
|
49
|
-
required: true
|
|
50
|
-
});
|
|
51
|
-
if (isCancel(response)) {
|
|
52
|
-
outro("Installation cancelled");
|
|
53
|
-
process.exit(0);
|
|
54
|
-
}
|
|
55
|
-
const selectedEditors = response;
|
|
56
60
|
if (selectedEditors.length === 0) {
|
|
57
61
|
log.warn("No editors selected.");
|
|
58
62
|
outro("Installation cancelled");
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import {\n\tconfirm,\n\tintro,\n\tisCancel,\n\tlog,\n\tmultiselect,\n\tnote,\n\toutro,\n} from \"@clack/prompts\";\nimport { bold, cyan } from \"yoctocolors\";\nimport { detectAvailableEditors } from \"./lib/editors.js\";\nimport { usesExtension } from \"./lib/extension.js\";\nimport { installNeon } from \"./lib/install.js\";\nimport { installAgentSkills } from \"./lib/skills.js\";\nimport type { Editor } from \"./lib/types.js\";\n\n/**\n * Initialize Neon projects with MCP Server\n */\nexport async function init(): Promise<void> {\n\tintro(\"Adding Neon
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import {\n\tconfirm,\n\tintro,\n\tisCancel,\n\tlog,\n\tmultiselect,\n\tnote,\n\toutro,\n} from \"@clack/prompts\";\nimport { bold, cyan } from \"yoctocolors\";\nimport { detectAvailableEditors } from \"./lib/editors.js\";\nimport { usesExtension } from \"./lib/extension.js\";\nimport { installNeon } from \"./lib/install.js\";\nimport { installAgentSkills } from \"./lib/skills.js\";\nimport type { Editor } from \"./lib/types.js\";\n\nexport interface InitOptions {\n\t/** When set, configures only this agent and skips the editor selection prompt. */\n\tagent?: Editor;\n}\n\n/**\n * Initialize Neon projects with MCP Server\n */\nexport async function init(options?: InitOptions): Promise<void> {\n\tintro(\n\t\t\"Adding Neon MCP server, extension (for VS Code and Cursor) and agent skills\",\n\t);\n\n\t// Get the home directory\n\tconst homeDir = process.env.HOME || process.env.USERPROFILE;\n\tif (!homeDir) {\n\t\tlog.error(\"Could not determine home directory\");\n\t\toutro(\"📣 Is this unexpected? Email us at feedback@neon.tech\");\n\t\tprocess.exit(1);\n\t}\n\n\t// Get the current workspace directory\n\tconst workspaceDir = process.cwd();\n\n\tlet selectedEditors: Editor[];\n\n\tif (options?.agent !== undefined) {\n\t\tselectedEditors = [options.agent];\n\t} else {\n\t\t// Detect available editors\n\t\tconst availableEditors = await detectAvailableEditors(homeDir);\n\n\t\t// If no editors detected, offer to continue anyway\n\t\tif (availableEditors.length === 0) {\n\t\t\tlog.warn(\"No supported editors detected on your system.\");\n\t\t\tlog.info(\"Supported editors:\");\n\t\t\tlog.info(\" • VS Code (with Neon Local Connect extension)\");\n\t\t\tlog.info(\" • Cursor (with Neon Local Connect extension)\");\n\t\t\tlog.info(\" • Claude CLI (with MCP Server)\");\n\n\t\t\tconst continueAnyway = await confirm({\n\t\t\t\tmessage:\n\t\t\t\t\t\"Would you like to configure Neon anyway? (You can manually select your editor)\",\n\t\t\t\tinitialValue: true,\n\t\t\t});\n\n\t\t\tif (isCancel(continueAnyway) || !continueAnyway) {\n\t\t\t\toutro(\"Installation cancelled\");\n\t\t\t\tprocess.exit(0);\n\t\t\t}\n\t\t}\n\n\t\t// Determine which editors to configure\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: [\"Cursor\", \"VS Code\", \"Claude CLI\"].map((editor) => ({\n\t\t\t\tvalue: editor,\n\t\t\t\tlabel: editor,\n\t\t\t\thint:\n\t\t\t\t\teditor === \"Claude CLI\"\n\t\t\t\t\t\t? \"MCP Server\"\n\t\t\t\t\t\t: \"Neon Local Connect extension\",\n\t\t\t})),\n\t\t\tinitialValues: availableEditors, // Select detected editors by default\n\t\t\trequired: true,\n\t\t});\n\n\t\tif (isCancel(response)) {\n\t\t\toutro(\"Installation cancelled\");\n\t\t\tprocess.exit(0);\n\t\t}\n\n\t\tselectedEditors = response as Editor[];\n\t}\n\n\tif (selectedEditors.length === 0) {\n\t\tlog.warn(\"No editors selected.\");\n\t\toutro(\"Installation cancelled\");\n\t\tprocess.exit(0);\n\t}\n\n\t// Install Neon for selected editors\n\tconst results = await installNeon(homeDir, workspaceDir, selectedEditors);\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\t// Install agent skills for successful installations\n\tif (successful.length > 0) {\n\t\tawait installAgentSkills(successful);\n\t}\n\n\t// Show different messages based on what was installed\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\t// Show helpful installation links for failed extension installations\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}\n\n\t// Exit with error if all installations failed\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\tprocess.exit(1);\n\t}\n\n\tif (extensionEditors.length > 0 && mcpEditors.length === 0) {\n\t\t// Only extension editors (VS Code/Cursor)\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\t// Only MCP editors (Claude CLI)\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\t// Mixed editors\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"],"mappings":"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"}
|
package/dist/lib/auth.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","names":[],"sources":["../../src/lib/auth.ts"],"sourcesContent":[],"mappings":";;AASA;
|
|
1
|
+
{"version":3,"file":"auth.d.ts","names":[],"sources":["../../src/lib/auth.ts"],"sourcesContent":[],"mappings":";;AASA;AAqDA;;iBArDsB,iBAAA,CAAA,GAAqB;;;;iBAqDrB,uBAAA,CAAA,GAA2B"}
|
package/dist/lib/auth.js
CHANGED
|
@@ -9,16 +9,25 @@ import { execa } from "execa";
|
|
|
9
9
|
* This will automatically start the OAuth flow if the user isn't already authenticated
|
|
10
10
|
*/
|
|
11
11
|
async function ensureNeonctlAuth() {
|
|
12
|
+
if (await getNeonctlAccessToken()) return true;
|
|
12
13
|
try {
|
|
13
14
|
await execa("npx", [
|
|
14
15
|
"-y",
|
|
15
16
|
"neonctl",
|
|
16
17
|
"me",
|
|
17
18
|
"--no-analytics"
|
|
18
|
-
], {
|
|
19
|
+
], {
|
|
20
|
+
stdio: "inherit",
|
|
21
|
+
env: {
|
|
22
|
+
...process.env,
|
|
23
|
+
CI: void 0
|
|
24
|
+
}
|
|
25
|
+
});
|
|
19
26
|
return true;
|
|
20
27
|
} catch (error) {
|
|
21
|
-
|
|
28
|
+
const msg = error instanceof Error ? error.message : "Unknown error";
|
|
29
|
+
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.");
|
|
30
|
+
else log.error(`Authentication failed: ${msg}`);
|
|
22
31
|
return false;
|
|
23
32
|
}
|
|
24
33
|
}
|
package/dist/lib/auth.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","names":[],"sources":["../../src/lib/auth.ts"],"sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { log } from \"@clack/prompts\";\nimport { execa } from \"execa\";\n\n/**\n * Ensures neonctl is authenticated by running a command that triggers auth if needed\n * This will automatically start the OAuth flow if the user isn't already authenticated\n */\nexport async function ensureNeonctlAuth(): Promise<boolean> {\n\ttry {\n\t\t// Use execa to authenticate with neonctl\n\t\tawait execa(\"npx\", [\"-y\", \"neonctl\", \"me\", \"--no-analytics\"], {\n\t\t\tstdio: \"inherit\"
|
|
1
|
+
{"version":3,"file":"auth.js","names":[],"sources":["../../src/lib/auth.ts"],"sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { log } from \"@clack/prompts\";\nimport { execa } from \"execa\";\n\n/**\n * Ensures neonctl is authenticated by running a command that triggers auth if needed\n * This will automatically start the OAuth flow if the user isn't already authenticated\n */\nexport async function ensureNeonctlAuth(): Promise<boolean> {\n\t// If already authenticated (e.g. ran in a terminal before), we can proceed\n\tconst existingToken = await getNeonctlAccessToken();\n\tif (existingToken) return true;\n\n\ttry {\n\t\t// Use execa to authenticate with neonctl\n\t\tawait execa(\"npx\", [\"-y\", \"neonctl\", \"me\", \"--no-analytics\"], {\n\t\t\t// Shows OAuth URL and prompts to the user\n\t\t\tstdio: \"inherit\",\n\t\t\t// Unset CI so neonctl doesn't refuse to open the browser (e.g. when run from agent chat)\n\t\t\tenv: { ...process.env, CI: undefined },\n\t\t});\n\t\treturn true;\n\t} catch (error) {\n\t\tconst msg = error instanceof Error ? error.message : \"Unknown error\";\n\t\tif (msg.includes(\"interactive auth\") || msg.includes(\"CI\")) {\n\t\t\tlog.error(\n\t\t\t\t\"Auth requires an interactive terminal. Run neon-init in your system terminal (outside the chat) to sign in.\",\n\t\t\t);\n\t\t} else {\n\t\t\tlog.error(`Authentication failed: ${msg}`);\n\t\t}\n\t\treturn false;\n\t}\n}\n\n/**\n * Gets the OAuth access token from neonctl's stored credentials\n */\nasync function getNeonctlAccessToken(): Promise<string | null> {\n\ttry {\n\t\tconst homeDir = process.env.HOME || process.env.USERPROFILE;\n\t\tif (!homeDir) return null;\n\n\t\tconst credentialsPath = resolve(\n\t\t\thomeDir,\n\t\t\t\".config\",\n\t\t\t\"neonctl\",\n\t\t\t\"credentials.json\",\n\t\t);\n\t\tif (!existsSync(credentialsPath)) return null;\n\n\t\tconst credentials = JSON.parse(readFileSync(credentialsPath, \"utf-8\"));\n\t\treturn credentials.access_token || null;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n/**\n * Creates an API key using the Neon API with the OAuth token from neonctl\n */\nexport async function createApiKeyFromNeonctl(): Promise<string | null> {\n\ttry {\n\t\tconst accessToken = await getNeonctlAccessToken();\n\t\tif (!accessToken) {\n\t\t\tlog.error(\"Could not find OAuth token from neonctl\");\n\t\t\treturn null;\n\t\t}\n\n\t\t// Generate a unique key name with timestamp\n\t\tconst timestamp = new Date()\n\t\t\t.toISOString()\n\t\t\t.replace(/[:.]/g, \"-\")\n\t\t\t.slice(0, -5); // e.g., 2024-10-08T15-30-45\n\t\tconst keyName = `neonctl-init-${timestamp}`;\n\n\t\t// Call Neon API to create an API key\n\t\tconst response = await fetch(\n\t\t\t\"https://console.neon.tech/api/v2/api_keys\",\n\t\t\t{\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: {\n\t\t\t\t\tAuthorization: `Bearer ${accessToken}`,\n\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t},\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\tkey_name: keyName,\n\t\t\t\t}),\n\t\t\t},\n\t\t);\n\n\t\tif (!response.ok) {\n\t\t\tconst errorText = await response.text();\n\t\t\tlog.error(\n\t\t\t\t`Failed to create API key: ${response.status} ${errorText}`,\n\t\t\t);\n\t\t\treturn null;\n\t\t}\n\n\t\tconst data = await response.json();\n\t\treturn data.key || null;\n\t} catch (error) {\n\t\tlog.error(\n\t\t\t`Failed to create API key: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n\t\t);\n\t\treturn null;\n\t}\n}\n"],"mappings":";;;;;;;;;;AASA,eAAsB,oBAAsC;AAG3D,KADsB,MAAM,uBAAuB,CAChC,QAAO;AAE1B,KAAI;AAEH,QAAM,MAAM,OAAO;GAAC;GAAM;GAAW;GAAM;GAAiB,EAAE;GAE7D,OAAO;GAEP,KAAK;IAAE,GAAG,QAAQ;IAAK,IAAI;IAAW;GACtC,CAAC;AACF,SAAO;UACC,OAAO;EACf,MAAM,MAAM,iBAAiB,QAAQ,MAAM,UAAU;AACrD,MAAI,IAAI,SAAS,mBAAmB,IAAI,IAAI,SAAS,KAAK,CACzD,KAAI,MACH,8GACA;MAED,KAAI,MAAM,0BAA0B,MAAM;AAE3C,SAAO;;;;;;AAOT,eAAe,wBAAgD;AAC9D,KAAI;EACH,MAAM,UAAU,QAAQ,IAAI,QAAQ,QAAQ,IAAI;AAChD,MAAI,CAAC,QAAS,QAAO;EAErB,MAAM,kBAAkB,QACvB,SACA,WACA,WACA,mBACA;AACD,MAAI,CAAC,WAAW,gBAAgB,CAAE,QAAO;AAGzC,SADoB,KAAK,MAAM,aAAa,iBAAiB,QAAQ,CAAC,CACnD,gBAAgB;SAC5B;AACP,SAAO;;;;;;AAOT,eAAsB,0BAAkD;AACvE,KAAI;EACH,MAAM,cAAc,MAAM,uBAAuB;AACjD,MAAI,CAAC,aAAa;AACjB,OAAI,MAAM,0CAA0C;AACpD,UAAO;;EAQR,MAAM,UAAU,iCAJE,IAAI,MAAM,EAC1B,aAAa,CACb,QAAQ,SAAS,IAAI,CACrB,MAAM,GAAG,GAAG;EAId,MAAM,WAAW,MAAM,MACtB,6CACA;GACC,QAAQ;GACR,SAAS;IACR,eAAe,UAAU;IACzB,gBAAgB;IAChB;GACD,MAAM,KAAK,UAAU,EACpB,UAAU,SACV,CAAC;GACF,CACD;AAED,MAAI,CAAC,SAAS,IAAI;GACjB,MAAM,YAAY,MAAM,SAAS,MAAM;AACvC,OAAI,MACH,6BAA6B,SAAS,OAAO,GAAG,YAChD;AACD,UAAO;;AAIR,UADa,MAAM,SAAS,MAAM,EACtB,OAAO;UACX,OAAO;AACf,MAAI,MACH,6BAA6B,iBAAiB,QAAQ,MAAM,UAAU,kBACtE;AACD,SAAO"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "neon-init",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "Initialize Neon projects",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"neon",
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
],
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@types/node": "^20.19.0",
|
|
38
|
+
"@types/yargs": "^17.0.35",
|
|
38
39
|
"@vitest/coverage-v8": "3.0.9",
|
|
39
40
|
"console-fail-test": "0.5.0",
|
|
40
41
|
"tsdown": "^0.14.1",
|
|
@@ -44,6 +45,7 @@
|
|
|
44
45
|
"dependencies": {
|
|
45
46
|
"@clack/prompts": "0.10.1",
|
|
46
47
|
"execa": "^9.5.2",
|
|
48
|
+
"yargs": "^18.0.0",
|
|
47
49
|
"yoctocolors": "^2.1.2"
|
|
48
50
|
},
|
|
49
51
|
"engines": {
|