import { copyFile, readFile } from "fs/promises"; import * as handlebars from 'handlebars'; import { join } from 'path'; import { Project } from "ts-morph"; import { IExportMethodToOpenAPIParameters } from "../openapi/nopeOpenAPIDecorators"; import { DecoratorInformation, MethodInformation } from "./analyzeTypescriptFiles"; import { createFile } from "./fileHelpers"; import { generateSchemas } from "./generateSchemas"; /** * Generate the Client Templates. * @param options */ export async function generateOpenAPI(options: { pathToSchemaTemplate: string, pathToApiTemplate: string, tempDir: string, inputDir: string, tsConfigFilePath: string, }) { // Create the Output dir (if it doenst exists) const { schemaMapping, analysis } = await generateSchemas(options) // load the File. const typescriptTemplate = await readFile(options.pathToApiTemplate, { encoding: 'utf-8' }) // Renderfuncting const renderAPI = handlebars.compile(typescriptTemplate); const methods: (IExportMethodToOpenAPIParameters & MethodInformation & DecoratorInformation & { className: string, baseUri: string, methodUri: string, useCustomParameters: boolean, useDefaultParameters: boolean, customParameters: string, inputSchema: string, outputSchema: string })[] = [] // Firstly copy the nopeDispatcher await copyFile( join(__dirname, '..', '..', '..', 'lib', 'dispatcher', 'nopeDispatcher.ts'), join(options.tempDir, 'api', 'nopeDispatcher.ts') ); for (const relevantClass of analysis) { for (const method of relevantClass.methods) { const settings: { className: string, baseUri: string, methodUri: string, useCustomParameters: boolean, useDefaultParameters: boolean, customParameters: string, inputSchema: string, outputSchema: string } = { className: relevantClass.className, baseUri: relevantClass.classDecorator.decoratorSettings.exportsElementsToOpenAPI.uri || relevantClass.className, methodUri: method.decoratorSettings.exportMethodToOpenAPI.uri || method.name, customParameters: JSON.stringify(method.decoratorSettings.exportMethodToOpenAPI.parameters || [], undefined, 4), useCustomParameters: Array.isArray(method.decoratorSettings.exportMethodToOpenAPI.parameters), useDefaultParameters: method.params.length > 0, inputSchema: JSON.stringify(schemaMapping[relevantClass.className], undefined, 4), outputSchema: JSON.stringify(schemaMapping[relevantClass.className], undefined, 4) } const item = Object.assign( method, { method: method.params.length > 0 ? 'POST' : 'GET' }, settings, method.decoratorSettings.exportMethodToOpenAPI as IExportMethodToOpenAPIParameters ); methods.push(item); const fileName = join(options.tempDir, 'api', item.baseUri, item.methodUri + '.ts'); // Write down the Schema: await createFile( // Generate the Path. fileName, renderAPI(item) ); // Function to Determine new project files. const project = new Project({ tsConfigFilePath: options.tsConfigFilePath, addFilesFromTsConfig: false, }); project.addSourceFileAtPath(fileName); // Readin the Source-Files. const sourceFiles = project.getSourceFiles(); for (const file of sourceFiles) { file.formatText(); await file.save(); } } } return schemaMapping; }