Fixing creation of functions

This commit is contained in:
Martin Karkowski 2020-09-08 10:46:52 +02:00
parent a54625e53a
commit 87311beab9
10 changed files with 2703 additions and 758 deletions

View File

@ -3,14 +3,14 @@ set DIR=%~dp0
cd "%DIR%"
SETLOCAL
echo Compiling Backend
(npx tsc -p ./tsconfigBackend.json --noEmit --pretty) && (
(npx tsc -p ./tsconfigBackend.json --pretty) && (
echo Generating API-Interface
@echo on
node ./dist/lib/cli/generateFiles
echo Generating API-Interface
@echo off
echo Compiling FrontendFiles
(npx tsc -p ./tsconfigBackend.json --noEmit --pretty) && (
(npx tsc -p ./tsconfigBackend.json --pretty) && (
echo Done
) || (
echo Done
@ -22,7 +22,7 @@ echo Compiling Backend
echo Generating API-Interface
@echo off
echo Compiling FrontendFiles
(npx tsc -p ./tsconfigBackend.json --noEmit --pretty) && (
(npx tsc -p ./tsconfigBackend.json --pretty) && (
echo Done
) || (
echo Done

View File

@ -11,8 +11,9 @@ import { createFile, createPath } from "./fileMethods";
* @param options
*/
export async function generateClientTemplate(options: {
pathToClientTemplate: string,
pathToInterfaceTemplate: string,
pathToClassInterfaceTemplate: string,
pathToFunctionInterfaceTemplate: string,
pathToBackendInterfaceTemplate: string,
outputDir: string,
inputDir: string,
tsConfigFilePath: string,
@ -20,11 +21,13 @@ export async function generateClientTemplate(options: {
logger?: Logger
}) {
// If there is a Logger Show a hint of the folders.
if (options.logger) {
options.logger.info('Templates will be stored in ' + options.outputDir);
}
// Define an Array containing elements that should be copied
// Copying the stuff is relevant for
const filesToCopy: {
src: string[],
name: string,
@ -35,11 +38,6 @@ export async function generateClientTemplate(options: {
path: ['dispatcher'],
src: ['lib', 'dispatcher']
},
// {
// name: 'nopeObservable.ts',
// path: ['observables'],
// src: ['lib', 'observables']
// },
{
name: 'nopeRemoteObservable.ts',
path: ['observables'],
@ -47,6 +45,7 @@ export async function generateClientTemplate(options: {
}
];
// Copy the Files.
for (const file of filesToCopy) {
// Create the Output dir (if it doenst exists)
await createPath(join(options.outputDir, ...file.path));
@ -58,7 +57,7 @@ export async function generateClientTemplate(options: {
);
if (options.logger) {
options.logger.info('Copied -> ' + file.name);
options.logger.info('Copied -> ' + join(options.outputDir, ...file.path, file.name));
}
}
@ -68,6 +67,7 @@ export async function generateClientTemplate(options: {
addFilesFromTsConfig: false,
});
// Readin the Sources of the Dir.
project.addSourceFilesAtPaths(options.inputDir);
// Readin the Source-Files.
@ -76,25 +76,14 @@ export async function generateClientTemplate(options: {
// 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.classes.map(item => {
// Enrich the Information.
result.classes = result.classes.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 as any).fileName = item.className + '_ClientInterface';
item.className = item.className + '_ClientInterface';
item.methods = item.methods.map(m => {
const methodUri = m.decoratorSettings.exportMethodToDispatcher ? m.decoratorSettings.exportMethodToDispatcher.uri || m.name : m.name;
@ -113,14 +102,56 @@ export async function generateClientTemplate(options: {
return p;
});
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 => {
return {
name: item.className + '.ts',
content: renderClient(item)
name: (item as any).fileName + '.ts',
content: renderClientInterface(item)
}
});
// load the File.
const interfaceTemplate = await readFile(options.pathToInterfaceTemplate, {
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, {
encoding: 'utf-8'
})
@ -130,25 +161,56 @@ export async function generateClientTemplate(options: {
await createFile(
// Generate the Path.
join(options.outputDir, 'BackendInterface.ts'),
renderInterface({ classes: result })
renderInterface(result)
);
if (options.logger) {
options.logger.info('Generated -> BackendInterface.ts');
options.logger.info('Generated -> ' + join(options.outputDir, 'BackendInterface.ts'));
}
for (const file of files) {
for (const file of classFiles) {
// Define the File Name:
const fileName = join(options.outputDir, 'clients', file.name);
await createFile(
// Generate the Path.
join(options.outputDir, 'clients', file.name),
fileName,
file.content
);
if (options.logger) {
options.logger.info('Generated -> ' + join('clients', fileName));
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,
file.content
);
if (options.logger) {
options.logger.info('Generated -> ' + fileName);
}
// Function to Determine new project files.

View File

@ -34,6 +34,10 @@ export class {{className}} {
public {{name}}: nopeRemoteObservable<{{{simplifiedSubType}}}>
{{/each}}
/**
* Creates an instance of the Class.
* @param _dispatcher The Dispatcher to use.
*/
constructor(protected _dispatcher: nopeDispatcher){
{{#each properties}}
this.{{name}} = new nopeRemoteObservable(_dispatcher,{
@ -42,21 +46,15 @@ export class {{className}} {
{{/each}}
}
{{!--
declaration: MethodDeclaration;
params: ParameterInformation[];
isAbstract: boolean;
name: string;
isAsync: boolean;
isGenerator: boolean;
isImplementation: boolean;
returnType: TypeInformation;
head: string;
Iterate over the Methods and create the Function Interface
--}}
{{#each methods}}
{{!-- Use the Docu of the Author --}}
{{{authorDescription}}}
public async {{name}}{{{head}}}{
// Perform the Method
// Perform the Method via the Dispatcher.
{{!-- Perform the Dispather-Call --}}
return await this._dispatcher.performCall<{{{returnType.simplifiedSubType}}}>('{{uri}}', [{{#each params}}{{name}}{{#unless @last}}, {{/unless}}{{/each}}])
}
{{/each}}

View File

@ -0,0 +1,17 @@
// Automatic Genearted File for Backendclass: "{{className}}"
// To update run `npm run build:backend`
import { nopeDispatcher } from "../dispatcher/nopeDispatcher"
{{!-- Define the Imports. --}}
{{#if imports.required}}
{{{imports.content}}}
{{/if}}
export function {{generatorName}}(_dispatcher: nopeDispatcher){
return async ({{#each params}}{{#if isBaseType}}{{name}}{{#if isOptional}}?{{/if}}: {{{originalCode}}}{{/if}}{{#unless isBaseType}}{{name}}{{#if isOptional}}?{{/if}}: {{{simplifiedType}}}{{/unless}}{{#unless @last}}, {{/unless}}{{/each}}) => {
// Perform the Method via the Dispatcher.
{{!-- Perform the Dispather-Call --}}
return await _dispatcher.performCall<{{{returnType.simplifiedSubType}}}>('{{uri}}', [{{#each params}}{{name}}{{#unless @last}}, {{/unless}}{{/each}}])
}
}

View File

@ -3,18 +3,29 @@
import { nopeDispatcher } from "./dispatcher/nopeDispatcher"
{{#each classes}}
import { {{className}} } from "./clients/{{className}}";
import { {{className}} } from "./clients/{{fileName}}";
{{/each}}
{{#each functions}}
import { {{generatorName}} } from "./functions/{{fileName}}";
{{/each}}
export class BackendInterface {
{{#each classes}}
public {{orginalName}}: {{className}};
public readonly {{orginalName}}: {{className}};
{{/each}}
{{#each functions}}
public readonly {{orginalName}}: ({{#each params}}{{#if isBaseType}}{{name}}{{#if isOptional}}?{{/if}}: {{{originalCode}}}{{/if}}{{#unless isBaseType}}{{name}}{{#if isOptional}}?{{/if}}: import("./functions/{{../fileName}}").{{{simplifiedType}}}{{/unless}}{{#unless @last}}, {{/unless}}{{/each}}) => Promise<{{{returnType.simplifiedSubType}}}>;
{{/each}}
constructor(protected _dispatcher: nopeDispatcher){
{{#each classes}}
this.{{orginalName}} = new {{className}}(_dispatcher);
{{/each}}
{{#each functions}}
this.{{orginalName}} = {{generatorName}}(_dispatcher);
{{/each}}
}
}

View File

@ -2,8 +2,9 @@
"dispatcher": {
"inputDir": "./test/*.ts",
"outputDir": "./resources/backend-api",
"pathToClientTemplate": "./lib/templates/clientInterface.handlebars",
"pathToInterfaceTemplate": "./lib/templates/backendInterface.handlebars",
"pathToClassInterfaceTemplate": "./lib/templates/backendClassInterface.handlebars",
"pathToFunctionInterfaceTemplate": "./lib/templates/backendFunctionInterface.handlebars",
"pathToBackendInterfaceTemplate": "./lib/templates/backendInterface.handlebars",
"tsConfigFilePath": "./tsconfigBackend.json"
},
"openapi": {

3243
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -32,38 +32,39 @@
"bootstrap": "^4.5.2",
"cors": "^2.8.5",
"express": "^4.17.1",
"express-openapi": "^7.0.0",
"express-openapi": "^7.0.1",
"handlebars": "^4.7.6",
"inquirer": "^7.3.3",
"inquirer-fuzzy-path": "^2.3.0",
"inversify": "^5.0.1",
"lodash": "^4.17.20",
"mqtt-pattern": "^1.2.0",
"next": "^9.5.2",
"next": "^9.5.3",
"node-ads": "^1.5.1",
"react": "^16.13.1",
"react-bootstrap": "^1.3.0",
"react-dom": "^16.13.1",
"react-icons": "^3.11.0",
"reflect-metadata": "^0.1.13",
"rxjs": "^6.6.2",
"rxjs": "^6.6.3",
"socket.io": "^2.3.0",
"socket.io-client": "^2.3.0",
"swagger-ui-react": "^3.32.4",
"ts-morph": "^7.3.0",
"swagger-ui-react": "^3.32.5",
"ts-morph": "^8.1.0",
"typescript-json-schema": "^0.43.0",
"uuid": "^8.3.0",
"winston": "^3.3.3"
},
"devDependencies": {
"@openapitools/openapi-generator-cli": "^1.0.15-4.3.1",
"@types/express": "^4.17.7",
"@types/lodash": "^4.14.159",
"@types/node": "^14.6.0",
"@types/react": "^16.9.46",
"@openapitools/openapi-generator-cli": "^1.0.18-4.3.1",
"@types/express": "^4.17.8",
"@types/lodash": "^4.14.161",
"@types/node": "^14.6.4",
"@types/react": "^16.9.49",
"@types/socket.io": "^2.1.11",
"@types/socket.io-client": "^1.4.33",
"openapi-typescript-codegen": "^0.4.10",
"typescript": "^3.9.7"
"npm-check-updates": "^8.1.1",
"openapi-typescript-codegen": "^0.4.11",
"typescript": "^4.0.2"
}
}

View File

@ -18,7 +18,8 @@
"isolatedModules": true,
"jsx": "preserve",
"downlevelIteration": true,
"experimentalDecorators": true
"experimentalDecorators": true,
"noImplicitAny": false
},
"include": [
"next-env.d.ts",

View File

@ -17,7 +17,8 @@
"removeComments": true,
"rootDir": "./",
"stripInternal": true,
"downlevelIteration": true
"downlevelIteration": true,
"noImplicitAny": false
},
"include": [
"next-env.d.ts",