diff --git a/examples/handlers/hello/put.ts b/examples/handlers/hello/put.ts index f18d7f6..a17d43e 100644 --- a/examples/handlers/hello/put.ts +++ b/examples/handlers/hello/put.ts @@ -1,3 +1,13 @@ +import { RouteShorthandOptions } from 'fastify'; +import schema from '../interfaces/JSC_IReqPokeHello'; + +export const option: RouteShorthandOptions = { + schema: { + querystring: schema.properties?.Querystring, + body: schema.properties?.Body, + }, +}; + export async function handler() { return 'hello'; } diff --git a/package.json b/package.json index 36b98dc..57905dc 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,8 @@ } }, "files": [ - "dist" + "dist", + "templates" ], "bugs": { "url": "https://github.com/imjuni/fast-maker/issues" diff --git a/src/compilers/interfaces/IFastifyRouteOptions.ts b/src/compilers/interfaces/IFastifyRouteOptions.ts index 884988b..7b1ef10 100644 --- a/src/compilers/interfaces/IFastifyRouteOptions.ts +++ b/src/compilers/interfaces/IFastifyRouteOptions.ts @@ -1,3 +1,4 @@ +import type { TFastifyRouteOption } from '#/compilers/interfaces/TFastifyRouteOption'; import type * as tsm from 'ts-morph'; export interface IFastifyRouteOptions { @@ -8,7 +9,7 @@ export interface IFastifyRouteOptions { }; node: { - option?: tsm.Node; + option?: TFastifyRouteOption; methods?: tsm.Node; map?: tsm.Node; }; diff --git a/src/compilers/interfaces/TFastifyRouteOption.ts b/src/compilers/interfaces/TFastifyRouteOption.ts new file mode 100644 index 0000000..222e51d --- /dev/null +++ b/src/compilers/interfaces/TFastifyRouteOption.ts @@ -0,0 +1,35 @@ +import type * as tsm from 'ts-morph'; + +interface IFastifyRouteOption { + /** 동기/비동기 함수 정보 */ + kind: 'async' | 'sync'; + + /** 이름 */ + name: string; + + /** 경로 */ + path: string; +} + +export type TFastifyRouteOption = + | (IFastifyRouteOption & { + /** 함수/ 화살표 함수 정보 */ + type: 'variable'; + + /** 실제 노드 정보 */ + node: tsm.VariableDeclaration; + }) + | (IFastifyRouteOption & { + /** 함수/ 화살표 함수 정보 */ + type: 'function'; + + /** 실제 노드 정보 */ + node: tsm.FunctionDeclaration; + }) + | (IFastifyRouteOption & { + /** 함수/ 화살표 함수 정보 */ + type: 'arrow'; + + /** 실제 노드 정보 */ + node: tsm.ArrowFunction; + }); diff --git a/src/compilers/navigate/__tests__/local.module.test.ts b/src/compilers/navigate/__tests__/local.module.test.ts index ddf27cb..6438d54 100644 --- a/src/compilers/navigate/__tests__/local.module.test.ts +++ b/src/compilers/navigate/__tests__/local.module.test.ts @@ -1,5 +1,5 @@ import { getResolvedInFileImportedModules } from '#/compilers/navigate/getResolvedInFileImportedModules'; -import { getRouteNode } from '#/compilers/routes/getRouteNode'; +import { getRouteFunction } from '#/compilers/routes/getRouteFunction'; import { getTypeReferences } from '#/compilers/type-tools/getTypeReferences'; import { CE_EXT_KIND } from '#/configs/const-enum/CE_EXT_KIND'; import { atOrThrow, orThrow } from 'my-easy-fp'; @@ -41,7 +41,7 @@ export function handler(req: FastifyRequest<{ Querystring: TQuerystring, Params: project.createSourceFile(path.join('examples', name), code, { overwrite }); const sourceFile = create(filename01, source01, true); - const node = orThrow(getRouteNode(sourceFile)); + const node = orThrow(getRouteFunction(sourceFile)); const parameters = node.node.getParameters(); const parameter = atOrThrow(parameters, 0); const types = getTypeReferences(parameter); diff --git a/src/compilers/navigate/__tests__/property.signature.test.ts b/src/compilers/navigate/__tests__/property.signature.test.ts index 61279a2..be3a8bb 100644 --- a/src/compilers/navigate/__tests__/property.signature.test.ts +++ b/src/compilers/navigate/__tests__/property.signature.test.ts @@ -1,5 +1,5 @@ import { getPropertySignatures } from '#/compilers/navigate/getPropertySignatures'; -import { getRouteNodeOrThrow } from '#/compilers/routes/getRouteNodeOrThrow'; +import { getRouteFunctionOrThrow } from '#/compilers/routes/getRouteFunctionOrThrow'; import { atOrThrow } from 'my-easy-fp'; import { randomUUID } from 'node:crypto'; import path from 'node:path'; @@ -29,7 +29,7 @@ export function handler(req: { Q: { name: string }; B: { age: number} }) { project.createSourceFile(path.join('examples', name), code, { overwrite }); const sourceFile02 = create(filename01, source01.trim(), true); - const node = getRouteNodeOrThrow(sourceFile02); + const node = getRouteFunctionOrThrow(sourceFile02); const parameter = atOrThrow(node.node.getParameters(), 0); const r01 = getPropertySignatures(parameter); @@ -49,7 +49,7 @@ export function handler(req: ITestInfoType01) { project.createSourceFile(path.join('examples', name), code, { overwrite }); const sourceFile02 = create(filename01, source01.trim(), true); - const node = getRouteNodeOrThrow(sourceFile02); + const node = getRouteFunctionOrThrow(sourceFile02); const parameter = atOrThrow(node.node.getParameters(), 0); const r01 = getPropertySignatures(parameter); @@ -69,7 +69,7 @@ export function handler(req: FastifyRequest) { project.createSourceFile(path.join('examples', name), code, { overwrite }); const sourceFile02 = create(filename01, source01.trim(), true); - const node = getRouteNodeOrThrow(sourceFile02); + const node = getRouteFunctionOrThrow(sourceFile02); const parameter = atOrThrow(node.node.getParameters(), 0); const r01 = getPropertySignatures(parameter); @@ -89,7 +89,7 @@ export function handler(req: FastifyRequest) { project.createSourceFile(path.join('examples', name), code, { overwrite }); const sourceFile02 = create(filename01, source01.trim(), true); - const node = getRouteNodeOrThrow(sourceFile02); + const node = getRouteFunctionOrThrow(sourceFile02); const parameter = atOrThrow(node.node.getParameters(), 0); const r01 = getPropertySignatures(parameter); diff --git a/src/compilers/navigate/__tests__/resolved.module.test.ts b/src/compilers/navigate/__tests__/resolved.module.test.ts index 1a00235..c461bc7 100644 --- a/src/compilers/navigate/__tests__/resolved.module.test.ts +++ b/src/compilers/navigate/__tests__/resolved.module.test.ts @@ -1,5 +1,5 @@ import { getResolvedImportedModules } from '#/compilers/navigate/getResolvedImportedModules'; -import { getRouteNode } from '#/compilers/routes/getRouteNode'; +import { getRouteFunction } from '#/compilers/routes/getRouteFunction'; import { getTypeReferences } from '#/compilers/type-tools/getTypeReferences'; import { CE_EXT_KIND } from '#/configs/const-enum/CE_EXT_KIND'; import { posixJoin } from '#/tools/posixJoin'; @@ -41,7 +41,7 @@ export function handler(req: FastifyRequest<{ Querystring: ITestInfoType01 }>) { create(filename01, abilityInterfaceSourceCode, true); const sourceFile02 = create(filename02, source02.trim(), true); - const node = orThrow(getRouteNode(sourceFile02)); + const node = orThrow(getRouteFunction(sourceFile02)); const parameters = node.node.getParameters(); const parameter = atOrThrow(parameters, 0); const types = getTypeReferences(parameter); @@ -104,7 +104,7 @@ export function handler(req: FastifyRequest<{ Querystring: ICompany }>) { create(filename01, abilityInterfaceSourceCode, true); const sourceFile02 = create(filename02, source02.trim(), true); - const node = orThrow(getRouteNode(sourceFile02)); + const node = orThrow(getRouteFunction(sourceFile02)); const parameters = node.node.getParameters(); const parameter = atOrThrow(parameters, 0); const types = getTypeReferences(parameter); @@ -168,7 +168,7 @@ export function handler(req: FastifyRequest<{ Querystring: ICompany }, Server>) create(filename01, abilityInterfaceSourceCode, true); const sourceFile02 = create(filename02, source02.trim(), true); - const node = orThrow(getRouteNode(sourceFile02)); + const node = orThrow(getRouteFunction(sourceFile02)); const parameters = node.node.getParameters(); const parameter = atOrThrow(parameters, 0); const types = getTypeReferences(parameter); @@ -250,7 +250,7 @@ export function handler(req: FastifyRequest<{ Querystring: ICompany }, Server>) create(filename01, abilityInterfaceSourceCode, true); const sourceFile02 = create(filename02, source02.trim(), true); - const node = orThrow(getRouteNode(sourceFile02)); + const node = orThrow(getRouteFunction(sourceFile02)); const parameters = node.node.getParameters(); const parameter = atOrThrow(parameters, 0); const types = getTypeReferences(parameter); diff --git a/src/compilers/navigate/__tests__/symbol.test.ts b/src/compilers/navigate/__tests__/symbol.test.ts index 6454458..79a53cb 100644 --- a/src/compilers/navigate/__tests__/symbol.test.ts +++ b/src/compilers/navigate/__tests__/symbol.test.ts @@ -1,5 +1,5 @@ import { getSymbol } from '#/compilers/navigate/getSymbol'; -import { getRouteNode } from '#/compilers/routes/getRouteNode'; +import { getRouteFunction } from '#/compilers/routes/getRouteFunction'; import { atOrThrow } from 'my-easy-fp'; import { randomUUID } from 'node:crypto'; import path from 'node:path'; @@ -33,7 +33,7 @@ export function handler(param: { Querystring: IAbility }) { project.createSourceFile(filename01, abilityInterfaceSourceCode, { overwrite: true }); const sourceFile02 = project.createSourceFile(filename02, source02.trim(), { overwrite: true }); - const node = getRouteNode(sourceFile02); + const node = getRouteFunction(sourceFile02); const parameters = node?.node.getParameters() ?? []; const parameter = atOrThrow(parameters, 0); const r01 = getSymbol(parameter.getType()); @@ -56,7 +56,7 @@ export function handler(param: FastifyRequest<{ Querystring: IAbility }>) { project.createSourceFile(filename01, abilityInterfaceSourceCode, { overwrite: true }); const sourceFile02 = project.createSourceFile(filename02, source02.trim(), { overwrite: true }); - const node = getRouteNode(sourceFile02); + const node = getRouteFunction(sourceFile02); const parameters = node?.node.getParameters() ?? []; const parameter = atOrThrow(parameters, 0); const r01 = getSymbol(parameter.getType()); @@ -73,7 +73,7 @@ export function handler(param: FastifyRequest<{ Querystring: IAbility }>) { `.trim(); const sourceFile02 = project.createSourceFile(filename02, source02.trim(), { overwrite: true }); - const node = getRouteNode(sourceFile02); + const node = getRouteFunction(sourceFile02); const parameters = node?.node.getParameters() ?? []; const parameter = atOrThrow(parameters, 0); const r01 = getSymbol(parameter.getType()); diff --git a/src/compilers/navigate/getArrowFunctionOptionNode.ts b/src/compilers/navigate/getArrowFunctionOptionNode.ts new file mode 100644 index 0000000..cfc20f8 --- /dev/null +++ b/src/compilers/navigate/getArrowFunctionOptionNode.ts @@ -0,0 +1,32 @@ +import type { TFastifyRouteOption } from '#/compilers/interfaces/TFastifyRouteOption'; +import { findOrThrow } from 'my-easy-fp'; +import type { ExportedDeclarations } from 'ts-morph'; +import { SyntaxKind } from 'ts-morph'; + +/** + * Arrow function에서 identifier 노드를 얻어낸다. identifier 노드를 얻어서 추후 route.ts 파일을 생성할 때 + * identifier 노드에서 name 필드를 얻어서 fastify handler에 전달하는 역할을 한다. + */ +export function getArrowFunctionOptionNode(nodes: ExportedDeclarations[]): TFastifyRouteOption | undefined { + const identifierNode = findOrThrow(nodes, (node) => node.getKind() === SyntaxKind.Identifier).asKindOrThrow( + SyntaxKind.Identifier, + ); + + const expectArrowNode = nodes.find((node) => node.getKind() === SyntaxKind.ArrowFunction); + + if (expectArrowNode == null) { + return undefined; + } + + const arrowFunctionNode = findOrThrow(nodes, (node) => node.getKind() === SyntaxKind.ArrowFunction).asKindOrThrow( + SyntaxKind.ArrowFunction, + ); + + return { + path: arrowFunctionNode.getSourceFile().getFilePath().toString(), + kind: arrowFunctionNode.isAsync() ? 'async' : 'sync', + type: 'arrow', + node: arrowFunctionNode, + name: identifierNode.getText(), + }; +} diff --git a/src/compilers/navigate/getFunctionOptionNode.ts b/src/compilers/navigate/getFunctionOptionNode.ts new file mode 100644 index 0000000..c67e532 --- /dev/null +++ b/src/compilers/navigate/getFunctionOptionNode.ts @@ -0,0 +1,20 @@ +import type { TFastifyRouteOption } from '#/compilers/interfaces/TFastifyRouteOption'; +import { findOrThrow } from 'my-easy-fp'; +import * as tsm from 'ts-morph'; + +export function getFunctionOptionNode(nodes: tsm.ExportedDeclarations[]): TFastifyRouteOption | undefined { + const functionDeclarationNode = findOrThrow( + nodes, + (node) => node.getKind() === tsm.SyntaxKind.FunctionDeclaration, + ).asKindOrThrow(tsm.SyntaxKind.FunctionDeclaration); + + const identifierNode = functionDeclarationNode.getNameNodeOrThrow(); + + return { + path: functionDeclarationNode.getSourceFile().getFilePath().toString(), + kind: functionDeclarationNode.isAsync() ? 'async' : 'sync', + type: 'function', + node: functionDeclarationNode, + name: identifierNode.getText(), + }; +} diff --git a/src/compilers/routes/__tests__/route.node.test.ts b/src/compilers/routes/__tests__/route.node.test.ts index 52b46f8..313791b 100644 --- a/src/compilers/routes/__tests__/route.node.test.ts +++ b/src/compilers/routes/__tests__/route.node.test.ts @@ -1,4 +1,4 @@ -import { getRouteNode } from '#/compilers/routes/getRouteNode'; +import { getRouteFunction } from '#/compilers/routes/getRouteFunction'; import { posixJoin } from '#/tools/posixJoin'; import { randomUUID } from 'node:crypto'; import * as tsm from 'ts-morph'; @@ -47,7 +47,7 @@ export const option: RouteShorthandOptions = { }, };`.trim(); -describe('getRouteOptions', () => { +describe('getRouteFunction', () => { it('synchronous function', () => { const uuid = randomUUID(); @@ -62,7 +62,7 @@ export function handler(req: FastifyRequest<{ Body: IAbility }>) { project.createSourceFile(filename01, abilityInterfaceSourceCode.trim(), { overwrite: true }); const sourceFile02 = project.createSourceFile(filename02, source02.trim(), { overwrite: true }); - const r01 = getRouteNode(sourceFile02); + const r01 = getRouteFunction(sourceFile02); // @ts-expect-error delete r01?.node; @@ -88,7 +88,7 @@ export async function handler(req: FastifyRequest<{ Body: IAbility }>) { project.createSourceFile(filename01, abilityInterfaceSourceCode.trim(), { overwrite: true }); const sourceFile02 = project.createSourceFile(filename02, source02.trim(), { overwrite: true }); - const r01 = getRouteNode(sourceFile02); + const r01 = getRouteFunction(sourceFile02); // @ts-expect-error delete r01?.node; @@ -113,7 +113,7 @@ export const handler = (req: FastifyRequest<{ Body: IAbility }>) => { project.createSourceFile(filename01, abilityInterfaceSourceCode.trim(), { overwrite: true }); const sourceFile02 = project.createSourceFile(filename02, source02.trim(), { overwrite: true }); - const r01 = getRouteNode(sourceFile02); + const r01 = getRouteFunction(sourceFile02); // @ts-expect-error delete r01?.node; @@ -138,7 +138,7 @@ export const handler = async (req: FastifyRequest<{ Body: IAbility }>) => { project.createSourceFile(filename01, abilityInterfaceSourceCode.trim(), { overwrite: true }); const sourceFile02 = project.createSourceFile(filename02, source02.trim(), { overwrite: true }); - const r01 = getRouteNode(sourceFile02); + const r01 = getRouteFunction(sourceFile02); // @ts-expect-error delete r01?.node; @@ -161,7 +161,7 @@ export type handler = { a: number };`; project.createSourceFile(filename01, abilityInterfaceSourceCode.trim(), { overwrite: true }); const sourceFile02 = project.createSourceFile(filename02, source02.trim(), { overwrite: true }); - const r01 = getRouteNode(sourceFile02); + const r01 = getRouteFunction(sourceFile02); expect(r01).toBeUndefined(); }); @@ -177,7 +177,7 @@ export const handler: number = 1;`; project.createSourceFile(filename01, abilityInterfaceSourceCode.trim(), { overwrite: true }); const sourceFile02 = project.createSourceFile(filename02, source02.trim(), { overwrite: true }); - const r01 = getRouteNode(sourceFile02); + const r01 = getRouteFunction(sourceFile02); expect(r01).toBeUndefined(); }); @@ -193,7 +193,7 @@ export type hello = { a: number };`; project.createSourceFile(filename01, abilityInterfaceSourceCode.trim(), { overwrite: true }); const sourceFile02 = project.createSourceFile(filename02, source02.trim(), { overwrite: true }); - const r01 = getRouteNode(sourceFile02); + const r01 = getRouteFunction(sourceFile02); expect(r01).toBeUndefined(); }); diff --git a/src/compilers/routes/__tests__/route.option.test.ts b/src/compilers/routes/__tests__/route.option.test.ts index 893f3e3..1d7166a 100644 --- a/src/compilers/routes/__tests__/route.option.test.ts +++ b/src/compilers/routes/__tests__/route.option.test.ts @@ -1,15 +1,46 @@ +import { getRouteOptionVariable } from '#/compilers/routes/getRouteOptionVariable'; import { getRouteOptions } from '#/compilers/routes/getRouteOptions'; +import { posixJoin } from '#/tools/posixJoin'; import { randomUUID } from 'node:crypto'; -import path from 'node:path'; import * as tsm from 'ts-morph'; import { describe, expect, it } from 'vitest'; -const tsconfigPath = path.join(process.cwd(), 'examples', 'tsconfig.example.json'); +const tsconfigDir = posixJoin(process.cwd(), 'examples'); +const tsconfigPath = posixJoin(tsconfigDir, 'tsconfig.example.json'); +const project = new tsm.Project({ tsConfigFilePath: tsconfigPath }); const context: { index: number } = { index: 0 }; +const create = (name: string, code: string, overwrite: boolean) => + project.createSourceFile(posixJoin('examples', name), code, { overwrite }); +const fastifyImport = `import { FastifyInstance } from 'fastify';`; +const mapExport = `export const map: Map = new Map([['time', ':hour(^\\d{2})h:minute(^\\d{2})m']]);`; +const methodsExport = `export const methods: number = ['SEARCH'];`; +const optionBody = ` + schema: { + querystring: { + type: 'object', + properties: { + name: { + type: 'string', + }, + }, + required: ['name'], + }, + body: { + type: 'object', + properties: { + weight: { + type: 'string', + }, + age: { + type: 'number', + }, + }, + required: ['weight', 'age'], + }, + },`.trim(); describe('getRouteOptions', () => { it('successfully loaded', () => { - const project = new tsm.Project({ tsConfigFilePath: tsconfigPath }); const uuid = randomUUID(); const filename01 = `${uuid}_0${(context.index += 1)}.ts`; const source01 = ` @@ -18,37 +49,158 @@ export const map: Map = new Map([['time', ':hour export const methods: number = ['SEARCH']; export const option: RouteShorthandOptions = { - schema: { - querystring: { - type: 'object', - properties: { - name: { - type: 'string', - }, - }, - required: ['name'], - }, - body: { - type: 'object', - properties: { - weight: { - type: 'string', - }, - age: { - type: 'number', - }, - }, - required: ['weight', 'age'], - }, - }, + ${optionBody} }; export async function handler(req: FastifyRequest<{ Body: IAbility }>) { return req.body; }`; - const sourceFile = project.createSourceFile(filename01, source01.trim(), { overwrite: true }); + const sourceFile = create(filename01, source01.trim(), true); + const r01 = getRouteOptions(sourceFile); + expect(r01).toMatchObject({ has: { option: true, methods: true, map: true } }); }); }); + +describe('getRouteOptionVariable', () => { + it('variable declaration', () => { + const uuid = randomUUID(); + const filename01 = `${uuid}_0${(context.index += 1)}.ts`; + const source01 = ` +export const map: Map = new Map([['time', ':hour(^\\d{2})h:minute(^\\d{2})m']]); + +export const methods: number = ['SEARCH']; + +export const option: RouteShorthandOptions = { + ${optionBody} +}; + +export async function handler(req: FastifyRequest<{ Body: IAbility }>) { + return req.body; +}`; + + const sourceFile = create(filename01, source01.trim(), true); + const r01 = getRouteOptionVariable(sourceFile); + + expect(r01).toMatchObject({ + kind: 'sync', + type: 'variable', + path: posixJoin(tsconfigDir, filename01), + name: 'option', + }); + }); + + it('sync function declaration', () => { + const uuid = randomUUID(); + const filename01 = `${uuid}_0${(context.index += 1)}.ts`; + const source01 = `${fastifyImport} +${mapExport} +${methodsExport} + +export function option(fastify: FastifyInstance): RouteShorthandOptions { + return { + ${optionBody} + }; +}; + +export async function handler(req: FastifyRequest<{ Body: IAbility }>) { + return req.body; +}`; + + const sourceFile = create(filename01, source01.trim(), true); + const r01 = getRouteOptionVariable(sourceFile); + + expect(r01).toMatchObject({ + kind: 'sync', + type: 'function', + path: posixJoin(tsconfigDir, filename01), + name: 'option', + }); + }); + + it('async function declaration', () => { + const uuid = randomUUID(); + const filename01 = `${uuid}_0${(context.index += 1)}.ts`; + const source01 = `${fastifyImport} +${mapExport} +${methodsExport} + +export async function option(fastify: FastifyInstance): RouteShorthandOptions { + return { + ${optionBody} + }; +}; + +export async function handler(req: FastifyRequest<{ Body: IAbility }>) { + return req.body; +}`; + + const sourceFile = create(filename01, source01.trim(), true); + const r01 = getRouteOptionVariable(sourceFile); + + expect(r01).toMatchObject({ + kind: 'async', + type: 'function', + path: posixJoin(tsconfigDir, filename01), + name: 'option', + }); + }); + + it('sync arrow function declaration', () => { + const uuid = randomUUID(); + const filename01 = `${uuid}_0${(context.index += 1)}.ts`; + const source01 = `${fastifyImport} +${mapExport} +${methodsExport} + +export const option = (fastify: FastifyInstance): RouteShorthandOptions => { + return { + ${optionBody} + }; +}; + +export async function handler(req: FastifyRequest<{ Body: IAbility }>) { + return req.body; +}`; + + const sourceFile = create(filename01, source01.trim(), true); + const r01 = getRouteOptionVariable(sourceFile); + + expect(r01).toMatchObject({ + kind: 'sync', + type: 'arrow', + path: posixJoin(tsconfigDir, filename01), + name: 'option', + }); + }); + + it('async arrow function declaration', () => { + const uuid = randomUUID(); + const filename01 = `${uuid}_0${(context.index += 1)}.ts`; + const source01 = `${fastifyImport} +${mapExport} +${methodsExport} + +export const option = async (fastify: FastifyInstance): RouteShorthandOptions => { + return { + ${optionBody} + }; +}; + +export async function handler(req: FastifyRequest<{ Body: IAbility }>) { + return req.body; +}`; + + const sourceFile = create(filename01, source01.trim(), true); + const r01 = getRouteOptionVariable(sourceFile); + + expect(r01).toMatchObject({ + kind: 'async', + type: 'arrow', + path: posixJoin(tsconfigDir, filename01), + name: 'option', + }); + }); +}); diff --git a/src/compilers/routes/getRouteNode.ts b/src/compilers/routes/getRouteFunction.ts similarity index 82% rename from src/compilers/routes/getRouteNode.ts rename to src/compilers/routes/getRouteFunction.ts index 0d57ebf..5959a18 100644 --- a/src/compilers/routes/getRouteNode.ts +++ b/src/compilers/routes/getRouteFunction.ts @@ -1,12 +1,13 @@ import type { TFastifyRouteHandler } from '#/compilers/interfaces/TFastifyRouteHandler'; import { getArrowFunctionHandlerNode } from '#/compilers/navigate/getArrowFunctionHandlerNode'; import { getFunctionHandlerNode } from '#/compilers/navigate/getFunctionHandlerNode'; +import { CE_DEFAULT_VALUE } from '#/configs/const-enum/CE_DEFAULT_VALUE'; import { atOrThrow } from 'my-easy-fp'; import * as tsm from 'ts-morph'; -export function getRouteNode(sourceFile: tsm.SourceFile): TFastifyRouteHandler | undefined { +export function getRouteFunction(sourceFile: tsm.SourceFile): TFastifyRouteHandler | undefined { const declarationMap = sourceFile.getExportedDeclarations(); - const declarations = declarationMap.get('handler'); + const declarations = declarationMap.get(CE_DEFAULT_VALUE.HANDLER_NAME); if (declarations != null) { if (declarations.some((handlerNode) => handlerNode.getKind() === tsm.SyntaxKind.VariableDeclaration)) { diff --git a/src/compilers/routes/getRouteNodeOrThrow.ts b/src/compilers/routes/getRouteFunctionOrThrow.ts similarity index 56% rename from src/compilers/routes/getRouteNodeOrThrow.ts rename to src/compilers/routes/getRouteFunctionOrThrow.ts index 3023db0..56c116a 100644 --- a/src/compilers/routes/getRouteNodeOrThrow.ts +++ b/src/compilers/routes/getRouteFunctionOrThrow.ts @@ -1,9 +1,9 @@ import type { TFastifyRouteHandler } from '#/compilers/interfaces/TFastifyRouteHandler'; -import { getRouteNode } from '#/compilers/routes/getRouteNode'; +import { getRouteFunction } from '#/compilers/routes/getRouteFunction'; import type * as tsm from 'ts-morph'; -export function getRouteNodeOrThrow(sourceFile: tsm.SourceFile): TFastifyRouteHandler { - const node = getRouteNode(sourceFile); +export function getRouteFunctionOrThrow(sourceFile: tsm.SourceFile): TFastifyRouteHandler { + const node = getRouteFunction(sourceFile); if (node != null) { return node; diff --git a/src/compilers/routes/getRouteHandler.ts b/src/compilers/routes/getRouteHandler.ts index 2844357..ba16086 100644 --- a/src/compilers/routes/getRouteHandler.ts +++ b/src/compilers/routes/getRouteHandler.ts @@ -2,7 +2,8 @@ import type { IImportConfiguration } from '#/compilers/interfaces/IImportConfigu import { getPropertySignatures } from '#/compilers/navigate/getPropertySignatures'; import { getResolvedImportedModules } from '#/compilers/navigate/getResolvedImportedModules'; import { getResolvedInFileImportedModules } from '#/compilers/navigate/getResolvedInFileImportedModules'; -import { getRouteNode } from '#/compilers/routes/getRouteNode'; +import { getRouteFunction } from '#/compilers/routes/getRouteFunction'; +import { getRouteOptionKind } from '#/compilers/routes/getRouteOptionKind'; import { getRouteOptions } from '#/compilers/routes/getRouteOptions'; import { CE_REQUEST_KIND } from '#/compilers/type-tools/const-enum/CE_REQUEST_KIND'; import { getRequestTypeParameter } from '#/compilers/type-tools/getRequestTypeParameter'; @@ -28,7 +29,7 @@ export async function getRouteHandler( sourceFile: tsm.SourceFile, options: Pick, ) { - const node = getRouteNode(sourceFile); + const node = getRouteFunction(sourceFile); if (node == null) { return undefined; @@ -82,6 +83,7 @@ export async function getRouteHandler( const routeConfiguration: IRouteConfiguration = { methods: [routePathConfiguration.method, ...extraMethods].map((method) => method.toLowerCase() as CE_ROUTE_METHOD), routePath: routePathConfiguration.routePath, + optionKind: routeOptions.node.option != null ? getRouteOptionKind(routeOptions.node.option) : undefined, hash, hasOption: routeOptions.has.option, handlerName: `handler_${hash}`, diff --git a/src/compilers/routes/getRouteOptionKind.ts b/src/compilers/routes/getRouteOptionKind.ts new file mode 100644 index 0000000..facdb42 --- /dev/null +++ b/src/compilers/routes/getRouteOptionKind.ts @@ -0,0 +1,26 @@ +import type { TFastifyRouteOption } from '#/compilers/interfaces/TFastifyRouteOption'; +import type { IRouteConfiguration } from '#/routes/interfaces/IRouteConfiguration'; + +export function getRouteOptionKind(option: TFastifyRouteOption): IRouteConfiguration['optionKind'] | undefined { + if (option.kind === 'async' && option.type === 'arrow') { + return 'async-arrow'; + } + + if (option.kind === 'sync' && option.type === 'arrow') { + return 'sync-arrow'; + } + + if (option.kind === 'async' && option.type === 'function') { + return 'async-function'; + } + + if (option.kind === 'sync' && option.type === 'function') { + return 'sync-function'; + } + + if (option.kind === 'sync' && option.type === 'variable') { + return 'variable'; + } + + return undefined; +} diff --git a/src/compilers/routes/getRouteOptionVariable.ts b/src/compilers/routes/getRouteOptionVariable.ts new file mode 100644 index 0000000..6b4453d --- /dev/null +++ b/src/compilers/routes/getRouteOptionVariable.ts @@ -0,0 +1,41 @@ +import type { TFastifyRouteOption } from '#/compilers/interfaces/TFastifyRouteOption'; +import { getArrowFunctionOptionNode } from '#/compilers/navigate/getArrowFunctionOptionNode'; +import { getFunctionOptionNode } from '#/compilers/navigate/getFunctionOptionNode'; +import { CE_DEFAULT_VALUE } from '#/configs/const-enum/CE_DEFAULT_VALUE'; +import { atOrThrow } from 'my-easy-fp'; +import * as tsm from 'ts-morph'; + +export function getRouteOptionVariable(sourceFile: tsm.SourceFile): TFastifyRouteOption | undefined { + const declarationMap = sourceFile.getExportedDeclarations(); + const declarations = declarationMap.get(CE_DEFAULT_VALUE.OPTION_NAME); + + if (declarations != null) { + if (declarations.some((handlerNode) => handlerNode.getKind() === tsm.SyntaxKind.VariableDeclaration)) { + const declaration = atOrThrow(declarations, 0); + const variableDeclarationNode = declaration.asKindOrThrow(tsm.SyntaxKind.VariableDeclaration); + + const initialiezer = variableDeclarationNode.getInitializerOrThrow(); + const identifier = variableDeclarationNode.getNameNode().asKindOrThrow(tsm.SyntaxKind.Identifier); + + if (initialiezer.getKind() === tsm.SyntaxKind.ObjectLiteralExpression) { + return { + kind: 'sync', + type: 'variable', + path: sourceFile.getFilePath().toString(), + node: variableDeclarationNode, + name: identifier.getText(), + }; + } + + return getArrowFunctionOptionNode([identifier, initialiezer]); + } + + if (declarations.some((handlerNode) => handlerNode.getKind() === tsm.SyntaxKind.FunctionDeclaration)) { + return getFunctionOptionNode(declarations); + } + + return undefined; + } + + return undefined; +} diff --git a/src/compilers/routes/getRouteOptions.ts b/src/compilers/routes/getRouteOptions.ts index 69bf897..604da1a 100644 --- a/src/compilers/routes/getRouteOptions.ts +++ b/src/compilers/routes/getRouteOptions.ts @@ -1,11 +1,12 @@ import type { IFastifyRouteOptions } from '#/compilers/interfaces/IFastifyRouteOptions'; +import { getRouteOptionVariable } from '#/compilers/routes/getRouteOptionVariable'; import * as tsm from 'ts-morph'; export function getRouteOptions(sourceFile: tsm.SourceFile): IFastifyRouteOptions { const declarationMap = sourceFile.getExportedDeclarations(); // options은 options이 있는지 없는지 확인만 하면 된다 - const option = declarationMap.get('option'); + const option = getRouteOptionVariable(sourceFile); // methods는 methods가 있는지 없는지 확인만 하면 된다. 실제로는 getExtraMethods 함수를 사용해서 // 내용을 읽고, 내용이 올바른지 확인한 뒤 사용할 것이라서 존재 여부만 확인하면 된다 @@ -22,7 +23,7 @@ export function getRouteOptions(sourceFile: tsm.SourceFile): IFastifyRouteOption map: map != null, }, node: { - option: option?.filter((declaration) => declaration.getKind() === tsm.SyntaxKind.VariableDeclaration).at(0), + option, methods: methods?.filter((declaration) => declaration.getKind() === tsm.SyntaxKind.VariableDeclaration).at(0), map: map?.filter((declaration) => declaration.getKind() === tsm.SyntaxKind.VariableDeclaration).at(0), }, diff --git a/src/compilers/tools/__tests__/symbol.test.ts b/src/compilers/tools/__tests__/symbol.test.ts index f722c89..008d170 100644 --- a/src/compilers/tools/__tests__/symbol.test.ts +++ b/src/compilers/tools/__tests__/symbol.test.ts @@ -1,4 +1,4 @@ -import { getRouteNode } from '#/compilers/routes/getRouteNode'; +import { getRouteFunction } from '#/compilers/routes/getRouteFunction'; import { getTypeSymbolText } from '#/compilers/tools/getTypeSymbolText'; import { atOrThrow } from 'my-easy-fp'; import { randomUUID } from 'node:crypto'; @@ -27,7 +27,7 @@ export function handler(req: FastifyRequest<{ Querystring: ITestInfoType01 }>) { const create = (name: string, code: string, overwrite?: boolean) => project.createSourceFile(path.join('examples', name), code, { overwrite: overwrite ?? true }); const sourceFile = create(filename01, sourcecode01); - const node = getRouteNode(sourceFile); + const node = getRouteFunction(sourceFile); const parameters = node?.node.getParameters() ?? []; const parameter = atOrThrow(parameters, 0); const typeArgument = atOrThrow(parameter.getType().getTypeArguments(), 0); @@ -51,7 +51,7 @@ export function handler(req: FastifyRequest) { const create = (name: string, code: string, overwrite?: boolean) => project.createSourceFile(path.join('examples', name), code, { overwrite: overwrite ?? true }); const sourceFile = create(filename01, sourcecode01); - const node = getRouteNode(sourceFile); + const node = getRouteFunction(sourceFile); const parameters = node?.node.getParameters() ?? []; const parameter = atOrThrow(parameters, 0); const typeArgument = atOrThrow(parameter.getType().getTypeArguments(), 0); diff --git a/src/compilers/type-tools/__tests__/example.test.ts b/src/compilers/type-tools/__tests__/example.test.ts index c4670a7..c98ce23 100644 --- a/src/compilers/type-tools/__tests__/example.test.ts +++ b/src/compilers/type-tools/__tests__/example.test.ts @@ -1,4 +1,4 @@ -import { getRouteNodeOrThrow } from '#/compilers/routes/getRouteNodeOrThrow'; +import { getRouteFunctionOrThrow } from '#/compilers/routes/getRouteFunctionOrThrow'; import { getRequestTypeParameter } from '#/compilers/type-tools/getRequestTypeParameter'; import { atOrThrow } from 'my-easy-fp'; import path from 'node:path'; @@ -18,7 +18,7 @@ describe('getRequestTypeParameter', () => { console.log(sourceFile.getFilePath().toString()); - const node = getRouteNodeOrThrow(sourceFile); + const node = getRouteFunctionOrThrow(sourceFile); const parameter = atOrThrow(node.node.getParameters(), 0); getRequestTypeParameter(parameter); diff --git a/src/compilers/type-tools/__tests__/request.argument.test.ts b/src/compilers/type-tools/__tests__/request.argument.test.ts index 0f25dea..7f17496 100644 --- a/src/compilers/type-tools/__tests__/request.argument.test.ts +++ b/src/compilers/type-tools/__tests__/request.argument.test.ts @@ -1,4 +1,4 @@ -import { getRouteNodeOrThrow } from '#/compilers/routes/getRouteNodeOrThrow'; +import { getRouteFunctionOrThrow } from '#/compilers/routes/getRouteFunctionOrThrow'; import { CE_REQUEST_KIND } from '#/compilers/type-tools/const-enum/CE_REQUEST_KIND'; import { getFastifyRequestTypeArgument } from '#/compilers/type-tools/getFastifyRequestTypeArgument'; import { getTypePropertySignature } from '#/compilers/type-tools/getTypePropertySignature'; @@ -72,7 +72,7 @@ describe('getRequestTypeArgument', () => { const sourceFile02 = project.createSourceFile(pathjoin(handlerDir, handlerMethod), source02.trim(), { overwrite: true, }); - const node = getRouteNodeOrThrow(sourceFile02); + const node = getRouteFunctionOrThrow(sourceFile02); const parameter = atOrThrow(node.node.getParameters(), 0); const r01 = getFastifyRequestTypeArgument(parameter); @@ -103,7 +103,7 @@ describe('getRequestTypeArgument', () => { const sourceFile02 = project.createSourceFile(pathjoin(handlerDir, handlerMethod), source02.trim(), { overwrite: true, }); - const node = getRouteNodeOrThrow(sourceFile02); + const node = getRouteFunctionOrThrow(sourceFile02); const parameter = atOrThrow(node.node.getParameters(), 0); const r01 = getFastifyRequestTypeArgument(parameter); @@ -139,7 +139,7 @@ describe('getRequestTypeArgument', () => { const sourceFile02 = project.createSourceFile(pathjoin(handlerDir, handlerMethod), source02.trim(), { overwrite: true, }); - const node = getRouteNodeOrThrow(sourceFile02); + const node = getRouteFunctionOrThrow(sourceFile02); const parameter = atOrThrow(node.node.getParameters(), 0); const r01 = getFastifyRequestTypeArgument(parameter); @@ -175,7 +175,7 @@ describe('getRequestTypeArgument', () => { const sourceFile02 = project.createSourceFile(pathjoin(handlerDir, handlerMethod), source02.trim(), { overwrite: true, }); - const node = getRouteNodeOrThrow(sourceFile02); + const node = getRouteFunctionOrThrow(sourceFile02); const parameter = atOrThrow(node.node.getParameters(), 0); const r01 = getFastifyRequestTypeArgument(parameter); @@ -211,7 +211,7 @@ describe('getRequestTypeArgument', () => { const sourceFile02 = project.createSourceFile(pathjoin(handlerDir, handlerMethod), source02.trim(), { overwrite: true, }); - const node = getRouteNodeOrThrow(sourceFile02); + const node = getRouteFunctionOrThrow(sourceFile02); const parameter = atOrThrow(node.node.getParameters(), 0); const r01 = getFastifyRequestTypeArgument(parameter); @@ -247,7 +247,7 @@ describe('getRequestTypeArgument', () => { const sourceFile02 = project.createSourceFile(pathjoin(handlerDir, handlerMethod), source02.trim(), { overwrite: true, }); - const node = getRouteNodeOrThrow(sourceFile02); + const node = getRouteFunctionOrThrow(sourceFile02); const parameter = atOrThrow(node.node.getParameters(), 0); const r01 = getTypePropertySignature(parameter); @@ -283,7 +283,7 @@ describe('getRequestTypeArgument', () => { const sourceFile02 = project.createSourceFile(pathjoin(handlerDir, handlerMethod), source02.trim(), { overwrite: true, }); - const node = getRouteNodeOrThrow(sourceFile02); + const node = getRouteFunctionOrThrow(sourceFile02); const parameter = atOrThrow(node.node.getParameters(), 0); const r01 = getTypePropertySignature(parameter); @@ -319,7 +319,7 @@ describe('getRequestTypeArgument', () => { const sourceFile02 = project.createSourceFile(pathjoin(handlerDir, handlerMethod), source02.trim(), { overwrite: true, }); - const node = getRouteNodeOrThrow(sourceFile02); + const node = getRouteFunctionOrThrow(sourceFile02); const parameter = atOrThrow(node.node.getParameters(), 0); const r01 = getTypePropertySignature(parameter); @@ -355,7 +355,7 @@ describe('getRequestTypeArgument', () => { const sourceFile02 = project.createSourceFile(pathjoin(handlerDir, handlerMethod), source02.trim(), { overwrite: true, }); - const node = getRouteNodeOrThrow(sourceFile02); + const node = getRouteFunctionOrThrow(sourceFile02); const parameter = atOrThrow(node.node.getParameters(), 0); const r01 = getTypePropertySignature(parameter); diff --git a/src/compilers/type-tools/__tests__/type.test.ts b/src/compilers/type-tools/__tests__/type.test.ts index 2fd6833..f160b80 100644 --- a/src/compilers/type-tools/__tests__/type.test.ts +++ b/src/compilers/type-tools/__tests__/type.test.ts @@ -1,4 +1,4 @@ -import { getRouteNode } from '#/compilers/routes/getRouteNode'; +import { getRouteFunction } from '#/compilers/routes/getRouteFunction'; import { getTypeReferences } from '#/compilers/type-tools/getTypeReferences'; import { isExternalModule } from '#/compilers/type-tools/isExternalModule'; import { randomUUID } from 'crypto'; @@ -63,7 +63,7 @@ export function handler(req: FastifyRequest<{ Body: IAbility }>) { project.createSourceFile(filename01, abilityInterfaceSourceCode.trim(), { overwrite: true }); const sourceFile02 = project.createSourceFile(filename02, source02.trim(), { overwrite: true }); - const routeNode = getRouteNode(sourceFile02); + const routeNode = getRouteFunction(sourceFile02); if (routeNode == null) { throw new Error('invalid route node'); @@ -87,7 +87,7 @@ export function handler(req: FastifyRequest<{ Body: IAbility, Querystring: IAbil project.createSourceFile(filename01, abilityInterfaceSourceCode.trim(), { overwrite: true }); const sourceFile02 = project.createSourceFile(filename02, source02.trim(), { overwrite: true }); - const routeNode = getRouteNode(sourceFile02); + const routeNode = getRouteFunction(sourceFile02); if (routeNode == null) { throw new Error('invalid route node'); diff --git a/src/compilers/validators/__tests__/validator.property.test.ts b/src/compilers/validators/__tests__/validator.property.test.ts index e7f5121..7b93f2f 100644 --- a/src/compilers/validators/__tests__/validator.property.test.ts +++ b/src/compilers/validators/__tests__/validator.property.test.ts @@ -1,5 +1,5 @@ import { getPropertySignatures } from '#/compilers/navigate/getPropertySignatures'; -import { getRouteNodeOrThrow } from '#/compilers/routes/getRouteNodeOrThrow'; +import { getRouteFunctionOrThrow } from '#/compilers/routes/getRouteFunctionOrThrow'; import { CE_REQUEST_KIND } from '#/compilers/type-tools/const-enum/CE_REQUEST_KIND'; import { validatePropertySignature } from '#/compilers/validators/validatePropertySignature'; import { posixJoin } from '#/tools/posixJoin'; @@ -45,7 +45,7 @@ export function handler(req: { Querystring: ITestInfoType01; bod: TBody }) { create(filename01, abilityInterfaceSourceCode, true); const sourceFile02 = create(filename02, source02.trim(), true); - const node = getRouteNodeOrThrow(sourceFile02); + const node = getRouteFunctionOrThrow(sourceFile02); const parameter = atOrThrow(node.node.getParameters(), 0); const propertySignatures = getPropertySignatures(parameter); const r01 = validatePropertySignature({ propertySignatures, kind: CE_REQUEST_KIND.PROPERTY_SIGNATURE }); @@ -87,7 +87,7 @@ export function handler(req: FastifyRequest) { create(filename01, abilityInterfaceSourceCode, true); const sourceFile02 = create(filename02, source02.trim(), true); - const node = getRouteNodeOrThrow(sourceFile02); + const node = getRouteFunctionOrThrow(sourceFile02); const parameter = atOrThrow(node.node.getParameters(), 0); const propertySignatures = getPropertySignatures(parameter); const r01 = validatePropertySignature({ propertySignatures, kind: CE_REQUEST_KIND.FASTIFY_REQUEST }); @@ -129,7 +129,7 @@ export function handler(req: FastifyRequest<{ Querystring: ITestInfoType01; bod: create(filename01, abilityInterfaceSourceCode, true); const sourceFile02 = create(filename02, source02.trim(), true); - const node = getRouteNodeOrThrow(sourceFile02); + const node = getRouteFunctionOrThrow(sourceFile02); const parameter = atOrThrow(node.node.getParameters(), 0); const propertySignatures = getPropertySignatures(parameter); const r01 = validatePropertySignature({ propertySignatures, kind: CE_REQUEST_KIND.FASTIFY_REQUEST }); @@ -166,7 +166,7 @@ export function handler(req: FastifyRequest<{ Querystring: ITestInfoType01 }>) { create(filename01, abilityInterfaceSourceCode, true); const sourceFile02 = create(filename02, source02.trim(), true); - const node = getRouteNodeOrThrow(sourceFile02); + const node = getRouteFunctionOrThrow(sourceFile02); const parameter = atOrThrow(node.node.getParameters(), 0); const propertySignatures = getPropertySignatures(parameter); const r01 = validatePropertySignature({ propertySignatures, kind: CE_REQUEST_KIND.FASTIFY_REQUEST }); diff --git a/src/compilers/validators/__tests__/validator.reference.test.ts b/src/compilers/validators/__tests__/validator.reference.test.ts index ef6e877..afea31f 100644 --- a/src/compilers/validators/__tests__/validator.reference.test.ts +++ b/src/compilers/validators/__tests__/validator.reference.test.ts @@ -1,4 +1,4 @@ -import { getRouteNodeOrThrow } from '#/compilers/routes/getRouteNodeOrThrow'; +import { getRouteFunctionOrThrow } from '#/compilers/routes/getRouteFunctionOrThrow'; import { getTypeReferences } from '#/compilers/type-tools/getTypeReferences'; import { validateTypeReferences } from '#/compilers/validators/validateTypeReferences'; import { posixJoin } from '#/tools/posixJoin'; @@ -45,7 +45,7 @@ export function handler(req: FastifyRequest<{ Querystring: ITestInfoType01; Body create(filename01, abilityInterfaceSourceCode, true); const sourceFile02 = create(filename02, source02.trim(), true); - const node = getRouteNodeOrThrow(sourceFile02); + const node = getRouteFunctionOrThrow(sourceFile02); const parameters = node.node.getParameters(); const parameter = atOrThrow(parameters, 0); const typereferences = getTypeReferences(parameter); @@ -82,7 +82,7 @@ export function handler(req: FastifyRequest<{ Querystring: ITestInfoType01; Body create(filename01, abilityInterfaceSourceCode, true); const sourceFile02 = create(filename02, source02.trim(), true); - const node = getRouteNodeOrThrow(sourceFile02); + const node = getRouteFunctionOrThrow(sourceFile02); const parameters = node.node.getParameters(); const parameter = atOrThrow(parameters, 0); const typereferences = getTypeReferences(parameter); @@ -119,7 +119,7 @@ export function handler(req: FastifyRequest<{ Querystring: ITestInfoType01; Body create(filename01, abilityInterfaceSourceCode, true); const sourceFile02 = create(filename02, source02.trim(), true); - const node = getRouteNodeOrThrow(sourceFile02); + const node = getRouteFunctionOrThrow(sourceFile02); const parameters = node.node.getParameters(); const parameter = atOrThrow(parameters, 0); const typereferences = getTypeReferences(parameter); @@ -160,7 +160,7 @@ export function handler(req: FastifyRequest<{ Querystring: ITestInfoType01; Body create(filename01, abilityInterfaceSourceCode, true); const sourceFile02 = create(filename02, source02.trim(), true); - const node = getRouteNodeOrThrow(sourceFile02); + const node = getRouteFunctionOrThrow(sourceFile02); const parameters = node.node.getParameters(); const parameter = atOrThrow(parameters, 0); const typereferences = getTypeReferences(parameter); @@ -209,7 +209,7 @@ export function handler(req: FastifyRequest<{ Querystring: ITestInfoType01; Body create(filename01, abilityInterfaceSourceCode, true); const sourceFile02 = create(filename02, source02.trim(), true); - const node = getRouteNodeOrThrow(sourceFile02); + const node = getRouteFunctionOrThrow(sourceFile02); const parameters = node.node.getParameters(); const parameter = atOrThrow(parameters, 0); const typereferences = getTypeReferences(parameter); diff --git a/src/configs/const-enum/CE_DEFAULT_VALUE.ts b/src/configs/const-enum/CE_DEFAULT_VALUE.ts index 96bdb82..1941f81 100644 --- a/src/configs/const-enum/CE_DEFAULT_VALUE.ts +++ b/src/configs/const-enum/CE_DEFAULT_VALUE.ts @@ -3,6 +3,8 @@ export const CE_DEFAULT_VALUE = { TSCONFIG_FILE_NAME: 'tsconfig.json', WATCH_DEFAULT_GLOB: '**/*.ts', TEMPLATES_PATH: 'templates', + HANDLER_NAME: 'handler', + OPTION_NAME: 'option', DEFAULT_TASK_WAIT_SECOND: 30, } as const; diff --git a/src/routes/interfaces/IRouteConfiguration.ts b/src/routes/interfaces/IRouteConfiguration.ts index 2ba0181..3290d3c 100644 --- a/src/routes/interfaces/IRouteConfiguration.ts +++ b/src/routes/interfaces/IRouteConfiguration.ts @@ -14,6 +14,8 @@ export interface IRouteConfiguration { /** this route path have option variable */ hasOption: boolean; + optionKind?: 'variable' | 'sync-function' | 'async-function' | 'sync-arrow' | 'async-arrow'; + /** * name of handler with hash * @example handle_PDq0q2qANIHiZy5vU3VeCgIYyT8mERjU diff --git a/src/template/__tests__/template.test.ts b/src/template/__tests__/template.test.ts index 0ac1cb7..93d0126 100644 --- a/src/template/__tests__/template.test.ts +++ b/src/template/__tests__/template.test.ts @@ -53,8 +53,7 @@ describe('TemplateContainer', () => { export default function routing(fastify: FastifyInstance): void { fastify.route<{ Querystring: IReadSuperheroQuerystring; Params: IReadSuperheroParams }>({ - ...option_zLRHkFp00cylJZ0CJlgEiLOpyIGY5Pwl(fastify), - method: ["get"], + method: ["get"], url: '/v1/superhero/:name', handler: handler_zLRHkFp00cylJZ0CJlgEiLOpyIGY5Pwl, }); diff --git a/templates/route.eta b/templates/route.eta index 020bc34..65b76a4 100644 --- a/templates/route.eta +++ b/templates/route.eta @@ -1,9 +1,27 @@ +<% + function getRouteOption(routeOption) { + switch (routeOption.optionKind) { + case 'variable': + return `...option_${routeOption.hash},` + case 'sync-function': + return `...option_${routeOption.hash}(fastify),` + case 'async-function': + return `...(await option_${routeOption.hash}(fastify)),` + case 'sync-arrow': + return `...option_${routeOption.hash}(fastify),` + case 'async-arrow': + return `...(await option_${routeOption.hash}(fastify)),` + default: + return ''; + } + } +%> export default function routing(fastify: FastifyInstance): void { <% it.routes.forEach((route) => { %> <% if (route.typeArgument != null && route.typeArgument.text !== '' ) { %> fastify.route<<%= route.typeArgument.text %>>({ - <% if (route.hasOption) { %> - ...option_<%= route.hash %>(fastify), + <% if (route.optionKind != null) { %> + <%= getRouteOption(route) %> method: <%= JSON.stringify(route.methods) %>, url: '<%= route.routePath %>', handler: <%= route.handlerName %>, @@ -15,8 +33,8 @@ export default function routing(fastify: FastifyInstance): void { }); <% } else { %> fastify.route({ - <% if (route.hasOption) { %> - ...option_<%= route.hash %>(fastify), + <% if (route.optionKind != null) { %> + <%= getRouteOption(route) %> method: <%= JSON.stringify(route.methods) %>, url: '<%= route.routePath %>', handler: <%= route.handlerName %>,