frontmcp 0.6.3 → 0.7.2
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/package.json +2 -1
- package/src/args.d.ts +1 -0
- package/src/args.js +2 -0
- package/src/args.js.map +1 -1
- package/src/cli.js +1 -0
- package/src/cli.js.map +1 -1
- package/src/commands/build/adapters/vercel.js +11 -11
- package/src/commands/build/adapters/vercel.js.map +1 -1
- package/src/commands/build/index.js +6 -5
- package/src/commands/build/index.js.map +1 -1
- package/src/commands/create.js +25 -14
- package/src/commands/create.js.map +1 -1
- package/src/commands/doctor.js +5 -5
- package/src/commands/doctor.js.map +1 -1
- package/src/commands/inspector.js +2 -2
- package/src/commands/inspector.js.map +1 -1
- package/src/commands/template.js +6 -6
- package/src/commands/template.js.map +1 -1
- package/src/commands/test.js +19 -3
- package/src/commands/test.js.map +1 -1
- package/src/tsconfig.js +4 -4
- package/src/tsconfig.js.map +1 -1
- package/src/utils/fs.d.ts +4 -8
- package/src/utils/fs.js +14 -57
- package/src/utils/fs.js.map +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create.js","sourceRoot":"","sources":["../../../src/commands/create.ts"],"names":[],"mappings":"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","sourcesContent":["import * as path from 'path';\nimport * as readline from 'readline';\nimport { promises as fsp } from 'fs';\nimport { c } from '../colors';\nimport { ensureDir, fileExists, isDirEmpty, writeJSON } from '../utils/fs';\nimport { runInit } from '../tsconfig';\nimport { getSelfVersion } from '../version';\nimport { readJSON } from '../utils/fs';\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport type DeploymentTarget = 'node' | 'vercel' | 'lambda' | 'cloudflare';\nexport type RedisSetup = 'docker' | 'existing' | 'none';\n\nexport interface CreateOptions {\n projectName: string;\n deploymentTarget: DeploymentTarget;\n redisSetup: RedisSetup;\n enableGitHubActions: boolean;\n}\n\nexport interface CreateFlags {\n yes?: boolean;\n target?: DeploymentTarget;\n redis?: RedisSetup;\n cicd?: boolean;\n}\n\ninterface PackageJson {\n name?: string;\n version?: string;\n private?: boolean;\n type?: string;\n main?: string;\n scripts?: Record<string, string>;\n engines?: { node?: string; npm?: string };\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n [key: string]: unknown;\n}\n\n// =============================================================================\n// Interactive Prompt Utility\n// =============================================================================\n\ninterface PromptOption<T> {\n label: string;\n value: T;\n}\n\nfunction createPrompt() {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n return {\n ask: (question: string): Promise<string> =>\n new Promise((resolve) => rl.question(question, (ans) => resolve(ans.trim()))),\n\n select: async <T extends string>(question: string, options: PromptOption<T>[], defaultIndex = 0): Promise<T> => {\n console.log(question);\n options.forEach((opt, i) => {\n const marker = i === defaultIndex ? c('green', '●') : c('gray', '○');\n console.log(` ${marker} ${c('cyan', `${i + 1})`)} ${opt.label}`);\n });\n const answer = await new Promise<string>((resolve) =>\n rl.question(`${c('gray', `Select [1-${options.length}]:`)} `, resolve),\n );\n const idx = parseInt(answer.trim(), 10) - 1;\n if (!isNaN(idx) && idx >= 0 && idx < options.length) return options[idx].value;\n return options[defaultIndex].value;\n },\n\n confirm: async (question: string, defaultValue = true): Promise<boolean> => {\n const hint = defaultValue ? '[Y/n]' : '[y/N]';\n const answer = await new Promise<string>((resolve) => rl.question(`${question} ${c('gray', hint)} `, resolve));\n if (!answer.trim()) return defaultValue;\n return answer.trim().toLowerCase().startsWith('y');\n },\n\n close: () => rl.close(),\n };\n}\n\nfunction isInteractive(): boolean {\n return process.stdin.isTTY === true;\n}\n\nfunction sanitizeForFolder(name: string): string {\n const seg = name.startsWith('@') && name.includes('/') ? name.split('/')[1] : name;\n return (\n seg\n .replace(/[^a-zA-Z0-9._-]/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '')\n .toLowerCase() || 'frontmcp-app'\n );\n}\n\nfunction sanitizeForNpm(name: string): string {\n if (name.startsWith('@') && name.includes('/')) {\n const [scope, pkg] = name.split('/');\n const s = scope.replace(/[^a-z0-9-]/gi, '').toLowerCase();\n const p = pkg.replace(/[^a-z0-9._-]/gi, '-').toLowerCase();\n return `@${s}/${p || 'frontmcp-app'}`;\n }\n return name.replace(/[^a-z0-9._-]/gi, '-').toLowerCase() || 'frontmcp-app';\n}\n\nfunction pkgNameFromCwd(cwd: string) {\n return (\n path\n .basename(cwd)\n .replace(/[^a-zA-Z0-9._-]/g, '-')\n .toLowerCase() || 'frontmcp-app'\n );\n}\n\nasync function scaffoldFileIfMissing(baseDir: string, p: string, content: string) {\n if (await fileExists(p)) {\n console.log(c('gray', `skip: ${path.relative(baseDir, p)} already exists`));\n return;\n }\n await ensureDir(path.dirname(p));\n await fsp.writeFile(p, content.replace(/^\\n/, ''), 'utf8');\n console.log(c('green', `✓ created ${path.relative(baseDir, p)}`));\n}\n\nconst TEMPLATE_MAIN_TS = `\nimport 'reflect-metadata';\nimport { FrontMcp } from '@frontmcp/sdk';\nimport { CalcApp } from './calc.app';\n\n@FrontMcp({\n info: { name: 'Demo 🚀', version: '0.1.0' },\n apps: [CalcApp],\n})\nexport default class Server {}\n`;\n\nconst TEMPLATE_CALC_APP_TS = `\nimport { App } from '@frontmcp/sdk';\nimport AddTool from './tools/add.tool';\n\n@App({\n id: 'calc',\n name: 'Calculator',\n tools: [AddTool],\n})\nexport class CalcApp {}\n`;\n\nconst TEMPLATE_ADD_TOOL_TS = `\nimport {Tool, ToolContext} from \"@frontmcp/sdk\";\nimport {z} from \"zod\";\n\n@Tool({\n name: 'add',\n description: 'Add two numbers',\n inputSchema: {a: z.number(), b: z.number()},\n outputSchema: {result: z.number()}\n})\nexport default class AddTool extends ToolContext {\n async execute(input: { a: number, b: number }) {\n return {\n result: input.a + input.b,\n };\n }\n}\n`;\n\nconst TEMPLATE_E2E_TEST_TS = `\nimport { test, expect } from '@frontmcp/testing';\n\ntest.describe('Server E2E', () => {\n test.use({\n server: './src/main.ts',\n port: 3100,\n });\n\n test('should connect and initialize', async ({ mcp }) => {\n expect(mcp.isConnected()).toBe(true);\n expect(mcp.serverInfo.name).toBeDefined();\n });\n\n test('should list tools', async ({ mcp }) => {\n const tools = await mcp.tools.list();\n expect(tools.length).toBeGreaterThanOrEqual(0);\n });\n\n test('should call add tool', async ({ mcp }) => {\n const result = await mcp.tools.call('add', { a: 2, b: 3 });\n expect(result).toBeSuccessful();\n });\n});\n`;\n\nconst TEMPLATE_GITIGNORE = `\n# Dependencies\nnode_modules/\n\n# Build output\ndist/\n*.tsbuildinfo\n\n# IDE\n.idea/\n.vscode/\n*.swp\n*.swo\n\n# OS files\n.DS_Store\nThumbs.db\n\n# Logs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n# Environment variables\n.env\n.env.local\n.env.*.local\n\n# FrontMCP development keys (contains private keys - never commit!)\n.frontmcp/\n\n# Coverage\ncoverage/\n\n# Test output\ntest-output/\n`;\n\nconst TEMPLATE_JEST_E2E_CONFIG = `\n/* eslint-disable */\nexport default {\n displayName: 'e2e',\n testEnvironment: 'node',\n testMatch: ['<rootDir>/e2e/**/*.e2e.test.ts'],\n testTimeout: 60000,\n setupFilesAfterEnv: ['@frontmcp/testing/setup'],\n transform: {\n '^.+\\\\\\\\.[tj]s$': [\n '@swc/jest',\n {\n jsc: {\n target: 'es2022',\n parser: {\n syntax: 'typescript',\n decorators: true,\n dynamicImport: true,\n },\n transform: {\n decoratorMetadata: true,\n legacyDecorator: true,\n },\n keepClassNames: true,\n externalHelpers: true,\n loose: true,\n },\n module: {\n type: 'es6',\n },\n sourceMaps: true,\n swcrc: false,\n },\n ],\n },\n moduleFileExtensions: ['ts', 'js', 'html'],\n transformIgnorePatterns: ['node_modules/(?!(jose)/)'],\n};\n`;\n\nconst TEMPLATE_DOCKER_COMPOSE = `\nversion: '3.8'\n\nservices:\n redis:\n image: redis:7-alpine\n ports:\n - '6379:6379'\n volumes:\n - redis-data:/data\n command: redis-server --appendonly yes\n healthcheck:\n test: ['CMD', 'redis-cli', 'ping']\n interval: 10s\n timeout: 5s\n retries: 3\n\n app:\n build:\n context: .\n dockerfile: Dockerfile\n ports:\n - '\\${PORT:-3000}:3000'\n environment:\n - NODE_ENV=\\${NODE_ENV:-development}\n - REDIS_HOST=redis\n - REDIS_PORT=6379\n depends_on:\n redis:\n condition: service_healthy\n volumes:\n - ./src:/app/src\n command: npm run dev\n\nvolumes:\n redis-data:\n`;\n\nconst TEMPLATE_DOCKERFILE = `\n# Build stage\nFROM node:22-alpine AS builder\n\nWORKDIR /app\n\n# Install all dependencies (including devDependencies for build)\nCOPY package*.json ./\nRUN npm ci\n\n# Copy source and build\nCOPY . .\nRUN npm run build\n\n# Production stage\nFROM node:22-alpine AS runner\n\nWORKDIR /app\nENV NODE_ENV=production\n\n# Install production dependencies only\nCOPY package*.json ./\nRUN npm ci --omit=dev\n\n# Copy built artifacts from builder\nCOPY --from=builder /app/dist ./dist\n\nEXPOSE 3000\n\nCMD [\"node\", \"dist/main.js\"]\n`;\n\nconst TEMPLATE_ENV_EXAMPLE = `\n# Application\nPORT=3000\nNODE_ENV=development\n\n# Redis (recommended for development, required for production)\nREDIS_HOST=localhost\nREDIS_PORT=6379\n# SECURITY: Set a strong password in production\nREDIS_PASSWORD=\nREDIS_DB=0\n\n# Optional: Redis TLS (enable for production)\nREDIS_TLS=false\n`;\n\nconst TEMPLATE_ENV_DOCKER = `\n# Docker-specific environment\n# Copy this to .env when running with docker compose\n\n# Application\nPORT=3000\nNODE_ENV=development\n\n# Redis - use 'redis' (service name) as host inside Docker network\nREDIS_HOST=redis\nREDIS_PORT=6379\n# SECURITY: Set a strong password in production\nREDIS_PASSWORD=\nREDIS_DB=0\nREDIS_TLS=false\n`;\n\nconst TEMPLATE_README = `\n# FrontMCP Server\n\nA TypeScript MCP server built with [FrontMCP](https://github.com/agentfront/frontmcp).\n\n## Quick Start\n\n\\`\\`\\`bash\n# Install dependencies\nnpm install\n\n# Start development server\nnpm run dev\n\n# Run MCP Inspector\nnpm run inspect\n\\`\\`\\`\n\n## Development with Docker\n\n### Prerequisites\n- Docker & Docker Compose installed\n\n### Quick Start\n\n\\`\\`\\`bash\n# Start Redis and app in development mode\ndocker compose up\n\n# Start only Redis (for local development)\ndocker compose up redis -d\n\n# Stop all services\ndocker compose down\n\\`\\`\\`\n\n### Environment Variables\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| \\`PORT\\` | 3000 | Application port |\n| \\`NODE_ENV\\` | development | Environment mode |\n| \\`REDIS_HOST\\` | localhost | Redis host (use \\`redis\\` in Docker) |\n| \\`REDIS_PORT\\` | 6379 | Redis port |\n\n## Redis Configuration\n\n### Development\nRedis is **recommended** for development to enable caching and session persistence.\nUse the included \\`docker-compose.yml\\` to run Redis locally:\n\n\\`\\`\\`bash\ndocker compose up redis -d\n\\`\\`\\`\n\n### Production\nRedis is **required** in production for:\n- Session storage (multi-instance deployments)\n- Caching (performance optimization)\n- Rate limiting (if enabled)\n\nSee the [Redis Setup Guide](https://docs.agentfront.dev/docs/deployment/redis-setup) for production configuration.\n\n## Scripts\n\n| Script | Description |\n|--------|-------------|\n| \\`npm run dev\\` | Start development server with hot reload |\n| \\`npm run build\\` | Build for production |\n| \\`npm run inspect\\` | Launch MCP Inspector |\n| \\`npm run doctor\\` | Check project configuration |\n| \\`npm run test\\` | Run unit tests |\n| \\`npm run test:e2e\\` | Run E2E tests |\n\n## Project Structure\n\n\\`\\`\\`\n├── .env.example # Environment variables template\n├── .gitignore # Git ignore rules\n├── docker-compose.yml # Docker services config\n├── Dockerfile # Container build config\n├── e2e/ # E2E tests\n├── jest.e2e.config.ts # Jest E2E configuration\n├── package.json # Dependencies and scripts\n├── src/\n│ ├── main.ts # Server entry point\n│ ├── calc.app.ts # Example app\n│ └── tools/\n│ └── add.tool.ts # Example tool\n└── tsconfig.json # TypeScript config\n\\`\\`\\`\n\n## Learn More\n\n- [FrontMCP Documentation](https://docs.agentfront.dev)\n- [MCP Specification](https://modelcontextprotocol.io)\n`;\n\n// =============================================================================\n// Deployment Target Templates\n// =============================================================================\n\n// Docker templates (moved to ci/ folder)\nconst TEMPLATE_DOCKERFILE_CI = `\n# Build stage\nFROM node:22-alpine AS builder\n\nWORKDIR /app\n\n# Install all dependencies (including devDependencies for build)\nCOPY package*.json ./\nRUN npm ci\n\n# Copy source and build\nCOPY . .\nRUN npm run build\n\n# Production stage\nFROM node:22-alpine AS runner\n\nWORKDIR /app\nENV NODE_ENV=production\n\n# Install production dependencies only\nCOPY package*.json ./\nRUN npm ci --omit=dev\n\n# Copy built artifacts from builder\nCOPY --from=builder /app/dist ./dist\n\nEXPOSE 3000\n\nCMD [\"node\", \"dist/main.js\"]\n`;\n\nconst TEMPLATE_DOCKER_COMPOSE_WITH_REDIS = `\nversion: '3.8'\n\nservices:\n redis:\n image: redis:7-alpine\n ports:\n - '6379:6379'\n volumes:\n - redis-data:/data\n command: redis-server --appendonly yes\n healthcheck:\n test: ['CMD', 'redis-cli', 'ping']\n interval: 10s\n timeout: 5s\n retries: 3\n\n app:\n build:\n context: .\n dockerfile: ci/Dockerfile\n ports:\n - '\\${PORT:-3000}:3000'\n environment:\n - NODE_ENV=\\${NODE_ENV:-development}\n - REDIS_HOST=redis\n - REDIS_PORT=6379\n depends_on:\n redis:\n condition: service_healthy\n volumes:\n - ./src:/app/src\n command: npm run dev\n\nvolumes:\n redis-data:\n`;\n\nconst TEMPLATE_DOCKER_COMPOSE_NO_REDIS = `\nversion: '3.8'\n\nservices:\n app:\n build:\n context: .\n dockerfile: ci/Dockerfile\n ports:\n - '\\${PORT:-3000}:3000'\n environment:\n - NODE_ENV=\\${NODE_ENV:-development}\n volumes:\n - ./src:/app/src\n command: npm run dev\n`;\n\nconst TEMPLATE_ENV_DOCKER_CI = `\n# Docker-specific environment\n# Use with: docker compose -f ci/docker-compose.yml --env-file ci/.env.docker up\n\n# Application\nPORT=3000\nNODE_ENV=development\n\n# Redis - use 'redis' (service name) as host inside Docker network\nREDIS_HOST=redis\nREDIS_PORT=6379\n# SECURITY: Set a strong password in production\nREDIS_PASSWORD=\nREDIS_DB=0\nREDIS_TLS=false\n`;\n\n// Vercel template\nconst TEMPLATE_VERCEL_JSON = (projectName: string) =>\n JSON.stringify(\n {\n $schema: 'https://openapi.vercel.sh/vercel.json',\n name: projectName,\n version: 2,\n builds: [\n {\n src: 'dist/main.js',\n use: '@vercel/node',\n },\n ],\n routes: [\n {\n src: '/(.*)',\n dest: '/dist/main.js',\n },\n ],\n env: {\n NODE_ENV: 'production',\n },\n },\n null,\n 2,\n );\n\n// AWS Lambda SAM template\nconst TEMPLATE_SAM_YAML = (projectName: string) => `\nAWSTemplateFormatVersion: '2010-09-09'\nTransform: AWS::Serverless-2016-10-31\nDescription: ${projectName} - FrontMCP Lambda Function\n\nGlobals:\n Function:\n Timeout: 30\n Runtime: nodejs22.x\n MemorySize: 256\n\nResources:\n FrontMCPFunction:\n Type: AWS::Serverless::Function\n Properties:\n CodeUri: ../dist/\n Handler: main.handler\n Events:\n ApiEvent:\n Type: HttpApi\n Properties:\n Path: /{proxy+}\n Method: ANY\n\nOutputs:\n ApiEndpoint:\n Description: API Gateway endpoint URL\n Value: !Sub \"https://\\${ServerlessHttpApi}.execute-api.\\${AWS::Region}.amazonaws.com\"\n`;\n\n// Cloudflare Workers template\nconst TEMPLATE_WRANGLER_TOML = (projectName: string) => `\nname = \"${projectName}\"\nmain = \"dist/main.js\"\ncompatibility_date = \"2024-01-01\"\n\n[vars]\nNODE_ENV = \"production\"\n\n# Uncomment to enable KV namespace for caching\n# [[kv_namespaces]]\n# binding = \"CACHE\"\n# id = \"your-kv-namespace-id\"\n`;\n\n// =============================================================================\n// GitHub Actions Templates\n// =============================================================================\n\nconst TEMPLATE_GH_CI = `\nname: CI\n\non:\n push:\n branches: [main]\n pull_request:\n branches: [main]\n\njobs:\n lint-and-test:\n runs-on: ubuntu-latest\n\n steps:\n - uses: actions/checkout@v4\n\n - name: Setup Node.js\n uses: actions/setup-node@v4\n with:\n node-version: '22'\n cache: 'npm'\n\n - name: Install dependencies\n run: npm ci\n\n - name: Type check\n run: npx tsc --noEmit\n\n - name: Run tests\n run: npm test\n`;\n\nconst TEMPLATE_GH_E2E = `\nname: E2E Tests\n\non:\n push:\n branches: [main]\n pull_request:\n branches: [main]\n\njobs:\n e2e:\n runs-on: ubuntu-latest\n\n steps:\n - uses: actions/checkout@v4\n\n - name: Setup Node.js\n uses: actions/setup-node@v4\n with:\n node-version: '22'\n cache: 'npm'\n\n - name: Install dependencies\n run: npm ci\n\n - name: Build\n run: npm run build\n\n - name: Run E2E tests\n run: npm run test:e2e\n`;\n\nconst TEMPLATE_GH_DEPLOY_DOCKER = `\nname: Build and Push Docker Image\n\non:\n push:\n branches: [main]\n tags: ['v*']\n\nenv:\n REGISTRY: ghcr.io\n IMAGE_NAME: \\${{ github.repository }}\n\njobs:\n build-and-push:\n runs-on: ubuntu-latest\n permissions:\n contents: read\n packages: write\n\n steps:\n - uses: actions/checkout@v4\n\n - name: Log in to Container Registry\n uses: docker/login-action@v3\n with:\n registry: \\${{ env.REGISTRY }}\n username: \\${{ github.actor }}\n password: \\${{ secrets.GITHUB_TOKEN }}\n\n - name: Extract metadata\n id: meta\n uses: docker/metadata-action@v5\n with:\n images: \\${{ env.REGISTRY }}/\\${{ env.IMAGE_NAME }}\n\n - name: Build and push\n uses: docker/build-push-action@v5\n with:\n context: .\n file: ./ci/Dockerfile\n push: true\n tags: \\${{ steps.meta.outputs.tags }}\n labels: \\${{ steps.meta.outputs.labels }}\n`;\n\nconst TEMPLATE_GH_DEPLOY_VERCEL = `\nname: Deploy to Vercel\n\non:\n push:\n branches: [main]\n\njobs:\n deploy:\n runs-on: ubuntu-latest\n\n steps:\n - uses: actions/checkout@v4\n\n - name: Setup Node.js\n uses: actions/setup-node@v4\n with:\n node-version: '22'\n cache: 'npm'\n\n - name: Install dependencies\n run: npm ci\n\n - name: Build\n run: npm run build\n\n - name: Deploy to Vercel\n uses: amondnet/vercel-action@v25\n with:\n vercel-token: \\${{ secrets.VERCEL_TOKEN }}\n vercel-org-id: \\${{ secrets.VERCEL_ORG_ID }}\n vercel-project-id: \\${{ secrets.VERCEL_PROJECT_ID }}\n vercel-args: '--prod'\n`;\n\nconst TEMPLATE_GH_DEPLOY_LAMBDA = `\nname: Deploy to AWS Lambda\n\non:\n push:\n branches: [main]\n\njobs:\n deploy:\n runs-on: ubuntu-latest\n\n steps:\n - uses: actions/checkout@v4\n\n - name: Setup Node.js\n uses: actions/setup-node@v4\n with:\n node-version: '22'\n cache: 'npm'\n\n - name: Install dependencies\n run: npm ci\n\n - name: Build\n run: npm run build\n\n - name: Configure AWS credentials\n uses: aws-actions/configure-aws-credentials@v4\n with:\n aws-access-key-id: \\${{ secrets.AWS_ACCESS_KEY_ID }}\n aws-secret-access-key: \\${{ secrets.AWS_SECRET_ACCESS_KEY }}\n aws-region: \\${{ secrets.AWS_REGION }}\n\n - name: Setup SAM\n uses: aws-actions/setup-sam@v2\n\n - name: Deploy with SAM\n run: |\n cd ci\n sam build\n sam deploy --no-confirm-changeset --no-fail-on-empty-changeset\n`;\n\nconst TEMPLATE_GH_DEPLOY_CLOUDFLARE = `\nname: Deploy to Cloudflare Workers\n\non:\n push:\n branches: [main]\n\njobs:\n deploy:\n runs-on: ubuntu-latest\n\n steps:\n - uses: actions/checkout@v4\n\n - name: Setup Node.js\n uses: actions/setup-node@v4\n with:\n node-version: '22'\n cache: 'npm'\n\n - name: Install dependencies\n run: npm ci\n\n - name: Build\n run: npm run build\n\n - name: Deploy to Cloudflare\n uses: cloudflare/wrangler-action@v3\n with:\n apiToken: \\${{ secrets.CLOUDFLARE_API_TOKEN }}\n`;\n\n// =============================================================================\n// Dynamic README Templates\n// =============================================================================\n\nfunction generateReadme(options: CreateOptions): string {\n const { projectName, deploymentTarget, redisSetup, enableGitHubActions } = options;\n\n let readme = `# ${projectName}\n\nA TypeScript MCP server built with [FrontMCP](https://github.com/agentfront/frontmcp).\n`;\n\n // Add CI badge if GitHub Actions enabled\n if (enableGitHubActions) {\n readme += `\n\n`;\n }\n\n readme += `\n## Quick Start\n\n\\`\\`\\`bash\n# Install dependencies\nnpm install\n\n# Start development server\nnpm run dev\n\n# Run MCP Inspector\nnpm run inspect\n\\`\\`\\`\n`;\n\n // Deployment-specific sections\n if (deploymentTarget === 'node') {\n readme += `\n## Docker Development\n\n\\`\\`\\`bash\n# Start all services${redisSetup === 'docker' ? ' (includes Redis)' : ''}\nnpm run docker:up\n\n# Stop all services\nnpm run docker:down\n\n# Rebuild Docker image\nnpm run docker:build\n\\`\\`\\`\n`;\n\n if (redisSetup === 'docker') {\n readme += `\n### Redis\n\nRedis is included in the Docker Compose setup. For local development without Docker:\n\n\\`\\`\\`bash\n# Start only Redis\ndocker compose -f ci/docker-compose.yml up redis -d\n\\`\\`\\`\n`;\n }\n\n readme += `\n## Production Deployment\n\nBuild and push the Docker image:\n\n\\`\\`\\`bash\ndocker build -f ci/Dockerfile -t ${projectName}:latest .\ndocker push your-registry/${projectName}:latest\n\\`\\`\\`\n`;\n }\n\n if (deploymentTarget === 'vercel') {\n readme += `\n## Deploy to Vercel\n\n\\`\\`\\`bash\n# Build for production\nnpm run build\n\n# Deploy using Vercel CLI\nnpx vercel --prod\n\\`\\`\\`\n\nOr connect your repository to Vercel for automatic deployments.\n`;\n }\n\n if (deploymentTarget === 'lambda') {\n readme += `\n## Deploy to AWS Lambda\n\n\\`\\`\\`bash\n# Build the project\nnpm run build\n\n# Deploy using AWS SAM\nnpm run deploy\n\\`\\`\\`\n\n### Prerequisites\n\n- AWS CLI configured with appropriate credentials\n- AWS SAM CLI installed (\\`brew install aws-sam-cli\\` or \\`pip install aws-sam-cli\\`)\n`;\n }\n\n if (deploymentTarget === 'cloudflare') {\n readme += `\n## Deploy to Cloudflare Workers\n\n\\`\\`\\`bash\n# Build the project\nnpm run build\n\n# Deploy using Wrangler\nnpm run deploy\n\\`\\`\\`\n\n### Prerequisites\n\n- Wrangler CLI installed (\\`npm install -g wrangler\\`)\n- Cloudflare account configured (\\`wrangler login\\`)\n`;\n }\n\n // Environment variables section\n readme += `\n## Environment Variables\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| \\`PORT\\` | 3000 | Application port |\n| \\`NODE_ENV\\` | development | Environment mode |\n`;\n\n if (deploymentTarget === 'node' && redisSetup !== 'none') {\n readme += `| \\`REDIS_HOST\\` | localhost | Redis host (use \\`redis\\` in Docker) |\n| \\`REDIS_PORT\\` | 6379 | Redis port |\n| \\`REDIS_PASSWORD\\` | - | Redis password (set in production) |\n`;\n }\n\n // GitHub Actions section\n if (enableGitHubActions) {\n readme += `\n## CI/CD\n\nThis project includes GitHub Actions workflows:\n\n- **ci.yml**: Runs on every push/PR - type checking and tests\n- **e2e.yml**: Runs E2E tests\n- **deploy.yml**: Deploys to ${\n deploymentTarget === 'node'\n ? 'GitHub Container Registry'\n : deploymentTarget === 'vercel'\n ? 'Vercel'\n : deploymentTarget === 'lambda'\n ? 'AWS Lambda'\n : 'Cloudflare Workers'\n }\n\n### Required Secrets\n`;\n\n if (deploymentTarget === 'vercel') {\n readme += `\n- \\`VERCEL_TOKEN\\`: Vercel API token\n- \\`VERCEL_ORG_ID\\`: Vercel organization ID\n- \\`VERCEL_PROJECT_ID\\`: Vercel project ID\n`;\n } else if (deploymentTarget === 'lambda') {\n readme += `\n- \\`AWS_ACCESS_KEY_ID\\`: AWS access key\n- \\`AWS_SECRET_ACCESS_KEY\\`: AWS secret key\n- \\`AWS_REGION\\`: AWS region (e.g., us-east-1)\n`;\n } else if (deploymentTarget === 'cloudflare') {\n readme += `\n- \\`CLOUDFLARE_API_TOKEN\\`: Cloudflare API token with Workers permissions\n`;\n } else {\n readme += `\nNo additional secrets required - uses \\`GITHUB_TOKEN\\` for GHCR.\n`;\n }\n }\n\n readme += `\n## Scripts\n\n| Script | Description |\n|--------|-------------|\n| \\`npm run dev\\` | Start development server with hot reload |\n| \\`npm run build\\` | Build for production |\n| \\`npm run inspect\\` | Launch MCP Inspector |\n| \\`npm run doctor\\` | Check project configuration |\n| \\`npm run test\\` | Run unit tests |\n| \\`npm run test:e2e\\` | Run E2E tests |\n`;\n\n if (deploymentTarget === 'node') {\n readme += `| \\`npm run docker:up\\` | Start Docker services |\n| \\`npm run docker:down\\` | Stop Docker services |\n| \\`npm run docker:build\\` | Rebuild Docker image |\n`;\n }\n\n if (deploymentTarget === 'lambda' || deploymentTarget === 'cloudflare') {\n readme += `| \\`npm run deploy\\` | Deploy to ${deploymentTarget === 'lambda' ? 'AWS Lambda' : 'Cloudflare Workers'} |\n`;\n }\n\n readme += `\n## Project Structure\n\n\\`\\`\\`\n`;\n\n // Dynamic project structure based on options\n readme += `├── .env.example # Environment variables template\n├── .gitignore # Git ignore rules\n`;\n\n if (deploymentTarget === 'node') {\n readme += `├── ci/\n│ ├── Dockerfile # Container build config\n│ ├── docker-compose.yml # Docker services config\n│ └── .env.docker # Docker-specific env vars\n`;\n }\n\n if (deploymentTarget === 'vercel') {\n readme += `├── vercel.json # Vercel deployment config\n`;\n }\n\n if (deploymentTarget === 'lambda') {\n readme += `├── ci/\n│ └── template.yaml # AWS SAM template\n`;\n }\n\n if (deploymentTarget === 'cloudflare') {\n readme += `├── wrangler.toml # Cloudflare Workers config\n`;\n }\n\n if (enableGitHubActions) {\n readme += `├── .github/workflows/\n│ ├── ci.yml # CI workflow\n│ ├── e2e.yml # E2E test workflow\n│ └── deploy.yml # Deployment workflow\n`;\n }\n\n readme += `├── e2e/ # E2E tests\n├── jest.e2e.config.ts # Jest E2E configuration\n├── package.json # Dependencies and scripts\n├── src/\n│ ├── main.ts # Server entry point\n│ ├── calc.app.ts # Example app\n│ └── tools/\n│ └── add.tool.ts # Example tool\n└── tsconfig.json # TypeScript config\n\\`\\`\\`\n\n## Learn More\n\n- [FrontMCP Documentation](https://docs.agentfront.dev)\n- [MCP Specification](https://modelcontextprotocol.io)\n`;\n\n return readme;\n}\n\n// =============================================================================\n// Scaffolding Functions\n// =============================================================================\n\nfunction getDefaults(projectArg?: string): CreateOptions {\n return {\n projectName: projectArg || 'frontmcp-app',\n deploymentTarget: 'node',\n redisSetup: 'docker',\n enableGitHubActions: true,\n };\n}\n\nasync function collectOptions(\n prompt: ReturnType<typeof createPrompt>,\n projectArg?: string,\n flags?: CreateFlags,\n): Promise<CreateOptions> {\n // Project name\n let projectName = projectArg;\n if (!projectName) {\n projectName = await prompt.ask(`${c('cyan', '?')} Project name: `);\n if (!projectName) {\n throw new Error('Project name is required');\n }\n } else {\n console.log(`${c('cyan', '?')} Project name: ${c('bold', projectName)}`);\n }\n\n // Deployment target\n const deploymentTarget =\n flags?.target ||\n (await prompt.select<DeploymentTarget>(`\\n${c('cyan', '?')} Select deployment target:`, [\n { label: 'Node.js (Docker) - Recommended for production', value: 'node' },\n { label: 'Vercel (Serverless)', value: 'vercel' },\n { label: 'AWS Lambda', value: 'lambda' },\n { label: 'Cloudflare Workers', value: 'cloudflare' },\n ]));\n\n // Redis setup (only for Node.js/Docker)\n let redisSetup: RedisSetup = 'none';\n if (deploymentTarget === 'node') {\n redisSetup =\n flags?.redis ||\n (await prompt.select<RedisSetup>(`\\n${c('cyan', '?')} Redis setup:`, [\n { label: 'Docker Compose (recommended for development)', value: 'docker' },\n { label: 'Existing Redis (I have my own Redis)', value: 'existing' },\n { label: 'None (skip Redis)', value: 'none' },\n ]));\n }\n\n // GitHub Actions\n const enableGitHubActions =\n flags?.cicd ?? (await prompt.confirm(`\\n${c('cyan', '?')} Set up GitHub Actions CI/CD?`, true));\n\n return {\n projectName,\n deploymentTarget,\n redisSetup,\n enableGitHubActions,\n };\n}\n\nasync function scaffoldDeploymentFiles(targetDir: string, options: CreateOptions): Promise<void> {\n const { deploymentTarget, redisSetup, projectName } = options;\n\n switch (deploymentTarget) {\n case 'node': {\n const ciDir = path.join(targetDir, 'ci');\n await ensureDir(ciDir);\n await scaffoldFileIfMissing(targetDir, path.join(ciDir, 'Dockerfile'), TEMPLATE_DOCKERFILE_CI);\n\n const dockerCompose =\n redisSetup === 'docker' ? TEMPLATE_DOCKER_COMPOSE_WITH_REDIS : TEMPLATE_DOCKER_COMPOSE_NO_REDIS;\n await scaffoldFileIfMissing(targetDir, path.join(ciDir, 'docker-compose.yml'), dockerCompose);\n await scaffoldFileIfMissing(targetDir, path.join(ciDir, '.env.docker'), TEMPLATE_ENV_DOCKER_CI);\n break;\n }\n\n case 'vercel':\n await scaffoldFileIfMissing(\n targetDir,\n path.join(targetDir, 'vercel.json'),\n TEMPLATE_VERCEL_JSON(sanitizeForFolder(projectName)),\n );\n break;\n\n case 'lambda': {\n const ciDir = path.join(targetDir, 'ci');\n await ensureDir(ciDir);\n await scaffoldFileIfMissing(targetDir, path.join(ciDir, 'template.yaml'), TEMPLATE_SAM_YAML(projectName));\n break;\n }\n\n case 'cloudflare':\n await scaffoldFileIfMissing(\n targetDir,\n path.join(targetDir, 'wrangler.toml'),\n TEMPLATE_WRANGLER_TOML(sanitizeForFolder(projectName)),\n );\n break;\n }\n\n // Always create .env.example at root\n const envExample =\n deploymentTarget === 'node' && redisSetup !== 'none' ? TEMPLATE_ENV_EXAMPLE : TEMPLATE_ENV_EXAMPLE_BASIC;\n await scaffoldFileIfMissing(targetDir, path.join(targetDir, '.env.example'), envExample);\n}\n\n// Basic .env.example without Redis\nconst TEMPLATE_ENV_EXAMPLE_BASIC = `\n# Application\nPORT=3000\nNODE_ENV=development\n`;\n\nasync function scaffoldGitHubActions(targetDir: string, deploymentTarget: DeploymentTarget): Promise<void> {\n const workflowDir = path.join(targetDir, '.github', 'workflows');\n await ensureDir(workflowDir);\n\n // Always create CI and E2E workflows\n await scaffoldFileIfMissing(targetDir, path.join(workflowDir, 'ci.yml'), TEMPLATE_GH_CI);\n await scaffoldFileIfMissing(targetDir, path.join(workflowDir, 'e2e.yml'), TEMPLATE_GH_E2E);\n\n // Create deployment workflow based on target\n const deployTemplate = getDeployWorkflowTemplate(deploymentTarget);\n await scaffoldFileIfMissing(targetDir, path.join(workflowDir, 'deploy.yml'), deployTemplate);\n}\n\nfunction getDeployWorkflowTemplate(target: DeploymentTarget): string {\n switch (target) {\n case 'node':\n return TEMPLATE_GH_DEPLOY_DOCKER;\n case 'vercel':\n return TEMPLATE_GH_DEPLOY_VERCEL;\n case 'lambda':\n return TEMPLATE_GH_DEPLOY_LAMBDA;\n case 'cloudflare':\n return TEMPLATE_GH_DEPLOY_CLOUDFLARE;\n }\n}\n\nasync function scaffoldProject(options: CreateOptions): Promise<void> {\n const { projectName, deploymentTarget, redisSetup, enableGitHubActions } = options;\n\n const folder = sanitizeForFolder(projectName);\n const pkgName = sanitizeForNpm(projectName);\n const targetDir = path.resolve(process.cwd(), folder);\n\n // Validate directory\n try {\n const stat = await fsp.stat(targetDir);\n if (!stat.isDirectory()) {\n console.error(\n c('red', `Refusing to scaffold into non-directory path: ${path.relative(process.cwd(), targetDir)}`),\n );\n console.log(c('gray', 'Pick a different project name or remove/rename the existing file.'));\n process.exit(1);\n }\n if (!(await isDirEmpty(targetDir))) {\n console.error(\n c('red', `Refusing to scaffold into non-empty directory: ${path.relative(process.cwd(), targetDir)}`),\n );\n console.log(c('gray', 'Pick a different name or start with an empty folder.'));\n process.exit(1);\n }\n } catch (e: unknown) {\n if (e && typeof e === 'object' && 'code' in e && e.code === 'ENOENT') {\n await ensureDir(targetDir);\n } else {\n throw e;\n }\n }\n\n console.log(`\\n${c('cyan', '[create]')} Creating project in ${c('bold', './' + folder)}`);\n console.log(c('gray', ` Deployment: ${deploymentTarget}`));\n if (deploymentTarget === 'node') {\n console.log(c('gray', ` Redis: ${redisSetup}`));\n }\n console.log(c('gray', ` GitHub Actions: ${enableGitHubActions ? 'Yes' : 'No'}`));\n console.log('');\n\n process.chdir(targetDir);\n\n // Initialize tsconfig\n await runInit(targetDir);\n\n // Create package.json with deployment-specific scripts\n const selfVersion = getSelfVersion();\n await upsertPackageJsonWithTarget(targetDir, pkgName, selfVersion, deploymentTarget);\n\n // Scaffold base files\n await scaffoldFileIfMissing(targetDir, path.join(targetDir, 'src', 'main.ts'), TEMPLATE_MAIN_TS);\n await scaffoldFileIfMissing(targetDir, path.join(targetDir, 'src', 'calc.app.ts'), TEMPLATE_CALC_APP_TS);\n await scaffoldFileIfMissing(targetDir, path.join(targetDir, 'src', 'tools', 'add.tool.ts'), TEMPLATE_ADD_TOOL_TS);\n\n // E2E scaffolding\n await scaffoldFileIfMissing(targetDir, path.join(targetDir, 'e2e', 'server.e2e.test.ts'), TEMPLATE_E2E_TEST_TS);\n await scaffoldFileIfMissing(targetDir, path.join(targetDir, 'jest.e2e.config.ts'), TEMPLATE_JEST_E2E_CONFIG);\n\n // Git configuration\n await scaffoldFileIfMissing(targetDir, path.join(targetDir, '.gitignore'), TEMPLATE_GITIGNORE);\n\n // Deployment-specific files\n await scaffoldDeploymentFiles(targetDir, options);\n\n // GitHub Actions\n if (enableGitHubActions) {\n await scaffoldGitHubActions(targetDir, deploymentTarget);\n }\n\n // Dynamic README\n await scaffoldFileIfMissing(targetDir, path.join(targetDir, 'README.md'), generateReadme(options));\n\n // Print next steps\n printNextSteps(folder, deploymentTarget, redisSetup, enableGitHubActions);\n}\n\nfunction printNextSteps(\n folder: string,\n deploymentTarget: DeploymentTarget,\n redisSetup: RedisSetup,\n enableGitHubActions: boolean,\n): void {\n console.log('\\nNext steps:');\n console.log(` 1) cd ${folder}`);\n console.log(' 2) npm install');\n console.log(' 3) npm run dev ', c('gray', '# tsx watcher + async tsc type-check'));\n console.log(' 4) npm run inspect ', c('gray', '# launch MCP Inspector'));\n console.log(' 5) npm run build ', c('gray', '# compile with tsc via frontmcp build'));\n console.log(' 6) npm run test:e2e ', c('gray', '# run E2E tests'));\n\n if (deploymentTarget === 'node') {\n console.log('');\n console.log(c('cyan', 'Docker:'));\n console.log(\n ' npm run docker:up ',\n c('gray', `# start${redisSetup === 'docker' ? ' Redis +' : ''} app in Docker`),\n );\n console.log(' npm run docker:down ', c('gray', '# stop Docker services'));\n }\n\n if (deploymentTarget === 'vercel') {\n console.log('');\n console.log(c('cyan', 'Deploy to Vercel:'));\n console.log(' npx vercel ', c('gray', '# deploy to Vercel'));\n }\n\n if (deploymentTarget === 'lambda') {\n console.log('');\n console.log(c('cyan', 'Deploy to AWS Lambda:'));\n console.log(' npm run deploy ', c('gray', '# deploy with SAM'));\n }\n\n if (deploymentTarget === 'cloudflare') {\n console.log('');\n console.log(c('cyan', 'Deploy to Cloudflare:'));\n console.log(' npm run deploy ', c('gray', '# deploy with Wrangler'));\n }\n\n if (enableGitHubActions) {\n console.log('');\n console.log(c('cyan', 'GitHub Actions:'));\n console.log(' .github/workflows/ ', c('gray', '# CI, E2E, and deploy workflows ready'));\n }\n}\n\n// =============================================================================\n// Package.json with Target-Specific Scripts\n// =============================================================================\n\nasync function upsertPackageJsonWithTarget(\n cwd: string,\n nameOverride: string | undefined,\n selfVersion: string,\n deploymentTarget: DeploymentTarget,\n) {\n const pkgPath = path.join(cwd, 'package.json');\n const existing = await readJSON<PackageJson>(pkgPath);\n\n const frontmcpLibRange = `~${selfVersion}`;\n\n const baseScripts: Record<string, string> = {\n dev: 'frontmcp dev',\n build: 'frontmcp build',\n inspect: 'frontmcp inspector',\n doctor: 'frontmcp doctor',\n test: 'frontmcp test',\n 'test:e2e': 'jest --config jest.e2e.config.ts --runInBand',\n };\n\n // Add target-specific scripts\n if (deploymentTarget === 'node') {\n baseScripts['docker:up'] = 'docker compose -f ci/docker-compose.yml up';\n baseScripts['docker:down'] = 'docker compose -f ci/docker-compose.yml down';\n baseScripts['docker:build'] = 'docker compose -f ci/docker-compose.yml build';\n }\n\n if (deploymentTarget === 'lambda') {\n baseScripts['deploy'] = 'cd ci && sam build && sam deploy';\n }\n\n if (deploymentTarget === 'cloudflare') {\n baseScripts['deploy'] = 'wrangler deploy';\n }\n\n const base = {\n name: nameOverride ?? pkgNameFromCwd(cwd),\n version: '0.1.0',\n private: true,\n type: 'commonjs',\n main: 'src/main.ts',\n scripts: baseScripts,\n engines: {\n node: '>=22',\n npm: '>=10',\n },\n dependencies: {\n '@frontmcp/sdk': frontmcpLibRange,\n '@frontmcp/plugins': frontmcpLibRange,\n '@frontmcp/adapters': frontmcpLibRange,\n zod: '^4.0.0',\n 'reflect-metadata': '^0.2.2',\n },\n devDependencies: {\n frontmcp: selfVersion,\n '@frontmcp/testing': frontmcpLibRange,\n '@swc/core': '^1.11.29',\n '@swc/jest': '^0.2.37',\n jest: '^29.7.0',\n '@types/jest': '^29.5.14',\n tsx: '^4.20.6',\n '@types/node': '^24.0.0',\n typescript: '^5.5.3',\n },\n };\n\n if (!existing) {\n await writeJSON(pkgPath, base);\n console.log(c('green', '✅ Created package.json (synced @frontmcp libs to CLI version + exact frontmcp)'));\n return;\n }\n\n const merged: PackageJson = { ...base, ...existing };\n\n merged.name = existing.name || base.name;\n merged.main = existing.main || base.main;\n merged.type = existing.type || base.type;\n\n // Preserve user scripts, add base scripts only if missing\n merged.scripts = {\n ...baseScripts,\n ...(existing.scripts || {}),\n };\n\n merged.engines = {\n ...(existing.engines || {}),\n node: existing.engines?.node || base.engines.node,\n npm: existing.engines?.npm || base.engines.npm,\n };\n\n merged.dependencies = {\n ...(existing.dependencies || {}),\n ...base.dependencies,\n };\n\n merged.devDependencies = {\n ...(existing.devDependencies || {}),\n ...base.devDependencies,\n };\n\n await writeJSON(pkgPath, merged);\n console.log(c('green', '✅ Updated package.json (synced @frontmcp libs + frontmcp to current CLI version)'));\n}\n\n// =============================================================================\n// Main Entry Point\n// =============================================================================\n\nexport async function runCreate(projectArg?: string, flags?: CreateFlags): Promise<void> {\n // Non-interactive mode: use --yes flag or non-TTY environment\n if (flags?.yes || !isInteractive()) {\n const options = getDefaults(projectArg);\n // Override defaults with any provided flags\n if (flags?.target) options.deploymentTarget = flags.target;\n if (flags?.redis) options.redisSetup = flags.redis;\n if (flags?.cicd !== undefined) options.enableGitHubActions = flags.cicd;\n if (projectArg) options.projectName = projectArg;\n\n if (!options.projectName) {\n console.error(c('red', 'Error: project name is required in non-interactive mode.\\n'));\n console.log(`Usage: ${c('bold', 'npx frontmcp create <project-name> --yes')}`);\n process.exit(1);\n }\n\n await scaffoldProject(options);\n return;\n }\n\n // Interactive mode\n console.log(`\\n${c('bold', 'Create a new FrontMCP project')}\\n`);\n\n const prompt = createPrompt();\n try {\n const options = await collectOptions(prompt, projectArg, flags);\n await scaffoldProject(options);\n } catch (err) {\n if (err instanceof Error && err.message === 'Project name is required') {\n console.error(c('red', '\\nError: Project name is required.'));\n process.exit(1);\n }\n throw err;\n } finally {\n prompt.close();\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"create.js","sourceRoot":"","sources":["../../../src/commands/create.ts"],"names":[],"mappings":"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","sourcesContent":["import * as path from 'path';\nimport * as readline from 'readline';\nimport { promises as fsp } from 'fs';\nimport { c } from '../colors';\nimport { ensureDir, fileExists, isDirEmpty, writeJSON, readJSON } from '@frontmcp/utils';\nimport { runInit } from '../tsconfig';\nimport { getSelfVersion } from '../version';\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport type DeploymentTarget = 'node' | 'vercel' | 'lambda' | 'cloudflare';\nexport type RedisSetup = 'docker' | 'existing' | 'none';\n\nexport interface CreateOptions {\n projectName: string;\n deploymentTarget: DeploymentTarget;\n redisSetup: RedisSetup;\n enableGitHubActions: boolean;\n}\n\nexport interface CreateFlags {\n yes?: boolean;\n target?: DeploymentTarget;\n redis?: RedisSetup;\n cicd?: boolean;\n}\n\ninterface PackageJson {\n name?: string;\n version?: string;\n private?: boolean;\n type?: string;\n main?: string;\n scripts?: Record<string, string>;\n engines?: { node?: string; npm?: string };\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n [key: string]: unknown;\n}\n\n// =============================================================================\n// Interactive Prompt Utility\n// =============================================================================\n\ninterface PromptOption<T> {\n label: string;\n value: T;\n}\n\nfunction createPrompt() {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n return {\n ask: (question: string): Promise<string> =>\n new Promise((resolve) => rl.question(question, (ans) => resolve(ans.trim()))),\n\n select: async <T extends string>(question: string, options: PromptOption<T>[], defaultIndex = 0): Promise<T> => {\n console.log(question);\n options.forEach((opt, i) => {\n const marker = i === defaultIndex ? c('green', '●') : c('gray', '○');\n console.log(` ${marker} ${c('cyan', `${i + 1})`)} ${opt.label}`);\n });\n const answer = await new Promise<string>((resolve) =>\n rl.question(`${c('gray', `Select [1-${options.length}]:`)} `, resolve),\n );\n const idx = parseInt(answer.trim(), 10) - 1;\n if (!isNaN(idx) && idx >= 0 && idx < options.length) return options[idx].value;\n return options[defaultIndex].value;\n },\n\n confirm: async (question: string, defaultValue = true): Promise<boolean> => {\n const hint = defaultValue ? '[Y/n]' : '[y/N]';\n const answer = await new Promise<string>((resolve) => rl.question(`${question} ${c('gray', hint)} `, resolve));\n if (!answer.trim()) return defaultValue;\n return answer.trim().toLowerCase().startsWith('y');\n },\n\n close: () => rl.close(),\n };\n}\n\nfunction isInteractive(): boolean {\n return process.stdin.isTTY === true;\n}\n\nfunction sanitizeForFolder(name: string): string {\n const seg = name.startsWith('@') && name.includes('/') ? name.split('/')[1] : name;\n return (\n seg\n .replace(/[^a-zA-Z0-9._-]/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '')\n .toLowerCase() || 'frontmcp-app'\n );\n}\n\nfunction sanitizeForNpm(name: string): string {\n if (name.startsWith('@') && name.includes('/')) {\n const [scope, pkg] = name.split('/');\n const s = scope.replace(/[^a-z0-9-]/gi, '').toLowerCase();\n const p = pkg.replace(/[^a-z0-9._-]/gi, '-').toLowerCase();\n return `@${s}/${p || 'frontmcp-app'}`;\n }\n return name.replace(/[^a-z0-9._-]/gi, '-').toLowerCase() || 'frontmcp-app';\n}\n\nfunction pkgNameFromCwd(cwd: string) {\n return (\n path\n .basename(cwd)\n .replace(/[^a-zA-Z0-9._-]/g, '-')\n .toLowerCase() || 'frontmcp-app'\n );\n}\n\nasync function scaffoldFileIfMissing(baseDir: string, p: string, content: string) {\n if (await fileExists(p)) {\n console.log(c('gray', `skip: ${path.relative(baseDir, p)} already exists`));\n return;\n }\n await ensureDir(path.dirname(p));\n await fsp.writeFile(p, content.replace(/^\\n/, ''), 'utf8');\n console.log(c('green', `✓ created ${path.relative(baseDir, p)}`));\n}\n\nconst TEMPLATE_MAIN_TS = `\nimport 'reflect-metadata';\nimport { FrontMcp } from '@frontmcp/sdk';\nimport { CalcApp } from './calc.app';\n\n@FrontMcp({\n info: { name: 'Demo 🚀', version: '0.1.0' },\n apps: [CalcApp],\n})\nexport default class Server {}\n`;\n\nconst TEMPLATE_CALC_APP_TS = `\nimport { App } from '@frontmcp/sdk';\nimport AddTool from './tools/add.tool';\n\n@App({\n id: 'calc',\n name: 'Calculator',\n tools: [AddTool],\n})\nexport class CalcApp {}\n`;\n\nconst TEMPLATE_ADD_TOOL_TS = `\nimport {Tool, ToolContext} from \"@frontmcp/sdk\";\nimport {z} from \"zod\";\n\n@Tool({\n name: 'add',\n description: 'Add two numbers',\n inputSchema: {a: z.number(), b: z.number()},\n outputSchema: {result: z.number()}\n})\nexport default class AddTool extends ToolContext {\n async execute(input: { a: number, b: number }) {\n return {\n result: input.a + input.b,\n };\n }\n}\n`;\n\nconst TEMPLATE_E2E_TEST_TS = `\nimport { test, expect } from '@frontmcp/testing';\n\ntest.describe('Server E2E', () => {\n test.use({\n server: './src/main.ts',\n port: 3100,\n });\n\n test('should connect and initialize', async ({ mcp }) => {\n expect(mcp.isConnected()).toBe(true);\n expect(mcp.serverInfo.name).toBeDefined();\n });\n\n test('should list tools', async ({ mcp }) => {\n const tools = await mcp.tools.list();\n expect(tools.length).toBeGreaterThanOrEqual(0);\n });\n\n test('should call add tool', async ({ mcp }) => {\n const result = await mcp.tools.call('add', { a: 2, b: 3 });\n expect(result).toBeSuccessful();\n });\n});\n`;\n\nconst TEMPLATE_GITIGNORE = `\n# Dependencies\nnode_modules/\n\n# Build output\ndist/\n*.tsbuildinfo\n\n# IDE\n.idea/\n.vscode/\n*.swp\n*.swo\n\n# OS files\n.DS_Store\nThumbs.db\n\n# Logs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n# Environment variables\n.env\n.env.local\n.env.*.local\n\n# FrontMCP development keys (contains private keys - never commit!)\n.frontmcp/\n\n# Coverage\ncoverage/\n\n# Test output\ntest-output/\n`;\n\nconst TEMPLATE_JEST_E2E_CONFIG = `\n/* eslint-disable */\nexport default {\n displayName: 'e2e',\n testEnvironment: 'node',\n testMatch: ['<rootDir>/e2e/**/*.e2e.test.ts'],\n testTimeout: 60000,\n setupFilesAfterEnv: ['@frontmcp/testing/setup'],\n transform: {\n '^.+\\\\\\\\.[tj]s$': [\n '@swc/jest',\n {\n jsc: {\n target: 'es2022',\n parser: {\n syntax: 'typescript',\n decorators: true,\n dynamicImport: true,\n },\n transform: {\n decoratorMetadata: true,\n legacyDecorator: true,\n },\n keepClassNames: true,\n externalHelpers: true,\n loose: true,\n },\n module: {\n type: 'es6',\n },\n sourceMaps: true,\n swcrc: false,\n },\n ],\n },\n moduleFileExtensions: ['ts', 'js', 'html'],\n transformIgnorePatterns: ['node_modules/(?!(jose)/)'],\n};\n`;\n\nconst TEMPLATE_TSCONFIG_E2E = `\n{\n \"extends\": \"./tsconfig.json\",\n \"compilerOptions\": {\n \"types\": [\"node\", \"jest\"]\n },\n \"include\": [\"e2e/**/*.ts\", \"jest.e2e.config.ts\"]\n}\n`;\n\nconst TEMPLATE_DOCKER_COMPOSE = `\nversion: '3.8'\n\nservices:\n redis:\n image: redis:7-alpine\n ports:\n - '6379:6379'\n volumes:\n - redis-data:/data\n command: redis-server --appendonly yes\n healthcheck:\n test: ['CMD', 'redis-cli', 'ping']\n interval: 10s\n timeout: 5s\n retries: 3\n\n app:\n build:\n context: .\n dockerfile: Dockerfile\n ports:\n - '\\${PORT:-3000}:3000'\n environment:\n - NODE_ENV=\\${NODE_ENV:-development}\n - REDIS_HOST=redis\n - REDIS_PORT=6379\n depends_on:\n redis:\n condition: service_healthy\n volumes:\n - ./src:/app/src\n command: npm run dev\n\nvolumes:\n redis-data:\n`;\n\nconst TEMPLATE_DOCKERFILE = `\n# Build stage\nFROM node:22-alpine AS builder\n\nWORKDIR /app\n\n# Install all dependencies (including devDependencies for build)\nCOPY package*.json ./\nRUN npm ci\n\n# Copy source and build\nCOPY . .\nRUN npm run build\n\n# Production stage\nFROM node:22-alpine AS runner\n\nWORKDIR /app\nENV NODE_ENV=production\n\n# Install production dependencies only\nCOPY package*.json ./\nRUN npm ci --omit=dev\n\n# Copy built artifacts from builder\nCOPY --from=builder /app/dist ./dist\n\nEXPOSE 3000\n\nCMD [\"node\", \"dist/main.js\"]\n`;\n\nconst TEMPLATE_ENV_EXAMPLE = `\n# Application\nPORT=3000\nNODE_ENV=development\n\n# Redis (recommended for development, required for production)\nREDIS_HOST=localhost\nREDIS_PORT=6379\n# SECURITY: Set a strong password in production\nREDIS_PASSWORD=\nREDIS_DB=0\n\n# Optional: Redis TLS (enable for production)\nREDIS_TLS=false\n`;\n\nconst TEMPLATE_ENV_DOCKER = `\n# Docker-specific environment\n# Copy this to .env when running with docker compose\n\n# Application\nPORT=3000\nNODE_ENV=development\n\n# Redis - use 'redis' (service name) as host inside Docker network\nREDIS_HOST=redis\nREDIS_PORT=6379\n# SECURITY: Set a strong password in production\nREDIS_PASSWORD=\nREDIS_DB=0\nREDIS_TLS=false\n`;\n\nconst TEMPLATE_README = `\n# FrontMCP Server\n\nA TypeScript MCP server built with [FrontMCP](https://github.com/agentfront/frontmcp).\n\n## Quick Start\n\n\\`\\`\\`bash\n# Install dependencies\nnpm install\n\n# Start development server\nnpm run dev\n\n# Run MCP Inspector\nnpm run inspect\n\\`\\`\\`\n\n## Development with Docker\n\n### Prerequisites\n- Docker & Docker Compose installed\n\n### Quick Start\n\n\\`\\`\\`bash\n# Start Redis and app in development mode\ndocker compose up\n\n# Start only Redis (for local development)\ndocker compose up redis -d\n\n# Stop all services\ndocker compose down\n\\`\\`\\`\n\n### Environment Variables\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| \\`PORT\\` | 3000 | Application port |\n| \\`NODE_ENV\\` | development | Environment mode |\n| \\`REDIS_HOST\\` | localhost | Redis host (use \\`redis\\` in Docker) |\n| \\`REDIS_PORT\\` | 6379 | Redis port |\n\n## Redis Configuration\n\n### Development\nRedis is **recommended** for development to enable caching and session persistence.\nUse the included \\`docker-compose.yml\\` to run Redis locally:\n\n\\`\\`\\`bash\ndocker compose up redis -d\n\\`\\`\\`\n\n### Production\nRedis is **required** in production for:\n- Session storage (multi-instance deployments)\n- Caching (performance optimization)\n- Rate limiting (if enabled)\n\nSee the [Redis Setup Guide](https://docs.agentfront.dev/docs/deployment/redis-setup) for production configuration.\n\n## Scripts\n\n| Script | Description |\n|--------|-------------|\n| \\`npm run dev\\` | Start development server with hot reload |\n| \\`npm run build\\` | Build for production |\n| \\`npm run inspect\\` | Launch MCP Inspector |\n| \\`npm run doctor\\` | Check project configuration |\n| \\`npm run test\\` | Run unit tests |\n| \\`npm run test:e2e\\` | Run E2E tests |\n\n## Project Structure\n\n\\`\\`\\`\n├── .env.example # Environment variables template\n├── .gitignore # Git ignore rules\n├── docker-compose.yml # Docker services config\n├── Dockerfile # Container build config\n├── e2e/ # E2E tests\n├── jest.e2e.config.ts # Jest E2E configuration\n├── package.json # Dependencies and scripts\n├── src/\n│ ├── main.ts # Server entry point\n│ ├── calc.app.ts # Example app\n│ └── tools/\n│ └── add.tool.ts # Example tool\n├── tsconfig.json # TypeScript config\n└── tsconfig.e2e.json # TypeScript config for E2E tests\n\\`\\`\\`\n\n## Learn More\n\n- [FrontMCP Documentation](https://docs.agentfront.dev)\n- [MCP Specification](https://modelcontextprotocol.io)\n`;\n\n// =============================================================================\n// Deployment Target Templates\n// =============================================================================\n\n// Docker templates (moved to ci/ folder)\nconst TEMPLATE_DOCKERFILE_CI = `\n# Build stage\nFROM node:22-alpine AS builder\n\nWORKDIR /app\n\n# Install all dependencies (including devDependencies for build)\nCOPY package*.json ./\nRUN npm ci\n\n# Copy source and build\nCOPY . .\nRUN npm run build\n\n# Production stage\nFROM node:22-alpine AS runner\n\nWORKDIR /app\nENV NODE_ENV=production\n\n# Install production dependencies only\nCOPY package*.json ./\nRUN npm ci --omit=dev\n\n# Copy built artifacts from builder\nCOPY --from=builder /app/dist ./dist\n\nEXPOSE 3000\n\nCMD [\"node\", \"dist/main.js\"]\n`;\n\nconst TEMPLATE_DOCKER_COMPOSE_WITH_REDIS = `\nversion: '3.8'\n\nservices:\n redis:\n image: redis:7-alpine\n ports:\n - '6379:6379'\n volumes:\n - redis-data:/data\n command: redis-server --appendonly yes\n healthcheck:\n test: ['CMD', 'redis-cli', 'ping']\n interval: 10s\n timeout: 5s\n retries: 3\n\n app:\n build:\n context: .\n dockerfile: ci/Dockerfile\n ports:\n - '\\${PORT:-3000}:3000'\n environment:\n - NODE_ENV=\\${NODE_ENV:-development}\n - REDIS_HOST=redis\n - REDIS_PORT=6379\n depends_on:\n redis:\n condition: service_healthy\n volumes:\n - ./src:/app/src\n command: npm run dev\n\nvolumes:\n redis-data:\n`;\n\nconst TEMPLATE_DOCKER_COMPOSE_NO_REDIS = `\nversion: '3.8'\n\nservices:\n app:\n build:\n context: .\n dockerfile: ci/Dockerfile\n ports:\n - '\\${PORT:-3000}:3000'\n environment:\n - NODE_ENV=\\${NODE_ENV:-development}\n volumes:\n - ./src:/app/src\n command: npm run dev\n`;\n\nconst TEMPLATE_ENV_DOCKER_CI = `\n# Docker-specific environment\n# Use with: docker compose -f ci/docker-compose.yml --env-file ci/.env.docker up\n\n# Application\nPORT=3000\nNODE_ENV=development\n\n# Redis - use 'redis' (service name) as host inside Docker network\nREDIS_HOST=redis\nREDIS_PORT=6379\n# SECURITY: Set a strong password in production\nREDIS_PASSWORD=\nREDIS_DB=0\nREDIS_TLS=false\n`;\n\n// Vercel template\nconst TEMPLATE_VERCEL_JSON = (projectName: string) =>\n JSON.stringify(\n {\n $schema: 'https://openapi.vercel.sh/vercel.json',\n name: projectName,\n version: 2,\n builds: [\n {\n src: 'dist/main.js',\n use: '@vercel/node',\n },\n ],\n routes: [\n {\n src: '/(.*)',\n dest: '/dist/main.js',\n },\n ],\n env: {\n NODE_ENV: 'production',\n },\n },\n null,\n 2,\n );\n\n// AWS Lambda SAM template\nconst TEMPLATE_SAM_YAML = (projectName: string) => `\nAWSTemplateFormatVersion: '2010-09-09'\nTransform: AWS::Serverless-2016-10-31\nDescription: ${projectName} - FrontMCP Lambda Function\n\nGlobals:\n Function:\n Timeout: 30\n Runtime: nodejs22.x\n MemorySize: 256\n\nResources:\n FrontMCPFunction:\n Type: AWS::Serverless::Function\n Properties:\n CodeUri: ../dist/\n Handler: main.handler\n Events:\n ApiEvent:\n Type: HttpApi\n Properties:\n Path: /{proxy+}\n Method: ANY\n\nOutputs:\n ApiEndpoint:\n Description: API Gateway endpoint URL\n Value: !Sub \"https://\\${ServerlessHttpApi}.execute-api.\\${AWS::Region}.amazonaws.com\"\n`;\n\n// Cloudflare Workers template\nconst TEMPLATE_WRANGLER_TOML = (projectName: string) => `\nname = \"${projectName}\"\nmain = \"dist/main.js\"\ncompatibility_date = \"2024-01-01\"\n\n[vars]\nNODE_ENV = \"production\"\n\n# Uncomment to enable KV namespace for caching\n# [[kv_namespaces]]\n# binding = \"CACHE\"\n# id = \"your-kv-namespace-id\"\n`;\n\n// =============================================================================\n// GitHub Actions Templates\n// =============================================================================\n\nconst TEMPLATE_GH_CI = `\nname: CI\n\non:\n push:\n branches: [main]\n pull_request:\n branches: [main]\n\njobs:\n lint-and-test:\n runs-on: ubuntu-latest\n\n steps:\n - uses: actions/checkout@v4\n\n - name: Setup Node.js\n uses: actions/setup-node@v4\n with:\n node-version: '22'\n cache: 'npm'\n\n - name: Install dependencies\n run: npm ci\n\n - name: Type check\n run: npx tsc --noEmit\n\n - name: Run tests\n run: npm test\n`;\n\nconst TEMPLATE_GH_E2E = `\nname: E2E Tests\n\non:\n push:\n branches: [main]\n pull_request:\n branches: [main]\n\njobs:\n e2e:\n runs-on: ubuntu-latest\n\n steps:\n - uses: actions/checkout@v4\n\n - name: Setup Node.js\n uses: actions/setup-node@v4\n with:\n node-version: '22'\n cache: 'npm'\n\n - name: Install dependencies\n run: npm ci\n\n - name: Build\n run: npm run build\n\n - name: Run E2E tests\n run: npm run test:e2e\n`;\n\nconst TEMPLATE_GH_DEPLOY_DOCKER = `\nname: Build and Push Docker Image\n\non:\n push:\n branches: [main]\n tags: ['v*']\n\nenv:\n REGISTRY: ghcr.io\n IMAGE_NAME: \\${{ github.repository }}\n\njobs:\n build-and-push:\n runs-on: ubuntu-latest\n permissions:\n contents: read\n packages: write\n\n steps:\n - uses: actions/checkout@v4\n\n - name: Log in to Container Registry\n uses: docker/login-action@v3\n with:\n registry: \\${{ env.REGISTRY }}\n username: \\${{ github.actor }}\n password: \\${{ secrets.GITHUB_TOKEN }}\n\n - name: Extract metadata\n id: meta\n uses: docker/metadata-action@v5\n with:\n images: \\${{ env.REGISTRY }}/\\${{ env.IMAGE_NAME }}\n\n - name: Build and push\n uses: docker/build-push-action@v5\n with:\n context: .\n file: ./ci/Dockerfile\n push: true\n tags: \\${{ steps.meta.outputs.tags }}\n labels: \\${{ steps.meta.outputs.labels }}\n`;\n\nconst TEMPLATE_GH_DEPLOY_VERCEL = `\nname: Deploy to Vercel\n\non:\n push:\n branches: [main]\n\njobs:\n deploy:\n runs-on: ubuntu-latest\n\n steps:\n - uses: actions/checkout@v4\n\n - name: Setup Node.js\n uses: actions/setup-node@v4\n with:\n node-version: '22'\n cache: 'npm'\n\n - name: Install dependencies\n run: npm ci\n\n - name: Build\n run: npm run build\n\n - name: Deploy to Vercel\n uses: amondnet/vercel-action@v25\n with:\n vercel-token: \\${{ secrets.VERCEL_TOKEN }}\n vercel-org-id: \\${{ secrets.VERCEL_ORG_ID }}\n vercel-project-id: \\${{ secrets.VERCEL_PROJECT_ID }}\n vercel-args: '--prod'\n`;\n\nconst TEMPLATE_GH_DEPLOY_LAMBDA = `\nname: Deploy to AWS Lambda\n\non:\n push:\n branches: [main]\n\njobs:\n deploy:\n runs-on: ubuntu-latest\n\n steps:\n - uses: actions/checkout@v4\n\n - name: Setup Node.js\n uses: actions/setup-node@v4\n with:\n node-version: '22'\n cache: 'npm'\n\n - name: Install dependencies\n run: npm ci\n\n - name: Build\n run: npm run build\n\n - name: Configure AWS credentials\n uses: aws-actions/configure-aws-credentials@v4\n with:\n aws-access-key-id: \\${{ secrets.AWS_ACCESS_KEY_ID }}\n aws-secret-access-key: \\${{ secrets.AWS_SECRET_ACCESS_KEY }}\n aws-region: \\${{ secrets.AWS_REGION }}\n\n - name: Setup SAM\n uses: aws-actions/setup-sam@v2\n\n - name: Deploy with SAM\n run: |\n cd ci\n sam build\n sam deploy --no-confirm-changeset --no-fail-on-empty-changeset\n`;\n\nconst TEMPLATE_GH_DEPLOY_CLOUDFLARE = `\nname: Deploy to Cloudflare Workers\n\non:\n push:\n branches: [main]\n\njobs:\n deploy:\n runs-on: ubuntu-latest\n\n steps:\n - uses: actions/checkout@v4\n\n - name: Setup Node.js\n uses: actions/setup-node@v4\n with:\n node-version: '22'\n cache: 'npm'\n\n - name: Install dependencies\n run: npm ci\n\n - name: Build\n run: npm run build\n\n - name: Deploy to Cloudflare\n uses: cloudflare/wrangler-action@v3\n with:\n apiToken: \\${{ secrets.CLOUDFLARE_API_TOKEN }}\n`;\n\n// =============================================================================\n// Dynamic README Templates\n// =============================================================================\n\nfunction generateReadme(options: CreateOptions): string {\n const { projectName, deploymentTarget, redisSetup, enableGitHubActions } = options;\n\n let readme = `# ${projectName}\n\nA TypeScript MCP server built with [FrontMCP](https://github.com/agentfront/frontmcp).\n`;\n\n // Add CI badge if GitHub Actions enabled\n if (enableGitHubActions) {\n readme += `\n\n`;\n }\n\n readme += `\n## Quick Start\n\n\\`\\`\\`bash\n# Install dependencies\nnpm install\n\n# Start development server\nnpm run dev\n\n# Run MCP Inspector\nnpm run inspect\n\\`\\`\\`\n`;\n\n // Deployment-specific sections\n if (deploymentTarget === 'node') {\n readme += `\n## Docker Development\n\n\\`\\`\\`bash\n# Start all services${redisSetup === 'docker' ? ' (includes Redis)' : ''}\nnpm run docker:up\n\n# Stop all services\nnpm run docker:down\n\n# Rebuild Docker image\nnpm run docker:build\n\\`\\`\\`\n`;\n\n if (redisSetup === 'docker') {\n readme += `\n### Redis\n\nRedis is included in the Docker Compose setup. For local development without Docker:\n\n\\`\\`\\`bash\n# Start only Redis\ndocker compose -f ci/docker-compose.yml up redis -d\n\\`\\`\\`\n`;\n }\n\n readme += `\n## Production Deployment\n\nBuild and push the Docker image:\n\n\\`\\`\\`bash\ndocker build -f ci/Dockerfile -t ${projectName}:latest .\ndocker push your-registry/${projectName}:latest\n\\`\\`\\`\n`;\n }\n\n if (deploymentTarget === 'vercel') {\n readme += `\n## Deploy to Vercel\n\n\\`\\`\\`bash\n# Build for production\nnpm run build\n\n# Deploy using Vercel CLI\nnpx vercel --prod\n\\`\\`\\`\n\nOr connect your repository to Vercel for automatic deployments.\n`;\n }\n\n if (deploymentTarget === 'lambda') {\n readme += `\n## Deploy to AWS Lambda\n\n\\`\\`\\`bash\n# Build the project\nnpm run build\n\n# Deploy using AWS SAM\nnpm run deploy\n\\`\\`\\`\n\n### Prerequisites\n\n- AWS CLI configured with appropriate credentials\n- AWS SAM CLI installed (\\`brew install aws-sam-cli\\` or \\`pip install aws-sam-cli\\`)\n`;\n }\n\n if (deploymentTarget === 'cloudflare') {\n readme += `\n## Deploy to Cloudflare Workers\n\n\\`\\`\\`bash\n# Build the project\nnpm run build\n\n# Deploy using Wrangler\nnpm run deploy\n\\`\\`\\`\n\n### Prerequisites\n\n- Wrangler CLI installed (\\`npm install -g wrangler\\`)\n- Cloudflare account configured (\\`wrangler login\\`)\n`;\n }\n\n // Environment variables section\n readme += `\n## Environment Variables\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| \\`PORT\\` | 3000 | Application port |\n| \\`NODE_ENV\\` | development | Environment mode |\n`;\n\n if (deploymentTarget === 'node' && redisSetup !== 'none') {\n readme += `| \\`REDIS_HOST\\` | localhost | Redis host (use \\`redis\\` in Docker) |\n| \\`REDIS_PORT\\` | 6379 | Redis port |\n| \\`REDIS_PASSWORD\\` | - | Redis password (set in production) |\n`;\n }\n\n // GitHub Actions section\n if (enableGitHubActions) {\n readme += `\n## CI/CD\n\nThis project includes GitHub Actions workflows:\n\n- **ci.yml**: Runs on every push/PR - type checking and tests\n- **e2e.yml**: Runs E2E tests\n- **deploy.yml**: Deploys to ${\n deploymentTarget === 'node'\n ? 'GitHub Container Registry'\n : deploymentTarget === 'vercel'\n ? 'Vercel'\n : deploymentTarget === 'lambda'\n ? 'AWS Lambda'\n : 'Cloudflare Workers'\n }\n\n### Required Secrets\n`;\n\n if (deploymentTarget === 'vercel') {\n readme += `\n- \\`VERCEL_TOKEN\\`: Vercel API token\n- \\`VERCEL_ORG_ID\\`: Vercel organization ID\n- \\`VERCEL_PROJECT_ID\\`: Vercel project ID\n`;\n } else if (deploymentTarget === 'lambda') {\n readme += `\n- \\`AWS_ACCESS_KEY_ID\\`: AWS access key\n- \\`AWS_SECRET_ACCESS_KEY\\`: AWS secret key\n- \\`AWS_REGION\\`: AWS region (e.g., us-east-1)\n`;\n } else if (deploymentTarget === 'cloudflare') {\n readme += `\n- \\`CLOUDFLARE_API_TOKEN\\`: Cloudflare API token with Workers permissions\n`;\n } else {\n readme += `\nNo additional secrets required - uses \\`GITHUB_TOKEN\\` for GHCR.\n`;\n }\n }\n\n readme += `\n## Scripts\n\n| Script | Description |\n|--------|-------------|\n| \\`npm run dev\\` | Start development server with hot reload |\n| \\`npm run build\\` | Build for production |\n| \\`npm run inspect\\` | Launch MCP Inspector |\n| \\`npm run doctor\\` | Check project configuration |\n| \\`npm run test\\` | Run unit tests |\n| \\`npm run test:e2e\\` | Run E2E tests |\n`;\n\n if (deploymentTarget === 'node') {\n readme += `| \\`npm run docker:up\\` | Start Docker services |\n| \\`npm run docker:down\\` | Stop Docker services |\n| \\`npm run docker:build\\` | Rebuild Docker image |\n`;\n }\n\n if (deploymentTarget === 'lambda' || deploymentTarget === 'cloudflare') {\n readme += `| \\`npm run deploy\\` | Deploy to ${deploymentTarget === 'lambda' ? 'AWS Lambda' : 'Cloudflare Workers'} |\n`;\n }\n\n readme += `\n## Project Structure\n\n\\`\\`\\`\n`;\n\n // Dynamic project structure based on options\n readme += `├── .env.example # Environment variables template\n├── .gitignore # Git ignore rules\n`;\n\n if (deploymentTarget === 'node') {\n readme += `├── ci/\n│ ├── Dockerfile # Container build config\n│ ├── docker-compose.yml # Docker services config\n│ └── .env.docker # Docker-specific env vars\n`;\n }\n\n if (deploymentTarget === 'vercel') {\n readme += `├── vercel.json # Vercel deployment config\n`;\n }\n\n if (deploymentTarget === 'lambda') {\n readme += `├── ci/\n│ └── template.yaml # AWS SAM template\n`;\n }\n\n if (deploymentTarget === 'cloudflare') {\n readme += `├── wrangler.toml # Cloudflare Workers config\n`;\n }\n\n if (enableGitHubActions) {\n readme += `├── .github/workflows/\n│ ├── ci.yml # CI workflow\n│ ├── e2e.yml # E2E test workflow\n│ └── deploy.yml # Deployment workflow\n`;\n }\n\n readme += `├── e2e/ # E2E tests\n├── jest.e2e.config.ts # Jest E2E configuration\n├── package.json # Dependencies and scripts\n├── src/\n│ ├── main.ts # Server entry point\n│ ├── calc.app.ts # Example app\n│ └── tools/\n│ └── add.tool.ts # Example tool\n├── tsconfig.json # TypeScript config\n└── tsconfig.e2e.json # TypeScript config for E2E tests\n\\`\\`\\`\n\n## Learn More\n\n- [FrontMCP Documentation](https://docs.agentfront.dev)\n- [MCP Specification](https://modelcontextprotocol.io)\n`;\n\n return readme;\n}\n\n// =============================================================================\n// Scaffolding Functions\n// =============================================================================\n\nfunction getDefaults(projectArg?: string): CreateOptions {\n return {\n projectName: projectArg || 'frontmcp-app',\n deploymentTarget: 'node',\n redisSetup: 'docker',\n enableGitHubActions: true,\n };\n}\n\nasync function collectOptions(\n prompt: ReturnType<typeof createPrompt>,\n projectArg?: string,\n flags?: CreateFlags,\n): Promise<CreateOptions> {\n // Project name\n let projectName = projectArg;\n if (!projectName) {\n projectName = await prompt.ask(`${c('cyan', '?')} Project name: `);\n if (!projectName) {\n throw new Error('Project name is required');\n }\n } else {\n console.log(`${c('cyan', '?')} Project name: ${c('bold', projectName)}`);\n }\n\n // Deployment target\n const deploymentTarget =\n flags?.target ||\n (await prompt.select<DeploymentTarget>(`\\n${c('cyan', '?')} Select deployment target:`, [\n { label: 'Node.js (Docker) - Recommended for production', value: 'node' },\n { label: 'Vercel (Serverless)', value: 'vercel' },\n { label: 'AWS Lambda', value: 'lambda' },\n { label: 'Cloudflare Workers', value: 'cloudflare' },\n ]));\n\n // Redis setup (only for Node.js/Docker)\n let redisSetup: RedisSetup = 'none';\n if (deploymentTarget === 'node') {\n redisSetup =\n flags?.redis ||\n (await prompt.select<RedisSetup>(`\\n${c('cyan', '?')} Redis setup:`, [\n { label: 'Docker Compose (recommended for development)', value: 'docker' },\n { label: 'Existing Redis (I have my own Redis)', value: 'existing' },\n { label: 'None (skip Redis)', value: 'none' },\n ]));\n }\n\n // GitHub Actions\n const enableGitHubActions =\n flags?.cicd ?? (await prompt.confirm(`\\n${c('cyan', '?')} Set up GitHub Actions CI/CD?`, true));\n\n return {\n projectName,\n deploymentTarget,\n redisSetup,\n enableGitHubActions,\n };\n}\n\nasync function scaffoldDeploymentFiles(targetDir: string, options: CreateOptions): Promise<void> {\n const { deploymentTarget, redisSetup, projectName } = options;\n\n switch (deploymentTarget) {\n case 'node': {\n const ciDir = path.join(targetDir, 'ci');\n await ensureDir(ciDir);\n await scaffoldFileIfMissing(targetDir, path.join(ciDir, 'Dockerfile'), TEMPLATE_DOCKERFILE_CI);\n\n const dockerCompose =\n redisSetup === 'docker' ? TEMPLATE_DOCKER_COMPOSE_WITH_REDIS : TEMPLATE_DOCKER_COMPOSE_NO_REDIS;\n await scaffoldFileIfMissing(targetDir, path.join(ciDir, 'docker-compose.yml'), dockerCompose);\n await scaffoldFileIfMissing(targetDir, path.join(ciDir, '.env.docker'), TEMPLATE_ENV_DOCKER_CI);\n break;\n }\n\n case 'vercel':\n await scaffoldFileIfMissing(\n targetDir,\n path.join(targetDir, 'vercel.json'),\n TEMPLATE_VERCEL_JSON(sanitizeForFolder(projectName)),\n );\n break;\n\n case 'lambda': {\n const ciDir = path.join(targetDir, 'ci');\n await ensureDir(ciDir);\n await scaffoldFileIfMissing(targetDir, path.join(ciDir, 'template.yaml'), TEMPLATE_SAM_YAML(projectName));\n break;\n }\n\n case 'cloudflare':\n await scaffoldFileIfMissing(\n targetDir,\n path.join(targetDir, 'wrangler.toml'),\n TEMPLATE_WRANGLER_TOML(sanitizeForFolder(projectName)),\n );\n break;\n }\n\n // Always create .env.example at root\n const envExample =\n deploymentTarget === 'node' && redisSetup !== 'none' ? TEMPLATE_ENV_EXAMPLE : TEMPLATE_ENV_EXAMPLE_BASIC;\n await scaffoldFileIfMissing(targetDir, path.join(targetDir, '.env.example'), envExample);\n}\n\n// Basic .env.example without Redis\nconst TEMPLATE_ENV_EXAMPLE_BASIC = `\n# Application\nPORT=3000\nNODE_ENV=development\n`;\n\nasync function scaffoldGitHubActions(targetDir: string, deploymentTarget: DeploymentTarget): Promise<void> {\n const workflowDir = path.join(targetDir, '.github', 'workflows');\n await ensureDir(workflowDir);\n\n // Always create CI and E2E workflows\n await scaffoldFileIfMissing(targetDir, path.join(workflowDir, 'ci.yml'), TEMPLATE_GH_CI);\n await scaffoldFileIfMissing(targetDir, path.join(workflowDir, 'e2e.yml'), TEMPLATE_GH_E2E);\n\n // Create deployment workflow based on target\n const deployTemplate = getDeployWorkflowTemplate(deploymentTarget);\n await scaffoldFileIfMissing(targetDir, path.join(workflowDir, 'deploy.yml'), deployTemplate);\n}\n\nfunction getDeployWorkflowTemplate(target: DeploymentTarget): string {\n switch (target) {\n case 'node':\n return TEMPLATE_GH_DEPLOY_DOCKER;\n case 'vercel':\n return TEMPLATE_GH_DEPLOY_VERCEL;\n case 'lambda':\n return TEMPLATE_GH_DEPLOY_LAMBDA;\n case 'cloudflare':\n return TEMPLATE_GH_DEPLOY_CLOUDFLARE;\n }\n}\n\nasync function scaffoldProject(options: CreateOptions): Promise<void> {\n const { projectName, deploymentTarget, redisSetup, enableGitHubActions } = options;\n\n const folder = sanitizeForFolder(projectName);\n const pkgName = sanitizeForNpm(projectName);\n const targetDir = path.resolve(process.cwd(), folder);\n\n // Validate directory\n try {\n const stat = await fsp.stat(targetDir);\n if (!stat.isDirectory()) {\n console.error(\n c('red', `Refusing to scaffold into non-directory path: ${path.relative(process.cwd(), targetDir)}`),\n );\n console.log(c('gray', 'Pick a different project name or remove/rename the existing file.'));\n process.exit(1);\n }\n if (!(await isDirEmpty(targetDir))) {\n console.error(\n c('red', `Refusing to scaffold into non-empty directory: ${path.relative(process.cwd(), targetDir)}`),\n );\n console.log(c('gray', 'Pick a different name or start with an empty folder.'));\n process.exit(1);\n }\n } catch (e: unknown) {\n if (e && typeof e === 'object' && 'code' in e && e.code === 'ENOENT') {\n await ensureDir(targetDir);\n } else {\n throw e;\n }\n }\n\n console.log(`\\n${c('cyan', '[create]')} Creating project in ${c('bold', './' + folder)}`);\n console.log(c('gray', ` Deployment: ${deploymentTarget}`));\n if (deploymentTarget === 'node') {\n console.log(c('gray', ` Redis: ${redisSetup}`));\n }\n console.log(c('gray', ` GitHub Actions: ${enableGitHubActions ? 'Yes' : 'No'}`));\n console.log('');\n\n process.chdir(targetDir);\n\n // Initialize tsconfig\n await runInit(targetDir);\n\n // Create package.json with deployment-specific scripts\n const selfVersion = getSelfVersion();\n await upsertPackageJsonWithTarget(targetDir, pkgName, selfVersion, deploymentTarget);\n\n // Scaffold base files\n await scaffoldFileIfMissing(targetDir, path.join(targetDir, 'src', 'main.ts'), TEMPLATE_MAIN_TS);\n await scaffoldFileIfMissing(targetDir, path.join(targetDir, 'src', 'calc.app.ts'), TEMPLATE_CALC_APP_TS);\n await scaffoldFileIfMissing(targetDir, path.join(targetDir, 'src', 'tools', 'add.tool.ts'), TEMPLATE_ADD_TOOL_TS);\n\n // E2E scaffolding\n await scaffoldFileIfMissing(targetDir, path.join(targetDir, 'e2e', 'server.e2e.test.ts'), TEMPLATE_E2E_TEST_TS);\n await scaffoldFileIfMissing(targetDir, path.join(targetDir, 'jest.e2e.config.ts'), TEMPLATE_JEST_E2E_CONFIG);\n await scaffoldFileIfMissing(targetDir, path.join(targetDir, 'tsconfig.e2e.json'), TEMPLATE_TSCONFIG_E2E);\n\n // Git configuration\n await scaffoldFileIfMissing(targetDir, path.join(targetDir, '.gitignore'), TEMPLATE_GITIGNORE);\n\n // Deployment-specific files\n await scaffoldDeploymentFiles(targetDir, options);\n\n // GitHub Actions\n if (enableGitHubActions) {\n await scaffoldGitHubActions(targetDir, deploymentTarget);\n }\n\n // Dynamic README\n await scaffoldFileIfMissing(targetDir, path.join(targetDir, 'README.md'), generateReadme(options));\n\n // Print next steps\n printNextSteps(folder, deploymentTarget, redisSetup, enableGitHubActions);\n}\n\nfunction printNextSteps(\n folder: string,\n deploymentTarget: DeploymentTarget,\n redisSetup: RedisSetup,\n enableGitHubActions: boolean,\n): void {\n console.log('\\nNext steps:');\n console.log(` 1) cd ${folder}`);\n console.log(' 2) npm install');\n console.log(' 3) npm run dev ', c('gray', '# tsx watcher + async tsc type-check'));\n console.log(' 4) npm run inspect ', c('gray', '# launch MCP Inspector'));\n console.log(' 5) npm run build ', c('gray', '# compile with tsc via frontmcp build'));\n console.log(' 6) npm run test:e2e ', c('gray', '# run E2E tests'));\n\n if (deploymentTarget === 'node') {\n console.log('');\n console.log(c('cyan', 'Docker:'));\n console.log(\n ' npm run docker:up ',\n c('gray', `# start${redisSetup === 'docker' ? ' Redis +' : ''} app in Docker`),\n );\n console.log(' npm run docker:down ', c('gray', '# stop Docker services'));\n }\n\n if (deploymentTarget === 'vercel') {\n console.log('');\n console.log(c('cyan', 'Deploy to Vercel:'));\n console.log(' npx vercel ', c('gray', '# deploy to Vercel'));\n }\n\n if (deploymentTarget === 'lambda') {\n console.log('');\n console.log(c('cyan', 'Deploy to AWS Lambda:'));\n console.log(' npm run deploy ', c('gray', '# deploy with SAM'));\n }\n\n if (deploymentTarget === 'cloudflare') {\n console.log('');\n console.log(c('cyan', 'Deploy to Cloudflare:'));\n console.log(' npm run deploy ', c('gray', '# deploy with Wrangler'));\n }\n\n if (enableGitHubActions) {\n console.log('');\n console.log(c('cyan', 'GitHub Actions:'));\n console.log(' .github/workflows/ ', c('gray', '# CI, E2E, and deploy workflows ready'));\n }\n}\n\n// =============================================================================\n// Package.json with Target-Specific Scripts\n// =============================================================================\n\nasync function upsertPackageJsonWithTarget(\n cwd: string,\n nameOverride: string | undefined,\n selfVersion: string,\n deploymentTarget: DeploymentTarget,\n) {\n const pkgPath = path.join(cwd, 'package.json');\n const existing = await readJSON<PackageJson>(pkgPath);\n\n const frontmcpLibRange = `~${selfVersion}`;\n\n const baseScripts: Record<string, string> = {\n dev: 'frontmcp dev',\n build: 'frontmcp build',\n inspect: 'frontmcp inspector',\n doctor: 'frontmcp doctor',\n test: 'frontmcp test',\n 'test:e2e': 'jest --config jest.e2e.config.ts --runInBand',\n };\n\n // Add target-specific scripts\n if (deploymentTarget === 'node') {\n baseScripts['docker:up'] = 'docker compose -f ci/docker-compose.yml up';\n baseScripts['docker:down'] = 'docker compose -f ci/docker-compose.yml down';\n baseScripts['docker:build'] = 'docker compose -f ci/docker-compose.yml build';\n }\n\n if (deploymentTarget === 'lambda') {\n baseScripts['deploy'] = 'cd ci && sam build && sam deploy';\n }\n\n if (deploymentTarget === 'cloudflare') {\n baseScripts['deploy'] = 'wrangler deploy';\n }\n\n const base = {\n name: nameOverride ?? pkgNameFromCwd(cwd),\n version: '0.1.0',\n private: true,\n type: 'commonjs',\n main: 'src/main.ts',\n scripts: baseScripts,\n engines: {\n node: '>=22',\n npm: '>=10',\n },\n dependencies: {\n '@frontmcp/sdk': frontmcpLibRange,\n '@frontmcp/plugins': frontmcpLibRange,\n '@frontmcp/adapters': frontmcpLibRange,\n zod: '^4.0.0',\n 'reflect-metadata': '^0.2.2',\n },\n devDependencies: {\n frontmcp: selfVersion,\n '@frontmcp/testing': frontmcpLibRange,\n '@swc/core': '^1.11.29',\n '@swc/jest': '^0.2.37',\n jest: '^29.7.0',\n '@types/jest': '^29.5.14',\n tsx: '^4.20.6',\n '@types/node': '^24.0.0',\n typescript: '^5.5.3',\n },\n };\n\n if (!existing) {\n await writeJSON(pkgPath, base);\n console.log(c('green', '✅ Created package.json (synced @frontmcp libs to CLI version + exact frontmcp)'));\n return;\n }\n\n const merged: PackageJson = { ...base, ...existing };\n\n merged.name = existing.name || base.name;\n merged.main = existing.main || base.main;\n merged.type = existing.type || base.type;\n\n // Preserve user scripts, add base scripts only if missing\n merged.scripts = {\n ...baseScripts,\n ...(existing.scripts || {}),\n };\n\n merged.engines = {\n ...(existing.engines || {}),\n node: existing.engines?.node || base.engines.node,\n npm: existing.engines?.npm || base.engines.npm,\n };\n\n merged.dependencies = {\n ...(existing.dependencies || {}),\n ...base.dependencies,\n };\n\n merged.devDependencies = {\n ...(existing.devDependencies || {}),\n ...base.devDependencies,\n };\n\n await writeJSON(pkgPath, merged);\n console.log(c('green', '✅ Updated package.json (synced @frontmcp libs + frontmcp to current CLI version)'));\n}\n\n// =============================================================================\n// Main Entry Point\n// =============================================================================\n\nexport async function runCreate(projectArg?: string, flags?: CreateFlags): Promise<void> {\n // Non-interactive mode: use --yes flag or non-TTY environment\n if (flags?.yes || !isInteractive()) {\n const options = getDefaults(projectArg);\n // Override defaults with any provided flags\n if (flags?.target) options.deploymentTarget = flags.target;\n if (flags?.redis) options.redisSetup = flags.redis;\n if (flags?.cicd !== undefined) options.enableGitHubActions = flags.cicd;\n if (projectArg) options.projectName = projectArg;\n\n if (!options.projectName) {\n console.error(c('red', 'Error: project name is required in non-interactive mode.\\n'));\n console.log(`Usage: ${c('bold', 'npx frontmcp create <project-name> --yes')}`);\n process.exit(1);\n }\n\n await scaffoldProject(options);\n return;\n }\n\n // Interactive mode\n console.log(`\\n${c('bold', 'Create a new FrontMCP project')}\\n`);\n\n const prompt = createPrompt();\n try {\n const options = await collectOptions(prompt, projectArg, flags);\n await scaffoldProject(options);\n } catch (err) {\n if (err instanceof Error && err.message === 'Project name is required') {\n console.error(c('red', '\\nError: Project name is required.'));\n process.exit(1);\n }\n throw err;\n } finally {\n prompt.close();\n }\n}\n"]}
|
package/src/commands/doctor.js
CHANGED
|
@@ -5,9 +5,9 @@ const tslib_1 = require("tslib");
|
|
|
5
5
|
const path = tslib_1.__importStar(require("path"));
|
|
6
6
|
const child_process_1 = require("child_process");
|
|
7
7
|
const colors_1 = require("../colors");
|
|
8
|
-
const
|
|
8
|
+
const utils_1 = require("@frontmcp/utils");
|
|
9
9
|
const tsconfig_1 = require("../tsconfig");
|
|
10
|
-
const
|
|
10
|
+
const fs_1 = require("../utils/fs");
|
|
11
11
|
function cmpSemver(a, b) {
|
|
12
12
|
const pa = a.split('.').map((n) => parseInt(n, 10) || 0);
|
|
13
13
|
const pb = b.split('.').map((n) => parseInt(n, 10) || 0);
|
|
@@ -54,9 +54,9 @@ async function runDoctor() {
|
|
|
54
54
|
console.log('❌ npm not found in PATH');
|
|
55
55
|
}
|
|
56
56
|
const tsconfigPath = path.join(cwd, 'tsconfig.json');
|
|
57
|
-
if (await (0,
|
|
57
|
+
if (await (0, utils_1.fileExists)(tsconfigPath)) {
|
|
58
58
|
console.log(`✅ tsconfig.json found`);
|
|
59
|
-
const tsconfig = await (0,
|
|
59
|
+
const tsconfig = await (0, utils_1.readJSON)(tsconfigPath);
|
|
60
60
|
const { ok: oks, issues } = (0, tsconfig_1.checkRequiredTsOptions)(tsconfig?.compilerOptions);
|
|
61
61
|
for (const line of oks)
|
|
62
62
|
console.log((0, colors_1.c)('green', ` ✓ ${line}`));
|
|
@@ -72,7 +72,7 @@ async function runDoctor() {
|
|
|
72
72
|
console.log(`❌ tsconfig.json not found — run ${(0, colors_1.c)('cyan', 'frontmcp init')}`);
|
|
73
73
|
}
|
|
74
74
|
try {
|
|
75
|
-
const entry = await (0,
|
|
75
|
+
const entry = await (0, fs_1.resolveEntry)(cwd);
|
|
76
76
|
console.log(`✅ entry detected: ${path.relative(cwd, entry)}`);
|
|
77
77
|
}
|
|
78
78
|
catch (e) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../../src/commands/doctor.ts"],"names":[],"mappings":";;AAiBA,8BA6DC;;AA9ED,mDAA6B;AAC7B,iDAAsC;AACtC,sCAA8B;AAC9B,
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../../src/commands/doctor.ts"],"names":[],"mappings":"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","sourcesContent":["import * as path from 'path';\nimport { spawn } from 'child_process';\nimport { c } from '../colors';\nimport { fileExists, readJSON } from '@frontmcp/utils';\nimport { checkRequiredTsOptions } from '../tsconfig';\nimport { resolveEntry } from '../utils/fs';\n\nfunction cmpSemver(a: string, b: string): number {\n const pa = a.split('.').map((n) => parseInt(n, 10) || 0);\n const pb = b.split('.').map((n) => parseInt(n, 10) || 0);\n for (let i = 0; i < 3; i++) {\n if ((pa[i] || 0) > (pb[i] || 0)) return 1;\n if ((pa[i] || 0) < (pb[i] || 0)) return -1;\n }\n return 0;\n}\n\nexport async function runDoctor(): Promise<void> {\n const MIN_NODE = '22.0.0';\n const MIN_NPM = '10.0.0';\n const cwd = process.cwd();\n\n let ok = true;\n\n const nodeVer = process.versions.node;\n if (cmpSemver(nodeVer, MIN_NODE) >= 0) {\n console.log(`✅ Node ${nodeVer} (min ${MIN_NODE})`);\n } else {\n ok = false;\n console.log(`❌ Node ${nodeVer} — please upgrade to >= ${MIN_NODE}`);\n }\n\n let npmVer = 'unknown';\n try {\n npmVer = await new Promise<string>((resolve, reject) => {\n const child = spawn('npm', ['-v'], { shell: true });\n let out = '';\n child.stdout?.on('data', (d) => (out += String(d)));\n child.on('close', () => resolve(out.trim()));\n child.on('error', reject);\n });\n if (cmpSemver(npmVer, MIN_NPM) >= 0) {\n console.log(`✅ npm ${npmVer} (min ${MIN_NPM})`);\n } else {\n ok = false;\n console.log(`❌ npm ${npmVer} — please upgrade to >= ${MIN_NPM}`);\n }\n } catch {\n ok = false;\n console.log('❌ npm not found in PATH');\n }\n\n const tsconfigPath = path.join(cwd, 'tsconfig.json');\n if (await fileExists(tsconfigPath)) {\n console.log(`✅ tsconfig.json found`);\n const tsconfig = await readJSON<Record<string, any>>(tsconfigPath);\n const { ok: oks, issues } = checkRequiredTsOptions(tsconfig?.compilerOptions);\n for (const line of oks) console.log(c('green', ` ✓ ${line}`));\n if (issues.length) {\n ok = false;\n for (const line of issues) console.log(c('yellow', ` • ${line}`));\n console.log(c('cyan', ` -> Run \"frontmcp init\" to apply the required settings.`));\n }\n } else {\n ok = false;\n console.log(`❌ tsconfig.json not found — run ${c('cyan', 'frontmcp init')}`);\n }\n\n try {\n const entry = await resolveEntry(cwd);\n console.log(`✅ entry detected: ${path.relative(cwd, entry)}`);\n } catch (e: any) {\n const firstLine = (e?.message as string | undefined)?.split('\\n')?.[0] ?? 'entry not found';\n console.log(`❌ entry not detected — ${firstLine}`);\n }\n\n if (ok) console.log(c('green', '\\nAll checks passed. You are ready to go!'));\n else console.log(c('yellow', '\\nSome checks failed. See above for fixes.'));\n}\n"]}
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.runInspector = runInspector;
|
|
4
4
|
const colors_1 = require("../colors");
|
|
5
|
-
const
|
|
5
|
+
const utils_1 = require("@frontmcp/utils");
|
|
6
6
|
async function runInspector() {
|
|
7
7
|
console.log(`${(0, colors_1.c)('cyan', '[inspector]')} launching MCP Inspector...`);
|
|
8
|
-
await (0,
|
|
8
|
+
await (0, utils_1.runCmd)('npx', ['-y', '@modelcontextprotocol/inspector']);
|
|
9
9
|
}
|
|
10
10
|
//# sourceMappingURL=inspector.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inspector.js","sourceRoot":"","sources":["../../../src/commands/inspector.ts"],"names":[],"mappings":";;AAGA,oCAGC;AAND,sCAA8B;AAC9B,
|
|
1
|
+
{"version":3,"file":"inspector.js","sourceRoot":"","sources":["../../../src/commands/inspector.ts"],"names":[],"mappings":";;AAGA,oCAGC;AAND,sCAA8B;AAC9B,2CAAyC;AAElC,KAAK,UAAU,YAAY;IAChC,OAAO,CAAC,GAAG,CAAC,GAAG,IAAA,UAAC,EAAC,MAAM,EAAE,aAAa,CAAC,6BAA6B,CAAC,CAAC;IACtE,MAAM,IAAA,cAAM,EAAC,KAAK,EAAE,CAAC,IAAI,EAAE,iCAAiC,CAAC,CAAC,CAAC;AACjE,CAAC","sourcesContent":["import { c } from '../colors';\nimport { runCmd } from '@frontmcp/utils';\n\nexport async function runInspector(): Promise<void> {\n console.log(`${c('cyan', '[inspector]')} launching MCP Inspector...`);\n await runCmd('npx', ['-y', '@modelcontextprotocol/inspector']);\n}\n"]}
|
package/src/commands/template.js
CHANGED
|
@@ -5,6 +5,7 @@ const tslib_1 = require("tslib");
|
|
|
5
5
|
const path = tslib_1.__importStar(require("path"));
|
|
6
6
|
const readline = tslib_1.__importStar(require("readline"));
|
|
7
7
|
const colors_1 = require("../colors");
|
|
8
|
+
const utils_1 = require("@frontmcp/utils");
|
|
8
9
|
const fs_1 = require("../utils/fs");
|
|
9
10
|
/**
|
|
10
11
|
* frontmcp template <templateName>
|
|
@@ -84,12 +85,11 @@ async function runTemplate(templateName) {
|
|
|
84
85
|
const ctx = { owner, service, authType };
|
|
85
86
|
const cwd = process.cwd();
|
|
86
87
|
const destRoot = path.resolve(cwd, 'integrations', owner, service);
|
|
87
|
-
await (0,
|
|
88
|
+
await (0, utils_1.ensureDir)(destRoot);
|
|
88
89
|
console.log((0, colors_1.c)('gray', `[template] Scaffolding into ${path.relative(cwd, destRoot)}`));
|
|
89
90
|
await copyTemplateTree(templateRoot, destRoot, ctx);
|
|
90
91
|
console.log('');
|
|
91
|
-
console.log((0, colors_1.c)('green', '✔ Template hydrated into: ') +
|
|
92
|
-
path.relative(cwd, destRoot));
|
|
92
|
+
console.log((0, colors_1.c)('green', '✔ Template hydrated into: ') + path.relative(cwd, destRoot));
|
|
93
93
|
console.log((0, colors_1.c)('gray', 'You can now edit or delete the generated example files and create your own tools.'));
|
|
94
94
|
}
|
|
95
95
|
finally {
|
|
@@ -157,18 +157,18 @@ async function copyTemplateTree(templateRoot, destRoot, ctx) {
|
|
|
157
157
|
const relWithPlaceholders = applyPlaceholders(relFromRoot, ctx);
|
|
158
158
|
const destPath = path.join(destRoot, relWithPlaceholders);
|
|
159
159
|
if (entry.isDirectory()) {
|
|
160
|
-
await (0,
|
|
160
|
+
await (0, utils_1.ensureDir)(destPath);
|
|
161
161
|
await walk(srcPath);
|
|
162
162
|
}
|
|
163
163
|
else if (entry.isFile()) {
|
|
164
164
|
// Read template file, apply placeholders, write if not existing
|
|
165
165
|
const content = await fs_1.fsp.readFile(srcPath, 'utf8');
|
|
166
166
|
const processed = applyPlaceholders(content, ctx);
|
|
167
|
-
if (await (0,
|
|
167
|
+
if (await (0, utils_1.fileExists)(destPath)) {
|
|
168
168
|
console.log((0, colors_1.c)('gray', `skip: ${path.relative(process.cwd(), destPath)} already exists`));
|
|
169
169
|
continue;
|
|
170
170
|
}
|
|
171
|
-
await (0,
|
|
171
|
+
await (0, utils_1.ensureDir)(path.dirname(destPath));
|
|
172
172
|
await fs_1.fsp.writeFile(destPath, processed, 'utf8');
|
|
173
173
|
console.log((0, colors_1.c)('green', `✓ created ${path.relative(process.cwd(), destPath)}`));
|
|
174
174
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"template.js","sourceRoot":"","sources":["../../../src/commands/template.ts"],"names":[],"mappings":"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","sourcesContent":["import * as path from 'path';\nimport * as readline from 'readline';\nimport { c } from '../colors';\nimport { ensureDir, fileExists, fsp } from '../utils/fs';\n\ntype AuthType = 'oauth2' | 'bearer' | 'apiKey';\n\ninterface TemplateContext {\n owner: string;\n service: string;\n authType: AuthType;\n}\n\n/**\n * frontmcp template <templateName>\n *\n * Example:\n * npx frontmcp template 3rd-party-integration\n *\n * This will look for templates in:\n * src/templates/<templateName> (built to dist/templates/<templateName>)\n * and copy them into:\n * integrations/<owner>/<service>\n * with __OWNER__, __SERVICE__, __AUTH_TYPE__ replaced.\n */\nexport async function runTemplate(templateName?: string): Promise<void> {\n const name = (templateName || '').trim();\n if (!name) {\n console.log(c('red', 'Template name is required (e.g. 3rd-party-integration).'));\n return;\n }\n\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n const ask = (q: string): Promise<string> =>\n new Promise((resolve) => rl.question(q, (ans) => resolve(ans.trim())));\n\n try {\n const templatesRoot = path.resolve(__dirname, '..', 'templates');\n\n // 1) Collect available templates up-front\n const available = await listAvailableTemplates(templatesRoot);\n if (!available.length) {\n console.log(\n c('red', `No templates found under ${path.relative(process.cwd(), templatesRoot)}.`),\n );\n return;\n }\n\n // 2) Sanitize the name and choose the actual template folder\n const sanitized = sanitizeTemplateName(name);\n let selected: string | null = null;\n\n if (available.includes(name)) {\n selected = name;\n } else if (available.includes(sanitized)) {\n selected = sanitized;\n if (sanitized !== name) {\n console.log(\n c('yellow', `[template] Template \"${name}\" not found, using sanitized \"${sanitized}\"`),\n );\n }\n }\n\n if (!selected) {\n console.log(\n c('red', `Template \"${name}\" not found under ${path.relative(process.cwd(), templatesRoot)}.`),\n );\n console.log(c('gray', '\\nAvailable templates:'));\n for (const t of available) {\n console.log(' -', t);\n }\n return;\n }\n\n const templateRoot = path.resolve(templatesRoot, selected);\n\n console.log(\n c('cyan', '[template]') + ` Using template \"${selected}\" from src/templates/${selected}`,\n );\n\n // Ask for owner & service\n let owner = await ask(`Third-party owner (e.g. google, github, slack): `);\n if (!owner) {\n console.log(c('red', 'Owner is required.'));\n return;\n }\n owner = sanitizeSlug(owner);\n\n let service = await ask(\n `Third-party service (e.g. gmail, slack-bot): `,\n );\n if (!service) {\n console.log(c('red', 'Service is required.'));\n return;\n }\n service = sanitizeSlug(service);\n\n // Auth type (for placeholders only – you can use or ignore in templates)\n let authRaw = await ask(\n `Default auth type (oauth2/bearer/apiKey) [oauth2]: `,\n );\n if (!authRaw) authRaw = 'oauth2';\n const authType = authRaw as AuthType;\n if (!['oauth2', 'bearer', 'apiKey'].includes(authType)) {\n console.log(c('red', `Invalid auth type: ${authRaw}`));\n return;\n }\n\n const ctx: TemplateContext = { owner, service, authType };\n\n const cwd = process.cwd();\n const destRoot = path.resolve(cwd, 'integrations', owner, service);\n await ensureDir(destRoot);\n\n console.log(\n c('gray', `[template] Scaffolding into ${path.relative(cwd, destRoot)}`),\n );\n\n await copyTemplateTree(templateRoot, destRoot, ctx);\n\n console.log('');\n console.log(\n c('green', '✔ Template hydrated into: ') +\n path.relative(cwd, destRoot),\n );\n console.log(\n c(\n 'gray',\n 'You can now edit or delete the generated example files and create your own tools.',\n ),\n );\n } finally {\n rl.close();\n }\n}\n\n/* -------------------------------------------------------------------------- */\n/* Helpers */\n/* -------------------------------------------------------------------------- */\n\nfunction sanitizeSlug(val: string): string {\n return (\n val\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9-]/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '') || 'service'\n );\n}\n\n// More permissive for template folder names (allow . _ -)\nfunction sanitizeTemplateName(val: string): string {\n return (\n val\n .trim()\n .replace(/[^a-zA-Z0-9._-]/g, '-') // replace weird chars\n .replace(/-+/g, '-') // collapse multiple dashes\n .replace(/^-|-$/g, '') || 'template'\n );\n}\n\nasync function dirExists(p: string): Promise<boolean> {\n try {\n const st = await fsp.stat(p);\n return st.isDirectory();\n } catch {\n return false;\n }\n}\n\nasync function listAvailableTemplates(templatesRoot: string): Promise<string[]> {\n try {\n const entries = await fsp.readdir(templatesRoot, { withFileTypes: true });\n return entries.filter((e) => e.isDirectory()).map((e) => e.name);\n } catch {\n return [];\n }\n}\n\n/**\n * Replace placeholders in both filenames and file contents.\n *\n * Supported placeholders:\n * __OWNER__\n * __SERVICE__\n * __AUTH_TYPE__\n */\nfunction applyPlaceholders(input: string, ctx: TemplateContext): string {\n return input\n .replaceAll('__OWNER__', ctx.owner)\n .replaceAll('__SERVICE__', ctx.service)\n .replaceAll('__AUTH_TYPE__', ctx.authType);\n}\n\nasync function copyTemplateTree(\n templateRoot: string,\n destRoot: string,\n ctx: TemplateContext,\n): Promise<void> {\n const walk = async (srcDir: string) => {\n const entries = await fsp.readdir(srcDir, { withFileTypes: true });\n\n for (const entry of entries) {\n const srcPath = path.join(srcDir, entry.name);\n const relFromRoot = path.relative(templateRoot, srcPath);\n\n // Apply placeholders in path segments too\n const relWithPlaceholders = applyPlaceholders(relFromRoot, ctx);\n const destPath = path.join(destRoot, relWithPlaceholders);\n\n if (entry.isDirectory()) {\n await ensureDir(destPath);\n await walk(srcPath);\n } else if (entry.isFile()) {\n // Read template file, apply placeholders, write if not existing\n const content = await fsp.readFile(srcPath, 'utf8');\n const processed = applyPlaceholders(content, ctx);\n\n if (await fileExists(destPath)) {\n console.log(\n c('gray', `skip: ${path.relative(process.cwd(), destPath)} already exists`),\n );\n continue;\n }\n\n await ensureDir(path.dirname(destPath));\n await fsp.writeFile(destPath, processed, 'utf8');\n console.log(\n c('green', `✓ created ${path.relative(process.cwd(), destPath)}`),\n );\n }\n }\n };\n\n await walk(templateRoot);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"template.js","sourceRoot":"","sources":["../../../src/commands/template.ts"],"names":[],"mappings":"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","sourcesContent":["import * as path from 'path';\nimport * as readline from 'readline';\nimport { c } from '../colors';\nimport { ensureDir, fileExists } from '@frontmcp/utils';\nimport { fsp } from '../utils/fs';\n\ntype AuthType = 'oauth2' | 'bearer' | 'apiKey';\n\ninterface TemplateContext {\n owner: string;\n service: string;\n authType: AuthType;\n}\n\n/**\n * frontmcp template <templateName>\n *\n * Example:\n * npx frontmcp template 3rd-party-integration\n *\n * This will look for templates in:\n * src/templates/<templateName> (built to dist/templates/<templateName>)\n * and copy them into:\n * integrations/<owner>/<service>\n * with __OWNER__, __SERVICE__, __AUTH_TYPE__ replaced.\n */\nexport async function runTemplate(templateName?: string): Promise<void> {\n const name = (templateName || '').trim();\n if (!name) {\n console.log(c('red', 'Template name is required (e.g. 3rd-party-integration).'));\n return;\n }\n\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n const ask = (q: string): Promise<string> => new Promise((resolve) => rl.question(q, (ans) => resolve(ans.trim())));\n\n try {\n const templatesRoot = path.resolve(__dirname, '..', 'templates');\n\n // 1) Collect available templates up-front\n const available = await listAvailableTemplates(templatesRoot);\n if (!available.length) {\n console.log(c('red', `No templates found under ${path.relative(process.cwd(), templatesRoot)}.`));\n return;\n }\n\n // 2) Sanitize the name and choose the actual template folder\n const sanitized = sanitizeTemplateName(name);\n let selected: string | null = null;\n\n if (available.includes(name)) {\n selected = name;\n } else if (available.includes(sanitized)) {\n selected = sanitized;\n if (sanitized !== name) {\n console.log(c('yellow', `[template] Template \"${name}\" not found, using sanitized \"${sanitized}\"`));\n }\n }\n\n if (!selected) {\n console.log(c('red', `Template \"${name}\" not found under ${path.relative(process.cwd(), templatesRoot)}.`));\n console.log(c('gray', '\\nAvailable templates:'));\n for (const t of available) {\n console.log(' -', t);\n }\n return;\n }\n\n const templateRoot = path.resolve(templatesRoot, selected);\n\n console.log(c('cyan', '[template]') + ` Using template \"${selected}\" from src/templates/${selected}`);\n\n // Ask for owner & service\n let owner = await ask(`Third-party owner (e.g. google, github, slack): `);\n if (!owner) {\n console.log(c('red', 'Owner is required.'));\n return;\n }\n owner = sanitizeSlug(owner);\n\n let service = await ask(`Third-party service (e.g. gmail, slack-bot): `);\n if (!service) {\n console.log(c('red', 'Service is required.'));\n return;\n }\n service = sanitizeSlug(service);\n\n // Auth type (for placeholders only – you can use or ignore in templates)\n let authRaw = await ask(`Default auth type (oauth2/bearer/apiKey) [oauth2]: `);\n if (!authRaw) authRaw = 'oauth2';\n const authType = authRaw as AuthType;\n if (!['oauth2', 'bearer', 'apiKey'].includes(authType)) {\n console.log(c('red', `Invalid auth type: ${authRaw}`));\n return;\n }\n\n const ctx: TemplateContext = { owner, service, authType };\n\n const cwd = process.cwd();\n const destRoot = path.resolve(cwd, 'integrations', owner, service);\n await ensureDir(destRoot);\n\n console.log(c('gray', `[template] Scaffolding into ${path.relative(cwd, destRoot)}`));\n\n await copyTemplateTree(templateRoot, destRoot, ctx);\n\n console.log('');\n console.log(c('green', '✔ Template hydrated into: ') + path.relative(cwd, destRoot));\n console.log(c('gray', 'You can now edit or delete the generated example files and create your own tools.'));\n } finally {\n rl.close();\n }\n}\n\n/* -------------------------------------------------------------------------- */\n/* Helpers */\n/* -------------------------------------------------------------------------- */\n\nfunction sanitizeSlug(val: string): string {\n return (\n val\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9-]/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '') || 'service'\n );\n}\n\n// More permissive for template folder names (allow . _ -)\nfunction sanitizeTemplateName(val: string): string {\n return (\n val\n .trim()\n .replace(/[^a-zA-Z0-9._-]/g, '-') // replace weird chars\n .replace(/-+/g, '-') // collapse multiple dashes\n .replace(/^-|-$/g, '') || 'template'\n );\n}\n\nasync function dirExists(p: string): Promise<boolean> {\n try {\n const st = await fsp.stat(p);\n return st.isDirectory();\n } catch {\n return false;\n }\n}\n\nasync function listAvailableTemplates(templatesRoot: string): Promise<string[]> {\n try {\n const entries = await fsp.readdir(templatesRoot, { withFileTypes: true });\n return entries.filter((e) => e.isDirectory()).map((e) => e.name);\n } catch {\n return [];\n }\n}\n\n/**\n * Replace placeholders in both filenames and file contents.\n *\n * Supported placeholders:\n * __OWNER__\n * __SERVICE__\n * __AUTH_TYPE__\n */\nfunction applyPlaceholders(input: string, ctx: TemplateContext): string {\n return input\n .replaceAll('__OWNER__', ctx.owner)\n .replaceAll('__SERVICE__', ctx.service)\n .replaceAll('__AUTH_TYPE__', ctx.authType);\n}\n\nasync function copyTemplateTree(templateRoot: string, destRoot: string, ctx: TemplateContext): Promise<void> {\n const walk = async (srcDir: string) => {\n const entries = await fsp.readdir(srcDir, { withFileTypes: true });\n\n for (const entry of entries) {\n const srcPath = path.join(srcDir, entry.name);\n const relFromRoot = path.relative(templateRoot, srcPath);\n\n // Apply placeholders in path segments too\n const relWithPlaceholders = applyPlaceholders(relFromRoot, ctx);\n const destPath = path.join(destRoot, relWithPlaceholders);\n\n if (entry.isDirectory()) {\n await ensureDir(destPath);\n await walk(srcPath);\n } else if (entry.isFile()) {\n // Read template file, apply placeholders, write if not existing\n const content = await fsp.readFile(srcPath, 'utf8');\n const processed = applyPlaceholders(content, ctx);\n\n if (await fileExists(destPath)) {\n console.log(c('gray', `skip: ${path.relative(process.cwd(), destPath)} already exists`));\n continue;\n }\n\n await ensureDir(path.dirname(destPath));\n await fsp.writeFile(destPath, processed, 'utf8');\n console.log(c('green', `✓ created ${path.relative(process.cwd(), destPath)}`));\n }\n }\n };\n\n await walk(templateRoot);\n}\n"]}
|
package/src/commands/test.js
CHANGED
|
@@ -6,6 +6,7 @@ const path = tslib_1.__importStar(require("path"));
|
|
|
6
6
|
const os = tslib_1.__importStar(require("os"));
|
|
7
7
|
const child_process_1 = require("child_process");
|
|
8
8
|
const colors_1 = require("../colors");
|
|
9
|
+
const utils_1 = require("@frontmcp/utils");
|
|
9
10
|
const fs_1 = require("../utils/fs");
|
|
10
11
|
/**
|
|
11
12
|
* Generate Jest configuration programmatically for E2E tests.
|
|
@@ -58,8 +59,16 @@ function generateJestConfig(cwd, opts) {
|
|
|
58
59
|
transformIgnorePatterns: ['node_modules/(?!(jose)/)'],
|
|
59
60
|
// Ignore patterns
|
|
60
61
|
testPathIgnorePatterns: ['/node_modules/', '/dist/'],
|
|
61
|
-
// Coverage settings
|
|
62
|
-
collectCoverage: false,
|
|
62
|
+
// Coverage settings
|
|
63
|
+
collectCoverage: opts.coverage ?? false,
|
|
64
|
+
// Coverage configuration when enabled
|
|
65
|
+
...(opts.coverage
|
|
66
|
+
? {
|
|
67
|
+
coverageDirectory: '<rootDir>/coverage',
|
|
68
|
+
coverageReporters: ['text', 'lcov', 'json'],
|
|
69
|
+
collectCoverageFrom: ['<rootDir>/src/**/*.ts', '!<rootDir>/src/**/*.test.ts', '!<rootDir>/src/**/*.spec.ts'],
|
|
70
|
+
}
|
|
71
|
+
: {}),
|
|
63
72
|
// Verbose output
|
|
64
73
|
verbose: opts.verbose ?? true,
|
|
65
74
|
};
|
|
@@ -78,7 +87,7 @@ async function runTest(opts) {
|
|
|
78
87
|
const cwd = process.cwd();
|
|
79
88
|
// Check for e2e directory
|
|
80
89
|
const e2eDir = path.join(cwd, 'e2e');
|
|
81
|
-
const hasE2EDir = await (0,
|
|
90
|
+
const hasE2EDir = await (0, utils_1.fileExists)(e2eDir);
|
|
82
91
|
if (!hasE2EDir) {
|
|
83
92
|
console.error((0, colors_1.c)('red', 'No e2e directory found.'));
|
|
84
93
|
console.error('');
|
|
@@ -110,6 +119,10 @@ async function runTest(opts) {
|
|
|
110
119
|
if (opts.verbose) {
|
|
111
120
|
jestArgs.push('--verbose');
|
|
112
121
|
}
|
|
122
|
+
// Add coverage flag
|
|
123
|
+
if (opts.coverage) {
|
|
124
|
+
jestArgs.push('--coverage');
|
|
125
|
+
}
|
|
113
126
|
// Add any additional positional args (e.g., test file patterns)
|
|
114
127
|
const testPatterns = opts._.slice(1); // Skip 'test' command itself
|
|
115
128
|
if (testPatterns.length > 0) {
|
|
@@ -123,6 +136,9 @@ async function runTest(opts) {
|
|
|
123
136
|
if (opts.watch) {
|
|
124
137
|
console.log(`${(0, colors_1.c)('gray', '[test]')} watch mode enabled`);
|
|
125
138
|
}
|
|
139
|
+
if (opts.coverage) {
|
|
140
|
+
console.log(`${(0, colors_1.c)('gray', '[test]')} coverage collection enabled`);
|
|
141
|
+
}
|
|
126
142
|
console.log(`${(0, colors_1.c)('gray', 'hint:')} press Ctrl+C to stop\n`);
|
|
127
143
|
// Run Jest directly via node_modules/.bin or npx without shell
|
|
128
144
|
// Using shell: false with explicit args array avoids escaping issues
|