clqms-be/public/bundle-api-docs.js
root 2bcdf09b55 chore: repo-wide normalization + rules test coverage
Normalize formatting/line endings across configs, controllers, models, tests, and OpenAPI specs.

Update rule expression/rule engine implementation and remove obsolete RuleAction controller/model.

Add unit tests for rule expression syntax and multi-action behavior, and include docs updates.
2026-03-16 07:24:50 +07:00

101 lines
3.5 KiB
JavaScript

#!/usr/bin/env node
/**
* OpenAPI Documentation Bundler - Node.js Version
*
* This script merges the modular OpenAPI specification files into a single
* api-docs.bundled.yaml file that can be served to Swagger UI.
*
* It merges paths from the paths/ directory and then uses Redocly CLI to resolve
* all $ref references into inline definitions.
*
* Usage: node bundle-api-docs.js
*/
const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');
const publicDir = __dirname;
const pathsDir = path.join(publicDir, 'paths');
const tempFile = path.join(publicDir, 'api-docs.merged.yaml');
const outputFile = path.join(publicDir, 'api-docs.bundled.yaml');
// Read the base api-docs.yaml
const apiDocsPath = path.join(publicDir, 'api-docs.yaml');
let apiDocsContent = fs.readFileSync(apiDocsPath, 'utf8');
// Parse YAML manually (simple approach - looking for paths: {})
const pathsMatch = apiDocsContent.match(/^paths:\s*\{\}/m);
if (!pathsMatch) {
console.error('Could not find empty paths section in api-docs.yaml');
process.exit(1);
}
// Read all path files
const pathFiles = fs.readdirSync(pathsDir)
.filter(f => f.endsWith('.yaml'))
.map(f => path.join(pathsDir, f));
console.log(`Found ${pathFiles.length} path files to merge...`);
// Merge all paths content
let mergedPaths = [];
for (const filepath of pathFiles) {
const filename = path.basename(filepath);
try {
let content = fs.readFileSync(filepath, 'utf8');
// Fix relative paths: ../components/ -> ./components/
// because paths are now at the root level after merging
content = content.replace(/\.\.\/components\//g, './components/');
mergedPaths.push(`# From: ${filename}\n${content}`);
console.log(` [OK] Merged paths from ${filename}`);
} catch (e) {
console.log(` [WARN] Failed to read ${filename}: ${e.message}`);
}
}
// Replace empty paths with merged paths
const pathsYaml = mergedPaths.join('\n\n');
const mergedContent = apiDocsContent.replace(
/^paths:\s*\{\}/m,
`paths:\n${pathsYaml.split('\n').map(line => ' ' + line).join('\n')}`
);
// Write merged file (still has $refs)
fs.writeFileSync(tempFile, mergedContent, 'utf8');
console.log(`\n[SUCCESS] Merged paths into: ${tempFile}`);
// Now use Redocly CLI to resolve all $ref references
console.log('\nResolving $ref references with Redocly CLI...');
try {
const runBundle = (cmd) => execSync(cmd, { cwd: publicDir, stdio: 'inherit' });
try {
runBundle(`redocly bundle "${tempFile}" -o "${outputFile}"`);
} catch (e) {
// Fallback: use npx if redocly isn't installed globally
runBundle(`npx --yes @redocly/cli bundle "${tempFile}" -o "${outputFile}"`);
}
console.log(`\n[SUCCESS] Resolved all $ref references to: ${outputFile}`);
// Clean up temp file
fs.unlinkSync(tempFile);
console.log(`[CLEANUP] Removed temp file: ${tempFile}`);
// Show stats
const stats = fs.statSync(outputFile);
console.log(`\n${'='.repeat(60)}`);
console.log('Bundling complete!');
console.log(` Output: ${outputFile}`);
console.log(` Size: ${(stats.size / 1024).toFixed(1)} KB`);
console.log(`\nYou can now serve this file to Swagger UI.`);
console.log(`${'='.repeat(60)}`);
} catch (e) {
console.error(`\n[ERROR] Failed to run Redocly CLI: ${e.message}`);
console.error('Make sure Redocly CLI is installed (global or via npx): npm install -g @redocly/cli');
process.exit(1);
}