141 lines
3.7 KiB
TypeScript
141 lines
3.7 KiB
TypeScript
import { readFile } from "fs/promises";
|
|
import * as handlebars from 'handlebars';
|
|
import { join } from 'path';
|
|
import { Project } from "ts-morph";
|
|
import * as TJS from "typescript-json-schema";
|
|
import { Logger } from 'winston';
|
|
import { IJsonSchema } from "../../types/IJSONSchema";
|
|
import { analyzeFiles, defaultClassFilter, defaultPropFilter } from "./analyzeTypescriptFiles";
|
|
import { createFile, createPath } from "./fileMethods";
|
|
import { flattenSchema } from "./jsonSchemaMethods";
|
|
|
|
|
|
/**
|
|
* Generate the Client Templates.
|
|
* @param options
|
|
*/
|
|
export async function generateSchemas(options: {
|
|
pathToSchemaTemplate: string,
|
|
tempDir: string,
|
|
inputDir: string,
|
|
tsConfigFilePath: string,
|
|
logger?: Logger,
|
|
}) {
|
|
|
|
// Create the Output dir (if it doenst exists)
|
|
await createPath(options.tempDir);
|
|
|
|
// Function to Determine new project files.
|
|
const project = new Project({
|
|
tsConfigFilePath: options.tsConfigFilePath,
|
|
addFilesFromTsConfig: false,
|
|
});
|
|
|
|
project.addSourceFilesAtPaths(options.inputDir);
|
|
|
|
// Readin the Source-Files.
|
|
const sourceFiles = project.getSourceFiles();
|
|
|
|
// Generate the Files
|
|
const result = analyzeFiles(sourceFiles, {
|
|
classDecorator: 'exportsElementsToOpenAPI',
|
|
methodDecorator: 'exportMethodToOpenAPI',
|
|
propertyDecorator: 'exportPropertyToOpenAPI',
|
|
filterClasses: defaultClassFilter({
|
|
classDecorator: 'exportsElementsToOpenAPI',
|
|
classInterface: ''
|
|
}),
|
|
filterMethods: (cl, method) => {
|
|
return method.isImplementation && method.isAsync && method.params.filter(param => param.baseType === 'function').length === 0
|
|
},
|
|
filterProperties: defaultPropFilter({
|
|
propertyDecorator: 'exportPropertyToDispatcher',
|
|
propertyType: 'nopeObservable'
|
|
}),
|
|
checkImport: type => type !== 'nopeObservable'
|
|
}
|
|
);
|
|
|
|
// load the File.
|
|
const schemaTemplate = await readFile(options.pathToSchemaTemplate, {
|
|
encoding: 'utf-8'
|
|
})
|
|
|
|
// Renderfuncting
|
|
const renderSchema = handlebars.compile(schemaTemplate);
|
|
|
|
// Generate the Files.
|
|
const files: {
|
|
className: string,
|
|
name: string,
|
|
content: string,
|
|
}[] = result.map(item => {
|
|
return {
|
|
className: item.className,
|
|
name: item.className + 'Schema',
|
|
content: renderSchema(item)
|
|
}
|
|
});
|
|
|
|
for (const file of files) {
|
|
|
|
// Generate the Path.
|
|
const fileName = join(options.tempDir, 'classes', file.name + '.ts');
|
|
await createFile(
|
|
fileName,
|
|
file.content
|
|
);
|
|
|
|
if (options.logger) {
|
|
options.logger.info('Generated -> ' + fileName);
|
|
}
|
|
}
|
|
|
|
// After all files has been written => Generate the Schemas:
|
|
const _settings: TJS.PartialArgs = {
|
|
required: true,
|
|
};
|
|
|
|
// Options for the TJS.Compiler;
|
|
const compilerOptions: TJS.CompilerOptions = {
|
|
strictNullChecks: true,
|
|
skipLibCheck: true
|
|
};
|
|
|
|
const schemaMapping: { [index: string]: IJsonSchema } = {};
|
|
|
|
for (const file of files) {
|
|
const _program = TJS.getProgramFromFiles(
|
|
[join(options.tempDir, 'classes', file.name + '.ts')],
|
|
compilerOptions
|
|
);
|
|
|
|
// We can either get the schema for one file and one type...
|
|
const _schema = TJS.generateSchema(_program, "*", _settings);
|
|
|
|
// Flatten the Schema.
|
|
const _flattendSchema = flattenSchema(_schema as any)
|
|
|
|
// Receive the Element
|
|
schemaMapping[file.className] = _flattendSchema;
|
|
|
|
// Generate the Path.
|
|
const fileName = join(options.tempDir, 'schema', file.name + '.json')
|
|
|
|
// Write down the Schema:
|
|
await createFile(
|
|
fileName,
|
|
JSON.stringify(_flattendSchema, undefined, 4)
|
|
);
|
|
|
|
if (options.logger) {
|
|
options.logger.info('Generated -> ' + fileName);
|
|
}
|
|
}
|
|
|
|
return {
|
|
schemaMapping,
|
|
analysis: result
|
|
};
|
|
}
|