nope/lib/helpers/generateOpenAPI.ts

128 lines
4.1 KiB
TypeScript
Raw Normal View History

2020-08-24 21:15:47 +00:00
import { copyFile, readFile } from "fs/promises";
import * as handlebars from 'handlebars';
import { join } from 'path';
import { Project } from "ts-morph";
import { Logger } from 'winston';
import { IJsonSchema } from "../../types/IJSONSchema";
2020-08-24 21:15:47 +00:00
import { IExportMethodToOpenAPIParameters } from "../openapi/nopeOpenAPIDecorators";
import { DecoratorInformation, MethodInformation } from "./analyzeTypescriptFiles";
import { createFile, createPath } from "./fileHelpers";
2020-08-24 21:15:47 +00:00
import { generateSchemas } from "./generateSchemas";
import { schemaGetDefinition } from "./jsonSchemaMethods";
2020-08-24 21:15:47 +00:00
function generateSchema(methodName: string, schema: IJsonSchema) {
return JSON.stringify(schemaGetDefinition(schema, "#/definitions/" + methodName), undefined, 4);
}
2020-08-24 21:15:47 +00:00
/**
* Generate the Client Templates.
* @param options
*/
export async function generateOpenAPI(options: {
pathToSchemaTemplate: string,
pathToApiTemplate: string,
tempDir: string,
outputDir: string,
2020-08-24 21:15:47 +00:00
inputDir: string,
tsConfigFilePath: string,
logger?: Logger,
2020-08-24 21:15:47 +00:00
}) {
// 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
})[] = []
await createPath(join(options.outputDir));
2020-08-24 21:15:47 +00:00
// Firstly copy the nopeDispatcher
await copyFile(
join(__dirname, '..', '..', '..', 'lib', 'dispatcher', 'nopeDispatcher.ts'),
join(options.outputDir, 'nopeDispatcher.ts')
2020-08-24 21:15:47 +00:00
);
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: generateSchema(method.name + 'Input', schemaMapping[relevantClass.className]),
outputSchema: generateSchema(method.name + 'Output', schemaMapping[relevantClass.className]),
2020-08-24 21:15:47 +00:00
}
const item = Object.assign(
method,
{
method: method.params.length > 0 ? 'POST' : 'GET',
operationId: settings.className + method.name,
2020-08-24 21:15:47 +00:00
},
settings,
method.decoratorSettings.exportMethodToOpenAPI as IExportMethodToOpenAPIParameters
);
methods.push(item);
const fileName = join(options.outputDir, item.baseUri, item.methodUri + '.ts');
2020-08-24 21:15:47 +00:00
// Write down the Schema:
await createFile(
// Generate the Path.
fileName,
renderAPI(item)
);
if (options.logger) {
options.logger.info('Generated -> ' + fileName);
}
2020-08-24 21:15:47 +00:00
// 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;
}