@c9up/ream 0.1.25 → 0.1.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -0
- package/dist/ConfigLoader.d.ts +46 -5
- package/dist/ConfigLoader.d.ts.map +1 -1
- package/dist/ConfigLoader.js +60 -9
- package/dist/ConfigLoader.js.map +1 -1
- package/dist/HttpKernel.d.ts.map +1 -1
- package/dist/HttpKernel.js +46 -6
- package/dist/HttpKernel.js.map +1 -1
- package/dist/Ignitor.d.ts +115 -7
- package/dist/Ignitor.d.ts.map +1 -1
- package/dist/Ignitor.js +254 -40
- package/dist/Ignitor.js.map +1 -1
- package/dist/console/BaseCommand.d.ts +217 -0
- package/dist/console/BaseCommand.d.ts.map +1 -0
- package/dist/console/BaseCommand.js +340 -0
- package/dist/console/BaseCommand.js.map +1 -0
- package/dist/console/Console.d.ts +86 -0
- package/dist/console/Console.d.ts.map +1 -0
- package/dist/console/Console.js +134 -0
- package/dist/console/Console.js.map +1 -0
- package/dist/console/ExceptionHandler.d.ts +28 -0
- package/dist/console/ExceptionHandler.d.ts.map +1 -0
- package/dist/console/ExceptionHandler.js +76 -0
- package/dist/console/ExceptionHandler.js.map +1 -0
- package/dist/console/HelpCommand.d.ts +16 -0
- package/dist/console/HelpCommand.d.ts.map +1 -0
- package/dist/console/HelpCommand.js +40 -0
- package/dist/console/HelpCommand.js.map +1 -0
- package/dist/console/IndexGenerator.d.ts +24 -0
- package/dist/console/IndexGenerator.d.ts.map +1 -0
- package/dist/console/IndexGenerator.js +65 -0
- package/dist/console/IndexGenerator.js.map +1 -0
- package/dist/console/Kernel.d.ts +298 -0
- package/dist/console/Kernel.d.ts.map +1 -0
- package/dist/console/Kernel.js +1120 -0
- package/dist/console/Kernel.js.map +1 -0
- package/dist/console/ListCommand.d.ts +18 -0
- package/dist/console/ListCommand.d.ts.map +1 -0
- package/dist/console/ListCommand.js +60 -0
- package/dist/console/ListCommand.js.map +1 -0
- package/dist/console/assertions.d.ts +20 -0
- package/dist/console/assertions.d.ts.map +1 -0
- package/dist/console/assertions.js +84 -0
- package/dist/console/assertions.js.map +1 -0
- package/dist/console/cliui.d.ts +248 -0
- package/dist/console/cliui.d.ts.map +1 -0
- package/dist/console/cliui.js +587 -0
- package/dist/console/cliui.js.map +1 -0
- package/dist/console/decorators.d.ts +90 -0
- package/dist/console/decorators.d.ts.map +1 -0
- package/dist/console/decorators.js +142 -0
- package/dist/console/decorators.js.map +1 -0
- package/dist/console/index.d.ts +32 -0
- package/dist/console/index.d.ts.map +1 -0
- package/dist/console/index.js +24 -0
- package/dist/console/index.js.map +1 -0
- package/dist/console/loaders.d.ts +52 -0
- package/dist/console/loaders.d.ts.map +1 -0
- package/dist/console/loaders.js +131 -0
- package/dist/console/loaders.js.map +1 -0
- package/dist/console/parser.d.ts +86 -0
- package/dist/console/parser.d.ts.map +1 -0
- package/dist/console/parser.js +440 -0
- package/dist/console/parser.js.map +1 -0
- package/dist/console/prompts.d.ts +124 -0
- package/dist/console/prompts.d.ts.map +1 -0
- package/dist/console/prompts.js +356 -0
- package/dist/console/prompts.js.map +1 -0
- package/dist/console/tracing.d.ts +17 -0
- package/dist/console/tracing.d.ts.map +1 -0
- package/dist/console/tracing.js +11 -0
- package/dist/console/tracing.js.map +1 -0
- package/dist/console/types.d.ts +255 -0
- package/dist/console/types.d.ts.map +1 -0
- package/dist/console/types.js +25 -0
- package/dist/console/types.js.map +1 -0
- package/dist/console/ui.d.ts +20 -0
- package/dist/console/ui.d.ts.map +1 -0
- package/dist/console/ui.js +31 -0
- package/dist/console/ui.js.map +1 -0
- package/dist/console/utils.d.ts +27 -0
- package/dist/console/utils.d.ts.map +1 -0
- package/dist/console/utils.js +56 -0
- package/dist/console/utils.js.map +1 -0
- package/dist/container/Container.d.ts +23 -3
- package/dist/container/Container.d.ts.map +1 -1
- package/dist/container/Container.js +177 -70
- package/dist/container/Container.js.map +1 -1
- package/dist/container/types.d.ts +14 -2
- package/dist/container/types.d.ts.map +1 -1
- package/dist/decorators/Service.d.ts +7 -0
- package/dist/decorators/Service.d.ts.map +1 -1
- package/dist/decorators/Service.js +23 -3
- package/dist/decorators/Service.js.map +1 -1
- package/dist/env/Env.d.ts +29 -4
- package/dist/env/Env.d.ts.map +1 -1
- package/dist/env/Env.js +27 -4
- package/dist/env/Env.js.map +1 -1
- package/dist/env/Secret.d.ts +11 -0
- package/dist/env/Secret.d.ts.map +1 -0
- package/dist/env/Secret.js +36 -0
- package/dist/env/Secret.js.map +1 -0
- package/dist/env/interpolate.d.ts +26 -0
- package/dist/env/interpolate.d.ts.map +1 -0
- package/dist/env/interpolate.js +48 -0
- package/dist/env/interpolate.js.map +1 -0
- package/dist/env/loadEnvFiles.d.ts.map +1 -1
- package/dist/env/loadEnvFiles.js +14 -4
- package/dist/env/loadEnvFiles.js.map +1 -1
- package/dist/env/schema.d.ts +23 -6
- package/dist/env/schema.d.ts.map +1 -1
- package/dist/env/schema.js +67 -33
- package/dist/env/schema.js.map +1 -1
- package/dist/errors/ReamError.d.ts +25 -0
- package/dist/errors/ReamError.d.ts.map +1 -1
- package/dist/errors/ReamError.js +5 -0
- package/dist/errors/ReamError.js.map +1 -1
- package/dist/errors/prettyPrintError.d.ts +9 -0
- package/dist/errors/prettyPrintError.d.ts.map +1 -0
- package/dist/errors/prettyPrintError.js +22 -0
- package/dist/errors/prettyPrintError.js.map +1 -0
- package/dist/events/Emitter.d.ts +1 -1
- package/dist/events/Emitter.d.ts.map +1 -1
- package/dist/events/Emitter.js +1 -1
- package/dist/events/Emitter.js.map +1 -1
- package/dist/events/EventsProvider.d.ts +2 -2
- package/dist/events/EventsProvider.d.ts.map +1 -1
- package/dist/events/EventsProvider.js +3 -3
- package/dist/events/EventsProvider.js.map +1 -1
- package/dist/graphql/GraphQLEngine.d.ts +1 -1
- package/dist/graphql/GraphQLEngine.d.ts.map +1 -1
- package/dist/graphql/GraphQLEngine.js +2 -2
- package/dist/graphql/GraphQLEngine.js.map +1 -1
- package/dist/graphql/GraphQLProvider.d.ts.map +1 -1
- package/dist/graphql/GraphQLProvider.js +7 -3
- package/dist/graphql/GraphQLProvider.js.map +1 -1
- package/dist/http/Exception.d.ts +63 -1
- package/dist/http/Exception.d.ts.map +1 -1
- package/dist/http/Exception.js +185 -48
- package/dist/http/Exception.js.map +1 -1
- package/dist/http/HttpContext.d.ts +53 -7
- package/dist/http/HttpContext.d.ts.map +1 -1
- package/dist/http/HttpContext.js +56 -15
- package/dist/http/HttpContext.js.map +1 -1
- package/dist/http/RedirectBuilder.d.ts.map +1 -1
- package/dist/http/RedirectBuilder.js +4 -1
- package/dist/http/RedirectBuilder.js.map +1 -1
- package/dist/http/Request.d.ts +141 -10
- package/dist/http/Request.d.ts.map +1 -1
- package/dist/http/Request.js +244 -34
- package/dist/http/Request.js.map +1 -1
- package/dist/http/Response.d.ts +176 -9
- package/dist/http/Response.d.ts.map +1 -1
- package/dist/http/Response.js +404 -16
- package/dist/http/Response.js.map +1 -1
- package/dist/index.d.ts +19 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +20 -5
- package/dist/index.js.map +1 -1
- package/dist/middleware/Pipeline.d.ts +29 -8
- package/dist/middleware/Pipeline.d.ts.map +1 -1
- package/dist/middleware/Pipeline.js +40 -2
- package/dist/middleware/Pipeline.js.map +1 -1
- package/dist/openapi/OpenApiProvider.js +4 -4
- package/dist/openapi/OpenApiProvider.js.map +1 -1
- package/dist/router/Router.d.ts +223 -31
- package/dist/router/Router.d.ts.map +1 -1
- package/dist/router/Router.js +520 -102
- package/dist/router/Router.js.map +1 -1
- package/dist/rpc/RpcProvider.d.ts +1 -0
- package/dist/rpc/RpcProvider.d.ts.map +1 -1
- package/dist/rpc/RpcProvider.js +7 -3
- package/dist/rpc/RpcProvider.js.map +1 -1
- package/dist/rpc/RpcRouter.d.ts +2 -2
- package/dist/rpc/RpcRouter.d.ts.map +1 -1
- package/dist/rpc/RpcRouter.js +17 -5
- package/dist/rpc/RpcRouter.js.map +1 -1
- package/dist/scheduler/ScheduleProvider.d.ts.map +1 -1
- package/dist/scheduler/ScheduleProvider.js +7 -15
- package/dist/scheduler/ScheduleProvider.js.map +1 -1
- package/dist/server/Server.d.ts +17 -4
- package/dist/server/Server.d.ts.map +1 -1
- package/dist/server/Server.js +41 -7
- package/dist/server/Server.js.map +1 -1
- package/dist/services/app.d.ts +1 -1
- package/dist/services/app.js +1 -1
- package/dist/services/console.d.ts +21 -0
- package/dist/services/console.d.ts.map +1 -0
- package/dist/services/console.js +35 -0
- package/dist/services/console.js.map +1 -0
- package/dist/session/SessionMiddleware.js +3 -3
- package/dist/session/SessionMiddleware.js.map +1 -1
- package/dist/storage/StaticProvider.js +1 -1
- package/dist/storage/StaticProvider.js.map +1 -1
- package/dist/testing/ApiResponse.d.ts +218 -0
- package/dist/testing/ApiResponse.d.ts.map +1 -0
- package/dist/testing/ApiResponse.js +576 -0
- package/dist/testing/ApiResponse.js.map +1 -0
- package/dist/testing/RequestBuilder.d.ts +155 -35
- package/dist/testing/RequestBuilder.d.ts.map +1 -1
- package/dist/testing/RequestBuilder.js +455 -109
- package/dist/testing/RequestBuilder.js.map +1 -1
- package/dist/testing/TestClient.d.ts +53 -37
- package/dist/testing/TestClient.d.ts.map +1 -1
- package/dist/testing/TestClient.js +84 -52
- package/dist/testing/TestClient.js.map +1 -1
- package/dist/utils/Macroable.d.ts +30 -0
- package/dist/utils/Macroable.d.ts.map +1 -0
- package/dist/utils/Macroable.js +43 -0
- package/dist/utils/Macroable.js.map +1 -0
- package/dist/utils/inflect.d.ts +17 -0
- package/dist/utils/inflect.d.ts.map +1 -0
- package/dist/utils/inflect.js +32 -0
- package/dist/utils/inflect.js.map +1 -0
- package/dist/utils/objectPath.d.ts +57 -0
- package/dist/utils/objectPath.d.ts.map +1 -0
- package/dist/utils/objectPath.js +141 -0
- package/dist/utils/objectPath.js.map +1 -0
- package/events.darwin-arm64.node +0 -0
- package/events.darwin-x64.node +0 -0
- package/events.linux-arm64-gnu.node +0 -0
- package/events.linux-x64-gnu.node +0 -0
- package/events.win32-x64-msvc.node +0 -0
- package/index.darwin-arm64.node +0 -0
- package/index.darwin-x64.node +0 -0
- package/index.linux-arm64-gnu.node +0 -0
- package/index.linux-x64-gnu.node +0 -0
- package/index.win32-x64-msvc.node +0 -0
- package/package.json +20 -2
- package/scheduler.darwin-arm64.node +0 -0
- package/scheduler.darwin-x64.node +0 -0
- package/scheduler.linux-arm64-gnu.node +0 -0
- package/scheduler.linux-x64-gnu.node +0 -0
- package/scheduler.win32-x64-msvc.node +0 -0
- package/src/ConfigLoader.ts +72 -9
- package/src/HttpKernel.ts +53 -15
- package/src/Ignitor.ts +364 -45
- package/src/console/BaseCommand.ts +467 -0
- package/src/console/Console.ts +174 -0
- package/src/console/ExceptionHandler.ts +91 -0
- package/src/console/HelpCommand.ts +37 -0
- package/src/console/IndexGenerator.ts +79 -0
- package/src/console/Kernel.ts +1382 -0
- package/src/console/ListCommand.ts +55 -0
- package/src/console/assertions.ts +114 -0
- package/src/console/cliui.ts +756 -0
- package/src/console/decorators.ts +199 -0
- package/src/console/index.ts +67 -0
- package/src/console/loaders.ts +145 -0
- package/src/console/parser.ts +598 -0
- package/src/console/prompts.ts +548 -0
- package/src/console/tracing.ts +22 -0
- package/src/console/types.ts +280 -0
- package/src/console/ui.ts +37 -0
- package/src/console/utils.ts +69 -0
- package/src/container/Container.ts +198 -72
- package/src/container/types.ts +15 -2
- package/src/decorators/Service.ts +28 -3
- package/src/env/Env.ts +49 -5
- package/src/env/Secret.ts +41 -0
- package/src/env/interpolate.ts +54 -0
- package/src/env/loadEnvFiles.ts +12 -4
- package/src/env/schema.ts +109 -35
- package/src/errors/ReamError.ts +31 -0
- package/src/errors/prettyPrintError.ts +20 -0
- package/src/events/Emitter.ts +2 -2
- package/src/events/EventsProvider.ts +5 -5
- package/src/graphql/GraphQLEngine.ts +4 -4
- package/src/graphql/GraphQLProvider.ts +7 -3
- package/src/http/Exception.ts +214 -37
- package/src/http/HttpContext.ts +87 -18
- package/src/http/RedirectBuilder.ts +4 -1
- package/src/http/Request.ts +264 -34
- package/src/http/Response.ts +478 -27
- package/src/index.ts +41 -6
- package/src/middleware/Pipeline.ts +77 -6
- package/src/openapi/OpenApiProvider.ts +4 -4
- package/src/router/Router.ts +631 -113
- package/src/rpc/RpcProvider.ts +6 -2
- package/src/rpc/RpcRouter.ts +22 -7
- package/src/scheduler/ScheduleProvider.ts +7 -15
- package/src/server/Server.ts +49 -10
- package/src/services/app.ts +1 -1
- package/src/services/console.ts +42 -0
- package/src/session/SessionMiddleware.ts +4 -4
- package/src/storage/StaticProvider.ts +1 -1
- package/src/testing/ApiResponse.ts +691 -0
- package/src/testing/RequestBuilder.ts +577 -137
- package/src/testing/TestClient.ts +110 -77
- package/src/utils/Macroable.ts +54 -0
- package/src/utils/inflect.ts +29 -0
- package/src/utils/objectPath.ts +142 -0
- package/dist/console/CommandRunner.d.ts +0 -18
- package/dist/console/CommandRunner.d.ts.map +0 -1
- package/dist/console/CommandRunner.js +0 -65
- package/dist/console/CommandRunner.js.map +0 -1
- package/dist/decorators/Lazy.d.ts +0 -19
- package/dist/decorators/Lazy.d.ts.map +0 -1
- package/dist/decorators/Lazy.js +0 -53
- package/dist/decorators/Lazy.js.map +0 -1
- package/src/console/CommandRunner.ts +0 -82
- package/src/decorators/Lazy.ts +0 -57
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Console command contract — the STATIC shape the kernel dispatches against.
|
|
3
|
+
*
|
|
4
|
+
* Console parity: a command is a class carrying its own metadata as statics
|
|
5
|
+
* (`commandName`, `description`, `options`) plus the argument/flag metadata
|
|
6
|
+
* collected by the `@args` / `@flags` decorators. The kernel never requires the
|
|
7
|
+
* class to extend {@link BaseCommand}: ANY class exposing these statics is
|
|
8
|
+
* dispatchable.
|
|
9
|
+
*
|
|
10
|
+
* That is deliberate. Framework-agnostic packages (atlas and friends) must not
|
|
11
|
+
* import `@c9up/ream` — the same constraint that made the old `AtlasCommand`
|
|
12
|
+
* duck-type the `{ name, description, run }` object shape. Keeping the contract
|
|
13
|
+
* on statics lets those packages declare classes with typed args/flags and stay
|
|
14
|
+
* dependency-free.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/** Per-command behaviour switches. Mirrors Console's `CommandOptions`. */
|
|
18
|
+
export interface CommandOptions {
|
|
19
|
+
/**
|
|
20
|
+
* Boot the application (providers, DB, container) before `run()`.
|
|
21
|
+
*
|
|
22
|
+
* Defaults to `false`, as in Console: a scaffolding command has no business
|
|
23
|
+
* opening a database connection. Commands that resolve services from the
|
|
24
|
+
* container must opt in.
|
|
25
|
+
*/
|
|
26
|
+
startApp?: boolean
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Keep the process alive after `run()` resolves (long-running commands such
|
|
30
|
+
* as a queue worker). Defaults to `false` — the kernel tears the app down and
|
|
31
|
+
* lets the process exit.
|
|
32
|
+
*/
|
|
33
|
+
staysAlive?: boolean
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Accept flags the command did not declare instead of failing. Off by
|
|
37
|
+
* default so a typo (`--warm` for `--warn`) is reported, not swallowed.
|
|
38
|
+
*/
|
|
39
|
+
allowUnknownFlags?: boolean
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Metadata recorded by an `@args.*` decorator. */
|
|
43
|
+
export interface ArgumentMetaData {
|
|
44
|
+
type: 'string' | 'spread'
|
|
45
|
+
/** Class property the parsed value is assigned to. */
|
|
46
|
+
propertyName: string
|
|
47
|
+
/** Name shown in help output (defaults to the dash-cased property name). */
|
|
48
|
+
argumentName: string
|
|
49
|
+
description?: string
|
|
50
|
+
required: boolean
|
|
51
|
+
default?: string | string[]
|
|
52
|
+
/**
|
|
53
|
+
* Accept an empty value (`ream greet ""`). Rejected by default, as in Console: an
|
|
54
|
+
* empty positional is nearly always a shell variable that did not expand.
|
|
55
|
+
*/
|
|
56
|
+
allowEmptyValue?: boolean
|
|
57
|
+
/** Transforms/validates the raw value before it is assigned (Console `parse`). */
|
|
58
|
+
parse?: (value: string | string[]) => unknown
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** Metadata recorded by a `@flags.*` decorator. */
|
|
62
|
+
export interface FlagMetaData {
|
|
63
|
+
type: 'string' | 'boolean' | 'number' | 'array'
|
|
64
|
+
/** Class property the parsed value is assigned to. */
|
|
65
|
+
propertyName: string
|
|
66
|
+
/** Name used on the command line (defaults to the dash-cased property name). */
|
|
67
|
+
flagName: string
|
|
68
|
+
description?: string
|
|
69
|
+
/** Single-character shorthands, e.g. `['r']` for `-r`. */
|
|
70
|
+
alias: string[]
|
|
71
|
+
default?: string | string[] | number | boolean
|
|
72
|
+
required: boolean
|
|
73
|
+
/**
|
|
74
|
+
* Accept `--name` with nothing behind it, as an empty value rather than an
|
|
75
|
+
* error (Console `allowEmptyValue`).
|
|
76
|
+
*/
|
|
77
|
+
allowEmptyValue?: boolean
|
|
78
|
+
/** Transforms/validates the coerced value before it is assigned (Console `parse`). */
|
|
79
|
+
parse?: (value: string | string[] | number | boolean) => unknown
|
|
80
|
+
/** List `--no-<flag>` alongside the flag in help (booleans only). */
|
|
81
|
+
showNegatedVariantInHelp?: boolean
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** What the kernel produces from argv and assigns onto the command instance. */
|
|
85
|
+
/**
|
|
86
|
+
* The parsed CLI input, in the shape Console publishes it.
|
|
87
|
+
*
|
|
88
|
+
* Positionals are a LIST, in declaration order, and flags are keyed by their
|
|
89
|
+
* COMMAND-LINE name — `parsed.flags['user-email']`, not `parsed.flags.userEmail`.
|
|
90
|
+
* The property names are what the values are assigned TO on the command; the
|
|
91
|
+
* parsed bag describes what was typed.
|
|
92
|
+
*/
|
|
93
|
+
export interface ParsedInput {
|
|
94
|
+
args: unknown[]
|
|
95
|
+
flags: Record<string, unknown>
|
|
96
|
+
/**
|
|
97
|
+
* Names of the flags that were passed but not declared (Console
|
|
98
|
+
* `this.parsed.unknownFlags`). Their values are in {@link flags}; this is the
|
|
99
|
+
* list a command inspects to know what it was handed but does not know about.
|
|
100
|
+
*/
|
|
101
|
+
unknownFlags: string[]
|
|
102
|
+
/**
|
|
103
|
+
* Positionals beyond what the command declared.
|
|
104
|
+
*
|
|
105
|
+
* Normally none: an undeclared positional is an error. A command running with
|
|
106
|
+
* `allowUnknownFlags` is a proxy, so they are kept here instead of being
|
|
107
|
+
* dropped — forwarding them is the whole point of such a command.
|
|
108
|
+
*/
|
|
109
|
+
extraArgs: string[]
|
|
110
|
+
/** Console's name for {@link extraArgs} — the same array, not a copy. */
|
|
111
|
+
_: string[]
|
|
112
|
+
/**
|
|
113
|
+
* The arguments node itself was started with (Console `nodeArgs`), filled only
|
|
114
|
+
* for the command invoked from the command line.
|
|
115
|
+
*/
|
|
116
|
+
nodeArgs: string[]
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* The instance side of a command.
|
|
121
|
+
*
|
|
122
|
+
* Only `run()` is required. The lifecycle hooks are optional: the kernel calls
|
|
123
|
+
* whichever the command defines, in Console's order — prepare, interact, run,
|
|
124
|
+
* completed.
|
|
125
|
+
*/
|
|
126
|
+
export interface CommandInstance {
|
|
127
|
+
/**
|
|
128
|
+
* Whatever it returns becomes `result` on the executed command.
|
|
129
|
+
*
|
|
130
|
+
* Parameters are allowed: the container injects them (Console `@inject()` on a
|
|
131
|
+
* lifecycle method), and a no-arg signature would reject those commands.
|
|
132
|
+
*/
|
|
133
|
+
run(...args: never[]): unknown
|
|
134
|
+
prepare?(...args: never[]): void | Promise<void>
|
|
135
|
+
interact?(...args: never[]): void | Promise<void>
|
|
136
|
+
/** Returning `true` marks the error handled, stopping its propagation. */
|
|
137
|
+
// biome-ignore lint/suspicious/noConfusingVoidType: Console contract — returning `true` marks the error handled, returning nothing is the normal case
|
|
138
|
+
completed?(...args: never[]): boolean | void | Promise<boolean | void>
|
|
139
|
+
/** Set by the command to force a code; the kernel fills it in otherwise. */
|
|
140
|
+
exitCode?: number
|
|
141
|
+
/** Filled by the kernel before `completed()` runs. */
|
|
142
|
+
error?: unknown
|
|
143
|
+
/** Filled by the kernel with what `run()` returned. */
|
|
144
|
+
result?: unknown
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* A command's metadata as plain data (Console `serialize`).
|
|
149
|
+
*
|
|
150
|
+
* JSON-safe on purpose: the `parse` callbacks carried by the live metadata are
|
|
151
|
+
* dropped, so this can be printed, cached or sent over a wire without a
|
|
152
|
+
* function silently disappearing at the boundary.
|
|
153
|
+
*/
|
|
154
|
+
/**
|
|
155
|
+
* How one positional argument is parsed (Console `ArgumentsParserOptions`).
|
|
156
|
+
*
|
|
157
|
+
* Derived from the declarations by `BaseCommand.getParserOptions()`. Ream's own
|
|
158
|
+
* parser reads the declarations directly; this shape exists so code ported from
|
|
159
|
+
* Console — which inspects it — keeps working.
|
|
160
|
+
*/
|
|
161
|
+
export interface ArgumentsParserOptions {
|
|
162
|
+
type: 'string' | 'spread'
|
|
163
|
+
default?: string | string[]
|
|
164
|
+
parse?: (value: string | string[]) => unknown
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/** How the flags are parsed, grouped by type (Console `FlagsParserOptions`). */
|
|
168
|
+
export interface FlagsParserOptions {
|
|
169
|
+
all: string[]
|
|
170
|
+
string: string[]
|
|
171
|
+
boolean: string[]
|
|
172
|
+
number: string[]
|
|
173
|
+
array: string[]
|
|
174
|
+
/** Flag name → its single-character shorthands. */
|
|
175
|
+
alias: Record<string, string[]>
|
|
176
|
+
count: string[]
|
|
177
|
+
/** Flag name → its `parse` callback. */
|
|
178
|
+
coerce: Record<string, (value: never) => unknown>
|
|
179
|
+
default: Record<string, unknown>
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export interface SerializedCommand {
|
|
183
|
+
commandName: string
|
|
184
|
+
/**
|
|
185
|
+
* Where the command was found, relative to the directory it was loaded from.
|
|
186
|
+
*
|
|
187
|
+
* Set by loaders that read files, and by nothing else: it is what lets a
|
|
188
|
+
* generated manifest import a command without scanning anything.
|
|
189
|
+
*/
|
|
190
|
+
filePath?: string
|
|
191
|
+
/** The part before `:` — `make` for `make:controller`, null when there is none. */
|
|
192
|
+
namespace: string | null
|
|
193
|
+
description: string
|
|
194
|
+
help?: string | string[]
|
|
195
|
+
aliases: string[]
|
|
196
|
+
options: CommandOptions
|
|
197
|
+
args: Array<Omit<ArgumentMetaData, 'parse'>>
|
|
198
|
+
flags: Array<Omit<FlagMetaData, 'parse'>>
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* A snapshot of a command that has run (Console `toJSON`).
|
|
203
|
+
*
|
|
204
|
+
* Unlike {@link SerializedCommand} this is about one execution: the values it
|
|
205
|
+
* received and what it produced. `args` / `flags` are the parsed VALUES, not
|
|
206
|
+
* their declarations.
|
|
207
|
+
*/
|
|
208
|
+
export interface CommandSnapshot {
|
|
209
|
+
commandName: string
|
|
210
|
+
options: CommandOptions
|
|
211
|
+
/** Positional VALUES in declaration order — Console exposes a list here. */
|
|
212
|
+
args: unknown[]
|
|
213
|
+
flags: Record<string, unknown>
|
|
214
|
+
error: unknown
|
|
215
|
+
result: unknown
|
|
216
|
+
exitCode: number | undefined
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* A command that has run.
|
|
221
|
+
*
|
|
222
|
+
* The three outcome fields are guaranteed here, which is what `exec()` returns:
|
|
223
|
+
* without it the documented `command.exitCode` / `.result` / `.error` does not
|
|
224
|
+
* typecheck for a caller, and the only way to read them is a reflective escape
|
|
225
|
+
* hatch — which is exactly what the tests had ended up doing.
|
|
226
|
+
*/
|
|
227
|
+
/**
|
|
228
|
+
* Assertions available on a command that has run.
|
|
229
|
+
*
|
|
230
|
+
* Part of what `exec()` returns, so a caller can use them without the type
|
|
231
|
+
* hiding what exists at runtime. The kernel attaches them to every command it
|
|
232
|
+
* runs, including one that does not extend `BaseCommand`.
|
|
233
|
+
*/
|
|
234
|
+
export interface CommandAssertions {
|
|
235
|
+
assertSucceeded(): void
|
|
236
|
+
assertFailed(): void
|
|
237
|
+
assertExitCode(expected: number): void
|
|
238
|
+
assertNotExitCode(unexpected: number): void
|
|
239
|
+
assertLog(message: string, stream?: 'stdout' | 'stderr'): void
|
|
240
|
+
assertLogMatches(pattern: RegExp, stream?: 'stdout' | 'stderr'): void
|
|
241
|
+
assertTableRows(expected: readonly (readonly string[])[]): void
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
export interface ExecutedCommand extends CommandInstance, CommandAssertions {
|
|
245
|
+
exitCode: number
|
|
246
|
+
error: unknown
|
|
247
|
+
result: unknown
|
|
248
|
+
/** A snapshot of this execution (Console `toJSON`). */
|
|
249
|
+
toJSON(): CommandSnapshot
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* The static side. `args` / `flags` are optional so a command with neither
|
|
254
|
+
* still satisfies the contract without declaring empty arrays.
|
|
255
|
+
*/
|
|
256
|
+
export interface CommandClass {
|
|
257
|
+
// Not `new ()`: a command built through the container receives its injected
|
|
258
|
+
// dependencies, and a zero-arg signature rejects every such class.
|
|
259
|
+
new (...args: never[]): CommandInstance
|
|
260
|
+
commandName: string
|
|
261
|
+
description: string
|
|
262
|
+
/** Alternative names the command also answers to (Console `static aliases`). */
|
|
263
|
+
aliases?: readonly string[]
|
|
264
|
+
options?: CommandOptions
|
|
265
|
+
args?: readonly ArgumentMetaData[]
|
|
266
|
+
flags?: readonly FlagMetaData[]
|
|
267
|
+
/** Longer help text printed under the usage line by `<cmd> --help`. */
|
|
268
|
+
help?: string | string[]
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/** Narrowing guard used by the kernel when loading modules. */
|
|
272
|
+
export function isCommandClass(value: unknown): value is CommandClass {
|
|
273
|
+
if (typeof value !== 'function') return false
|
|
274
|
+
const candidate = value as Partial<CommandClass>
|
|
275
|
+
return (
|
|
276
|
+
typeof candidate.commandName === 'string' &&
|
|
277
|
+
candidate.commandName.length > 0 &&
|
|
278
|
+
typeof candidate.description === 'string'
|
|
279
|
+
)
|
|
280
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Console UI — `this.logger` and `this.prompt` on every command (Console parity).
|
|
3
|
+
*
|
|
4
|
+
* Kept dependency-free: the framework ships no colour or prompt library, and
|
|
5
|
+
* pulling one in for the CLI surface alone is not worth the install weight.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { stdout } from 'node:process'
|
|
9
|
+
|
|
10
|
+
/** Colour is opt-out via NO_COLOR and skipped when piped to a file. */
|
|
11
|
+
function supportsColour(stream: NodeJS.WriteStream): boolean {
|
|
12
|
+
if (process.env.NO_COLOR !== undefined && process.env.NO_COLOR !== '') return false
|
|
13
|
+
if (process.env.FORCE_COLOR !== undefined && process.env.FORCE_COLOR !== '') return true
|
|
14
|
+
return Boolean(stream.isTTY)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const CODES = {
|
|
18
|
+
reset: '\u001B[0m',
|
|
19
|
+
dim: '\u001B[2m',
|
|
20
|
+
red: '\u001B[31m',
|
|
21
|
+
green: '\u001B[32m',
|
|
22
|
+
yellow: '\u001B[33m',
|
|
23
|
+
blue: '\u001B[34m',
|
|
24
|
+
magenta: '\u001B[35m',
|
|
25
|
+
cyan: '\u001B[36m',
|
|
26
|
+
} as const
|
|
27
|
+
|
|
28
|
+
export type Colour = keyof Omit<typeof CODES, 'reset'>
|
|
29
|
+
|
|
30
|
+
export function colourise(
|
|
31
|
+
text: string,
|
|
32
|
+
colour: Colour,
|
|
33
|
+
stream: NodeJS.WriteStream = stdout,
|
|
34
|
+
): string {
|
|
35
|
+
if (!supportsColour(stream)) return text
|
|
36
|
+
return `${CODES[colour]}${text}${CODES.reset}`
|
|
37
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The helpers Console exposes around commands (`@adonisjs/consoleApp` utils).
|
|
3
|
+
*
|
|
4
|
+
* They exist as exports because a custom loader needs them: validating what a
|
|
5
|
+
* module exported, and reporting a name that resolved to nothing.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { ReamError } from '../errors/ReamError.js'
|
|
9
|
+
import type { Logger } from './cliui.js'
|
|
10
|
+
import { type CommandClass, isCommandClass, type SerializedCommand } from './types.js'
|
|
11
|
+
|
|
12
|
+
/** Sort command and namespace names the way the listing does. */
|
|
13
|
+
export function sortAlphabetically(prev: string, curr: string): number {
|
|
14
|
+
return prev.localeCompare(curr)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Report a name that resolved to nothing, with the closest matches.
|
|
19
|
+
*
|
|
20
|
+
* Shared by the kernel's unknown-command report and the `help` command: two
|
|
21
|
+
* wordings for the same dead end is how they end up disagreeing.
|
|
22
|
+
*/
|
|
23
|
+
export function renderErrorWithSuggestions(
|
|
24
|
+
logger: Logger,
|
|
25
|
+
message: string,
|
|
26
|
+
suggestions: readonly string[],
|
|
27
|
+
): void {
|
|
28
|
+
logger.error(message)
|
|
29
|
+
if (suggestions.length === 0) return
|
|
30
|
+
process.stderr.write(` Did you mean "${suggestions.slice(0, 4).join('", "')}"?\n`)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Assert that a module's export is a command class.
|
|
35
|
+
*
|
|
36
|
+
* `exportPath` names the file, because the useful part of the message is WHICH
|
|
37
|
+
* module exported the wrong thing.
|
|
38
|
+
*/
|
|
39
|
+
export function validateCommand(
|
|
40
|
+
command: unknown,
|
|
41
|
+
exportPath: string,
|
|
42
|
+
): asserts command is CommandClass {
|
|
43
|
+
if (isCommandClass(command)) return
|
|
44
|
+
throw new ReamError('E_CONSOLE_INVALID_COMMAND', `Invalid command exported from ${exportPath}.`, {
|
|
45
|
+
hint: 'Expected a class with a static commandName, a static description and a run() method.',
|
|
46
|
+
})
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** The same, for a metadata object a loader published. */
|
|
50
|
+
export function validateCommandMetaData(
|
|
51
|
+
metadata: unknown,
|
|
52
|
+
exportPath: string,
|
|
53
|
+
): asserts metadata is SerializedCommand {
|
|
54
|
+
const invalid = (reason: string): never => {
|
|
55
|
+
throw new ReamError(
|
|
56
|
+
'E_CONSOLE_INVALID_COMMAND_METADATA',
|
|
57
|
+
`Invalid command metadata exported from ${exportPath}: ${reason}.`,
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (typeof metadata !== 'object' || metadata === null) invalid('expected an object')
|
|
62
|
+
const record = metadata as Record<string, unknown>
|
|
63
|
+
if (typeof record.commandName !== 'string' || record.commandName === '') {
|
|
64
|
+
invalid('"commandName" is missing')
|
|
65
|
+
}
|
|
66
|
+
if (typeof record.description !== 'string') invalid('"description" is missing')
|
|
67
|
+
if (!Array.isArray(record.args)) invalid('"args" is missing')
|
|
68
|
+
if (!Array.isArray(record.flags)) invalid('"flags" is missing')
|
|
69
|
+
}
|