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";
|
2020-08-25 08:21:55 +00:00
|
|
|
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";
|
2020-08-25 22:11:26 +00:00
|
|
|
import { createFile, createPath } from "./fileMethods";
|
2020-08-24 21:15:47 +00:00
|
|
|
import { generateSchemas } from "./generateSchemas";
|
2020-08-25 08:21:55 +00:00
|
|
|
import { schemaGetDefinition } from "./jsonSchemaMethods";
|
2020-08-24 21:15:47 +00:00
|
|
|
|
2020-08-25 08:21:55 +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: {
|
2020-09-07 21:23:46 +00:00
|
|
|
pathToClassSchemaTemplate: string,
|
|
|
|
pathToFunctionSchemaTemplate: string,
|
2020-08-24 21:15:47 +00:00
|
|
|
pathToApiTemplate: string,
|
2020-09-07 21:23:46 +00:00
|
|
|
pathToFunctionTemplate: string,
|
2020-08-24 21:15:47 +00:00
|
|
|
tempDir: string,
|
2020-08-25 08:21:55 +00:00
|
|
|
outputDir: string,
|
2020-08-24 21:15:47 +00:00
|
|
|
inputDir: string,
|
|
|
|
tsConfigFilePath: string,
|
2020-08-25 08:21:55 +00:00
|
|
|
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
|
|
|
|
})[] = []
|
|
|
|
|
2020-08-25 08:21:55 +00:00
|
|
|
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'),
|
2020-08-25 08:21:55 +00:00
|
|
|
join(options.outputDir, 'nopeDispatcher.ts')
|
2020-08-24 21:15:47 +00:00
|
|
|
);
|
|
|
|
|
2020-09-07 18:12:19 +00:00
|
|
|
for (const relevantClass of analysis.classes) {
|
2020-08-24 21:15:47 +00:00
|
|
|
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,
|
2020-08-25 08:21:55 +00:00
|
|
|
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,
|
|
|
|
{
|
2020-08-25 08:21:55 +00:00
|
|
|
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);
|
|
|
|
|
2020-08-25 08:21:55 +00:00
|
|
|
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)
|
|
|
|
);
|
|
|
|
|
2020-08-25 08:21:55 +00:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-07 21:23:46 +00:00
|
|
|
// load the File.
|
|
|
|
const typescriptFunctionTemplate = await readFile(options.pathToApiTemplate, {
|
|
|
|
encoding: 'utf-8'
|
|
|
|
})
|
|
|
|
|
|
|
|
// Renderfuncting
|
|
|
|
const renderFunction = handlebars.compile(typescriptFunctionTemplate);
|
|
|
|
|
|
|
|
for (const func of analysis.functions) {
|
|
|
|
// Iterate over the available Functions.
|
|
|
|
const fileName = join(options.outputDir, 'functions', func.name + '.ts');
|
|
|
|
|
|
|
|
const settings: {
|
|
|
|
className: string,
|
|
|
|
baseUri: string,
|
|
|
|
methodUri: string,
|
|
|
|
// useCustomParameters: boolean,
|
|
|
|
useDefaultParameters: boolean,
|
|
|
|
// customParameters: string,
|
|
|
|
inputSchema: string,
|
|
|
|
outputSchema: string
|
|
|
|
} = {
|
|
|
|
className: func.className,
|
|
|
|
baseUri: 'functions',
|
|
|
|
methodUri: func.name,
|
|
|
|
// customParameters: JSON.stringify(method.decoratorSettings.exportMethodToOpenAPI.parameters || [], undefined, 4),
|
|
|
|
// useCustomParameters: Array.isArray(method.decoratorSettings.exportMethodToOpenAPI.parameters),
|
|
|
|
useDefaultParameters: func.params.length > 0,
|
|
|
|
inputSchema: generateSchema(func.name + 'Input', schemaMapping[func.className]),
|
|
|
|
outputSchema: generateSchema(func.name + 'Output', schemaMapping[func.className]),
|
|
|
|
}
|
|
|
|
|
|
|
|
const item = Object.assign(
|
|
|
|
func,
|
|
|
|
{
|
|
|
|
method: func.params.length > 0 ? 'POST' : 'GET',
|
|
|
|
operationId: settings.className + func.name,
|
|
|
|
},
|
|
|
|
settings,
|
|
|
|
// method.decoratorSettings.exportMethodToOpenAPI as IExportMethodToOpenAPIParameters
|
|
|
|
);
|
|
|
|
|
|
|
|
// const item = Object.assign(
|
|
|
|
// func,
|
|
|
|
// {
|
|
|
|
// method: 'POST',
|
|
|
|
// operationId: 'function' + func.name,
|
|
|
|
// },
|
|
|
|
// // settings,
|
|
|
|
// );
|
|
|
|
|
|
|
|
// Write down the Schema:
|
|
|
|
await createFile(
|
|
|
|
// Generate the Path.
|
|
|
|
fileName,
|
|
|
|
renderFunction(item)
|
|
|
|
);
|
|
|
|
|
|
|
|
if (options.logger) {
|
|
|
|
options.logger.info('Generated -> ' + fileName);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-24 21:15:47 +00:00
|
|
|
return schemaMapping;
|
|
|
|
}
|