@nestia/sdk
Version:
Nestia SDK and Swagger generator
266 lines (256 loc) • 8.95 kB
text/typescript
import ts from "typescript";
import { IJsDocTagInfo } from "typia";
import { IdentifierFactory } from "typia/lib/factories/IdentifierFactory";
import { ITypedWebSocketRoute } from "../../structures/ITypedWebSocketRoute";
import { FilePrinter } from "./FilePrinter";
import { ImportDictionary } from "./ImportDictionary";
import { SdkAliasCollection } from "./SdkAliasCollection";
import { SdkImportWizard } from "./SdkImportWizard";
import { SdkWebSocketNamespaceProgrammer } from "./SdkWebSocketNamespaceProgrammer";
export namespace SdkWebSocketRouteProgrammer {
export const write =
(importer: ImportDictionary) =>
(route: ITypedWebSocketRoute): ts.Statement[] => [
FilePrinter.description(
writeFunction(importer)(route),
writeDescription(route),
),
SdkWebSocketNamespaceProgrammer.write(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.parameters
.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 =
(importer: ImportDictionary) =>
(route: ITypedWebSocketRoute): ts.FunctionDeclaration =>
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`)],
),
),
...route.parameters
.filter((p) => p.category === "param" || p.category === "query")
.map((p) =>
IdentifierFactory.parameter(
p.name,
p.category === "param"
? SdkAliasCollection.name(p)
: ts.factory.createTypeReferenceNode(`${route.name}.Query`),
),
),
IdentifierFactory.parameter(
"provider",
ts.factory.createTypeReferenceNode(`${route.name}.Provider`),
),
],
ts.factory.createTypeReferenceNode("Promise", [
ts.factory.createTypeReferenceNode(`${route.name}.Output`),
]),
ts.factory.createBlock(writeFunctionBody(importer)(route), true),
);
const writeFunctionBody =
(importer: ImportDictionary) =>
(route: ITypedWebSocketRoute): ts.Statement[] => [
local("connector")(
ts.factory.createTypeReferenceNode(
importer.external({
type: false,
library: "tgrid",
instance: "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({
type: false,
library: "tgrid",
instance: "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),
),
ts.factory.createIdentifier("provider"),
],
),
),
ts.factory.createExpressionStatement(
ts.factory.createAwaitExpression(
ts.factory.createCallExpression(
ts.factory.createPropertyAccessExpression(
ts.factory.createIdentifier("connector"),
"connect",
),
undefined,
[
joinPath(
ts.factory.createCallExpression(
ts.factory.createPropertyAccessExpression(
ts.factory.createIdentifier(route.name),
"path",
),
[],
route.parameters
.filter(
(p) => p.category === "param" || p.category === "query",
)
.map((x) => ts.factory.createIdentifier(x.name)),
),
),
],
),
),
),
local("driver")(
ts.factory.createTypeReferenceNode(
importer.external({
type: true,
library: "tgrid",
instance: "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"),
],
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("", ""),
),
]);