@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.
Files changed (302) hide show
  1. package/README.md +65 -0
  2. package/dist/ConfigLoader.d.ts +46 -5
  3. package/dist/ConfigLoader.d.ts.map +1 -1
  4. package/dist/ConfigLoader.js +60 -9
  5. package/dist/ConfigLoader.js.map +1 -1
  6. package/dist/HttpKernel.d.ts.map +1 -1
  7. package/dist/HttpKernel.js +46 -6
  8. package/dist/HttpKernel.js.map +1 -1
  9. package/dist/Ignitor.d.ts +115 -7
  10. package/dist/Ignitor.d.ts.map +1 -1
  11. package/dist/Ignitor.js +254 -40
  12. package/dist/Ignitor.js.map +1 -1
  13. package/dist/console/BaseCommand.d.ts +217 -0
  14. package/dist/console/BaseCommand.d.ts.map +1 -0
  15. package/dist/console/BaseCommand.js +340 -0
  16. package/dist/console/BaseCommand.js.map +1 -0
  17. package/dist/console/Console.d.ts +86 -0
  18. package/dist/console/Console.d.ts.map +1 -0
  19. package/dist/console/Console.js +134 -0
  20. package/dist/console/Console.js.map +1 -0
  21. package/dist/console/ExceptionHandler.d.ts +28 -0
  22. package/dist/console/ExceptionHandler.d.ts.map +1 -0
  23. package/dist/console/ExceptionHandler.js +76 -0
  24. package/dist/console/ExceptionHandler.js.map +1 -0
  25. package/dist/console/HelpCommand.d.ts +16 -0
  26. package/dist/console/HelpCommand.d.ts.map +1 -0
  27. package/dist/console/HelpCommand.js +40 -0
  28. package/dist/console/HelpCommand.js.map +1 -0
  29. package/dist/console/IndexGenerator.d.ts +24 -0
  30. package/dist/console/IndexGenerator.d.ts.map +1 -0
  31. package/dist/console/IndexGenerator.js +65 -0
  32. package/dist/console/IndexGenerator.js.map +1 -0
  33. package/dist/console/Kernel.d.ts +298 -0
  34. package/dist/console/Kernel.d.ts.map +1 -0
  35. package/dist/console/Kernel.js +1120 -0
  36. package/dist/console/Kernel.js.map +1 -0
  37. package/dist/console/ListCommand.d.ts +18 -0
  38. package/dist/console/ListCommand.d.ts.map +1 -0
  39. package/dist/console/ListCommand.js +60 -0
  40. package/dist/console/ListCommand.js.map +1 -0
  41. package/dist/console/assertions.d.ts +20 -0
  42. package/dist/console/assertions.d.ts.map +1 -0
  43. package/dist/console/assertions.js +84 -0
  44. package/dist/console/assertions.js.map +1 -0
  45. package/dist/console/cliui.d.ts +248 -0
  46. package/dist/console/cliui.d.ts.map +1 -0
  47. package/dist/console/cliui.js +587 -0
  48. package/dist/console/cliui.js.map +1 -0
  49. package/dist/console/decorators.d.ts +90 -0
  50. package/dist/console/decorators.d.ts.map +1 -0
  51. package/dist/console/decorators.js +142 -0
  52. package/dist/console/decorators.js.map +1 -0
  53. package/dist/console/index.d.ts +32 -0
  54. package/dist/console/index.d.ts.map +1 -0
  55. package/dist/console/index.js +24 -0
  56. package/dist/console/index.js.map +1 -0
  57. package/dist/console/loaders.d.ts +52 -0
  58. package/dist/console/loaders.d.ts.map +1 -0
  59. package/dist/console/loaders.js +131 -0
  60. package/dist/console/loaders.js.map +1 -0
  61. package/dist/console/parser.d.ts +86 -0
  62. package/dist/console/parser.d.ts.map +1 -0
  63. package/dist/console/parser.js +440 -0
  64. package/dist/console/parser.js.map +1 -0
  65. package/dist/console/prompts.d.ts +124 -0
  66. package/dist/console/prompts.d.ts.map +1 -0
  67. package/dist/console/prompts.js +356 -0
  68. package/dist/console/prompts.js.map +1 -0
  69. package/dist/console/tracing.d.ts +17 -0
  70. package/dist/console/tracing.d.ts.map +1 -0
  71. package/dist/console/tracing.js +11 -0
  72. package/dist/console/tracing.js.map +1 -0
  73. package/dist/console/types.d.ts +255 -0
  74. package/dist/console/types.d.ts.map +1 -0
  75. package/dist/console/types.js +25 -0
  76. package/dist/console/types.js.map +1 -0
  77. package/dist/console/ui.d.ts +20 -0
  78. package/dist/console/ui.d.ts.map +1 -0
  79. package/dist/console/ui.js +31 -0
  80. package/dist/console/ui.js.map +1 -0
  81. package/dist/console/utils.d.ts +27 -0
  82. package/dist/console/utils.d.ts.map +1 -0
  83. package/dist/console/utils.js +56 -0
  84. package/dist/console/utils.js.map +1 -0
  85. package/dist/container/Container.d.ts +23 -3
  86. package/dist/container/Container.d.ts.map +1 -1
  87. package/dist/container/Container.js +177 -70
  88. package/dist/container/Container.js.map +1 -1
  89. package/dist/container/types.d.ts +14 -2
  90. package/dist/container/types.d.ts.map +1 -1
  91. package/dist/decorators/Service.d.ts +7 -0
  92. package/dist/decorators/Service.d.ts.map +1 -1
  93. package/dist/decorators/Service.js +23 -3
  94. package/dist/decorators/Service.js.map +1 -1
  95. package/dist/env/Env.d.ts +29 -4
  96. package/dist/env/Env.d.ts.map +1 -1
  97. package/dist/env/Env.js +27 -4
  98. package/dist/env/Env.js.map +1 -1
  99. package/dist/env/Secret.d.ts +11 -0
  100. package/dist/env/Secret.d.ts.map +1 -0
  101. package/dist/env/Secret.js +36 -0
  102. package/dist/env/Secret.js.map +1 -0
  103. package/dist/env/interpolate.d.ts +26 -0
  104. package/dist/env/interpolate.d.ts.map +1 -0
  105. package/dist/env/interpolate.js +48 -0
  106. package/dist/env/interpolate.js.map +1 -0
  107. package/dist/env/loadEnvFiles.d.ts.map +1 -1
  108. package/dist/env/loadEnvFiles.js +14 -4
  109. package/dist/env/loadEnvFiles.js.map +1 -1
  110. package/dist/env/schema.d.ts +23 -6
  111. package/dist/env/schema.d.ts.map +1 -1
  112. package/dist/env/schema.js +67 -33
  113. package/dist/env/schema.js.map +1 -1
  114. package/dist/errors/ReamError.d.ts +25 -0
  115. package/dist/errors/ReamError.d.ts.map +1 -1
  116. package/dist/errors/ReamError.js +5 -0
  117. package/dist/errors/ReamError.js.map +1 -1
  118. package/dist/errors/prettyPrintError.d.ts +9 -0
  119. package/dist/errors/prettyPrintError.d.ts.map +1 -0
  120. package/dist/errors/prettyPrintError.js +22 -0
  121. package/dist/errors/prettyPrintError.js.map +1 -0
  122. package/dist/events/Emitter.d.ts +1 -1
  123. package/dist/events/Emitter.d.ts.map +1 -1
  124. package/dist/events/Emitter.js +1 -1
  125. package/dist/events/Emitter.js.map +1 -1
  126. package/dist/events/EventsProvider.d.ts +2 -2
  127. package/dist/events/EventsProvider.d.ts.map +1 -1
  128. package/dist/events/EventsProvider.js +3 -3
  129. package/dist/events/EventsProvider.js.map +1 -1
  130. package/dist/graphql/GraphQLEngine.d.ts +1 -1
  131. package/dist/graphql/GraphQLEngine.d.ts.map +1 -1
  132. package/dist/graphql/GraphQLEngine.js +2 -2
  133. package/dist/graphql/GraphQLEngine.js.map +1 -1
  134. package/dist/graphql/GraphQLProvider.d.ts.map +1 -1
  135. package/dist/graphql/GraphQLProvider.js +7 -3
  136. package/dist/graphql/GraphQLProvider.js.map +1 -1
  137. package/dist/http/Exception.d.ts +63 -1
  138. package/dist/http/Exception.d.ts.map +1 -1
  139. package/dist/http/Exception.js +185 -48
  140. package/dist/http/Exception.js.map +1 -1
  141. package/dist/http/HttpContext.d.ts +53 -7
  142. package/dist/http/HttpContext.d.ts.map +1 -1
  143. package/dist/http/HttpContext.js +56 -15
  144. package/dist/http/HttpContext.js.map +1 -1
  145. package/dist/http/RedirectBuilder.d.ts.map +1 -1
  146. package/dist/http/RedirectBuilder.js +4 -1
  147. package/dist/http/RedirectBuilder.js.map +1 -1
  148. package/dist/http/Request.d.ts +141 -10
  149. package/dist/http/Request.d.ts.map +1 -1
  150. package/dist/http/Request.js +244 -34
  151. package/dist/http/Request.js.map +1 -1
  152. package/dist/http/Response.d.ts +176 -9
  153. package/dist/http/Response.d.ts.map +1 -1
  154. package/dist/http/Response.js +404 -16
  155. package/dist/http/Response.js.map +1 -1
  156. package/dist/index.d.ts +19 -8
  157. package/dist/index.d.ts.map +1 -1
  158. package/dist/index.js +20 -5
  159. package/dist/index.js.map +1 -1
  160. package/dist/middleware/Pipeline.d.ts +29 -8
  161. package/dist/middleware/Pipeline.d.ts.map +1 -1
  162. package/dist/middleware/Pipeline.js +40 -2
  163. package/dist/middleware/Pipeline.js.map +1 -1
  164. package/dist/openapi/OpenApiProvider.js +4 -4
  165. package/dist/openapi/OpenApiProvider.js.map +1 -1
  166. package/dist/router/Router.d.ts +223 -31
  167. package/dist/router/Router.d.ts.map +1 -1
  168. package/dist/router/Router.js +520 -102
  169. package/dist/router/Router.js.map +1 -1
  170. package/dist/rpc/RpcProvider.d.ts +1 -0
  171. package/dist/rpc/RpcProvider.d.ts.map +1 -1
  172. package/dist/rpc/RpcProvider.js +7 -3
  173. package/dist/rpc/RpcProvider.js.map +1 -1
  174. package/dist/rpc/RpcRouter.d.ts +2 -2
  175. package/dist/rpc/RpcRouter.d.ts.map +1 -1
  176. package/dist/rpc/RpcRouter.js +17 -5
  177. package/dist/rpc/RpcRouter.js.map +1 -1
  178. package/dist/scheduler/ScheduleProvider.d.ts.map +1 -1
  179. package/dist/scheduler/ScheduleProvider.js +7 -15
  180. package/dist/scheduler/ScheduleProvider.js.map +1 -1
  181. package/dist/server/Server.d.ts +17 -4
  182. package/dist/server/Server.d.ts.map +1 -1
  183. package/dist/server/Server.js +41 -7
  184. package/dist/server/Server.js.map +1 -1
  185. package/dist/services/app.d.ts +1 -1
  186. package/dist/services/app.js +1 -1
  187. package/dist/services/console.d.ts +21 -0
  188. package/dist/services/console.d.ts.map +1 -0
  189. package/dist/services/console.js +35 -0
  190. package/dist/services/console.js.map +1 -0
  191. package/dist/session/SessionMiddleware.js +3 -3
  192. package/dist/session/SessionMiddleware.js.map +1 -1
  193. package/dist/storage/StaticProvider.js +1 -1
  194. package/dist/storage/StaticProvider.js.map +1 -1
  195. package/dist/testing/ApiResponse.d.ts +218 -0
  196. package/dist/testing/ApiResponse.d.ts.map +1 -0
  197. package/dist/testing/ApiResponse.js +576 -0
  198. package/dist/testing/ApiResponse.js.map +1 -0
  199. package/dist/testing/RequestBuilder.d.ts +155 -35
  200. package/dist/testing/RequestBuilder.d.ts.map +1 -1
  201. package/dist/testing/RequestBuilder.js +455 -109
  202. package/dist/testing/RequestBuilder.js.map +1 -1
  203. package/dist/testing/TestClient.d.ts +53 -37
  204. package/dist/testing/TestClient.d.ts.map +1 -1
  205. package/dist/testing/TestClient.js +84 -52
  206. package/dist/testing/TestClient.js.map +1 -1
  207. package/dist/utils/Macroable.d.ts +30 -0
  208. package/dist/utils/Macroable.d.ts.map +1 -0
  209. package/dist/utils/Macroable.js +43 -0
  210. package/dist/utils/Macroable.js.map +1 -0
  211. package/dist/utils/inflect.d.ts +17 -0
  212. package/dist/utils/inflect.d.ts.map +1 -0
  213. package/dist/utils/inflect.js +32 -0
  214. package/dist/utils/inflect.js.map +1 -0
  215. package/dist/utils/objectPath.d.ts +57 -0
  216. package/dist/utils/objectPath.d.ts.map +1 -0
  217. package/dist/utils/objectPath.js +141 -0
  218. package/dist/utils/objectPath.js.map +1 -0
  219. package/events.darwin-arm64.node +0 -0
  220. package/events.darwin-x64.node +0 -0
  221. package/events.linux-arm64-gnu.node +0 -0
  222. package/events.linux-x64-gnu.node +0 -0
  223. package/events.win32-x64-msvc.node +0 -0
  224. package/index.darwin-arm64.node +0 -0
  225. package/index.darwin-x64.node +0 -0
  226. package/index.linux-arm64-gnu.node +0 -0
  227. package/index.linux-x64-gnu.node +0 -0
  228. package/index.win32-x64-msvc.node +0 -0
  229. package/package.json +20 -2
  230. package/scheduler.darwin-arm64.node +0 -0
  231. package/scheduler.darwin-x64.node +0 -0
  232. package/scheduler.linux-arm64-gnu.node +0 -0
  233. package/scheduler.linux-x64-gnu.node +0 -0
  234. package/scheduler.win32-x64-msvc.node +0 -0
  235. package/src/ConfigLoader.ts +72 -9
  236. package/src/HttpKernel.ts +53 -15
  237. package/src/Ignitor.ts +364 -45
  238. package/src/console/BaseCommand.ts +467 -0
  239. package/src/console/Console.ts +174 -0
  240. package/src/console/ExceptionHandler.ts +91 -0
  241. package/src/console/HelpCommand.ts +37 -0
  242. package/src/console/IndexGenerator.ts +79 -0
  243. package/src/console/Kernel.ts +1382 -0
  244. package/src/console/ListCommand.ts +55 -0
  245. package/src/console/assertions.ts +114 -0
  246. package/src/console/cliui.ts +756 -0
  247. package/src/console/decorators.ts +199 -0
  248. package/src/console/index.ts +67 -0
  249. package/src/console/loaders.ts +145 -0
  250. package/src/console/parser.ts +598 -0
  251. package/src/console/prompts.ts +548 -0
  252. package/src/console/tracing.ts +22 -0
  253. package/src/console/types.ts +280 -0
  254. package/src/console/ui.ts +37 -0
  255. package/src/console/utils.ts +69 -0
  256. package/src/container/Container.ts +198 -72
  257. package/src/container/types.ts +15 -2
  258. package/src/decorators/Service.ts +28 -3
  259. package/src/env/Env.ts +49 -5
  260. package/src/env/Secret.ts +41 -0
  261. package/src/env/interpolate.ts +54 -0
  262. package/src/env/loadEnvFiles.ts +12 -4
  263. package/src/env/schema.ts +109 -35
  264. package/src/errors/ReamError.ts +31 -0
  265. package/src/errors/prettyPrintError.ts +20 -0
  266. package/src/events/Emitter.ts +2 -2
  267. package/src/events/EventsProvider.ts +5 -5
  268. package/src/graphql/GraphQLEngine.ts +4 -4
  269. package/src/graphql/GraphQLProvider.ts +7 -3
  270. package/src/http/Exception.ts +214 -37
  271. package/src/http/HttpContext.ts +87 -18
  272. package/src/http/RedirectBuilder.ts +4 -1
  273. package/src/http/Request.ts +264 -34
  274. package/src/http/Response.ts +478 -27
  275. package/src/index.ts +41 -6
  276. package/src/middleware/Pipeline.ts +77 -6
  277. package/src/openapi/OpenApiProvider.ts +4 -4
  278. package/src/router/Router.ts +631 -113
  279. package/src/rpc/RpcProvider.ts +6 -2
  280. package/src/rpc/RpcRouter.ts +22 -7
  281. package/src/scheduler/ScheduleProvider.ts +7 -15
  282. package/src/server/Server.ts +49 -10
  283. package/src/services/app.ts +1 -1
  284. package/src/services/console.ts +42 -0
  285. package/src/session/SessionMiddleware.ts +4 -4
  286. package/src/storage/StaticProvider.ts +1 -1
  287. package/src/testing/ApiResponse.ts +691 -0
  288. package/src/testing/RequestBuilder.ts +577 -137
  289. package/src/testing/TestClient.ts +110 -77
  290. package/src/utils/Macroable.ts +54 -0
  291. package/src/utils/inflect.ts +29 -0
  292. package/src/utils/objectPath.ts +142 -0
  293. package/dist/console/CommandRunner.d.ts +0 -18
  294. package/dist/console/CommandRunner.d.ts.map +0 -1
  295. package/dist/console/CommandRunner.js +0 -65
  296. package/dist/console/CommandRunner.js.map +0 -1
  297. package/dist/decorators/Lazy.d.ts +0 -19
  298. package/dist/decorators/Lazy.d.ts.map +0 -1
  299. package/dist/decorators/Lazy.js +0 -53
  300. package/dist/decorators/Lazy.js.map +0 -1
  301. package/src/console/CommandRunner.ts +0 -82
  302. 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
+ }