neon-init 0.4.1 → 0.7.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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"sourcesContent":[],"mappings":";;AA6bA;;iBAAsB,IAAA,CAAA,GAAQ"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"sourcesContent":[],"mappings":";;AAsdA;;iBAAsB,IAAA,CAAA,GAAQ"}
package/dist/index.js CHANGED
@@ -4,6 +4,7 @@ import { dirname, resolve } from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
5
  import { promisify } from "node:util";
6
6
  import { confirm, intro, isCancel, log, outro, select, spinner } from "@clack/prompts";
7
+ import { execa } from "execa";
7
8
 
8
9
  //#region src/index.ts
9
10
  const execAsync = promisify(exec);
@@ -14,22 +15,14 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
14
15
  */
15
16
  async function ensureNeonctlAuth() {
16
17
  try {
17
- const { spawn } = await import("node:child_process");
18
- await new Promise((resolve$1, reject) => {
19
- const meProcess = spawn("npx", [
20
- "-y",
21
- "neon",
22
- "me",
23
- "--output",
24
- "json",
25
- "--no-analytics"
26
- ], { stdio: "inherit" });
27
- meProcess.on("close", (code) => {
28
- if (code === 0) resolve$1();
29
- else reject(/* @__PURE__ */ new Error(`Authentication failed with exit code ${code}`));
30
- });
31
- meProcess.on("error", reject);
32
- });
18
+ await execa("npx", [
19
+ "-y",
20
+ "neonctl",
21
+ "me",
22
+ "--output",
23
+ "json",
24
+ "--no-analytics"
25
+ ], { stdio: "inherit" });
33
26
  return true;
34
27
  } catch (error) {
35
28
  log.error(`Authentication failed: ${error instanceof Error ? error.message : "Unknown error"}`);
@@ -82,7 +75,7 @@ async function createApiKeyFromNeonctl() {
82
75
  }
83
76
  async function fetchOrganizations() {
84
77
  try {
85
- const { stdout } = await execAsync("npx -y neon orgs list --output json --no-analytics", { maxBuffer: 1024 * 1024 });
78
+ const { stdout } = await execAsync("npx -y neonctl orgs list --output json --no-analytics", { maxBuffer: 1024 * 1024 });
86
79
  const data = JSON.parse(stdout);
87
80
  return Array.isArray(data) ? data.map((org) => ({
88
81
  id: org.id,
@@ -116,13 +109,13 @@ function writeMCPConfig(cursorDir, config) {
116
109
  writeFileSync(mcpConfigPath, JSON.stringify(config, null, 2), "utf-8");
117
110
  }
118
111
  /**
119
- * Gets the AGENTS.md template with Neon-specific best practices
112
+ * Gets the neon.md template with Neon-specific best practices
120
113
  */
121
- function getAgentsMdTemplate() {
114
+ function getNeonMdTemplate() {
122
115
  return readFileSync(resolve(__dirname, "../src/agents-template.md"), "utf-8");
123
116
  }
124
117
  /**
125
- * Generates the organization configuration section for AGENTS.md
118
+ * Generates the organization configuration section for neon.md
126
119
  */
127
120
  function getOrgConfigSection(orgId) {
128
121
  return `## Neon Project Configuration
@@ -142,35 +135,66 @@ When using any Neon MCP tools or API calls, always pass this \`org_id\` paramete
142
135
  `;
143
136
  }
144
137
  /**
145
- * Creates or updates AGENTS.md with Neon-specific best practices
138
+ * Gets the reference text to add to AGENTS.md
139
+ */
140
+ function getAgentsNeonReference() {
141
+ return `## Working with Neon Database
142
+
143
+ When the user asks to **"Get started with Neon"** or something similar, refer to the detailed guidelines in \`neon.md\`.`;
144
+ }
145
+ /**
146
+ * Creates or updates neon.md with detailed Neon guidelines
147
+ */
148
+ async function createNeonMd(orgId) {
149
+ const neonMdPath = resolve(process.cwd(), "neon.md");
150
+ try {
151
+ if (existsSync(neonMdPath)) {
152
+ log.info("neon.md already exists");
153
+ const response = await confirm({
154
+ message: "Replace existing neon.md with updated guidelines? (suggested)",
155
+ initialValue: true
156
+ });
157
+ if (isCancel(response)) return false;
158
+ if (!response) {
159
+ log.info("Keeping existing neon.md");
160
+ return true;
161
+ }
162
+ }
163
+ let content = "";
164
+ if (orgId) content += getOrgConfigSection(orgId);
165
+ content += getNeonMdTemplate();
166
+ writeFileSync(neonMdPath, content, "utf-8");
167
+ log.success(`Created neon.md with detailed guidelines at ${neonMdPath}`);
168
+ return true;
169
+ } catch (error) {
170
+ log.error(`Failed to create neon.md: ${error instanceof Error ? error.message : "Unknown error"}`);
171
+ return false;
172
+ }
173
+ }
174
+ /**
175
+ * Creates or updates AGENTS.md with a reference to neon.md
146
176
  */
147
- async function createAgentsMd(orgId) {
177
+ async function createAgentsMd() {
148
178
  const agentsPath = resolve(process.cwd(), "AGENTS.md");
149
179
  try {
180
+ const neonReference = getAgentsNeonReference();
150
181
  if (existsSync(agentsPath)) {
151
182
  const existingContent = readFileSync(agentsPath, "utf-8");
152
- if (existingContent.includes("## Neon Database Guidelines")) {
153
- log.info("Neon guidelines already exist in AGENTS.md");
183
+ if (existingContent.includes("## Working with Neon Database")) {
184
+ log.info("Neon reference already exists in AGENTS.md");
154
185
  return true;
155
186
  }
156
- const separator = "\n\n---\n\n";
157
- let content = "";
158
- if (orgId) content += getOrgConfigSection(orgId);
159
- content += getAgentsMdTemplate();
160
- writeFileSync(agentsPath, existingContent + separator + content, "utf-8");
161
- log.success(`Appended Neon best practices to existing AGENTS.md at ${agentsPath}`);
187
+ writeFileSync(agentsPath, existingContent + "\n\n---\n\n" + neonReference, "utf-8");
188
+ log.success(`Appended Neon reference to existing AGENTS.md at ${agentsPath}`);
162
189
  } else {
163
- let content = "";
164
- if (orgId) content += getOrgConfigSection(orgId);
165
- content += getAgentsMdTemplate();
166
190
  writeFileSync(agentsPath, `# AGENTS.md
167
191
 
168
192
  This file provides guidance to AI coding assistants when working with code in this project.
169
193
 
170
194
  ---
171
195
 
172
- ${content}`, "utf-8");
173
- log.success(`Created AGENTS.md with Neon best practices at ${agentsPath}`);
196
+ ${neonReference}`, "utf-8");
197
+ log.success(`Created AGENTS.md with Neon reference at ${agentsPath}`);
174
198
  }
175
199
  return true;
176
200
  } catch (error) {
@@ -195,8 +219,8 @@ async function installMCPServer() {
195
219
  if (alreadyConfigured) {
196
220
  log.info("Neon MCP Server is already configured globally");
197
221
  const response = await confirm({
198
- message: "Would you like to reconfigure it?",
199
- initialValue: false
222
+ message: "Would you like to reconfigure it? (suggested)",
223
+ initialValue: true
200
224
  });
201
225
  if (isCancel(response)) return { success: false };
202
226
  shouldReconfigure = response;
@@ -246,15 +270,9 @@ async function installMCPServer() {
246
270
  log.info("You can manually create one at: https://console.neon.tech/app/settings/api-keys");
247
271
  return { success: false };
248
272
  }
249
- const args = [
250
- "-y",
251
- "@neondatabase/mcp-server-neon",
252
- "start",
253
- apiKey
254
- ];
255
273
  config.mcpServers.Neon = {
256
- command: "npx",
257
- args
274
+ url: "https://mcp.neon.tech/mcp",
275
+ headers: { Authorization: `Bearer ${apiKey}` }
258
276
  };
259
277
  try {
260
278
  writeMCPConfig(cursorDir, config);
@@ -274,24 +292,44 @@ async function installMCPServer() {
274
292
  */
275
293
  async function init() {
276
294
  intro("🚀 Neon Project Initialization");
295
+ const homeDir = process.env.HOME || process.env.USERPROFILE;
296
+ if (!homeDir) {
297
+ log.error("Could not determine home directory");
298
+ process.exit(1);
299
+ }
300
+ if (!existsSync(resolve(homeDir, ".cursor"))) {
301
+ log.warn("This tool currently only supports Cursor IDE.");
302
+ log.info("We'd love to hear which IDE you're using!");
303
+ log.info("");
304
+ log.info("Please send your feedback to: init-feedback@neon.tech");
305
+ log.info("");
306
+ outro("❌ Cursor IDE is required to continue.");
307
+ process.exit(1);
308
+ }
277
309
  log.info("This will set up your project with Neon's MCP Server and AI coding best practices.");
278
- log.step("Step 1/2: Configuring Neon MCP Server");
310
+ log.step("Step 1/3: Configuring Neon MCP Server...");
279
311
  const { success: mcpSuccess, orgId } = await installMCPServer();
280
312
  if (!mcpSuccess) {
281
313
  outro("❌ Initialization cancelled or failed.");
282
314
  process.exit(1);
283
315
  }
284
- log.step("Step 2/2: Creating AGENTS.md with Neon best practices");
285
- if (!await createAgentsMd(orgId)) log.warn("Failed to create AGENTS.md, but MCP Server is configured.");
316
+ log.step("Step 2/3: Creating neon.md with detailed guidelines...");
317
+ if (!await createNeonMd(orgId)) log.warn("Failed to create neon.md, but MCP Server is configured.");
318
+ log.step("Step 3/3: Creating AGENTS.md for Cursor...");
319
+ if (!await createAgentsMd()) log.warn("Failed to create AGENTS.md, but MCP Server is configured.");
286
320
  outro("Success! Neon project initialized.");
287
321
  console.log("");
288
322
  console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
289
323
  console.log("");
324
+ console.log("⚠️ The init command is still in its early stages.");
325
+ console.log(" We'd appreciate any feedback! Send us an email at:");
326
+ console.log(" init-feedback@neon.tech");
327
+ console.log("");
290
328
  console.log("Next steps:");
291
329
  console.log("");
292
- console.log(" 1. Restart your AI coding assistant (Cursor, Windsurf, etc.)");
330
+ console.log(" 1. Restart Cursor");
293
331
  console.log("");
294
- console.log(" 2. Type this in your AI chat to begin:");
332
+ console.log(" 2. Type this in your Cursor chat to begin:");
295
333
  console.log("");
296
334
  console.log(" ┌──────────────────────────────────────┐");
297
335
  console.log(" │ │");
@@ -299,7 +337,8 @@ async function init() {
299
337
  console.log(" │ │");
300
338
  console.log(" └──────────────────────────────────────┘");
301
339
  console.log("");
302
- console.log("Your AI assistant now has access to Neon best practices via AGENTS.md");
340
+ console.log("Your AI assistant now has access to Neon best practices via neon.md");
341
+ console.log("(referenced in AGENTS.md for easy discovery)");
303
342
  console.log("");
304
343
  console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
305
344
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["selectedOrgId: string | undefined"],"sources":["../src/index.ts"],"sourcesContent":["import { exec } from \"node:child_process\";\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { promisify } from \"node:util\";\nimport {\n\tconfirm,\n\tintro,\n\tisCancel,\n\tlog,\n\toutro,\n\tselect,\n\tspinner,\n} from \"@clack/prompts\";\n\nconst execAsync = promisify(exec);\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\ninterface MCPConfig {\n\tmcpServers: {\n\t\t[key: string]: {\n\t\t\tcommand: string;\n\t\t\targs: string[];\n\t\t\tenv?: Record<string, string>;\n\t\t};\n\t};\n}\n\ninterface NeonOrganization {\n\tid: string;\n\tname: string;\n}\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 */\nasync function ensureNeonctlAuth(): Promise<boolean> {\n\ttry {\n\t\t// Use spawn to show OAuth URL if authentication is needed\n\t\tconst { spawn } = await import(\"node:child_process\");\n\n\t\tawait new Promise<void>((resolve, reject) => {\n\t\t\tconst meProcess = spawn(\n\t\t\t\t\"npx\",\n\t\t\t\t[\"-y\", \"neon\", \"me\", \"--output\", \"json\", \"--no-analytics\"],\n\t\t\t\t{\n\t\t\t\t\tstdio: \"inherit\", // Shows OAuth URL and prompts to the user\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tmeProcess.on(\"close\", (code) => {\n\t\t\t\tif (code === 0) {\n\t\t\t\t\tresolve();\n\t\t\t\t} else {\n\t\t\t\t\treject(\n\t\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\t`Authentication failed with exit code ${code}`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tmeProcess.on(\"error\", reject);\n\t\t});\n\n\t\treturn true;\n\t} catch (error) {\n\t\tlog.error(\n\t\t\t`Authentication failed: ${error instanceof Error ? error.message : \"Unknown error\"}`,\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 */\nasync 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\nasync function fetchOrganizations(): Promise<NeonOrganization[]> {\n\ttry {\n\t\tconst { stdout } = await execAsync(\n\t\t\t\"npx -y neon orgs list --output json --no-analytics\",\n\t\t\t{ maxBuffer: 1024 * 1024 },\n\t\t);\n\n\t\tconst data = JSON.parse(stdout);\n\n\t\t// The neon CLI returns an array of organizations\n\t\tconst organizations: NeonOrganization[] = Array.isArray(data)\n\t\t\t? data.map((org: { id: string; name?: string }) => ({\n\t\t\t\t\tid: org.id,\n\t\t\t\t\tname: org.name || org.id,\n\t\t\t\t}))\n\t\t\t: [];\n\n\t\treturn organizations;\n\t} catch (error) {\n\t\tlog.warn(\n\t\t\t`Unable to fetch organizations: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n\t\t);\n\t\treturn [];\n\t}\n}\n\n/**\n * Gets or creates the .cursor/mcp.json configuration\n */\nfunction getMCPConfig(cursorDir: string): MCPConfig {\n\tconst mcpConfigPath = resolve(cursorDir, \"mcp.json\");\n\n\tif (existsSync(mcpConfigPath)) {\n\t\ttry {\n\t\t\tconst content = readFileSync(mcpConfigPath, \"utf-8\");\n\t\t\treturn JSON.parse(content);\n\t\t} catch (_error) {\n\t\t\tlog.warn(\n\t\t\t\t\"Failed to parse existing mcp.json. Creating a new configuration.\",\n\t\t\t);\n\t\t\treturn { mcpServers: {} };\n\t\t}\n\t}\n\n\treturn { mcpServers: {} };\n}\n\n/**\n * Writes the MCP configuration to .cursor/mcp.json\n */\nfunction writeMCPConfig(cursorDir: string, config: MCPConfig): void {\n\tconst mcpConfigPath = resolve(cursorDir, \"mcp.json\");\n\n\tif (!existsSync(cursorDir)) {\n\t\tmkdirSync(cursorDir, { recursive: true });\n\t}\n\n\twriteFileSync(mcpConfigPath, JSON.stringify(config, null, 2), \"utf-8\");\n}\n\n/**\n * Gets the AGENTS.md template with Neon-specific best practices\n */\nfunction getAgentsMdTemplate(): string {\n\tconst templatePath = resolve(__dirname, \"../src/agents-template.md\");\n\treturn readFileSync(templatePath, \"utf-8\");\n}\n\n/**\n * Generates the organization configuration section for AGENTS.md\n */\nfunction getOrgConfigSection(orgId: string): string {\n\treturn `## Neon Project Configuration\n\n> **🔴 IMPORTANT: You MUST use this organization for all Neon operations in this project.**\n\n**Organization ID:** \\`${orgId}\\`\n\nWhen using any Neon MCP tools or API calls, always pass this \\`org_id\\` parameter. The MCP server is pre-configured with this organization.\n\n**Example:**\n- When listing projects: Use \\`mcp_Neon_list_projects\\` with \\`org_id: \"${orgId}\"\\`\n- When creating resources: Always include \\`org_id: \"${orgId}\"\\` in your tool calls\n\n---\n\n`;\n}\n\n/**\n * Creates or updates AGENTS.md with Neon-specific best practices\n */\nasync function createAgentsMd(orgId?: string): Promise<boolean> {\n\tconst agentsPath = resolve(process.cwd(), \"AGENTS.md\");\n\n\ttry {\n\t\t// Check if AGENTS.md already exists\n\t\tif (existsSync(agentsPath)) {\n\t\t\t// Append to existing file\n\t\t\tconst existingContent = readFileSync(agentsPath, \"utf-8\");\n\n\t\t\t// Check if Neon section already exists to avoid duplicates\n\t\t\tif (existingContent.includes(\"## Neon Database Guidelines\")) {\n\t\t\t\tlog.info(\"Neon guidelines already exist in AGENTS.md\");\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tconst separator = \"\\n\\n---\\n\\n\";\n\t\t\tlet content = \"\";\n\n\t\t\t// Add org ID context if provided\n\t\t\tif (orgId) {\n\t\t\t\tcontent += getOrgConfigSection(orgId);\n\t\t\t}\n\n\t\t\tcontent += getAgentsMdTemplate();\n\n\t\t\tconst updatedContent = existingContent + separator + content;\n\t\t\twriteFileSync(agentsPath, updatedContent, \"utf-8\");\n\t\t\tlog.success(\n\t\t\t\t`Appended Neon best practices to existing AGENTS.md at ${agentsPath}`,\n\t\t\t);\n\t\t} else {\n\t\t\t// Create new file with proper header\n\t\t\tlet content = \"\";\n\n\t\t\t// Add org ID context if provided\n\t\t\tif (orgId) {\n\t\t\t\tcontent += getOrgConfigSection(orgId);\n\t\t\t}\n\n\t\t\tcontent += getAgentsMdTemplate();\n\n\t\t\tconst newContent = `# AGENTS.md\n\nThis file provides guidance to AI coding assistants when working with code in this project.\n\n---\n\n${content}`;\n\t\t\twriteFileSync(agentsPath, newContent, \"utf-8\");\n\t\t\tlog.success(\n\t\t\t\t`Created AGENTS.md with Neon best practices at ${agentsPath}`,\n\t\t\t);\n\t\t}\n\t\treturn true;\n\t} catch (error) {\n\t\tlog.error(\n\t\t\t`Failed to create/update AGENTS.md: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n\t\t);\n\t\treturn false;\n\t}\n}\n\n/**\n * Installs Neon's MCP Server by configuring it globally in ~/.cursor/mcp.json\n * Returns the selected organization ID if one was chosen\n */\nasync function installMCPServer(): Promise<{\n\tsuccess: boolean;\n\torgId?: string;\n}> {\n\tconst homeDir = process.env.HOME || process.env.USERPROFILE;\n\tif (!homeDir) {\n\t\tlog.error(\"Could not determine home directory\");\n\t\treturn { success: false };\n\t}\n\tconst cursorDir = resolve(homeDir, \".cursor\");\n\tconst config = getMCPConfig(cursorDir);\n\n\t// Check if already configured\n\tconst alreadyConfigured = Boolean(config.mcpServers.Neon);\n\tlet shouldReconfigure = false;\n\n\tif (alreadyConfigured) {\n\t\tlog.info(\"Neon MCP Server is already configured globally\");\n\t\tconst response = await confirm({\n\t\t\tmessage: \"Would you like to reconfigure it?\",\n\t\t\tinitialValue: false,\n\t\t});\n\n\t\tif (isCancel(response)) {\n\t\t\treturn { success: false };\n\t\t}\n\n\t\tshouldReconfigure = response as boolean;\n\n\t\tif (!shouldReconfigure) {\n\t\t\tlog.info(\"Keeping existing global configuration.\");\n\t\t}\n\t}\n\n\t// Step 1: Ensure authentication (will trigger OAuth if needed)\n\tlog.step(\"Authenticating with Neon...\");\n\tlog.info(\"The authentication URL will be displayed below if needed.\");\n\tlog.info(\"\");\n\n\tconst authSpinner = spinner();\n\tauthSpinner.start(\"Waiting for authentication...\");\n\n\tconst authSuccess = await ensureNeonctlAuth();\n\n\tif (!authSuccess) {\n\t\tauthSpinner.stop(\"Authentication failed\");\n\t\treturn { success: false };\n\t}\n\n\tauthSpinner.stop(\"Authentication successful ✓\");\n\n\t// Step 2: Fetch organizations and let user select\n\tlet selectedOrgId: string | undefined;\n\n\tconst orgSpinner = spinner();\n\torgSpinner.start(\"Fetching your organizations...\");\n\tconst organizations = await fetchOrganizations();\n\torgSpinner.stop(\n\t\t`Found ${organizations.length} organization${organizations.length !== 1 ? \"s\" : \"\"}`,\n\t);\n\n\tif (organizations.length > 1) {\n\t\tconst orgChoice = await select({\n\t\t\tmessage: \"Select an organization for this project:\",\n\t\t\toptions: organizations.map((org) => ({\n\t\t\t\tvalue: org.id,\n\t\t\t\tlabel: org.name,\n\t\t\t})),\n\t\t});\n\n\t\tif (isCancel(orgChoice)) {\n\t\t\treturn { success: false };\n\t\t}\n\n\t\tselectedOrgId = orgChoice.toString();\n\t\tconst selectedOrg = organizations.find(\n\t\t\t(org) => org.id === selectedOrgId,\n\t\t);\n\t\tlog.success(`Selected organization: ${selectedOrg?.name}`);\n\t} else if (organizations.length === 1) {\n\t\t// Only one org, auto-select it\n\t\tselectedOrgId = organizations[0].id;\n\t\tlog.info(`Using organization: ${organizations[0].name}`);\n\t} else {\n\t\t// No organizations found (personal account)\n\t\tlog.info(\"Using personal account\");\n\t}\n\n\t// If user chose not to reconfigure, we're done (but we still return the org ID)\n\tif (alreadyConfigured && !shouldReconfigure) {\n\t\treturn { success: true, orgId: selectedOrgId };\n\t}\n\n\t// Step 3: Create API key using the OAuth token\n\tconst s = spinner();\n\ts.start(\"Creating API key...\");\n\tconst apiKey = await createApiKeyFromNeonctl();\n\ts.stop(\n\t\tapiKey ? \"API key created successfully ✓\" : \"Failed to create API key\",\n\t);\n\n\tif (!apiKey) {\n\t\tlog.error(\"Could not create API key after authentication.\");\n\t\tlog.info(\n\t\t\t\"You can manually create one at: https://console.neon.tech/app/settings/api-keys\",\n\t\t);\n\t\treturn { success: false };\n\t}\n\n\t// Step 4: Configure Neon MCP Server\n\tconst args = [\"-y\", \"@neondatabase/mcp-server-neon\", \"start\", apiKey];\n\n\tconfig.mcpServers.Neon = {\n\t\tcommand: \"npx\",\n\t\targs,\n\t};\n\n\t// Write configuration\n\ttry {\n\t\twriteMCPConfig(cursorDir, config);\n\t\tlog.success(\n\t\t\t`Neon MCP Server configured globally at ${resolve(cursorDir, \"mcp.json\")}`,\n\t\t);\n\t\tlog.info(\"This configuration will be available in all your projects.\");\n\t\treturn { success: true, orgId: selectedOrgId };\n\t} catch (error) {\n\t\tlog.error(\n\t\t\t`Failed to write global configuration: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n\t\t);\n\t\treturn { success: false };\n\t}\n}\n\n/**\n * Initialize Neon projects with MCP Server and AI assistant rules\n */\nexport async function init(): Promise<void> {\n\tintro(\"🚀 Neon Project Initialization\");\n\n\tlog.info(\n\t\t\"This will set up your project with Neon's MCP Server and AI coding best practices.\",\n\t);\n\n\tlog.step(\"Step 1/2: Configuring Neon MCP Server\");\n\tconst { success: mcpSuccess, orgId } = await installMCPServer();\n\n\tif (!mcpSuccess) {\n\t\toutro(\"❌ Initialization cancelled or failed.\");\n\t\tprocess.exit(1);\n\t}\n\n\tlog.step(\"Step 2/2: Creating AGENTS.md with Neon best practices\");\n\tconst agentsSuccess = await createAgentsMd(orgId);\n\n\tif (!agentsSuccess) {\n\t\tlog.warn(\"Failed to create AGENTS.md, but MCP Server is configured.\");\n\t}\n\n\toutro(\"Success! Neon project initialized.\");\n\tconsole.log(\"\");\n\tconsole.log(\n\t\t\"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\",\n\t);\n\tconsole.log(\"\");\n\tconsole.log(\"Next steps:\");\n\tconsole.log(\"\");\n\tconsole.log(\n\t\t\" 1. Restart your AI coding assistant (Cursor, Windsurf, etc.)\",\n\t);\n\tconsole.log(\"\");\n\tconsole.log(\" 2. Type this in your AI chat to begin:\");\n\tconsole.log(\"\");\n\tconsole.log(\" ┌──────────────────────────────────────┐\");\n\tconsole.log(\" │ │\");\n\tconsole.log(\" │ Get started with Neon │\");\n\tconsole.log(\" │ │\");\n\tconsole.log(\" └──────────────────────────────────────┘\");\n\tconsole.log(\"\");\n\tconsole.log(\n\t\t\"Your AI assistant now has access to Neon best practices via AGENTS.md\",\n\t);\n\tconsole.log(\"\");\n\tconsole.log(\n\t\t\"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\",\n\t);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["selectedOrgId: string | undefined"],"sources":["../src/index.ts"],"sourcesContent":["import { exec } from \"node:child_process\";\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { promisify } from \"node:util\";\nimport {\n\tconfirm,\n\tintro,\n\tisCancel,\n\tlog,\n\toutro,\n\tselect,\n\tspinner,\n} from \"@clack/prompts\";\nimport { execa } from \"execa\";\n\nconst execAsync = promisify(exec);\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\ninterface MCPConfig {\n\tmcpServers: {\n\t\t[key: string]: {\n\t\t\turl: string;\n\t\t\theaders?: Record<string, string>;\n\t\t};\n\t};\n}\n\ninterface NeonOrganization {\n\tid: string;\n\tname: string;\n}\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 */\nasync function ensureNeonctlAuth(): Promise<boolean> {\n\ttry {\n\t\t// Use execa to authenticate with neonctl\n\t\tawait execa(\n\t\t\t\"npx\",\n\t\t\t[\"-y\", \"neonctl\", \"me\", \"--output\", \"json\", \"--no-analytics\"],\n\t\t\t{\n\t\t\t\tstdio: \"inherit\", // Shows OAuth URL and prompts to the user\n\t\t\t},\n\t\t);\n\n\t\treturn true;\n\t} catch (error) {\n\t\tlog.error(\n\t\t\t`Authentication failed: ${error instanceof Error ? error.message : \"Unknown error\"}`,\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 */\nasync 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\nasync function fetchOrganizations(): Promise<NeonOrganization[]> {\n\ttry {\n\t\tconst { stdout } = await execAsync(\n\t\t\t\"npx -y neonctl orgs list --output json --no-analytics\",\n\t\t\t{ maxBuffer: 1024 * 1024 },\n\t\t);\n\n\t\tconst data = JSON.parse(stdout);\n\n\t\t// The neon CLI returns an array of organizations\n\t\tconst organizations: NeonOrganization[] = Array.isArray(data)\n\t\t\t? data.map((org: { id: string; name?: string }) => ({\n\t\t\t\t\tid: org.id,\n\t\t\t\t\tname: org.name || org.id,\n\t\t\t\t}))\n\t\t\t: [];\n\n\t\treturn organizations;\n\t} catch (error) {\n\t\tlog.warn(\n\t\t\t`Unable to fetch organizations: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n\t\t);\n\t\treturn [];\n\t}\n}\n\n/**\n * Gets or creates the .cursor/mcp.json configuration\n */\nfunction getMCPConfig(cursorDir: string): MCPConfig {\n\tconst mcpConfigPath = resolve(cursorDir, \"mcp.json\");\n\n\tif (existsSync(mcpConfigPath)) {\n\t\ttry {\n\t\t\tconst content = readFileSync(mcpConfigPath, \"utf-8\");\n\t\t\treturn JSON.parse(content);\n\t\t} catch (_error) {\n\t\t\tlog.warn(\n\t\t\t\t\"Failed to parse existing mcp.json. Creating a new configuration.\",\n\t\t\t);\n\t\t\treturn { mcpServers: {} };\n\t\t}\n\t}\n\n\treturn { mcpServers: {} };\n}\n\n/**\n * Writes the MCP configuration to .cursor/mcp.json\n */\nfunction writeMCPConfig(cursorDir: string, config: MCPConfig): void {\n\tconst mcpConfigPath = resolve(cursorDir, \"mcp.json\");\n\n\tif (!existsSync(cursorDir)) {\n\t\tmkdirSync(cursorDir, { recursive: true });\n\t}\n\n\twriteFileSync(mcpConfigPath, JSON.stringify(config, null, 2), \"utf-8\");\n}\n\n/**\n * Gets the neon.md template with Neon-specific best practices\n */\nfunction getNeonMdTemplate(): string {\n\tconst templatePath = resolve(__dirname, \"../src/agents-template.md\");\n\treturn readFileSync(templatePath, \"utf-8\");\n}\n\n/**\n * Generates the organization configuration section for neon.md\n */\nfunction getOrgConfigSection(orgId: string): string {\n\treturn `## Neon Project Configuration\n\n> **🔴 IMPORTANT: You MUST use this organization for all Neon operations in this project.**\n\n**Organization ID:** \\`${orgId}\\`\n\nWhen using any Neon MCP tools or API calls, always pass this \\`org_id\\` parameter. The MCP server is pre-configured with this organization.\n\n**Example:**\n- When listing projects: Use \\`mcp_Neon_list_projects\\` with \\`org_id: \"${orgId}\"\\`\n- When creating resources: Always include \\`org_id: \"${orgId}\"\\` in your tool calls\n\n---\n\n`;\n}\n\n/**\n * Gets the reference text to add to AGENTS.md\n */\nfunction getAgentsNeonReference(): string {\n\treturn `## Working with Neon Database\n\nWhen the user asks to **\"Get started with Neon\"** or something similar, refer to the detailed guidelines in \\`neon.md\\`.`;\n}\n\n/**\n * Creates or updates neon.md with detailed Neon guidelines\n */\nasync function createNeonMd(orgId?: string): Promise<boolean> {\n\tconst neonMdPath = resolve(process.cwd(), \"neon.md\");\n\n\ttry {\n\t\t// Check if neon.md already exists\n\t\tif (existsSync(neonMdPath)) {\n\t\t\tlog.info(\"neon.md already exists\");\n\t\t\tconst response = await confirm({\n\t\t\t\tmessage:\n\t\t\t\t\t\"Replace existing neon.md with updated guidelines? (suggested)\",\n\t\t\t\tinitialValue: true,\n\t\t\t});\n\n\t\t\tif (isCancel(response)) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif (!response) {\n\t\t\t\tlog.info(\"Keeping existing neon.md\");\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\tlet content = \"\";\n\n\t\t// Add org ID context if provided\n\t\tif (orgId) {\n\t\t\tcontent += getOrgConfigSection(orgId);\n\t\t}\n\n\t\tcontent += getNeonMdTemplate();\n\n\t\twriteFileSync(neonMdPath, content, \"utf-8\");\n\t\tlog.success(\n\t\t\t`Created neon.md with detailed guidelines at ${neonMdPath}`,\n\t\t);\n\t\treturn true;\n\t} catch (error) {\n\t\tlog.error(\n\t\t\t`Failed to create neon.md: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n\t\t);\n\t\treturn false;\n\t}\n}\n\n/**\n * Creates or updates AGENTS.md with a reference to neon.md\n */\nasync function createAgentsMd(): Promise<boolean> {\n\tconst agentsPath = resolve(process.cwd(), \"AGENTS.md\");\n\n\ttry {\n\t\tconst neonReference = getAgentsNeonReference();\n\n\t\t// Check if AGENTS.md already exists\n\t\tif (existsSync(agentsPath)) {\n\t\t\t// Append to existing file\n\t\t\tconst existingContent = readFileSync(agentsPath, \"utf-8\");\n\n\t\t\t// Check if Neon section already exists to avoid duplicates\n\t\t\tif (existingContent.includes(\"## Working with Neon Database\")) {\n\t\t\t\tlog.info(\"Neon reference already exists in AGENTS.md\");\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tconst separator = \"\\n\\n---\\n\\n\";\n\t\t\tconst updatedContent = existingContent + separator + neonReference;\n\t\t\twriteFileSync(agentsPath, updatedContent, \"utf-8\");\n\t\t\tlog.success(\n\t\t\t\t`Appended Neon reference to existing AGENTS.md at ${agentsPath}`,\n\t\t\t);\n\t\t} else {\n\t\t\t// Create new file with proper header\n\t\t\tconst newContent = `# AGENTS.md\n\nThis file provides guidance to AI coding assistants when working with code in this project.\n\n---\n\n${neonReference}`;\n\t\t\twriteFileSync(agentsPath, newContent, \"utf-8\");\n\t\t\tlog.success(\n\t\t\t\t`Created AGENTS.md with Neon reference at ${agentsPath}`,\n\t\t\t);\n\t\t}\n\t\treturn true;\n\t} catch (error) {\n\t\tlog.error(\n\t\t\t`Failed to create/update AGENTS.md: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n\t\t);\n\t\treturn false;\n\t}\n}\n\n/**\n * Installs Neon's MCP Server by configuring it globally in ~/.cursor/mcp.json\n * Returns the selected organization ID if one was chosen\n */\nasync function installMCPServer(): Promise<{\n\tsuccess: boolean;\n\torgId?: string;\n}> {\n\tconst homeDir = process.env.HOME || process.env.USERPROFILE;\n\tif (!homeDir) {\n\t\tlog.error(\"Could not determine home directory\");\n\t\treturn { success: false };\n\t}\n\tconst cursorDir = resolve(homeDir, \".cursor\");\n\tconst config = getMCPConfig(cursorDir);\n\n\t// Check if already configured\n\tconst alreadyConfigured = Boolean(config.mcpServers.Neon);\n\tlet shouldReconfigure = false;\n\n\tif (alreadyConfigured) {\n\t\tlog.info(\"Neon MCP Server is already configured globally\");\n\t\tconst response = await confirm({\n\t\t\tmessage: \"Would you like to reconfigure it? (suggested)\",\n\t\t\tinitialValue: true,\n\t\t});\n\n\t\tif (isCancel(response)) {\n\t\t\treturn { success: false };\n\t\t}\n\n\t\tshouldReconfigure = response as boolean;\n\n\t\tif (!shouldReconfigure) {\n\t\t\tlog.info(\"Keeping existing global configuration.\");\n\t\t}\n\t}\n\n\t// Step 1: Ensure authentication (will trigger OAuth if needed)\n\tlog.step(\"Authenticating with Neon...\");\n\tlog.info(\"The authentication URL will be displayed below if needed.\");\n\tlog.info(\"\");\n\n\tconst authSpinner = spinner();\n\tauthSpinner.start(\"Waiting for authentication...\");\n\n\tconst authSuccess = await ensureNeonctlAuth();\n\n\tif (!authSuccess) {\n\t\tauthSpinner.stop(\"Authentication failed\");\n\t\treturn { success: false };\n\t}\n\n\tauthSpinner.stop(\"Authentication successful ✓\");\n\n\t// Step 2: Fetch organizations and let user select\n\tlet selectedOrgId: string | undefined;\n\n\tconst orgSpinner = spinner();\n\torgSpinner.start(\"Fetching your organizations...\");\n\tconst organizations = await fetchOrganizations();\n\torgSpinner.stop(\n\t\t`Found ${organizations.length} organization${organizations.length !== 1 ? \"s\" : \"\"}`,\n\t);\n\n\tif (organizations.length > 1) {\n\t\tconst orgChoice = await select({\n\t\t\tmessage: \"Select an organization for this project:\",\n\t\t\toptions: organizations.map((org) => ({\n\t\t\t\tvalue: org.id,\n\t\t\t\tlabel: org.name,\n\t\t\t})),\n\t\t});\n\n\t\tif (isCancel(orgChoice)) {\n\t\t\treturn { success: false };\n\t\t}\n\n\t\tselectedOrgId = orgChoice.toString();\n\t\tconst selectedOrg = organizations.find(\n\t\t\t(org) => org.id === selectedOrgId,\n\t\t);\n\t\tlog.success(`Selected organization: ${selectedOrg?.name}`);\n\t} else if (organizations.length === 1) {\n\t\t// Only one org, auto-select it\n\t\tselectedOrgId = organizations[0].id;\n\t\tlog.info(`Using organization: ${organizations[0].name}`);\n\t} else {\n\t\t// No organizations found (personal account)\n\t\tlog.info(\"Using personal account\");\n\t}\n\n\t// If user chose not to reconfigure, we're done (but we still return the org ID)\n\tif (alreadyConfigured && !shouldReconfigure) {\n\t\treturn { success: true, orgId: selectedOrgId };\n\t}\n\n\t// Step 3: Create API key using the OAuth token\n\tconst s = spinner();\n\ts.start(\"Creating API key...\");\n\tconst apiKey = await createApiKeyFromNeonctl();\n\ts.stop(\n\t\tapiKey ? \"API key created successfully ✓\" : \"Failed to create API key\",\n\t);\n\n\tif (!apiKey) {\n\t\tlog.error(\"Could not create API key after authentication.\");\n\t\tlog.info(\n\t\t\t\"You can manually create one at: https://console.neon.tech/app/settings/api-keys\",\n\t\t);\n\t\treturn { success: false };\n\t}\n\n\t// Step 4: Configure Neon MCP Server\n\t// Using remote MCP server with API key authentication\n\t// Ref: https://neon.com/docs/ai/neon-mcp-server#api-key-based-authentication\n\tconfig.mcpServers.Neon = {\n\t\turl: \"https://mcp.neon.tech/mcp\",\n\t\theaders: {\n\t\t\tAuthorization: `Bearer ${apiKey}`,\n\t\t},\n\t};\n\n\t// Write configuration\n\ttry {\n\t\twriteMCPConfig(cursorDir, config);\n\t\tlog.success(\n\t\t\t`Neon MCP Server configured globally at ${resolve(cursorDir, \"mcp.json\")}`,\n\t\t);\n\t\tlog.info(\"This configuration will be available in all your projects.\");\n\t\treturn { success: true, orgId: selectedOrgId };\n\t} catch (error) {\n\t\tlog.error(\n\t\t\t`Failed to write global configuration: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n\t\t);\n\t\treturn { success: false };\n\t}\n}\n\n/**\n * Initialize Neon projects with MCP Server and AI assistant rules\n */\nexport async function init(): Promise<void> {\n\tintro(\"🚀 Neon Project Initialization\");\n\n\t// Check if Cursor is installed\n\tconst homeDir = process.env.HOME || process.env.USERPROFILE;\n\tif (!homeDir) {\n\t\tlog.error(\"Could not determine home directory\");\n\t\tprocess.exit(1);\n\t}\n\n\tconst cursorDir = resolve(homeDir, \".cursor\");\n\tif (!existsSync(cursorDir)) {\n\t\tlog.warn(\"This tool currently only supports Cursor IDE.\");\n\t\tlog.info(\"We'd love to hear which IDE you're using!\");\n\t\tlog.info(\"\");\n\t\tlog.info(\"Please send your feedback to: init-feedback@neon.tech\");\n\t\tlog.info(\"\");\n\t\toutro(\"❌ Cursor IDE is required to continue.\");\n\t\tprocess.exit(1);\n\t}\n\n\tlog.info(\n\t\t\"This will set up your project with Neon's MCP Server and AI coding best practices.\",\n\t);\n\n\tlog.step(\"Step 1/3: Configuring Neon MCP Server...\");\n\tconst { success: mcpSuccess, orgId } = await installMCPServer();\n\n\tif (!mcpSuccess) {\n\t\toutro(\"❌ Initialization cancelled or failed.\");\n\t\tprocess.exit(1);\n\t}\n\n\tlog.step(\"Step 2/3: Creating neon.md with detailed guidelines...\");\n\tconst neonMdSuccess = await createNeonMd(orgId);\n\n\tif (!neonMdSuccess) {\n\t\tlog.warn(\"Failed to create neon.md, but MCP Server is configured.\");\n\t}\n\n\tlog.step(\"Step 3/3: Creating AGENTS.md for Cursor...\");\n\tconst agentsSuccess = await createAgentsMd();\n\n\tif (!agentsSuccess) {\n\t\tlog.warn(\"Failed to create AGENTS.md, but MCP Server is configured.\");\n\t}\n\n\toutro(\"Success! Neon project initialized.\");\n\tconsole.log(\"\");\n\tconsole.log(\n\t\t\"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\",\n\t);\n\tconsole.log(\"\");\n\tconsole.log(\"⚠️ The init command is still in its early stages.\");\n\tconsole.log(\" We'd appreciate any feedback! Send us an email at:\");\n\tconsole.log(\" init-feedback@neon.tech\");\n\tconsole.log(\"\");\n\tconsole.log(\"Next steps:\");\n\tconsole.log(\"\");\n\tconsole.log(\" 1. Restart Cursor\");\n\tconsole.log(\"\");\n\tconsole.log(\" 2. Type this in your Cursor chat to begin:\");\n\tconsole.log(\"\");\n\tconsole.log(\" ┌──────────────────────────────────────┐\");\n\tconsole.log(\" │ │\");\n\tconsole.log(\" │ Get started with Neon │\");\n\tconsole.log(\" │ │\");\n\tconsole.log(\" └──────────────────────────────────────┘\");\n\tconsole.log(\"\");\n\tconsole.log(\n\t\t\"Your AI assistant now has access to Neon best practices via neon.md\",\n\t);\n\tconsole.log(\"(referenced in AGENTS.md for easy discovery)\");\n\tconsole.log(\"\");\n\tconsole.log(\n\t\t\"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\",\n\t);\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neon-init",
3
- "version": "0.4.1",
3
+ "version": "0.7.0",
4
4
  "description": "Initialize Neon projects",
5
5
  "keywords": [
6
6
  "neon",
@@ -35,7 +35,7 @@
35
35
  "src/agents-template.md"
36
36
  ],
37
37
  "devDependencies": {
38
- "@types/node": "22.13.10",
38
+ "@types/node": "^20.19.0",
39
39
  "@vitest/coverage-v8": "3.0.9",
40
40
  "console-fail-test": "0.5.0",
41
41
  "tsdown": "^0.14.1",
@@ -43,7 +43,8 @@
43
43
  "vitest": "^3.0.9"
44
44
  },
45
45
  "dependencies": {
46
- "@clack/prompts": "0.10.1"
46
+ "@clack/prompts": "0.10.1",
47
+ "execa": "^9.5.2"
47
48
  },
48
49
  "engines": {
49
50
  "node": ">=20.19.0"