@geekmidas/constructs 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +614 -0
- package/dist/AWSLambdaFunction-CpHFE2m6.d.mts +27 -0
- package/dist/AWSLambdaFunction-CwagvPG3.d.cts +27 -0
- package/dist/AWSLambdaFunction-DWIZYsCy.mjs +79 -0
- package/dist/AWSLambdaFunction-DWIZYsCy.mjs.map +1 -0
- package/dist/AWSLambdaFunction-qA5LqPsv.cjs +85 -0
- package/dist/AWSLambdaFunction-qA5LqPsv.cjs.map +1 -0
- package/dist/AWSLambdaSubscriberAdaptor-C1wQuucQ.d.mts +32 -0
- package/dist/AWSLambdaSubscriberAdaptor-CmPZ10JF.cjs +138 -0
- package/dist/AWSLambdaSubscriberAdaptor-CmPZ10JF.cjs.map +1 -0
- package/dist/AWSLambdaSubscriberAdaptor-G8y3YkWj.mjs +132 -0
- package/dist/AWSLambdaSubscriberAdaptor-G8y3YkWj.mjs.map +1 -0
- package/dist/AWSLambdaSubscriberAdaptor-QKVxR6qh.d.cts +32 -0
- package/dist/AmazonApiGatewayEndpointAdaptor-BoBh7vvD.d.mts +61 -0
- package/dist/AmazonApiGatewayEndpointAdaptor-Cx1oqcqh.mjs +124 -0
- package/dist/AmazonApiGatewayEndpointAdaptor-Cx1oqcqh.mjs.map +1 -0
- package/dist/AmazonApiGatewayEndpointAdaptor-DtzgQ9Vb.d.cts +61 -0
- package/dist/AmazonApiGatewayEndpointAdaptor-i74DEUbc.cjs +130 -0
- package/dist/AmazonApiGatewayEndpointAdaptor-i74DEUbc.cjs.map +1 -0
- package/dist/AmazonApiGatewayV1EndpointAdaptor-CLmBDYsl.mjs +42 -0
- package/dist/AmazonApiGatewayV1EndpointAdaptor-CLmBDYsl.mjs.map +1 -0
- package/dist/AmazonApiGatewayV1EndpointAdaptor-EhMd1YqV.d.mts +21 -0
- package/dist/AmazonApiGatewayV1EndpointAdaptor-GkMAUPL5.cjs +47 -0
- package/dist/AmazonApiGatewayV1EndpointAdaptor-GkMAUPL5.cjs.map +1 -0
- package/dist/AmazonApiGatewayV1EndpointAdaptor-Gw-j61qM.d.cts +21 -0
- package/dist/AmazonApiGatewayV2EndpointAdaptor-3RqegmJC.mjs +41 -0
- package/dist/AmazonApiGatewayV2EndpointAdaptor-3RqegmJC.mjs.map +1 -0
- package/dist/AmazonApiGatewayV2EndpointAdaptor-LUlpwmUW.d.cts +21 -0
- package/dist/AmazonApiGatewayV2EndpointAdaptor-YlFoFSS9.cjs +46 -0
- package/dist/AmazonApiGatewayV2EndpointAdaptor-YlFoFSS9.cjs.map +1 -0
- package/dist/AmazonApiGatewayV2EndpointAdaptor-zfd1gqXA.d.mts +21 -0
- package/dist/BaseFunctionBuilder-5QCHkchp.d.cts +31 -0
- package/dist/BaseFunctionBuilder-BFPVGnKi.d.mts +31 -0
- package/dist/BaseFunctionBuilder-BPE9JBbT.mjs +56 -0
- package/dist/BaseFunctionBuilder-BPE9JBbT.mjs.map +1 -0
- package/dist/BaseFunctionBuilder-DtO4Nwxm.cjs +62 -0
- package/dist/BaseFunctionBuilder-DtO4Nwxm.cjs.map +1 -0
- package/dist/Construct-BSEs6uwW.cjs +75 -0
- package/dist/Construct-BSEs6uwW.cjs.map +1 -0
- package/dist/Construct-BbKCIPQm.mjs +63 -0
- package/dist/Construct-BbKCIPQm.mjs.map +1 -0
- package/dist/Construct-Bm-PSO2V.d.cts +42 -0
- package/dist/Construct-DIguIyw4.d.mts +42 -0
- package/dist/Construct.cjs +4 -0
- package/dist/Construct.d.cts +2 -0
- package/dist/Construct.d.mts +2 -0
- package/dist/Construct.mjs +3 -0
- package/dist/Cron-Bgs6EQOb.mjs +20 -0
- package/dist/Cron-Bgs6EQOb.mjs.map +1 -0
- package/dist/Cron-DQiCj3ef.cjs +25 -0
- package/dist/Cron-DQiCj3ef.cjs.map +1 -0
- package/dist/Cron-FpAw03k6.d.mts +25 -0
- package/dist/Cron-ztnK6zgU.d.cts +25 -0
- package/dist/CronBuilder-B2clNQSP.d.mts +24 -0
- package/dist/CronBuilder-Cje9K8lZ.d.cts +24 -0
- package/dist/CronBuilder-DIBqJkh_.cjs +60 -0
- package/dist/CronBuilder-DIBqJkh_.cjs.map +1 -0
- package/dist/CronBuilder-DecAvvcn.mjs +54 -0
- package/dist/CronBuilder-DecAvvcn.mjs.map +1 -0
- package/dist/Endpoint-BaHC9y4Z.cjs +291 -0
- package/dist/Endpoint-BaHC9y4Z.cjs.map +1 -0
- package/dist/Endpoint-C7z9YJHK.d.cts +405 -0
- package/dist/Endpoint-DCn53Vd8.d.mts +405 -0
- package/dist/Endpoint-ierdM62O.mjs +279 -0
- package/dist/Endpoint-ierdM62O.mjs.map +1 -0
- package/dist/EndpointBuilder-BHFSpbPR.cjs +107 -0
- package/dist/EndpointBuilder-BHFSpbPR.cjs.map +1 -0
- package/dist/EndpointBuilder-BLUsoK3l.mjs +101 -0
- package/dist/EndpointBuilder-BLUsoK3l.mjs.map +1 -0
- package/dist/EndpointBuilder-Bfnb2oJr.d.mts +49 -0
- package/dist/EndpointBuilder-CP9RGwZH.d.cts +49 -0
- package/dist/EndpointFactory-BYdDVCNj.mjs +127 -0
- package/dist/EndpointFactory-BYdDVCNj.mjs.map +1 -0
- package/dist/EndpointFactory-CNtMXgIh.d.mts +52 -0
- package/dist/EndpointFactory-CXX4E6Gx.cjs +139 -0
- package/dist/EndpointFactory-CXX4E6Gx.cjs.map +1 -0
- package/dist/EndpointFactory-D2zgWbXZ.d.cts +52 -0
- package/dist/Function-BP58p9Mp.d.cts +59 -0
- package/dist/Function-BsBxc2wA.d.mts +59 -0
- package/dist/Function-C5mW-38v.mjs +72 -0
- package/dist/Function-C5mW-38v.mjs.map +1 -0
- package/dist/Function-CbO2NZx-.cjs +84 -0
- package/dist/Function-CbO2NZx-.cjs.map +1 -0
- package/dist/FunctionBuilder-BS1KgxA_.d.cts +24 -0
- package/dist/FunctionBuilder-C-PfPN3r.d.mts +24 -0
- package/dist/FunctionBuilder-CosgPmMl.mjs +53 -0
- package/dist/FunctionBuilder-CosgPmMl.mjs.map +1 -0
- package/dist/FunctionBuilder-DuOeWCAl.cjs +59 -0
- package/dist/FunctionBuilder-DuOeWCAl.cjs.map +1 -0
- package/dist/FunctionExecutionWrapper-Bx-Dl-2a.d.cts +24 -0
- package/dist/FunctionExecutionWrapper-CElXEjPe.cjs +42 -0
- package/dist/FunctionExecutionWrapper-CElXEjPe.cjs.map +1 -0
- package/dist/FunctionExecutionWrapper-DvglBBjE.d.mts +24 -0
- package/dist/FunctionExecutionWrapper-XGrSAAPD.mjs +36 -0
- package/dist/FunctionExecutionWrapper-XGrSAAPD.mjs.map +1 -0
- package/dist/HonoEndpointAdaptor-B0IO1zj2.d.mts +41 -0
- package/dist/HonoEndpointAdaptor-B4snrp7v.cjs +154 -0
- package/dist/HonoEndpointAdaptor-B4snrp7v.cjs.map +1 -0
- package/dist/HonoEndpointAdaptor-B6lW9Q1k.d.cts +41 -0
- package/dist/HonoEndpointAdaptor-D-M4-6Tf.mjs +148 -0
- package/dist/HonoEndpointAdaptor-D-M4-6Tf.mjs.map +1 -0
- package/dist/Subscriber-BoFm12i_.d.cts +33 -0
- package/dist/Subscriber-BwuCaC9G.mjs +28 -0
- package/dist/Subscriber-BwuCaC9G.mjs.map +1 -0
- package/dist/Subscriber-THGsj7Iy.d.mts +33 -0
- package/dist/Subscriber-iMRFG7ba.cjs +34 -0
- package/dist/Subscriber-iMRFG7ba.cjs.map +1 -0
- package/dist/SubscriberBuilder-CiPxgnKT.d.mts +26 -0
- package/dist/SubscriberBuilder-Dhz0C_t-.mjs +54 -0
- package/dist/SubscriberBuilder-Dhz0C_t-.mjs.map +1 -0
- package/dist/SubscriberBuilder-DuIgxuzc.d.cts +26 -0
- package/dist/SubscriberBuilder-wthr-FL9.cjs +60 -0
- package/dist/SubscriberBuilder-wthr-FL9.cjs.map +1 -0
- package/dist/adaptors/aws.cjs +19 -0
- package/dist/adaptors/aws.d.cts +15 -0
- package/dist/adaptors/aws.d.mts +15 -0
- package/dist/adaptors/aws.mjs +16 -0
- package/dist/adaptors/hono.cjs +12 -0
- package/dist/adaptors/hono.d.cts +9 -0
- package/dist/adaptors/hono.d.mts +9 -0
- package/dist/adaptors/hono.mjs +12 -0
- package/dist/chunk-CUT6urMc.cjs +30 -0
- package/dist/crons/Cron.cjs +8 -0
- package/dist/crons/Cron.d.cts +7 -0
- package/dist/crons/Cron.d.mts +7 -0
- package/dist/crons/Cron.mjs +8 -0
- package/dist/crons/CronBuilder.cjs +9 -0
- package/dist/crons/CronBuilder.d.cts +8 -0
- package/dist/crons/CronBuilder.d.mts +8 -0
- package/dist/crons/CronBuilder.mjs +9 -0
- package/dist/crons/index.cjs +16 -0
- package/dist/crons/index.cjs.map +1 -0
- package/dist/crons/index.d.cts +16 -0
- package/dist/crons/index.d.mts +16 -0
- package/dist/crons/index.mjs +14 -0
- package/dist/crons/index.mjs.map +1 -0
- package/dist/endpoints/AmazonApiGatewayEndpointAdaptor.cjs +10 -0
- package/dist/endpoints/AmazonApiGatewayEndpointAdaptor.d.cts +9 -0
- package/dist/endpoints/AmazonApiGatewayEndpointAdaptor.d.mts +9 -0
- package/dist/endpoints/AmazonApiGatewayEndpointAdaptor.mjs +10 -0
- package/dist/endpoints/AmazonApiGatewayV1EndpointAdaptor.cjs +12 -0
- package/dist/endpoints/AmazonApiGatewayV1EndpointAdaptor.d.cts +10 -0
- package/dist/endpoints/AmazonApiGatewayV1EndpointAdaptor.d.mts +10 -0
- package/dist/endpoints/AmazonApiGatewayV1EndpointAdaptor.mjs +12 -0
- package/dist/endpoints/AmazonApiGatewayV2EndpointAdaptor.cjs +12 -0
- package/dist/endpoints/AmazonApiGatewayV2EndpointAdaptor.d.cts +10 -0
- package/dist/endpoints/AmazonApiGatewayV2EndpointAdaptor.d.mts +10 -0
- package/dist/endpoints/AmazonApiGatewayV2EndpointAdaptor.mjs +12 -0
- package/dist/endpoints/Endpoint.cjs +9 -0
- package/dist/endpoints/Endpoint.d.cts +8 -0
- package/dist/endpoints/Endpoint.d.mts +8 -0
- package/dist/endpoints/Endpoint.mjs +8 -0
- package/dist/endpoints/EndpointBuilder.cjs +9 -0
- package/dist/endpoints/EndpointBuilder.d.cts +9 -0
- package/dist/endpoints/EndpointBuilder.d.mts +9 -0
- package/dist/endpoints/EndpointBuilder.mjs +9 -0
- package/dist/endpoints/EndpointFactory.cjs +11 -0
- package/dist/endpoints/EndpointFactory.d.cts +10 -0
- package/dist/endpoints/EndpointFactory.d.mts +10 -0
- package/dist/endpoints/EndpointFactory.mjs +10 -0
- package/dist/endpoints/HonoEndpointAdaptor.cjs +12 -0
- package/dist/endpoints/HonoEndpointAdaptor.d.cts +9 -0
- package/dist/endpoints/HonoEndpointAdaptor.d.mts +9 -0
- package/dist/endpoints/HonoEndpointAdaptor.mjs +12 -0
- package/dist/endpoints/TestEndpointAdaptor.cjs +54 -0
- package/dist/endpoints/TestEndpointAdaptor.cjs.map +1 -0
- package/dist/endpoints/TestEndpointAdaptor.d.cts +29 -0
- package/dist/endpoints/TestEndpointAdaptor.d.mts +29 -0
- package/dist/endpoints/TestEndpointAdaptor.mjs +53 -0
- package/dist/endpoints/TestEndpointAdaptor.mjs.map +1 -0
- package/dist/endpoints/helpers.cjs +10 -0
- package/dist/endpoints/helpers.d.cts +58 -0
- package/dist/endpoints/helpers.d.mts +58 -0
- package/dist/endpoints/helpers.mjs +9 -0
- package/dist/endpoints/index.cjs +16 -0
- package/dist/endpoints/index.cjs.map +1 -0
- package/dist/endpoints/index.d.cts +16 -0
- package/dist/endpoints/index.d.mts +16 -0
- package/dist/endpoints/index.mjs +15 -0
- package/dist/endpoints/index.mjs.map +1 -0
- package/dist/endpoints/parseHonoQuery.cjs +3 -0
- package/dist/endpoints/parseHonoQuery.d.cts +12 -0
- package/dist/endpoints/parseHonoQuery.d.mts +12 -0
- package/dist/endpoints/parseHonoQuery.mjs +3 -0
- package/dist/endpoints/parseQueryParams.cjs +3 -0
- package/dist/endpoints/parseQueryParams.d.cts +13 -0
- package/dist/endpoints/parseQueryParams.d.mts +13 -0
- package/dist/endpoints/parseQueryParams.mjs +3 -0
- package/dist/functions/AWSLambdaFunction.cjs +9 -0
- package/dist/functions/AWSLambdaFunction.d.cts +5 -0
- package/dist/functions/AWSLambdaFunction.d.mts +5 -0
- package/dist/functions/AWSLambdaFunction.mjs +9 -0
- package/dist/functions/BaseFunctionBuilder.cjs +4 -0
- package/dist/functions/BaseFunctionBuilder.d.cts +3 -0
- package/dist/functions/BaseFunctionBuilder.d.mts +3 -0
- package/dist/functions/BaseFunctionBuilder.mjs +4 -0
- package/dist/functions/Function.cjs +5 -0
- package/dist/functions/Function.d.cts +3 -0
- package/dist/functions/Function.d.mts +3 -0
- package/dist/functions/Function.mjs +4 -0
- package/dist/functions/FunctionBuilder.cjs +6 -0
- package/dist/functions/FunctionBuilder.d.cts +5 -0
- package/dist/functions/FunctionBuilder.d.mts +5 -0
- package/dist/functions/FunctionBuilder.mjs +6 -0
- package/dist/functions/FunctionExecutionWrapper.cjs +8 -0
- package/dist/functions/FunctionExecutionWrapper.d.cts +4 -0
- package/dist/functions/FunctionExecutionWrapper.d.mts +4 -0
- package/dist/functions/FunctionExecutionWrapper.mjs +8 -0
- package/dist/functions/TestFunctionAdaptor.cjs +38 -0
- package/dist/functions/TestFunctionAdaptor.cjs.map +1 -0
- package/dist/functions/TestFunctionAdaptor.d.cts +26 -0
- package/dist/functions/TestFunctionAdaptor.d.mts +26 -0
- package/dist/functions/TestFunctionAdaptor.mjs +37 -0
- package/dist/functions/TestFunctionAdaptor.mjs.map +1 -0
- package/dist/functions/index.cjs +10 -0
- package/dist/functions/index.d.cts +6 -0
- package/dist/functions/index.d.mts +6 -0
- package/dist/functions/index.mjs +7 -0
- package/dist/functions-DVDb5wEA.cjs +13 -0
- package/dist/functions-DVDb5wEA.cjs.map +1 -0
- package/dist/functions-mM-jcphA.mjs +8 -0
- package/dist/functions-mM-jcphA.mjs.map +1 -0
- package/dist/helpers-BeGM4pP_.cjs +95 -0
- package/dist/helpers-BeGM4pP_.cjs.map +1 -0
- package/dist/helpers-DbpO95aE.mjs +83 -0
- package/dist/helpers-DbpO95aE.mjs.map +1 -0
- package/dist/index-CuGR4L7O.d.mts +9 -0
- package/dist/index-Fg3N3EKD.d.cts +9 -0
- package/dist/index.cjs +4 -0
- package/dist/index.d.cts +4 -0
- package/dist/index.d.mts +4 -0
- package/dist/index.mjs +3 -0
- package/dist/parseHonoQuery-DopC24vB.cjs +37 -0
- package/dist/parseHonoQuery-DopC24vB.cjs.map +1 -0
- package/dist/parseHonoQuery-znDKBhdE.mjs +31 -0
- package/dist/parseHonoQuery-znDKBhdE.mjs.map +1 -0
- package/dist/parseQueryParams-BJaRh3OB.mjs +32 -0
- package/dist/parseQueryParams-BJaRh3OB.mjs.map +1 -0
- package/dist/parseQueryParams-BzPop4I1.cjs +38 -0
- package/dist/parseQueryParams-BzPop4I1.cjs.map +1 -0
- package/dist/publisher-Bw4770Hi.mjs +41 -0
- package/dist/publisher-Bw4770Hi.mjs.map +1 -0
- package/dist/publisher-lFQleddL.cjs +53 -0
- package/dist/publisher-lFQleddL.cjs.map +1 -0
- package/dist/publisher.cjs +4 -0
- package/dist/publisher.d.cts +13 -0
- package/dist/publisher.d.mts +13 -0
- package/dist/publisher.mjs +3 -0
- package/dist/subscribers/AWSLambdaSubscriberAdaptor.cjs +3 -0
- package/dist/subscribers/AWSLambdaSubscriberAdaptor.d.cts +4 -0
- package/dist/subscribers/AWSLambdaSubscriberAdaptor.d.mts +4 -0
- package/dist/subscribers/AWSLambdaSubscriberAdaptor.mjs +3 -0
- package/dist/subscribers/Subscriber.cjs +4 -0
- package/dist/subscribers/Subscriber.d.cts +3 -0
- package/dist/subscribers/Subscriber.d.mts +3 -0
- package/dist/subscribers/Subscriber.mjs +4 -0
- package/dist/subscribers/SubscriberBuilder.cjs +5 -0
- package/dist/subscribers/SubscriberBuilder.d.cts +4 -0
- package/dist/subscribers/SubscriberBuilder.d.mts +4 -0
- package/dist/subscribers/SubscriberBuilder.mjs +5 -0
- package/dist/subscribers/index.cjs +12 -0
- package/dist/subscribers/index.cjs.map +1 -0
- package/dist/subscribers/index.d.cts +10 -0
- package/dist/subscribers/index.d.mts +10 -0
- package/dist/subscribers/index.mjs +10 -0
- package/dist/subscribers/index.mjs.map +1 -0
- package/dist/types-Bp9ysFXd.d.cts +7 -0
- package/dist/types-DBKNYvsW.d.mts +7 -0
- package/dist/types.cjs +0 -0
- package/dist/types.d.cts +2 -0
- package/dist/types.d.mts +2 -0
- package/dist/types.mjs +0 -0
- package/package.json +91 -0
- package/src/Construct.ts +98 -0
- package/src/__tests__/Construct.environment.spec.ts +360 -0
- package/src/__tests__/publisher.setting.spec.ts +511 -0
- package/src/__tests__/publisher.spec.ts +454 -0
- package/src/adaptors/aws.ts +4 -0
- package/src/adaptors/hono.ts +1 -0
- package/src/crons/Cron.ts +137 -0
- package/src/crons/CronBuilder.ts +192 -0
- package/src/crons/__tests__/Cron.spec.ts +464 -0
- package/src/crons/index.ts +11 -0
- package/src/endpoints/AmazonApiGatewayEndpointAdaptor.ts +315 -0
- package/src/endpoints/AmazonApiGatewayV1EndpointAdaptor.ts +101 -0
- package/src/endpoints/AmazonApiGatewayV2EndpointAdaptor.ts +95 -0
- package/src/endpoints/Endpoint.ts +771 -0
- package/src/endpoints/EndpointBuilder.ts +308 -0
- package/src/endpoints/EndpointFactory.ts +329 -0
- package/src/endpoints/HonoEndpointAdaptor.ts +365 -0
- package/src/endpoints/TestEndpointAdaptor.ts +130 -0
- package/src/endpoints/__tests__/AmazonApiGatewayV1EndpointAdaptor.events.spec.ts +553 -0
- package/src/endpoints/__tests__/AmazonApiGatewayV1EndpointAdaptor.spec.ts +927 -0
- package/src/endpoints/__tests__/AmazonApiGatewayV2EndpointAdaptor.events.spec.ts +721 -0
- package/src/endpoints/__tests__/AmazonApiGatewayV2EndpointAdaptor.factory-publisher.spec.ts +296 -0
- package/src/endpoints/__tests__/AmazonApiGatewayV2EndpointAdaptor.spec.ts +441 -0
- package/src/endpoints/__tests__/Endpoint.spec.ts +800 -0
- package/src/endpoints/__tests__/EndpointBuilder.spec.ts +488 -0
- package/src/endpoints/__tests__/EndpointFactory.spec.ts +479 -0
- package/src/endpoints/__tests__/HonoEndpointAdaptor.events.spec.ts +569 -0
- package/src/endpoints/__tests__/HonoEndpointAdaptor.openapi.spec.ts +313 -0
- package/src/endpoints/__tests__/HonoEndpointAdaptor.spec.ts +1078 -0
- package/src/endpoints/__tests__/TestEndpointAdaptor.spec.ts +236 -0
- package/src/endpoints/__tests__/__snapshots__/HonoEndpointAdaptor.spec.ts.snap +54 -0
- package/src/endpoints/__tests__/endpoint-types.test.ts +88 -0
- package/src/endpoints/helpers.ts +99 -0
- package/src/endpoints/index.ts +5 -0
- package/src/endpoints/parseHonoQuery.ts +51 -0
- package/src/endpoints/parseQueryParams.ts +51 -0
- package/src/functions/AWSLambdaFunction.ts +222 -0
- package/src/functions/BaseFunctionBuilder.ts +110 -0
- package/src/functions/Function.ts +160 -0
- package/src/functions/FunctionBuilder.ts +182 -0
- package/src/functions/FunctionExecutionWrapper.ts +86 -0
- package/src/functions/TestFunctionAdaptor.ts +125 -0
- package/src/functions/__tests__/AWSLambdaFunctionAdaptor.spec.ts +376 -0
- package/src/functions/__tests__/Function.spec.ts +402 -0
- package/src/functions/__tests__/TestFunctionAdaptor.spec.ts +398 -0
- package/src/functions/index.ts +10 -0
- package/src/index.ts +14 -0
- package/src/publisher.ts +83 -0
- package/src/subscribers/AWSLambdaSubscriberAdaptor.ts +269 -0
- package/src/subscribers/Subscriber.ts +112 -0
- package/src/subscribers/SubscriberBuilder.ts +150 -0
- package/src/subscribers/__tests__/AWSLambdaSubscriberAdaptor.spec.ts +623 -0
- package/src/subscribers/__tests__/Subscriber.spec.ts +432 -0
- package/src/subscribers/index.ts +5 -0
- package/src/types.ts +13 -0
- package/tsdown.config.ts +3 -0
|
@@ -0,0 +1,1078 @@
|
|
|
1
|
+
import { EnvironmentParser } from '@geekmidas/envkit';
|
|
2
|
+
import type { Logger } from '@geekmidas/logger';
|
|
3
|
+
import { ServiceDiscovery } from '@geekmidas/services';
|
|
4
|
+
import { Hono } from 'hono';
|
|
5
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
import { Endpoint, type EndpointContext } from '../Endpoint';
|
|
8
|
+
import { HonoEndpoint } from '../HonoEndpointAdaptor';
|
|
9
|
+
|
|
10
|
+
describe('HonoEndpointAdaptor', () => {
|
|
11
|
+
const mockLogger: Logger = {
|
|
12
|
+
debug: vi.fn(),
|
|
13
|
+
info: vi.fn(),
|
|
14
|
+
warn: vi.fn(),
|
|
15
|
+
error: vi.fn(),
|
|
16
|
+
fatal: vi.fn(),
|
|
17
|
+
trace: vi.fn(),
|
|
18
|
+
child: vi.fn(() => mockLogger),
|
|
19
|
+
};
|
|
20
|
+
const envParser = new EnvironmentParser({});
|
|
21
|
+
const serviceDiscovery = ServiceDiscovery.getInstance(mockLogger, envParser);
|
|
22
|
+
|
|
23
|
+
describe('addRoute', () => {
|
|
24
|
+
it('should register a GET endpoint', async () => {
|
|
25
|
+
const endpoint = new Endpoint({
|
|
26
|
+
route: '/users',
|
|
27
|
+
method: 'GET',
|
|
28
|
+
fn: async () => ({ users: [] }),
|
|
29
|
+
input: undefined,
|
|
30
|
+
output: z.object({ users: z.array(z.any()) }),
|
|
31
|
+
services: [],
|
|
32
|
+
logger: mockLogger,
|
|
33
|
+
timeout: undefined,
|
|
34
|
+
status: undefined,
|
|
35
|
+
getSession: undefined,
|
|
36
|
+
authorize: undefined,
|
|
37
|
+
description: undefined,
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
const adaptor = new HonoEndpoint(endpoint);
|
|
41
|
+
const app = new Hono();
|
|
42
|
+
|
|
43
|
+
adaptor.addRoute(serviceDiscovery, app);
|
|
44
|
+
|
|
45
|
+
const response = await app.request('/users');
|
|
46
|
+
expect(response.status).toBe(200);
|
|
47
|
+
expect(await response.json()).toEqual({ users: [] });
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('should register a POST endpoint with body validation', async () => {
|
|
51
|
+
const bodySchema = z.object({
|
|
52
|
+
name: z.string(),
|
|
53
|
+
email: z.string().email(),
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
const endpoint = new Endpoint({
|
|
57
|
+
route: '/users',
|
|
58
|
+
method: 'POST',
|
|
59
|
+
fn: async ({ body }) => ({ id: '123', ...body }),
|
|
60
|
+
input: {
|
|
61
|
+
body: bodySchema,
|
|
62
|
+
},
|
|
63
|
+
output: z.object({
|
|
64
|
+
id: z.string(),
|
|
65
|
+
name: z.string(),
|
|
66
|
+
email: z.string(),
|
|
67
|
+
}),
|
|
68
|
+
services: [],
|
|
69
|
+
logger: mockLogger,
|
|
70
|
+
timeout: undefined,
|
|
71
|
+
status: undefined,
|
|
72
|
+
getSession: undefined,
|
|
73
|
+
authorize: undefined,
|
|
74
|
+
description: undefined,
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
const adaptor = new HonoEndpoint(endpoint);
|
|
78
|
+
const app = new Hono();
|
|
79
|
+
|
|
80
|
+
adaptor.addRoute(serviceDiscovery, app);
|
|
81
|
+
|
|
82
|
+
const response = await app.request('/users', {
|
|
83
|
+
method: 'POST',
|
|
84
|
+
body: JSON.stringify({ name: 'John', email: 'john@example.com' }),
|
|
85
|
+
headers: { 'Content-Type': 'application/json' },
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
expect(response.status).toBe(200);
|
|
89
|
+
expect(await response.json()).toEqual({
|
|
90
|
+
id: '123',
|
|
91
|
+
name: 'John',
|
|
92
|
+
email: 'john@example.com',
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it('should validate query parameters', async () => {
|
|
97
|
+
const querySchema = z.object({
|
|
98
|
+
page: z.string().transform(Number),
|
|
99
|
+
limit: z.string().transform(Number),
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
const endpoint = new Endpoint({
|
|
103
|
+
route: '/users',
|
|
104
|
+
method: 'GET',
|
|
105
|
+
fn: async ({ query }) => ({
|
|
106
|
+
page: query.page,
|
|
107
|
+
limit: query.limit,
|
|
108
|
+
users: [],
|
|
109
|
+
}),
|
|
110
|
+
input: {
|
|
111
|
+
query: querySchema,
|
|
112
|
+
},
|
|
113
|
+
output: z.object({
|
|
114
|
+
page: z.number(),
|
|
115
|
+
limit: z.number(),
|
|
116
|
+
users: z.array(z.any()),
|
|
117
|
+
}),
|
|
118
|
+
services: [],
|
|
119
|
+
logger: mockLogger,
|
|
120
|
+
timeout: undefined,
|
|
121
|
+
status: undefined,
|
|
122
|
+
getSession: undefined,
|
|
123
|
+
authorize: undefined,
|
|
124
|
+
description: undefined,
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
const adaptor = new HonoEndpoint(endpoint);
|
|
128
|
+
const app = new Hono();
|
|
129
|
+
|
|
130
|
+
adaptor.addRoute(serviceDiscovery, app);
|
|
131
|
+
|
|
132
|
+
const response = await app.request('/users?page=1&limit=10');
|
|
133
|
+
expect(response.status).toBe(200);
|
|
134
|
+
expect(await response.json()).toEqual({
|
|
135
|
+
page: 1,
|
|
136
|
+
limit: 10,
|
|
137
|
+
users: [],
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
it('should validate path parameters', async () => {
|
|
142
|
+
const paramsSchema = z.object({
|
|
143
|
+
id: z.string().uuid(),
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
const endpoint = new Endpoint({
|
|
147
|
+
route: '/users/:id',
|
|
148
|
+
method: 'GET',
|
|
149
|
+
fn: async ({ params }) => ({
|
|
150
|
+
id: params.id,
|
|
151
|
+
name: 'John Doe',
|
|
152
|
+
}),
|
|
153
|
+
input: {
|
|
154
|
+
params: paramsSchema,
|
|
155
|
+
},
|
|
156
|
+
output: z.object({ id: z.string(), name: z.string() }),
|
|
157
|
+
services: [],
|
|
158
|
+
logger: mockLogger,
|
|
159
|
+
timeout: undefined,
|
|
160
|
+
status: undefined,
|
|
161
|
+
getSession: undefined,
|
|
162
|
+
authorize: undefined,
|
|
163
|
+
description: undefined,
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
const adaptor = new HonoEndpoint(endpoint);
|
|
167
|
+
const app = new Hono();
|
|
168
|
+
|
|
169
|
+
adaptor.addRoute(serviceDiscovery, app);
|
|
170
|
+
|
|
171
|
+
const response = await app.request(
|
|
172
|
+
'/users/550e8400-e29b-41d4-a716-446655440000',
|
|
173
|
+
);
|
|
174
|
+
expect(response.status).toBe(200);
|
|
175
|
+
expect(await response.json()).toEqual({
|
|
176
|
+
id: '550e8400-e29b-41d4-a716-446655440000',
|
|
177
|
+
name: 'John Doe',
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
it('should return 422 for invalid body', async () => {
|
|
182
|
+
const bodySchema = z.object({
|
|
183
|
+
name: z.string().min(3),
|
|
184
|
+
age: z.number().min(18),
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
const endpoint = new Endpoint({
|
|
188
|
+
route: '/users',
|
|
189
|
+
method: 'POST',
|
|
190
|
+
fn: async ({ body }) => ({ id: '123', ...body }),
|
|
191
|
+
input: {
|
|
192
|
+
body: bodySchema,
|
|
193
|
+
},
|
|
194
|
+
output: undefined,
|
|
195
|
+
services: [],
|
|
196
|
+
logger: mockLogger,
|
|
197
|
+
timeout: undefined,
|
|
198
|
+
status: undefined,
|
|
199
|
+
getSession: undefined,
|
|
200
|
+
authorize: undefined,
|
|
201
|
+
description: undefined,
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
const adaptor = new HonoEndpoint(endpoint);
|
|
205
|
+
const app = new Hono();
|
|
206
|
+
|
|
207
|
+
adaptor.addRoute(serviceDiscovery, app);
|
|
208
|
+
|
|
209
|
+
const response = await app.request('/users', {
|
|
210
|
+
method: 'POST',
|
|
211
|
+
body: JSON.stringify({ name: 'Jo', age: 'not a number' }),
|
|
212
|
+
headers: { 'Content-Type': 'application/json' },
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
expect(response.status).toBe(422);
|
|
216
|
+
const error = await response.json();
|
|
217
|
+
expect(error).toMatchSnapshot();
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
it('should return 422 for invalid query parameters', async () => {
|
|
221
|
+
const querySchema = z.object({
|
|
222
|
+
page: z.string().regex(/^\d+$/).transform(Number),
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
const endpoint = new Endpoint({
|
|
226
|
+
route: '/users',
|
|
227
|
+
method: 'GET',
|
|
228
|
+
fn: async ({ query }) => ({ page: query.page }),
|
|
229
|
+
input: {
|
|
230
|
+
query: querySchema,
|
|
231
|
+
},
|
|
232
|
+
output: undefined,
|
|
233
|
+
services: [],
|
|
234
|
+
logger: mockLogger,
|
|
235
|
+
timeout: undefined,
|
|
236
|
+
status: undefined,
|
|
237
|
+
getSession: undefined,
|
|
238
|
+
authorize: undefined,
|
|
239
|
+
description: undefined,
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
const adaptor = new HonoEndpoint(endpoint);
|
|
243
|
+
const app = new Hono();
|
|
244
|
+
|
|
245
|
+
adaptor.addRoute(serviceDiscovery, app);
|
|
246
|
+
|
|
247
|
+
const response = await app.request('/users?page=abc');
|
|
248
|
+
expect(response.status).toBe(422);
|
|
249
|
+
const error = await response.json();
|
|
250
|
+
expect(error).toMatchSnapshot();
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
it('should return 422 for invalid path parameters', async () => {
|
|
254
|
+
const paramsSchema = z.object({
|
|
255
|
+
id: z.string().uuid(),
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
const endpoint = new Endpoint({
|
|
259
|
+
route: '/users/:id',
|
|
260
|
+
method: 'GET',
|
|
261
|
+
fn: async ({ params }) => ({ id: params.id }),
|
|
262
|
+
input: {
|
|
263
|
+
params: paramsSchema,
|
|
264
|
+
},
|
|
265
|
+
output: undefined,
|
|
266
|
+
services: [],
|
|
267
|
+
logger: mockLogger,
|
|
268
|
+
timeout: undefined,
|
|
269
|
+
status: undefined,
|
|
270
|
+
getSession: undefined,
|
|
271
|
+
authorize: undefined,
|
|
272
|
+
description: undefined,
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
const adaptor = new HonoEndpoint(endpoint);
|
|
276
|
+
const app = new Hono();
|
|
277
|
+
|
|
278
|
+
adaptor.addRoute(serviceDiscovery, app);
|
|
279
|
+
|
|
280
|
+
const response = await app.request('/users/not-a-uuid');
|
|
281
|
+
|
|
282
|
+
expect(response.status).toBe(422);
|
|
283
|
+
const error = await response.json();
|
|
284
|
+
|
|
285
|
+
expect(error).toMatchSnapshot();
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
it('should handle PUT method', async () => {
|
|
289
|
+
const bodySchema = z.object({
|
|
290
|
+
name: z.string(),
|
|
291
|
+
});
|
|
292
|
+
const paramsSchema = z.object({
|
|
293
|
+
id: z.string(),
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
const endpoint = new Endpoint({
|
|
297
|
+
route: '/users/:id',
|
|
298
|
+
method: 'PUT',
|
|
299
|
+
fn: async ({ params, body }) => ({ id: params.id, ...body }),
|
|
300
|
+
input: {
|
|
301
|
+
body: bodySchema,
|
|
302
|
+
params: paramsSchema,
|
|
303
|
+
},
|
|
304
|
+
output: z.object({ id: z.string(), name: z.string() }),
|
|
305
|
+
services: [],
|
|
306
|
+
logger: mockLogger,
|
|
307
|
+
timeout: undefined,
|
|
308
|
+
status: undefined,
|
|
309
|
+
getSession: undefined,
|
|
310
|
+
authorize: undefined,
|
|
311
|
+
description: undefined,
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
const adaptor = new HonoEndpoint(endpoint);
|
|
315
|
+
const app = new Hono();
|
|
316
|
+
|
|
317
|
+
adaptor.addRoute(serviceDiscovery, app);
|
|
318
|
+
|
|
319
|
+
const response = await app.request('/users/123', {
|
|
320
|
+
method: 'PUT',
|
|
321
|
+
body: JSON.stringify({ name: 'Updated Name' }),
|
|
322
|
+
headers: { 'Content-Type': 'application/json' },
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
expect(response.status).toBe(200);
|
|
326
|
+
expect(await response.json()).toEqual({
|
|
327
|
+
id: '123',
|
|
328
|
+
name: 'Updated Name',
|
|
329
|
+
});
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
it('should handle DELETE method', async () => {
|
|
333
|
+
const paramsSchema = z.object({
|
|
334
|
+
id: z.string(),
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
const endpoint = new Endpoint({
|
|
338
|
+
route: '/users/:id',
|
|
339
|
+
method: 'DELETE',
|
|
340
|
+
fn: async ({ params }) => ({ deleted: true, id: params.id }),
|
|
341
|
+
input: {
|
|
342
|
+
params: paramsSchema,
|
|
343
|
+
},
|
|
344
|
+
output: z.object({ deleted: z.boolean(), id: z.string() }),
|
|
345
|
+
services: [],
|
|
346
|
+
logger: mockLogger,
|
|
347
|
+
timeout: undefined,
|
|
348
|
+
status: undefined,
|
|
349
|
+
getSession: undefined,
|
|
350
|
+
authorize: undefined,
|
|
351
|
+
description: undefined,
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
const adaptor = new HonoEndpoint(endpoint);
|
|
355
|
+
const app = new Hono();
|
|
356
|
+
|
|
357
|
+
adaptor.addRoute(serviceDiscovery, app);
|
|
358
|
+
|
|
359
|
+
const response = await app.request('/users/123', {
|
|
360
|
+
method: 'DELETE',
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
expect(response.status).toBe(200);
|
|
364
|
+
expect(await response.json()).toEqual({
|
|
365
|
+
deleted: true,
|
|
366
|
+
id: '123',
|
|
367
|
+
});
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
it('should handle PATCH method', async () => {
|
|
371
|
+
const bodySchema = z.object({
|
|
372
|
+
name: z.string().optional(),
|
|
373
|
+
email: z.string().email().optional(),
|
|
374
|
+
});
|
|
375
|
+
const paramsSchema = z.object({
|
|
376
|
+
id: z.string(),
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
const endpoint = new Endpoint({
|
|
380
|
+
route: '/users/:id',
|
|
381
|
+
method: 'PATCH',
|
|
382
|
+
fn: async ({ params, body }) => ({
|
|
383
|
+
id: params.id,
|
|
384
|
+
updated: true,
|
|
385
|
+
...body,
|
|
386
|
+
}),
|
|
387
|
+
input: {
|
|
388
|
+
body: bodySchema,
|
|
389
|
+
params: paramsSchema,
|
|
390
|
+
},
|
|
391
|
+
output: z.object({
|
|
392
|
+
id: z.string(),
|
|
393
|
+
updated: z.boolean(),
|
|
394
|
+
name: z.string().optional(),
|
|
395
|
+
email: z.string().optional(),
|
|
396
|
+
}),
|
|
397
|
+
services: [],
|
|
398
|
+
logger: mockLogger,
|
|
399
|
+
timeout: undefined,
|
|
400
|
+
status: undefined,
|
|
401
|
+
getSession: undefined,
|
|
402
|
+
authorize: undefined,
|
|
403
|
+
description: undefined,
|
|
404
|
+
});
|
|
405
|
+
|
|
406
|
+
const adaptor = new HonoEndpoint(endpoint);
|
|
407
|
+
const app = new Hono();
|
|
408
|
+
|
|
409
|
+
adaptor.addRoute(serviceDiscovery, app);
|
|
410
|
+
|
|
411
|
+
const response = await app.request('/users/123', {
|
|
412
|
+
method: 'PATCH',
|
|
413
|
+
body: JSON.stringify({ email: 'new@example.com' }),
|
|
414
|
+
headers: { 'Content-Type': 'application/json' },
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
expect(response.status).toBe(200);
|
|
418
|
+
expect(await response.json()).toEqual({
|
|
419
|
+
id: '123',
|
|
420
|
+
updated: true,
|
|
421
|
+
email: 'new@example.com',
|
|
422
|
+
});
|
|
423
|
+
});
|
|
424
|
+
|
|
425
|
+
it('should pass headers to endpoint handler', async () => {
|
|
426
|
+
const endpoint = new Endpoint({
|
|
427
|
+
route: '/auth/check',
|
|
428
|
+
method: 'GET',
|
|
429
|
+
fn: async ({ header }) => ({
|
|
430
|
+
authorized: header('authorization') === 'Bearer valid-token',
|
|
431
|
+
}),
|
|
432
|
+
input: undefined,
|
|
433
|
+
output: z.object({ authorized: z.boolean() }),
|
|
434
|
+
services: [],
|
|
435
|
+
logger: mockLogger,
|
|
436
|
+
timeout: undefined,
|
|
437
|
+
status: undefined,
|
|
438
|
+
getSession: undefined,
|
|
439
|
+
authorize: undefined,
|
|
440
|
+
description: undefined,
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
const adaptor = new HonoEndpoint(endpoint);
|
|
444
|
+
const app = new Hono();
|
|
445
|
+
|
|
446
|
+
adaptor.addRoute(serviceDiscovery, app);
|
|
447
|
+
|
|
448
|
+
const response = await app.request('/auth/check', {
|
|
449
|
+
headers: { Authorization: 'Bearer valid-token' },
|
|
450
|
+
});
|
|
451
|
+
|
|
452
|
+
expect(response.status).toBe(200);
|
|
453
|
+
expect(await response.json()).toEqual({ authorized: true });
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
it('should provide services to endpoint handler', async () => {
|
|
457
|
+
const service = {
|
|
458
|
+
getMessage: () => 'Hello from service',
|
|
459
|
+
};
|
|
460
|
+
const TestService = {
|
|
461
|
+
serviceName: 'test' as const,
|
|
462
|
+
|
|
463
|
+
async register() {
|
|
464
|
+
return service;
|
|
465
|
+
},
|
|
466
|
+
};
|
|
467
|
+
|
|
468
|
+
await serviceDiscovery.register([TestService]);
|
|
469
|
+
|
|
470
|
+
const endpoint = new Endpoint({
|
|
471
|
+
route: '/service-test',
|
|
472
|
+
method: 'GET',
|
|
473
|
+
fn: async ({
|
|
474
|
+
services,
|
|
475
|
+
}: EndpointContext<{}, [typeof TestService], Logger>) => {
|
|
476
|
+
return {
|
|
477
|
+
message: await services.test.getMessage(),
|
|
478
|
+
};
|
|
479
|
+
},
|
|
480
|
+
input: undefined,
|
|
481
|
+
output: z.object({ message: z.string() }),
|
|
482
|
+
services: [TestService],
|
|
483
|
+
logger: mockLogger,
|
|
484
|
+
timeout: undefined,
|
|
485
|
+
status: undefined,
|
|
486
|
+
getSession: undefined,
|
|
487
|
+
authorize: undefined,
|
|
488
|
+
description: undefined,
|
|
489
|
+
publisherService: undefined,
|
|
490
|
+
});
|
|
491
|
+
|
|
492
|
+
const adaptor = new HonoEndpoint(endpoint);
|
|
493
|
+
const app = new Hono();
|
|
494
|
+
|
|
495
|
+
adaptor.addRoute(serviceDiscovery, app);
|
|
496
|
+
|
|
497
|
+
const response = await app.request('/service-test');
|
|
498
|
+
expect(response.status).toBe(200);
|
|
499
|
+
expect(await response.json()).toEqual({
|
|
500
|
+
message: 'Hello from service',
|
|
501
|
+
});
|
|
502
|
+
});
|
|
503
|
+
|
|
504
|
+
it('should provide logger to endpoint handler', async () => {
|
|
505
|
+
let loggedMessage: string | undefined;
|
|
506
|
+
|
|
507
|
+
const customLogger: Logger = {
|
|
508
|
+
...mockLogger,
|
|
509
|
+
info: vi.fn((obj: any, msg?: string) => {
|
|
510
|
+
loggedMessage = msg || obj.message;
|
|
511
|
+
}),
|
|
512
|
+
};
|
|
513
|
+
|
|
514
|
+
const endpoint = new Endpoint({
|
|
515
|
+
route: '/log-test',
|
|
516
|
+
method: 'GET',
|
|
517
|
+
fn: async ({ logger }) => {
|
|
518
|
+
logger.info({ action: 'test' }, 'Test log message');
|
|
519
|
+
return { logged: true };
|
|
520
|
+
},
|
|
521
|
+
input: undefined,
|
|
522
|
+
output: z.object({ logged: z.boolean() }),
|
|
523
|
+
services: [],
|
|
524
|
+
logger: customLogger as Logger,
|
|
525
|
+
timeout: undefined,
|
|
526
|
+
status: undefined,
|
|
527
|
+
getSession: undefined,
|
|
528
|
+
authorize: undefined,
|
|
529
|
+
description: undefined,
|
|
530
|
+
publisherService: undefined,
|
|
531
|
+
});
|
|
532
|
+
|
|
533
|
+
const adaptor = new HonoEndpoint(endpoint);
|
|
534
|
+
const app = new Hono();
|
|
535
|
+
|
|
536
|
+
adaptor.addRoute(serviceDiscovery, app);
|
|
537
|
+
|
|
538
|
+
const response = await app.request('/log-test');
|
|
539
|
+
expect(response.status).toBe(200);
|
|
540
|
+
expect(await response.json()).toEqual({ logged: true });
|
|
541
|
+
});
|
|
542
|
+
|
|
543
|
+
it('should handle endpoints with all input types combined', async () => {
|
|
544
|
+
const bodySchema = z.object({
|
|
545
|
+
content: z.string(),
|
|
546
|
+
});
|
|
547
|
+
const querySchema = z.object({
|
|
548
|
+
format: z.enum(['json', 'xml']),
|
|
549
|
+
});
|
|
550
|
+
const paramsSchema = z.object({
|
|
551
|
+
userId: z.string(),
|
|
552
|
+
postId: z.string(),
|
|
553
|
+
});
|
|
554
|
+
|
|
555
|
+
const endpoint = new Endpoint({
|
|
556
|
+
route: '/users/:userId/posts/:postId',
|
|
557
|
+
method: 'PUT',
|
|
558
|
+
fn: async ({ params, query, body, ...rest }) => {
|
|
559
|
+
return {
|
|
560
|
+
userId: params.userId,
|
|
561
|
+
postId: params.postId,
|
|
562
|
+
format: query.format,
|
|
563
|
+
content: body.content,
|
|
564
|
+
updated: true,
|
|
565
|
+
};
|
|
566
|
+
},
|
|
567
|
+
input: {
|
|
568
|
+
body: bodySchema,
|
|
569
|
+
query: querySchema,
|
|
570
|
+
params: paramsSchema,
|
|
571
|
+
},
|
|
572
|
+
output: z.object({
|
|
573
|
+
userId: z.string(),
|
|
574
|
+
postId: z.string(),
|
|
575
|
+
format: z.enum(['json', 'xml']),
|
|
576
|
+
content: z.string(),
|
|
577
|
+
updated: z.boolean(),
|
|
578
|
+
}),
|
|
579
|
+
services: [],
|
|
580
|
+
logger: mockLogger,
|
|
581
|
+
timeout: undefined,
|
|
582
|
+
status: undefined,
|
|
583
|
+
getSession: undefined,
|
|
584
|
+
authorize: undefined,
|
|
585
|
+
publisherService: undefined,
|
|
586
|
+
description: undefined,
|
|
587
|
+
});
|
|
588
|
+
|
|
589
|
+
const adaptor = new HonoEndpoint(endpoint);
|
|
590
|
+
const app = new Hono();
|
|
591
|
+
|
|
592
|
+
adaptor.addRoute(serviceDiscovery, app);
|
|
593
|
+
|
|
594
|
+
const response = await app.request(
|
|
595
|
+
'/users/user123/posts/post456?format=json',
|
|
596
|
+
{
|
|
597
|
+
method: 'PUT',
|
|
598
|
+
body: JSON.stringify({ content: 'Updated content' }),
|
|
599
|
+
headers: { 'Content-Type': 'application/json' },
|
|
600
|
+
},
|
|
601
|
+
);
|
|
602
|
+
|
|
603
|
+
expect(response.status).toBe(200);
|
|
604
|
+
expect(await response.json()).toEqual({
|
|
605
|
+
userId: 'user123',
|
|
606
|
+
postId: 'post456',
|
|
607
|
+
format: 'json',
|
|
608
|
+
content: 'Updated content',
|
|
609
|
+
updated: true,
|
|
610
|
+
});
|
|
611
|
+
});
|
|
612
|
+
});
|
|
613
|
+
|
|
614
|
+
describe('query parameter handling', () => {
|
|
615
|
+
it('should handle array query parameters', async () => {
|
|
616
|
+
const querySchema = z.object({
|
|
617
|
+
tags: z.array(z.string()),
|
|
618
|
+
limit: z.coerce.number().default(10),
|
|
619
|
+
});
|
|
620
|
+
const outputSchema = z.object({
|
|
621
|
+
tags: z.array(z.string()),
|
|
622
|
+
limit: z.number(),
|
|
623
|
+
});
|
|
624
|
+
|
|
625
|
+
const endpoint = new Endpoint({
|
|
626
|
+
route: '/search',
|
|
627
|
+
method: 'GET',
|
|
628
|
+
fn: async ({ query }) => ({
|
|
629
|
+
tags: query.tags,
|
|
630
|
+
limit: query.limit,
|
|
631
|
+
}),
|
|
632
|
+
input: {
|
|
633
|
+
query: querySchema,
|
|
634
|
+
},
|
|
635
|
+
output: outputSchema,
|
|
636
|
+
services: [],
|
|
637
|
+
logger: mockLogger,
|
|
638
|
+
timeout: undefined,
|
|
639
|
+
authorize: undefined,
|
|
640
|
+
status: 200,
|
|
641
|
+
getSession: undefined,
|
|
642
|
+
description: undefined,
|
|
643
|
+
});
|
|
644
|
+
|
|
645
|
+
const adaptor = new HonoEndpoint(endpoint);
|
|
646
|
+
const app = new Hono();
|
|
647
|
+
|
|
648
|
+
adaptor.addRoute(serviceDiscovery, app);
|
|
649
|
+
|
|
650
|
+
const response = await app.request(
|
|
651
|
+
'/search?tags=nodejs&tags=typescript&tags=javascript&limit=20',
|
|
652
|
+
);
|
|
653
|
+
|
|
654
|
+
expect(response.status).toBe(200);
|
|
655
|
+
expect(await response.json()).toEqual({
|
|
656
|
+
tags: ['nodejs', 'typescript', 'javascript'],
|
|
657
|
+
limit: 20,
|
|
658
|
+
});
|
|
659
|
+
});
|
|
660
|
+
|
|
661
|
+
it('should handle object query parameters with dot notation', async () => {
|
|
662
|
+
const querySchema = z.object({
|
|
663
|
+
filter: z.object({
|
|
664
|
+
category: z.string(),
|
|
665
|
+
active: z.coerce.boolean(),
|
|
666
|
+
minPrice: z.coerce.number(),
|
|
667
|
+
}),
|
|
668
|
+
sort: z.string().default('name'),
|
|
669
|
+
});
|
|
670
|
+
const outputSchema = z.object({
|
|
671
|
+
filter: z.object({
|
|
672
|
+
category: z.string(),
|
|
673
|
+
active: z.boolean(),
|
|
674
|
+
minPrice: z.number(),
|
|
675
|
+
}),
|
|
676
|
+
sort: z.string(),
|
|
677
|
+
});
|
|
678
|
+
|
|
679
|
+
const endpoint = new Endpoint({
|
|
680
|
+
route: '/products',
|
|
681
|
+
method: 'GET',
|
|
682
|
+
fn: async ({ query }) => ({
|
|
683
|
+
filter: query.filter,
|
|
684
|
+
sort: query.sort,
|
|
685
|
+
}),
|
|
686
|
+
input: {
|
|
687
|
+
query: querySchema,
|
|
688
|
+
},
|
|
689
|
+
output: outputSchema,
|
|
690
|
+
services: [],
|
|
691
|
+
logger: mockLogger,
|
|
692
|
+
timeout: undefined,
|
|
693
|
+
authorize: undefined,
|
|
694
|
+
status: 200,
|
|
695
|
+
getSession: undefined,
|
|
696
|
+
description: undefined,
|
|
697
|
+
});
|
|
698
|
+
|
|
699
|
+
const adaptor = new HonoEndpoint(endpoint);
|
|
700
|
+
const app = new Hono();
|
|
701
|
+
|
|
702
|
+
adaptor.addRoute(serviceDiscovery, app);
|
|
703
|
+
|
|
704
|
+
const response = await app.request(
|
|
705
|
+
'/products?filter.category=electronics&filter.active=true&filter.minPrice=100&sort=price',
|
|
706
|
+
);
|
|
707
|
+
|
|
708
|
+
expect(response.status).toBe(200);
|
|
709
|
+
expect(await response.json()).toEqual({
|
|
710
|
+
filter: {
|
|
711
|
+
category: 'electronics',
|
|
712
|
+
active: true,
|
|
713
|
+
minPrice: 100,
|
|
714
|
+
},
|
|
715
|
+
sort: 'price',
|
|
716
|
+
});
|
|
717
|
+
});
|
|
718
|
+
});
|
|
719
|
+
|
|
720
|
+
describe('validate', () => {
|
|
721
|
+
it('should return undefined when no schema is provided', async () => {
|
|
722
|
+
const mockContext: any = {
|
|
723
|
+
json: vi.fn(),
|
|
724
|
+
};
|
|
725
|
+
|
|
726
|
+
const result = await HonoEndpoint.validate(
|
|
727
|
+
mockContext,
|
|
728
|
+
{ any: 'data' },
|
|
729
|
+
undefined,
|
|
730
|
+
);
|
|
731
|
+
|
|
732
|
+
expect(result).toBeUndefined();
|
|
733
|
+
expect(mockContext.json).not.toHaveBeenCalled();
|
|
734
|
+
});
|
|
735
|
+
|
|
736
|
+
it('should validate data against schema and return parsed value', async () => {
|
|
737
|
+
const mockContext: any = {
|
|
738
|
+
json: vi.fn(),
|
|
739
|
+
};
|
|
740
|
+
|
|
741
|
+
const schema = z.object({
|
|
742
|
+
name: z.string(),
|
|
743
|
+
age: z.number(),
|
|
744
|
+
});
|
|
745
|
+
|
|
746
|
+
const result = await HonoEndpoint.validate(
|
|
747
|
+
mockContext,
|
|
748
|
+
{ name: 'John', age: 30 },
|
|
749
|
+
schema,
|
|
750
|
+
);
|
|
751
|
+
|
|
752
|
+
expect(result).toEqual({ name: 'John', age: 30 });
|
|
753
|
+
expect(mockContext.json).not.toHaveBeenCalled();
|
|
754
|
+
});
|
|
755
|
+
});
|
|
756
|
+
|
|
757
|
+
describe('authorization', () => {
|
|
758
|
+
it('should allow requests when authorize returns true', async () => {
|
|
759
|
+
const endpoint = new Endpoint({
|
|
760
|
+
route: '/protected',
|
|
761
|
+
method: 'GET',
|
|
762
|
+
fn: async () => ({ success: true }),
|
|
763
|
+
input: undefined,
|
|
764
|
+
output: z.object({ success: z.boolean() }),
|
|
765
|
+
services: [],
|
|
766
|
+
logger: mockLogger,
|
|
767
|
+
timeout: undefined,
|
|
768
|
+
status: undefined,
|
|
769
|
+
getSession: undefined,
|
|
770
|
+
authorize: undefined,
|
|
771
|
+
description: undefined,
|
|
772
|
+
});
|
|
773
|
+
|
|
774
|
+
// Set authorize function that returns true
|
|
775
|
+
endpoint.authorize = async () => true;
|
|
776
|
+
|
|
777
|
+
const adaptor = new HonoEndpoint(endpoint);
|
|
778
|
+
const app = new Hono();
|
|
779
|
+
|
|
780
|
+
adaptor.addRoute(serviceDiscovery, app);
|
|
781
|
+
|
|
782
|
+
const response = await app.request('/protected');
|
|
783
|
+
expect(response.status).toBe(200);
|
|
784
|
+
expect(await response.json()).toEqual({ success: true });
|
|
785
|
+
});
|
|
786
|
+
|
|
787
|
+
it('should return 401 when authorize returns false', async () => {
|
|
788
|
+
const endpoint = new Endpoint({
|
|
789
|
+
route: '/protected',
|
|
790
|
+
method: 'GET',
|
|
791
|
+
fn: async () => ({ success: true }),
|
|
792
|
+
input: undefined,
|
|
793
|
+
output: z.object({ success: z.boolean() }),
|
|
794
|
+
services: [],
|
|
795
|
+
logger: mockLogger,
|
|
796
|
+
timeout: undefined,
|
|
797
|
+
status: undefined,
|
|
798
|
+
getSession: undefined,
|
|
799
|
+
authorize: undefined,
|
|
800
|
+
description: undefined,
|
|
801
|
+
});
|
|
802
|
+
|
|
803
|
+
// Set authorize function that returns false
|
|
804
|
+
endpoint.authorize = async () => false;
|
|
805
|
+
|
|
806
|
+
const adaptor = new HonoEndpoint(endpoint);
|
|
807
|
+
const app = new Hono();
|
|
808
|
+
|
|
809
|
+
adaptor.addRoute(serviceDiscovery, app);
|
|
810
|
+
|
|
811
|
+
const response = await app.request('/protected');
|
|
812
|
+
expect(response.status).toBe(401);
|
|
813
|
+
expect(await response.json()).toEqual({ error: 'Unauthorized' });
|
|
814
|
+
expect(mockLogger.warn).toHaveBeenCalledWith(
|
|
815
|
+
'Unauthorized access attempt',
|
|
816
|
+
);
|
|
817
|
+
});
|
|
818
|
+
|
|
819
|
+
it('should handle async authorize functions with headers', async () => {
|
|
820
|
+
const endpoint = new Endpoint({
|
|
821
|
+
route: '/protected',
|
|
822
|
+
method: 'GET',
|
|
823
|
+
fn: async () => ({ success: true }),
|
|
824
|
+
input: undefined,
|
|
825
|
+
output: z.object({ success: z.boolean() }),
|
|
826
|
+
services: [],
|
|
827
|
+
logger: mockLogger,
|
|
828
|
+
timeout: undefined,
|
|
829
|
+
status: undefined,
|
|
830
|
+
getSession: undefined,
|
|
831
|
+
authorize: undefined,
|
|
832
|
+
description: undefined,
|
|
833
|
+
});
|
|
834
|
+
|
|
835
|
+
// Set async authorize function that checks bearer token
|
|
836
|
+
endpoint.authorize = async ({ header }) => {
|
|
837
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
838
|
+
return header('authorization') === 'Bearer valid-token';
|
|
839
|
+
};
|
|
840
|
+
|
|
841
|
+
const adaptor = new HonoEndpoint(endpoint);
|
|
842
|
+
const app = new Hono();
|
|
843
|
+
|
|
844
|
+
adaptor.addRoute(serviceDiscovery, app);
|
|
845
|
+
|
|
846
|
+
// Test with valid token
|
|
847
|
+
const validResponse = await app.request('/protected', {
|
|
848
|
+
headers: { Authorization: 'Bearer valid-token' },
|
|
849
|
+
});
|
|
850
|
+
expect(validResponse.status).toBe(200);
|
|
851
|
+
expect(await validResponse.json()).toEqual({ success: true });
|
|
852
|
+
|
|
853
|
+
// Test with invalid token
|
|
854
|
+
const invalidResponse = await app.request('/protected', {
|
|
855
|
+
headers: { Authorization: 'Bearer invalid-token' },
|
|
856
|
+
});
|
|
857
|
+
expect(invalidResponse.status).toBe(401);
|
|
858
|
+
expect(await invalidResponse.json()).toEqual({ error: 'Unauthorized' });
|
|
859
|
+
});
|
|
860
|
+
|
|
861
|
+
it('should authorize with services available', async () => {
|
|
862
|
+
const service = {
|
|
863
|
+
isValidToken: (token: string) => token === 'valid-token',
|
|
864
|
+
};
|
|
865
|
+
const AuthService = {
|
|
866
|
+
serviceName: 'authService' as const,
|
|
867
|
+
|
|
868
|
+
async register() {
|
|
869
|
+
return service;
|
|
870
|
+
},
|
|
871
|
+
};
|
|
872
|
+
|
|
873
|
+
const endpoint = new Endpoint({
|
|
874
|
+
route: '/protected',
|
|
875
|
+
method: 'GET',
|
|
876
|
+
fn: async () => ({ success: true }),
|
|
877
|
+
input: undefined,
|
|
878
|
+
output: z.object({ success: z.boolean() }),
|
|
879
|
+
services: [AuthService],
|
|
880
|
+
logger: mockLogger,
|
|
881
|
+
authorize: async ({ header, services }) => {
|
|
882
|
+
const token = header('authorization')?.replace('Bearer ', '') || '';
|
|
883
|
+
return services.authService.isValidToken(token);
|
|
884
|
+
},
|
|
885
|
+
timeout: undefined,
|
|
886
|
+
status: undefined,
|
|
887
|
+
getSession: undefined,
|
|
888
|
+
description: undefined,
|
|
889
|
+
});
|
|
890
|
+
|
|
891
|
+
const adaptor = new HonoEndpoint(endpoint);
|
|
892
|
+
const app = new Hono();
|
|
893
|
+
|
|
894
|
+
adaptor.addRoute(serviceDiscovery, app);
|
|
895
|
+
|
|
896
|
+
// Test with valid token
|
|
897
|
+
const validResponse = await app.request('/protected', {
|
|
898
|
+
headers: { Authorization: 'Bearer valid-token' },
|
|
899
|
+
});
|
|
900
|
+
|
|
901
|
+
expect(validResponse.status).toBe(200);
|
|
902
|
+
|
|
903
|
+
// Test with invalid token
|
|
904
|
+
const invalidResponse = await app.request('/protected', {
|
|
905
|
+
headers: { Authorization: 'Bearer invalid-token' },
|
|
906
|
+
});
|
|
907
|
+
expect(invalidResponse.status).toBe(401);
|
|
908
|
+
});
|
|
909
|
+
|
|
910
|
+
it('should authorize with session', async () => {
|
|
911
|
+
const endpoint = new Endpoint({
|
|
912
|
+
route: '/protected',
|
|
913
|
+
method: 'GET',
|
|
914
|
+
fn: async () => ({ success: true }),
|
|
915
|
+
input: undefined,
|
|
916
|
+
output: z.object({ success: z.boolean() }),
|
|
917
|
+
services: [],
|
|
918
|
+
logger: mockLogger,
|
|
919
|
+
timeout: undefined,
|
|
920
|
+
status: undefined,
|
|
921
|
+
getSession: async ({ header }) => {
|
|
922
|
+
const token = header('authorization');
|
|
923
|
+
return token === 'Bearer user-token'
|
|
924
|
+
? { userId: 'user-123', role: 'user' }
|
|
925
|
+
: null;
|
|
926
|
+
},
|
|
927
|
+
authorize: undefined,
|
|
928
|
+
description: undefined,
|
|
929
|
+
});
|
|
930
|
+
|
|
931
|
+
endpoint.authorize = async ({ session }) => {
|
|
932
|
+
return session?.role === 'user' || session?.role === 'admin';
|
|
933
|
+
};
|
|
934
|
+
|
|
935
|
+
const adaptor = new HonoEndpoint(endpoint as any);
|
|
936
|
+
const app = new Hono();
|
|
937
|
+
|
|
938
|
+
adaptor.addRoute(serviceDiscovery, app);
|
|
939
|
+
|
|
940
|
+
// Test with valid user token
|
|
941
|
+
const validResponse = await app.request('/protected', {
|
|
942
|
+
headers: { Authorization: 'Bearer user-token' },
|
|
943
|
+
});
|
|
944
|
+
expect(validResponse.status).toBe(200);
|
|
945
|
+
|
|
946
|
+
// Test with no token (no session)
|
|
947
|
+
const noTokenResponse = await app.request('/protected');
|
|
948
|
+
expect(noTokenResponse.status).toBe(401);
|
|
949
|
+
});
|
|
950
|
+
|
|
951
|
+
it('should handle authorization errors', async () => {
|
|
952
|
+
const endpoint = new Endpoint({
|
|
953
|
+
route: '/protected',
|
|
954
|
+
method: 'GET',
|
|
955
|
+
fn: async () => ({ success: true }),
|
|
956
|
+
input: undefined,
|
|
957
|
+
output: z.object({ success: z.boolean() }),
|
|
958
|
+
services: [],
|
|
959
|
+
logger: mockLogger,
|
|
960
|
+
timeout: undefined,
|
|
961
|
+
status: undefined,
|
|
962
|
+
getSession: undefined,
|
|
963
|
+
authorize: async () => {
|
|
964
|
+
throw new Error('Authorization service unavailable');
|
|
965
|
+
},
|
|
966
|
+
description: undefined,
|
|
967
|
+
});
|
|
968
|
+
|
|
969
|
+
const adaptor = new HonoEndpoint(endpoint);
|
|
970
|
+
const app = new Hono();
|
|
971
|
+
|
|
972
|
+
adaptor.addRoute(serviceDiscovery, app);
|
|
973
|
+
|
|
974
|
+
const response = await app.request('/protected');
|
|
975
|
+
expect(response.status).toBe(500);
|
|
976
|
+
});
|
|
977
|
+
});
|
|
978
|
+
|
|
979
|
+
describe('output validation', () => {
|
|
980
|
+
it('should validate output against schema and return validated response', async () => {
|
|
981
|
+
const outputSchema = z.object({
|
|
982
|
+
id: z.string(),
|
|
983
|
+
name: z.string(),
|
|
984
|
+
age: z.number(),
|
|
985
|
+
});
|
|
986
|
+
|
|
987
|
+
const endpoint = new Endpoint({
|
|
988
|
+
route: '/users/validated',
|
|
989
|
+
method: 'GET',
|
|
990
|
+
fn: async () => ({ id: '123', name: 'John', age: 30 }),
|
|
991
|
+
input: undefined,
|
|
992
|
+
output: outputSchema,
|
|
993
|
+
services: [],
|
|
994
|
+
logger: mockLogger,
|
|
995
|
+
timeout: undefined,
|
|
996
|
+
status: 200,
|
|
997
|
+
getSession: undefined,
|
|
998
|
+
authorize: undefined,
|
|
999
|
+
description: undefined,
|
|
1000
|
+
});
|
|
1001
|
+
|
|
1002
|
+
const adaptor = new HonoEndpoint(endpoint);
|
|
1003
|
+
const app = new Hono();
|
|
1004
|
+
|
|
1005
|
+
adaptor.addRoute(serviceDiscovery, app);
|
|
1006
|
+
|
|
1007
|
+
const response = await app.request('/users/validated');
|
|
1008
|
+
expect(response.status).toBe(200);
|
|
1009
|
+
expect(await response.json()).toEqual({
|
|
1010
|
+
id: '123',
|
|
1011
|
+
name: 'John',
|
|
1012
|
+
age: 30,
|
|
1013
|
+
});
|
|
1014
|
+
});
|
|
1015
|
+
|
|
1016
|
+
it('should return 422 when output validation fails', async () => {
|
|
1017
|
+
const outputSchema = z.object({
|
|
1018
|
+
id: z.string(),
|
|
1019
|
+
name: z.string(),
|
|
1020
|
+
age: z.number(),
|
|
1021
|
+
});
|
|
1022
|
+
|
|
1023
|
+
const endpoint = new Endpoint({
|
|
1024
|
+
route: '/users/invalid-output',
|
|
1025
|
+
method: 'GET',
|
|
1026
|
+
// @ts-ignore
|
|
1027
|
+
fn: async () => ({ id: 123, name: 'John', age: 'not-a-number' }), // Invalid output
|
|
1028
|
+
input: undefined,
|
|
1029
|
+
output: outputSchema,
|
|
1030
|
+
services: [],
|
|
1031
|
+
logger: mockLogger,
|
|
1032
|
+
timeout: undefined,
|
|
1033
|
+
status: 200,
|
|
1034
|
+
getSession: undefined,
|
|
1035
|
+
authorize: undefined,
|
|
1036
|
+
description: undefined,
|
|
1037
|
+
});
|
|
1038
|
+
|
|
1039
|
+
const adaptor = new HonoEndpoint(endpoint);
|
|
1040
|
+
const app = new Hono();
|
|
1041
|
+
|
|
1042
|
+
adaptor.addRoute(serviceDiscovery, app);
|
|
1043
|
+
|
|
1044
|
+
const response = await app.request('/users/invalid-output');
|
|
1045
|
+
expect(response.status).toBe(422);
|
|
1046
|
+
|
|
1047
|
+
const error = await response.json();
|
|
1048
|
+
expect(error).toHaveProperty('statusCode', 422);
|
|
1049
|
+
expect(error).toHaveProperty('message', 'Validation failed');
|
|
1050
|
+
});
|
|
1051
|
+
|
|
1052
|
+
it('should return empty object when no output schema is defined', async () => {
|
|
1053
|
+
const endpoint = new Endpoint({
|
|
1054
|
+
route: '/users/no-schema',
|
|
1055
|
+
method: 'GET',
|
|
1056
|
+
fn: async () => ({ anything: 'goes', here: true, number: 42 }),
|
|
1057
|
+
input: undefined,
|
|
1058
|
+
output: undefined, // No output schema
|
|
1059
|
+
services: [],
|
|
1060
|
+
logger: mockLogger,
|
|
1061
|
+
timeout: undefined,
|
|
1062
|
+
status: 200,
|
|
1063
|
+
getSession: undefined,
|
|
1064
|
+
authorize: undefined,
|
|
1065
|
+
description: undefined,
|
|
1066
|
+
});
|
|
1067
|
+
|
|
1068
|
+
const adaptor = new HonoEndpoint(endpoint);
|
|
1069
|
+
const app = new Hono();
|
|
1070
|
+
|
|
1071
|
+
adaptor.addRoute(serviceDiscovery, app);
|
|
1072
|
+
|
|
1073
|
+
const response = await app.request('/users/no-schema');
|
|
1074
|
+
expect(response.status).toBe(200);
|
|
1075
|
+
expect(await response.json()).toEqual({});
|
|
1076
|
+
});
|
|
1077
|
+
});
|
|
1078
|
+
});
|