2020-08-24 21:16:09 +00:00
|
|
|
import { copyFile, readFile } from "fs/promises";
|
2020-08-24 07:37:48 +00:00
|
|
|
import * as handlebars from 'handlebars';
|
|
|
|
import { join } from 'path';
|
2020-08-24 21:16:09 +00:00
|
|
|
import { Project } from "ts-morph";
|
2020-08-25 08:21:55 +00:00
|
|
|
import { Logger } from 'winston';
|
2020-08-24 21:16:09 +00:00
|
|
|
import { analyzeFiles } from "./analyzeTypescriptFiles";
|
2020-08-25 22:11:26 +00:00
|
|
|
import { createFile, createPath } from "./fileMethods";
|
2020-08-23 07:25:10 +00:00
|
|
|
|
|
|
|
/**
|
2020-08-24 07:37:48 +00:00
|
|
|
* Generate the Client Templates.
|
|
|
|
* @param options
|
2020-08-23 07:25:10 +00:00
|
|
|
*/
|
2020-08-24 07:37:48 +00:00
|
|
|
export async function generateClientTemplate(options: {
|
2020-09-08 08:46:52 +00:00
|
|
|
pathToClassInterfaceTemplate: string,
|
|
|
|
pathToFunctionInterfaceTemplate: string,
|
|
|
|
pathToBackendInterfaceTemplate: string,
|
2020-08-24 07:37:48 +00:00
|
|
|
outputDir: string,
|
|
|
|
inputDir: string,
|
|
|
|
tsConfigFilePath: string,
|
2020-08-25 08:21:55 +00:00
|
|
|
// A Logger.
|
|
|
|
logger?: Logger
|
2020-08-24 07:37:48 +00:00
|
|
|
}) {
|
|
|
|
|
2020-09-08 08:46:52 +00:00
|
|
|
// If there is a Logger Show a hint of the folders.
|
2020-08-25 08:21:55 +00:00
|
|
|
if (options.logger) {
|
|
|
|
options.logger.info('Templates will be stored in ' + options.outputDir);
|
|
|
|
}
|
|
|
|
|
2020-09-08 08:46:52 +00:00
|
|
|
// Define an Array containing elements that should be copied
|
|
|
|
// Copying the stuff is relevant for
|
2020-08-25 10:33:33 +00:00
|
|
|
const filesToCopy: {
|
|
|
|
src: string[],
|
|
|
|
name: string,
|
|
|
|
path: string[]
|
|
|
|
}[] = [
|
|
|
|
{
|
|
|
|
name: 'nopeDispatcher.ts',
|
|
|
|
path: ['dispatcher'],
|
|
|
|
src: ['lib', 'dispatcher']
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: 'nopeRemoteObservable.ts',
|
|
|
|
path: ['observables'],
|
|
|
|
src: ['lib', 'observables']
|
|
|
|
}
|
|
|
|
];
|
|
|
|
|
2020-09-08 08:46:52 +00:00
|
|
|
// Copy the Files.
|
2020-08-25 10:33:33 +00:00
|
|
|
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) {
|
2020-09-08 08:46:52 +00:00
|
|
|
options.logger.info('Copied -> ' + join(options.outputDir, ...file.path, file.name));
|
2020-08-25 10:33:33 +00:00
|
|
|
}
|
2020-08-25 10:50:17 +00:00
|
|
|
}
|
2020-08-24 07:37:48 +00:00
|
|
|
|
|
|
|
// Function to Determine new project files.
|
|
|
|
const project = new Project({
|
|
|
|
tsConfigFilePath: options.tsConfigFilePath,
|
|
|
|
addFilesFromTsConfig: false,
|
|
|
|
});
|
|
|
|
|
2020-09-08 08:46:52 +00:00
|
|
|
// Readin the Sources of the Dir.
|
2020-08-24 07:37:48 +00:00
|
|
|
project.addSourceFilesAtPaths(options.inputDir);
|
|
|
|
|
|
|
|
// Readin the Source-Files.
|
|
|
|
const sourceFiles = project.getSourceFiles();
|
|
|
|
|
|
|
|
// Generate the Files
|
|
|
|
const result = analyzeFiles(sourceFiles);
|
|
|
|
|
2020-09-08 08:46:52 +00:00
|
|
|
// Enrich the Information.
|
|
|
|
result.classes = result.classes.map(item => {
|
2020-08-25 10:33:33 +00:00
|
|
|
// Extract the Class uri
|
|
|
|
const classUri = item.classDecorator.decoratorSettings.exportsElementsToDispatcher ? item.classDecorator.decoratorSettings.exportsElementsToDispatcher.uri || item.className : item.className;
|
|
|
|
|
2020-08-25 10:50:17 +00:00
|
|
|
(item as any).orginalName = item.className;
|
2020-09-08 08:46:52 +00:00
|
|
|
(item as any).fileName = item.className + '_ClientInterface';
|
|
|
|
item.className = item.className + '_ClientInterface';
|
2020-08-25 10:33:33 +00:00
|
|
|
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;
|
|
|
|
});
|
2020-08-24 07:37:48 +00:00
|
|
|
|
2020-09-08 08:46:52 +00:00
|
|
|
return item;
|
|
|
|
});
|
|
|
|
|
|
|
|
result.functions = result.functions.map(item => {
|
|
|
|
// Adding a generatorName
|
|
|
|
(item as any).generatorName = 'generate_' + item.name + '_Accessor';
|
|
|
|
(item as any).orginalName = item.name;
|
|
|
|
(item as any).fileName = item.name + '_ClientInterface';
|
|
|
|
return item;
|
|
|
|
});
|
|
|
|
|
|
|
|
// load the File.
|
|
|
|
const clientTemplate = await readFile(options.pathToClassInterfaceTemplate, {
|
|
|
|
encoding: 'utf-8'
|
|
|
|
})
|
|
|
|
|
|
|
|
// Renderfuncting
|
|
|
|
const renderClientInterface = handlebars.compile(clientTemplate);
|
|
|
|
|
|
|
|
// Generate the Files.
|
|
|
|
const classFiles: {
|
|
|
|
name: string,
|
|
|
|
content: string,
|
|
|
|
}[] = result.classes.map(item => {
|
2020-08-24 07:37:48 +00:00
|
|
|
return {
|
2020-09-08 08:46:52 +00:00
|
|
|
name: (item as any).fileName + '.ts',
|
|
|
|
content: renderClientInterface(item)
|
2020-08-23 07:25:10 +00:00
|
|
|
}
|
2020-08-24 07:37:48 +00:00
|
|
|
});
|
|
|
|
|
2020-08-25 10:50:17 +00:00
|
|
|
// load the File.
|
2020-09-08 08:46:52 +00:00
|
|
|
const functionTemplate = await readFile(options.pathToFunctionInterfaceTemplate, {
|
|
|
|
encoding: 'utf-8'
|
|
|
|
})
|
|
|
|
|
|
|
|
// Renderfuncting
|
|
|
|
const renderFunctionInterface = handlebars.compile(functionTemplate);
|
|
|
|
|
|
|
|
const functionFiles: {
|
|
|
|
name: string,
|
|
|
|
content: string,
|
|
|
|
}[] = result.functions.map(func => {
|
|
|
|
return {
|
|
|
|
name: (func as any).fileName + '.ts',
|
|
|
|
content: renderFunctionInterface(func)
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// load the File.
|
|
|
|
const interfaceTemplate = await readFile(options.pathToBackendInterfaceTemplate, {
|
2020-08-25 10:50:17 +00:00
|
|
|
encoding: 'utf-8'
|
|
|
|
})
|
|
|
|
|
|
|
|
// Renderfuncting
|
|
|
|
const renderInterface = handlebars.compile(interfaceTemplate);
|
|
|
|
|
|
|
|
await createFile(
|
|
|
|
// Generate the Path.
|
|
|
|
join(options.outputDir, 'BackendInterface.ts'),
|
2020-09-08 08:46:52 +00:00
|
|
|
renderInterface(result)
|
2020-08-25 10:50:17 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
if (options.logger) {
|
2020-09-08 08:46:52 +00:00
|
|
|
options.logger.info('Generated -> ' + join(options.outputDir, 'BackendInterface.ts'));
|
2020-08-25 10:50:17 +00:00
|
|
|
}
|
|
|
|
|
2020-09-08 08:46:52 +00:00
|
|
|
for (const file of classFiles) {
|
2020-08-25 08:21:55 +00:00
|
|
|
// Define the File Name:
|
2020-08-24 21:16:09 +00:00
|
|
|
const fileName = join(options.outputDir, 'clients', file.name);
|
2020-08-25 08:21:55 +00:00
|
|
|
|
2020-08-24 07:37:48 +00:00
|
|
|
await createFile(
|
|
|
|
// Generate the Path.
|
2020-09-08 08:46:52 +00:00
|
|
|
fileName,
|
|
|
|
file.content
|
|
|
|
);
|
|
|
|
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (const file of functionFiles) {
|
|
|
|
// Define the File Name:
|
|
|
|
const fileName = join(options.outputDir, 'functions', file.name);
|
|
|
|
|
|
|
|
await createFile(
|
|
|
|
// Generate the Path.
|
|
|
|
fileName,
|
2020-08-24 07:37:48 +00:00
|
|
|
file.content
|
2020-08-24 21:16:09 +00:00
|
|
|
);
|
|
|
|
|
2020-08-25 08:21:55 +00:00
|
|
|
if (options.logger) {
|
2020-09-08 08:46:52 +00:00
|
|
|
options.logger.info('Generated -> ' + fileName);
|
2020-08-25 08:21:55 +00:00
|
|
|
}
|
|
|
|
|
2020-08-24 21:16:09 +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-08-23 07:25:10 +00:00
|
|
|
}
|
|
|
|
|
2020-08-24 07:37:48 +00:00
|
|
|
// Compile the Template and parse the Code.
|
2020-08-24 21:16:09 +00:00
|
|
|
return true;
|
2020-08-23 07:25:10 +00:00
|
|
|
}
|