UNPKG

@nestia/sdk

Version:

Nestia SDK and Swagger generator

303 lines (293 loc) 10.6 kB
import ts from "typescript"; import { IJsDocTagInfo } from "typia"; import { IdentifierFactory } from "typia/lib/factories/IdentifierFactory"; import { INestiaProject } from "../../structures/INestiaProject"; import { ITypedWebSocketRoute } from "../../structures/ITypedWebSocketRoute"; import { FilePrinter } from "./FilePrinter"; import { ImportDictionary } from "./ImportDictionary"; import { SdkImportWizard } from "./SdkImportWizard"; import { SdkWebSocketNamespaceProgrammer } from "./SdkWebSocketNamespaceProgrammer"; import { SdkWebSocketParameterProgrammer } from "./SdkWebSocketParameterProgrammer"; export namespace SdkWebSocketRouteProgrammer { export const write = (project: INestiaProject) => (importer: ImportDictionary) => (route: ITypedWebSocketRoute): ts.Statement[] => [ FilePrinter.description( writeFunction(project)(importer)(route), writeDescription(route), ), SdkWebSocketNamespaceProgrammer.write(project)(importer)(route), ]; const writeDescription = (route: ITypedWebSocketRoute): string => { // MAIN DESCRIPTION const comments: string[] = route.description ? route.description.split("\n") : []; // COMMENT TAGS const tags: IJsDocTagInfo[] = route.jsDocTags.filter( (tag) => tag.name !== "param" || [...route.pathParameters, ...(route.query ? [route.query] : [])] .filter((p) => p.category === "param" || p.category === "query") .some((p) => p.name === tag.text?.[0]?.text), ); if (tags.length !== 0) { const content: string[] = tags.map((t) => t.text?.length ? `@${t.name} ${t.text.map((e) => e.text).join("")}` : `@${t.name}`, ); comments.push("", ...new Set(content)); } // POSTFIX if (!!comments.length) comments.push(""); comments.push( `@controller ${route.controller.class.name}.${route.name}`, `@path ${route.path}`, `@nestia Generated by Nestia - https://github.com/samchon/nestia`, ); return comments.join("\n"); }; const writeFunction = (project: INestiaProject) => (importer: ImportDictionary) => (route: ITypedWebSocketRoute): ts.FunctionDeclaration => { return ts.factory.createFunctionDeclaration( [ ts.factory.createModifier(ts.SyntaxKind.ExportKeyword), ts.factory.createModifier(ts.SyntaxKind.AsyncKeyword), ], undefined, route.name, undefined, [ IdentifierFactory.parameter( "connection", ts.factory.createTypeReferenceNode( SdkImportWizard.IConnection(importer), [ts.factory.createTypeReferenceNode(`${route.name}.Header`)], ), ), ...SdkWebSocketParameterProgrammer.getParameterDeclarations({ project, route, provider: true, prefix: true, }), ], ts.factory.createTypeReferenceNode("Promise", [ ts.factory.createTypeReferenceNode(`${route.name}.Output`), ]), ts.factory.createBlock( writeFunctionBody(project)(importer)(route), true, ), ); }; const writeFunctionBody = (project: INestiaProject) => (importer: ImportDictionary) => (route: ITypedWebSocketRoute): ts.Statement[] => { const access = (key: string) => project.config.keyword === true ? ts.factory.createPropertyAccessExpression( ts.factory.createIdentifier("props"), key, ) : ts.factory.createIdentifier(key); return [ local("url")(ts.factory.createTypeReferenceNode("string"))( joinPath( ts.factory.createCallExpression( ts.factory.createPropertyAccessExpression( ts.factory.createIdentifier(route.name), "path", ), [], project.config.keyword === true && SdkWebSocketParameterProgrammer.isPathEmpty(route) === false ? [ts.factory.createIdentifier("props")] : SdkWebSocketParameterProgrammer.getEntries({ project, route, provider: false, prefix: true, }).map((p) => ts.factory.createIdentifier(p.key)), ), ), ), local("connector")( ts.factory.createTypeReferenceNode( importer.external({ declaration: false, file: "tgrid", type: "element", name: "WebSocketConnector", }), [ ts.factory.createTypeReferenceNode(`${route.name}.Header`), ts.factory.createTypeReferenceNode(`${route.name}.Provider`), ts.factory.createTypeReferenceNode(`${route.name}.Listener`), ], ), )( ts.factory.createNewExpression( ts.factory.createIdentifier( importer.external({ declaration: false, file: "tgrid", type: "element", name: "WebSocketConnector", }), ), undefined, [ ts.factory.createAsExpression( ts.factory.createBinaryExpression( ts.factory.createPropertyAccessExpression( ts.factory.createIdentifier("connection"), "headers", ), ts.factory.createToken(ts.SyntaxKind.QuestionQuestionToken), ts.factory.createObjectLiteralExpression([], false), ), ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword), ), access("provider"), ], ), ), ts.factory.createExpressionStatement( ts.factory.createAwaitExpression( ts.factory.createCallExpression( ts.factory.createPropertyAccessExpression( ts.factory.createIdentifier("connector"), "connect", ), undefined, [ts.factory.createIdentifier("url")], ), ), ), local("driver")( ts.factory.createTypeReferenceNode( importer.external({ declaration: true, file: "tgrid", type: "element", name: "Driver", }), [ts.factory.createTypeReferenceNode(`${route.name}.Listener`)], ), )( ts.factory.createCallExpression( ts.factory.createPropertyAccessExpression( ts.factory.createIdentifier("connector"), "getDriver", ), undefined, undefined, ), ), ts.factory.createReturnStatement( ts.factory.createObjectLiteralExpression( [ ts.factory.createShorthandPropertyAssignment("connector"), ts.factory.createShorthandPropertyAssignment("driver"), ts.factory.createPropertyAssignment( ts.factory.createIdentifier("reconnect"), ts.factory.createArrowFunction( [ts.factory.createToken(ts.SyntaxKind.AsyncKeyword)], undefined, [], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.factory.createAwaitExpression( ts.factory.createCallExpression( ts.factory.createPropertyAccessExpression( ts.factory.createIdentifier("connector"), ts.factory.createIdentifier("connect"), ), undefined, [ts.factory.createIdentifier("url")], ), ), ), ), ], true, ), ), ]; }; } const local = (name: string) => (type: ts.TypeNode) => (expression: ts.Expression) => ts.factory.createVariableStatement( [], ts.factory.createVariableDeclarationList( [ ts.factory.createVariableDeclaration( name, undefined, type, expression, ), ], ts.NodeFlags.Const, ), ); const joinPath = (caller: ts.Expression) => ts.factory.createTemplateExpression(ts.factory.createTemplateHead("", ""), [ ts.factory.createTemplateSpan( ts.factory.createConditionalExpression( ts.factory.createCallExpression( ts.factory.createPropertyAccessExpression( ts.factory.createPropertyAccessExpression( ts.factory.createIdentifier("connection"), ts.factory.createIdentifier("host"), ), ts.factory.createIdentifier("endsWith"), ), undefined, [ts.factory.createStringLiteral("/")], ), ts.factory.createToken(ts.SyntaxKind.QuestionToken), ts.factory.createCallExpression( ts.factory.createPropertyAccessExpression( ts.factory.createPropertyAccessExpression( ts.factory.createIdentifier("connection"), ts.factory.createIdentifier("host"), ), ts.factory.createIdentifier("substring"), ), undefined, [ ts.factory.createNumericLiteral("0"), ts.factory.createBinaryExpression( ts.factory.createPropertyAccessExpression( ts.factory.createPropertyAccessExpression( ts.factory.createIdentifier("connection"), ts.factory.createIdentifier("host"), ), ts.factory.createIdentifier("length"), ), ts.factory.createToken(ts.SyntaxKind.MinusToken), ts.factory.createNumericLiteral("1"), ), ], ), ts.factory.createToken(ts.SyntaxKind.ColonToken), ts.factory.createPropertyAccessExpression( ts.factory.createIdentifier("connection"), ts.factory.createIdentifier("host"), ), ), ts.factory.createTemplateMiddle("", ""), ), ts.factory.createTemplateSpan( caller, ts.factory.createTemplateTail("", ""), ), ]);