75 lines
2.9 KiB
JavaScript
75 lines
2.9 KiB
JavaScript
|
|
const fs = require('fs');
|
||
|
|
const path = require('path');
|
||
|
|
|
||
|
|
const PROJECT_SRC = path.join(__dirname, '..', 'wwjcloud', 'src', 'common');
|
||
|
|
const CONTRACT_FILE = path.join(__dirname, 'contracts', 'routes.json');
|
||
|
|
|
||
|
|
function toCamelCase(input) {
|
||
|
|
return input.replace(/[-_]+([a-zA-Z0-9])/g, (_, c) => c.toUpperCase());
|
||
|
|
}
|
||
|
|
|
||
|
|
function toPascalCase(input) {
|
||
|
|
const camel = toCamelCase(input);
|
||
|
|
return camel.charAt(0).toUpperCase() + camel.slice(1);
|
||
|
|
}
|
||
|
|
|
||
|
|
function ensureDir(dir) {
|
||
|
|
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
||
|
|
}
|
||
|
|
|
||
|
|
function buildMethodName(method, relPath) {
|
||
|
|
const cleaned = relPath.replace(/:\w+/g, '').replace(/\/$/, '');
|
||
|
|
const parts = cleaned.split('/').filter(Boolean);
|
||
|
|
const base = parts.length ? parts.join('_') : 'root';
|
||
|
|
return method.toLowerCase() + toPascalCase(base);
|
||
|
|
}
|
||
|
|
|
||
|
|
function controllerTemplate(prefix, className, routes) {
|
||
|
|
const imports = "import { Controller, Get, Post, Put, Delete, Body, Param, Query, UseGuards } from '@nestjs/common';\n" +
|
||
|
|
"import { ApiOperation, ApiTags } from '@nestjs/swagger';\n" +
|
||
|
|
"import { AdminCheckTokenGuard } from '../../../../core/security/adminCheckToken.guard';\n" +
|
||
|
|
"import { SiteScopeGuard } from '../../../../core/security/siteScopeGuard';\n\n";
|
||
|
|
const header = `@ApiTags('${prefix}')\n@UseGuards(AdminCheckTokenGuard, SiteScopeGuard)\n@Controller('adminapi/${prefix}')\nexport class ${className} {`;
|
||
|
|
const methods = routes.map(r => {
|
||
|
|
const decorator = `@${r.method.charAt(0) + r.method.slice(1).toLowerCase()}('${r.rel}')`;
|
||
|
|
const summary = `@ApiOperation({ summary: '${r.method} ${r.rel}' })`;
|
||
|
|
const methodName = buildMethodName(r.method, r.rel);
|
||
|
|
return ` ${decorator}\n ${summary}\n ${methodName}() {\n return { success: true };\n }`;
|
||
|
|
}).join('\n\n');
|
||
|
|
return imports + header + '\n' + methods + '\n}\n';
|
||
|
|
}
|
||
|
|
|
||
|
|
function main() {
|
||
|
|
const contract = JSON.parse(fs.readFileSync(CONTRACT_FILE, 'utf8'));
|
||
|
|
// group by first segment after adminapi/
|
||
|
|
const groups = new Map();
|
||
|
|
for (const r of contract) {
|
||
|
|
if (!r.path.startsWith('adminapi/')) continue;
|
||
|
|
const rest = r.path.slice('adminapi/'.length);
|
||
|
|
const [prefix, ...restParts] = rest.split('/');
|
||
|
|
const rel = restParts.join('/');
|
||
|
|
const arr = groups.get(prefix) || [];
|
||
|
|
arr.push({ method: r.method, rel });
|
||
|
|
groups.set(prefix, arr);
|
||
|
|
}
|
||
|
|
for (const [prefix, routes] of groups) {
|
||
|
|
const moduleDir = path.join(PROJECT_SRC, prefix);
|
||
|
|
const ctrlDir = path.join(moduleDir, 'controllers', 'adminapi');
|
||
|
|
ensureDir(ctrlDir);
|
||
|
|
const fileName = `${toCamelCase(prefix)}.controller.ts`;
|
||
|
|
const filePath = path.join(ctrlDir, fileName);
|
||
|
|
if (fs.existsSync(filePath)) {
|
||
|
|
// do not overwrite; skip existing controllers
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
const className = `${toPascalCase(prefix)}Controller`;
|
||
|
|
const content = controllerTemplate(prefix, className, routes);
|
||
|
|
fs.writeFileSync(filePath, content);
|
||
|
|
console.log('Generated', filePath);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
main();
|
||
|
|
|
||
|
|
|