UNPKG

@methodus/contracts

Version:

This package is part of the Methodus tollbelt. It's purpose is generating contract packages of the server code, to be used by JavaScript browser / server clients.

324 lines 14.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MethodusProject = void 0; const ts_morph_1 = require("ts-morph"); const path = require("path"); const interfaces_1 = require("../builder-models/interfaces"); const typescript_1 = require("typescript"); class MethodusProject { constructor(projectPath, packageName, options) { this.projectPath = projectPath; this.packageName = packageName; const activeOptions = {}; if (!options.tsConfig) { activeOptions.compilerOptions = { target: ts_morph_1.ScriptTarget.ES5, module: typescript_1.ModuleKind.CommonJS, moduleResolution: typescript_1.ModuleResolutionKind.NodeJs, declaration: true, sourceMap: true, preserveConstEnums: true, emitDecoratorMetadata: true, experimentalDecorators: true, outDir: `${projectPath}/lib`, }; } else { activeOptions.tsConfigFilePath = options.tsConfig; } this.project = new ts_morph_1.Project(Object.assign({ manipulationSettings: { // TwoSpaces, FourSpaces, EightSpaces, or Tab indentationText: ts_morph_1.IndentationText.Tab, // LineFeed or CarriageReturnLineFeed newLineKind: ts_morph_1.NewLineKind.CarriageReturnLineFeed, // Single or Double quoteKind: ts_morph_1.QuoteKind.Single, // Whether to change shorthand property assignments to property assignments // and add aliases to import & export specifiers (see more information in // the renaming section of the documentation). usePrefixAndSuffixTextForRename: false } }, activeOptions)); this.project.addSourceFilesAtPaths(`${projectPath}/src/**/*{.ts}`); this.sourceFiles = this.project.getSourceFiles(); } HandleConstructor(constructor, options) { if (options.isClient) { constructor.getParameters().forEach((param) => { const decorators = param.getDecorators(); if (decorators.length) { const decoratorRef = decorators[0]; if (decoratorRef.getText().indexOf('@M.') !== 0) { decoratorRef.replaceWithText(`@M.${decoratorRef.getText().substr(1)}`); } } }); } } HandleMethod(method, options) { method.getDecorators().forEach((decoratorRef) => { if (decoratorRef.getName() === 'Method' || decoratorRef.getName() === 'MethodPipe') { decoratorRef.getArguments().forEach((argument, index) => { if (index > 1) { try { decoratorRef.removeArgument(argument); return; } catch (error) { console.error(error); } } try { if (options.isClient && argument.getText().indexOf('Verbs.') === 0) { argument.replaceWithText(`M.${argument.getText()}`); } } catch (error) { console.error(error); } }); } if (options.isClient) { try { if (decoratorRef.getText().indexOf('@M.') !== 0) { decoratorRef.replaceWithText(`@M.${decoratorRef.getText().substr(1)}`); } } catch (error) { console.error(error); } } }); const xparams = method.getParameters(); xparams.forEach((arg, i) => { const paramDecorator = arg.getDecorators(); if (paramDecorator && paramDecorator[0] && paramDecorator[0].getName() === 'SecurityContext') { arg.remove(); } else { if (paramDecorator[0] && paramDecorator[0].getText().indexOf('@M') !== 0) { if (options.isClient) { paramDecorator[0].replaceWithText(`@M.P.${paramDecorator[0].getText().substr(1)}`); } else { paramDecorator[0].replaceWithText(`@Mapping.${paramDecorator[0].getText().substr(1)}`); } } } }); options.isMocked = this.HandleClientMethods(method, options); this.HandleMethodReturn(method, options); options.isMocked = false; } HandleClientMethods(method, options) { if (options.isClient) { method.getDecorators().forEach((decoratorRef) => { if (decoratorRef && decoratorRef.getName() === 'MethodMock') { const struct = decoratorRef.getStructure(); const mockResult = (struct.arguments && struct.arguments.length > 0) ? struct.arguments[0] : null; decoratorRef.remove(); method.getStatements().forEach((statement) => { statement.remove(); }); const methodStruct = method.getStructure(); const argsRow = (methodStruct.parameters) ? methodStruct.parameters.map((argument) => { return argument.name; }).join(',') : ''; method.setBodyText(writer => writer.writeLine(`return ${mockResult}.apply(this, [${argsRow}]);`)); this.project.saveSync(); options.isMocked = true; } }); } return options.isMocked; } HandleMethodReturn(method, options) { if (!options.isMocked) { method.getStatements().forEach((statement) => { statement.remove(); }); } if (method.getReturnTypeNode()) { const returnType = method.getReturnTypeNode(); if (returnType) { let retTypeText = returnType.getText(); if (retTypeText.indexOf('Promise<') > -1) { retTypeText = retTypeText.replace('Promise<', ''); retTypeText = retTypeText.substr(0, retTypeText.length - 1); } if (options.isClient) { if (retTypeText.indexOf('MethodResult<') > -1) { retTypeText = retTypeText.replace('MethodResult<', ''); retTypeText = retTypeText.substr(0, retTypeText.length - 1); } if (retTypeText === 'MethodResult') { retTypeText = 'any'; } const retNode = method.getReturnTypeNode(); if (retNode) { retNode.replaceWithText(`Promise<${retTypeText}>`); } } if (!options.isMocked && method.getBody()) { const methodBody = method.getBody(); if (methodBody) { method.insertText(methodBody.getEnd() - 1, ` return null! as ${retTypeText};\n `); } } } } } HandleIncludeFile(sourceFile, dirName, options) { const basePath = path.join(this.projectPath, 'src', 'includes'); this.project.createDirectory(basePath); this.project.saveSync(); const filePath = path.join(basePath, sourceFile.getBaseName()); const targetFile = this.project.createSourceFile(filePath, sourceFile.getStructure(), { overwrite: true }); if (options.isClient) { targetFile.getImportDeclarations().forEach((importDec) => { if (importDec.getText().indexOf('@methodus/server') > -1) { importDec.replaceWithText(`import * as M from '@methodus/platform-web'`); } }); } targetFile.saveSync(); } ProxifyFromFile(file, dirName, contractKey, options) { const basePath = path.join(this.projectPath, 'src', dirName); this.project.createDirectory(basePath); this.project.saveSync(); // create the file const sourceFile = this.project.createSourceFile(path.join(basePath, `${file.getBaseName()}`), undefined, { overwrite: true }); sourceFile.insertText(0, writer => writer.writeLine(interfaces_1.HEADER)); const classes = file.getClasses(); if (classes) { if (!options.isClient) { sourceFile.addImportDeclaration({ moduleSpecifier: '@methodus/framework-decorators', namedImports: ['Proxy', 'MethodConfig', 'Method'] }); sourceFile.addImportDeclaration({ moduleSpecifier: '@methodus/framework-decorators/commons', namedImports: ['Mapping', 'MethodResult', 'MethodResultStatus'] }); sourceFile.addImportDeclaration({ moduleSpecifier: '@methodus/platform-rest', namedImports: ['Verbs'] }); } else { sourceFile.addImportDeclaration({ moduleSpecifier: '@methodus/platform-web', namespaceImport: 'M' }); } sourceFile.addImportDeclaration({ moduleSpecifier: `../models`, }); sourceFile.addImportDeclaration({ moduleSpecifier: `../contracts`, }); const classDec = ts_morph_1.createWrappedNode(classes[0].compilerNode); try { const targetClass = sourceFile.addClass(classDec.getStructure()); // //methodConfig decorator targetClass.getDecorators().forEach((decoratorRef) => { if (decoratorRef.getName() === 'MethodConfig' || decoratorRef.getName() === 'MethodConfigBase') { decoratorRef.getArguments().forEach((argument, index) => { if (index === 1) { try { argument.replaceWithText('[]'); } catch (error) { console.error(error); } } }); } if (options.isClient && decoratorRef.getText().indexOf('@M.') !== 0) { decoratorRef.replaceWithText(`@M.${decoratorRef.getText().substr(1)}`); } }); if (!options.isClient) { const relativeFilename = file.getFilePath().replace(process.cwd().replace(/\\/g, '/'), ''); targetClass.insertDecorator(0, { name: 'Proxy.ProxyClass', arguments: [`'${this.packageName}'`, `'${classDec.getName()}'`, `'.${relativeFilename}'`] }); } targetClass.getConstructors().forEach((method) => { this.HandleConstructor(method, options); }); targetClass.getMethods().forEach((method) => { if (!method.hasModifier(typescript_1.SyntaxKind.PrivateKeyword)) { this.HandleMethod(method, options); } else { method.remove(); } }); if (options.isClient) { sourceFile.addStatements(`new ${classDec.getName()}()`); } sourceFile.fixMissingImports({}, { disableSuggestions: true }); sourceFile.saveSync(); } catch (error) { console.error(error); } } } ProxifyFromModel(file, dirName, modelKey) { const basePath = path.join(this.projectPath, 'src', dirName); this.project.createDirectory(basePath); this.project.saveSync(); // create the file const sourceFile = this.project.createSourceFile(path.join(basePath, `${file.getBaseName()}`), undefined, { overwrite: true }); const classes = file.getClasses(); if (!classes[0]) { console.log(`file ${file.getFilePath()} doesn't contain a class model`); return; } const classDec = ts_morph_1.createWrappedNode(classes[0].compilerNode); const modelClass = sourceFile.addClass(classDec.getStructure()); modelClass.getProperties().forEach((prop) => { prop.getDecorators().forEach((decorator) => { decorator.remove(); }); }); modelClass.removeExtends(); const constructor = modelClass.getConstructors()[0]; if (constructor) { constructor.removeBody().addBody(); } modelClass.getDecorators().forEach((decorator) => { decorator.remove(); }); const format = {}; const prefernces = { importModuleSpecifierPreference: 'non-relative' }; try { sourceFile.fixMissingImports(format, prefernces); sourceFile.saveSync(); } catch (error) { console.error(file.getFilePath()); console.error(error); } } Exportify(buildConfiguration) { const indexPath = path.join(this.projectPath, 'src', 'index.ts'); const indexFile = this.project.createSourceFile(indexPath, undefined, { overwrite: true }); ['models', 'includes', 'contracts'].forEach((name) => { if (buildConfiguration[name] && Object.keys(buildConfiguration[name]).length > 0) { indexFile.addExportDeclaration({ moduleSpecifier: `./${name}/`, }); } }); indexFile.saveSync(); return indexFile; } } exports.MethodusProject = MethodusProject; //# sourceMappingURL=project.js.map