@lakutata/entrypoint 3.0.0-beta.0
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/LICENSE +23 -0
- package/README.md +183 -0
- package/THIRD_PARTY_NOTICES.md +206 -0
- package/dist/cjs/Entrypoint.d.ts +868 -0
- package/dist/cjs/Entrypoint.js +998 -0
- package/dist/cjs/adapter/commander/CommanderCLIEntrypoint.d.ts +192 -0
- package/dist/cjs/adapter/commander/CommanderCLIEntrypoint.js +439 -0
- package/dist/cjs/adapter/commander/Prompt.d.ts +22 -0
- package/dist/cjs/adapter/commander/Prompt.js +164 -0
- package/dist/cjs/adapter/commander/Width.d.ts +12 -0
- package/dist/cjs/adapter/commander/Width.js +67 -0
- package/dist/cjs/adapter/electron/ElectronIPCServiceEntrypoint.d.ts +203 -0
- package/dist/cjs/adapter/electron/ElectronIPCServiceEntrypoint.js +249 -0
- package/dist/cjs/adapter/express/ExpressHTTPEntrypoint.d.ts +172 -0
- package/dist/cjs/adapter/express/ExpressHTTPEntrypoint.js +301 -0
- package/dist/cjs/adapter/express/Responders.d.ts +89 -0
- package/dist/cjs/adapter/express/Responders.js +71 -0
- package/dist/cjs/adapter/express/StaticUI.d.ts +83 -0
- package/dist/cjs/adapter/express/StaticUI.js +104 -0
- package/dist/cjs/adapter/fastify/FastifyHTTPEntrypoint.d.ts +156 -0
- package/dist/cjs/adapter/fastify/FastifyHTTPEntrypoint.js +339 -0
- package/dist/cjs/adapter/fastify/Responders.d.ts +88 -0
- package/dist/cjs/adapter/fastify/Responders.js +77 -0
- package/dist/cjs/adapter/http/HTTPServiceEntrypoint.d.ts +117 -0
- package/dist/cjs/adapter/http/HTTPServiceEntrypoint.js +257 -0
- package/dist/cjs/adapter/jsonrpc/JSONRPCProtocol.d.ts +194 -0
- package/dist/cjs/adapter/jsonrpc/JSONRPCProtocol.js +187 -0
- package/dist/cjs/adapter/jsonrpc/JSONRPCServiceEntrypoint.d.ts +154 -0
- package/dist/cjs/adapter/jsonrpc/JSONRPCServiceEntrypoint.js +397 -0
- package/dist/cjs/adapter/schedule/ScheduleEntrypoint.d.ts +86 -0
- package/dist/cjs/adapter/schedule/ScheduleEntrypoint.js +275 -0
- package/dist/cjs/adapter/socket.io/SocketIOServiceEntrypoint.d.ts +138 -0
- package/dist/cjs/adapter/socket.io/SocketIOServiceEntrypoint.js +216 -0
- package/dist/cjs/channel/BuiltinChannels.d.ts +18 -0
- package/dist/cjs/channel/BuiltinChannels.js +128 -0
- package/dist/cjs/channel/Channel.d.ts +196 -0
- package/dist/cjs/channel/Channel.js +106 -0
- package/dist/cjs/channel/EntrypointAdapter.d.ts +195 -0
- package/dist/cjs/channel/EntrypointAdapter.js +43 -0
- package/dist/cjs/context/BaseContext.d.ts +75 -0
- package/dist/cjs/context/BaseContext.js +90 -0
- package/dist/cjs/context/CLIContext.d.ts +38 -0
- package/dist/cjs/context/CLIContext.js +53 -0
- package/dist/cjs/context/HTTPContext.d.ts +52 -0
- package/dist/cjs/context/HTTPContext.js +78 -0
- package/dist/cjs/context/ScheduleContext.d.ts +47 -0
- package/dist/cjs/context/ScheduleContext.js +65 -0
- package/dist/cjs/context/ServiceContext.d.ts +47 -0
- package/dist/cjs/context/ServiceContext.js +62 -0
- package/dist/cjs/decorators/CLIAction.d.ts +120 -0
- package/dist/cjs/decorators/CLIAction.js +13 -0
- package/dist/cjs/decorators/HTTPAction.d.ts +178 -0
- package/dist/cjs/decorators/HTTPAction.js +14 -0
- package/dist/cjs/decorators/Prefix.d.ts +44 -0
- package/dist/cjs/decorators/Prefix.js +48 -0
- package/dist/cjs/decorators/Schedule.d.ts +120 -0
- package/dist/cjs/decorators/Schedule.js +64 -0
- package/dist/cjs/decorators/ServiceAction.d.ts +116 -0
- package/dist/cjs/decorators/ServiceAction.js +12 -0
- package/dist/cjs/decorators/UseMiddlewares.d.ts +52 -0
- package/dist/cjs/decorators/UseMiddlewares.js +58 -0
- package/dist/cjs/decorators/http/DELETE.d.ts +87 -0
- package/dist/cjs/decorators/http/DELETE.js +7 -0
- package/dist/cjs/decorators/http/GET.d.ts +89 -0
- package/dist/cjs/decorators/http/GET.js +7 -0
- package/dist/cjs/decorators/http/HEAD.d.ts +84 -0
- package/dist/cjs/decorators/http/HEAD.js +7 -0
- package/dist/cjs/decorators/http/OPTIONS.d.ts +80 -0
- package/dist/cjs/decorators/http/OPTIONS.js +7 -0
- package/dist/cjs/decorators/http/PATCH.d.ts +90 -0
- package/dist/cjs/decorators/http/PATCH.js +7 -0
- package/dist/cjs/decorators/http/POST.d.ts +91 -0
- package/dist/cjs/decorators/http/POST.js +7 -0
- package/dist/cjs/decorators/http/PUT.d.ts +92 -0
- package/dist/cjs/decorators/http/PUT.js +7 -0
- package/dist/cjs/exceptions/AccessDeniedException.d.ts +10 -0
- package/dist/cjs/exceptions/AccessDeniedException.js +17 -0
- package/dist/cjs/exceptions/ControllerActionNotFoundException.d.ts +9 -0
- package/dist/cjs/exceptions/ControllerActionNotFoundException.js +16 -0
- package/dist/cjs/exceptions/DuplicateActionNameException.d.ts +8 -0
- package/dist/cjs/exceptions/DuplicateActionNameException.js +15 -0
- package/dist/cjs/exceptions/EntrypointStoppedException.d.ts +9 -0
- package/dist/cjs/exceptions/EntrypointStoppedException.js +16 -0
- package/dist/cjs/exceptions/InvalidActionGroupException.d.ts +4 -0
- package/dist/cjs/exceptions/InvalidActionGroupException.js +11 -0
- package/dist/cjs/exceptions/InvalidChannelException.d.ts +8 -0
- package/dist/cjs/exceptions/InvalidChannelException.js +15 -0
- package/dist/cjs/exceptions/InvalidEntrypointAdapterException.d.ts +9 -0
- package/dist/cjs/exceptions/InvalidEntrypointAdapterException.js +16 -0
- package/dist/cjs/exceptions/InvalidMiddlewareException.d.ts +8 -0
- package/dist/cjs/exceptions/InvalidMiddlewareException.js +15 -0
- package/dist/cjs/exceptions/InvalidPrefixException.d.ts +8 -0
- package/dist/cjs/exceptions/InvalidPrefixException.js +15 -0
- package/dist/cjs/exceptions/MiddlewareNextCalledException.d.ts +8 -0
- package/dist/cjs/exceptions/MiddlewareNextCalledException.js +15 -0
- package/dist/cjs/exceptions/RouteNotFoundException.d.ts +9 -0
- package/dist/cjs/exceptions/RouteNotFoundException.js +16 -0
- package/dist/cjs/exceptions/ServiceInvokeException.d.ts +11 -0
- package/dist/cjs/exceptions/ServiceInvokeException.js +14 -0
- package/dist/cjs/exports/CTRLDecorators.d.ts +13 -0
- package/dist/cjs/exports/CTRLDecorators.js +38 -0
- package/dist/cjs/exports/Channel.d.ts +14 -0
- package/dist/cjs/exports/Channel.js +33 -0
- package/dist/cjs/exports/CommanderAdapter.d.ts +1 -0
- package/dist/cjs/exports/CommanderAdapter.js +8 -0
- package/dist/cjs/exports/ElectronAdapter.d.ts +1 -0
- package/dist/cjs/exports/ElectronAdapter.js +9 -0
- package/dist/cjs/exports/Entrypoint.d.ts +24 -0
- package/dist/cjs/exports/Entrypoint.js +55 -0
- package/dist/cjs/exports/ExpressAdapter.d.ts +4 -0
- package/dist/cjs/exports/ExpressAdapter.js +15 -0
- package/dist/cjs/exports/FastifyAdapter.d.ts +4 -0
- package/dist/cjs/exports/FastifyAdapter.js +14 -0
- package/dist/cjs/exports/JSONRPCAdapter.d.ts +2 -0
- package/dist/cjs/exports/JSONRPCAdapter.js +11 -0
- package/dist/cjs/exports/SocketIOAdapter.d.ts +1 -0
- package/dist/cjs/exports/SocketIOAdapter.js +9 -0
- package/dist/cjs/lib/AccessControl.d.ts +118 -0
- package/dist/cjs/lib/AccessControl.js +208 -0
- package/dist/cjs/lib/AccessControlRule.d.ts +91 -0
- package/dist/cjs/lib/AccessControlRule.js +76 -0
- package/dist/cjs/lib/ActionOptions.d.ts +67 -0
- package/dist/cjs/lib/ActionOptions.js +67 -0
- package/dist/cjs/lib/ActionResult.d.ts +28 -0
- package/dist/cjs/lib/ActionResult.js +28 -0
- package/dist/cjs/lib/ApplicationOf.d.ts +6 -0
- package/dist/cjs/lib/ApplicationOf.js +14 -0
- package/dist/cjs/lib/Controller.d.ts +59 -0
- package/dist/cjs/lib/Controller.js +64 -0
- package/dist/cjs/lib/ControllerEntrypoint.d.ts +168 -0
- package/dist/cjs/lib/ControllerEntrypoint.js +239 -0
- package/dist/cjs/lib/GetActionDTOAndOptions.d.ts +29 -0
- package/dist/cjs/lib/GetActionDTOAndOptions.js +49 -0
- package/dist/cjs/lib/HTTPErrors.d.ts +55 -0
- package/dist/cjs/lib/HTTPErrors.js +52 -0
- package/dist/cjs/lib/Middleware.d.ts +146 -0
- package/dist/cjs/lib/Middleware.js +144 -0
- package/dist/cjs/lib/Prefix.d.ts +98 -0
- package/dist/cjs/lib/Prefix.js +151 -0
- package/dist/cjs/lib/Result.d.ts +173 -0
- package/dist/cjs/lib/Result.js +153 -0
- package/dist/cjs/lib/ServiceResponseCodec.d.ts +82 -0
- package/dist/cjs/lib/ServiceResponseCodec.js +117 -0
- package/dist/cjs/lib/StringifyPattern.d.ts +7 -0
- package/dist/cjs/lib/StringifyPattern.js +58 -0
- package/dist/cjs/lib/UnsetValue.d.ts +12 -0
- package/dist/cjs/lib/UnsetValue.js +216 -0
- package/dist/cjs/lib/pattern/GlobPattern.d.ts +34 -0
- package/dist/cjs/lib/pattern/GlobPattern.js +68 -0
- package/dist/cjs/lib/pattern/PatternManager.d.ts +103 -0
- package/dist/cjs/lib/pattern/PatternManager.js +233 -0
- package/dist/cjs/lib/schedule/Cron.d.ts +56 -0
- package/dist/cjs/lib/schedule/Cron.js +282 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/types/CLIContextParams.d.ts +14 -0
- package/dist/cjs/types/CLIContextParams.js +2 -0
- package/dist/cjs/types/ErrorDescription.d.ts +14 -0
- package/dist/cjs/types/ErrorDescription.js +2 -0
- package/dist/cjs/types/HTTPContextParams.d.ts +27 -0
- package/dist/cjs/types/HTTPContextParams.js +2 -0
- package/dist/cjs/types/ScheduleContextParams.d.ts +21 -0
- package/dist/cjs/types/ScheduleContextParams.js +2 -0
- package/dist/cjs/types/ServiceContextParams.d.ts +16 -0
- package/dist/cjs/types/ServiceContextParams.js +2 -0
- package/dist/esm/Entrypoint.js +985 -0
- package/dist/esm/adapter/commander/CommanderCLIEntrypoint.js +433 -0
- package/dist/esm/adapter/commander/Prompt.js +127 -0
- package/dist/esm/adapter/commander/Width.js +63 -0
- package/dist/esm/adapter/electron/ElectronIPCServiceEntrypoint.js +212 -0
- package/dist/esm/adapter/express/ExpressHTTPEntrypoint.js +295 -0
- package/dist/esm/adapter/express/Responders.js +66 -0
- package/dist/esm/adapter/express/StaticUI.js +96 -0
- package/dist/esm/adapter/fastify/FastifyHTTPEntrypoint.js +333 -0
- package/dist/esm/adapter/fastify/Responders.js +73 -0
- package/dist/esm/adapter/http/HTTPServiceEntrypoint.js +253 -0
- package/dist/esm/adapter/jsonrpc/JSONRPCProtocol.js +182 -0
- package/dist/esm/adapter/jsonrpc/JSONRPCServiceEntrypoint.js +361 -0
- package/dist/esm/adapter/schedule/ScheduleEntrypoint.js +272 -0
- package/dist/esm/adapter/socket.io/SocketIOServiceEntrypoint.js +212 -0
- package/dist/esm/channel/BuiltinChannels.js +125 -0
- package/dist/esm/channel/Channel.js +100 -0
- package/dist/esm/channel/EntrypointAdapter.js +39 -0
- package/dist/esm/context/BaseContext.js +87 -0
- package/dist/esm/context/CLIContext.js +49 -0
- package/dist/esm/context/HTTPContext.js +74 -0
- package/dist/esm/context/ScheduleContext.js +61 -0
- package/dist/esm/context/ServiceContext.js +58 -0
- package/dist/esm/decorators/CLIAction.js +10 -0
- package/dist/esm/decorators/HTTPAction.js +11 -0
- package/dist/esm/decorators/Prefix.js +45 -0
- package/dist/esm/decorators/Schedule.js +61 -0
- package/dist/esm/decorators/ServiceAction.js +9 -0
- package/dist/esm/decorators/UseMiddlewares.js +55 -0
- package/dist/esm/decorators/http/DELETE.js +4 -0
- package/dist/esm/decorators/http/GET.js +4 -0
- package/dist/esm/decorators/http/HEAD.js +4 -0
- package/dist/esm/decorators/http/OPTIONS.js +4 -0
- package/dist/esm/decorators/http/PATCH.js +4 -0
- package/dist/esm/decorators/http/POST.js +4 -0
- package/dist/esm/decorators/http/PUT.js +4 -0
- package/dist/esm/exceptions/AccessDeniedException.js +13 -0
- package/dist/esm/exceptions/ControllerActionNotFoundException.js +12 -0
- package/dist/esm/exceptions/DuplicateActionNameException.js +11 -0
- package/dist/esm/exceptions/EntrypointStoppedException.js +12 -0
- package/dist/esm/exceptions/InvalidActionGroupException.js +7 -0
- package/dist/esm/exceptions/InvalidChannelException.js +11 -0
- package/dist/esm/exceptions/InvalidEntrypointAdapterException.js +12 -0
- package/dist/esm/exceptions/InvalidMiddlewareException.js +11 -0
- package/dist/esm/exceptions/InvalidPrefixException.js +11 -0
- package/dist/esm/exceptions/MiddlewareNextCalledException.js +11 -0
- package/dist/esm/exceptions/RouteNotFoundException.js +12 -0
- package/dist/esm/exceptions/ServiceInvokeException.js +10 -0
- package/dist/esm/exports/CTRLDecorators.js +19 -0
- package/dist/esm/exports/Channel.js +11 -0
- package/dist/esm/exports/CommanderAdapter.js +1 -0
- package/dist/esm/exports/ElectronAdapter.js +1 -0
- package/dist/esm/exports/Entrypoint.js +22 -0
- package/dist/esm/exports/ExpressAdapter.js +3 -0
- package/dist/esm/exports/FastifyAdapter.js +3 -0
- package/dist/esm/exports/JSONRPCAdapter.js +2 -0
- package/dist/esm/exports/SocketIOAdapter.js +1 -0
- package/dist/esm/lib/AccessControl.js +204 -0
- package/dist/esm/lib/AccessControlRule.js +72 -0
- package/dist/esm/lib/ActionOptions.js +63 -0
- package/dist/esm/lib/ActionResult.js +24 -0
- package/dist/esm/lib/ApplicationOf.js +11 -0
- package/dist/esm/lib/Controller.js +61 -0
- package/dist/esm/lib/ControllerEntrypoint.js +229 -0
- package/dist/esm/lib/GetActionDTOAndOptions.js +46 -0
- package/dist/esm/lib/HTTPErrors.js +48 -0
- package/dist/esm/lib/Middleware.js +134 -0
- package/dist/esm/lib/Prefix.js +143 -0
- package/dist/esm/lib/Result.js +147 -0
- package/dist/esm/lib/ServiceResponseCodec.js +113 -0
- package/dist/esm/lib/StringifyPattern.js +55 -0
- package/dist/esm/lib/UnsetValue.js +213 -0
- package/dist/esm/lib/pattern/GlobPattern.js +64 -0
- package/dist/esm/lib/pattern/PatternManager.js +229 -0
- package/dist/esm/lib/schedule/Cron.js +277 -0
- package/dist/esm/types/CLIContextParams.js +1 -0
- package/dist/esm/types/ErrorDescription.js +1 -0
- package/dist/esm/types/HTTPContextParams.js +1 -0
- package/dist/esm/types/ScheduleContextParams.js +1 -0
- package/dist/esm/types/ServiceContextParams.js +1 -0
- package/dist/types/Entrypoint.d.ts +868 -0
- package/dist/types/adapter/commander/CommanderCLIEntrypoint.d.ts +192 -0
- package/dist/types/adapter/commander/Prompt.d.ts +22 -0
- package/dist/types/adapter/commander/Width.d.ts +12 -0
- package/dist/types/adapter/electron/ElectronIPCServiceEntrypoint.d.ts +203 -0
- package/dist/types/adapter/express/ExpressHTTPEntrypoint.d.ts +172 -0
- package/dist/types/adapter/express/Responders.d.ts +89 -0
- package/dist/types/adapter/express/StaticUI.d.ts +83 -0
- package/dist/types/adapter/fastify/FastifyHTTPEntrypoint.d.ts +156 -0
- package/dist/types/adapter/fastify/Responders.d.ts +88 -0
- package/dist/types/adapter/http/HTTPServiceEntrypoint.d.ts +117 -0
- package/dist/types/adapter/jsonrpc/JSONRPCProtocol.d.ts +194 -0
- package/dist/types/adapter/jsonrpc/JSONRPCServiceEntrypoint.d.ts +154 -0
- package/dist/types/adapter/schedule/ScheduleEntrypoint.d.ts +86 -0
- package/dist/types/adapter/socket.io/SocketIOServiceEntrypoint.d.ts +138 -0
- package/dist/types/channel/BuiltinChannels.d.ts +18 -0
- package/dist/types/channel/Channel.d.ts +196 -0
- package/dist/types/channel/EntrypointAdapter.d.ts +195 -0
- package/dist/types/context/BaseContext.d.ts +75 -0
- package/dist/types/context/CLIContext.d.ts +38 -0
- package/dist/types/context/HTTPContext.d.ts +52 -0
- package/dist/types/context/ScheduleContext.d.ts +47 -0
- package/dist/types/context/ServiceContext.d.ts +47 -0
- package/dist/types/decorators/CLIAction.d.ts +120 -0
- package/dist/types/decorators/HTTPAction.d.ts +178 -0
- package/dist/types/decorators/Prefix.d.ts +44 -0
- package/dist/types/decorators/Schedule.d.ts +120 -0
- package/dist/types/decorators/ServiceAction.d.ts +116 -0
- package/dist/types/decorators/UseMiddlewares.d.ts +52 -0
- package/dist/types/decorators/http/DELETE.d.ts +87 -0
- package/dist/types/decorators/http/GET.d.ts +89 -0
- package/dist/types/decorators/http/HEAD.d.ts +84 -0
- package/dist/types/decorators/http/OPTIONS.d.ts +80 -0
- package/dist/types/decorators/http/PATCH.d.ts +90 -0
- package/dist/types/decorators/http/POST.d.ts +91 -0
- package/dist/types/decorators/http/PUT.d.ts +92 -0
- package/dist/types/exceptions/AccessDeniedException.d.ts +10 -0
- package/dist/types/exceptions/ControllerActionNotFoundException.d.ts +9 -0
- package/dist/types/exceptions/DuplicateActionNameException.d.ts +8 -0
- package/dist/types/exceptions/EntrypointStoppedException.d.ts +9 -0
- package/dist/types/exceptions/InvalidActionGroupException.d.ts +4 -0
- package/dist/types/exceptions/InvalidChannelException.d.ts +8 -0
- package/dist/types/exceptions/InvalidEntrypointAdapterException.d.ts +9 -0
- package/dist/types/exceptions/InvalidMiddlewareException.d.ts +8 -0
- package/dist/types/exceptions/InvalidPrefixException.d.ts +8 -0
- package/dist/types/exceptions/MiddlewareNextCalledException.d.ts +8 -0
- package/dist/types/exceptions/RouteNotFoundException.d.ts +9 -0
- package/dist/types/exceptions/ServiceInvokeException.d.ts +11 -0
- package/dist/types/exports/CTRLDecorators.d.ts +13 -0
- package/dist/types/exports/Channel.d.ts +14 -0
- package/dist/types/exports/CommanderAdapter.d.ts +1 -0
- package/dist/types/exports/ElectronAdapter.d.ts +1 -0
- package/dist/types/exports/Entrypoint.d.ts +24 -0
- package/dist/types/exports/ExpressAdapter.d.ts +4 -0
- package/dist/types/exports/FastifyAdapter.d.ts +4 -0
- package/dist/types/exports/JSONRPCAdapter.d.ts +2 -0
- package/dist/types/exports/SocketIOAdapter.d.ts +1 -0
- package/dist/types/lib/AccessControl.d.ts +118 -0
- package/dist/types/lib/AccessControlRule.d.ts +91 -0
- package/dist/types/lib/ActionOptions.d.ts +67 -0
- package/dist/types/lib/ActionResult.d.ts +28 -0
- package/dist/types/lib/ApplicationOf.d.ts +6 -0
- package/dist/types/lib/Controller.d.ts +59 -0
- package/dist/types/lib/ControllerEntrypoint.d.ts +168 -0
- package/dist/types/lib/GetActionDTOAndOptions.d.ts +29 -0
- package/dist/types/lib/HTTPErrors.d.ts +55 -0
- package/dist/types/lib/Middleware.d.ts +146 -0
- package/dist/types/lib/Prefix.d.ts +98 -0
- package/dist/types/lib/Result.d.ts +173 -0
- package/dist/types/lib/ServiceResponseCodec.d.ts +82 -0
- package/dist/types/lib/StringifyPattern.d.ts +7 -0
- package/dist/types/lib/UnsetValue.d.ts +12 -0
- package/dist/types/lib/pattern/GlobPattern.d.ts +34 -0
- package/dist/types/lib/pattern/PatternManager.d.ts +103 -0
- package/dist/types/lib/schedule/Cron.d.ts +56 -0
- package/dist/types/types/CLIContextParams.d.ts +14 -0
- package/dist/types/types/ErrorDescription.d.ts +14 -0
- package/dist/types/types/HTTPContextParams.d.ts +27 -0
- package/dist/types/types/ScheduleContextParams.d.ts +21 -0
- package/dist/types/types/ServiceContextParams.d.ts +16 -0
- package/package.json +152 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import type { Request, Response } from 'express';
|
|
2
|
+
import { describeError, type HTTPErrorOrigin, statusOfError } from '../../lib/HTTPErrors.js';
|
|
3
|
+
export { describeError, statusOfError, type HTTPErrorOrigin };
|
|
4
|
+
/**
|
|
5
|
+
* How {@link expressHTTPEntrypoint} writes the results and the errors of the actions (its `respond` option). Implement
|
|
6
|
+
* it to give the responses another shape; {@link JSONResponder} is the default, {@link jsonEnvelope} wraps them in an
|
|
7
|
+
* envelope. The file results and the event streams are not written by the responder.
|
|
8
|
+
*/
|
|
9
|
+
export interface ExpressResponder {
|
|
10
|
+
/**
|
|
11
|
+
* Write the result of an action. For a `StatusResult`, its status and headers are already set on the response and
|
|
12
|
+
* `data` is its payload.
|
|
13
|
+
* @param response The express response to write.
|
|
14
|
+
* @param data The action's result, `undefined` when it returned nothing.
|
|
15
|
+
* @param request The express request being answered.
|
|
16
|
+
*/
|
|
17
|
+
success(response: Response, data: unknown, request: Request): void;
|
|
18
|
+
/**
|
|
19
|
+
* Write an error: a failed action (validation, access control, its own exception), an error passed by an express
|
|
20
|
+
* middleware (`next(error)`: an authenticator), or a request matching no route (`RouteNotFoundException`). Not
|
|
21
|
+
* called once the response headers are sent, nor after the client left.
|
|
22
|
+
* @param response The express response to write.
|
|
23
|
+
* @param error The thrown error.
|
|
24
|
+
* @param request The express request being answered.
|
|
25
|
+
* @param origin Where the error comes from: `'action'` (the dispatch of an action failed) or `'request'` (an
|
|
26
|
+
* express middleware, a route not found); see {@link HTTPErrorOrigin}.
|
|
27
|
+
*/
|
|
28
|
+
error(response: Response, error: unknown, request: Request, origin?: HTTPErrorOrigin): void;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* The default responder of {@link expressHTTPEntrypoint}: a result is sent as JSON, no result as an empty 204 (or the
|
|
32
|
+
* status set by a `StatusResult`); an error is sent as `{errno, errMsg}` (see `describeError`) with its HTTP status
|
|
33
|
+
* (see `statusOfError`: the first 4xx status in its cause chain, its own status, or 500).
|
|
34
|
+
*/
|
|
35
|
+
export declare const JSONResponder: ExpressResponder;
|
|
36
|
+
/**
|
|
37
|
+
* The options of {@link jsonEnvelope}.
|
|
38
|
+
*/
|
|
39
|
+
export type JSONEnvelopeOptions = {
|
|
40
|
+
/**
|
|
41
|
+
* The HTTP status of every error response, such as 200 for the clients that read the errors from the envelope.
|
|
42
|
+
* @default the error's own status (see `statusOfError`)
|
|
43
|
+
*/
|
|
44
|
+
errorStatus?: number;
|
|
45
|
+
/**
|
|
46
|
+
* The HTTP status of the errors of the actions only (their dispatch failed: validation, access control, their own
|
|
47
|
+
* exceptions), over `errorStatus`; the errors of the express middlewares (an authenticator's 401) and the routes
|
|
48
|
+
* not found keep theirs. 200 answers as the applications of lakutata 2.x usually did.
|
|
49
|
+
* @default `errorStatus`
|
|
50
|
+
*/
|
|
51
|
+
actionErrorStatus?: number;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Create a responder for {@link expressHTTPEntrypoint} that wraps every response in the envelope
|
|
55
|
+
* `{errno, errMsg, data}`: a result as `{errno: null, errMsg: null, data}` (`data` is `null` when the action returned
|
|
56
|
+
* nothing, and its status is not turned into 204), an error as `{errno, errMsg, data: null}` with the error's status,
|
|
57
|
+
* the `errorStatus` option, or for the errors of the actions the `actionErrorStatus` option.
|
|
58
|
+
* @param options The envelope options.
|
|
59
|
+
* @returns The responder, to give to the `respond` option of `expressHTTPEntrypoint`.
|
|
60
|
+
* @example
|
|
61
|
+
* ```typescript
|
|
62
|
+
* import {Application} from 'lakutata'
|
|
63
|
+
* import {buildEntrypoints, Controller} from 'lakutata/com/entrypoint'
|
|
64
|
+
* import {GET} from 'lakutata/decorator/ctrl'
|
|
65
|
+
* import {expressHTTPEntrypoint, jsonEnvelope} from 'lakutata/adapter/express'
|
|
66
|
+
*
|
|
67
|
+
* class PingController extends Controller {
|
|
68
|
+
* //GET /ping answers {"errno": null, "errMsg": null, "data": "pong"}
|
|
69
|
+
* @GET('/ping')
|
|
70
|
+
* public async ping(): Promise<string> {
|
|
71
|
+
* return 'pong'
|
|
72
|
+
* }
|
|
73
|
+
* }
|
|
74
|
+
*
|
|
75
|
+
* Application.run({
|
|
76
|
+
* id: 'web.app',
|
|
77
|
+
* name: 'Web',
|
|
78
|
+
* components: {
|
|
79
|
+
* entrypoint: buildEntrypoints({
|
|
80
|
+
* controllers: [PingController],
|
|
81
|
+
* //The errors of the actions answered with 200 too (as the applications of lakutata 2.x), the routes not
|
|
82
|
+
* //found and the errors of the express middlewares with their status (404, 401…)
|
|
83
|
+
* http: expressHTTPEntrypoint({port: 8080, respond: jsonEnvelope({actionErrorStatus: 200})})
|
|
84
|
+
* })
|
|
85
|
+
* }
|
|
86
|
+
* })
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
export declare function jsonEnvelope(options?: JSONEnvelopeOptions): ExpressResponder;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { type RequestHandler } from 'express';
|
|
2
|
+
/**
|
|
3
|
+
* The options of {@link staticUI}.
|
|
4
|
+
*/
|
|
5
|
+
export type StaticUIOptions = {
|
|
6
|
+
/**
|
|
7
|
+
* Serve a single-page application: a GET or HEAD request accepting HTML, whose path has no file extension and
|
|
8
|
+
* matches no file, is answered with the index (the client-side router handles the path). With `false`, such a
|
|
9
|
+
* request is passed on (a 404 behind `expressHTTPEntrypoint`).
|
|
10
|
+
* @default true
|
|
11
|
+
*/
|
|
12
|
+
spa?: boolean;
|
|
13
|
+
/**
|
|
14
|
+
* The index file of the application, relative to the directory.
|
|
15
|
+
* @default 'index.html'
|
|
16
|
+
*/
|
|
17
|
+
index?: string;
|
|
18
|
+
/**
|
|
19
|
+
* How long the browsers may cache the files with a content hash in their name (the assets of a Vite build:
|
|
20
|
+
* `index-B2x9fQ1a.js`): a number of seconds, or a duration (`'30d'`, `'12h'`; a string of digits is seconds). A file
|
|
21
|
+
* counts as hashed when it is a script, a style, a font or an image whose name ends with a dot or a dash followed by
|
|
22
|
+
* at least 8 letters, digits, `_` or `-`, among them a digit or an uppercase letter, before its extension
|
|
23
|
+
* (`index-B2x9fQ1a.js`, `main.3f2a1b9c.css`, not `my-component.js`). The other files and the index are sent with
|
|
24
|
+
* `Cache-Control: no-cache`.
|
|
25
|
+
* @default 31536000 (one year)
|
|
26
|
+
*/
|
|
27
|
+
assetsMaxAge?: string | number;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Whether a file of a built UI has a content hash in its name: a script, a style, a font or an image whose name ends
|
|
31
|
+
* with a dot or a dash followed by at least 8 letters, digits, `_` or `-`, among them a digit or an uppercase letter
|
|
32
|
+
* @param file
|
|
33
|
+
* @internal
|
|
34
|
+
*/
|
|
35
|
+
export declare function isHashedAsset(file: string): boolean;
|
|
36
|
+
/**
|
|
37
|
+
* The seconds the hashed assets are cached: a number of seconds, or a duration
|
|
38
|
+
* @param value
|
|
39
|
+
* @internal
|
|
40
|
+
*/
|
|
41
|
+
export declare function assetsMaxAge(value: string | number | undefined): number;
|
|
42
|
+
/**
|
|
43
|
+
* Create an express handler serving a built web UI (the `dist` directory of a Vite application): its files, and its
|
|
44
|
+
* index for the paths of its client-side routes. Given as the `fallback` of {@link expressHTTPEntrypoint}, it never
|
|
45
|
+
* receives the paths of the actions. It needs the optional peer dependency `express`.
|
|
46
|
+
*
|
|
47
|
+
* The files with a content hash in their name are cached for a long time (`assetsMaxAge`), the other files and the
|
|
48
|
+
* index are revalidated on each request. A request matching no file that is not a page request (an asset, a non-GET
|
|
49
|
+
* request, a client not accepting HTML) is passed on to the next handler.
|
|
50
|
+
* @param directory The directory of the built UI, resolved from the current working directory.
|
|
51
|
+
* @param options How the index is served and the assets cached.
|
|
52
|
+
* @returns The express request handler.
|
|
53
|
+
* @example
|
|
54
|
+
* ```typescript
|
|
55
|
+
* import {Application} from 'lakutata'
|
|
56
|
+
* import {buildEntrypoints, Controller} from 'lakutata/com/entrypoint'
|
|
57
|
+
* import {GET} from 'lakutata/decorator/ctrl'
|
|
58
|
+
* import {expressHTTPEntrypoint, staticUI} from 'lakutata/adapter/express'
|
|
59
|
+
*
|
|
60
|
+
* class DeviceController extends Controller {
|
|
61
|
+
* //GET /api/devices answers the action; GET /settings answers the index of the UI
|
|
62
|
+
* @GET('/api/devices')
|
|
63
|
+
* public async list(): Promise<string[]> {
|
|
64
|
+
* return ['sensor-1']
|
|
65
|
+
* }
|
|
66
|
+
* }
|
|
67
|
+
*
|
|
68
|
+
* Application.run({
|
|
69
|
+
* id: 'console.app',
|
|
70
|
+
* name: 'Console',
|
|
71
|
+
* components: {
|
|
72
|
+
* entrypoint: buildEntrypoints({
|
|
73
|
+
* controllers: [DeviceController],
|
|
74
|
+
* http: expressHTTPEntrypoint({
|
|
75
|
+
* port: 8080,
|
|
76
|
+
* fallback: staticUI('./ui/dist', {assetsMaxAge: 86400})
|
|
77
|
+
* })
|
|
78
|
+
* })
|
|
79
|
+
* }
|
|
80
|
+
* })
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
export declare function staticUI(directory: string, options?: StaticUIOptions): RequestHandler;
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { type FastifyInstance, type FastifyReply, type FastifyRequest, type FastifyServerOptions } from 'fastify';
|
|
2
|
+
import type { Server } from 'node:http';
|
|
3
|
+
import type { Module } from '@lakutata/core';
|
|
4
|
+
import type { EntrypointAdapter } from '../../channel/EntrypointAdapter.js';
|
|
5
|
+
import type { MiddlewareDefinition } from '../../lib/Middleware.js';
|
|
6
|
+
import { HTTPContext } from '../../context/HTTPContext.js';
|
|
7
|
+
import { type FastifyResponder } from './Responders.js';
|
|
8
|
+
/**
|
|
9
|
+
* What the `before` hook of {@link fastifyHTTPEntrypoint} receives besides the fastify instance: the entrypoint's
|
|
10
|
+
* module, the HTTP server (not listening yet) and the routes the actions will occupy.
|
|
11
|
+
*/
|
|
12
|
+
export type FastifyHookContext = {
|
|
13
|
+
/**
|
|
14
|
+
* The module owning the entrypoint, to get the application's objects from (`await module.getObject('db')`).
|
|
15
|
+
*/
|
|
16
|
+
readonly module: Module;
|
|
17
|
+
/**
|
|
18
|
+
* The HTTP server of the fastify instance. It does not listen yet when the hook runs; attach other servers to it
|
|
19
|
+
* there (such as a socket.io server, see the `server` option of `socketIOServiceEntrypoint`).
|
|
20
|
+
*/
|
|
21
|
+
readonly server: Server;
|
|
22
|
+
/**
|
|
23
|
+
* Each action route mapped to its HTTP methods, in upper case (`'/users/:id'` → `{'GET', 'DELETE'}`).
|
|
24
|
+
*/
|
|
25
|
+
readonly routes: Map<string, Set<string>>;
|
|
26
|
+
/**
|
|
27
|
+
* The first segment of each action route (`'/device'`, `'/user'`…). A route starting with a parameter (`/:id`)
|
|
28
|
+
* adds none.
|
|
29
|
+
*/
|
|
30
|
+
readonly actionPrefixes: string[];
|
|
31
|
+
/**
|
|
32
|
+
* Tell whether a request path belongs to the actions: it equals one of the action prefixes or starts with one
|
|
33
|
+
* followed by `/`.
|
|
34
|
+
*/
|
|
35
|
+
readonly isActionPath: (requestPath: string) => boolean;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* The options of {@link fastifyHTTPEntrypoint}.
|
|
39
|
+
*/
|
|
40
|
+
export type FastifyHTTPEntrypointOptions = {
|
|
41
|
+
/**
|
|
42
|
+
* The adapter name, to tell apart several HTTP adapters of one entrypoint.
|
|
43
|
+
*/
|
|
44
|
+
name?: string;
|
|
45
|
+
/**
|
|
46
|
+
* The port the server listens on; 0 picks a random free port. The entrypoint fails to start when the port is in use.
|
|
47
|
+
* @default 80
|
|
48
|
+
*/
|
|
49
|
+
port?: number;
|
|
50
|
+
/**
|
|
51
|
+
* The host or address the server listens on.
|
|
52
|
+
* @default every interface, as the other HTTP adapters (`::`, or `0.0.0.0` without IPv6)
|
|
53
|
+
*/
|
|
54
|
+
host?: string;
|
|
55
|
+
/**
|
|
56
|
+
* An existing fastify instance to add the action routes to, or the options of the instance to create (`bodyLimit`,
|
|
57
|
+
* `trustProxy`, `logger`…). The adapter closes the instance when it stops, a given one included.
|
|
58
|
+
* @default a new fastify instance with its default options (a body limit of 1 MiB)
|
|
59
|
+
*/
|
|
60
|
+
fastify?: FastifyInstance | FastifyServerOptions;
|
|
61
|
+
/**
|
|
62
|
+
* Build an action's input from a request. The route parameters are always merged over its result.
|
|
63
|
+
* @default the query parameters, then the properties of an object body over them (an array body is ignored)
|
|
64
|
+
*/
|
|
65
|
+
input?: (request: FastifyRequest) => Record<string, unknown>;
|
|
66
|
+
/**
|
|
67
|
+
* How the results and the errors of the actions are written.
|
|
68
|
+
* @default FastifyJSONResponder
|
|
69
|
+
*/
|
|
70
|
+
respond?: FastifyResponder;
|
|
71
|
+
/**
|
|
72
|
+
* The middlewares of this adapter's actions, run after the entrypoint's global middlewares.
|
|
73
|
+
*/
|
|
74
|
+
middlewares?: MiddlewareDefinition[];
|
|
75
|
+
/**
|
|
76
|
+
* Run before the action routes are added, to register the application's own plugins, hooks and routes. A failure
|
|
77
|
+
* fails the entrypoint start.
|
|
78
|
+
*/
|
|
79
|
+
before?: (app: FastifyInstance, context: FastifyHookContext) => void | Promise<void>;
|
|
80
|
+
/**
|
|
81
|
+
* The handler of the requests that match no route and whose path is outside the action prefixes, such as the pages
|
|
82
|
+
* of a web application. The unmatched requests inside the action prefixes, and all of them without a fallback, are
|
|
83
|
+
* answered with a `RouteNotFoundException` (404).
|
|
84
|
+
*/
|
|
85
|
+
fallback?: (request: FastifyRequest, reply: FastifyReply) => unknown;
|
|
86
|
+
/**
|
|
87
|
+
* Run when the adapter stops, after the server is closed.
|
|
88
|
+
*/
|
|
89
|
+
stop?: () => void | Promise<void>;
|
|
90
|
+
/**
|
|
91
|
+
* The interval between the comments keeping the event streams (`EventsResult`) alive through the proxies, in
|
|
92
|
+
* milliseconds.
|
|
93
|
+
* @default 15000
|
|
94
|
+
*/
|
|
95
|
+
heartbeat?: number;
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* Create the HTTP adapter of an entrypoint served by a fastify instance: each HTTP action (`@GET`, `@POST`,
|
|
99
|
+
* `@HTTPAction`…) becomes a fastify route. It needs the optional peer dependency `fastify`.
|
|
100
|
+
*
|
|
101
|
+
* An action's input is the request's query and body (see the `input` option) with the route parameters merged over
|
|
102
|
+
* them. Its result is written by the responder (JSON by default, 204 for no result); a `StatusResult` sets the status
|
|
103
|
+
* and the headers, a `FileResult` sends a file, a buffer or a stream (its content type guessed from the extension of
|
|
104
|
+
* its file name, 304 when its ETag matches `If-None-Match`), and an `EventsResult` streams Server-Sent Events. An action
|
|
105
|
+
* that writes the response itself (through `HTTPContext.response`) is left alone. The errors, those of fastify included
|
|
106
|
+
* (a body too large: 413, a malformed JSON body: 400), are written by the responder with their status (500 by default).
|
|
107
|
+
* A GET action also answers HEAD, unless a HEAD action is declared for its route.
|
|
108
|
+
*
|
|
109
|
+
* When the client disconnects before the response, the action's abort signal fires and nothing is written. When the
|
|
110
|
+
* entrypoint stops, fastify stops accepting connections and answers the new requests with 503, the event streams end,
|
|
111
|
+
* and the requests in progress are given up to one second after they settle to send their responses before the
|
|
112
|
+
* remaining connections are closed.
|
|
113
|
+
* @param options The adapter options; by default it listens on port 80 with a new fastify instance.
|
|
114
|
+
* @returns The adapter, to give to the `http` option of `buildEntrypoints`.
|
|
115
|
+
* @example
|
|
116
|
+
* ```typescript
|
|
117
|
+
* import {Application} from 'lakutata'
|
|
118
|
+
* import {buildEntrypoints, Controller} from 'lakutata/com/entrypoint'
|
|
119
|
+
* import {GET, POST} from 'lakutata/decorator/ctrl'
|
|
120
|
+
* import {fastifyHTTPEntrypoint} from 'lakutata/adapter/fastify'
|
|
121
|
+
*
|
|
122
|
+
* class UserController extends Controller {
|
|
123
|
+
* //GET /users/1?verbose=true: the route parameter id merged over the query
|
|
124
|
+
* @GET('/users/:id')
|
|
125
|
+
* public async get(input: {id: string, verbose?: string}): Promise<{id: string}> {
|
|
126
|
+
* return {id: input.id}
|
|
127
|
+
* }
|
|
128
|
+
*
|
|
129
|
+
* //POST /users with the JSON body {"name": "Ada"}
|
|
130
|
+
* @POST('/users')
|
|
131
|
+
* public async create(input: {name: string}): Promise<{name: string}> {
|
|
132
|
+
* return {name: input.name}
|
|
133
|
+
* }
|
|
134
|
+
* }
|
|
135
|
+
*
|
|
136
|
+
* Application.run({
|
|
137
|
+
* id: 'web.app',
|
|
138
|
+
* name: 'Web',
|
|
139
|
+
* components: {
|
|
140
|
+
* entrypoint: buildEntrypoints({
|
|
141
|
+
* controllers: [UserController],
|
|
142
|
+
* http: fastifyHTTPEntrypoint({
|
|
143
|
+
* port: 8080,
|
|
144
|
+
* host: '0.0.0.0',
|
|
145
|
+
* fastify: {bodyLimit: 5 * 1024 * 1024, trustProxy: true},
|
|
146
|
+
* //The application's own routes
|
|
147
|
+
* before: (app): void => {
|
|
148
|
+
* app.get('/health', async (): Promise<string> => 'ok')
|
|
149
|
+
* }
|
|
150
|
+
* })
|
|
151
|
+
* })
|
|
152
|
+
* }
|
|
153
|
+
* })
|
|
154
|
+
* ```
|
|
155
|
+
*/
|
|
156
|
+
export declare function fastifyHTTPEntrypoint(options?: FastifyHTTPEntrypointOptions): EntrypointAdapter<HTTPContext>;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import type { FastifyReply, FastifyRequest } from 'fastify';
|
|
2
|
+
import { type HTTPErrorOrigin } from '../../lib/HTTPErrors.js';
|
|
3
|
+
/**
|
|
4
|
+
* How {@link fastifyHTTPEntrypoint} writes the results and the errors of the actions (its `respond` option). Implement
|
|
5
|
+
* it to give the responses another shape; {@link FastifyJSONResponder} is the default, {@link fastifyJSONEnvelope}
|
|
6
|
+
* wraps them in an envelope. The file results and the event streams are not written by the responder.
|
|
7
|
+
*/
|
|
8
|
+
export interface FastifyResponder {
|
|
9
|
+
/**
|
|
10
|
+
* Write the result of an action. For a `StatusResult`, its status and headers are already set on the reply and
|
|
11
|
+
* `data` is its payload.
|
|
12
|
+
* @param reply The fastify reply to send.
|
|
13
|
+
* @param data The action's result, `undefined` when it returned nothing.
|
|
14
|
+
* @param request The fastify request being answered.
|
|
15
|
+
*/
|
|
16
|
+
success(reply: FastifyReply, data: unknown, request: FastifyRequest): void;
|
|
17
|
+
/**
|
|
18
|
+
* Write an error: a failed action (validation, access control, its own exception), an error of fastify (a hook such
|
|
19
|
+
* as an authenticator, a body too large), or a request matching no route (`RouteNotFoundException`). Not called for
|
|
20
|
+
* an action once the reply is sent, nor after the client left.
|
|
21
|
+
* @param reply The fastify reply to send.
|
|
22
|
+
* @param error The thrown error.
|
|
23
|
+
* @param request The fastify request being answered.
|
|
24
|
+
* @param origin Where the error comes from: `'action'` (the dispatch of an action failed) or `'request'` (a hook,
|
|
25
|
+
* an error of fastify, a route not found); see `HTTPErrorOrigin`.
|
|
26
|
+
*/
|
|
27
|
+
error(reply: FastifyReply, error: unknown, request: FastifyRequest, origin?: HTTPErrorOrigin): void;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The default responder of {@link fastifyHTTPEntrypoint}: a result is sent as JSON, no result as an empty 204 (or the
|
|
31
|
+
* status set by a `StatusResult`); an error is sent as `{errno, errMsg}` (see `describeError`) with its HTTP status
|
|
32
|
+
* (see `statusOfError`: the first 4xx status in its cause chain, its own status, or 500).
|
|
33
|
+
*/
|
|
34
|
+
export declare const FastifyJSONResponder: FastifyResponder;
|
|
35
|
+
/**
|
|
36
|
+
* The options of {@link fastifyJSONEnvelope}.
|
|
37
|
+
*/
|
|
38
|
+
export type FastifyJSONEnvelopeOptions = {
|
|
39
|
+
/**
|
|
40
|
+
* The HTTP status of every error response, such as 200 for the clients that read the errors from the envelope.
|
|
41
|
+
* @default the error's own status (see `statusOfError`)
|
|
42
|
+
*/
|
|
43
|
+
errorStatus?: number;
|
|
44
|
+
/**
|
|
45
|
+
* The HTTP status of the errors of the actions only (their dispatch failed: validation, access control, their own
|
|
46
|
+
* exceptions), over `errorStatus`; the errors of the hooks (an authenticator's 401), of fastify and the routes not
|
|
47
|
+
* found keep theirs. 200 answers as the applications of lakutata 2.x usually did.
|
|
48
|
+
* @default `errorStatus`
|
|
49
|
+
*/
|
|
50
|
+
actionErrorStatus?: number;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Create a responder for {@link fastifyHTTPEntrypoint} that wraps every response in the envelope
|
|
54
|
+
* `{errno, errMsg, data}`: a result as `{errno: null, errMsg: null, data}` (`data` is `null` when the action returned
|
|
55
|
+
* nothing, and its status is not turned into 204), an error as `{errno, errMsg, data: null}` with the error's status,
|
|
56
|
+
* the `errorStatus` option, or for the errors of the actions the `actionErrorStatus` option.
|
|
57
|
+
* @param options The envelope options.
|
|
58
|
+
* @returns The responder, to give to the `respond` option of `fastifyHTTPEntrypoint`.
|
|
59
|
+
* @example
|
|
60
|
+
* ```typescript
|
|
61
|
+
* import {Application} from 'lakutata'
|
|
62
|
+
* import {buildEntrypoints, Controller} from 'lakutata/com/entrypoint'
|
|
63
|
+
* import {GET} from 'lakutata/decorator/ctrl'
|
|
64
|
+
* import {fastifyHTTPEntrypoint, fastifyJSONEnvelope} from 'lakutata/adapter/fastify'
|
|
65
|
+
*
|
|
66
|
+
* class PingController extends Controller {
|
|
67
|
+
* //GET /ping answers {"errno": null, "errMsg": null, "data": "pong"}
|
|
68
|
+
* @GET('/ping')
|
|
69
|
+
* public async ping(): Promise<string> {
|
|
70
|
+
* return 'pong'
|
|
71
|
+
* }
|
|
72
|
+
* }
|
|
73
|
+
*
|
|
74
|
+
* Application.run({
|
|
75
|
+
* id: 'web.app',
|
|
76
|
+
* name: 'Web',
|
|
77
|
+
* components: {
|
|
78
|
+
* entrypoint: buildEntrypoints({
|
|
79
|
+
* controllers: [PingController],
|
|
80
|
+
* //The errors of the actions answered with 200 too (as the applications of lakutata 2.x), the routes not
|
|
81
|
+
* //found and the errors of the hooks with their status (404, 401…)
|
|
82
|
+
* http: fastifyHTTPEntrypoint({port: 8080, respond: fastifyJSONEnvelope({actionErrorStatus: 200})})
|
|
83
|
+
* })
|
|
84
|
+
* }
|
|
85
|
+
* })
|
|
86
|
+
* ```
|
|
87
|
+
*/
|
|
88
|
+
export declare function fastifyJSONEnvelope(options?: FastifyJSONEnvelopeOptions): FastifyResponder;
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { type IncomingMessage, type Server } from 'node:http';
|
|
2
|
+
import type { EntrypointAdapter } from '../../channel/EntrypointAdapter.js';
|
|
3
|
+
import type { MiddlewareDefinition } from '../../lib/Middleware.js';
|
|
4
|
+
import { ServiceContext } from '../../context/ServiceContext.js';
|
|
5
|
+
/**
|
|
6
|
+
* The options of {@link httpServiceEntrypoint}.
|
|
7
|
+
*/
|
|
8
|
+
export type HTTPServiceEntrypointOptions = {
|
|
9
|
+
/**
|
|
10
|
+
* The adapter name, to tell apart several service adapters of one entrypoint.
|
|
11
|
+
*/
|
|
12
|
+
name?: string;
|
|
13
|
+
/**
|
|
14
|
+
* The port the server listens on; 0 picks a random free port. The entrypoint fails to start when the port is in use.
|
|
15
|
+
* @default 3000
|
|
16
|
+
*/
|
|
17
|
+
port?: number;
|
|
18
|
+
/**
|
|
19
|
+
* The host or address the server listens on.
|
|
20
|
+
* @default all the interfaces
|
|
21
|
+
*/
|
|
22
|
+
host?: string;
|
|
23
|
+
/**
|
|
24
|
+
* The path receiving the requests (POST). The event stream is served on `events` under it (`/api` → `/api/events`).
|
|
25
|
+
* @default '/'
|
|
26
|
+
*/
|
|
27
|
+
path?: string;
|
|
28
|
+
/**
|
|
29
|
+
* The largest request body, in bytes; a larger one is answered with 413 and an error response.
|
|
30
|
+
* @default 10485760 (10 MiB)
|
|
31
|
+
*/
|
|
32
|
+
limit?: number;
|
|
33
|
+
/**
|
|
34
|
+
* The middlewares of this adapter's actions, run after the entrypoint's global middlewares.
|
|
35
|
+
*/
|
|
36
|
+
middlewares?: MiddlewareDefinition[];
|
|
37
|
+
/**
|
|
38
|
+
* Run once the server listens, with the server (to read the port picked for port 0). A failure fails the entrypoint
|
|
39
|
+
* start.
|
|
40
|
+
*/
|
|
41
|
+
listening?: (server: Server) => void | Promise<void>;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Get the HTTP request carrying a service action's request, when {@link httpServiceEntrypoint} serves it (to read its
|
|
45
|
+
* headers, its remote address…).
|
|
46
|
+
* @param context The service action's context (`this.context` in a controller).
|
|
47
|
+
* @returns The Node.js HTTP request, or `undefined` when another adapter serves the request.
|
|
48
|
+
* @example
|
|
49
|
+
* ```typescript
|
|
50
|
+
* import {Controller, httpRequestOfContext, ServiceContext} from 'lakutata/com/entrypoint'
|
|
51
|
+
* import {ServiceAction} from 'lakutata/decorator/ctrl'
|
|
52
|
+
*
|
|
53
|
+
* class WhoAmIController extends Controller {
|
|
54
|
+
* @ServiceAction({cmd: 'whoami'})
|
|
55
|
+
* public async whoami(): Promise<string | undefined> {
|
|
56
|
+
* return httpRequestOfContext(this.context as ServiceContext)?.socket.remoteAddress
|
|
57
|
+
* }
|
|
58
|
+
* }
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
export declare function httpRequestOfContext(context: ServiceContext): IncomingMessage | undefined;
|
|
62
|
+
/**
|
|
63
|
+
* Create a service adapter of an entrypoint served over plain HTTP, handy to call the service actions from tools such
|
|
64
|
+
* as curl or Postman during development. It needs no optional dependency.
|
|
65
|
+
*
|
|
66
|
+
* A request is a `POST` to the path whose JSON body holds the action's pattern and input (`{"cmd": "echo", "text":
|
|
67
|
+
* "hi"}`). The response is always 200 with the body `{success, error, payload}` (see `ServiceResponseCodec`): `payload`
|
|
68
|
+
* is the result, or `error` the whole error object when the action failed (no matching action, validation…). A body that
|
|
69
|
+
* is not JSON or exceeds `limit` is answered with 400 and an error body; any other method or path with 404. The CORS
|
|
70
|
+
* headers allow any origin.
|
|
71
|
+
*
|
|
72
|
+
* The events pushed to the clients (`Entrypoint.notify`, `Entrypoint.broadcast`) are streamed as Server-Sent Events by
|
|
73
|
+
* `GET <path>/events`: each event's name is the SSE event, its arguments the JSON array of its data. A client gives its
|
|
74
|
+
* id in the `id` header or the `id` query parameter (at most 200 characters), the same on its requests so that they
|
|
75
|
+
* carry it as `ServiceContext.clientId`; without one, the stream assigns a random id, sent first as the `client` event.
|
|
76
|
+
* The streams receive a keep-alive comment every 15 seconds.
|
|
77
|
+
*
|
|
78
|
+
* When a client disconnects before its response, the action's abort signal fires. When the entrypoint stops, the new
|
|
79
|
+
* requests are answered with an `EntrypointStoppedException` error; once the requests in progress end, the event
|
|
80
|
+
* streams are closed and the server shuts down.
|
|
81
|
+
* @param options The adapter options; by default it listens on port 3000 of all the interfaces, on the path `/`.
|
|
82
|
+
* @returns The adapter, to give to the `service` option of `buildEntrypoints`.
|
|
83
|
+
* @example
|
|
84
|
+
* ```typescript
|
|
85
|
+
* import {Application} from 'lakutata'
|
|
86
|
+
* import {buildEntrypoints, Controller, httpServiceEntrypoint} from 'lakutata/com/entrypoint'
|
|
87
|
+
* import {ServiceAction} from 'lakutata/decorator/ctrl'
|
|
88
|
+
*
|
|
89
|
+
* class EchoController extends Controller {
|
|
90
|
+
* @ServiceAction({cmd: 'echo'})
|
|
91
|
+
* public async echo(input: {text: string}): Promise<string> {
|
|
92
|
+
* return input.text
|
|
93
|
+
* }
|
|
94
|
+
* }
|
|
95
|
+
*
|
|
96
|
+
* Application.run({
|
|
97
|
+
* id: 'echo.service',
|
|
98
|
+
* name: 'Echo',
|
|
99
|
+
* components: {
|
|
100
|
+
* entrypoint: buildEntrypoints({
|
|
101
|
+
* controllers: [EchoController],
|
|
102
|
+
* service: httpServiceEntrypoint({port: 3000, path: '/rpc'})
|
|
103
|
+
* })
|
|
104
|
+
* }
|
|
105
|
+
* })
|
|
106
|
+
*
|
|
107
|
+
* //A client: the response is {"success": true, "error": null, "payload": "hi"}
|
|
108
|
+
* const response: Response = await fetch('http://localhost:3000/rpc', {
|
|
109
|
+
* method: 'POST',
|
|
110
|
+
* headers: {'Content-Type': 'application/json', 'id': 'client-1'},
|
|
111
|
+
* body: JSON.stringify({cmd: 'echo', text: 'hi'})
|
|
112
|
+
* })
|
|
113
|
+
* console.log(await response.json())
|
|
114
|
+
* //The events pushed to client-1: GET http://localhost:3000/rpc/events?id=client-1 (text/event-stream)
|
|
115
|
+
* ```
|
|
116
|
+
*/
|
|
117
|
+
export declare function httpServiceEntrypoint(options?: HTTPServiceEntrypointOptions): EntrypointAdapter<ServiceContext>;
|