@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
|
@@ -23,46 +23,39 @@ 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
|
-
}
|
|
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'
|
|
34
32
|
|
|
35
33
|
/**
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
34
|
+
* Named-route manifest — `name → path pattern`, e.g. `{ 'users.show':
|
|
35
|
+
* '/users/:id' }`. Feed `router.namedManifest()` here so `visit()` can resolve
|
|
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).
|
|
40
41
|
*/
|
|
41
|
-
export
|
|
42
|
-
|
|
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
|
-
}
|
|
42
|
+
export type RouteEntry = string | { path: string; method?: HttpMethod }
|
|
43
|
+
export type RouteManifest = Record<string, RouteEntry>
|
|
53
44
|
|
|
54
45
|
export class TestClient {
|
|
55
46
|
#port = 0
|
|
56
47
|
#headers: Dict = {}
|
|
57
48
|
#bootFn: (port: number) => Promise<{ port: number; close: () => Promise<void> | void }>
|
|
58
49
|
#auth: AuthStrategy | null
|
|
50
|
+
#routes: RouteManifest | null
|
|
59
51
|
|
|
60
52
|
constructor(
|
|
61
53
|
bootFn: (port: number) => Promise<{ port: number; close: () => Promise<void> | void }>,
|
|
62
|
-
options: { auth?: AuthStrategy } = {},
|
|
54
|
+
options: { auth?: AuthStrategy; routes?: RouteManifest } = {},
|
|
63
55
|
) {
|
|
64
56
|
this.#bootFn = bootFn
|
|
65
57
|
this.#auth = options.auth ?? null
|
|
58
|
+
this.#routes = options.routes ?? null
|
|
66
59
|
}
|
|
67
60
|
|
|
68
61
|
#server: { port: number; close: () => Promise<void> | void } | null = null
|
|
@@ -97,29 +90,47 @@ export class TestClient {
|
|
|
97
90
|
return this
|
|
98
91
|
}
|
|
99
92
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
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)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** POST request — rich, awaitable builder. */
|
|
104
|
+
post(path: string): RequestBuilder {
|
|
105
|
+
return this.fluent('POST', path)
|
|
103
106
|
}
|
|
104
107
|
|
|
105
|
-
/**
|
|
106
|
-
|
|
107
|
-
return this.
|
|
108
|
+
/** PUT request — rich, awaitable builder. */
|
|
109
|
+
put(path: string): RequestBuilder {
|
|
110
|
+
return this.fluent('PUT', path)
|
|
108
111
|
}
|
|
109
112
|
|
|
110
|
-
/**
|
|
111
|
-
|
|
112
|
-
return this.
|
|
113
|
+
/** PATCH request — rich, awaitable builder. */
|
|
114
|
+
patch(path: string): RequestBuilder {
|
|
115
|
+
return this.fluent('PATCH', path)
|
|
113
116
|
}
|
|
114
117
|
|
|
115
|
-
/**
|
|
116
|
-
|
|
117
|
-
return this.
|
|
118
|
+
/** DELETE request — rich, awaitable builder. */
|
|
119
|
+
delete(path: string): RequestBuilder {
|
|
120
|
+
return this.fluent('DELETE', path)
|
|
118
121
|
}
|
|
119
122
|
|
|
120
|
-
/**
|
|
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)
|
|
123
134
|
}
|
|
124
135
|
|
|
125
136
|
/**
|
|
@@ -136,49 +147,37 @@ export class TestClient {
|
|
|
136
147
|
p,
|
|
137
148
|
{ ...this.#headers, ...init.headers },
|
|
138
149
|
init.body.toString('utf8'),
|
|
150
|
+
init.timeoutMs,
|
|
139
151
|
)
|
|
140
152
|
return new RequestBuilder(sender, method, path, this.#auth)
|
|
141
153
|
}
|
|
142
154
|
|
|
143
|
-
/**
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
json(data: unknown) {
|
|
155
|
-
bodyContent = JSON.stringify(data)
|
|
156
|
-
headers['content-type'] = 'application/json'
|
|
157
|
-
return builder
|
|
158
|
-
},
|
|
159
|
-
body(content: string, contentType?: string) {
|
|
160
|
-
bodyContent = content
|
|
161
|
-
if (contentType) headers['content-type'] = contentType
|
|
162
|
-
return builder
|
|
163
|
-
},
|
|
164
|
-
cookie(name: string, value: string) {
|
|
165
|
-
cookies.push(`${name}=${value}`)
|
|
166
|
-
return builder
|
|
167
|
-
},
|
|
168
|
-
send: async () => {
|
|
169
|
-
if (cookies.length > 0) {
|
|
170
|
-
headers.cookie = cookies.join('; ')
|
|
171
|
-
}
|
|
172
|
-
return sendRequest(this.#port, method, path, headers, bodyContent)
|
|
173
|
-
},
|
|
174
|
-
// Thenable: `await client.get('/x')` (or any builder) sends the request,
|
|
175
|
-
// matching AdonisJS/japa's api-client ergonomics. The `then` IS the public
|
|
176
|
-
// contract here — awaiting the builder is the documented way to send.
|
|
177
|
-
// biome-ignore lint/suspicious/noThenProperty: thenable request builder is the intended API (AdonisJS/japa parity) — `await client.get(path)` sends
|
|
178
|
-
then: (onfulfilled, onrejected) => builder.send().then(onfulfilled, onrejected),
|
|
155
|
+
/**
|
|
156
|
+
* GET a named route — japa/api-client's `.visit()`. Resolves `name` against
|
|
157
|
+
* the `routes` manifest (`router.namedManifest()`), fills `:param`
|
|
158
|
+
* placeholders, and returns the rich chainable builder. Throws a clear error
|
|
159
|
+
* when no manifest was configured or the name is unknown.
|
|
160
|
+
*/
|
|
161
|
+
visit(name: string, params?: Record<string, string>): RequestBuilder {
|
|
162
|
+
if (!this.#routes) {
|
|
163
|
+
throw new Error(
|
|
164
|
+
'TestClient: visit() needs a named-route manifest. Pass `routes: router.namedManifest()` in the client options.',
|
|
165
|
+
)
|
|
179
166
|
}
|
|
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))
|
|
172
|
+
}
|
|
180
173
|
|
|
181
|
-
|
|
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)
|
|
182
181
|
}
|
|
183
182
|
}
|
|
184
183
|
|
|
@@ -198,9 +197,41 @@ export {
|
|
|
198
197
|
type HttpMethod,
|
|
199
198
|
type HttpSender,
|
|
200
199
|
partialMatch,
|
|
200
|
+
type QueryParams,
|
|
201
201
|
RequestBuilder,
|
|
202
202
|
} from './RequestBuilder.js'
|
|
203
203
|
|
|
204
|
+
/**
|
|
205
|
+
* Resolve a named route against a manifest — the client-side twin of
|
|
206
|
+
* `Router.urlFor`. Fills `:param` placeholders (word-boundary safe), strips
|
|
207
|
+
* unprovided `:optional?` segments, and throws on an unknown name or a missing
|
|
208
|
+
* required param.
|
|
209
|
+
*/
|
|
210
|
+
export function resolveNamedRoute(
|
|
211
|
+
manifest: RouteManifest,
|
|
212
|
+
name: string,
|
|
213
|
+
params?: Record<string, string>,
|
|
214
|
+
): string {
|
|
215
|
+
const entry = manifest[name]
|
|
216
|
+
if (entry === undefined) {
|
|
217
|
+
const available = Object.keys(manifest).join(', ') || '(none)'
|
|
218
|
+
throw new Error(`Route '${name}' not found. Available: ${available}`)
|
|
219
|
+
}
|
|
220
|
+
let url = typeof entry === 'string' ? entry : entry.path
|
|
221
|
+
if (params) {
|
|
222
|
+
for (const [key, value] of Object.entries(params)) {
|
|
223
|
+
const escaped = key.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
224
|
+
url = url.replace(new RegExp(`:${escaped}\\??(?![\\w])`, 'g'), encodeURIComponent(value))
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
url = url.replace(/\/:[A-Za-z_][\w]*\?/g, '')
|
|
228
|
+
const missing = url.match(/:[A-Za-z_][\w]*/g)
|
|
229
|
+
if (missing && missing.length > 0) {
|
|
230
|
+
throw new Error(`Cannot generate URL for route '${name}': missing params ${missing.join(', ')}`)
|
|
231
|
+
}
|
|
232
|
+
return url
|
|
233
|
+
}
|
|
234
|
+
|
|
204
235
|
/** Send an HTTP request using raw TCP (no external dependencies). */
|
|
205
236
|
async function sendRequest(
|
|
206
237
|
port: number,
|
|
@@ -208,6 +239,7 @@ async function sendRequest(
|
|
|
208
239
|
path: string,
|
|
209
240
|
headers: Dict,
|
|
210
241
|
body: string,
|
|
242
|
+
timeoutMs?: number,
|
|
211
243
|
): Promise<TestResponse> {
|
|
212
244
|
const { connect } = await import('node:net')
|
|
213
245
|
|
|
@@ -253,8 +285,9 @@ async function sendRequest(
|
|
|
253
285
|
// tokio runtimes) the cumulative latency exceeded 5s ~30% of runs
|
|
254
286
|
// and surfaced as flaky `bob accepts` / `non-member 403` failures
|
|
255
287
|
// in kitchen-sink's workspace.test.ts. 30s matches the helix
|
|
256
|
-
// `--timeout=60000` per-test budget without masking real hangs.
|
|
257
|
-
|
|
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, () => {
|
|
258
291
|
socket.destroy()
|
|
259
292
|
reject(new Error('TestClient request timed out'))
|
|
260
293
|
})
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Macroable — lets a package extend a class at runtime with extra methods
|
|
3
|
+
* (`macro`) and computed properties (`getter`), AdonisJS-style. A framework
|
|
4
|
+
* class (Request, Response, HttpContext, Router, …) extends this so an add-on
|
|
5
|
+
* can attach behaviour without a subclass:
|
|
6
|
+
*
|
|
7
|
+
* Request.macro('wantsJson', function () { return this.accepts(['json']) === 'json' })
|
|
8
|
+
* HttpContext.getter('tenant', function () { return resolveTenant(this) })
|
|
9
|
+
*
|
|
10
|
+
* TypeScript sees only the base class; consumers type their macros with
|
|
11
|
+
* declaration merging (`declare module`) exactly as in AdonisJS.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* A macro method. When invoked, `this` is the instance it's attached to —
|
|
16
|
+
* declare it explicitly in your callback (`function (this: Request) { … }`) to
|
|
17
|
+
* type the receiver; the alias itself leaves `this` open so any class fits.
|
|
18
|
+
*/
|
|
19
|
+
export type MacroFn = (...args: unknown[]) => unknown
|
|
20
|
+
|
|
21
|
+
/** A getter implementation — declare `this` in your callback to type the receiver. */
|
|
22
|
+
export type GetterFn = () => unknown
|
|
23
|
+
|
|
24
|
+
export class Macroable {
|
|
25
|
+
/** Attach a method to every instance of this class (AdonisJS `macro`). */
|
|
26
|
+
static macro(name: string, fn: MacroFn): void {
|
|
27
|
+
Object.defineProperty(Macroable.prototype, name, {
|
|
28
|
+
value: fn,
|
|
29
|
+
writable: true,
|
|
30
|
+
configurable: true,
|
|
31
|
+
})
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Attach a computed property to every instance (AdonisJS `getter`). With
|
|
36
|
+
* `singleton`, the value is computed once per instance and cached.
|
|
37
|
+
*/
|
|
38
|
+
static getter(name: string, fn: GetterFn, singleton = false): void {
|
|
39
|
+
if (!singleton) {
|
|
40
|
+
Object.defineProperty(Macroable.prototype, name, { get: fn, configurable: true })
|
|
41
|
+
return
|
|
42
|
+
}
|
|
43
|
+
const cacheKey = Symbol(name)
|
|
44
|
+
Object.defineProperty(Macroable.prototype, name, {
|
|
45
|
+
configurable: true,
|
|
46
|
+
get(this: Record<symbol, unknown>) {
|
|
47
|
+
if (!(cacheKey in this)) {
|
|
48
|
+
Object.defineProperty(this, cacheKey, { value: fn.call(this), configurable: true })
|
|
49
|
+
}
|
|
50
|
+
return this[cacheKey]
|
|
51
|
+
},
|
|
52
|
+
})
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal zero-dependency string inflection — the two operations resourceful
|
|
3
|
+
* routing needs from AdonisJS's `@poppinss/utils/string`: `snakeCase` (route
|
|
4
|
+
* name normalisation) and `singular` (nested-resource param naming, `photos`
|
|
5
|
+
* → `photo_id`).
|
|
6
|
+
*
|
|
7
|
+
* Deviation from AdonisJS (named): `singular` covers regular English plurals
|
|
8
|
+
* only (`-ies→-y`, `-(s|x|z|ch|sh)es→drop es`, trailing `-s→drop`). Irregular
|
|
9
|
+
* plurals (`people→person`, `geese→goose`) are NOT handled — resource names in
|
|
10
|
+
* REST APIs are overwhelmingly regular, and a full inflector (irregular tables,
|
|
11
|
+
* uncountables) would be a dependency-sized rabbit hole for a niche case.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/** Convert `camelCase`/`PascalCase`/`kebab-case`/spaced text to `snake_case`. */
|
|
15
|
+
export function snakeCase(value: string): string {
|
|
16
|
+
return value
|
|
17
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1_$2')
|
|
18
|
+
.replace(/[-\s]+/g, '_')
|
|
19
|
+
.toLowerCase()
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Singularize a regular English plural (see module deviation note). */
|
|
23
|
+
export function singular(word: string): string {
|
|
24
|
+
if (word.length > 3 && /ies$/i.test(word)) return word.replace(/ies$/i, 'y')
|
|
25
|
+
if (/(?:s|x|z|ch|sh)es$/i.test(word)) return word.replace(/es$/i, '')
|
|
26
|
+
if (/ss$/i.test(word)) return word
|
|
27
|
+
if (/s$/i.test(word)) return word.replace(/s$/i, '')
|
|
28
|
+
return word
|
|
29
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zero-dependency dot-path object access — the small subset of `lodash`
|
|
3
|
+
* (`get`/`set`/`has`/`pick`/`omit`/`merge`) that Config and Request need for
|
|
4
|
+
* AdonisJS-parity nested access (`config.get('database.mysql.host')`,
|
|
5
|
+
* `request.input('user.address.city')`).
|
|
6
|
+
*
|
|
7
|
+
* AdonisJS uses `@poppinss/utils/lodash` for this. Ream stays lean and
|
|
8
|
+
* dependency-free (same stance as aurora's hand-written `cn`/`clsx`), so we
|
|
9
|
+
* reimplement exactly the four semantics we rely on — no more.
|
|
10
|
+
*
|
|
11
|
+
* Path syntax: `a.b.c` and `a[0].c` / `a.0.c` (bracket + dotted indices) are
|
|
12
|
+
* both accepted, matching lodash's tokenizer for the shapes config/request
|
|
13
|
+
* data actually take (plain JSON objects and arrays).
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/** A JSON-ish record we can index by string key. */
|
|
17
|
+
type UnknownRecord = Record<string, unknown>
|
|
18
|
+
|
|
19
|
+
/** True for plain objects and arrays (anything indexable by a path segment). */
|
|
20
|
+
function isIndexable(value: unknown): value is UnknownRecord {
|
|
21
|
+
return typeof value === 'object' && value !== null
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Split a dot/bracket path into segments: `a.b[0].c` → `['a','b','0','c']`.
|
|
26
|
+
* A single already-simple key (no `.`/`[`) is returned as-is, so keys that
|
|
27
|
+
* happen to contain neither delimiter cost nothing.
|
|
28
|
+
*/
|
|
29
|
+
function toSegments(path: string): string[] {
|
|
30
|
+
if (path.indexOf('.') === -1 && path.indexOf('[') === -1) return [path]
|
|
31
|
+
const segments: string[] = []
|
|
32
|
+
const matcher = /[^.[\]]+/g
|
|
33
|
+
let match: RegExpExecArray | null = matcher.exec(path)
|
|
34
|
+
while (match !== null) {
|
|
35
|
+
segments.push(match[0])
|
|
36
|
+
match = matcher.exec(path)
|
|
37
|
+
}
|
|
38
|
+
return segments
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Read a nested value by dot-path. Returns `defaultValue` when any segment is
|
|
43
|
+
* missing or the resolved value is `undefined` (lodash.get semantics).
|
|
44
|
+
*/
|
|
45
|
+
export function getPath(source: unknown, path: string, defaultValue?: unknown): unknown {
|
|
46
|
+
const segments = toSegments(path)
|
|
47
|
+
let current: unknown = source
|
|
48
|
+
for (const segment of segments) {
|
|
49
|
+
if (!isIndexable(current)) return defaultValue
|
|
50
|
+
current = current[segment]
|
|
51
|
+
}
|
|
52
|
+
return current === undefined ? defaultValue : current
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* True when the full dot-path exists on `source` (each segment is an own key),
|
|
57
|
+
* even if the leaf value is `undefined` (lodash.has semantics).
|
|
58
|
+
*/
|
|
59
|
+
export function hasPath(source: unknown, path: string): boolean {
|
|
60
|
+
const segments = toSegments(path)
|
|
61
|
+
let current: unknown = source
|
|
62
|
+
for (const segment of segments) {
|
|
63
|
+
if (!isIndexable(current) || !Object.hasOwn(current, segment)) return false
|
|
64
|
+
current = current[segment]
|
|
65
|
+
}
|
|
66
|
+
return true
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Set a nested value by dot-path, creating intermediate plain objects as
|
|
71
|
+
* needed, and return the (mutated) root.
|
|
72
|
+
*
|
|
73
|
+
* Deviation from lodash.set (named): integer segments create plain objects,
|
|
74
|
+
* NOT arrays. Config trees and request-data picks are keyed objects; ream
|
|
75
|
+
* never sets array indices through a path, so array auto-vivification would be
|
|
76
|
+
* dead behaviour.
|
|
77
|
+
*/
|
|
78
|
+
export function setPath(target: UnknownRecord, path: string, value: unknown): UnknownRecord {
|
|
79
|
+
const segments = toSegments(path)
|
|
80
|
+
let current: UnknownRecord = target
|
|
81
|
+
for (let i = 0; i < segments.length - 1; i += 1) {
|
|
82
|
+
const key = segments[i]
|
|
83
|
+
const next = current[key]
|
|
84
|
+
if (!isIndexable(next)) {
|
|
85
|
+
const created: UnknownRecord = {}
|
|
86
|
+
current[key] = created
|
|
87
|
+
current = created
|
|
88
|
+
} else {
|
|
89
|
+
current = next
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
current[segments[segments.length - 1]] = value
|
|
93
|
+
return target
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Return a new object containing only the given dot-paths (lodash.pick).
|
|
98
|
+
* Missing paths are skipped; nested paths reconstruct their branch, so
|
|
99
|
+
* `pickPaths({a:{b:1,c:2}}, ['a.b'])` yields `{a:{b:1}}`.
|
|
100
|
+
*/
|
|
101
|
+
export function pickPaths(source: unknown, paths: string[]): UnknownRecord {
|
|
102
|
+
const result: UnknownRecord = {}
|
|
103
|
+
for (const path of paths) {
|
|
104
|
+
if (hasPath(source, path)) setPath(result, path, getPath(source, path))
|
|
105
|
+
}
|
|
106
|
+
return result
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Return a deep clone of `source` with the given dot-paths removed
|
|
111
|
+
* (lodash.omit). Operates on JSON-ish data (body + query), so `structuredClone`
|
|
112
|
+
* is a safe deep copy that never mutates the caller's input.
|
|
113
|
+
*/
|
|
114
|
+
export function omitPaths(source: UnknownRecord, paths: string[]): UnknownRecord {
|
|
115
|
+
const result = structuredClone(source)
|
|
116
|
+
for (const path of paths) {
|
|
117
|
+
const segments = toSegments(path)
|
|
118
|
+
let current: unknown = result
|
|
119
|
+
for (let i = 0; i < segments.length - 1; i += 1) {
|
|
120
|
+
if (!isIndexable(current)) break
|
|
121
|
+
current = current[segments[i]]
|
|
122
|
+
}
|
|
123
|
+
if (isIndexable(current)) delete current[segments[segments.length - 1]]
|
|
124
|
+
}
|
|
125
|
+
return result
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Deep-merge `source` over `target` (recursively for nested plain objects;
|
|
130
|
+
* scalars and arrays from `source` replace `target`). Returns a new object;
|
|
131
|
+
* neither input is mutated. Backs `Config.defaults` — the AdonisJS semantics
|
|
132
|
+
* where existing config wins over provided defaults.
|
|
133
|
+
*/
|
|
134
|
+
export function mergeDeep(target: unknown, source: unknown): unknown {
|
|
135
|
+
if (!isIndexable(target) || Array.isArray(target)) return source === undefined ? target : source
|
|
136
|
+
if (!isIndexable(source) || Array.isArray(source)) return source === undefined ? target : source
|
|
137
|
+
const out: UnknownRecord = { ...target }
|
|
138
|
+
for (const key of Object.keys(source)) {
|
|
139
|
+
out[key] = mergeDeep(out[key], source[key])
|
|
140
|
+
}
|
|
141
|
+
return out
|
|
142
|
+
}
|
|
@@ -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,19 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @Lazy() decorator — deferred injection to break circular dependencies.
|
|
3
|
-
*
|
|
4
|
-
* @implements FR15
|
|
5
|
-
*/
|
|
6
|
-
import 'reflect-metadata';
|
|
7
|
-
/**
|
|
8
|
-
* @Lazy() — marks a constructor parameter for deferred resolution.
|
|
9
|
-
* The dependency is resolved on first property access, not at construction.
|
|
10
|
-
*/
|
|
11
|
-
export declare function Lazy(): ParameterDecorator;
|
|
12
|
-
/** Get lazy parameter indices for a constructor. */
|
|
13
|
-
export declare function getLazyParams(target: object): number[];
|
|
14
|
-
/**
|
|
15
|
-
* Create a lazy proxy that defers resolution until first access.
|
|
16
|
-
* Traps get, set, has, ownKeys, getOwnPropertyDescriptor for full compatibility.
|
|
17
|
-
*/
|
|
18
|
-
export declare function createLazyProxy<T extends object>(resolver: () => T): T;
|
|
19
|
-
//# sourceMappingURL=Lazy.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Lazy.d.ts","sourceRoot":"","sources":["../../src/decorators/Lazy.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,kBAAkB,CAAA;AAIzB;;;GAGG;AACH,wBAAgB,IAAI,IAAI,kBAAkB,CAMzC;AAED,oDAAoD;AACpD,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAEtD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC,CAyBtE"}
|
package/dist/decorators/Lazy.js
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @Lazy() decorator — deferred injection to break circular dependencies.
|
|
3
|
-
*
|
|
4
|
-
* @implements FR15
|
|
5
|
-
*/
|
|
6
|
-
import 'reflect-metadata';
|
|
7
|
-
const LAZY_KEY = Symbol.for('ream:lazy');
|
|
8
|
-
/**
|
|
9
|
-
* @Lazy() — marks a constructor parameter for deferred resolution.
|
|
10
|
-
* The dependency is resolved on first property access, not at construction.
|
|
11
|
-
*/
|
|
12
|
-
export function Lazy() {
|
|
13
|
-
return (target, propertyKey, parameterIndex) => {
|
|
14
|
-
const existing = Reflect.getOwnMetadata(LAZY_KEY, target, propertyKey ?? '') ?? [];
|
|
15
|
-
existing.push(parameterIndex);
|
|
16
|
-
Reflect.defineMetadata(LAZY_KEY, existing, target, propertyKey ?? '');
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
/** Get lazy parameter indices for a constructor. */
|
|
20
|
-
export function getLazyParams(target) {
|
|
21
|
-
return Reflect.getOwnMetadata(LAZY_KEY, target, '') ?? [];
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Create a lazy proxy that defers resolution until first access.
|
|
25
|
-
* Traps get, set, has, ownKeys, getOwnPropertyDescriptor for full compatibility.
|
|
26
|
-
*/
|
|
27
|
-
export function createLazyProxy(resolver) {
|
|
28
|
-
let instance;
|
|
29
|
-
const ensure = () => {
|
|
30
|
-
if (!instance)
|
|
31
|
-
instance = resolver();
|
|
32
|
-
return instance;
|
|
33
|
-
};
|
|
34
|
-
// biome-ignore lint/suspicious/noExplicitAny: Proxy target must be an object literal; T is branded at call site
|
|
35
|
-
return new Proxy({}, {
|
|
36
|
-
get(_target, prop, receiver) {
|
|
37
|
-
return Reflect.get(ensure(), prop, receiver);
|
|
38
|
-
},
|
|
39
|
-
set(_target, prop, value, receiver) {
|
|
40
|
-
return Reflect.set(ensure(), prop, value, receiver);
|
|
41
|
-
},
|
|
42
|
-
has(_target, prop) {
|
|
43
|
-
return Reflect.has(ensure(), prop);
|
|
44
|
-
},
|
|
45
|
-
ownKeys() {
|
|
46
|
-
return Reflect.ownKeys(ensure());
|
|
47
|
-
},
|
|
48
|
-
getOwnPropertyDescriptor(_target, prop) {
|
|
49
|
-
return Object.getOwnPropertyDescriptor(ensure(), prop);
|
|
50
|
-
},
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
//# sourceMappingURL=Lazy.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Lazy.js","sourceRoot":"","sources":["../../src/decorators/Lazy.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,kBAAkB,CAAA;AAEzB,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;AAExC;;;GAGG;AACH,MAAM,UAAU,IAAI;IAClB,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,cAAc,EAAE,EAAE;QAC7C,MAAM,QAAQ,GAAa,OAAO,CAAC,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,IAAI,EAAE,CAAC,IAAI,EAAE,CAAA;QAC5F,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,CAAA;QAC7B,OAAO,CAAC,cAAc,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,IAAI,EAAE,CAAC,CAAA;IACvE,CAAC,CAAA;AACH,CAAC;AAED,oDAAoD;AACpD,MAAM,UAAU,aAAa,CAAC,MAAc;IAC1C,OAAO,OAAO,CAAC,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,CAAC,IAAI,EAAE,CAAA;AAC3D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAmB,QAAiB;IACjE,IAAI,QAAuB,CAAA;IAC3B,MAAM,MAAM,GAAG,GAAM,EAAE;QACrB,IAAI,CAAC,QAAQ;YAAE,QAAQ,GAAG,QAAQ,EAAE,CAAA;QACpC,OAAO,QAAQ,CAAA;IACjB,CAAC,CAAA;IAED,gHAAgH;IAChH,OAAO,IAAI,KAAK,CAAC,EAAc,EAAE;QAC/B,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,QAAQ;YACzB,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAA;QAC9C,CAAC;QACD,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ;YAChC,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAA;QACrD,CAAC;QACD,GAAG,CAAC,OAAO,EAAE,IAAI;YACf,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,IAAI,CAAC,CAAA;QACpC,CAAC;QACD,OAAO;YACL,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;QAClC,CAAC;QACD,wBAAwB,CAAC,OAAO,EAAE,IAAI;YACpC,OAAO,MAAM,CAAC,wBAAwB,CAAC,MAAM,EAAE,EAAE,IAAI,CAAC,CAAA;QACxD,CAAC;KACF,CAAC,CAAA;AACJ,CAAC"}
|