@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,397 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.jsonRPCServiceEntrypoint = jsonRPCServiceEntrypoint;
|
|
37
|
+
const node_crypto_1 = require("node:crypto");
|
|
38
|
+
const node_http_1 = require("node:http");
|
|
39
|
+
const BuiltinChannels_js_1 = require("../../channel/BuiltinChannels.js");
|
|
40
|
+
const JSONRPCProtocol_js_1 = require("./JSONRPCProtocol.js");
|
|
41
|
+
const ApplicationOf_js_1 = require("../../lib/ApplicationOf.js");
|
|
42
|
+
/**
|
|
43
|
+
* The headers of the responses of HTTP: the tools of the browsers may call the adapter
|
|
44
|
+
*/
|
|
45
|
+
const CORS_HEADERS = {
|
|
46
|
+
'Access-Control-Allow-Origin': '*',
|
|
47
|
+
'Access-Control-Allow-Methods': 'POST, OPTIONS',
|
|
48
|
+
'Access-Control-Allow-Headers': 'Content-Type, id'
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* The id of the client of a request of HTTP (its header id, its query id)
|
|
52
|
+
* @param request
|
|
53
|
+
*/
|
|
54
|
+
function clientIdOf(request) {
|
|
55
|
+
const url = new URL(request.url ?? '/', 'http://localhost');
|
|
56
|
+
const given = request.headers.id ?? url.searchParams.get('id');
|
|
57
|
+
const id = Array.isArray(given) ? given[0] : given ?? undefined;
|
|
58
|
+
return id && id.length <= 200 ? id : undefined;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* The body of a request, up to a limit
|
|
62
|
+
* @param request
|
|
63
|
+
* @param limit
|
|
64
|
+
*/
|
|
65
|
+
async function readBody(request, limit) {
|
|
66
|
+
const chunks = [];
|
|
67
|
+
let size = 0;
|
|
68
|
+
for await (const chunk of request) {
|
|
69
|
+
size += chunk.length;
|
|
70
|
+
if (size > limit)
|
|
71
|
+
throw Object.assign(new Error(`The body of the request is larger than ${limit} bytes`), { status: 413 });
|
|
72
|
+
chunks.push(chunk);
|
|
73
|
+
}
|
|
74
|
+
return Buffer.concat(chunks).toString('utf8');
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* The messages of a stream framed by lines, or by their Content-Length headers. A message larger than the limit is
|
|
78
|
+
* skipped (the rest of its line, or the length its header declares, keeping the framing) and reported
|
|
79
|
+
* @param input
|
|
80
|
+
* @param framing
|
|
81
|
+
* @param limit
|
|
82
|
+
* @param receive
|
|
83
|
+
* @param ended
|
|
84
|
+
* @param oversized
|
|
85
|
+
*/
|
|
86
|
+
function readMessages(input, framing, limit, receive, ended, oversized) {
|
|
87
|
+
let buffer = Buffer.alloc(0);
|
|
88
|
+
//The bytes of an oversized message still to skip (content-length), or its line being skipped (newline)
|
|
89
|
+
let skipping = 0;
|
|
90
|
+
let skippingLine = false;
|
|
91
|
+
const onData = (chunk) => {
|
|
92
|
+
buffer = Buffer.concat([buffer, typeof chunk === 'string' ? Buffer.from(chunk) : chunk]);
|
|
93
|
+
for (;;) {
|
|
94
|
+
if (skipping) {
|
|
95
|
+
const skipped = Math.min(skipping, buffer.length);
|
|
96
|
+
buffer = buffer.subarray(skipped);
|
|
97
|
+
skipping -= skipped;
|
|
98
|
+
if (skipping)
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
101
|
+
if (framing === 'newline') {
|
|
102
|
+
const end = buffer.indexOf(0x0a);
|
|
103
|
+
if (end < 0) {
|
|
104
|
+
//A line growing over the limit: skipped up to its end
|
|
105
|
+
if (buffer.length > limit) {
|
|
106
|
+
buffer = Buffer.alloc(0);
|
|
107
|
+
if (!skippingLine)
|
|
108
|
+
oversized();
|
|
109
|
+
skippingLine = true;
|
|
110
|
+
}
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
const tooLarge = skippingLine || end > limit;
|
|
114
|
+
const line = tooLarge ? '' : buffer.subarray(0, end).toString('utf8').trim();
|
|
115
|
+
buffer = buffer.subarray(end + 1);
|
|
116
|
+
if (tooLarge && !skippingLine)
|
|
117
|
+
oversized();
|
|
118
|
+
skippingLine = false;
|
|
119
|
+
if (line)
|
|
120
|
+
receive(line);
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
const headerEnd = buffer.indexOf('\r\n\r\n');
|
|
124
|
+
if (headerEnd < 0) {
|
|
125
|
+
//No header of a message: what is not one is dropped, its end kept (a part of the next header)
|
|
126
|
+
if (buffer.length > limit)
|
|
127
|
+
buffer = buffer.subarray(buffer.length - 3);
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
const length = Number(buffer.subarray(0, headerEnd).toString('ascii').match(/content-length:\s*(\d+)/i)?.[1] ?? NaN);
|
|
131
|
+
if (!Number.isFinite(length)) {
|
|
132
|
+
//Not a header of a message: skipped
|
|
133
|
+
buffer = buffer.subarray(headerEnd + 4);
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
if (length > limit) {
|
|
137
|
+
//Its content skipped as it arrives
|
|
138
|
+
buffer = buffer.subarray(headerEnd + 4);
|
|
139
|
+
skipping = length;
|
|
140
|
+
oversized();
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
if (buffer.length < headerEnd + 4 + length)
|
|
144
|
+
break;
|
|
145
|
+
receive(buffer.subarray(headerEnd + 4, headerEnd + 4 + length).toString('utf8'));
|
|
146
|
+
buffer = buffer.subarray(headerEnd + 4 + length);
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
input.on('data', onData);
|
|
150
|
+
input.once('end', ended);
|
|
151
|
+
return () => {
|
|
152
|
+
input.off('data', onData);
|
|
153
|
+
input.off('end', ended);
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Create a service adapter of an entrypoint served over JSON-RPC 2.0, on HTTP, WebSocket or stdio. Only the WebSocket
|
|
158
|
+
* transport needs an optional peer dependency, `ws`; without it, the entrypoint fails to start.
|
|
159
|
+
*
|
|
160
|
+
* A request's method and named params become the service action's pattern and input: by default
|
|
161
|
+
* `{"method": "user.get", "params": {"id": 1}}` is dispatched as `{method: 'user.get', id: 1}` (see
|
|
162
|
+
* {@link JSONRPCMappingOptions} for the other mappings). The batches are answered with an array of responses, the
|
|
163
|
+
* notifications (no `id`) run without a response. The action's result is the response's `result` (`null` for none);
|
|
164
|
+
* its error becomes a JSON-RPC error (see {@link JSONRPCErrorCode}): `METHOD_NOT_FOUND`, `INVALID_PARAMS` for a failed
|
|
165
|
+
* validation, otherwise `SERVER_ERROR` with the whole error object as its `data`.
|
|
166
|
+
*
|
|
167
|
+
* Over HTTP, a message is the body of a `POST` to the path, answered with 200 and the JSON response (204 when it held
|
|
168
|
+
* only notifications); any other method or path is answered with 404, and the CORS headers allow any origin. Over
|
|
169
|
+
* WebSocket and stdio, the events pushed by `Entrypoint.notify` and `Entrypoint.broadcast` are sent as notifications,
|
|
170
|
+
* `{"jsonrpc": "2.0", "method": event, "params": args}`. The client id carried by `ServiceContext.clientId` is the `id`
|
|
171
|
+
* header or `id` query parameter of the HTTP request or of the WebSocket connection (at most 200 characters; a random
|
|
172
|
+
* one for a WebSocket connection without it), and `'stdio'` on stdio.
|
|
173
|
+
*
|
|
174
|
+
* When an HTTP client disconnects before its response, the action's abort signal fires. When the entrypoint stops,
|
|
175
|
+
* stdio stops reading, the new requests are answered with `STOPPING`, and once the requests in progress are answered
|
|
176
|
+
* the WebSocket connections are closed (code 1001) and the server shuts down.
|
|
177
|
+
* @param options The adapter options; by default it serves HTTP on port 3000 of all the interfaces, on the path `/`.
|
|
178
|
+
* @returns The adapter, to give to the `service` option of `buildEntrypoints`.
|
|
179
|
+
* @example
|
|
180
|
+
* ```typescript
|
|
181
|
+
* import {Application} from 'lakutata'
|
|
182
|
+
* import {buildEntrypoints, Controller} from 'lakutata/com/entrypoint'
|
|
183
|
+
* import {ServiceAction} from 'lakutata/decorator/ctrl'
|
|
184
|
+
* import {jsonRPCServiceEntrypoint} from 'lakutata/adapter/jsonrpc'
|
|
185
|
+
* import WebSocket from 'ws'
|
|
186
|
+
*
|
|
187
|
+
* class UserController extends Controller {
|
|
188
|
+
* @ServiceAction({method: 'user.get'})
|
|
189
|
+
* public async get(input: {id: number}): Promise<{id: number, name: string}> {
|
|
190
|
+
* return {id: input.id, name: 'Ada'}
|
|
191
|
+
* }
|
|
192
|
+
* }
|
|
193
|
+
*
|
|
194
|
+
* Application.run({
|
|
195
|
+
* id: 'user.service',
|
|
196
|
+
* name: 'Users',
|
|
197
|
+
* components: {
|
|
198
|
+
* entrypoint: buildEntrypoints({
|
|
199
|
+
* controllers: [UserController],
|
|
200
|
+
* service: [
|
|
201
|
+
* //POST http://localhost:3000/rpc
|
|
202
|
+
* jsonRPCServiceEntrypoint({name: 'rpc-http', port: 3000, path: '/rpc'}),
|
|
203
|
+
* //ws://localhost:3001/rpc, with the events pushed
|
|
204
|
+
* jsonRPCServiceEntrypoint({name: 'rpc-ws', transport: 'websocket', port: 3001, path: '/rpc'})
|
|
205
|
+
* ]
|
|
206
|
+
* })
|
|
207
|
+
* }
|
|
208
|
+
* })
|
|
209
|
+
*
|
|
210
|
+
* //An HTTP client: {"jsonrpc": "2.0", "id": 1, "result": {"id": 1, "name": "Ada"}}
|
|
211
|
+
* const response: Response = await fetch('http://localhost:3000/rpc', {
|
|
212
|
+
* method: 'POST',
|
|
213
|
+
* headers: {'Content-Type': 'application/json'},
|
|
214
|
+
* body: JSON.stringify({jsonrpc: '2.0', id: 1, method: 'user.get', params: {id: 1}})
|
|
215
|
+
* })
|
|
216
|
+
* console.log(await response.json())
|
|
217
|
+
*
|
|
218
|
+
* //A WebSocket client, identified as client-1: the responses and the notifications arrive as messages
|
|
219
|
+
* const socket: WebSocket = new WebSocket('ws://localhost:3001/rpc?id=client-1')
|
|
220
|
+
* socket.on('open', (): void => socket.send(JSON.stringify({jsonrpc: '2.0', id: 2, method: 'user.get', params: {id: 2}})))
|
|
221
|
+
* socket.on('message', (data: WebSocket.RawData): void => console.log(JSON.parse(data.toString())))
|
|
222
|
+
* ```
|
|
223
|
+
*/
|
|
224
|
+
function jsonRPCServiceEntrypoint(options = {}) {
|
|
225
|
+
const transport = options.transport ?? 'http';
|
|
226
|
+
const protocol = new JSONRPCProtocol_js_1.JSONRPCProtocol(options);
|
|
227
|
+
const limit = options.limit ?? 10 * 1024 * 1024;
|
|
228
|
+
const path = (options.path ?? '/').replace(/(.)\/+$/, '$1');
|
|
229
|
+
let stopping = false;
|
|
230
|
+
let server;
|
|
231
|
+
let webSocketServer;
|
|
232
|
+
let stopReading;
|
|
233
|
+
let heartbeat;
|
|
234
|
+
//The connections of each client (WebSocket), the output of stdio
|
|
235
|
+
const clients = new Map();
|
|
236
|
+
const inProgress = new Set();
|
|
237
|
+
const addClient = (clientId, send) => {
|
|
238
|
+
if (!clients.has(clientId))
|
|
239
|
+
clients.set(clientId, new Set());
|
|
240
|
+
clients.get(clientId).add(send);
|
|
241
|
+
return () => {
|
|
242
|
+
clients.get(clientId)?.delete(send);
|
|
243
|
+
if (!clients.get(clientId)?.size)
|
|
244
|
+
clients.delete(clientId);
|
|
245
|
+
};
|
|
246
|
+
};
|
|
247
|
+
/**
|
|
248
|
+
* Answer a message
|
|
249
|
+
* @param runtime
|
|
250
|
+
* @param message
|
|
251
|
+
* @param dispatch
|
|
252
|
+
* @param send
|
|
253
|
+
*/
|
|
254
|
+
const answer = (runtime, message, dispatch, send) => {
|
|
255
|
+
const handled = protocol.handle(message, { ...dispatch, runtime: runtime, transport: transport, stopping: () => stopping })
|
|
256
|
+
.then((response) => {
|
|
257
|
+
if (response)
|
|
258
|
+
send(JSON.stringify(response));
|
|
259
|
+
})
|
|
260
|
+
.catch(() => undefined);
|
|
261
|
+
inProgress.add(handled);
|
|
262
|
+
void handled.finally(() => inProgress.delete(handled));
|
|
263
|
+
return handled;
|
|
264
|
+
};
|
|
265
|
+
const listen = async (target) => {
|
|
266
|
+
await new Promise((resolve, reject) => {
|
|
267
|
+
target.once('error', reject).listen(options.port ?? 3000, options.host, () => {
|
|
268
|
+
target.off('error', reject);
|
|
269
|
+
resolve();
|
|
270
|
+
});
|
|
271
|
+
});
|
|
272
|
+
await options.listening?.(target);
|
|
273
|
+
};
|
|
274
|
+
return {
|
|
275
|
+
channel: 'service',
|
|
276
|
+
definition: BuiltinChannels_js_1.ServiceChannel,
|
|
277
|
+
name: options.name,
|
|
278
|
+
middlewares: options.middlewares,
|
|
279
|
+
start: async (runtime) => {
|
|
280
|
+
if (transport === 'stdio') {
|
|
281
|
+
const output = options.output ?? process.stdout;
|
|
282
|
+
const write = (message) => output.write(options.framing === 'content-length' ? `Content-Length: ${Buffer.byteLength(message)}\r\n\r\n${message}` : `${message}\n`);
|
|
283
|
+
addClient('stdio', write);
|
|
284
|
+
const ended = () => {
|
|
285
|
+
const mode = options.end ?? 'application';
|
|
286
|
+
//The requests in progress answered first
|
|
287
|
+
void Promise.allSettled([...inProgress]).then(async () => {
|
|
288
|
+
if (typeof mode === 'function')
|
|
289
|
+
return await mode();
|
|
290
|
+
if (mode === 'application')
|
|
291
|
+
(0, ApplicationOf_js_1.applicationOf)(runtime.module)?.exit(0);
|
|
292
|
+
});
|
|
293
|
+
};
|
|
294
|
+
//A message over the limit: an Invalid Request error, without id (it is not read)
|
|
295
|
+
const oversized = () => write(JSON.stringify({ jsonrpc: '2.0', id: null, error: { code: JSONRPCProtocol_js_1.JSONRPCErrorCode.INVALID_REQUEST, message: `The message is larger than ${limit} bytes` } }));
|
|
296
|
+
stopReading = readMessages(options.input ?? process.stdin, options.framing ?? 'newline', limit, (message) => void answer(runtime, message, { clientId: 'stdio' }, write), ended, oversized);
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
if (transport === 'http') {
|
|
300
|
+
server = (0, node_http_1.createServer)((request, response) => {
|
|
301
|
+
const url = new URL(request.url ?? '/', 'http://localhost');
|
|
302
|
+
if (request.method === 'OPTIONS')
|
|
303
|
+
return void response.writeHead(204, CORS_HEADERS).end();
|
|
304
|
+
if (request.method !== 'POST' || url.pathname !== path) {
|
|
305
|
+
return void response.writeHead(404, { ...CORS_HEADERS, 'Content-Type': 'application/json' }).end(JSON.stringify({ jsonrpc: '2.0', id: null, error: { code: -32600, message: `POST ${path} receives the requests of JSON-RPC 2.0` } }));
|
|
306
|
+
}
|
|
307
|
+
const aborted = new AbortController();
|
|
308
|
+
response.once('close', () => {
|
|
309
|
+
if (!response.writableFinished)
|
|
310
|
+
aborted.abort();
|
|
311
|
+
});
|
|
312
|
+
readBody(request, limit).then((body) => {
|
|
313
|
+
void answer(runtime, body, { clientId: clientIdOf(request), extra: { request: request }, signal: aborted.signal }, (message) => {
|
|
314
|
+
response.writeHead(200, { ...CORS_HEADERS, 'Content-Type': 'application/json; charset=utf-8' }).end(message);
|
|
315
|
+
}).then(() => {
|
|
316
|
+
//Only notifications: no content
|
|
317
|
+
if (!response.headersSent)
|
|
318
|
+
response.writeHead(204, CORS_HEADERS).end();
|
|
319
|
+
});
|
|
320
|
+
}, (error) => {
|
|
321
|
+
response.writeHead(error.status ?? 400, { ...CORS_HEADERS, 'Content-Type': 'application/json' }).end(JSON.stringify({ jsonrpc: '2.0', id: null, error: { code: -32600, message: error.message } }));
|
|
322
|
+
});
|
|
323
|
+
});
|
|
324
|
+
return await listen(server);
|
|
325
|
+
}
|
|
326
|
+
//WebSocket: the server of ws (an optional dependency)
|
|
327
|
+
let ws;
|
|
328
|
+
try {
|
|
329
|
+
ws = await Promise.resolve().then(() => __importStar(require('ws')));
|
|
330
|
+
}
|
|
331
|
+
catch {
|
|
332
|
+
throw new Error('The WebSocket transport of jsonRPCServiceEntrypoint needs the package ws (npm install ws)');
|
|
333
|
+
}
|
|
334
|
+
server = (0, node_http_1.createServer)((_request, response) => void response.writeHead(426, { 'Content-Type': 'text/plain' }).end('A WebSocket connection is expected'));
|
|
335
|
+
webSocketServer = new ws.WebSocketServer({ server: server, path: path, maxPayload: limit });
|
|
336
|
+
//Whether each connection answered the last ping
|
|
337
|
+
const alive = new WeakMap();
|
|
338
|
+
webSocketServer.on('connection', (socket, request) => {
|
|
339
|
+
const clientId = clientIdOf(request) ?? (0, node_crypto_1.randomUUID)();
|
|
340
|
+
const send = (message) => {
|
|
341
|
+
if (socket.readyState === 1)
|
|
342
|
+
socket.send(message);
|
|
343
|
+
};
|
|
344
|
+
const remove = addClient(clientId, send);
|
|
345
|
+
socket.on('message', (data, isBinary) => {
|
|
346
|
+
if (isBinary)
|
|
347
|
+
return;
|
|
348
|
+
void answer(runtime, Buffer.isBuffer(data) ? data.toString('utf8') : Array.isArray(data) ? Buffer.concat(data).toString('utf8') : Buffer.from(data).toString('utf8'), { clientId: clientId, extra: { socket: socket, request: request } }, send);
|
|
349
|
+
});
|
|
350
|
+
socket.on('close', remove);
|
|
351
|
+
socket.on('error', () => undefined);
|
|
352
|
+
socket.on('pong', () => alive.set(socket, true));
|
|
353
|
+
alive.set(socket, true);
|
|
354
|
+
});
|
|
355
|
+
//The connections which do not answer the pings closed (the ones a proxy dropped)
|
|
356
|
+
const interval = options.heartbeat ?? 30000;
|
|
357
|
+
if (interval > 0) {
|
|
358
|
+
heartbeat = setInterval(() => webSocketServer?.clients.forEach((socket) => {
|
|
359
|
+
if (!alive.get(socket))
|
|
360
|
+
return socket.terminate();
|
|
361
|
+
alive.set(socket, false);
|
|
362
|
+
socket.ping();
|
|
363
|
+
}), interval);
|
|
364
|
+
heartbeat.unref();
|
|
365
|
+
}
|
|
366
|
+
await listen(server);
|
|
367
|
+
},
|
|
368
|
+
stop: () => {
|
|
369
|
+
//The new requests are refused, the requests in progress end
|
|
370
|
+
stopping = true;
|
|
371
|
+
stopReading?.();
|
|
372
|
+
},
|
|
373
|
+
close: async () => {
|
|
374
|
+
clearInterval(heartbeat);
|
|
375
|
+
await Promise.allSettled([...inProgress]);
|
|
376
|
+
clients.clear();
|
|
377
|
+
if (webSocketServer) {
|
|
378
|
+
webSocketServer.clients.forEach((socket) => socket.close(1001, 'The service stops'));
|
|
379
|
+
await new Promise((resolve) => webSocketServer.close(() => resolve()));
|
|
380
|
+
}
|
|
381
|
+
if (!server)
|
|
382
|
+
return;
|
|
383
|
+
const closing = new Promise((resolve) => void server.close(() => resolve()));
|
|
384
|
+
server.closeAllConnections();
|
|
385
|
+
await closing;
|
|
386
|
+
},
|
|
387
|
+
notify: (clientId, event, args) => {
|
|
388
|
+
const connections = clients.get(clientId);
|
|
389
|
+
connections?.forEach((send) => send(JSONRPCProtocol_js_1.JSONRPCProtocol.notification(event, args)));
|
|
390
|
+
return !!connections?.size;
|
|
391
|
+
},
|
|
392
|
+
broadcast: (event, args) => {
|
|
393
|
+
clients.forEach((connections) => connections.forEach((send) => send(JSONRPCProtocol_js_1.JSONRPCProtocol.notification(event, args))));
|
|
394
|
+
return clients.size;
|
|
395
|
+
}
|
|
396
|
+
};
|
|
397
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import type { ChannelActionInfo, EntrypointAdapter } from '../../channel/EntrypointAdapter.js';
|
|
2
|
+
import type { MiddlewareDefinition } from '../../lib/Middleware.js';
|
|
3
|
+
import { ScheduleContext } from '../../context/ScheduleContext.js';
|
|
4
|
+
/**
|
|
5
|
+
* The options of {@link scheduleEntrypoint}.
|
|
6
|
+
*/
|
|
7
|
+
export type ScheduleEntrypointOptions = {
|
|
8
|
+
/**
|
|
9
|
+
* The adapter name, to tell apart several schedule adapters of one entrypoint.
|
|
10
|
+
*/
|
|
11
|
+
name?: string;
|
|
12
|
+
/**
|
|
13
|
+
* The middlewares of this adapter's runs, run after the entrypoint's global middlewares.
|
|
14
|
+
*/
|
|
15
|
+
middlewares?: MiddlewareDefinition[];
|
|
16
|
+
/**
|
|
17
|
+
* Called when a run fails (the action, a middleware or the access control threw), with the error, the action and
|
|
18
|
+
* the run's context. A failed run does not stop the next ones.
|
|
19
|
+
* @default the error is written to the application's `log` component (`console.error` without one)
|
|
20
|
+
*/
|
|
21
|
+
onError?: (error: unknown, action: ChannelActionInfo, context: ScheduleContext) => void | Promise<void>;
|
|
22
|
+
/**
|
|
23
|
+
* Called when a run is skipped, with the action, the time the run was due and why: `'overlap'` when the action's
|
|
24
|
+
* previous run is still in progress (an action without `overlap: true`), `'exclusive'` when another instance of the
|
|
25
|
+
* application holds the run's lock (an `exclusive` action). An error it throws is written to the application's
|
|
26
|
+
* `log` component; the schedule goes on.
|
|
27
|
+
*/
|
|
28
|
+
onSkip?: (action: ChannelActionInfo, scheduledAt: Date, reason: 'overlap' | 'exclusive') => void;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Create the schedule adapter of an entrypoint: it runs the controller actions declared with `@Schedule`, which never
|
|
32
|
+
* run without it. It needs no optional dependency.
|
|
33
|
+
*
|
|
34
|
+
* The runs begin once the application has launched (all its objects, its bootstrap and the other adapters are ready).
|
|
35
|
+
* Each run is dispatched like a request: a new controller in its own scope, the middlewares and the access control, a
|
|
36
|
+
* {@link ScheduleContext} giving the schedule, the time the run was due and its number. An interval keeps its pace:
|
|
37
|
+
* the runs missed while the process was suspended are skipped, not caught up. An action whose previous run is still in
|
|
38
|
+
* progress skips its run unless it allows `overlap`.
|
|
39
|
+
*
|
|
40
|
+
* An `exclusive` action runs in one instance of the application at a time: each run first tries to acquire a lock
|
|
41
|
+
* named `schedule:<key>` (the `key` of its `exclusive` option, the action name by default) from the mutex component
|
|
42
|
+
* (the `Mutex` of `lakutata/com/mutex`, named `mutex` by default), and is skipped when another
|
|
43
|
+
* instance holds it; the lock is kept after the run for half of its period (30 seconds at most) so that the instances
|
|
44
|
+
* whose clocks are late skip it too. An exclusive action whose mutex component cannot be resolved never runs (the
|
|
45
|
+
* error is logged).
|
|
46
|
+
*
|
|
47
|
+
* When the entrypoint stops, no new run starts, the kept locks are released and the entrypoint waits for the runs in
|
|
48
|
+
* progress (aborting them after its `shutdownTimeout`).
|
|
49
|
+
* @param options The adapter options.
|
|
50
|
+
* @returns The adapter, to give to the `schedule` option of `buildEntrypoints`.
|
|
51
|
+
* @example
|
|
52
|
+
* ```typescript
|
|
53
|
+
* import {Application} from 'lakutata'
|
|
54
|
+
* import {buildEntrypoints, Controller, ScheduleContext, scheduleEntrypoint} from 'lakutata/com/entrypoint'
|
|
55
|
+
* import {Schedule} from 'lakutata/decorator/ctrl'
|
|
56
|
+
*
|
|
57
|
+
* class MaintenanceController extends Controller {
|
|
58
|
+
* //Every 5 minutes, and once the application launched
|
|
59
|
+
* @Schedule({every: '5m', immediate: true})
|
|
60
|
+
* public async purge(): Promise<void> {
|
|
61
|
+
* const context: ScheduleContext = this.context as ScheduleContext
|
|
62
|
+
* console.log(`Run ${context.run}, due at ${context.scheduledAt.toISOString()}`)
|
|
63
|
+
* }
|
|
64
|
+
*
|
|
65
|
+
* //Every day at 03:00 in Shanghai
|
|
66
|
+
* @Schedule({cron: '0 3 * * *', timezone: 'Asia/Shanghai'})
|
|
67
|
+
* public async report(): Promise<void> {
|
|
68
|
+
* }
|
|
69
|
+
* }
|
|
70
|
+
*
|
|
71
|
+
* Application.run({
|
|
72
|
+
* id: 'worker.app',
|
|
73
|
+
* name: 'Worker',
|
|
74
|
+
* components: {
|
|
75
|
+
* entrypoint: buildEntrypoints({
|
|
76
|
+
* controllers: [MaintenanceController],
|
|
77
|
+
* schedule: scheduleEntrypoint({
|
|
78
|
+
* onError: (error, action): void => console.error(`${action.name} failed`, error),
|
|
79
|
+
* onSkip: (action, scheduledAt, reason): void => console.warn(`${action.name} skipped (${reason})`)
|
|
80
|
+
* })
|
|
81
|
+
* })
|
|
82
|
+
* }
|
|
83
|
+
* })
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
export declare function scheduleEntrypoint(options?: ScheduleEntrypointOptions): EntrypointAdapter<ScheduleContext>;
|