feat: add configuration file strategy
This commit is contained in:
104
main.ts
104
main.ts
@@ -18,6 +18,13 @@ import { generateReport } from './src/generators/report.generator';
|
||||
import { lintGeneratedFiles } from './src/generators/lint.generator';
|
||||
import { findEnvironmentFile, parseApiKeys } from './src/utils/environment-finder';
|
||||
import { askApiKeysForTags, askSelectionFilter } from './src/utils/prompt';
|
||||
import {
|
||||
loadConfig,
|
||||
generateDefaultConfig,
|
||||
writeConfig,
|
||||
deriveSelectionFilter,
|
||||
deriveTagApiKeyMap
|
||||
} from './src/utils/config';
|
||||
import type { SelectionFilter } from './src/types';
|
||||
import type { CliOptions } from './src/types';
|
||||
import packageJson from './package.json';
|
||||
@@ -40,6 +47,8 @@ program
|
||||
.option('--dry-run', 'Simulate without generating files')
|
||||
.option('--skip-lint', 'Skip post-generation linting and formatting')
|
||||
.option('-s, --select-endpoints', 'Interactively select which tags and endpoints to generate')
|
||||
.option('-c, --config <file>', 'Use a JSON configuration file (skips interactive prompts)')
|
||||
.option('--init-config [file]', 'Generate a JSON configuration file instead of generating code')
|
||||
.parse(process.argv);
|
||||
|
||||
const options = program.opts<CliOptions>();
|
||||
@@ -52,6 +61,20 @@ async function main(): Promise<void> {
|
||||
log(' Angular + Clean Architecture Code Generator', 'cyan');
|
||||
console.log('='.repeat(60) + '\n');
|
||||
|
||||
// ── CONFIG FILE: override CLI defaults with config values ─────────────────
|
||||
const configFile = options.config;
|
||||
const generationConfig = configFile ? loadConfig(configFile) : undefined;
|
||||
|
||||
if (generationConfig) {
|
||||
if (generationConfig.input) options.input = generationConfig.input;
|
||||
if (generationConfig.output) options.output = generationConfig.output;
|
||||
if (generationConfig.templates) options.templates = generationConfig.templates;
|
||||
if (generationConfig.skipInstall !== undefined)
|
||||
options.skipInstall = generationConfig.skipInstall;
|
||||
if (generationConfig.skipLint !== undefined) options.skipLint = generationConfig.skipLint;
|
||||
logInfo(`Using configuration file: ${configFile}`);
|
||||
}
|
||||
|
||||
if (!fs.existsSync(options.input)) {
|
||||
logError(`File not found: ${options.input}`);
|
||||
process.exit(1);
|
||||
@@ -80,6 +103,26 @@ async function main(): Promise<void> {
|
||||
}
|
||||
|
||||
const analysis = analyzeSwagger(options.input);
|
||||
const tagSummaries = extractTagsWithOperations(analysis);
|
||||
|
||||
// ── INIT CONFIG MODE: generate config file and exit ───────────────────────
|
||||
if (options.initConfig !== undefined) {
|
||||
const envFile = findEnvironmentFile(process.cwd());
|
||||
let apiKeys: ReturnType<typeof parseApiKeys> = [];
|
||||
if (envFile) {
|
||||
const envContent = fs.readFileSync(envFile, 'utf8');
|
||||
apiKeys = parseApiKeys(envContent);
|
||||
}
|
||||
|
||||
const defaultConfig = generateDefaultConfig(analysis, tagSummaries, options, apiKeys);
|
||||
const outputFile =
|
||||
typeof options.initConfig === 'string' ? options.initConfig : 'generation-config.json';
|
||||
|
||||
writeConfig(defaultConfig, outputFile);
|
||||
logSuccess(`Configuration file generated: ${outputFile}`);
|
||||
logInfo('Edit the file to customise tags, endpoints and baseUrls, then run with --config');
|
||||
return;
|
||||
}
|
||||
|
||||
if (options.dryRun) {
|
||||
logInfo('Finishing in DRY RUN mode');
|
||||
@@ -89,37 +132,46 @@ async function main(): Promise<void> {
|
||||
createDirectoryStructure(options.output);
|
||||
|
||||
// ── SELECTION: tags and endpoints ─────────────────────────────────────────
|
||||
const tagSummaries = extractTagsWithOperations(analysis);
|
||||
let selectionFilter: SelectionFilter = {};
|
||||
let tagApiKeyMap: Record<string, string>;
|
||||
|
||||
if (options.selectEndpoints) {
|
||||
selectionFilter = await askSelectionFilter(tagSummaries);
|
||||
}
|
||||
|
||||
const selectedTags = options.selectEndpoints
|
||||
? Object.keys(selectionFilter)
|
||||
: tagSummaries.map((t) => t.tag);
|
||||
|
||||
// ── ENVIRONMENT API KEY SELECTION ──────────────────────────────────────────
|
||||
const envFile = findEnvironmentFile(process.cwd());
|
||||
let apiKeys: ReturnType<typeof parseApiKeys> = [];
|
||||
|
||||
if (envFile) {
|
||||
const envContent = fs.readFileSync(envFile, 'utf8');
|
||||
apiKeys = parseApiKeys(envContent);
|
||||
logSuccess(
|
||||
`environment.ts found: ${colors.cyan}${path.relative(process.cwd(), envFile)}${colors.reset}`
|
||||
);
|
||||
if (apiKeys.length > 0) {
|
||||
logInfo(`Detected API keys: ${apiKeys.map((k) => k.key).join(', ')}`);
|
||||
} else {
|
||||
logWarning('No keys containing "api" found in environment.ts. Will be requested manually.');
|
||||
}
|
||||
if (generationConfig) {
|
||||
// Config-driven: derive everything from the JSON file
|
||||
selectionFilter = deriveSelectionFilter(generationConfig);
|
||||
tagApiKeyMap = deriveTagApiKeyMap(generationConfig);
|
||||
logInfo(`Tags from config: ${Object.keys(generationConfig.tags).join(', ')}`);
|
||||
} else {
|
||||
logWarning('No environment.ts found. The key will be requested manually per repository.');
|
||||
// Interactive mode (original behaviour)
|
||||
if (options.selectEndpoints) {
|
||||
selectionFilter = await askSelectionFilter(tagSummaries);
|
||||
}
|
||||
|
||||
const selectedTags = options.selectEndpoints
|
||||
? Object.keys(selectionFilter)
|
||||
: tagSummaries.map((t) => t.tag);
|
||||
|
||||
// ── ENVIRONMENT API KEY SELECTION ────────────────────────────────────────
|
||||
const envFile = findEnvironmentFile(process.cwd());
|
||||
let apiKeys: ReturnType<typeof parseApiKeys> = [];
|
||||
|
||||
if (envFile) {
|
||||
const envContent = fs.readFileSync(envFile, 'utf8');
|
||||
apiKeys = parseApiKeys(envContent);
|
||||
logSuccess(
|
||||
`environment.ts found: ${colors.cyan}${path.relative(process.cwd(), envFile)}${colors.reset}`
|
||||
);
|
||||
if (apiKeys.length > 0) {
|
||||
logInfo(`Detected API keys: ${apiKeys.map((k) => k.key).join(', ')}`);
|
||||
} else {
|
||||
logWarning('No keys containing "api" found in environment.ts. Will be requested manually.');
|
||||
}
|
||||
} else {
|
||||
logWarning('No environment.ts found. The key will be requested manually per repository.');
|
||||
}
|
||||
|
||||
tagApiKeyMap = await askApiKeysForTags(selectedTags, apiKeys);
|
||||
}
|
||||
|
||||
const tagApiKeyMap = await askApiKeysForTags(selectedTags, apiKeys);
|
||||
// ──────────────────────────────────────────────────────────────────────────
|
||||
|
||||
const tempDir = generateCode(options.input, options.templates);
|
||||
|
||||
Reference in New Issue
Block a user