@syntropysoft/praetorian
Version:
Praetorian CLI ā A universal multi-environment configuration validator for DevSecOps teams. Validate, compare, and secure YAML/ENV files with ease.
219 lines (208 loc) ⢠7.78 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.runTemplate = runTemplate;
const chalk_1 = __importDefault(require("chalk"));
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const inquirer_1 = __importDefault(require("inquirer"));
async function runTemplate(recipe, options = {}) {
console.log(chalk_1.default.blue('\nšļø Creating project from template...\n'));
try {
// Validate recipe
const availableRecipes = getAvailableRecipes();
if (!availableRecipes.includes(recipe)) {
console.error(chalk_1.default.red(`ā Unknown recipe: ${recipe}`));
console.log(chalk_1.default.yellow('\nAvailable recipes:'));
availableRecipes.forEach(r => console.log(chalk_1.default.gray(` ⢠${r}`)));
process.exit(1);
}
// Get project details
const projectDetails = await getProjectDetails(recipe, options);
// Create project
await createProject(recipe, projectDetails);
console.log(chalk_1.default.green('\nā
Project created successfully!'));
console.log(chalk_1.default.blue(`š Location: ${projectDetails.outputDir}`));
// Show next steps
showNextSteps(recipe, projectDetails);
}
catch (error) {
console.error(chalk_1.default.red('\nā Template creation failed:'));
console.error(error instanceof Error ? error.message : error);
process.exit(1);
}
}
function getAvailableRecipes() {
return [
'syntropylog-basic',
'syntropylog-nats',
'syntropylog-redis',
'syntropylog-http',
'syntropylog-full-stack',
'express-security',
'koa-performance',
'fastify-production'
];
}
async function getProjectDetails(recipe, options) {
const questions = [];
if (!options.name) {
questions.push({
type: 'input',
name: 'projectName',
message: 'Project name:',
default: getDefaultProjectName(recipe),
validate: (input) => {
if (!input.trim())
return 'Project name is required';
if (!/^[a-z0-9-]+$/.test(input)) {
return 'Project name must contain only lowercase letters, numbers, and hyphens';
}
return true;
}
});
}
if (!options.output) {
questions.push({
type: 'input',
name: 'outputDir',
message: 'Output directory:',
default: './',
validate: (input) => {
const fullPath = path_1.default.resolve(input);
if (fs_1.default.existsSync(fullPath) && !options.force) {
return 'Directory already exists. Use --force to overwrite.';
}
return true;
}
});
}
const answers = await inquirer_1.default.prompt(questions);
return {
projectName: options.name || answers.projectName,
outputDir: path_1.default.resolve(options.output || answers.outputDir),
force: options.force || false
};
}
function getDefaultProjectName(recipe) {
const nameMap = {
'syntropylog-basic': 'my-syntropylog-app',
'syntropylog-nats': 'syntropylog-nats-app',
'syntropylog-redis': 'syntropylog-redis-app',
'syntropylog-http': 'syntropylog-http-app',
'syntropylog-full-stack': 'syntropylog-full-stack',
'express-security': 'express-security-app',
'koa-performance': 'koa-performance-app',
'fastify-production': 'fastify-production-app'
};
return nameMap[recipe] || 'my-project';
}
async function createProject(recipe, details) {
const projectDir = path_1.default.join(details.outputDir, details.projectName);
// Create project directory
if (fs_1.default.existsSync(projectDir) && !details.force) {
throw new Error(`Project directory already exists: ${projectDir}`);
}
if (!fs_1.default.existsSync(projectDir)) {
fs_1.default.mkdirSync(projectDir, { recursive: true });
}
console.log(chalk_1.default.gray(`Creating project: ${details.projectName}`));
console.log(chalk_1.default.gray(`Location: ${projectDir}`));
// Generate template files
const template = getTemplate(recipe, details);
for (const [filePath, content] of Object.entries(template)) {
const fullPath = path_1.default.join(projectDir, filePath);
const dir = path_1.default.dirname(fullPath);
if (!fs_1.default.existsSync(dir)) {
fs_1.default.mkdirSync(dir, { recursive: true });
}
fs_1.default.writeFileSync(fullPath, content);
console.log(chalk_1.default.gray(` Created: ${filePath}`));
}
}
function getTemplate(recipe, details) {
const templates = {
'syntropylog-basic': {
'package.json': JSON.stringify({
name: details.projectName,
version: '1.0.0',
description: 'SyntropyLog application',
main: 'src/index.ts',
scripts: {
start: 'tsx src/index.ts',
dev: 'tsx watch src/index.ts',
build: 'tsc',
test: 'vitest'
},
dependencies: {
syntropylog: '^0.7.4'
},
devDependencies: {
typescript: '^5.0.0',
tsx: '^4.0.0',
vitest: '^1.0.0'
}
}, null, 2),
'src/index.ts': `import { SyntropyLog } from 'syntropylog';
// Initialize SyntropyLog
const logger = new SyntropyLog({
appName: '${details.projectName}',
environment: 'development',
logLevel: 'info'
});
// Your application code here
logger.info('Application started');
console.log('Hello from ${details.projectName}!');
`,
'tsconfig.json': JSON.stringify({
compilerOptions: {
target: 'ES2020',
module: 'ESNext',
moduleResolution: 'node',
strict: true,
esModuleInterop: true,
skipLibCheck: true,
forceConsistentCasingInFileNames: true,
outDir: './dist'
},
include: ['src/**/*'],
exclude: ['node_modules', 'dist']
}, null, 2),
'README.md': `# ${details.projectName}
A SyntropyLog application.
## Getting Started
\`\`\`bash
npm install
npm run dev
\`\`\`
## Scripts
- \`npm start\` - Start the application
- \`npm run dev\` - Start in development mode with hot reload
- \`npm run build\` - Build the application
- \`npm test\` - Run tests
`
}
};
return templates[recipe] || {
'README.md': `# ${details.projectName}
Template for ${recipe} is not implemented yet.
## Getting Started
\`\`\`bash
npm install
\`\`\`
`
};
}
function showNextSteps(recipe, details) {
console.log(chalk_1.default.blue('\nš Next Steps:\n'));
console.log(chalk_1.default.gray(`cd ${details.projectName}`));
console.log(chalk_1.default.gray('npm install'));
console.log(chalk_1.default.gray('npm run dev'));
if (recipe.startsWith('syntropylog-')) {
console.log(chalk_1.default.blue('\nš Learn more about SyntropyLog:'));
console.log(chalk_1.default.gray('https://github.com/syntropysoft/syntropylog'));
}
}
//# sourceMappingURL=template.js.map