nope/lib/helpers/generateTemplate.ts
2020-09-01 17:48:07 +02:00

173 lines
4.9 KiB
TypeScript

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 { analyzeFiles } from "./analyzeTypescriptFiles";
import { createFile, createPath } from "./fileMethods";
/**
* Generate the Client Templates.
* @param options
*/
export async function generateClientTemplate(options: {
pathToClientTemplate: string,
pathToInterfaceTemplate: string,
outputDir: string,
inputDir: string,
tsConfigFilePath: string,
// A Logger.
logger?: Logger
}) {
if (options.logger) {
options.logger.info('Templates will be stored in ' + options.outputDir);
}
const filesToCopy: {
src: string[],
name: string,
path: string[]
}[] = [
{
name: 'nopeDispatcher.ts',
path: ['dispatcher'],
src: ['lib', 'dispatcher']
},
// {
// name: 'nopeObservable.ts',
// path: ['observables'],
// src: ['lib', 'observables']
// },
{
name: 'nopeRemoteObservable.ts',
path: ['observables'],
src: ['lib', 'observables']
}
];
for (const file of filesToCopy) {
// Create the Output dir (if it doenst exists)
await createPath(join(options.outputDir, ...file.path));
// Copy the File.
await copyFile(
join(__dirname, '..', '..', '..', ...file.src, file.name),
join(options.outputDir, ...file.path, file.name)
);
if (options.logger) {
options.logger.info('Copied -> ' + file.name);
}
}
// 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);
// load the File.
const clientTemplate = await readFile(options.pathToClientTemplate, {
encoding: 'utf-8'
})
// Renderfuncting
const renderClient = handlebars.compile(clientTemplate);
// Generate the Files.
const files: {
name: string,
content: string,
}[] = result.map(item => {
// Extract the Class uri
const classUri = item.classDecorator.decoratorSettings.exportsElementsToDispatcher ? item.classDecorator.decoratorSettings.exportsElementsToDispatcher.uri || item.className : item.className;
(item as any).orginalName = item.className;
item.className = item.className + 'ClientInterface';
item.methods = item.methods.map(m => {
const methodUri = m.decoratorSettings.exportMethodToDispatcher ? m.decoratorSettings.exportMethodToDispatcher.uri || m.name : m.name;
(m as any).uri = classUri + '_' + methodUri;
return m;
});
item.properties = item.properties.map(p => {
const methodUri = p.decoratorSettings.exportPropertyToDispatcher ? p.decoratorSettings.exportPropertyToDispatcher.uri || p.name : p.name;
(p as any).uri = classUri + '_' + methodUri;
return p;
});
return {
name: item.className + '.ts',
content: renderClient(item)
}
});
// load the File.
const interfaceTemplate = await readFile(options.pathToInterfaceTemplate, {
encoding: 'utf-8'
})
// Renderfuncting
const renderInterface = handlebars.compile(interfaceTemplate);
await createFile(
// Generate the Path.
join(options.outputDir, 'BackendInterface.ts'),
renderInterface({ classes: result })
);
if (options.logger) {
options.logger.info('Generated -> BackendInterface.ts');
}
for (const file of files) {
// Define the File Name:
const fileName = join(options.outputDir, 'clients', file.name);
await createFile(
// Generate the Path.
join(options.outputDir, 'clients', file.name),
file.content
);
if (options.logger) {
options.logger.info('Generated -> ' + join('clients', 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();
}
}
// Compile the Template and parse the Code.
return true;
}