qraft
Version:
A powerful CLI tool to qraft structured project setups from GitHub template repositories
234 lines • 10.2 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ManifestBuilder = void 0;
const chalk_1 = __importDefault(require("chalk"));
const inquirer_1 = __importDefault(require("inquirer"));
class ManifestBuilder {
/**
* Interactive manifest building process
*/
async buildManifest(generatedMetadata, options = {}) {
console.log(chalk_1.default.cyan('\n🔧 Interactive Manifest Builder'));
console.log(chalk_1.default.gray('Let\'s gather information for your box manifest. Press Enter to use defaults.\n'));
// Step 1: Basic Information
console.log(chalk_1.default.yellow('📦 Basic Information'));
const basicAnswers = await inquirer_1.default.prompt([
{
type: 'input',
name: 'name',
message: 'Box name:',
default: options.suggestedName || generatedMetadata.name,
validate: (input) => {
if (!input.trim())
return 'Box name is required';
if (!/^[a-z0-9-_]+$/.test(input))
return 'Box name must contain only lowercase letters, numbers, hyphens, and underscores';
return true;
}
},
{
type: 'input',
name: 'description',
message: 'Description:',
default: options.suggestedDescription || generatedMetadata.description,
validate: (input) => input.trim() ? true : 'Description is required'
},
{
type: 'input',
name: 'author',
message: 'Author:',
default: options.suggestedAuthor || generatedMetadata.author || 'Unknown',
validate: (input) => input.trim() ? true : 'Author is required'
},
{
type: 'input',
name: 'version',
message: 'Version:',
default: generatedMetadata.version || '1.0.0',
validate: (input) => {
if (!input.trim())
return 'Version is required';
if (!/^\d+\.\d+\.\d+/.test(input))
return 'Version must follow semantic versioning (e.g., 1.0.0)';
return true;
}
}
]);
// Step 2: Tags and Configuration
console.log(chalk_1.default.yellow('\n🏷️ Tags and Configuration'));
const configAnswers = await inquirer_1.default.prompt([
{
type: 'input',
name: 'tags',
message: 'Tags (comma-separated):',
default: (options.suggestedTags || generatedMetadata.tags || []).join(', '),
filter: (input) => input.split(',').map(tag => tag.trim()).filter(tag => tag.length > 0)
},
{
type: 'input',
name: 'remotePath',
message: 'Remote path in registry:',
default: options.suggestedRemotePath || this.generateDefaultRemotePath(basicAnswers.name, options.localPath),
validate: (input) => {
if (!input.trim())
return 'Remote path is required';
if (!/^[a-zA-Z0-9/_-]+$/.test(input))
return 'Remote path must contain only letters, numbers, slashes, hyphens, and underscores';
return true;
}
},
{
type: 'input',
name: 'defaultTarget',
message: 'Default target directory:',
default: options.defaultTarget || this.generateDefaultTarget(basicAnswers.name),
}
]);
// Step 3: Advanced Options
console.log(chalk_1.default.yellow('\n⚙️ Advanced Options'));
const advancedAnswers = await inquirer_1.default.prompt([
{
type: 'confirm',
name: 'addExclusions',
message: 'Add file exclusions?',
default: false
},
{
type: 'input',
name: 'exclude',
message: 'Files to exclude (comma-separated patterns):',
when: (answers) => answers.addExclusions,
default: '*.log, .env, node_modules/**',
filter: (input) => input.split(',').map(pattern => pattern.trim()).filter(pattern => pattern.length > 0)
},
{
type: 'confirm',
name: 'addPostInstall',
message: 'Add post-installation steps?',
default: false
},
{
type: 'input',
name: 'postInstall',
message: 'Post-installation steps (comma-separated):',
when: (answers) => answers.addPostInstall,
default: 'npm install, Review configuration files',
filter: (input) => input.split(',').map(step => step.trim()).filter(step => step.length > 0)
}
]);
// Build the final manifest
const manifest = {
name: basicAnswers.name,
description: basicAnswers.description,
author: basicAnswers.author,
version: basicAnswers.version,
defaultTarget: configAnswers.defaultTarget || './target',
remotePath: configAnswers.remotePath,
tags: configAnswers.tags.length > 0 ? configAnswers.tags : undefined,
exclude: advancedAnswers.exclude || undefined,
postInstall: advancedAnswers.postInstall || undefined
};
// Show preview
console.log(chalk_1.default.cyan('\n📋 Manifest Preview:'));
console.log(chalk_1.default.gray(JSON.stringify(manifest, null, 2)));
const confirmAnswer = await inquirer_1.default.prompt([
{
type: 'confirm',
name: 'confirm',
message: 'Does this look correct?',
default: true
}
]);
if (!confirmAnswer.confirm) {
console.log(chalk_1.default.yellow('\n🔄 Let\'s try again...'));
return this.buildManifest(generatedMetadata, options);
}
return manifest;
}
/**
* Quick manifest building with minimal prompts
*/
async buildQuickManifest(generatedMetadata, options = {}) {
console.log(chalk_1.default.cyan('\n⚡ Quick Manifest Builder'));
console.log(chalk_1.default.gray('Essential information only. Use --interactive for full options.\n'));
const answers = await inquirer_1.default.prompt([
{
type: 'input',
name: 'name',
message: 'Box name:',
default: options.suggestedName || generatedMetadata.name,
validate: (input) => {
if (!input.trim())
return 'Box name is required';
if (!/^[a-z0-9-_]+$/.test(input))
return 'Box name must contain only lowercase letters, numbers, hyphens, and underscores';
return true;
}
},
{
type: 'input',
name: 'description',
message: 'Description:',
default: options.suggestedDescription || generatedMetadata.description,
validate: (input) => input.trim() ? true : 'Description is required'
},
{
type: 'confirm',
name: 'useDefaults',
message: 'Use smart defaults for other fields?',
default: true
}
]);
if (answers.useDefaults) {
const manifest = {
name: answers.name,
description: answers.description,
author: options.suggestedAuthor || generatedMetadata.author || 'Unknown',
version: generatedMetadata.version || '1.0.0',
defaultTarget: options.defaultTarget || './target',
remotePath: options.suggestedRemotePath || this.generateDefaultRemotePath(answers.name, options.localPath)
};
// Add optional properties only if they have values
const tags = options.suggestedTags || generatedMetadata.tags;
if (tags && tags.length > 0)
manifest.tags = tags;
return manifest;
}
// If user doesn't want defaults, fall back to full interactive mode
return this.buildManifest(generatedMetadata, options);
}
/**
* Generate a default remote path based on box name and local path
* @param boxName Name of the box
* @param localPath Local path being boxed (optional)
* @returns string Default remote path
*/
generateDefaultRemotePath(boxName, localPath) {
if (localPath) {
// If local path is provided, use it as the remote path
// Convert absolute paths to relative and clean up
const relativePath = localPath.replace(/^\.\//, '').replace(/\/$/, '');
// If the path looks like a nested structure, use it
if (relativePath.includes('/')) {
return relativePath;
}
}
// Fall back to box name
return boxName;
}
/**
* Generate a default target directory based on box name
* @param boxName Name of the box
* @returns string Default target directory
*/
generateDefaultTarget(boxName) {
// Extract the last part of the box name for the target
const targetName = boxName.includes('/') ? boxName.split('/').pop() : boxName;
return `./${targetName}`;
}
}
exports.ManifestBuilder = ManifestBuilder;
//# sourceMappingURL=manifestBuilder.js.map