nope/lib/helpers/generateSchemas.ts
2020-08-24 13:35:32 +02:00

119 lines
3.2 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 { IJsonSchema } from "../../types/IJSONSchema";
import { analyzeFiles, defaultClassFilter, defaultPropFilter } from "./analyzeTypescriptFiles";
import { createFile, createPath } from "./fileHelpers";
/**
* Generate the Client Templates.
* @param options
*/
export async function generateSchemas(options: {
pathToTemplate: string,
tempDir: string,
inputDir: string,
tsConfigFilePath: string,
}) {
// 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 template = await readFile(options.pathToTemplate, {
encoding: 'utf-8'
})
// Renderfuncting
const render = handlebars.compile(template);
// Generate the Files.
const files: {
className: string,
name: string,
content: string,
}[] = result.map(item => {
return {
className: item.className,
name: item.className + 'Schema',
content: render(item)
}
});
for (const file of files) {
await createFile(
// Generate the Path.
join(options.tempDir, 'classes', file.name + '.ts'),
file.content
);
}
// 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);
// Receive the Element
schemaMapping[file.className] = JSON.parse(JSON.stringify(_schema)) as IJsonSchema;
// Write down the Schema:
await createFile(
// Generate the Path.
join(options.tempDir, 'schema', file.name + '.json'),
JSON.stringify(_schema, undefined, 4)
);
}
return schemaMapping;
}