mockey-patcher-cli
Version:
Global CLI tool for managing Mockey Patcher backend services with Docker Compose - API mocking and request redirection made simple
403 lines (360 loc) ⢠12.9 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.setupCommand = setupCommand;
const fs = __importStar(require("fs-extra"));
const path = __importStar(require("path"));
const inquirer_1 = __importDefault(require("inquirer"));
const logger_1 = require("../utils/logger");
const config_1 = require("../utils/config");
async function setupCommand(options) {
try {
logger_1.Logger.header("Mockey Patcher Setup");
const currentPath = process.cwd();
let projectName = options.projectName;
let projectPath;
// Get project name if not provided
if (!projectName && options.interactive !== false) {
const answers = await inquirer_1.default.prompt([
{
type: "input",
name: "projectName",
message: "Enter project name:",
default: "my-mockey-patcher",
validate: (input) => {
if (!input.trim()) {
return "Project name cannot be empty";
}
if (!/^[a-zA-Z0-9-_]+$/.test(input)) {
return "Project name can only contain letters, numbers, hyphens, and underscores";
}
return true;
},
},
]);
projectName = answers.projectName;
}
// Use default if still not provided
if (!projectName) {
projectName = "my-mockey-patcher";
}
// Create project path
projectPath = path.join(currentPath, projectName);
// Check if project directory already exists
if (fs.existsSync(projectPath)) {
if (!options.force) {
if (options.interactive !== false) {
const { overwrite } = await inquirer_1.default.prompt([
{
type: "confirm",
name: "overwrite",
message: `Directory '${projectName}' already exists. Continue anyway?`,
default: false,
},
]);
if (!overwrite) {
logger_1.Logger.info("Setup cancelled");
return;
}
}
else {
logger_1.Logger.error(`Directory '${projectName}' already exists. Use --force to overwrite.`);
return;
}
}
}
// Create project directory
await fs.ensureDir(projectPath);
logger_1.Logger.info(`Created project directory: ${projectPath}`);
// Change to project directory for configuration
process.chdir(projectPath);
// Initialize configuration
let config;
const configPath = path.join(projectPath, ".redirector.json");
if (fs.existsSync(configPath) && !options.force) {
config = await config_1.ConfigManager.loadConfig(projectPath);
logger_1.Logger.info("Loaded existing configuration");
}
else {
config = {
backendPort: options.port || 3000,
postgresPort: options.postgresPort || 5432,
dockerUsername: options.dockerUsername || "shivarajbakale",
projectName: projectName,
environment: "production",
};
}
// Interactive configuration if enabled
if (options.interactive !== false) {
const answers = await inquirer_1.default.prompt([
{
type: "number",
name: "backendPort",
message: "Backend API port:",
default: config.backendPort,
validate: (input) => {
if (input < 1 || input > 65535) {
return "Port must be between 1 and 65535";
}
return true;
},
},
{
type: "number",
name: "postgresPort",
message: "PostgreSQL port:",
default: config.postgresPort,
validate: (input) => {
if (input < 1 || input > 65535) {
return "Port must be between 1 and 65535";
}
return true;
},
},
{
type: "input",
name: "dockerUsername",
message: "Docker Hub username:",
default: config.dockerUsername,
},
]);
config = { ...config, ...answers };
}
// Override with CLI options
if (options.port)
config.backendPort = options.port;
if (options.postgresPort)
config.postgresPort = options.postgresPort;
if (options.dockerUsername)
config.dockerUsername = options.dockerUsername;
// Save configuration
await config_1.ConfigManager.saveConfig(config, projectPath);
logger_1.Logger.success("Configuration saved");
// Generate project files
await generateProjectFiles(config, projectPath);
logger_1.Logger.success(`\nš Mockey Patcher project '${projectName}' initialized successfully!`);
logger_1.Logger.info(`\nNext steps:`);
logger_1.Logger.info(` cd ${projectName}`);
logger_1.Logger.info(` mockey-patcher start`);
logger_1.Logger.info(`\nAPI will be available at: http://localhost:${config.backendPort}`);
logger_1.Logger.info(`Health check: http://localhost:${config.backendPort}/health`);
// Change back to original directory
process.chdir(currentPath);
}
catch (error) {
logger_1.Logger.error(`Setup failed: ${error}`);
throw error;
}
}
async function generateProjectFiles(config, projectPath) {
try {
logger_1.Logger.info("Generating project files...");
// Generate docker-compose.yml
await fs.writeFile(path.join(projectPath, "docker-compose.yml"), generateDockerComposeTemplate(config));
logger_1.Logger.info("ā Generated docker-compose.yml");
// Generate .env file
await config_1.ConfigManager.createEnvFile(config, projectPath);
logger_1.Logger.info("ā Generated .env");
// Generate .gitignore
await fs.writeFile(path.join(projectPath, ".gitignore"), generateGitignoreTemplate());
logger_1.Logger.info("ā Generated .gitignore");
// Generate README.md
await fs.writeFile(path.join(projectPath, "README.md"), generateReadmeTemplate(config));
logger_1.Logger.info("ā Generated README.md");
// Create data directory
await fs.ensureDir(path.join(projectPath, "data"));
logger_1.Logger.success("All project files generated successfully");
}
catch (error) {
logger_1.Logger.error(`Failed to generate project files: ${error}`);
throw error;
}
}
function generateDockerComposeTemplate(config) {
return `services:
postgres:
image: postgres:15
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: redirector
ports:
- "\${POSTGRES_PORT:-${config.postgresPort}}:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres -d redirector"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
backend:
image: \${DOCKER_USERNAME:-${config.dockerUsername}}/redirector-backend:latest
ports:
- "\${BACKEND_PORT:-${config.backendPort}}:3000"
depends_on:
postgres:
condition: service_healthy
environment:
- NODE_ENV=${config.environment}
- DATABASE_URL=postgresql://postgres:postgres@postgres:5432/redirector
restart: unless-stopped
healthcheck:
test:
[
"CMD-SHELL",
"wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1",
]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
volumes:
postgres_data:
`;
}
function generateGitignoreTemplate() {
return `# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-files dependency directory (https://github.com/pledbrook/node-files)
node_modules/
# TypeScript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
.env.test
.env.local
.env.production
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# next.js build output
.next
# nuxt.js build output
.nuxt
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Docker volumes
data/
# Mockey Patcher specific
.redirector.json
`;
}
function generateReadmeTemplate(config) {
return `# Mockey Patcher Backend
This project was initialized with \`mockey-patcher-cli\`.
## Quick Start
\`\`\`bash
# Start services
mockey-patcher start
# Check status
mockey-patcher status
# View logs
mockey-patcher logs
# Stop services
mockey-patcher stop
\`\`\`
## Available Commands
- \`mockey-patcher setup\` - Initialize project configuration
- \`mockey-patcher start\` - Start all services
- \`mockey-patcher stop\` - Stop all services
- \`mockey-patcher restart\` - Restart all services
- \`mockey-patcher reset\` - Reset all data and volumes
- \`mockey-patcher status\` - Show service status
- \`mockey-patcher logs [service]\` - View service logs
## Configuration
The project uses environment variables for configuration:
- \`BACKEND_PORT\` - Backend API port (default: ${config.backendPort})
- \`POSTGRES_PORT\` - PostgreSQL port (default: ${config.postgresPort})
- \`DOCKER_USERNAME\` - Docker Hub username (default: ${config.dockerUsername})
## Services
- **Backend API**: Available at http://localhost:${config.backendPort}
- **PostgreSQL**: Available at localhost:${config.postgresPort}
- **Health Check**: http://localhost:${config.backendPort}/health
## API Endpoints
- \`GET /health\` - Health check
- \`GET /groups\` - List groups
- \`POST /groups/create\` - Create group
- \`GET /requests\` - List requests
For more information, visit: https://github.com/shivarajbakale/redirector-app
`;
}
//# sourceMappingURL=setup.js.map