From 87ed7de1816dd8c93be7245a8ede636ee8d300c7 Mon Sep 17 00:00:00 2001 From: Alex Andru Date: Mon, 16 Jun 2025 22:23:39 +0200 Subject: [PATCH] feat: add .gitignore on project creation --- src/cli/project/create.ts | 141 ++++++++++++++++++++------------------ 1 file changed, 75 insertions(+), 66 deletions(-) diff --git a/src/cli/project/create.ts b/src/cli/project/create.ts index ffda18f..276d9c4 100644 --- a/src/cli/project/create.ts +++ b/src/cli/project/create.ts @@ -1,11 +1,14 @@ -import { spawnSync } from "child_process"; -import { mkdir, writeFile } from "fs/promises"; -import { join } from "path"; -import prompts from "prompts"; -import { generateReadme } from "../templates/readme.js"; -import { execa } from "execa"; - -export async function createProject(name?: string, options?: { http?: boolean, cors?: boolean, port?: number, install?: boolean, example?: boolean }) { +import { spawnSync } from 'child_process'; +import { mkdir, writeFile } from 'fs/promises'; +import { join } from 'path'; +import prompts from 'prompts'; +import { generateReadme } from '../templates/readme.js'; +import { execa } from 'execa'; + +export async function createProject( + name?: string, + options?: { http?: boolean; cors?: boolean; port?: number; install?: boolean; example?: boolean } +) { let projectName: string; // Default install and example to true if not specified const shouldInstall = options?.install !== false; @@ -14,18 +17,18 @@ export async function createProject(name?: string, options?: { http?: boolean, c if (!name) { const response = await prompts([ { - type: "text", - name: "projectName", - message: "What is the name of your MCP server project?", + type: 'text', + name: 'projectName', + message: 'What is the name of your MCP server project?', validate: (value: string) => /^[a-z0-9-]+$/.test(value) ? true - : "Project name can only contain lowercase letters, numbers, and hyphens", + : 'Project name can only contain lowercase letters, numbers, and hyphens', }, ]); if (!response.projectName) { - console.log("Project creation cancelled"); + console.log('Project creation cancelled'); process.exit(1); } @@ -35,81 +38,88 @@ export async function createProject(name?: string, options?: { http?: boolean, c } if (!projectName) { - throw new Error("Project name is required"); + throw new Error('Project name is required'); } const projectDir = join(process.cwd(), projectName); - const srcDir = join(projectDir, "src"); - const toolsDir = join(srcDir, "tools"); + const srcDir = join(projectDir, 'src'); + const toolsDir = join(srcDir, 'tools'); try { - console.log("Creating project structure..."); + console.log('Creating project structure...'); await mkdir(projectDir); await mkdir(srcDir); await mkdir(toolsDir); const packageJson = { name: projectName, - version: "0.0.1", + version: '0.0.1', description: `${projectName} MCP server`, - type: "module", + type: 'module', bin: { - [projectName]: "./dist/index.js", + [projectName]: './dist/index.js', }, - files: ["dist"], + files: ['dist'], scripts: { - build: "tsc && mcp-build", - watch: "tsc --watch", - start: "node dist/index.js" + build: 'tsc && mcp-build', + watch: 'tsc --watch', + start: 'node dist/index.js', }, dependencies: { - "mcp-framework": "^0.2.2" + 'mcp-framework': '^0.2.2', }, devDependencies: { - "@types/node": "^20.11.24", - "typescript": "^5.3.3" + '@types/node': '^20.11.24', + typescript: '^5.3.3', }, engines: { - "node": ">=18.19.0" - } + node: '>=18.19.0', + }, }; const tsconfig = { compilerOptions: { - target: "ESNext", - module: "ESNext", - moduleResolution: "node", - outDir: "./dist", - rootDir: "./src", + target: 'ESNext', + module: 'ESNext', + moduleResolution: 'node', + outDir: './dist', + rootDir: './src', strict: true, esModuleInterop: true, skipLibCheck: true, forceConsistentCasingInFileNames: true, }, - include: ["src/**/*"], - exclude: ["node_modules"], + include: ['src/**/*'], + exclude: ['node_modules'], }; - let indexTs = ""; - + const gitignore = `node_modules + dist + .env + .DS_Store + .idea + .vscode + `; + let indexTs = ''; + if (options?.http) { const port = options.port || 8080; let transportConfig = `\n transport: { type: "http-stream", options: { port: ${port}`; - + if (options.cors) { transportConfig += `, cors: { allowOrigin: "*" }`; } - + transportConfig += ` } }`; - + indexTs = `import { MCPServer } from "mcp-framework"; const server = new MCPServer({${transportConfig}}); @@ -148,66 +158,65 @@ class ExampleTool extends MCPTool { export default ExampleTool;`; - // Prepare the files to write const filesToWrite = [ - writeFile(join(projectDir, "package.json"), JSON.stringify(packageJson, null, 2)), - writeFile(join(projectDir, "tsconfig.json"), JSON.stringify(tsconfig, null, 2)), - writeFile(join(projectDir, "README.md"), generateReadme(projectName)), - writeFile(join(srcDir, "index.ts"), indexTs), + writeFile(join(projectDir, 'package.json'), JSON.stringify(packageJson, null, 2)), + writeFile(join(projectDir, 'tsconfig.json'), JSON.stringify(tsconfig, null, 2)), + writeFile(join(projectDir, 'README.md'), generateReadme(projectName)), + writeFile(join(srcDir, 'index.ts'), indexTs), + writeFile(join(projectDir, '.gitignore'), gitignore), ]; - // Conditionally add the example tool if (shouldCreateExample) { - filesToWrite.push(writeFile(join(toolsDir, "ExampleTool.ts"), exampleToolTs)); + filesToWrite.push(writeFile(join(toolsDir, 'ExampleTool.ts'), exampleToolTs)); } - console.log("Creating project files..."); + console.log('Creating project files...'); await Promise.all(filesToWrite); process.chdir(projectDir); - console.log("Initializing git repository..."); - const gitInit = spawnSync("git", ["init"], { - stdio: "inherit", + console.log('Initializing git repository...'); + const gitInit = spawnSync('git', ['init'], { + stdio: 'inherit', shell: true, }); if (gitInit.status !== 0) { - throw new Error("Failed to initialize git repository"); + throw new Error('Failed to initialize git repository'); } if (shouldInstall) { - console.log("Installing dependencies..."); - const npmInstall = spawnSync("npm", ["install"], { - stdio: "inherit", - shell: true + console.log('Installing dependencies...'); + const npmInstall = spawnSync('npm', ['install'], { + stdio: 'inherit', + shell: true, }); if (npmInstall.status !== 0) { - throw new Error("Failed to install dependencies"); + throw new Error('Failed to install dependencies'); } - console.log("Building project..."); + console.log('Building project...'); const tscBuild = await execa('npx', ['tsc'], { cwd: projectDir, - stdio: "inherit", + stdio: 'inherit', }); if (tscBuild.exitCode !== 0) { - throw new Error("Failed to build TypeScript"); + throw new Error('Failed to build TypeScript'); } const mcpBuild = await execa('npx', ['mcp-build'], { cwd: projectDir, - stdio: "inherit", + stdio: 'inherit', env: { ...process.env, - MCP_SKIP_VALIDATION: "true" - } + MCP_SKIP_VALIDATION: 'true', + }, }); if (mcpBuild.exitCode !== 0) { - throw new Error("Failed to run mcp-build"); + throw new Error('Failed to run mcp-build'); } console.log(` @@ -231,7 +240,7 @@ You can now: `); } } catch (error) { - console.error("Error creating project:", error); + console.error('Error creating project:', error); process.exit(1); } }