Skip to content

Commit 983aef7

Browse files
committed
code review
1 parent 6a36601 commit 983aef7

File tree

1 file changed

+49
-66
lines changed

1 file changed

+49
-66
lines changed

β€Žsrc/commands/init/ai-rules.ts

Lines changed: 49 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { resolve } from 'node:path'
22
import { promises as fs } from 'node:fs'
3+
import { homedir } from 'node:os'
34
import type { NetlifyAPI } from '@netlify/api'
45

56
import { chalk, log, logAndThrowError, type APIError } from '../../utils/command-helpers.js'
@@ -80,71 +81,55 @@ const detectIDE = async (): Promise<ConsumerConfig | null> => {
8081
}
8182

8283
// Generate MCP configuration for the detected IDE
83-
const generateMcpConfig = (ide: ConsumerConfig): string => {
84-
const configs: Record<string, string> = {
85-
vscode: JSON.stringify(
86-
{
87-
servers: {
88-
netlify: {
89-
type: 'stdio',
90-
command: 'npx',
91-
args: ['-y', '@netlify/mcp'],
92-
},
84+
const generateMcpConfig = (ide: ConsumerConfig): Record<string, unknown> => {
85+
const configs: Record<string, Record<string, unknown>> = {
86+
vscode: {
87+
servers: {
88+
netlify: {
89+
type: 'stdio',
90+
command: 'npx',
91+
args: ['-y', '@netlify/mcp'],
9392
},
9493
},
95-
null,
96-
2,
97-
),
98-
cursor: JSON.stringify(
99-
{
100-
mcpServers: {
101-
netlify: {
102-
command: 'npx',
103-
args: ['-y', '@netlify/mcp'],
104-
},
94+
},
95+
cursor: {
96+
mcpServers: {
97+
netlify: {
98+
command: 'npx',
99+
args: ['-y', '@netlify/mcp'],
105100
},
106101
},
107-
null,
108-
2,
109-
),
110-
windsurf: JSON.stringify(
111-
{
112-
mcpServers: {
113-
netlify: {
114-
command: 'npx',
115-
args: ['-y', '@netlify/mcp'],
116-
},
102+
},
103+
windsurf: {
104+
mcpServers: {
105+
netlify: {
106+
command: 'npx',
107+
args: ['-y', '@netlify/mcp'],
117108
},
118109
},
119-
null,
120-
2,
121-
),
110+
},
122111
}
123112

124113
return (
125-
configs[ide.key] ||
126-
JSON.stringify(
127-
{
128-
mcpServers: {
129-
netlify: {
130-
command: 'npx',
131-
args: ['-y', '@netlify/mcp'],
132-
},
114+
configs[ide.key] ?? {
115+
mcpServers: {
116+
netlify: {
117+
command: 'npx',
118+
args: ['-y', '@netlify/mcp'],
133119
},
134120
},
135-
null,
136-
2,
137-
)
121+
}
138122
)
139123
}
140124

141125
// VS Code specific MCP configuration
142-
const configureMcpForVSCode = async (config: string, projectPath: string): Promise<void> => {
143-
const configPath = resolve(projectPath, '.vscode', 'mcp.json')
126+
const configureMcpForVSCode = async (config: Record<string, unknown>, projectPath: string): Promise<void> => {
127+
const vscodeDirPath = resolve(projectPath, '.vscode')
128+
const configPath = resolve(vscodeDirPath, 'mcp.json')
144129

145130
try {
146131
// Create .vscode directory if it doesn't exist
147-
await fs.mkdir(resolve(projectPath, '.vscode'), { recursive: true })
132+
await fs.mkdir(vscodeDirPath, { recursive: true })
148133

149134
// Write or update mcp.json
150135
let existingConfig: Record<string, unknown> = {}
@@ -155,8 +140,7 @@ const configureMcpForVSCode = async (config: string, projectPath: string): Promi
155140
// File doesn't exist or is invalid JSON
156141
}
157142

158-
const mcpConfig = JSON.parse(config) as Record<string, unknown>
159-
const updatedConfig = { ...existingConfig, ...mcpConfig }
143+
const updatedConfig = { ...existingConfig, ...config }
160144

161145
await fs.writeFile(configPath, JSON.stringify(updatedConfig, null, 2), 'utf-8')
162146
log(`${chalk.green('βœ…')} VS Code MCP configuration saved to ${chalk.cyan('.vscode/mcp.json')}`)
@@ -166,26 +150,26 @@ const configureMcpForVSCode = async (config: string, projectPath: string): Promi
166150
}
167151

168152
// Cursor specific MCP configuration
169-
const configureMcpForCursor = async (config: string, projectPath: string): Promise<void> => {
153+
const configureMcpForCursor = async (config: Record<string, unknown>, projectPath: string): Promise<void> => {
170154
const configPath = resolve(projectPath, '.cursor', 'mcp.json')
171155

172156
try {
173157
await fs.mkdir(resolve(projectPath, '.cursor'), { recursive: true })
174-
await fs.writeFile(configPath, config, 'utf-8')
158+
await fs.writeFile(configPath, JSON.stringify(config, null, 2), 'utf-8')
175159
log(`${chalk.green('βœ…')} Cursor MCP configuration saved to ${chalk.cyan('.cursor/mcp.json')}`)
176160
} catch (error) {
177161
throw new Error(`Failed to configure Cursor MCP: ${error instanceof Error ? error.message : 'Unknown error'}`)
178162
}
179163
}
180164

181165
// Windsurf specific MCP configuration
182-
const configureMcpForWindsurf = async (config: string, _projectPath: string): Promise<void> => {
183-
const { homedir } = await import('node:os')
184-
const configPath = resolve(homedir(), '.codeium', 'windsurf', 'mcp_config.json')
166+
const configureMcpForWindsurf = async (config: Record<string, unknown>, _projectPath: string): Promise<void> => {
167+
const windsurfDirPath = resolve(homedir(), '.codeium', 'windsurf')
168+
const configPath = resolve(windsurfDirPath, 'mcp_config.json')
185169

186170
try {
187171
// Create .codeium/windsurf directory if it doesn't exist
188-
await fs.mkdir(resolve(homedir(), '.codeium', 'windsurf'), { recursive: true })
172+
await fs.mkdir(windsurfDirPath, { recursive: true })
189173

190174
// Read existing config or create new one
191175
let existingConfig: Record<string, unknown> = {}
@@ -196,11 +180,9 @@ const configureMcpForWindsurf = async (config: string, _projectPath: string): Pr
196180
// File doesn't exist or is invalid JSON
197181
}
198182

199-
const mcpConfig = JSON.parse(config) as Record<string, unknown>
200-
201183
// Merge mcpServers from both configs
202184
const existingServers = (existingConfig.mcpServers as Record<string, unknown> | undefined) ?? {}
203-
const newServers = (mcpConfig.mcpServers as Record<string, unknown> | undefined) ?? {}
185+
const newServers = (config.mcpServers as Record<string, unknown> | undefined) ?? {}
204186

205187
const updatedConfig = {
206188
...existingConfig,
@@ -211,19 +193,19 @@ const configureMcpForWindsurf = async (config: string, _projectPath: string): Pr
211193
}
212194

213195
await fs.writeFile(configPath, JSON.stringify(updatedConfig, null, 2), 'utf-8')
214-
log(`${chalk.green('βœ…')} Windsurf MCP configuration saved to global config`)
196+
log(`${chalk.green('βœ…')} Windsurf MCP configuration saved`)
215197
log(`${chalk.gray('πŸ’‘')} Restart Windsurf to activate the MCP server`)
216198
} catch (error) {
217199
throw new Error(`Failed to configure Windsurf MCP: ${error instanceof Error ? error.message : 'Unknown error'}`)
218200
}
219201
}
220202

221203
// Generic MCP configuration display
222-
const showGenericMcpConfig = (config: string, ideName: string): void => {
204+
const showGenericMcpConfig = (config: Record<string, unknown>, ideName: string): void => {
223205
log(`\n${chalk.yellow('πŸ“‹ Manual Configuration Required')}`)
224206
log(`Please add the following configuration to your ${ideName} settings:`)
225207
log(`\n${chalk.gray('--- Configuration ---')}`)
226-
log(config)
208+
log(JSON.stringify(config, null, 2))
227209
log(`${chalk.gray('--- End Configuration ---')}\n`)
228210
}
229211

@@ -241,7 +223,9 @@ const triggerMcpConfiguration = async (ide: ConsumerConfig, projectPath: string)
241223
])
242224

243225
if (!shouldConfigure) {
244-
log(chalk.gray('Skipped MCP configuration. You can set it up manually later.'))
226+
log(
227+
chalk.gray('Skipped MCP configuration. You can set it up manually later by changing MCP settings in your editor'),
228+
)
245229
return false
246230
}
247231

@@ -289,7 +273,7 @@ const fetchProjectInfo = async (url: string): Promise<ProjectInfo> => {
289273
})
290274

291275
if (!response.ok) {
292-
throw new Error(`HTTP error! status: ${String(response.status)}`)
276+
throw new Error(`Failed to fetch project information: ${response.statusText}`)
293277
}
294278
const data = (await response.text()) as unknown as string
295279
const parsedData = JSON.parse(data) as unknown as ProjectInfo
@@ -346,7 +330,6 @@ export const initWithAiRules = async (hash: string, command: BaseCommand): Promi
346330
const { api } = command.netlify
347331

348332
log(`${chalk.blue('πŸ€– Initializing AI project')} with rules...`)
349-
log(`${chalk.gray('Hash:')} ${hash}`)
350333
log(`${chalk.gray('User:')} ${api.accessToken ? 'Authenticated βœ…' : 'Not authenticated ❌'}`)
351334

352335
try {
@@ -399,7 +382,7 @@ export const initWithAiRules = async (hash: string, command: BaseCommand): Promi
399382
let mcpConfigured = false
400383

401384
if (detectedIDE) {
402-
log(`${chalk.green('βœ…')} Detected IDE: ${chalk.cyan(detectedIDE.presentedName)}`)
385+
log(`${chalk.green('βœ…')} Detected development environment: ${chalk.cyan(detectedIDE.presentedName)}`)
403386
mcpConfigured = await triggerMcpConfiguration(detectedIDE, targetDir)
404387
}
405388

@@ -423,7 +406,7 @@ export const initWithAiRules = async (hash: string, command: BaseCommand): Promi
423406
if (mcpConfigured) {
424407
log(chalk.yellowBright(`πŸ”§ Step 2: MCP Server Configured`))
425408
log(` ${chalk.green('βœ…')} ${chalk.cyan(detectedIDE.key)} is ready with Netlify MCP server`)
426-
log(` ${chalk.gray('πŸ’‘ MCP will activate when you reload/restart your IDE window')}`)
409+
log(` ${chalk.gray('πŸ’‘ MCP will activate when you reload/restart your development environment')}`)
427410
} else {
428411
log(chalk.yellowBright(`πŸ”§ Step 2: Manual MCP Configuration`))
429412
log(` ${chalk.cyan(detectedIDE.key)} detected - MCP setup was skipped`)

0 commit comments

Comments
Β (0)