Initial commit

This commit is contained in:
Zhongwei Li
2025-11-30 09:04:14 +08:00
commit 70c36b5eff
248 changed files with 47482 additions and 0 deletions

View File

@@ -0,0 +1,259 @@
/**
* Autocomplete Prompt Template
*
* Use for: Large option lists with search
* Features: Type-ahead, fuzzy matching, suggestions
*
* Note: Requires inquirer-autocomplete-prompt plugin
* Install: npm install inquirer-autocomplete-prompt
*/
import inquirer from 'inquirer';
import inquirerAutocomplete from 'inquirer-autocomplete-prompt';
// Register the autocomplete prompt type
inquirer.registerPrompt('autocomplete', inquirerAutocomplete);
// Example: Countries list for autocomplete
const countries = [
'Afghanistan', 'Albania', 'Algeria', 'Andorra', 'Angola',
'Argentina', 'Armenia', 'Australia', 'Austria', 'Azerbaijan',
'Bahamas', 'Bahrain', 'Bangladesh', 'Barbados', 'Belarus',
'Belgium', 'Belize', 'Benin', 'Bhutan', 'Bolivia',
'Brazil', 'Brunei', 'Bulgaria', 'Burkina Faso', 'Burundi',
'Cambodia', 'Cameroon', 'Canada', 'Cape Verde', 'Chad',
'Chile', 'China', 'Colombia', 'Comoros', 'Congo',
'Costa Rica', 'Croatia', 'Cuba', 'Cyprus', 'Czech Republic',
'Denmark', 'Djibouti', 'Dominica', 'Dominican Republic',
'Ecuador', 'Egypt', 'El Salvador', 'Estonia', 'Ethiopia',
'Fiji', 'Finland', 'France', 'Gabon', 'Gambia',
'Georgia', 'Germany', 'Ghana', 'Greece', 'Grenada',
'Guatemala', 'Guinea', 'Guyana', 'Haiti', 'Honduras',
'Hungary', 'Iceland', 'India', 'Indonesia', 'Iran',
'Iraq', 'Ireland', 'Israel', 'Italy', 'Jamaica',
'Japan', 'Jordan', 'Kazakhstan', 'Kenya', 'Kuwait',
'Laos', 'Latvia', 'Lebanon', 'Lesotho', 'Liberia',
'Libya', 'Lithuania', 'Luxembourg', 'Madagascar', 'Malawi',
'Malaysia', 'Maldives', 'Mali', 'Malta', 'Mexico',
'Moldova', 'Monaco', 'Mongolia', 'Morocco', 'Mozambique',
'Myanmar', 'Namibia', 'Nepal', 'Netherlands', 'New Zealand',
'Nicaragua', 'Niger', 'Nigeria', 'Norway', 'Oman',
'Pakistan', 'Panama', 'Paraguay', 'Peru', 'Philippines',
'Poland', 'Portugal', 'Qatar', 'Romania', 'Russia',
'Rwanda', 'Saudi Arabia', 'Senegal', 'Serbia', 'Singapore',
'Slovakia', 'Slovenia', 'Somalia', 'South Africa', 'South Korea',
'Spain', 'Sri Lanka', 'Sudan', 'Sweden', 'Switzerland',
'Syria', 'Taiwan', 'Tanzania', 'Thailand', 'Togo',
'Tunisia', 'Turkey', 'Uganda', 'Ukraine', 'United Arab Emirates',
'United Kingdom', 'United States', 'Uruguay', 'Uzbekistan',
'Venezuela', 'Vietnam', 'Yemen', 'Zambia', 'Zimbabwe'
];
// Example: NPM packages for autocomplete
const popularPackages = [
'express', 'react', 'vue', 'angular', 'next', 'nuxt',
'axios', 'lodash', 'moment', 'dayjs', 'uuid', 'dotenv',
'typescript', 'eslint', 'prettier', 'jest', 'mocha', 'chai',
'webpack', 'vite', 'rollup', 'babel', 'esbuild',
'socket.io', 'redis', 'mongodb', 'mongoose', 'sequelize',
'prisma', 'typeorm', 'knex', 'pg', 'mysql2',
'bcrypt', 'jsonwebtoken', 'passport', 'helmet', 'cors',
'multer', 'sharp', 'puppeteer', 'playwright', 'cheerio'
];
// Fuzzy search function
function fuzzySearch(input, choices) {
if (!input) return choices;
const searchTerm = input.toLowerCase();
return choices.filter(choice => {
const item = typeof choice === 'string' ? choice : choice.name;
return item.toLowerCase().includes(searchTerm);
});
}
async function autocompletePromptExample() {
const answers = await inquirer.prompt([
{
type: 'autocomplete',
name: 'country',
message: 'Select your country:',
source: (answersSoFar, input) => {
return Promise.resolve(fuzzySearch(input, countries));
},
pageSize: 10
},
{
type: 'autocomplete',
name: 'package',
message: 'Search for an npm package:',
source: (answersSoFar, input) => {
const filtered = fuzzySearch(input, popularPackages);
return Promise.resolve(filtered);
},
pageSize: 8,
validate: (input) => {
return input.length > 0 || 'Please select a package';
}
},
{
type: 'autocomplete',
name: 'city',
message: 'Select city:',
source: async (answersSoFar, input) => {
// Example: Cities based on selected country
const citiesByCountry = {
'United States': ['New York', 'Los Angeles', 'Chicago', 'Houston', 'Phoenix'],
'United Kingdom': ['London', 'Manchester', 'Birmingham', 'Glasgow', 'Liverpool'],
'Canada': ['Toronto', 'Vancouver', 'Montreal', 'Calgary', 'Ottawa'],
'Australia': ['Sydney', 'Melbourne', 'Brisbane', 'Perth', 'Adelaide'],
'Germany': ['Berlin', 'Munich', 'Hamburg', 'Frankfurt', 'Cologne']
};
const cities = citiesByCountry[answersSoFar.country] || ['Capital City', 'Major City'];
return fuzzySearch(input, cities);
},
when: (answers) => ['United States', 'United Kingdom', 'Canada', 'Australia', 'Germany'].includes(answers.country)
}
]);
console.log('\n✅ Selections:');
console.log(JSON.stringify(answers, null, 2));
return answers;
}
// Example: Framework/Library search
async function frameworkSearchExample() {
const frameworks = [
{ name: 'React - UI library by Facebook', value: 'react' },
{ name: 'Vue.js - Progressive JavaScript framework', value: 'vue' },
{ name: 'Angular - Platform for building web apps', value: 'angular' },
{ name: 'Svelte - Cybernetically enhanced web apps', value: 'svelte' },
{ name: 'Next.js - React framework with SSR', value: 'next' },
{ name: 'Nuxt.js - Vue.js framework with SSR', value: 'nuxt' },
{ name: 'Remix - Full stack web framework', value: 'remix' },
{ name: 'SvelteKit - Svelte framework', value: 'sveltekit' },
{ name: 'Express - Fast Node.js web framework', value: 'express' },
{ name: 'Fastify - Fast and low overhead web framework', value: 'fastify' },
{ name: 'NestJS - Progressive Node.js framework', value: 'nestjs' },
{ name: 'Koa - Expressive middleware for Node.js', value: 'koa' }
];
const answer = await inquirer.prompt([
{
type: 'autocomplete',
name: 'framework',
message: 'Search for a framework:',
source: (answersSoFar, input) => {
const filtered = fuzzySearch(input, frameworks);
return Promise.resolve(filtered);
},
pageSize: 10
}
]);
console.log(`\n✅ Selected: ${answer.framework}`);
return answer;
}
// Example: Command search with categories
async function commandSearchExample() {
const commands = [
{ name: '📦 install - Install dependencies', value: 'install' },
{ name: '🚀 start - Start development server', value: 'start' },
{ name: '🏗️ build - Build for production', value: 'build' },
{ name: '🧪 test - Run tests', value: 'test' },
{ name: '🔍 lint - Check code quality', value: 'lint' },
{ name: '✨ format - Format code', value: 'format' },
{ name: '📝 generate - Generate files', value: 'generate' },
{ name: '🔄 update - Update dependencies', value: 'update' },
{ name: '🧹 clean - Clean build artifacts', value: 'clean' },
{ name: '🚢 deploy - Deploy application', value: 'deploy' },
{ name: '📊 analyze - Analyze bundle size', value: 'analyze' },
{ name: '🐛 debug - Start debugger', value: 'debug' }
];
const answer = await inquirer.prompt([
{
type: 'autocomplete',
name: 'command',
message: 'Search for a command:',
source: (answersSoFar, input) => {
return Promise.resolve(fuzzySearch(input, commands));
},
pageSize: 12
}
]);
console.log(`\n✅ Running: ${answer.command}`);
return answer;
}
// Example: Dynamic API search (simulated)
async function apiSearchExample() {
console.log('\n🔍 API Endpoint Search\n');
const answer = await inquirer.prompt([
{
type: 'autocomplete',
name: 'endpoint',
message: 'Search API endpoints:',
source: async (answersSoFar, input) => {
// Simulate API call
await new Promise(resolve => setTimeout(resolve, 100));
const endpoints = [
{ name: 'GET /users - List all users', value: '/users' },
{ name: 'GET /users/:id - Get user by ID', value: '/users/:id' },
{ name: 'POST /users - Create new user', value: '/users' },
{ name: 'PUT /users/:id - Update user', value: '/users/:id' },
{ name: 'DELETE /users/:id - Delete user', value: '/users/:id' },
{ name: 'GET /posts - List all posts', value: '/posts' },
{ name: 'GET /posts/:id - Get post by ID', value: '/posts/:id' },
{ name: 'POST /posts - Create new post', value: '/posts' },
{ name: 'GET /comments - List comments', value: '/comments' },
{ name: 'POST /auth/login - User login', value: '/auth/login' },
{ name: 'POST /auth/register - User registration', value: '/auth/register' },
{ name: 'POST /auth/logout - User logout', value: '/auth/logout' }
];
return fuzzySearch(input, endpoints);
},
pageSize: 10
}
]);
console.log(`\n✅ Selected endpoint: ${answer.endpoint}`);
return answer;
}
// Run if executed directly
if (import.meta.url === `file://${process.argv[1]}`) {
(async () => {
console.log('=== Autocomplete Examples ===\n');
console.log('1. Country & Package Selection');
await autocompletePromptExample();
console.log('\n2. Framework Search');
await frameworkSearchExample();
console.log('\n3. Command Search');
await commandSearchExample();
console.log('\n4. API Endpoint Search');
await apiSearchExample();
process.exit(0);
})().catch((error) => {
if (error.isTtyError) {
console.error('❌ Prompt could not be rendered in this environment');
} else {
console.error('❌ User interrupted prompt');
}
process.exit(1);
});
}
export { autocompletePromptExample, frameworkSearchExample, commandSearchExample, apiSearchExample };

View File

@@ -0,0 +1,140 @@
/**
* Checkbox Prompt Template
*
* Use for: Multiple selections from options
* Features: Space to toggle, Enter to confirm
*/
import inquirer from 'inquirer';
async function checkboxPromptExample() {
const answers = await inquirer.prompt([
{
type: 'checkbox',
name: 'features',
message: 'Select features to include:',
choices: [
'Authentication',
'Authorization',
'Database Integration',
'API Documentation',
'Testing Suite',
'CI/CD Pipeline',
'Monitoring',
'Logging'
],
validate: (choices) => {
if (choices.length === 0) {
return 'You must select at least one feature';
}
return true;
}
},
{
type: 'checkbox',
name: 'tools',
message: 'Select development tools:',
choices: [
{ name: 'ESLint (Linting)', value: 'eslint', checked: true },
{ name: 'Prettier (Formatting)', value: 'prettier', checked: true },
{ name: 'Jest (Testing)', value: 'jest' },
{ name: 'Husky (Git Hooks)', value: 'husky' },
{ name: 'TypeDoc (Documentation)', value: 'typedoc' },
{ name: 'Webpack (Bundling)', value: 'webpack' }
]
},
{
type: 'checkbox',
name: 'plugins',
message: 'Select plugins to install:',
choices: [
new inquirer.Separator('=== Essential ==='),
{ name: 'dotenv - Environment variables', value: 'dotenv', checked: true },
{ name: 'axios - HTTP client', value: 'axios', checked: true },
new inquirer.Separator('=== Utilities ==='),
{ name: 'lodash - Utility functions', value: 'lodash' },
{ name: 'dayjs - Date manipulation', value: 'dayjs' },
{ name: 'uuid - Unique IDs', value: 'uuid' },
new inquirer.Separator('=== Validation ==='),
{ name: 'joi - Schema validation', value: 'joi' },
{ name: 'zod - TypeScript-first validation', value: 'zod' },
new inquirer.Separator('=== Advanced ==='),
{ name: 'bull - Job queues', value: 'bull' },
{ name: 'socket.io - WebSockets', value: 'socket.io' }
],
pageSize: 15,
validate: (choices) => {
if (choices.length > 10) {
return 'Please select no more than 10 plugins to avoid bloat';
}
return true;
}
},
{
type: 'checkbox',
name: 'permissions',
message: 'Grant the following permissions:',
choices: [
{ name: '📁 Read files', value: 'read', checked: true },
{ name: '✏️ Write files', value: 'write' },
{ name: '🗑️ Delete files', value: 'delete' },
{ name: '🌐 Network access', value: 'network', checked: true },
{ name: '🖥️ System commands', value: 'system' },
{ name: '🔒 Keychain access', value: 'keychain' }
],
validate: (choices) => {
if (choices.includes('delete') && !choices.includes('write')) {
return 'Delete permission requires write permission';
}
return true;
}
},
{
type: 'checkbox',
name: 'environments',
message: 'Select deployment environments:',
choices: [
{ name: 'Development', value: 'dev', checked: true },
{ name: 'Staging', value: 'staging' },
{ name: 'Production', value: 'prod' },
{ name: 'Testing', value: 'test', checked: true }
],
validate: (choices) => {
if (!choices.includes('dev')) {
return 'Development environment is required';
}
if (choices.includes('prod') && !choices.includes('staging')) {
return 'Staging environment is recommended before production';
}
return true;
}
}
]);
console.log('\n✅ Selected options:');
console.log(JSON.stringify(answers, null, 2));
// Example: Process selections
console.log('\n📦 Installing selected features...');
answers.features.forEach(feature => {
console.log(` - ${feature}`);
});
return answers;
}
// Run if executed directly
if (import.meta.url === `file://${process.argv[1]}`) {
checkboxPromptExample()
.then(() => process.exit(0))
.catch((error) => {
if (error.isTtyError) {
console.error('❌ Prompt could not be rendered in this environment');
} else {
console.error('❌ User interrupted prompt');
}
process.exit(1);
});
}
export { checkboxPromptExample };

View File

@@ -0,0 +1,456 @@
/**
* Comprehensive CLI Example
*
* Complete project initialization wizard combining all prompt types:
* - Text input with validation
* - List selections
* - Checkbox selections
* - Password input
* - Autocomplete (optional)
* - Conditional logic
*/
import inquirer from 'inquirer';
async function projectInitWizard() {
console.log(`
╔═══════════════════════════════════════════════════════════╗
║ ║
║ 🚀 Project Initialization Wizard 🚀 ║
║ ║
╚═══════════════════════════════════════════════════════════╝
`);
const config = await inquirer.prompt([
// === PROJECT BASICS ===
{
type: 'input',
name: 'projectName',
message: '📦 Project name:',
validate: (input) => {
if (input.length === 0) return 'Project name is required';
if (!/^[a-z0-9-_]+$/.test(input)) {
return 'Use lowercase letters, numbers, hyphens, and underscores only';
}
if (input.length < 3) return 'Project name must be at least 3 characters';
return true;
},
transformer: (input) => input.toLowerCase()
},
{
type: 'input',
name: 'description',
message: '📝 Project description:',
validate: (input) => input.length > 0 || 'Description is required'
},
{
type: 'input',
name: 'version',
message: '🏷️ Initial version:',
default: '0.1.0',
validate: (input) => {
return /^\d+\.\d+\.\d+$/.test(input) || 'Use semantic versioning (e.g., 0.1.0)';
}
},
{
type: 'input',
name: 'author',
message: '👤 Author name:',
default: process.env.USER || ''
},
{
type: 'input',
name: 'email',
message: '📧 Author email:',
validate: (input) => {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(input) || 'Invalid email address';
}
},
{
type: 'list',
name: 'license',
message: '📜 License:',
choices: ['MIT', 'Apache-2.0', 'GPL-3.0', 'BSD-3-Clause', 'ISC', 'Unlicensed'],
default: 'MIT'
},
// === TECHNOLOGY STACK ===
{
type: 'list',
name: 'projectType',
message: '🛠️ Project type:',
choices: [
'Web Application',
'CLI Tool',
'API/Backend',
'Library/Package',
'Desktop Application',
'Mobile Application'
]
},
{
type: 'list',
name: 'language',
message: '💻 Programming language:',
choices: [
{ name: 'TypeScript (Recommended)', value: 'typescript', short: 'TS' },
{ name: 'JavaScript', value: 'javascript', short: 'JS' },
{ name: 'Python', value: 'python', short: 'Py' },
{ name: 'Go', value: 'go', short: 'Go' },
{ name: 'Rust', value: 'rust', short: 'Rust' }
]
},
{
type: 'list',
name: 'framework',
message: '🎨 Framework/Runtime:',
choices: (answers) => {
const frameworks = {
typescript: ['Next.js', 'Remix', 'Nest.js', 'Express', 'Fastify', 'Node.js'],
javascript: ['React', 'Vue', 'Svelte', 'Express', 'Fastify', 'Node.js'],
python: ['FastAPI', 'Django', 'Flask', 'Tornado', 'Sanic'],
go: ['Gin', 'Echo', 'Fiber', 'Standard library'],
rust: ['Actix', 'Rocket', 'Axum', 'Warp']
};
return frameworks[answers.language] || ['None'];
}
},
// === FEATURES & TOOLS ===
{
type: 'checkbox',
name: 'features',
message: '✨ Select features:',
choices: (answers) => {
const baseFeatures = [
{ name: 'Environment variables (.env)', value: 'env', checked: true },
{ name: 'Configuration management', value: 'config', checked: true },
{ name: 'Logging', value: 'logging', checked: true },
{ name: 'Error handling', value: 'error-handling', checked: true }
];
if (answers.projectType === 'Web Application' || answers.projectType === 'API/Backend') {
baseFeatures.push(
{ name: 'Authentication', value: 'auth' },
{ name: 'Database integration', value: 'database' },
{ name: 'API documentation', value: 'api-docs' },
{ name: 'CORS handling', value: 'cors' }
);
}
if (answers.projectType === 'CLI Tool') {
baseFeatures.push(
{ name: 'Command-line arguments parser', value: 'cli-parser', checked: true },
{ name: 'Interactive prompts', value: 'prompts', checked: true },
{ name: 'Progress bars', value: 'progress' }
);
}
return baseFeatures;
},
validate: (choices) => choices.length > 0 || 'Select at least one feature'
},
{
type: 'checkbox',
name: 'devTools',
message: '🔧 Development tools:',
choices: (answers) => {
const tools = [];
if (['typescript', 'javascript'].includes(answers.language)) {
tools.push(
{ name: 'ESLint - Linting', value: 'eslint', checked: true },
{ name: 'Prettier - Code formatting', value: 'prettier', checked: true },
{ name: 'Husky - Git hooks', value: 'husky' },
{ name: 'Jest - Testing framework', value: 'jest', checked: true },
{ name: 'TypeDoc/JSDoc - Documentation', value: 'docs' }
);
} else if (answers.language === 'python') {
tools.push(
{ name: 'Black - Code formatting', value: 'black', checked: true },
{ name: 'Flake8 - Linting', value: 'flake8', checked: true },
{ name: 'mypy - Type checking', value: 'mypy' },
{ name: 'pytest - Testing framework', value: 'pytest', checked: true },
{ name: 'Sphinx - Documentation', value: 'sphinx' }
);
}
return tools;
},
default: ['eslint', 'prettier', 'jest']
},
// === DATABASE CONFIGURATION ===
{
type: 'confirm',
name: 'useDatabase',
message: '🗄️ Use database?',
default: (answers) => {
return answers.features.includes('database') ||
['Web Application', 'API/Backend'].includes(answers.projectType);
},
when: (answers) => ['Web Application', 'API/Backend', 'CLI Tool'].includes(answers.projectType)
},
{
type: 'list',
name: 'databaseType',
message: '📊 Database type:',
choices: [
{ name: '🐘 PostgreSQL (Relational)', value: 'postgresql' },
{ name: '🐬 MySQL (Relational)', value: 'mysql' },
{ name: '🍃 MongoDB (Document)', value: 'mongodb' },
{ name: '⚡ Redis (Key-Value)', value: 'redis' },
{ name: '📁 SQLite (Embedded)', value: 'sqlite' },
{ name: '🔥 Supabase (PostgreSQL + APIs)', value: 'supabase' }
],
when: (answers) => answers.useDatabase
},
{
type: 'list',
name: 'databaseORM',
message: '🔗 ORM/Database client:',
choices: (answers) => {
const orms = {
typescript: {
postgresql: ['Prisma', 'TypeORM', 'Kysely', 'Drizzle'],
mysql: ['Prisma', 'TypeORM', 'Kysely', 'Drizzle'],
mongodb: ['Mongoose', 'Prisma', 'TypeORM'],
sqlite: ['Prisma', 'TypeORM', 'Better-SQLite3'],
supabase: ['Supabase Client', 'Prisma']
},
python: {
postgresql: ['SQLAlchemy', 'Django ORM', 'Tortoise ORM'],
mysql: ['SQLAlchemy', 'Django ORM', 'Tortoise ORM'],
mongodb: ['Motor', 'PyMongo', 'MongoEngine'],
sqlite: ['SQLAlchemy', 'Django ORM']
}
};
const lang = answers.language;
const db = answers.databaseType;
return orms[lang]?.[db] || ['None'];
},
when: (answers) => answers.useDatabase && answers.databaseType !== 'redis'
},
// === TESTING CONFIGURATION ===
{
type: 'confirm',
name: 'setupTesting',
message: '🧪 Setup testing?',
default: true
},
{
type: 'checkbox',
name: 'testTypes',
message: '🔬 Test types:',
choices: [
{ name: 'Unit tests', value: 'unit', checked: true },
{ name: 'Integration tests', value: 'integration', checked: true },
{ name: 'E2E tests', value: 'e2e' },
{ name: 'Performance tests', value: 'performance' }
],
when: (answers) => answers.setupTesting
},
// === CI/CD CONFIGURATION ===
{
type: 'confirm',
name: 'setupCICD',
message: '⚙️ Setup CI/CD?',
default: true
},
{
type: 'list',
name: 'cicdProvider',
message: '🔄 CI/CD provider:',
choices: ['GitHub Actions', 'GitLab CI', 'CircleCI', 'Jenkins', 'None'],
when: (answers) => answers.setupCICD
},
// === DEPLOYMENT CONFIGURATION ===
{
type: 'confirm',
name: 'setupDeployment',
message: '🚀 Setup deployment?',
default: (answers) => answers.projectType !== 'Library/Package'
},
{
type: 'list',
name: 'deploymentPlatform',
message: '☁️ Deployment platform:',
choices: (answers) => {
if (answers.projectType === 'Web Application') {
return ['Vercel', 'Netlify', 'AWS', 'Google Cloud', 'Azure', 'Self-hosted'];
} else if (answers.projectType === 'API/Backend') {
return ['AWS', 'Google Cloud', 'Azure', 'DigitalOcean', 'Heroku', 'Self-hosted'];
} else if (answers.projectType === 'CLI Tool') {
return ['npm', 'PyPI', 'Homebrew', 'Binary releases', 'Docker'];
}
return ['AWS', 'Google Cloud', 'Azure', 'Self-hosted'];
},
when: (answers) => answers.setupDeployment
},
{
type: 'confirm',
name: 'useDocker',
message: '🐳 Use Docker?',
default: true,
when: (answers) => {
return answers.setupDeployment &&
!['Vercel', 'Netlify'].includes(answers.deploymentPlatform);
}
},
// === MONITORING & OBSERVABILITY ===
{
type: 'confirm',
name: 'setupMonitoring',
message: '📊 Setup monitoring & observability?',
default: (answers) => answers.projectType !== 'Library/Package'
},
{
type: 'checkbox',
name: 'monitoringTools',
message: '📈 Monitoring tools:',
choices: [
{ name: 'Sentry - Error tracking', value: 'sentry' },
{ name: 'DataDog - Full observability', value: 'datadog' },
{ name: 'Prometheus - Metrics', value: 'prometheus' },
{ name: 'Grafana - Dashboards', value: 'grafana' },
{ name: 'New Relic - APM', value: 'newrelic' }
],
when: (answers) => answers.setupMonitoring
},
// === DOCUMENTATION ===
{
type: 'confirm',
name: 'generateDocs',
message: '📚 Generate documentation?',
default: true
},
{
type: 'checkbox',
name: 'docTypes',
message: '📖 Documentation types:',
choices: [
{ name: 'README.md', value: 'readme', checked: true },
{ name: 'API documentation', value: 'api', checked: true },
{ name: 'Contributing guidelines', value: 'contributing' },
{ name: 'Code of conduct', value: 'coc' },
{ name: 'Changelog', value: 'changelog', checked: true }
],
when: (answers) => answers.generateDocs
},
// === SECURITY ===
{
type: 'confirm',
name: 'securitySetup',
message: '🔒 Setup security features?',
default: true,
when: (answers) => ['Web Application', 'API/Backend'].includes(answers.projectType)
},
{
type: 'checkbox',
name: 'securityFeatures',
message: '🛡️ Security features:',
choices: [
{ name: 'Dependency scanning', value: 'dep-scan', checked: true },
{ name: 'Secret scanning', value: 'secret-scan', checked: true },
{ name: 'HTTPS enforcement', value: 'https' },
{ name: 'Rate limiting', value: 'rate-limit' },
{ name: 'Input validation', value: 'validation', checked: true },
{ name: 'Security headers', value: 'headers' }
],
when: (answers) => answers.securitySetup
},
// === FINAL CONFIRMATION ===
{
type: 'confirm',
name: 'confirm',
message: '✅ Initialize project with these settings?',
default: true
}
]);
if (!config.confirm) {
console.log('\n❌ Project initialization cancelled.\n');
return null;
}
// Display configuration summary
console.log('\n' + '═'.repeat(60));
console.log('📋 PROJECT CONFIGURATION SUMMARY');
console.log('═'.repeat(60) + '\n');
console.log(`📦 Project: ${config.projectName} v${config.version}`);
console.log(`📝 Description: ${config.description}`);
console.log(`👤 Author: ${config.author} <${config.email}>`);
console.log(`📜 License: ${config.license}\n`);
console.log(`💻 Language: ${config.language}`);
console.log(`🎨 Framework: ${config.framework}`);
console.log(`🛠️ Type: ${config.projectType}\n`);
if (config.useDatabase) {
console.log(`🗄️ Database: ${config.databaseType}`);
if (config.databaseORM) {
console.log(`🔗 ORM: ${config.databaseORM}\n`);
}
}
if (config.features.length > 0) {
console.log(`✨ Features: ${config.features.join(', ')}`);
}
if (config.devTools.length > 0) {
console.log(`🔧 Dev Tools: ${config.devTools.join(', ')}\n`);
}
if (config.setupDeployment) {
console.log(`🚀 Deployment: ${config.deploymentPlatform}`);
if (config.useDocker) console.log(`🐳 Docker: Enabled`);
}
if (config.setupCICD) {
console.log(`⚙️ CI/CD: ${config.cicdProvider}`);
}
console.log('\n' + '═'.repeat(60) + '\n');
console.log('🎉 Configuration complete! Initializing project...\n');
// Here you would actually create the project files
// This is just a demonstration
return config;
}
// Run if executed directly
if (import.meta.url === `file://${process.argv[1]}`) {
projectInitWizard()
.then((config) => {
if (config) {
console.log('✅ Project initialized successfully!\n');
console.log('Next steps:');
console.log(` 1. cd ${config.projectName}`);
console.log(' 2. Install dependencies');
console.log(' 3. Start development');
}
process.exit(0);
})
.catch((error) => {
if (error.isTtyError) {
console.error('❌ Prompt could not be rendered in this environment');
} else {
console.error('❌ User interrupted prompt');
}
process.exit(1);
});
}
export { projectInitWizard };

View File

@@ -0,0 +1,460 @@
/**
* Conditional Prompt Template
*
* Use for: Dynamic forms based on previous answers
* Features: Skip logic, dependent questions, branching
*/
import inquirer from 'inquirer';
async function conditionalPromptExample() {
const answers = await inquirer.prompt([
{
type: 'confirm',
name: 'useDatabase',
message: 'Do you want to use a database?',
default: true
},
{
type: 'list',
name: 'databaseType',
message: 'Select database type:',
choices: ['PostgreSQL', 'MySQL', 'MongoDB', 'SQLite', 'Redis'],
when: (answers) => answers.useDatabase
},
{
type: 'input',
name: 'databaseHost',
message: 'Database host:',
default: 'localhost',
when: (answers) => {
return answers.useDatabase && answers.databaseType !== 'SQLite';
}
},
{
type: 'input',
name: 'databasePort',
message: 'Database port:',
default: (answers) => {
const ports = {
'PostgreSQL': '5432',
'MySQL': '3306',
'MongoDB': '27017',
'Redis': '6379'
};
return ports[answers.databaseType] || '5432';
},
when: (answers) => {
return answers.useDatabase && answers.databaseType !== 'SQLite';
}
},
{
type: 'input',
name: 'databaseName',
message: 'Database name:',
when: (answers) => answers.useDatabase,
validate: (input) => input.length > 0 || 'Database name required'
},
{
type: 'confirm',
name: 'useAuthentication',
message: 'Do you want to use authentication?',
default: true,
when: (answers) => answers.useDatabase
},
{
type: 'input',
name: 'databaseUsername',
message: 'Database username:',
when: (answers) => answers.useDatabase && answers.useAuthentication,
validate: (input) => input.length > 0 || 'Username required'
},
{
type: 'password',
name: 'databasePassword',
message: 'Database password:',
mask: '*',
when: (answers) => answers.useDatabase && answers.useAuthentication
},
{
type: 'confirm',
name: 'useSSL',
message: 'Use SSL connection?',
default: false,
when: (answers) => {
return answers.useDatabase &&
answers.databaseType !== 'SQLite' &&
answers.databaseHost !== 'localhost';
}
},
{
type: 'input',
name: 'sslCertPath',
message: 'Path to SSL certificate:',
when: (answers) => answers.useSSL,
validate: (input) => input.length > 0 || 'SSL certificate path required'
}
]);
console.log('\n✅ Configuration:');
console.log(JSON.stringify(answers, null, 2));
return answers;
}
// Example: Deployment configuration wizard
async function deploymentWizard() {
console.log('\n🚀 Deployment Configuration Wizard\n');
const config = await inquirer.prompt([
{
type: 'list',
name: 'environment',
message: 'Select deployment environment:',
choices: ['Development', 'Staging', 'Production']
},
{
type: 'confirm',
name: 'useDocker',
message: 'Deploy using Docker?',
default: true
},
{
type: 'input',
name: 'dockerImage',
message: 'Docker image name:',
when: (answers) => answers.useDocker,
default: 'myapp:latest',
validate: (input) => /^[a-z0-9-_/:.]+$/.test(input) || 'Invalid Docker image name'
},
{
type: 'list',
name: 'registry',
message: 'Container registry:',
choices: ['Docker Hub', 'GitHub Container Registry', 'AWS ECR', 'Google Artifact Registry'],
when: (answers) => answers.useDocker
},
{
type: 'list',
name: 'platform',
message: 'Deployment platform:',
choices: ['AWS', 'Google Cloud', 'Azure', 'DigitalOcean', 'Vercel', 'Netlify', 'Self-hosted']
},
{
type: 'list',
name: 'awsService',
message: 'AWS service:',
choices: ['ECS', 'EKS', 'Lambda', 'Elastic Beanstalk', 'EC2'],
when: (answers) => answers.platform === 'AWS'
},
{
type: 'list',
name: 'gcpService',
message: 'Google Cloud service:',
choices: ['Cloud Run', 'GKE', 'App Engine', 'Compute Engine'],
when: (answers) => answers.platform === 'Google Cloud'
},
{
type: 'confirm',
name: 'autoScale',
message: 'Enable auto-scaling?',
default: true,
when: (answers) => {
const scalableServices = ['ECS', 'EKS', 'Cloud Run', 'GKE'];
return scalableServices.includes(answers.awsService) ||
scalableServices.includes(answers.gcpService);
}
},
{
type: 'input',
name: 'minInstances',
message: 'Minimum instances:',
default: '1',
when: (answers) => answers.autoScale,
validate: (input) => {
const num = parseInt(input);
return num > 0 || 'Must be at least 1';
}
},
{
type: 'input',
name: 'maxInstances',
message: 'Maximum instances:',
default: '10',
when: (answers) => answers.autoScale,
validate: (input, answers) => {
const num = parseInt(input);
const min = parseInt(answers.minInstances);
return num >= min || `Must be at least ${min}`;
}
},
{
type: 'confirm',
name: 'useCDN',
message: 'Use CDN for static assets?',
default: true,
when: (answers) => answers.environment === 'Production'
},
{
type: 'list',
name: 'cdnProvider',
message: 'CDN provider:',
choices: ['CloudFlare', 'AWS CloudFront', 'Google Cloud CDN', 'Azure CDN'],
when: (answers) => answers.useCDN
},
{
type: 'confirm',
name: 'setupMonitoring',
message: 'Setup monitoring?',
default: true
},
{
type: 'checkbox',
name: 'monitoringTools',
message: 'Select monitoring tools:',
choices: ['Prometheus', 'Grafana', 'Datadog', 'New Relic', 'Sentry'],
when: (answers) => answers.setupMonitoring,
validate: (choices) => choices.length > 0 || 'Select at least one tool'
}
]);
console.log('\n✅ Deployment configuration complete!');
console.log(JSON.stringify(config, null, 2));
return config;
}
// Example: Feature flag configuration
async function featureFlagWizard() {
console.log('\n🎛 Feature Flag Configuration\n');
const config = await inquirer.prompt([
{
type: 'input',
name: 'featureName',
message: 'Feature name:',
validate: (input) => /^[a-z-_]+$/.test(input) || 'Use lowercase, hyphens, underscores only'
},
{
type: 'confirm',
name: 'enabledByDefault',
message: 'Enabled by default?',
default: false
},
{
type: 'list',
name: 'rolloutStrategy',
message: 'Rollout strategy:',
choices: [
'All users',
'Percentage rollout',
'User targeting',
'Beta users only',
'Manual control'
]
},
{
type: 'input',
name: 'rolloutPercentage',
message: 'Rollout percentage (0-100):',
when: (answers) => answers.rolloutStrategy === 'Percentage rollout',
default: '10',
validate: (input) => {
const num = parseInt(input);
return (num >= 0 && num <= 100) || 'Must be between 0 and 100';
}
},
{
type: 'checkbox',
name: 'targetUserGroups',
message: 'Target user groups:',
choices: ['Beta testers', 'Premium users', 'Internal team', 'Early adopters', 'Specific regions'],
when: (answers) => answers.rolloutStrategy === 'User targeting',
validate: (choices) => choices.length > 0 || 'Select at least one group'
},
{
type: 'checkbox',
name: 'targetRegions',
message: 'Target regions:',
choices: ['North America', 'Europe', 'Asia Pacific', 'South America', 'Africa'],
when: (answers) => {
return answers.rolloutStrategy === 'User targeting' &&
answers.targetUserGroups.includes('Specific regions');
}
},
{
type: 'confirm',
name: 'enableMetrics',
message: 'Track feature usage metrics?',
default: true
},
{
type: 'checkbox',
name: 'metrics',
message: 'Select metrics to track:',
choices: [
'Usage count',
'User adoption rate',
'Performance impact',
'Error rate',
'User feedback'
],
when: (answers) => answers.enableMetrics
},
{
type: 'confirm',
name: 'addExpirationDate',
message: 'Set feature flag expiration?',
default: false
},
{
type: 'input',
name: 'expirationDate',
message: 'Expiration date (YYYY-MM-DD):',
when: (answers) => answers.addExpirationDate,
validate: (input) => {
const date = new Date(input);
if (isNaN(date.getTime())) return 'Invalid date format';
if (date < new Date()) return 'Date must be in the future';
return true;
}
}
]);
console.log('\n✅ Feature flag configured!');
console.log(JSON.stringify(config, null, 2));
return config;
}
// Example: CI/CD pipeline setup
async function cicdPipelineWizard() {
console.log('\n⚙ CI/CD Pipeline Configuration\n');
const config = await inquirer.prompt([
{
type: 'list',
name: 'provider',
message: 'CI/CD provider:',
choices: ['GitHub Actions', 'GitLab CI', 'CircleCI', 'Jenkins', 'Travis CI']
},
{
type: 'checkbox',
name: 'triggers',
message: 'Pipeline triggers:',
choices: [
'Push to main/master',
'Pull request',
'Tag creation',
'Manual trigger',
'Scheduled (cron)'
],
default: ['Push to main/master', 'Pull request']
},
{
type: 'input',
name: 'cronSchedule',
message: 'Cron schedule:',
when: (answers) => answers.triggers.includes('Scheduled (cron)'),
default: '0 2 * * *',
validate: (input) => {
// Basic cron validation
const parts = input.split(' ');
return parts.length === 5 || 'Invalid cron format (5 parts required)';
}
},
{
type: 'checkbox',
name: 'stages',
message: 'Pipeline stages:',
choices: ['Build', 'Test', 'Lint', 'Security scan', 'Deploy'],
default: ['Build', 'Test', 'Deploy'],
validate: (choices) => choices.length > 0 || 'Select at least one stage'
},
{
type: 'checkbox',
name: 'testTypes',
message: 'Test types to run:',
choices: ['Unit tests', 'Integration tests', 'E2E tests', 'Performance tests'],
when: (answers) => answers.stages.includes('Test')
},
{
type: 'checkbox',
name: 'securityTools',
message: 'Security scanning tools:',
choices: ['Snyk', 'Dependabot', 'SonarQube', 'OWASP Dependency Check'],
when: (answers) => answers.stages.includes('Security scan')
},
{
type: 'checkbox',
name: 'deployEnvironments',
message: 'Deployment environments:',
choices: ['Development', 'Staging', 'Production'],
when: (answers) => answers.stages.includes('Deploy'),
default: ['Staging', 'Production']
},
{
type: 'confirm',
name: 'requireApproval',
message: 'Require manual approval for production?',
default: true,
when: (answers) => {
return answers.stages.includes('Deploy') &&
answers.deployEnvironments?.includes('Production');
}
},
{
type: 'confirm',
name: 'enableNotifications',
message: 'Enable build notifications?',
default: true
},
{
type: 'checkbox',
name: 'notificationChannels',
message: 'Notification channels:',
choices: ['Email', 'Slack', 'Discord', 'Microsoft Teams'],
when: (answers) => answers.enableNotifications
}
]);
console.log('\n✅ CI/CD pipeline configured!');
console.log(JSON.stringify(config, null, 2));
return config;
}
// Run if executed directly
if (import.meta.url === `file://${process.argv[1]}`) {
(async () => {
console.log('=== Conditional Prompt Examples ===\n');
console.log('1. Database Configuration');
await conditionalPromptExample();
console.log('\n2. Deployment Wizard');
await deploymentWizard();
console.log('\n3. Feature Flag Configuration');
await featureFlagWizard();
console.log('\n4. CI/CD Pipeline Setup');
await cicdPipelineWizard();
process.exit(0);
})().catch((error) => {
if (error.isTtyError) {
console.error('❌ Prompt could not be rendered in this environment');
} else {
console.error('❌ User interrupted prompt');
}
process.exit(1);
});
}
export {
conditionalPromptExample,
deploymentWizard,
featureFlagWizard,
cicdPipelineWizard
};

View File

@@ -0,0 +1,104 @@
/**
* List Selection Prompt Template
*
* Use for: Single choice from predefined options
* Features: Arrow key navigation, search filtering
*/
import inquirer from 'inquirer';
async function listPromptExample() {
const answers = await inquirer.prompt([
{
type: 'list',
name: 'framework',
message: 'Choose your preferred framework:',
choices: [
'React',
'Vue',
'Angular',
'Svelte',
'Next.js',
'Nuxt.js'
],
default: 'React'
},
{
type: 'list',
name: 'language',
message: 'Choose programming language:',
choices: [
{ name: 'JavaScript', value: 'js' },
{ name: 'TypeScript', value: 'ts' },
{ name: 'Python', value: 'py' },
{ name: 'Ruby', value: 'rb' },
{ name: 'Go', value: 'go' }
],
default: 'ts'
},
{
type: 'list',
name: 'packageManager',
message: 'Choose package manager:',
choices: [
{ name: 'npm (Node Package Manager)', value: 'npm', short: 'npm' },
{ name: 'yarn (Fast, reliable package manager)', value: 'yarn', short: 'yarn' },
{ name: 'pnpm (Fast, disk space efficient)', value: 'pnpm', short: 'pnpm' },
{ name: 'bun (All-in-one toolkit)', value: 'bun', short: 'bun' }
]
},
{
type: 'list',
name: 'environment',
message: 'Select deployment environment:',
choices: [
new inquirer.Separator('--- Cloud Platforms ---'),
'AWS',
'Google Cloud',
'Azure',
new inquirer.Separator('--- Serverless ---'),
'Vercel',
'Netlify',
'Cloudflare Workers',
new inquirer.Separator('--- Self-hosted ---'),
'Docker',
'Kubernetes'
]
},
{
type: 'list',
name: 'database',
message: 'Choose database:',
choices: [
{ name: '🐘 PostgreSQL (Relational)', value: 'postgresql' },
{ name: '🐬 MySQL (Relational)', value: 'mysql' },
{ name: '🍃 MongoDB (Document)', value: 'mongodb' },
{ name: '⚡ Redis (Key-Value)', value: 'redis' },
{ name: '📊 SQLite (Embedded)', value: 'sqlite' },
{ name: '🔥 Supabase (PostgreSQL + APIs)', value: 'supabase' }
],
pageSize: 10
}
]);
console.log('\n✅ Selections:');
console.log(JSON.stringify(answers, null, 2));
return answers;
}
// Run if executed directly
if (import.meta.url === `file://${process.argv[1]}`) {
listPromptExample()
.then(() => process.exit(0))
.catch((error) => {
if (error.isTtyError) {
console.error('❌ Prompt could not be rendered in this environment');
} else {
console.error('❌ User interrupted prompt');
}
process.exit(1);
});
}
export { listPromptExample };

View File

@@ -0,0 +1,208 @@
/**
* Password Prompt Template
*
* Use for: Sensitive input (credentials, tokens)
* Features: Hidden input, confirmation, validation
*/
import inquirer from 'inquirer';
async function passwordPromptExample() {
const answers = await inquirer.prompt([
{
type: 'password',
name: 'password',
message: 'Enter your password:',
mask: '*',
validate: (input) => {
if (input.length < 8) {
return 'Password must be at least 8 characters';
}
if (!/[A-Z]/.test(input)) {
return 'Password must contain at least one uppercase letter';
}
if (!/[a-z]/.test(input)) {
return 'Password must contain at least one lowercase letter';
}
if (!/[0-9]/.test(input)) {
return 'Password must contain at least one number';
}
if (!/[!@#$%^&*(),.?":{}|<>]/.test(input)) {
return 'Password must contain at least one special character';
}
return true;
}
},
{
type: 'password',
name: 'confirmPassword',
message: 'Confirm your password:',
mask: '*',
validate: (input, answers) => {
if (input !== answers.password) {
return 'Passwords do not match';
}
return true;
}
},
{
type: 'password',
name: 'apiKey',
message: 'Enter your API key:',
mask: '•',
validate: (input) => {
if (input.length === 0) {
return 'API key is required';
}
// Example: Validate API key format (e.g., sk-...)
if (!input.startsWith('sk-') && !input.startsWith('pk-')) {
return 'API key must start with "sk-" or "pk-"';
}
if (input.length < 32) {
return 'API key appears to be too short';
}
return true;
}
},
{
type: 'password',
name: 'oldPassword',
message: 'Enter your old password (for password change):',
mask: '*',
when: (answers) => {
// Only ask for old password if changing password
return answers.password && answers.confirmPassword;
},
validate: (input) => {
if (input.length === 0) {
return 'Old password is required';
}
// In real app, you'd verify against stored password
return true;
}
},
{
type: 'password',
name: 'encryptionKey',
message: 'Enter encryption key (optional):',
mask: '#',
validate: (input) => {
if (input.length === 0) return true; // Optional
if (input.length < 16) {
return 'Encryption key must be at least 16 characters';
}
return true;
}
}
]);
// Don't log actual passwords!
console.log('\n✅ Credentials received (not displayed for security)');
console.log('Password strength:', calculatePasswordStrength(answers.password));
console.log('API key format:', answers.apiKey.substring(0, 6) + '...');
// In real app, you'd:
// - Hash the password before storing
// - Encrypt the API key
// - Store securely (not in plain text)
return {
passwordHash: hashPassword(answers.password),
apiKeyEncrypted: encryptApiKey(answers.apiKey)
};
}
// Helper function to calculate password strength
function calculatePasswordStrength(password) {
let strength = 0;
if (password.length >= 8) strength++;
if (password.length >= 12) strength++;
if (/[a-z]/.test(password)) strength++;
if (/[A-Z]/.test(password)) strength++;
if (/[0-9]/.test(password)) strength++;
if (/[!@#$%^&*(),.?":{}|<>]/.test(password)) strength++;
const levels = ['Very Weak', 'Weak', 'Fair', 'Good', 'Strong', 'Very Strong'];
return levels[Math.min(strength, levels.length - 1)];
}
// Placeholder for password hashing (use bcrypt in production)
function hashPassword(password) {
return `[HASHED:${password.length}_chars]`;
}
// Placeholder for API key encryption (use proper encryption in production)
function encryptApiKey(apiKey) {
return `[ENCRYPTED:${apiKey.substring(0, 6)}...]`;
}
// Example: Secure credential storage
async function securePasswordExample() {
console.log('\n🔐 Secure Password Setup\n');
const credentials = await inquirer.prompt([
{
type: 'input',
name: 'username',
message: 'Username:',
validate: (input) => input.length > 0 || 'Username required'
},
{
type: 'password',
name: 'password',
message: 'Password:',
mask: '*',
validate: (input) => {
const issues = [];
if (input.length < 12) issues.push('at least 12 characters');
if (!/[A-Z]/.test(input)) issues.push('an uppercase letter');
if (!/[a-z]/.test(input)) issues.push('a lowercase letter');
if (!/[0-9]/.test(input)) issues.push('a number');
if (!/[!@#$%^&*]/.test(input)) issues.push('a special character (!@#$%^&*)');
if (issues.length > 0) {
return `Password must contain: ${issues.join(', ')}`;
}
return true;
}
},
{
type: 'password',
name: 'confirm',
message: 'Confirm password:',
mask: '*',
validate: (input, answers) => {
return input === answers.password || 'Passwords do not match';
}
},
{
type: 'confirm',
name: 'remember',
message: 'Remember credentials? (stored securely)',
default: false
}
]);
console.log(`\n✅ Account created for: ${credentials.username}`);
console.log(`🔒 Password strength: ${calculatePasswordStrength(credentials.password)}`);
return credentials;
}
// Run if executed directly
if (import.meta.url === `file://${process.argv[1]}`) {
passwordPromptExample()
.then(() => securePasswordExample())
.then(() => process.exit(0))
.catch((error) => {
if (error.isTtyError) {
console.error('❌ Prompt could not be rendered in this environment');
} else {
console.error('❌ User interrupted prompt');
}
process.exit(1);
});
}
export { passwordPromptExample, securePasswordExample };

View File

@@ -0,0 +1,105 @@
/**
* Text Input Prompt Template
*
* Use for: Names, emails, URLs, paths, free-form text
* Features: Validation, default values, transform
*/
import inquirer from 'inquirer';
async function textPromptExample() {
const answers = await inquirer.prompt([
{
type: 'input',
name: 'username',
message: 'Enter your username:',
default: '',
validate: (input) => {
if (input.length === 0) {
return 'Username is required';
}
if (input.length < 3) {
return 'Username must be at least 3 characters';
}
if (!/^[a-zA-Z0-9_-]+$/.test(input)) {
return 'Username can only contain letters, numbers, hyphens, and underscores';
}
return true;
},
transformer: (input) => {
return input.toLowerCase();
}
},
{
type: 'input',
name: 'email',
message: 'Enter your email:',
validate: (input) => {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(input) || 'Invalid email address';
}
},
{
type: 'input',
name: 'website',
message: 'Enter your website (optional):',
default: '',
validate: (input) => {
if (input.length === 0) return true; // Optional field
const urlRegex = /^https?:\/\/.+/;
return urlRegex.test(input) || 'Must be a valid URL (http:// or https://)';
}
},
{
type: 'input',
name: 'age',
message: 'Enter your age:',
validate: (input) => {
const age = parseInt(input);
if (isNaN(age)) {
return 'Please enter a valid number';
}
if (age < 18) {
return 'You must be at least 18 years old';
}
if (age > 120) {
return 'Please enter a realistic age';
}
return true;
},
filter: (input) => parseInt(input)
},
{
type: 'input',
name: 'bio',
message: 'Enter a short bio:',
validate: (input) => {
if (input.length > 200) {
return 'Bio must be 200 characters or less';
}
return true;
}
}
]);
console.log('\n✅ Answers received:');
console.log(JSON.stringify(answers, null, 2));
return answers;
}
// Run if executed directly
if (import.meta.url === `file://${process.argv[1]}`) {
textPromptExample()
.then(() => process.exit(0))
.catch((error) => {
if (error.isTtyError) {
console.error('❌ Prompt could not be rendered in this environment');
} else {
console.error('❌ User interrupted prompt');
}
process.exit(1);
});
}
export { textPromptExample };

View File

@@ -0,0 +1,361 @@
"""
Autocomplete Prompt Template
Use for: Large option lists with search
Features: Type-ahead, fuzzy matching, suggestions
"""
import questionary
from questionary import Choice
# Example: Countries list for autocomplete
COUNTRIES = [
'Afghanistan', 'Albania', 'Algeria', 'Andorra', 'Angola',
'Argentina', 'Armenia', 'Australia', 'Austria', 'Azerbaijan',
'Bahamas', 'Bahrain', 'Bangladesh', 'Barbados', 'Belarus',
'Belgium', 'Belize', 'Benin', 'Bhutan', 'Bolivia',
'Brazil', 'Brunei', 'Bulgaria', 'Burkina Faso', 'Burundi',
'Cambodia', 'Cameroon', 'Canada', 'Cape Verde', 'Chad',
'Chile', 'China', 'Colombia', 'Comoros', 'Congo',
'Costa Rica', 'Croatia', 'Cuba', 'Cyprus', 'Czech Republic',
'Denmark', 'Djibouti', 'Dominica', 'Dominican Republic',
'Ecuador', 'Egypt', 'El Salvador', 'Estonia', 'Ethiopia',
'Fiji', 'Finland', 'France', 'Gabon', 'Gambia',
'Georgia', 'Germany', 'Ghana', 'Greece', 'Grenada',
'Guatemala', 'Guinea', 'Guyana', 'Haiti', 'Honduras',
'Hungary', 'Iceland', 'India', 'Indonesia', 'Iran',
'Iraq', 'Ireland', 'Israel', 'Italy', 'Jamaica',
'Japan', 'Jordan', 'Kazakhstan', 'Kenya', 'Kuwait',
'Laos', 'Latvia', 'Lebanon', 'Lesotho', 'Liberia',
'Libya', 'Lithuania', 'Luxembourg', 'Madagascar', 'Malawi',
'Malaysia', 'Maldives', 'Mali', 'Malta', 'Mexico',
'Moldova', 'Monaco', 'Mongolia', 'Morocco', 'Mozambique',
'Myanmar', 'Namibia', 'Nepal', 'Netherlands', 'New Zealand',
'Nicaragua', 'Niger', 'Nigeria', 'Norway', 'Oman',
'Pakistan', 'Panama', 'Paraguay', 'Peru', 'Philippines',
'Poland', 'Portugal', 'Qatar', 'Romania', 'Russia',
'Rwanda', 'Saudi Arabia', 'Senegal', 'Serbia', 'Singapore',
'Slovakia', 'Slovenia', 'Somalia', 'South Africa', 'South Korea',
'Spain', 'Sri Lanka', 'Sudan', 'Sweden', 'Switzerland',
'Syria', 'Taiwan', 'Tanzania', 'Thailand', 'Togo',
'Tunisia', 'Turkey', 'Uganda', 'Ukraine', 'United Arab Emirates',
'United Kingdom', 'United States', 'Uruguay', 'Uzbekistan',
'Venezuela', 'Vietnam', 'Yemen', 'Zambia', 'Zimbabwe'
]
# Example: Popular packages
POPULAR_PACKAGES = [
'express', 'react', 'vue', 'angular', 'next', 'nuxt',
'axios', 'lodash', 'moment', 'dayjs', 'uuid', 'dotenv',
'typescript', 'eslint', 'prettier', 'jest', 'mocha', 'chai',
'webpack', 'vite', 'rollup', 'babel', 'esbuild',
'socket.io', 'redis', 'mongodb', 'mongoose', 'sequelize',
'prisma', 'typeorm', 'knex', 'pg', 'mysql2',
'bcrypt', 'jsonwebtoken', 'passport', 'helmet', 'cors',
'multer', 'sharp', 'puppeteer', 'playwright', 'cheerio'
]
def autocomplete_prompt_example():
"""Example autocomplete prompts"""
print("\n🔍 Autocomplete Example\n")
# Country selection with autocomplete
country = questionary.autocomplete(
"Select your country:",
choices=COUNTRIES,
validate=lambda text: len(text) > 0 or "Please select a country"
).ask()
# Package selection
package = questionary.autocomplete(
"Search for an npm package:",
choices=POPULAR_PACKAGES
).ask()
# Cities based on country (conditional)
city = None
cities_by_country = {
'United States': ['New York', 'Los Angeles', 'Chicago', 'Houston', 'Phoenix'],
'United Kingdom': ['London', 'Manchester', 'Birmingham', 'Glasgow', 'Liverpool'],
'Canada': ['Toronto', 'Vancouver', 'Montreal', 'Calgary', 'Ottawa'],
'Australia': ['Sydney', 'Melbourne', 'Brisbane', 'Perth', 'Adelaide'],
'Germany': ['Berlin', 'Munich', 'Hamburg', 'Frankfurt', 'Cologne']
}
if country in cities_by_country:
city = questionary.autocomplete(
"Select city:",
choices=cities_by_country[country]
).ask()
answers = {
'country': country,
'package': package,
'city': city
}
print("\n✅ Selections:")
import json
print(json.dumps(answers, indent=2))
return answers
def framework_search_example():
"""Example: Framework/library search with descriptions"""
print("\n🔎 Framework Search Example\n")
frameworks = [
'React - UI library by Facebook',
'Vue.js - Progressive JavaScript framework',
'Angular - Platform for building web apps',
'Svelte - Cybernetically enhanced web apps',
'Next.js - React framework with SSR',
'Nuxt.js - Vue.js framework with SSR',
'Remix - Full stack web framework',
'SvelteKit - Svelte framework',
'Express - Fast Node.js web framework',
'Fastify - Fast and low overhead web framework',
'NestJS - Progressive Node.js framework',
'Koa - Expressive middleware for Node.js'
]
framework = questionary.autocomplete(
"Search for a framework:",
choices=frameworks
).ask()
# Extract value (remove description)
framework_name = framework.split(' - ')[0] if ' - ' in framework else framework
print(f"\n✅ Selected: {framework_name}")
return {'framework': framework_name}
def command_search_example():
"""Example: Command search with emojis and categories"""
print("\n⌨️ Command Search Example\n")
commands = [
'📦 install - Install dependencies',
'🚀 start - Start development server',
'🏗️ build - Build for production',
'🧪 test - Run tests',
'🔍 lint - Check code quality',
'✨ format - Format code',
'📝 generate - Generate files',
'🔄 update - Update dependencies',
'🧹 clean - Clean build artifacts',
'🚢 deploy - Deploy application',
'📊 analyze - Analyze bundle size',
'🐛 debug - Start debugger'
]
command = questionary.autocomplete(
"Search for a command:",
choices=commands
).ask()
# Extract command name
command_name = command.split(' - ')[0].split(' ', 1)[1] if ' - ' in command else command
print(f"\n✅ Running: {command_name}")
return {'command': command_name}
def api_endpoint_search():
"""Example: API endpoint search"""
print("\n🔍 API Endpoint Search\n")
endpoints = [
'GET /users - List all users',
'GET /users/:id - Get user by ID',
'POST /users - Create new user',
'PUT /users/:id - Update user',
'DELETE /users/:id - Delete user',
'GET /posts - List all posts',
'GET /posts/:id - Get post by ID',
'POST /posts - Create new post',
'GET /comments - List comments',
'POST /auth/login - User login',
'POST /auth/register - User registration',
'POST /auth/logout - User logout'
]
endpoint = questionary.autocomplete(
"Search API endpoints:",
choices=endpoints
).ask()
# Extract endpoint path
endpoint_path = endpoint.split(' - ')[0] if ' - ' in endpoint else endpoint
print(f"\n✅ Selected endpoint: {endpoint_path}")
return {'endpoint': endpoint_path}
def technology_stack_selection():
"""Example: Building technology stack with multiple autocomplete prompts"""
print("\n🛠️ Technology Stack Selection\n")
# Programming languages
languages = [
'JavaScript', 'TypeScript', 'Python', 'Go', 'Rust',
'Java', 'C++', 'Ruby', 'PHP', 'Swift', 'Kotlin'
]
language = questionary.autocomplete(
"Choose programming language:",
choices=languages
).ask()
# Frameworks based on language
frameworks_by_language = {
'JavaScript': ['React', 'Vue', 'Angular', 'Svelte', 'Express', 'Fastify'],
'TypeScript': ['Next.js', 'Nest.js', 'Angular', 'Remix', 'tRPC'],
'Python': ['Django', 'Flask', 'FastAPI', 'Tornado', 'Sanic'],
'Go': ['Gin', 'Echo', 'Fiber', 'Chi', 'Gorilla'],
'Rust': ['Actix', 'Rocket', 'Axum', 'Warp', 'Tide'],
'Java': ['Spring', 'Micronaut', 'Quarkus', 'Vert.x'],
'Ruby': ['Ruby on Rails', 'Sinatra', 'Hanami']
}
framework_choices = frameworks_by_language.get(language, ['None'])
framework = questionary.autocomplete(
f"Choose {language} framework:",
choices=framework_choices
).ask()
# Databases
databases = [
'PostgreSQL', 'MySQL', 'MongoDB', 'Redis', 'SQLite',
'Cassandra', 'DynamoDB', 'CouchDB', 'Neo4j', 'InfluxDB'
]
database = questionary.autocomplete(
"Choose database:",
choices=databases
).ask()
# Cloud providers
cloud_providers = [
'AWS', 'Google Cloud', 'Azure', 'DigitalOcean',
'Heroku', 'Vercel', 'Netlify', 'Cloudflare'
]
cloud = questionary.autocomplete(
"Choose cloud provider:",
choices=cloud_providers
).ask()
stack = {
'language': language,
'framework': framework,
'database': database,
'cloud': cloud
}
print("\n✅ Technology Stack:")
import json
print(json.dumps(stack, indent=2))
return stack
def file_path_autocomplete():
"""Example: File path autocomplete (simulated)"""
print("\n📁 File Path Autocomplete Example\n")
# Common project directories
directories = [
'/home/user/projects/web-app',
'/home/user/projects/api-server',
'/home/user/projects/cli-tool',
'/var/www/html',
'/opt/applications',
'~/Documents/code',
'~/workspace/nodejs',
'~/workspace/python'
]
project_path = questionary.autocomplete(
"Select project directory:",
choices=directories
).ask()
# Common config files
config_files = [
'package.json',
'tsconfig.json',
'jest.config.js',
'webpack.config.js',
'.env',
'.gitignore',
'README.md',
'Dockerfile',
'docker-compose.yml'
]
config_file = questionary.autocomplete(
"Select config file:",
choices=config_files
).ask()
result = {
'projectPath': project_path,
'configFile': config_file
}
print("\n✅ Selected:")
import json
print(json.dumps(result, indent=2))
return result
def main():
"""Run autocomplete prompt examples"""
try:
print("=== Autocomplete Examples ===")
# Example 1: Basic autocomplete
autocomplete_prompt_example()
# Example 2: Framework search
framework_search_example()
# Example 3: Command search
command_search_example()
# Example 4: API endpoint search
api_endpoint_search()
# Example 5: Technology stack
technology_stack_selection()
# Example 6: File path autocomplete
file_path_autocomplete()
print("\n✅ Autocomplete examples complete!")
except KeyboardInterrupt:
print("\n\n❌ User interrupted prompt")
exit(1)
except Exception as e:
print(f"\n\n❌ Error: {e}")
exit(1)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,310 @@
"""
Checkbox Prompt Template
Use for: Multiple selections from options
Features: Space to toggle, Enter to confirm
"""
import questionary
from questionary import Choice, Separator, ValidationError, Validator
class MinimumChoicesValidator(Validator):
"""Validator to ensure minimum number of choices selected"""
def __init__(self, minimum=1, message=None):
self.minimum = minimum
self.message = message or f"You must select at least {minimum} option(s)"
def validate(self, document):
# document.text contains selected choices as list
if len(document.text) < self.minimum:
raise ValidationError(
message=self.message,
cursor_position=0
)
class MaximumChoicesValidator(Validator):
"""Validator to ensure maximum number of choices selected"""
def __init__(self, maximum=10, message=None):
self.maximum = maximum
self.message = message or f"Please select no more than {maximum} options"
def validate(self, document):
if len(document.text) > self.maximum:
raise ValidationError(
message=self.message,
cursor_position=0
)
def checkbox_prompt_example():
"""Example checkbox prompts"""
print("\n☑️ Checkbox Selection Example\n")
# Simple checkbox
features = questionary.checkbox(
"Select features to include:",
choices=[
'Authentication',
'Authorization',
'Database Integration',
'API Documentation',
'Testing Suite',
'CI/CD Pipeline',
'Monitoring',
'Logging'
],
validate=lambda choices: len(choices) > 0 or "You must select at least one feature"
).ask()
# Checkbox with default selections
dev_tools = questionary.checkbox(
"Select development tools:",
choices=[
Choice('ESLint (Linting)', value='eslint', checked=True),
Choice('Prettier (Formatting)', value='prettier', checked=True),
Choice('Jest (Testing)', value='jest'),
Choice('Husky (Git Hooks)', value='husky'),
Choice('TypeDoc (Documentation)', value='typedoc'),
Choice('Webpack (Bundling)', value='webpack')
]
).ask()
# Checkbox with separators and checked defaults
plugins = questionary.checkbox(
"Select plugins to install:",
choices=[
Separator('=== Essential ==='),
Choice('dotenv - Environment variables', value='dotenv', checked=True),
Choice('axios - HTTP client', value='axios', checked=True),
Separator('=== Utilities ==='),
Choice('lodash - Utility functions', value='lodash'),
Choice('dayjs - Date manipulation', value='dayjs'),
Choice('uuid - Unique IDs', value='uuid'),
Separator('=== Validation ==='),
Choice('joi - Schema validation', value='joi'),
Choice('zod - TypeScript-first validation', value='zod'),
Separator('=== Advanced ==='),
Choice('bull - Job queues', value='bull'),
Choice('socket.io - WebSockets', value='socket.io')
],
validate=MaximumChoicesValidator(maximum=10)
).ask()
# Checkbox with emojis
permissions = questionary.checkbox(
"Grant the following permissions:",
choices=[
Choice('📁 Read files', value='read', checked=True),
Choice('✏️ Write files', value='write'),
Choice('🗑️ Delete files', value='delete'),
Choice('🌐 Network access', value='network', checked=True),
Choice('🖥️ System commands', value='system'),
Choice('🔒 Keychain access', value='keychain')
]
).ask()
# Validate permissions logic
if 'delete' in permissions and 'write' not in permissions:
print("\n⚠️ Warning: Delete permission requires write permission")
permissions.append('write')
# Checkbox with validation
environments = questionary.checkbox(
"Select deployment environments:",
choices=[
Choice('Development', value='dev', checked=True),
Choice('Staging', value='staging'),
Choice('Production', value='prod'),
Choice('Testing', value='test', checked=True)
],
validate=lambda choices: (
'dev' in choices or "Development environment is required"
)
).ask()
# Additional validation
if 'prod' in environments and 'staging' not in environments:
print("\n⚠️ Warning: Staging environment is recommended before production")
answers = {
'features': features,
'devTools': dev_tools,
'plugins': plugins,
'permissions': permissions,
'environments': environments
}
print("\n✅ Selected options:")
import json
print(json.dumps(answers, indent=2))
# Example: Process selections
print("\n📦 Installing selected features...")
for feature in features:
print(f" - {feature}")
return answers
def grouped_checkbox_example():
"""Example with logically grouped checkboxes"""
print("\n📂 Grouped Checkbox Example\n")
security_features = questionary.checkbox(
"Select security features:",
choices=[
Separator('=== Authentication ==='),
Choice('JWT Tokens', value='jwt', checked=True),
Choice('OAuth 2.0', value='oauth'),
Choice('Session Management', value='session'),
Choice('Two-Factor Auth', value='2fa'),
Separator('=== Authorization ==='),
Choice('Role-Based Access Control', value='rbac', checked=True),
Choice('Permission System', value='permissions', checked=True),
Choice('API Key Management', value='api-keys'),
Separator('=== Security ==='),
Choice('Rate Limiting', value='rate-limit', checked=True),
Choice('CORS Configuration', value='cors', checked=True),
Choice('Input Sanitization', value='sanitization', checked=True),
Choice('SQL Injection Prevention', value='sql-prevent', checked=True),
Choice('XSS Protection', value='xss-protect', checked=True),
Separator('=== Encryption ==='),
Choice('Data Encryption at Rest', value='encrypt-rest'),
Choice('SSL/TLS', value='ssl', checked=True),
Choice('Password Hashing', value='hash', checked=True)
],
validate=MinimumChoicesValidator(minimum=3, message="Select at least 3 security features")
).ask()
print(f"\n✅ Selected {len(security_features)} security features")
return {'securityFeatures': security_features}
def dependent_checkbox_example():
"""Example with checkboxes that depend on previous selections"""
print("\n🔗 Dependent Checkbox Example\n")
# First checkbox: Select cloud providers
cloud_providers = questionary.checkbox(
"Select cloud providers:",
choices=[
Choice('☁️ AWS', value='aws'),
Choice('☁️ Google Cloud', value='gcp'),
Choice('☁️ Azure', value='azure'),
Choice('☁️ DigitalOcean', value='do')
],
validate=lambda c: len(c) > 0 or "Select at least one cloud provider"
).ask()
# Second checkbox: AWS services (only if AWS selected)
aws_services = []
if 'aws' in cloud_providers:
aws_services = questionary.checkbox(
"Select AWS services:",
choices=[
Choice('EC2 - Virtual Servers', value='ec2'),
Choice('Lambda - Serverless', value='lambda'),
Choice('S3 - Object Storage', value='s3', checked=True),
Choice('RDS - Databases', value='rds'),
Choice('CloudFront - CDN', value='cloudfront')
]
).ask()
# Third checkbox: GCP services (only if GCP selected)
gcp_services = []
if 'gcp' in cloud_providers:
gcp_services = questionary.checkbox(
"Select GCP services:",
choices=[
Choice('Compute Engine', value='compute'),
Choice('Cloud Functions', value='functions'),
Choice('Cloud Storage', value='storage', checked=True),
Choice('Cloud SQL', value='sql'),
Choice('Cloud CDN', value='cdn')
]
).ask()
result = {
'cloudProviders': cloud_providers,
'awsServices': aws_services,
'gcpServices': gcp_services
}
print("\n✅ Configuration complete:")
import json
print(json.dumps(result, indent=2))
return result
def conditional_validation_example():
"""Example with conditional validation logic"""
print("\n🔍 Conditional Validation Example\n")
database_features = questionary.checkbox(
"Select database features:",
choices=[
Choice('Connection Pooling', value='pool', checked=True),
Choice('Migrations', value='migrations', checked=True),
Choice('Transactions', value='transactions'),
Choice('Replication', value='replication'),
Choice('Sharding', value='sharding'),
Choice('Caching', value='caching')
]
).ask()
# Conditional logic: Sharding requires replication
if 'sharding' in database_features and 'replication' not in database_features:
print("\n⚠️ Sharding requires replication. Adding replication...")
database_features.append('replication')
# Conditional logic: Caching works best with pooling
if 'caching' in database_features and 'pool' not in database_features:
add_pooling = questionary.confirm(
"Caching works best with connection pooling. Add it?",
default=True
).ask()
if add_pooling:
database_features.append('pool')
print(f"\n✅ Selected {len(database_features)} database features")
return {'databaseFeatures': database_features}
def main():
"""Run checkbox prompt examples"""
try:
print("=== Checkbox Prompt Examples ===")
# Example 1: Basic checkbox selections
checkbox_prompt_example()
# Example 2: Grouped checkboxes
grouped_checkbox_example()
# Example 3: Dependent checkboxes
dependent_checkbox_example()
# Example 4: Conditional validation
conditional_validation_example()
print("\n✅ Checkbox examples complete!")
except KeyboardInterrupt:
print("\n\n❌ User interrupted prompt")
exit(1)
except Exception as e:
print(f"\n\n❌ Error: {e}")
exit(1)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,501 @@
"""
Conditional Prompt Template
Use for: Dynamic forms based on previous answers
Features: Skip logic, dependent questions, branching
"""
import questionary
from questionary import Choice, Separator
def conditional_prompt_example():
"""Example conditional prompts"""
print("\n🔀 Conditional Prompt Example\n")
# First question: Use database?
use_database = questionary.confirm(
"Do you want to use a database?",
default=True
).ask()
database_config = {}
if use_database:
# Database type
database_type = questionary.select(
"Select database type:",
choices=['PostgreSQL', 'MySQL', 'MongoDB', 'SQLite', 'Redis']
).ask()
database_config['databaseType'] = database_type
# Host and port (not for SQLite)
if database_type != 'SQLite':
database_host = questionary.text(
"Database host:",
default="localhost"
).ask()
# Default ports based on database type
default_ports = {
'PostgreSQL': '5432',
'MySQL': '3306',
'MongoDB': '27017',
'Redis': '6379'
}
database_port = questionary.text(
"Database port:",
default=default_ports.get(database_type, '5432')
).ask()
database_config['host'] = database_host
database_config['port'] = database_port
# Database name
database_name = questionary.text(
"Database name:",
validate=lambda text: len(text) > 0 or "Database name required"
).ask()
database_config['databaseName'] = database_name
# Authentication
use_authentication = questionary.confirm(
"Do you want to use authentication?",
default=True
).ask()
if use_authentication:
database_username = questionary.text(
"Database username:",
validate=lambda text: len(text) > 0 or "Username required"
).ask()
database_password = questionary.password(
"Database password:"
).ask()
database_config['useAuthentication'] = True
database_config['username'] = database_username
# Don't store actual password in answers
# SSL (only for remote hosts)
if database_type != 'SQLite' and database_config.get('host') != 'localhost':
use_ssl = questionary.confirm(
"Use SSL connection?",
default=False
).ask()
if use_ssl:
ssl_cert_path = questionary.text(
"Path to SSL certificate:",
validate=lambda text: len(text) > 0 or "SSL certificate path required"
).ask()
database_config['useSSL'] = True
database_config['sslCertPath'] = ssl_cert_path
answers = {
'useDatabase': use_database,
'databaseConfig': database_config if use_database else None
}
print("\n✅ Configuration:")
import json
print(json.dumps(answers, indent=2))
return answers
def deployment_wizard():
"""Example: Deployment configuration wizard"""
print("\n🚀 Deployment Configuration Wizard\n")
# Environment
environment = questionary.select(
"Select deployment environment:",
choices=['Development', 'Staging', 'Production']
).ask()
config = {'environment': environment}
# Docker
use_docker = questionary.confirm(
"Deploy using Docker?",
default=True
).ask()
config['useDocker'] = use_docker
if use_docker:
docker_image = questionary.text(
"Docker image name:",
default="myapp:latest",
validate=lambda text: len(text) > 0 or "Docker image name required"
).ask()
config['dockerImage'] = docker_image
registry = questionary.select(
"Container registry:",
choices=[
'Docker Hub',
'GitHub Container Registry',
'AWS ECR',
'Google Artifact Registry'
]
).ask()
config['registry'] = registry
# Platform
platform = questionary.select(
"Deployment platform:",
choices=[
'AWS', 'Google Cloud', 'Azure',
'DigitalOcean', 'Vercel', 'Netlify', 'Self-hosted'
]
).ask()
config['platform'] = platform
# Platform-specific configuration
if platform == 'AWS':
aws_service = questionary.select(
"AWS service:",
choices=['ECS', 'EKS', 'Lambda', 'Elastic Beanstalk', 'EC2']
).ask()
config['awsService'] = aws_service
# Auto-scaling (only for certain services)
if aws_service in ['ECS', 'EKS']:
auto_scale = questionary.confirm(
"Enable auto-scaling?",
default=True
).ask()
config['autoScale'] = auto_scale
if auto_scale:
min_instances = questionary.text(
"Minimum instances:",
default="1",
validate=lambda text: text.isdigit() and int(text) > 0 or "Must be at least 1"
).ask()
max_instances = questionary.text(
"Maximum instances:",
default="10",
validate=lambda text: text.isdigit() and int(text) >= int(min_instances) or f"Must be at least {min_instances}"
).ask()
config['minInstances'] = int(min_instances)
config['maxInstances'] = int(max_instances)
elif platform == 'Google Cloud':
gcp_service = questionary.select(
"Google Cloud service:",
choices=['Cloud Run', 'GKE', 'App Engine', 'Compute Engine']
).ask()
config['gcpService'] = gcp_service
# CDN (only for production)
if environment == 'Production':
use_cdn = questionary.confirm(
"Use CDN for static assets?",
default=True
).ask()
config['useCDN'] = use_cdn
if use_cdn:
cdn_provider = questionary.select(
"CDN provider:",
choices=['CloudFlare', 'AWS CloudFront', 'Google Cloud CDN', 'Azure CDN']
).ask()
config['cdnProvider'] = cdn_provider
# Monitoring
setup_monitoring = questionary.confirm(
"Setup monitoring?",
default=True
).ask()
if setup_monitoring:
monitoring_tools = questionary.checkbox(
"Select monitoring tools:",
choices=['Prometheus', 'Grafana', 'Datadog', 'New Relic', 'Sentry'],
validate=lambda choices: len(choices) > 0 or "Select at least one tool"
).ask()
config['monitoringTools'] = monitoring_tools
print("\n✅ Deployment configuration complete!")
import json
print(json.dumps(config, indent=2))
return config
def feature_flag_wizard():
"""Example: Feature flag configuration"""
print("\n🎛️ Feature Flag Configuration\n")
# Feature name
feature_name = questionary.text(
"Feature name:",
validate=lambda text: text and text.replace('-', '').replace('_', '').islower() or "Use lowercase, hyphens, underscores only"
).ask()
# Enabled by default
enabled_by_default = questionary.confirm(
"Enabled by default?",
default=False
).ask()
config = {
'featureName': feature_name,
'enabledByDefault': enabled_by_default
}
# Rollout strategy
rollout_strategy = questionary.select(
"Rollout strategy:",
choices=[
'All users',
'Percentage rollout',
'User targeting',
'Beta users only',
'Manual control'
]
).ask()
config['rolloutStrategy'] = rollout_strategy
# Percentage rollout
if rollout_strategy == 'Percentage rollout':
rollout_percentage = questionary.text(
"Rollout percentage (0-100):",
default="10",
validate=lambda text: text.isdigit() and 0 <= int(text) <= 100 or "Must be between 0 and 100"
).ask()
config['rolloutPercentage'] = int(rollout_percentage)
# User targeting
if rollout_strategy == 'User targeting':
target_user_groups = questionary.checkbox(
"Target user groups:",
choices=[
'Beta testers',
'Premium users',
'Internal team',
'Early adopters',
'Specific regions'
],
validate=lambda choices: len(choices) > 0 or "Select at least one group"
).ask()
config['targetUserGroups'] = target_user_groups
# Specific regions
if 'Specific regions' in target_user_groups:
target_regions = questionary.checkbox(
"Target regions:",
choices=[
'North America',
'Europe',
'Asia Pacific',
'South America',
'Africa'
]
).ask()
config['targetRegions'] = target_regions
# Metrics
enable_metrics = questionary.confirm(
"Track feature usage metrics?",
default=True
).ask()
if enable_metrics:
metrics = questionary.checkbox(
"Select metrics to track:",
choices=[
'Usage count',
'User adoption rate',
'Performance impact',
'Error rate',
'User feedback'
]
).ask()
config['metrics'] = metrics
# Expiration
add_expiration_date = questionary.confirm(
"Set feature flag expiration?",
default=False
).ask()
if add_expiration_date:
expiration_date = questionary.text(
"Expiration date (YYYY-MM-DD):",
validate=lambda text: len(text) == 10 and text.count('-') == 2 or "Use format YYYY-MM-DD"
).ask()
config['expirationDate'] = expiration_date
print("\n✅ Feature flag configured!")
import json
print(json.dumps(config, indent=2))
return config
def cicd_pipeline_wizard():
"""Example: CI/CD pipeline setup"""
print("\n⚙️ CI/CD Pipeline Configuration\n")
# Provider
provider = questionary.select(
"CI/CD provider:",
choices=['GitHub Actions', 'GitLab CI', 'CircleCI', 'Jenkins', 'Travis CI']
).ask()
config = {'provider': provider}
# Triggers
triggers = questionary.checkbox(
"Pipeline triggers:",
choices=[
'Push to main/master',
'Pull request',
'Tag creation',
'Manual trigger',
'Scheduled (cron)'
],
default=['Push to main/master', 'Pull request']
).ask()
config['triggers'] = triggers
# Cron schedule
if 'Scheduled (cron)' in triggers:
cron_schedule = questionary.text(
"Cron schedule:",
default="0 2 * * *",
validate=lambda text: len(text.split()) == 5 or "Invalid cron format (5 parts required)"
).ask()
config['cronSchedule'] = cron_schedule
# Stages
stages = questionary.checkbox(
"Pipeline stages:",
choices=['Build', 'Test', 'Lint', 'Security scan', 'Deploy'],
default=['Build', 'Test', 'Deploy'],
validate=lambda choices: len(choices) > 0 or "Select at least one stage"
).ask()
config['stages'] = stages
# Test types
if 'Test' in stages:
test_types = questionary.checkbox(
"Test types to run:",
choices=[
'Unit tests',
'Integration tests',
'E2E tests',
'Performance tests'
]
).ask()
config['testTypes'] = test_types
# Security tools
if 'Security scan' in stages:
security_tools = questionary.checkbox(
"Security scanning tools:",
choices=['Snyk', 'Dependabot', 'SonarQube', 'OWASP Dependency Check']
).ask()
config['securityTools'] = security_tools
# Deploy environments
if 'Deploy' in stages:
deploy_environments = questionary.checkbox(
"Deployment environments:",
choices=['Development', 'Staging', 'Production'],
default=['Staging', 'Production']
).ask()
config['deployEnvironments'] = deploy_environments
# Approval for production
if 'Production' in deploy_environments:
require_approval = questionary.confirm(
"Require manual approval for production?",
default=True
).ask()
config['requireApproval'] = require_approval
# Notifications
enable_notifications = questionary.confirm(
"Enable build notifications?",
default=True
).ask()
if enable_notifications:
notification_channels = questionary.checkbox(
"Notification channels:",
choices=['Email', 'Slack', 'Discord', 'Microsoft Teams']
).ask()
config['notificationChannels'] = notification_channels
print("\n✅ CI/CD pipeline configured!")
import json
print(json.dumps(config, indent=2))
return config
def main():
"""Run conditional prompt examples"""
try:
print("=== Conditional Prompt Examples ===")
# Example 1: Database configuration
conditional_prompt_example()
# Example 2: Deployment wizard
deployment_wizard()
# Example 3: Feature flag configuration
feature_flag_wizard()
# Example 4: CI/CD pipeline setup
cicd_pipeline_wizard()
print("\n✅ Conditional prompt examples complete!")
except KeyboardInterrupt:
print("\n\n❌ User interrupted prompt")
exit(1)
except Exception as e:
print(f"\n\n❌ Error: {e}")
exit(1)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,221 @@
"""
List Selection Prompt Template
Use for: Single choice from predefined options
Features: Arrow key navigation, search filtering
"""
import questionary
from questionary import Choice, Separator
def list_prompt_example():
"""Example list selection prompts"""
print("\n📋 List Selection Example\n")
# Simple list
framework = questionary.select(
"Choose your preferred framework:",
choices=[
'React',
'Vue',
'Angular',
'Svelte',
'Next.js',
'Nuxt.js'
],
default='React'
).ask()
# List with values
language = questionary.select(
"Choose programming language:",
choices=[
Choice('JavaScript', value='js'),
Choice('TypeScript', value='ts'),
Choice('Python', value='py'),
Choice('Ruby', value='rb'),
Choice('Go', value='go')
],
default='ts'
).ask()
# List with descriptions
package_manager = questionary.select(
"Choose package manager:",
choices=[
Choice('npm - Node Package Manager', value='npm', shortcut_key='n'),
Choice('yarn - Fast, reliable package manager', value='yarn', shortcut_key='y'),
Choice('pnpm - Fast, disk space efficient', value='pnpm', shortcut_key='p'),
Choice('bun - All-in-one toolkit', value='bun', shortcut_key='b')
]
).ask()
# List with separators
environment = questionary.select(
"Select deployment environment:",
choices=[
Separator('--- Cloud Platforms ---'),
'AWS',
'Google Cloud',
'Azure',
Separator('--- Serverless ---'),
'Vercel',
'Netlify',
'Cloudflare Workers',
Separator('--- Self-hosted ---'),
'Docker',
'Kubernetes'
]
).ask()
# List with emojis and styling
database = questionary.select(
"Choose database:",
choices=[
Choice('🐘 PostgreSQL (Relational)', value='postgresql'),
Choice('🐬 MySQL (Relational)', value='mysql'),
Choice('🍃 MongoDB (Document)', value='mongodb'),
Choice('⚡ Redis (Key-Value)', value='redis'),
Choice('📊 SQLite (Embedded)', value='sqlite'),
Choice('🔥 Supabase (PostgreSQL + APIs)', value='supabase')
],
use_shortcuts=True,
use_arrow_keys=True
).ask()
answers = {
'framework': framework,
'language': language,
'packageManager': package_manager,
'environment': environment,
'database': database
}
print("\n✅ Selections:")
import json
print(json.dumps(answers, indent=2))
return answers
def dynamic_list_example():
"""Example with dynamic choices based on context"""
print("\n🔄 Dynamic List Example\n")
# First selection
project_type = questionary.select(
"Project type:",
choices=['Web Application', 'CLI Tool', 'API/Backend', 'Library']
).ask()
# Dynamic framework choices based on project type
framework_choices = {
'Web Application': ['React', 'Vue', 'Angular', 'Svelte', 'Next.js'],
'CLI Tool': ['Commander.js', 'Yargs', 'Click', 'Typer', 'Cobra'],
'API/Backend': ['Express', 'Fastify', 'Flask', 'FastAPI', 'Gin'],
'Library': ['TypeScript', 'JavaScript', 'Python', 'Go', 'Rust']
}
framework = questionary.select(
f"Choose framework for {project_type}:",
choices=framework_choices.get(project_type, ['None'])
).ask()
print(f"\n✅ Selected: {project_type} with {framework}")
return {'projectType': project_type, 'framework': framework}
def categorized_list_example():
"""Example with categorized options"""
print("\n📂 Categorized List Example\n")
cloud_service = questionary.select(
"Choose cloud service:",
choices=[
Separator('=== Compute ==='),
Choice('EC2 - Virtual Servers', value='ec2'),
Choice('Lambda - Serverless Functions', value='lambda'),
Choice('ECS - Container Service', value='ecs'),
Choice('EKS - Kubernetes Service', value='eks'),
Separator('=== Storage ==='),
Choice('S3 - Object Storage', value='s3'),
Choice('EBS - Block Storage', value='ebs'),
Choice('EFS - File System', value='efs'),
Separator('=== Database ==='),
Choice('RDS - Relational Database', value='rds'),
Choice('DynamoDB - NoSQL Database', value='dynamodb'),
Choice('ElastiCache - In-Memory Cache', value='elasticache'),
Separator('=== Other ==='),
Choice('CloudFront - CDN', value='cloudfront'),
Choice('Route53 - DNS', value='route53'),
Choice('SQS - Message Queue', value='sqs')
],
use_indicator=True
).ask()
print(f"\n✅ Selected: {cloud_service}")
return {'cloudService': cloud_service}
def numbered_list_example():
"""Example with numbered choices for easier selection"""
print("\n🔢 Numbered List Example\n")
languages = [
'Python', 'JavaScript', 'TypeScript', 'Go', 'Rust',
'Java', 'C++', 'Ruby', 'PHP', 'Swift'
]
# Add numbers to choices for easier reference
numbered_choices = [
Choice(f"{i+1}. {lang}", value=lang)
for i, lang in enumerate(languages)
]
language = questionary.select(
"Choose programming language:",
choices=numbered_choices,
use_shortcuts=False # Disable letter shortcuts when using numbers
).ask()
print(f"\n✅ Selected: {language}")
return {'language': language}
def main():
"""Run list prompt examples"""
try:
print("=== List Selection Examples ===")
# Example 1: Basic list selections
list_prompt_example()
# Example 2: Dynamic choices
dynamic_list_example()
# Example 3: Categorized options
categorized_list_example()
# Example 4: Numbered list
numbered_list_example()
print("\n✅ List selection examples complete!")
except KeyboardInterrupt:
print("\n\n❌ User interrupted prompt")
exit(1)
except Exception as e:
print(f"\n\n❌ Error: {e}")
exit(1)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,366 @@
"""
Password Prompt Template
Use for: Sensitive input (credentials, tokens)
Features: Hidden input, confirmation, validation
"""
import questionary
import re
from questionary import ValidationError, Validator
class PasswordStrengthValidator(Validator):
"""Validator for password strength requirements"""
def __init__(self, min_length=8, require_uppercase=True, require_lowercase=True,
require_digit=True, require_special=True):
self.min_length = min_length
self.require_uppercase = require_uppercase
self.require_lowercase = require_lowercase
self.require_digit = require_digit
self.require_special = require_special
def validate(self, document):
password = document.text
issues = []
if len(password) < self.min_length:
issues.append(f"at least {self.min_length} characters")
if self.require_uppercase and not re.search(r'[A-Z]', password):
issues.append("an uppercase letter")
if self.require_lowercase and not re.search(r'[a-z]', password):
issues.append("a lowercase letter")
if self.require_digit and not re.search(r'[0-9]', password):
issues.append("a number")
if self.require_special and not re.search(r'[!@#$%^&*(),.?":{}|<>]', password):
issues.append("a special character")
if issues:
raise ValidationError(
message=f"Password must contain: {', '.join(issues)}",
cursor_position=len(password)
)
class APIKeyValidator(Validator):
"""Validator for API key format"""
def validate(self, document):
api_key = document.text
if len(api_key) == 0:
raise ValidationError(
message="API key is required",
cursor_position=0
)
if not (api_key.startswith('sk-') or api_key.startswith('pk-')):
raise ValidationError(
message='API key must start with "sk-" or "pk-"',
cursor_position=len(api_key)
)
if len(api_key) < 32:
raise ValidationError(
message="API key appears to be too short",
cursor_position=len(api_key)
)
def calculate_password_strength(password):
"""Calculate password strength score"""
strength = 0
if len(password) >= 8:
strength += 1
if len(password) >= 12:
strength += 1
if re.search(r'[a-z]', password):
strength += 1
if re.search(r'[A-Z]', password):
strength += 1
if re.search(r'[0-9]', password):
strength += 1
if re.search(r'[!@#$%^&*(),.?":{}|<>]', password):
strength += 1
levels = ['Very Weak', 'Weak', 'Fair', 'Good', 'Strong', 'Very Strong']
return levels[min(strength, len(levels) - 1)]
def password_prompt_example():
"""Example password prompts with validation"""
print("\n🔒 Password Prompt Example\n")
# Password with strength validation
password = questionary.password(
"Enter your password:",
validate=PasswordStrengthValidator(min_length=8)
).ask()
# Confirm password
confirm_password = questionary.password(
"Confirm your password:",
validate=lambda text: text == password or "Passwords do not match"
).ask()
print(f"\n✅ Password strength: {calculate_password_strength(password)}")
# API key input
api_key = questionary.password(
"Enter your API key:",
validate=APIKeyValidator()
).ask()
print(f"✅ API key format: {api_key[:6]}...")
# Optional encryption key
encryption_key = questionary.password(
"Enter encryption key (optional, press Enter to skip):",
validate=lambda text: len(text) == 0 or len(text) >= 16 or "Encryption key must be at least 16 characters"
).ask()
# Don't log actual passwords!
answers = {
'passwordSet': True,
'passwordStrength': calculate_password_strength(password),
'apiKeyPrefix': api_key[:6],
'encryptionKeySet': len(encryption_key) > 0
}
print("\n✅ Credentials received (not displayed for security)")
import json
print(json.dumps(answers, indent=2))
return answers
def secure_account_setup():
"""Example: Complete secure account setup"""
print("\n🔐 Secure Account Setup\n")
# Username
username = questionary.text(
"Username:",
validate=lambda text: len(text) > 0 or "Username required"
).ask()
# Strong password
print("\n📝 Password requirements:")
print(" • At least 12 characters")
print(" • Uppercase and lowercase letters")
print(" • Numbers")
print(" • Special characters (!@#$%^&*)")
print()
password = questionary.password(
"Password:",
validate=PasswordStrengthValidator(
min_length=12,
require_uppercase=True,
require_lowercase=True,
require_digit=True,
require_special=True
)
).ask()
# Confirm password
confirm = questionary.password(
"Confirm password:",
validate=lambda text: text == password or "Passwords do not match"
).ask()
# Optional: Remember credentials
remember = questionary.confirm(
"Remember credentials? (stored securely)",
default=False
).ask()
strength = calculate_password_strength(password)
print(f"\n✅ Account created for: {username}")
print(f"🔒 Password strength: {strength}")
if remember:
print("💾 Credentials will be stored securely")
return {
'username': username,
'passwordStrength': strength,
'remember': remember
}
def database_credentials_setup():
"""Example: Database connection credentials"""
print("\n🗄️ Database Credentials Setup\n")
# Database username
db_user = questionary.text(
"Database username:",
default="postgres",
validate=lambda text: len(text) > 0 or "Username required"
).ask()
# Database password
db_password = questionary.password(
"Database password:",
validate=lambda text: len(text) >= 8 or "Password must be at least 8 characters"
).ask()
# Admin password (if needed)
is_admin = questionary.confirm(
"Create admin user?",
default=False
).ask()
admin_password = None
if is_admin:
admin_password = questionary.password(
"Admin password:",
validate=PasswordStrengthValidator(min_length=12)
).ask()
admin_confirm = questionary.password(
"Confirm admin password:",
validate=lambda text: text == admin_password or "Passwords do not match"
).ask()
print(f"\n✅ Admin password strength: {calculate_password_strength(admin_password)}")
credentials = {
'dbUser': db_user,
'dbPasswordSet': True,
'adminConfigured': is_admin
}
print("\n✅ Database credentials configured")
import json
print(json.dumps(credentials, indent=2))
return credentials
def api_token_setup():
"""Example: API token and secret key setup"""
print("\n🔑 API Token Setup\n")
# API key
api_key = questionary.password(
"Enter API key:",
validate=lambda text: len(text) > 0 or "API key required"
).ask()
# Secret key
secret_key = questionary.password(
"Enter secret key:",
validate=lambda text: len(text) >= 32 or "Secret key must be at least 32 characters"
).ask()
# Webhook secret (optional)
use_webhooks = questionary.confirm(
"Configure webhook authentication?",
default=False
).ask()
webhook_secret = None
if use_webhooks:
webhook_secret = questionary.password(
"Webhook secret:",
validate=lambda text: len(text) >= 16 or "Webhook secret must be at least 16 characters"
).ask()
# Environment
environment = questionary.select(
"Environment:",
choices=['Development', 'Staging', 'Production']
).ask()
config = {
'apiKeySet': True,
'secretKeySet': True,
'webhookConfigured': use_webhooks,
'environment': environment
}
print("\n✅ API credentials configured")
print(f"Environment: {environment}")
return config
def password_change_flow():
"""Example: Password change with old password verification"""
print("\n🔄 Change Password\n")
# Old password (in real app, verify against stored hash)
old_password = questionary.password(
"Enter current password:",
validate=lambda text: len(text) > 0 or "Current password required"
).ask()
# New password
new_password = questionary.password(
"Enter new password:",
validate=PasswordStrengthValidator(min_length=8)
).ask()
# Ensure new password is different
if new_password == old_password:
print("\n❌ New password must be different from current password")
return password_change_flow()
# Confirm new password
confirm_password = questionary.password(
"Confirm new password:",
validate=lambda text: text == new_password or "Passwords do not match"
).ask()
print(f"\n✅ Password changed successfully")
print(f"🔒 New password strength: {calculate_password_strength(new_password)}")
return {'passwordChanged': True}
def main():
"""Run password prompt examples"""
try:
print("=== Password Prompt Examples ===")
# Example 1: Basic password prompts
password_prompt_example()
# Example 2: Secure account setup
secure_account_setup()
# Example 3: Database credentials
database_credentials_setup()
# Example 4: API token setup
api_token_setup()
# Example 5: Password change
password_change_flow()
print("\n✅ Password prompt examples complete!")
except KeyboardInterrupt:
print("\n\n❌ User interrupted prompt")
exit(1)
except Exception as e:
print(f"\n\n❌ Error: {e}")
exit(1)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,220 @@
"""
Text Input Prompt Template
Use for: Names, emails, URLs, paths, free-form text
Features: Validation, default values, transform
"""
import questionary
import re
from questionary import ValidationError, Validator
class UsernameValidator(Validator):
"""Validate username format"""
def validate(self, document):
text = document.text
if len(text) == 0:
raise ValidationError(
message='Username is required',
cursor_position=len(text)
)
if len(text) < 3:
raise ValidationError(
message='Username must be at least 3 characters',
cursor_position=len(text)
)
if not re.match(r'^[a-zA-Z0-9_-]+$', text):
raise ValidationError(
message='Username can only contain letters, numbers, hyphens, and underscores',
cursor_position=len(text)
)
class EmailValidator(Validator):
"""Validate email format"""
def validate(self, document):
text = document.text
email_regex = r'^[^\s@]+@[^\s@]+\.[^\s@]+$'
if not re.match(email_regex, text):
raise ValidationError(
message='Invalid email address',
cursor_position=len(text)
)
class URLValidator(Validator):
"""Validate URL format"""
def validate(self, document):
text = document.text
if len(text) == 0:
return # Optional field
url_regex = r'^https?://.+'
if not re.match(url_regex, text):
raise ValidationError(
message='Must be a valid URL (http:// or https://)',
cursor_position=len(text)
)
class AgeValidator(Validator):
"""Validate age range"""
def validate(self, document):
text = document.text
try:
age = int(text)
if age < 18:
raise ValidationError(
message='You must be at least 18 years old',
cursor_position=len(text)
)
if age > 120:
raise ValidationError(
message='Please enter a realistic age',
cursor_position=len(text)
)
except ValueError:
raise ValidationError(
message='Please enter a valid number',
cursor_position=len(text)
)
class BioValidator(Validator):
"""Validate bio length"""
def validate(self, document):
text = document.text
if len(text) > 200:
raise ValidationError(
message='Bio must be 200 characters or less',
cursor_position=len(text)
)
def text_prompt_example():
"""Example text input prompts with validation"""
print("\n📝 Text Input Example\n")
# Username input
username = questionary.text(
"Enter your username:",
validate=UsernameValidator
).ask()
# Email input
email = questionary.text(
"Enter your email:",
validate=EmailValidator
).ask()
# Website input (optional)
website = questionary.text(
"Enter your website (optional):",
default="",
validate=URLValidator
).ask()
# Age input with conversion
age_str = questionary.text(
"Enter your age:",
validate=AgeValidator
).ask()
age = int(age_str)
# Bio input
bio = questionary.text(
"Enter a short bio:",
validate=BioValidator,
multiline=False
).ask()
answers = {
'username': username.lower(),
'email': email,
'website': website,
'age': age,
'bio': bio
}
print("\n✅ Answers received:")
import json
print(json.dumps(answers, indent=2))
return answers
# Alternative: Using lambda validators
def lambda_validator_example():
"""Example using lambda validators for simpler cases"""
print("\n📝 Lambda Validator Example\n")
# Simple required field
name = questionary.text(
"Name:",
validate=lambda text: len(text) > 0 or "Name is required"
).ask()
# Email validation
email = questionary.text(
"Email:",
validate=lambda text: bool(re.match(r'^[^\s@]+@[^\s@]+\.[^\s@]+$', text)) or "Invalid email"
).ask()
# Numeric validation
port = questionary.text(
"Port number:",
default="8000",
validate=lambda text: text.isdigit() and 1 <= int(text) <= 65535 or "Invalid port (1-65535)"
).ask()
# Path validation
path = questionary.text(
"Project path:",
default="./my-project",
validate=lambda text: len(text) > 0 or "Path is required"
).ask()
answers = {
'name': name,
'email': email,
'port': int(port),
'path': path
}
print("\n✅ Answers received:")
import json
print(json.dumps(answers, indent=2))
return answers
def main():
"""Run text prompt examples"""
try:
print("=== Text Prompt Examples ===")
# Example 1: Class-based validators
text_prompt_example()
# Example 2: Lambda validators
lambda_validator_example()
print("\n✅ Text prompt examples complete!")
except KeyboardInterrupt:
print("\n\n❌ User interrupted prompt")
exit(1)
except Exception as e:
print(f"\n\n❌ Error: {e}")
exit(1)
if __name__ == "__main__":
main()