#!/usr/bin/env node import fs from 'fs' import path from 'path' import { fileURLToPath } from 'url' const __filename = fileURLToPath(import.meta.url) const __dirname = path.dirname(__filename) interface ApiMethodParam { name: string type: string description: string optional: boolean } interface ApiMethod { name: string description: string return: string accessLevel: string params: ApiMethodParam[] } interface ApiModule { name: string methods: ApiMethod[] } interface ApiSpec { modules: ApiModule[] types: any[] } function generateMethod(method: ApiMethod): string { const sortedParams = [...method.params].sort((a, b) => { if (a.optional && !b.optional) return 1 if (!a.optional && b.optional) return -1 return 0 }) const params = sortedParams .map((param) => { const optional = param.optional ? '?' : '' return `${param.name}${optional}: ${param.type}` }) .join(', ') const callParams = method.params.map((param) => `${param.name}: ${param.name}`).join(', ') return ` /** * @description ${method.description} ${sortedParams.map((param) => ` * @param ${param.name} ${param.description}`).join('\n')} * @return ${method.return} */ async ${method.name}(${params}): Promise<${method.return}> { return this.call("${method.name}"${callParams ? ', {' + callParams + '}' : ''}); }` } function generateModule(module: ApiModule): string { const className = `${module.name}Module` const methods = module.methods.map(generateMethod).join('\n') return `export class ${className} extends RpcModuleBase { constructor(client: RpcClientBase) { super(client, "${module.name}"); }${methods} }` } function generateClient(spec: ApiSpec): string { const modules = spec.modules .map((module) => { const moduleName = module.name const className = `${module.name}Module` return ` public ${moduleName}: ${className};` }) .join('\n') const initializations = spec.modules .map((module) => { const moduleName = module.name const className = `${module.name}Module` return ` this.${moduleName} = new ${className}(this);` }) .join('\n') const moduleClasses = spec.modules.map(generateModule).join('\n\n') return `import {RpcClientBase} from "@/api/RpcClientBase.ts"; import {RpcModuleBase} from "@/api/RpcModuleBase.ts"; export class RpcClient extends RpcClientBase {${modules} constructor(baseUrl: string) { super(baseUrl); ${initializations} } } ${moduleClasses}` } function main() { const specPath = path.resolve(__dirname, '../../../api.spec.json') const outputPath = path.resolve(__dirname, '../src/generated/RpcClient.ts') console.log('🚀 Generating RPC client...') try { if (!fs.existsSync(specPath)) { throw new Error(`API spec file not found: ${specPath}`) } const specContent = fs.readFileSync(specPath, 'utf-8') const spec: ApiSpec = JSON.parse(specContent) const clientCode = generateClient(spec) const outputDir = path.dirname(outputPath) if (!fs.existsSync(outputDir)) { fs.mkdirSync(outputDir, { recursive: true }) } fs.writeFileSync(outputPath, clientCode) console.log(`✅ RPC client generated successfully: ${outputPath}`) console.log(`📋 Generated ${spec.modules.length} API modules`) } catch (error) { console.error('❌ Error generating RPC client:', error) process.exit(1) } } if (import.meta.url === `file://${process.argv[1]}`) { main() } export { main as generateClient }