@c9up/ream 0.1.26 → 0.1.28
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/Ignitor.d.ts +115 -7
- package/dist/Ignitor.d.ts.map +1 -1
- package/dist/Ignitor.js +233 -37
- 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 +364 -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.map +1 -1
- package/dist/container/Container.js +40 -12
- 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/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/index.d.ts +14 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -2
- 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 +39 -1
- package/dist/middleware/Pipeline.js.map +1 -1
- package/dist/rpc/RpcRouter.d.ts.map +1 -1
- package/dist/rpc/RpcRouter.js +13 -2
- package/dist/rpc/RpcRouter.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/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 +132 -72
- package/dist/testing/RequestBuilder.d.ts.map +1 -1
- package/dist/testing/RequestBuilder.js +389 -222
- package/dist/testing/RequestBuilder.js.map +1 -1
- package/dist/testing/TestClient.d.ts +34 -39
- package/dist/testing/TestClient.d.ts.map +1 -1
- package/dist/testing/TestClient.js +48 -56
- package/dist/testing/TestClient.js.map +1 -1
- package/dist/utils/Macroable.js +3 -3
- package/dist/utils/Macroable.js.map +1 -1
- 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 +15 -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/Ignitor.ts +340 -42
- 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 +556 -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 +55 -13
- package/src/container/types.ts +15 -2
- package/src/decorators/Service.ts +28 -3
- package/src/errors/ReamError.ts +31 -0
- package/src/errors/prettyPrintError.ts +20 -0
- package/src/index.ts +30 -4
- package/src/middleware/Pipeline.ts +76 -5
- package/src/rpc/RpcRouter.ts +16 -2
- package/src/services/app.ts +1 -1
- package/src/services/console.ts +42 -0
- package/src/testing/ApiResponse.ts +691 -0
- package/src/testing/RequestBuilder.ts +498 -275
- package/src/testing/TestClient.ts +63 -86
- package/src/utils/Macroable.ts +3 -3
- 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/src/console/CommandRunner.ts +0 -82
|
@@ -23,40 +23,24 @@ import {
|
|
|
23
23
|
type HttpMethod,
|
|
24
24
|
type HttpSender,
|
|
25
25
|
RequestBuilder,
|
|
26
|
+
type TestResponse,
|
|
26
27
|
} from './RequestBuilder.js'
|
|
27
28
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
body: string
|
|
32
|
-
json<T = unknown>(): T
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Fluent request builder. Thenable like AdonisJS/japa's api-client: `await
|
|
37
|
-
* client.get('/x')` sends the request, and chaining works on every verb —
|
|
38
|
-
* `await client.get('/x').header('authorization', token)`. The explicit
|
|
39
|
-
* `.send()` is kept for callers that prefer it.
|
|
40
|
-
*/
|
|
41
|
-
export interface TestRequestBuilder extends PromiseLike<TestResponse> {
|
|
42
|
-
/** Set a request header. */
|
|
43
|
-
header(name: string, value: string): TestRequestBuilder
|
|
44
|
-
/** Set the request body as JSON. */
|
|
45
|
-
json(data: unknown): TestRequestBuilder
|
|
46
|
-
/** Set a raw string body with optional content type. */
|
|
47
|
-
body(content: string, contentType?: string): TestRequestBuilder
|
|
48
|
-
/** Set a cookie. */
|
|
49
|
-
cookie(name: string, value: string): TestRequestBuilder
|
|
50
|
-
/** Send the request and return the response. */
|
|
51
|
-
send(): Promise<TestResponse>
|
|
52
|
-
}
|
|
29
|
+
// The raw response shape + the rich response live in ApiResponse.ts and are
|
|
30
|
+
// re-exported here so `@c9up/ream/testing` consumers keep their import path.
|
|
31
|
+
export { ApiResponse, type TestResponse } from './RequestBuilder.js'
|
|
53
32
|
|
|
54
33
|
/**
|
|
55
34
|
* Named-route manifest — `name → path pattern`, e.g. `{ 'users.show':
|
|
56
35
|
* '/users/:id' }`. Feed `router.namedManifest()` here so `visit()` can resolve
|
|
57
36
|
* named routes without the full Router.
|
|
37
|
+
*
|
|
38
|
+
* A value may be a bare path string OR `{ path, method }` — when the method is
|
|
39
|
+
* present, `visit(name)` uses it (Japa route-registry parity, e.g.
|
|
40
|
+
* `visit('users.store').json(...).assertCreated()` issues a POST).
|
|
58
41
|
*/
|
|
59
|
-
export type
|
|
42
|
+
export type RouteEntry = string | { path: string; method?: HttpMethod }
|
|
43
|
+
export type RouteManifest = Record<string, RouteEntry>
|
|
60
44
|
|
|
61
45
|
export class TestClient {
|
|
62
46
|
#port = 0
|
|
@@ -106,29 +90,47 @@ export class TestClient {
|
|
|
106
90
|
return this
|
|
107
91
|
}
|
|
108
92
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
93
|
+
// Verb shortcuts return the RICH builder — the full japa/api-client surface
|
|
94
|
+
// (assertOk/assertStatus/assertBody/… + auth/csrf) AND awaitable (`await
|
|
95
|
+
// client.get('/x')` sends and resolves to the response). One unified builder,
|
|
96
|
+
// no split between `get()` and `fluent()`.
|
|
97
|
+
|
|
98
|
+
/** GET request — rich, awaitable builder. */
|
|
99
|
+
get(path: string): RequestBuilder {
|
|
100
|
+
return this.fluent('GET', path)
|
|
112
101
|
}
|
|
113
102
|
|
|
114
|
-
/** POST request. */
|
|
115
|
-
post(path: string):
|
|
116
|
-
return this.
|
|
103
|
+
/** POST request — rich, awaitable builder. */
|
|
104
|
+
post(path: string): RequestBuilder {
|
|
105
|
+
return this.fluent('POST', path)
|
|
117
106
|
}
|
|
118
107
|
|
|
119
|
-
/** PUT request. */
|
|
120
|
-
put(path: string):
|
|
121
|
-
return this.
|
|
108
|
+
/** PUT request — rich, awaitable builder. */
|
|
109
|
+
put(path: string): RequestBuilder {
|
|
110
|
+
return this.fluent('PUT', path)
|
|
122
111
|
}
|
|
123
112
|
|
|
124
|
-
/** PATCH request. */
|
|
125
|
-
patch(path: string):
|
|
126
|
-
return this.
|
|
113
|
+
/** PATCH request — rich, awaitable builder. */
|
|
114
|
+
patch(path: string): RequestBuilder {
|
|
115
|
+
return this.fluent('PATCH', path)
|
|
127
116
|
}
|
|
128
117
|
|
|
129
|
-
/** DELETE request
|
|
130
|
-
delete(path: string):
|
|
131
|
-
return this.
|
|
118
|
+
/** DELETE request — rich, awaitable builder. */
|
|
119
|
+
delete(path: string): RequestBuilder {
|
|
120
|
+
return this.fluent('DELETE', path)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* HEAD request — japa/api-client's `.head()`. Returns the rich builder so you
|
|
125
|
+
* can assert status/headers (a HEAD response carries headers, no body).
|
|
126
|
+
*/
|
|
127
|
+
head(path: string): RequestBuilder {
|
|
128
|
+
return this.fluent('HEAD', path)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/** OPTIONS request — japa/api-client's `.options()`. */
|
|
132
|
+
options(path: string): RequestBuilder {
|
|
133
|
+
return this.fluent('OPTIONS', path)
|
|
132
134
|
}
|
|
133
135
|
|
|
134
136
|
/**
|
|
@@ -145,6 +147,7 @@ export class TestClient {
|
|
|
145
147
|
p,
|
|
146
148
|
{ ...this.#headers, ...init.headers },
|
|
147
149
|
init.body.toString('utf8'),
|
|
150
|
+
init.timeoutMs,
|
|
148
151
|
)
|
|
149
152
|
return new RequestBuilder(sender, method, path, this.#auth)
|
|
150
153
|
}
|
|
@@ -161,48 +164,20 @@ export class TestClient {
|
|
|
161
164
|
'TestClient: visit() needs a named-route manifest. Pass `routes: router.namedManifest()` in the client options.',
|
|
162
165
|
)
|
|
163
166
|
}
|
|
164
|
-
|
|
167
|
+
const entry = this.#routes[name]
|
|
168
|
+
// Method comes from the registry when the entry carries one (Japa parity),
|
|
169
|
+
// otherwise GET.
|
|
170
|
+
const method: HttpMethod = typeof entry === 'object' && entry.method ? entry.method : 'GET'
|
|
171
|
+
return this.fluent(method, resolveNamedRoute(this.#routes, name, params))
|
|
165
172
|
}
|
|
166
173
|
|
|
167
|
-
/**
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
header(name: string, value: string) {
|
|
175
|
-
headers[name.toLowerCase()] = value
|
|
176
|
-
return builder
|
|
177
|
-
},
|
|
178
|
-
json(data: unknown) {
|
|
179
|
-
bodyContent = JSON.stringify(data)
|
|
180
|
-
headers['content-type'] = 'application/json'
|
|
181
|
-
return builder
|
|
182
|
-
},
|
|
183
|
-
body(content: string, contentType?: string) {
|
|
184
|
-
bodyContent = content
|
|
185
|
-
if (contentType) headers['content-type'] = contentType
|
|
186
|
-
return builder
|
|
187
|
-
},
|
|
188
|
-
cookie(name: string, value: string) {
|
|
189
|
-
cookies.push(`${name}=${value}`)
|
|
190
|
-
return builder
|
|
191
|
-
},
|
|
192
|
-
send: async () => {
|
|
193
|
-
if (cookies.length > 0) {
|
|
194
|
-
headers.cookie = cookies.join('; ')
|
|
195
|
-
}
|
|
196
|
-
return sendRequest(this.#port, method, path, headers, bodyContent)
|
|
197
|
-
},
|
|
198
|
-
// Thenable: `await client.get('/x')` (or any builder) sends the request,
|
|
199
|
-
// matching AdonisJS/japa's api-client ergonomics. The `then` IS the public
|
|
200
|
-
// contract here — awaiting the builder is the documented way to send.
|
|
201
|
-
// biome-ignore lint/suspicious/noThenProperty: thenable request builder is the intended API (AdonisJS/japa parity) — `await client.get(path)` sends
|
|
202
|
-
then: (onfulfilled, onrejected) => builder.send().then(onfulfilled, onrejected),
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
return builder
|
|
174
|
+
/**
|
|
175
|
+
* Generic request — japa/api-client's `client.request(url, method)` (note the
|
|
176
|
+
* arg order: URL first, method second, defaulting to GET). Returns the same
|
|
177
|
+
* rich, awaitable builder as the verb shortcuts.
|
|
178
|
+
*/
|
|
179
|
+
request(path: string, method: HttpMethod = 'GET'): RequestBuilder {
|
|
180
|
+
return this.fluent(method, path)
|
|
206
181
|
}
|
|
207
182
|
}
|
|
208
183
|
|
|
@@ -237,12 +212,12 @@ export function resolveNamedRoute(
|
|
|
237
212
|
name: string,
|
|
238
213
|
params?: Record<string, string>,
|
|
239
214
|
): string {
|
|
240
|
-
const
|
|
241
|
-
if (
|
|
215
|
+
const entry = manifest[name]
|
|
216
|
+
if (entry === undefined) {
|
|
242
217
|
const available = Object.keys(manifest).join(', ') || '(none)'
|
|
243
218
|
throw new Error(`Route '${name}' not found. Available: ${available}`)
|
|
244
219
|
}
|
|
245
|
-
let url =
|
|
220
|
+
let url = typeof entry === 'string' ? entry : entry.path
|
|
246
221
|
if (params) {
|
|
247
222
|
for (const [key, value] of Object.entries(params)) {
|
|
248
223
|
const escaped = key.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
@@ -264,6 +239,7 @@ async function sendRequest(
|
|
|
264
239
|
path: string,
|
|
265
240
|
headers: Dict,
|
|
266
241
|
body: string,
|
|
242
|
+
timeoutMs?: number,
|
|
267
243
|
): Promise<TestResponse> {
|
|
268
244
|
const { connect } = await import('node:net')
|
|
269
245
|
|
|
@@ -309,8 +285,9 @@ async function sendRequest(
|
|
|
309
285
|
// tokio runtimes) the cumulative latency exceeded 5s ~30% of runs
|
|
310
286
|
// and surfaced as flaky `bob accepts` / `non-member 403` failures
|
|
311
287
|
// in kitchen-sink's workspace.test.ts. 30s matches the helix
|
|
312
|
-
// `--timeout=60000` per-test budget without masking real hangs.
|
|
313
|
-
|
|
288
|
+
// `--timeout=60000` per-test budget without masking real hangs. A
|
|
289
|
+
// per-request `.timeout(ms)` (Japa) overrides the default.
|
|
290
|
+
socket.setTimeout(timeoutMs && timeoutMs > 0 ? timeoutMs : 30_000, () => {
|
|
314
291
|
socket.destroy()
|
|
315
292
|
reject(new Error('TestClient request timed out'))
|
|
316
293
|
})
|
package/src/utils/Macroable.ts
CHANGED
|
@@ -24,7 +24,7 @@ export type GetterFn = () => unknown
|
|
|
24
24
|
export class Macroable {
|
|
25
25
|
/** Attach a method to every instance of this class (AdonisJS `macro`). */
|
|
26
26
|
static macro(name: string, fn: MacroFn): void {
|
|
27
|
-
Object.defineProperty(
|
|
27
|
+
Object.defineProperty(Macroable.prototype, name, {
|
|
28
28
|
value: fn,
|
|
29
29
|
writable: true,
|
|
30
30
|
configurable: true,
|
|
@@ -37,11 +37,11 @@ export class Macroable {
|
|
|
37
37
|
*/
|
|
38
38
|
static getter(name: string, fn: GetterFn, singleton = false): void {
|
|
39
39
|
if (!singleton) {
|
|
40
|
-
Object.defineProperty(
|
|
40
|
+
Object.defineProperty(Macroable.prototype, name, { get: fn, configurable: true })
|
|
41
41
|
return
|
|
42
42
|
}
|
|
43
43
|
const cacheKey = Symbol(name)
|
|
44
|
-
Object.defineProperty(
|
|
44
|
+
Object.defineProperty(Macroable.prototype, name, {
|
|
45
45
|
configurable: true,
|
|
46
46
|
get(this: Record<symbol, unknown>) {
|
|
47
47
|
if (!(cacheKey in this)) {
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* CommandRunner — minimal CLI command framework.
|
|
3
|
-
*
|
|
4
|
-
* Registers commands and dispatches based on argv.
|
|
5
|
-
* Like AdonisJS Ace but lightweight.
|
|
6
|
-
*/
|
|
7
|
-
export interface Command {
|
|
8
|
-
name: string;
|
|
9
|
-
description: string;
|
|
10
|
-
run(args: string[], flags: Record<string, string | boolean>): Promise<void>;
|
|
11
|
-
}
|
|
12
|
-
export declare class CommandRunner {
|
|
13
|
-
#private;
|
|
14
|
-
register(command: Command): this;
|
|
15
|
-
handle(argv: string[]): Promise<void>;
|
|
16
|
-
getCommands(): Map<string, Command>;
|
|
17
|
-
}
|
|
18
|
-
//# sourceMappingURL=CommandRunner.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"CommandRunner.d.ts","sourceRoot":"","sources":["../../src/console/CommandRunner.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC5E;AAED,qBAAa,aAAa;;IAGxB,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAK1B,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IA2B3C,WAAW,IAAI,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC;CAGpC"}
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* CommandRunner — minimal CLI command framework.
|
|
3
|
-
*
|
|
4
|
-
* Registers commands and dispatches based on argv.
|
|
5
|
-
* Like AdonisJS Ace but lightweight.
|
|
6
|
-
*/
|
|
7
|
-
export class CommandRunner {
|
|
8
|
-
#commands = new Map();
|
|
9
|
-
register(command) {
|
|
10
|
-
this.#commands.set(command.name, command);
|
|
11
|
-
return this;
|
|
12
|
-
}
|
|
13
|
-
async handle(argv) {
|
|
14
|
-
const { commandName, args, flags } = parseArgv(argv);
|
|
15
|
-
if (!commandName || commandName === 'help') {
|
|
16
|
-
this.#printHelp();
|
|
17
|
-
return;
|
|
18
|
-
}
|
|
19
|
-
const command = this.#commands.get(commandName);
|
|
20
|
-
if (!command) {
|
|
21
|
-
console.error(`Unknown command: ${commandName}`);
|
|
22
|
-
console.error(`Run without arguments to see available commands.`);
|
|
23
|
-
process.exitCode = 1;
|
|
24
|
-
return;
|
|
25
|
-
}
|
|
26
|
-
await command.run(args, flags);
|
|
27
|
-
}
|
|
28
|
-
#printHelp() {
|
|
29
|
-
console.log('\nAvailable commands:\n');
|
|
30
|
-
for (const [name, cmd] of this.#commands) {
|
|
31
|
-
console.log(` ${name.padEnd(25)} ${cmd.description}`);
|
|
32
|
-
}
|
|
33
|
-
console.log('');
|
|
34
|
-
}
|
|
35
|
-
getCommands() {
|
|
36
|
-
return new Map(this.#commands);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
function parseArgv(argv) {
|
|
40
|
-
const flags = {};
|
|
41
|
-
const positional = [];
|
|
42
|
-
for (const arg of argv) {
|
|
43
|
-
if (arg.startsWith('--')) {
|
|
44
|
-
const eqIdx = arg.indexOf('=');
|
|
45
|
-
if (eqIdx !== -1) {
|
|
46
|
-
flags[arg.slice(2, eqIdx)] = arg.slice(eqIdx + 1);
|
|
47
|
-
}
|
|
48
|
-
else {
|
|
49
|
-
flags[arg.slice(2)] = true;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
else if (arg.startsWith('-') && arg.length === 2) {
|
|
53
|
-
flags[arg.slice(1)] = true;
|
|
54
|
-
}
|
|
55
|
-
else {
|
|
56
|
-
positional.push(arg);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
return {
|
|
60
|
-
commandName: positional[0],
|
|
61
|
-
args: positional.slice(1),
|
|
62
|
-
flags,
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
//# sourceMappingURL=CommandRunner.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"CommandRunner.js","sourceRoot":"","sources":["../../src/console/CommandRunner.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH,MAAM,OAAO,aAAa;IACxB,SAAS,GAAyB,IAAI,GAAG,EAAE,CAAA;IAE3C,QAAQ,CAAC,OAAgB;QACvB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;QACzC,OAAO,IAAI,CAAA;IACb,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,IAAc;QACzB,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,SAAS,CAAC,IAAI,CAAC,CAAA;QAEpD,IAAI,CAAC,WAAW,IAAI,WAAW,KAAK,MAAM,EAAE,CAAC;YAC3C,IAAI,CAAC,UAAU,EAAE,CAAA;YACjB,OAAM;QACR,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;QAC/C,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,oBAAoB,WAAW,EAAE,CAAC,CAAA;YAChD,OAAO,CAAC,KAAK,CAAC,kDAAkD,CAAC,CAAA;YACjE,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAA;YACpB,OAAM;QACR,CAAC;QAED,MAAM,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IAChC,CAAC;IAED,UAAU;QACR,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAA;QACtC,KAAK,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACzC,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC,CAAA;QACxD,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IACjB,CAAC;IAED,WAAW;QACT,OAAO,IAAI,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;IAChC,CAAC;CACF;AAED,SAAS,SAAS,CAAC,IAAc;IAK/B,MAAM,KAAK,GAAqC,EAAE,CAAA;IAClD,MAAM,UAAU,GAAa,EAAE,CAAA;IAE/B,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACzB,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;YAC9B,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE,CAAC;gBACjB,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAA;YACnD,CAAC;iBAAM,CAAC;gBACN,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAA;YAC5B,CAAC;QACH,CAAC;aAAM,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACnD,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAA;QAC5B,CAAC;aAAM,CAAC;YACN,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QACtB,CAAC;IACH,CAAC;IAED,OAAO;QACL,WAAW,EAAE,UAAU,CAAC,CAAC,CAAC;QAC1B,IAAI,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;QACzB,KAAK;KACN,CAAA;AACH,CAAC"}
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* CommandRunner — minimal CLI command framework.
|
|
3
|
-
*
|
|
4
|
-
* Registers commands and dispatches based on argv.
|
|
5
|
-
* Like AdonisJS Ace but lightweight.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
export interface Command {
|
|
9
|
-
name: string
|
|
10
|
-
description: string
|
|
11
|
-
run(args: string[], flags: Record<string, string | boolean>): Promise<void>
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export class CommandRunner {
|
|
15
|
-
#commands: Map<string, Command> = new Map()
|
|
16
|
-
|
|
17
|
-
register(command: Command): this {
|
|
18
|
-
this.#commands.set(command.name, command)
|
|
19
|
-
return this
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
async handle(argv: string[]): Promise<void> {
|
|
23
|
-
const { commandName, args, flags } = parseArgv(argv)
|
|
24
|
-
|
|
25
|
-
if (!commandName || commandName === 'help') {
|
|
26
|
-
this.#printHelp()
|
|
27
|
-
return
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const command = this.#commands.get(commandName)
|
|
31
|
-
if (!command) {
|
|
32
|
-
console.error(`Unknown command: ${commandName}`)
|
|
33
|
-
console.error(`Run without arguments to see available commands.`)
|
|
34
|
-
process.exitCode = 1
|
|
35
|
-
return
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
await command.run(args, flags)
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
#printHelp(): void {
|
|
42
|
-
console.log('\nAvailable commands:\n')
|
|
43
|
-
for (const [name, cmd] of this.#commands) {
|
|
44
|
-
console.log(` ${name.padEnd(25)} ${cmd.description}`)
|
|
45
|
-
}
|
|
46
|
-
console.log('')
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
getCommands(): Map<string, Command> {
|
|
50
|
-
return new Map(this.#commands)
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
function parseArgv(argv: string[]): {
|
|
55
|
-
commandName: string | undefined
|
|
56
|
-
args: string[]
|
|
57
|
-
flags: Record<string, string | boolean>
|
|
58
|
-
} {
|
|
59
|
-
const flags: Record<string, string | boolean> = {}
|
|
60
|
-
const positional: string[] = []
|
|
61
|
-
|
|
62
|
-
for (const arg of argv) {
|
|
63
|
-
if (arg.startsWith('--')) {
|
|
64
|
-
const eqIdx = arg.indexOf('=')
|
|
65
|
-
if (eqIdx !== -1) {
|
|
66
|
-
flags[arg.slice(2, eqIdx)] = arg.slice(eqIdx + 1)
|
|
67
|
-
} else {
|
|
68
|
-
flags[arg.slice(2)] = true
|
|
69
|
-
}
|
|
70
|
-
} else if (arg.startsWith('-') && arg.length === 2) {
|
|
71
|
-
flags[arg.slice(1)] = true
|
|
72
|
-
} else {
|
|
73
|
-
positional.push(arg)
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
return {
|
|
78
|
-
commandName: positional[0],
|
|
79
|
-
args: positional.slice(1),
|
|
80
|
-
flags,
|
|
81
|
-
}
|
|
82
|
-
}
|