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: { pathToSchemaTemplate: 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 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) { 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, analysis: result }; }