arela
Version:
AI-powered CTO with multi-agent orchestration, code summarization, visual testing (web + mobile) for blazing fast development.
91 lines (90 loc) • 3.34 kB
JavaScript
/**
* TypeScript client generator - main orchestrator
*/
import path from 'path';
import fs from 'fs-extra';
import yaml from 'yaml';
import { generateTypes } from './type-generator.js';
import { generateSchemas } from './schema-generator.js';
import { generateClient } from './client-generator.js';
export async function generateTypeScriptClient(contractPath, outputDir, baseURL) {
const result = {
success: false,
filesGenerated: [],
linesOfCode: 0,
errors: [],
};
try {
// 1. Parse OpenAPI spec
const spec = await parseOpenAPISpec(contractPath);
const serviceName = normalizeServiceName(spec.info.title);
const serviceDir = path.join(outputDir, serviceName.toLowerCase());
// 2. Ensure output directory exists
await fs.ensureDir(serviceDir);
// 3. Generate all files
const generated = generateAllFiles(spec, serviceName, baseURL);
// 4. Write files
const typesPath = path.join(serviceDir, 'types.ts');
const schemasPath = path.join(serviceDir, 'schemas.ts');
const clientPath = path.join(serviceDir, 'client.ts');
const indexPath = path.join(serviceDir, 'index.ts');
await fs.writeFile(typesPath, generated.types);
await fs.writeFile(schemasPath, generated.schemas);
await fs.writeFile(clientPath, generated.client);
await fs.writeFile(indexPath, generated.index);
// 5. Calculate metrics
const totalLines = generated.types.split('\n').length +
generated.schemas.split('\n').length +
generated.client.split('\n').length +
generated.index.split('\n').length;
result.success = true;
result.filesGenerated = [typesPath, schemasPath, clientPath, indexPath];
result.linesOfCode = totalLines;
}
catch (error) {
result.errors = [error instanceof Error ? error.message : String(error)];
}
return result;
}
async function parseOpenAPISpec(contractPath) {
const content = await fs.readFile(contractPath, 'utf-8');
if (contractPath.endsWith('.yaml') || contractPath.endsWith('.yml')) {
return yaml.parse(content);
}
if (contractPath.endsWith('.json')) {
return JSON.parse(content);
}
throw new Error(`Unsupported file format: ${contractPath}`);
}
function normalizeServiceName(title) {
return title
.replace(/\s+/g, '_')
.replace(/[^a-zA-Z0-9_]/g, '')
.replace(/_+/g, '_')
.toLowerCase();
}
function generateAllFiles(spec, serviceName, baseURL) {
const types = generateTypes(spec);
const schemas = generateSchemas(spec);
const client = generateClient(spec, capitalize(serviceName), baseURL);
const index = generateIndex(serviceName);
return { types, schemas, client, index };
}
function generateIndex(serviceName) {
const className = capitalize(serviceName);
return `/**
* API Client exports
* Auto-generated by Arela
*/
export * from './types';
export * from './schemas';
export { ${className}Client, type ${className}ClientConfig } from './client';
`;
}
function capitalize(str) {
return str
.split('_')
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join('');
}
//# sourceMappingURL=typescript-generator.js.map