@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,192 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { type Module } from '@lakutata/core';
|
|
3
|
+
import type { EntrypointAdapter } from '../../channel/EntrypointAdapter.js';
|
|
4
|
+
import type { MiddlewareDefinition } from '../../lib/Middleware.js';
|
|
5
|
+
import { CLIContext } from '../../context/CLIContext.js';
|
|
6
|
+
/**
|
|
7
|
+
* The JSON schema of a property of the input of an action
|
|
8
|
+
*/
|
|
9
|
+
export type PropertySchema = {
|
|
10
|
+
type?: string | string[];
|
|
11
|
+
enum?: unknown[];
|
|
12
|
+
items?: PropertySchema;
|
|
13
|
+
default?: unknown;
|
|
14
|
+
description?: string;
|
|
15
|
+
format?: string;
|
|
16
|
+
[key: string]: unknown;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* A text of the help or of the prompts of {@link commanderCLIEntrypoint}, given to its `translate` function.
|
|
20
|
+
*/
|
|
21
|
+
export type CLIText = {
|
|
22
|
+
/**
|
|
23
|
+
* The key identifying the text: `description` (the program), `commands.<command>.description`,
|
|
24
|
+
* `commands.<command>.options.<property>`, `commands.<command>.arguments.<name>` (a nested command's words are joined
|
|
25
|
+
* with dots: `package.exe`), the help titles and labels (`help.usage`, `help.options`, `help.commands`,
|
|
26
|
+
* `help.default`, `help.choices`…), the prompt messages (`prompt.json`).
|
|
27
|
+
*/
|
|
28
|
+
key: string;
|
|
29
|
+
/**
|
|
30
|
+
* The English text, with its `{name}` placeholders.
|
|
31
|
+
*/
|
|
32
|
+
text: string;
|
|
33
|
+
/**
|
|
34
|
+
* The values of the text's `{name}` placeholders, by name.
|
|
35
|
+
*/
|
|
36
|
+
params?: Record<string, string>;
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Translate a text of the help or of the prompts into the user's language: return the translated text, its `{name}`
|
|
40
|
+
* placeholders filled from `params`.
|
|
41
|
+
*/
|
|
42
|
+
export type CLITranslate = (text: CLIText) => string;
|
|
43
|
+
/**
|
|
44
|
+
* The options of {@link commanderCLIEntrypoint}.
|
|
45
|
+
*/
|
|
46
|
+
export type CommanderCLIEntrypointOptions = {
|
|
47
|
+
/**
|
|
48
|
+
* The adapter name, to tell apart several CLI adapters of one entrypoint.
|
|
49
|
+
*/
|
|
50
|
+
name?: string;
|
|
51
|
+
/**
|
|
52
|
+
* The program name shown in the help.
|
|
53
|
+
* @default the name of the script run, without its extension
|
|
54
|
+
*/
|
|
55
|
+
bin?: string;
|
|
56
|
+
/**
|
|
57
|
+
* The program description shown in the help.
|
|
58
|
+
*/
|
|
59
|
+
description?: string;
|
|
60
|
+
/**
|
|
61
|
+
* The descriptions of the command groups, by group name: the first words of the nested commands (`'package'` for
|
|
62
|
+
* the command `'package exe <file>'`), whose help (`tool package --help`) lists their commands.
|
|
63
|
+
*/
|
|
64
|
+
groups?: Record<string, string>;
|
|
65
|
+
/**
|
|
66
|
+
* The program version; adds the `-V, --version` option.
|
|
67
|
+
*/
|
|
68
|
+
version?: string;
|
|
69
|
+
/**
|
|
70
|
+
* The command-line arguments to parse, without the node executable and the script.
|
|
71
|
+
* @default process.argv.slice(2)
|
|
72
|
+
*/
|
|
73
|
+
argv?: string[];
|
|
74
|
+
/**
|
|
75
|
+
* Prompt for the missing required options (it needs the optional package `@inquirer/prompts`): `'auto'` when both
|
|
76
|
+
* stdin and stdout are terminals, `true` always, `false` never. While prompting is on, the required options are not
|
|
77
|
+
* enforced by the parser; without `@inquirer/prompts` installed, prompting is off (the parser requires them).
|
|
78
|
+
* @default 'auto'
|
|
79
|
+
*/
|
|
80
|
+
interactive?: boolean | 'auto';
|
|
81
|
+
/**
|
|
82
|
+
* The input stream of the prompts.
|
|
83
|
+
* @default process.stdin
|
|
84
|
+
*/
|
|
85
|
+
stdin?: NodeJS.ReadableStream;
|
|
86
|
+
/**
|
|
87
|
+
* The output stream of the results, the help and the prompts.
|
|
88
|
+
* @default process.stdout
|
|
89
|
+
*/
|
|
90
|
+
stdout?: NodeJS.WritableStream;
|
|
91
|
+
/**
|
|
92
|
+
* The output stream of the errors.
|
|
93
|
+
* @default process.stderr
|
|
94
|
+
*/
|
|
95
|
+
stderr?: NodeJS.WritableStream;
|
|
96
|
+
/**
|
|
97
|
+
* Turn an action's result into the text or bytes written to stdout; `undefined` writes nothing.
|
|
98
|
+
* @default a string as is (with a final newline), bytes as is, `null` and `undefined` as nothing, any other value as
|
|
99
|
+
* indented JSON (the bigints as strings)
|
|
100
|
+
*/
|
|
101
|
+
format?: (result: unknown) => string | Uint8Array | undefined;
|
|
102
|
+
/**
|
|
103
|
+
* What happens when no argument is given: `'help'` writes the help and ends with the code 1, `'ignore'` runs no
|
|
104
|
+
* command and leaves the application running (an application also serving other channels).
|
|
105
|
+
* @default 'help'
|
|
106
|
+
*/
|
|
107
|
+
noCommand?: 'help' | 'ignore';
|
|
108
|
+
/**
|
|
109
|
+
* What happens once the command ended, with its exit code (0 on success, 1 on failure, the parser's code for a
|
|
110
|
+
* usage error): `'application'` exits the application with the code, `'process'` only sets `process.exitCode`,
|
|
111
|
+
* `'none'` does nothing, or a function receiving the code.
|
|
112
|
+
* @default 'application'
|
|
113
|
+
*/
|
|
114
|
+
exit?: 'application' | 'process' | 'none' | ((code: number) => void | Promise<void>);
|
|
115
|
+
/**
|
|
116
|
+
* Customize the commander program (hooks, global options, additional commands) after the action commands are
|
|
117
|
+
* added and before the arguments are parsed.
|
|
118
|
+
*/
|
|
119
|
+
configure?: (program: Command) => void | Promise<void>;
|
|
120
|
+
/**
|
|
121
|
+
* The middlewares of this adapter's actions, run after the entrypoint's global middlewares.
|
|
122
|
+
*/
|
|
123
|
+
middlewares?: MiddlewareDefinition[];
|
|
124
|
+
/**
|
|
125
|
+
* Translate the texts of the help and of the prompts (the program, command, argument and option descriptions, the
|
|
126
|
+
* help titles) into the user's language: given the entrypoint's module when the arguments are parsed, it returns the
|
|
127
|
+
* translating function (`commanderTranslator` of `lakutata/com/i18n` returns the one of an i18n component). The
|
|
128
|
+
* command and option names are never translated.
|
|
129
|
+
* @default the English texts
|
|
130
|
+
*/
|
|
131
|
+
translate?: (module: Module) => CLITranslate | Promise<CLITranslate>;
|
|
132
|
+
};
|
|
133
|
+
/**
|
|
134
|
+
* Create the CLI adapter of an entrypoint, parsing the command-line arguments with commander: each CLI action
|
|
135
|
+
* (`@CLIAction`) becomes a command, and the properties of its input DTO become its options. It needs the optional peer
|
|
136
|
+
* dependency `commander` (and `@inquirer/prompts` for the interactive prompts).
|
|
137
|
+
*
|
|
138
|
+
* A property becomes a kebab-case option (`deviceId` → `--device-id <value>`), parsed by its type: a number, `true` or
|
|
139
|
+
* `false`, a JSON object, an array (`--tags <values...>`), a boolean as a flag (with a `--no-<name>` negation when it
|
|
140
|
+
* defaults to `true`); the enums, the defaults and the descriptions appear in the help. The command text may declare
|
|
141
|
+
* positional arguments, given to the properties of their names (`'copy <files...> [target]'`), and its leading words
|
|
142
|
+
* before the last one name its groups (`'package exe <file>'` is the command `exe` of the group `package`).
|
|
143
|
+
*
|
|
144
|
+
* The command runs once the application has launched (all its objects, its bootstrap and the other adapters are
|
|
145
|
+
* ready). Its result is written to stdout (see `format`; an `EventsResult` writes each event's data, a `FileResult`
|
|
146
|
+
* the file's bytes); a failure writes `error: <message>` to stderr and ends with the code 1. Then the application exits
|
|
147
|
+
* with the command's code (see `exit`). When the entrypoint stops first, a command not started yet does not run, and
|
|
148
|
+
* the prompts and the event streams end.
|
|
149
|
+
* @param options The adapter options; by default it parses `process.argv`, prompts in a terminal, and exits the
|
|
150
|
+
* application once the command ended.
|
|
151
|
+
* @returns The adapter, to give to the `cli` option of `buildEntrypoints`.
|
|
152
|
+
* @example
|
|
153
|
+
* ```typescript
|
|
154
|
+
* import {Application, DTO} from 'lakutata'
|
|
155
|
+
* import {buildEntrypoints, Controller} from 'lakutata/com/entrypoint'
|
|
156
|
+
* import {CLIAction} from 'lakutata/decorator/ctrl'
|
|
157
|
+
* import {Expect} from 'lakutata/decorator/dto'
|
|
158
|
+
* import {commanderCLIEntrypoint} from 'lakutata/adapter/commander'
|
|
159
|
+
*
|
|
160
|
+
* class GreetDTO extends DTO {
|
|
161
|
+
* @Expect(DTO.String().required().description('The name to greet'))
|
|
162
|
+
* public name!: string
|
|
163
|
+
*
|
|
164
|
+
* @Expect(DTO.Number().integer().optional().default(1).description('How many times'))
|
|
165
|
+
* public times?: number
|
|
166
|
+
*
|
|
167
|
+
* @Expect(DTO.Boolean().optional().default(false))
|
|
168
|
+
* public loud?: boolean
|
|
169
|
+
* }
|
|
170
|
+
*
|
|
171
|
+
* class GreetController extends Controller {
|
|
172
|
+
* //tool greet Ada --times 2 --loud
|
|
173
|
+
* @CLIAction('greet <name>', GreetDTO)
|
|
174
|
+
* public async greet(input: GreetDTO): Promise<string> {
|
|
175
|
+
* const text: string = `Hello, ${input.name}`
|
|
176
|
+
* return (input.loud ? text.toUpperCase() : text).repeat(input.times ?? 1)
|
|
177
|
+
* }
|
|
178
|
+
* }
|
|
179
|
+
*
|
|
180
|
+
* Application.run({
|
|
181
|
+
* id: 'tool.app',
|
|
182
|
+
* name: 'Tool',
|
|
183
|
+
* components: {
|
|
184
|
+
* entrypoint: buildEntrypoints({
|
|
185
|
+
* controllers: [GreetController],
|
|
186
|
+
* cli: commanderCLIEntrypoint({bin: 'tool', description: 'A greeting tool', version: '1.0.0'})
|
|
187
|
+
* })
|
|
188
|
+
* }
|
|
189
|
+
* })
|
|
190
|
+
* ```
|
|
191
|
+
*/
|
|
192
|
+
export declare function commanderCLIEntrypoint(options?: CommanderCLIEntrypointOptions): EntrypointAdapter<CLIContext>;
|
|
@@ -0,0 +1,439 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.commanderCLIEntrypoint = commanderCLIEntrypoint;
|
|
7
|
+
const commander_1 = require("commander");
|
|
8
|
+
const node_fs_1 = require("node:fs");
|
|
9
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
10
|
+
const ApplicationOf_js_1 = require("../../lib/ApplicationOf.js");
|
|
11
|
+
const CLIContext_js_1 = require("../../context/CLIContext.js");
|
|
12
|
+
const BuiltinChannels_js_1 = require("../../channel/BuiltinChannels.js");
|
|
13
|
+
const Result_js_1 = require("../../lib/Result.js");
|
|
14
|
+
const Prompt_js_1 = require("./Prompt.js");
|
|
15
|
+
const Width_js_1 = require("./Width.js");
|
|
16
|
+
/**
|
|
17
|
+
* The English texts, their arguments filled
|
|
18
|
+
* @param text
|
|
19
|
+
*/
|
|
20
|
+
function english(text) {
|
|
21
|
+
return text.text.replace(/\{(\w+)\}/g, (all, name) => text.params?.[name] ?? all);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* The keys of the titles of the help of commander
|
|
25
|
+
*/
|
|
26
|
+
const TITLES = {
|
|
27
|
+
'Usage:': 'help.usage',
|
|
28
|
+
'Arguments:': 'help.arguments',
|
|
29
|
+
'Options:': 'help.options',
|
|
30
|
+
'Commands:': 'help.commands',
|
|
31
|
+
'Global Options:': 'help.globalOptions'
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* The type of a property, without null
|
|
35
|
+
* @param schema
|
|
36
|
+
*/
|
|
37
|
+
function typeOf(schema) {
|
|
38
|
+
const types = [].concat(schema.type ?? []).filter((type) => type !== 'null');
|
|
39
|
+
if (types.length)
|
|
40
|
+
return types[0];
|
|
41
|
+
if (schema.enum?.length)
|
|
42
|
+
return typeof schema.enum[0];
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* The kebab case of a property name (deviceId → device-id)
|
|
47
|
+
* @param name
|
|
48
|
+
*/
|
|
49
|
+
function kebabCase(name) {
|
|
50
|
+
return name.replace(/([a-z0-9])([A-Z])/g, '$1-$2').replace(/_/g, '-').toLowerCase();
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Parse a value of an option by its schema
|
|
54
|
+
* @param schema
|
|
55
|
+
* @param value
|
|
56
|
+
*/
|
|
57
|
+
function parseValue(schema, value) {
|
|
58
|
+
let parsed;
|
|
59
|
+
switch (typeOf(schema)) {
|
|
60
|
+
case 'integer':
|
|
61
|
+
case 'number': {
|
|
62
|
+
parsed = Number(value);
|
|
63
|
+
if (value.trim() === '' || Number.isNaN(parsed))
|
|
64
|
+
throw new commander_1.InvalidArgumentError('Not a number.');
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
case 'boolean': {
|
|
68
|
+
if (!['true', 'false'].includes(value))
|
|
69
|
+
throw new commander_1.InvalidArgumentError('Not a boolean.');
|
|
70
|
+
parsed = value === 'true';
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
case 'object': {
|
|
74
|
+
try {
|
|
75
|
+
parsed = JSON.parse(value);
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
throw new commander_1.InvalidArgumentError('Not a JSON object.');
|
|
79
|
+
}
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
default:
|
|
83
|
+
parsed = value;
|
|
84
|
+
}
|
|
85
|
+
if (schema.enum && !schema.enum.includes(parsed))
|
|
86
|
+
throw new commander_1.InvalidArgumentError(`Allowed choices are ${schema.enum.map((choice) => JSON.stringify(choice)).join(', ')}.`);
|
|
87
|
+
return parsed;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* The option of a property
|
|
91
|
+
* @param property
|
|
92
|
+
* @param schema
|
|
93
|
+
* @param mandatory
|
|
94
|
+
* @param say the text of the help in the language of the user
|
|
95
|
+
* @param command the name of the command
|
|
96
|
+
*/
|
|
97
|
+
function propertyOption(property, schema, mandatory, say, command) {
|
|
98
|
+
const flag = `--${kebabCase(property)}`;
|
|
99
|
+
//A boolean or a value (DTO.Alternatives(DTO.Boolean(), …)): a flag taking an optional value
|
|
100
|
+
const alternatives = Array.isArray(schema.anyOf) ? schema.anyOf : [];
|
|
101
|
+
const valued = alternatives.some((alternative) => typeOf(alternative) === 'boolean')
|
|
102
|
+
? alternatives.find((alternative) => typeOf(alternative) !== 'boolean')
|
|
103
|
+
: undefined;
|
|
104
|
+
const hints = [];
|
|
105
|
+
const choices = schema.enum ?? schema.items?.enum ?? valued?.enum;
|
|
106
|
+
if (choices)
|
|
107
|
+
hints.push(say('help.choices', 'choices: {choices}', { choices: choices.map((choice) => JSON.stringify(choice)).join(', ') }));
|
|
108
|
+
if (schema.default !== undefined)
|
|
109
|
+
hints.push(say('help.default', 'default: {value}', { value: JSON.stringify(schema.default) }));
|
|
110
|
+
const text = schema.description ? say(`commands.${command}.options.${property}`, schema.description) : '';
|
|
111
|
+
//The hints after the description, " (default: 1)"
|
|
112
|
+
const description = hints.length ? `${text}${say('help.hints', ' ({hints})', { hints: hints.join(say('help.separator', ', ')) })}`.trim() : text;
|
|
113
|
+
//--flag gives true, --flag <value> the value
|
|
114
|
+
if (valued)
|
|
115
|
+
return [new commander_1.Option(`${flag} [value]`, description).argParser((value) => parseValue(valued, value))];
|
|
116
|
+
const type = typeOf(schema);
|
|
117
|
+
if (type === 'boolean') {
|
|
118
|
+
const options = [new commander_1.Option(flag, description)];
|
|
119
|
+
//A flag on by default is turned off by its negation
|
|
120
|
+
if (schema.default === true)
|
|
121
|
+
options.push(new commander_1.Option(`--no-${kebabCase(property)}`, say('help.negate', 'Turn off {flag}', { flag: flag })));
|
|
122
|
+
return options;
|
|
123
|
+
}
|
|
124
|
+
const option = type === 'array'
|
|
125
|
+
? new commander_1.Option(`${flag} <values...>`, description).argParser((value, previous) => [...(Array.isArray(previous) ? previous : []), parseValue(schema.items ?? {}, value)])
|
|
126
|
+
: new commander_1.Option(`${flag} <${type === 'object' ? 'json' : 'value'}>`, description).argParser((value) => parseValue(schema, value));
|
|
127
|
+
return [option.makeOptionMandatory(mandatory)];
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* The default format of a result
|
|
131
|
+
* @param result
|
|
132
|
+
*/
|
|
133
|
+
function defaultFormat(result) {
|
|
134
|
+
if (result === undefined || result === null)
|
|
135
|
+
return undefined;
|
|
136
|
+
if (typeof result === 'string')
|
|
137
|
+
return result.endsWith('\n') ? result : `${result}\n`;
|
|
138
|
+
if (result instanceof Uint8Array)
|
|
139
|
+
return result;
|
|
140
|
+
return `${JSON.stringify(result, (key, value) => typeof value === 'bigint' ? value.toString() : value, 2)}\n`;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* The message of an error
|
|
144
|
+
* @param error
|
|
145
|
+
*/
|
|
146
|
+
function errorMessage(error) {
|
|
147
|
+
if (error && typeof error === 'object') {
|
|
148
|
+
const { errMsg, message } = error;
|
|
149
|
+
if (typeof errMsg === 'string' && errMsg)
|
|
150
|
+
return errMsg;
|
|
151
|
+
if (typeof message === 'string' && message)
|
|
152
|
+
return message;
|
|
153
|
+
}
|
|
154
|
+
return String(error);
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Create the CLI adapter of an entrypoint, parsing the command-line arguments with commander: each CLI action
|
|
158
|
+
* (`@CLIAction`) becomes a command, and the properties of its input DTO become its options. It needs the optional peer
|
|
159
|
+
* dependency `commander` (and `@inquirer/prompts` for the interactive prompts).
|
|
160
|
+
*
|
|
161
|
+
* A property becomes a kebab-case option (`deviceId` → `--device-id <value>`), parsed by its type: a number, `true` or
|
|
162
|
+
* `false`, a JSON object, an array (`--tags <values...>`), a boolean as a flag (with a `--no-<name>` negation when it
|
|
163
|
+
* defaults to `true`); the enums, the defaults and the descriptions appear in the help. The command text may declare
|
|
164
|
+
* positional arguments, given to the properties of their names (`'copy <files...> [target]'`), and its leading words
|
|
165
|
+
* before the last one name its groups (`'package exe <file>'` is the command `exe` of the group `package`).
|
|
166
|
+
*
|
|
167
|
+
* The command runs once the application has launched (all its objects, its bootstrap and the other adapters are
|
|
168
|
+
* ready). Its result is written to stdout (see `format`; an `EventsResult` writes each event's data, a `FileResult`
|
|
169
|
+
* the file's bytes); a failure writes `error: <message>` to stderr and ends with the code 1. Then the application exits
|
|
170
|
+
* with the command's code (see `exit`). When the entrypoint stops first, a command not started yet does not run, and
|
|
171
|
+
* the prompts and the event streams end.
|
|
172
|
+
* @param options The adapter options; by default it parses `process.argv`, prompts in a terminal, and exits the
|
|
173
|
+
* application once the command ended.
|
|
174
|
+
* @returns The adapter, to give to the `cli` option of `buildEntrypoints`.
|
|
175
|
+
* @example
|
|
176
|
+
* ```typescript
|
|
177
|
+
* import {Application, DTO} from 'lakutata'
|
|
178
|
+
* import {buildEntrypoints, Controller} from 'lakutata/com/entrypoint'
|
|
179
|
+
* import {CLIAction} from 'lakutata/decorator/ctrl'
|
|
180
|
+
* import {Expect} from 'lakutata/decorator/dto'
|
|
181
|
+
* import {commanderCLIEntrypoint} from 'lakutata/adapter/commander'
|
|
182
|
+
*
|
|
183
|
+
* class GreetDTO extends DTO {
|
|
184
|
+
* @Expect(DTO.String().required().description('The name to greet'))
|
|
185
|
+
* public name!: string
|
|
186
|
+
*
|
|
187
|
+
* @Expect(DTO.Number().integer().optional().default(1).description('How many times'))
|
|
188
|
+
* public times?: number
|
|
189
|
+
*
|
|
190
|
+
* @Expect(DTO.Boolean().optional().default(false))
|
|
191
|
+
* public loud?: boolean
|
|
192
|
+
* }
|
|
193
|
+
*
|
|
194
|
+
* class GreetController extends Controller {
|
|
195
|
+
* //tool greet Ada --times 2 --loud
|
|
196
|
+
* @CLIAction('greet <name>', GreetDTO)
|
|
197
|
+
* public async greet(input: GreetDTO): Promise<string> {
|
|
198
|
+
* const text: string = `Hello, ${input.name}`
|
|
199
|
+
* return (input.loud ? text.toUpperCase() : text).repeat(input.times ?? 1)
|
|
200
|
+
* }
|
|
201
|
+
* }
|
|
202
|
+
*
|
|
203
|
+
* Application.run({
|
|
204
|
+
* id: 'tool.app',
|
|
205
|
+
* name: 'Tool',
|
|
206
|
+
* components: {
|
|
207
|
+
* entrypoint: buildEntrypoints({
|
|
208
|
+
* controllers: [GreetController],
|
|
209
|
+
* cli: commanderCLIEntrypoint({bin: 'tool', description: 'A greeting tool', version: '1.0.0'})
|
|
210
|
+
* })
|
|
211
|
+
* }
|
|
212
|
+
* })
|
|
213
|
+
* ```
|
|
214
|
+
*/
|
|
215
|
+
function commanderCLIEntrypoint(options = {}) {
|
|
216
|
+
const stdout = options.stdout ?? process.stdout;
|
|
217
|
+
const stderr = options.stderr ?? process.stderr;
|
|
218
|
+
const stdin = options.stdin ?? process.stdin;
|
|
219
|
+
const format = options.format ?? defaultFormat;
|
|
220
|
+
//Aborts the prompts and the event streams when the adapter stops
|
|
221
|
+
const stopController = new AbortController();
|
|
222
|
+
const write = (output) => {
|
|
223
|
+
if (output !== undefined && output.length)
|
|
224
|
+
stdout.write(output);
|
|
225
|
+
};
|
|
226
|
+
/**
|
|
227
|
+
* Write the result of an action
|
|
228
|
+
* @param result
|
|
229
|
+
*/
|
|
230
|
+
const output = async (result) => {
|
|
231
|
+
if (result instanceof Result_js_1.EventsResult) {
|
|
232
|
+
return await result.producer((data) => {
|
|
233
|
+
if (!stopController.signal.aborted)
|
|
234
|
+
write(format(data));
|
|
235
|
+
}, stopController.signal);
|
|
236
|
+
}
|
|
237
|
+
if (result instanceof Result_js_1.FileResult) {
|
|
238
|
+
const source = result.source;
|
|
239
|
+
if (Buffer.isBuffer(source))
|
|
240
|
+
return write(source);
|
|
241
|
+
const stream = typeof source === 'string' ? (0, node_fs_1.createReadStream)(node_path_1.default.resolve(source)) : source;
|
|
242
|
+
return await new Promise((resolve, reject) => {
|
|
243
|
+
stream.once('error', reject).once('end', resolve).pipe(stdout, { end: false });
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
write(format(result instanceof Result_js_1.StatusResult ? result.data : result));
|
|
247
|
+
};
|
|
248
|
+
/**
|
|
249
|
+
* Whether the missing options are prompted: the prompts installed (else the parser requires the options)
|
|
250
|
+
*/
|
|
251
|
+
const interactive = async () => {
|
|
252
|
+
if (options.interactive === false)
|
|
253
|
+
return false;
|
|
254
|
+
if (options.interactive !== true && !(stdin.isTTY && stdout.isTTY))
|
|
255
|
+
return false;
|
|
256
|
+
return !!(await (0, Prompt_js_1.loadPrompts)());
|
|
257
|
+
};
|
|
258
|
+
/**
|
|
259
|
+
* Run a command
|
|
260
|
+
* @param runtime
|
|
261
|
+
* @param action
|
|
262
|
+
* @param data
|
|
263
|
+
* @param prompting
|
|
264
|
+
* @param describe the description of a property in the language of the user
|
|
265
|
+
* @param say the text of the prompts in the language of the user
|
|
266
|
+
*/
|
|
267
|
+
const execute = async (runtime, action, data, prompting, describe, say) => {
|
|
268
|
+
try {
|
|
269
|
+
if (prompting)
|
|
270
|
+
await (0, Prompt_js_1.prompt)(action, data, { input: stdin, output: stdout, signal: stopController.signal }, describe, say);
|
|
271
|
+
const context = new CLIContext_js_1.CLIContext({ command: action.address.command, data: data });
|
|
272
|
+
await output(await runtime.dispatchTo(action, context));
|
|
273
|
+
return 0;
|
|
274
|
+
}
|
|
275
|
+
catch (error) {
|
|
276
|
+
stderr.write(`error: ${errorMessage(error)}\n`);
|
|
277
|
+
return 1;
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
/**
|
|
281
|
+
* Parse the arguments and run the command
|
|
282
|
+
* @param runtime
|
|
283
|
+
*/
|
|
284
|
+
const run = async (runtime) => {
|
|
285
|
+
const argv = options.argv ?? process.argv.slice(2);
|
|
286
|
+
if (!argv.length && options.noCommand === 'ignore')
|
|
287
|
+
return undefined;
|
|
288
|
+
const prompting = await interactive();
|
|
289
|
+
//The texts of the help and of the prompts in the language of the user
|
|
290
|
+
const translate = options.translate ? await options.translate(runtime.module) : english;
|
|
291
|
+
const say = (key, text, params) => translate({ key: key, text: text, params: params });
|
|
292
|
+
const program = new commander_1.Command(options.bin ?? node_path_1.default.basename(process.argv[1] ?? 'cli', node_path_1.default.extname(process.argv[1] ?? '')))
|
|
293
|
+
.exitOverride()
|
|
294
|
+
.configureOutput({
|
|
295
|
+
writeOut: (text) => stdout.write(text),
|
|
296
|
+
writeErr: (text) => stderr.write(text)
|
|
297
|
+
});
|
|
298
|
+
if (options.translate) {
|
|
299
|
+
//Inherited by the commands created next
|
|
300
|
+
program
|
|
301
|
+
.configureHelp({
|
|
302
|
+
styleTitle: (title) => TITLES[title] ? say(TITLES[title], title) : title,
|
|
303
|
+
//The widths of the wide characters (Chinese, Japanese, Korean), their lines wrapped between them
|
|
304
|
+
displayWidth: Width_js_1.displayWidth,
|
|
305
|
+
boxWrap: (text, width) => (0, Width_js_1.boxWrap)(text, width)
|
|
306
|
+
})
|
|
307
|
+
.helpOption('-h, --help', say('help.helpOption', 'display help for command'));
|
|
308
|
+
if (runtime.actions.length)
|
|
309
|
+
program.helpCommand('help [command]', say('help.helpCommand', 'display help for command'));
|
|
310
|
+
}
|
|
311
|
+
if (options.description)
|
|
312
|
+
program.description(say('description', options.description));
|
|
313
|
+
/**
|
|
314
|
+
* A group of commands, its help listing them
|
|
315
|
+
* @param parent
|
|
316
|
+
* @param group its name
|
|
317
|
+
* @param names the names of its groups and its own
|
|
318
|
+
*/
|
|
319
|
+
const commandGroup = (parent, group, names) => {
|
|
320
|
+
const created = parent.command(group);
|
|
321
|
+
const description = options.groups?.[names.join(' ')];
|
|
322
|
+
if (description)
|
|
323
|
+
created.description(say(`commands.${names.join('.')}.description`, description));
|
|
324
|
+
if (options.translate)
|
|
325
|
+
created.helpCommand('help [command]', say('help.helpCommand', 'display help for command'));
|
|
326
|
+
return created;
|
|
327
|
+
};
|
|
328
|
+
if (options.version)
|
|
329
|
+
program.version(options.version, '-V, --version', say('help.versionOption', 'output the version number'));
|
|
330
|
+
let code = 0;
|
|
331
|
+
for (const action of runtime.actions) {
|
|
332
|
+
const schema = action.jsonSchema;
|
|
333
|
+
const required = new Set(schema.required ?? []);
|
|
334
|
+
//The command may declare positional arguments ("run <script>", "copy <files...> [target]"), given to the properties of their names;
|
|
335
|
+
//its words before them but the last are its groups ("package exe <file>": the command exe of the group package)
|
|
336
|
+
const words = action.address.command.trim().split(/\s+/);
|
|
337
|
+
const first = words.findIndex((word) => /^[<[]/.test(word));
|
|
338
|
+
const names = first < 0 ? words : words.slice(0, first);
|
|
339
|
+
let parent = program;
|
|
340
|
+
names.slice(0, -1).forEach((group, index) => {
|
|
341
|
+
parent = parent.commands.find((existing) => existing.name() === group) ?? commandGroup(parent, group, names.slice(0, index + 1));
|
|
342
|
+
});
|
|
343
|
+
const command = parent.command([names.at(-1), ...words.slice(names.length)].join(' ')).allowExcessArguments(false);
|
|
344
|
+
//The key of its texts: the names of its groups and its own
|
|
345
|
+
const name = names.join('.');
|
|
346
|
+
command.description(action.description ? say(`commands.${name}.description`, action.description) : action.name);
|
|
347
|
+
const positional = command.registeredArguments.map((argument) => argument.name());
|
|
348
|
+
//The description of a property: the one of its argument or of its option
|
|
349
|
+
const describe = (property) => {
|
|
350
|
+
const text = schema.properties?.[property]?.description;
|
|
351
|
+
return text ? say(`commands.${name}.${positional.includes(property) ? 'arguments' : 'options'}.${property}`, text) : undefined;
|
|
352
|
+
};
|
|
353
|
+
for (const argument of command.registeredArguments) {
|
|
354
|
+
const propertySchema = schema.properties?.[argument.name()];
|
|
355
|
+
if (!propertySchema)
|
|
356
|
+
continue;
|
|
357
|
+
if (propertySchema.description)
|
|
358
|
+
argument.description = describe(argument.name());
|
|
359
|
+
if (argument.variadic) {
|
|
360
|
+
argument.argParser((value, previous) => [...(Array.isArray(previous) ? previous : []), parseValue(propertySchema.items ?? {}, value)]);
|
|
361
|
+
}
|
|
362
|
+
else {
|
|
363
|
+
argument.argParser((value) => parseValue(propertySchema, value));
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
//The properties by the attribute names of their options
|
|
367
|
+
const properties = new Map();
|
|
368
|
+
for (const [property, propertySchema] of Object.entries(schema.properties ?? {})) {
|
|
369
|
+
if (positional.includes(property))
|
|
370
|
+
continue;
|
|
371
|
+
const mandatory = !prompting && required.has(property) && propertySchema.default === undefined;
|
|
372
|
+
for (const option of propertyOption(property, propertySchema, mandatory, say, name)) {
|
|
373
|
+
command.addOption(option);
|
|
374
|
+
properties.set(option.attributeName(), property);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
command.action(async () => {
|
|
378
|
+
const data = {};
|
|
379
|
+
positional.forEach((name, index) => {
|
|
380
|
+
const value = command.processedArgs[index];
|
|
381
|
+
if (value !== undefined)
|
|
382
|
+
data[name] = value;
|
|
383
|
+
});
|
|
384
|
+
for (const [attribute, value] of Object.entries(command.opts())) {
|
|
385
|
+
if (value !== undefined && properties.has(attribute))
|
|
386
|
+
data[properties.get(attribute)] = value;
|
|
387
|
+
}
|
|
388
|
+
code = await execute(runtime, action, data, prompting, describe, say);
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
await options.configure?.(program);
|
|
392
|
+
try {
|
|
393
|
+
await program.parseAsync(argv, { from: 'user' });
|
|
394
|
+
}
|
|
395
|
+
catch (error) {
|
|
396
|
+
if (error instanceof commander_1.CommanderError)
|
|
397
|
+
return error.exitCode;
|
|
398
|
+
throw error;
|
|
399
|
+
}
|
|
400
|
+
return code;
|
|
401
|
+
};
|
|
402
|
+
/**
|
|
403
|
+
* End with the code of the command
|
|
404
|
+
* @param runtime
|
|
405
|
+
* @param code
|
|
406
|
+
*/
|
|
407
|
+
const exit = async (runtime, code) => {
|
|
408
|
+
const mode = options.exit ?? 'application';
|
|
409
|
+
if (typeof mode === 'function')
|
|
410
|
+
return await mode(code);
|
|
411
|
+
if (mode === 'none')
|
|
412
|
+
return;
|
|
413
|
+
const application = mode === 'application' ? (0, ApplicationOf_js_1.applicationOf)(runtime.module) : undefined;
|
|
414
|
+
if (application)
|
|
415
|
+
return application.exit(code);
|
|
416
|
+
process.exitCode = code;
|
|
417
|
+
};
|
|
418
|
+
return {
|
|
419
|
+
channel: 'cli',
|
|
420
|
+
definition: BuiltinChannels_js_1.CLIChannel,
|
|
421
|
+
name: options.name,
|
|
422
|
+
middlewares: options.middlewares,
|
|
423
|
+
start: (runtime) => {
|
|
424
|
+
//The command runs once the application launched: every object, the bootstrap and the other adapters are ready
|
|
425
|
+
runtime.ready
|
|
426
|
+
.then(() => stopController.signal.aborted ? undefined : run(runtime))
|
|
427
|
+
.catch((error) => {
|
|
428
|
+
stderr.write(`error: ${errorMessage(error)}\n`);
|
|
429
|
+
return 1;
|
|
430
|
+
})
|
|
431
|
+
.then((code) => code === undefined || stopController.signal.aborted ? undefined : exit(runtime, code))
|
|
432
|
+
.catch((error) => stderr.write(`error: ${errorMessage(error)}\n`));
|
|
433
|
+
},
|
|
434
|
+
stop: () => {
|
|
435
|
+
//A command not started yet is not run, the prompts and the event streams are ended
|
|
436
|
+
stopController.abort();
|
|
437
|
+
}
|
|
438
|
+
};
|
|
439
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ChannelActionInfo } from '../../channel/EntrypointAdapter.js';
|
|
2
|
+
/**
|
|
3
|
+
* The streams of the prompts
|
|
4
|
+
*/
|
|
5
|
+
export type PromptStreams = {
|
|
6
|
+
input: NodeJS.ReadableStream;
|
|
7
|
+
output: NodeJS.WritableStream;
|
|
8
|
+
signal: AbortSignal;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Load the prompts
|
|
12
|
+
*/
|
|
13
|
+
export declare function loadPrompts(): Promise<any>;
|
|
14
|
+
/**
|
|
15
|
+
* Prompt for the required properties missing from the input of an action, when @inquirer/prompts is installed
|
|
16
|
+
* @param action
|
|
17
|
+
* @param data
|
|
18
|
+
* @param streams
|
|
19
|
+
* @param describe the description of a property in the language of the user
|
|
20
|
+
* @param say the text of the prompts in the language of the user
|
|
21
|
+
*/
|
|
22
|
+
export declare function prompt(action: ChannelActionInfo, data: Record<string, unknown>, streams: PromptStreams, describe?: (property: string) => string | undefined, say?: (key: string, text: string) => string): Promise<void>;
|