@mxweb/core 1.0.2 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +229 -0
- package/dist/application.d.ts +88 -27
- package/dist/application.js +1 -1
- package/dist/application.mjs +1 -1
- package/dist/common.d.ts +50 -3
- package/dist/config.d.ts +18 -0
- package/dist/config.js +1 -1
- package/dist/config.mjs +1 -1
- package/dist/decorator.d.ts +11 -4
- package/dist/execute.d.ts +312 -58
- package/dist/execute.js +1 -1
- package/dist/execute.mjs +1 -1
- package/dist/feature.d.ts +9 -7
- package/dist/feature.js +1 -1
- package/dist/feature.mjs +1 -1
- package/dist/hooks.d.ts +5 -6
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/dist/logger.js +1 -1
- package/dist/logger.mjs +1 -1
- package/dist/response.d.ts +297 -227
- package/dist/response.js +1 -1
- package/dist/response.mjs +1 -1
- package/dist/route.d.ts +107 -3
- package/dist/route.js +1 -1
- package/dist/route.mjs +1 -1
- package/dist/service.d.ts +9 -8
- package/package.json +1 -6
package/dist/config.d.ts
CHANGED
|
@@ -272,4 +272,22 @@ export declare class Config implements ApplicationInject {
|
|
|
272
272
|
* ```
|
|
273
273
|
*/
|
|
274
274
|
reset(): void;
|
|
275
|
+
/**
|
|
276
|
+
* Returns the Config instance itself for context switching.
|
|
277
|
+
* Allows accessing Config via `context.switch("config")`.
|
|
278
|
+
*
|
|
279
|
+
* @template T - The expected return type (defaults to Config)
|
|
280
|
+
* @returns The Config instance
|
|
281
|
+
*
|
|
282
|
+
* @example
|
|
283
|
+
* ```ts
|
|
284
|
+
* // In a controller or service
|
|
285
|
+
* const config = await this.context.switch<Config>("config");
|
|
286
|
+
* const dbHost = config.get<string>("db.host");
|
|
287
|
+
*
|
|
288
|
+
* // Or access config values directly
|
|
289
|
+
* const port = config.get<number>("port", 3000);
|
|
290
|
+
* ```
|
|
291
|
+
*/
|
|
292
|
+
switch<T = Config>(): T;
|
|
275
293
|
}
|
package/dist/config.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";class t{static forRoot(r="config"){return s=>{s.set(r,()=>(t.instance||(t.instance=new t),t.instance))}}async onInit(){await t.buildAsync()}static register(r,s){return t.providers.set(r,s),t}static registerAsync(r,s){return t.asyncProviders.set(r,s),t}static build(){if(!t.built){for(const[r,s]of t.providers)t.store.has(r)||t.store.set(r,s());t.built=!0}}static async buildAsync(){if(t.build(),!t.asyncBuilt){for(const[r,s]of t.asyncProviders)t.store.has(r)||t.store.set(r,await s());t.asyncBuilt=!0}}get(r,s){return t.build(),t.store.get(r)??s}async getAsync(r,s){return await t.buildAsync(),t.store.get(r)??s}getOrThrow(r){if(t.build(),!t.store.has(r))throw new Error(`[Config] Config key "${r}" not found`);return t.store.get(r)}async getAsyncOrThrow(r){if(await t.buildAsync(),!t.store.has(r))throw new Error(`[Config] Config key "${r}" not found`);return t.store.get(r)}has(r){return t.store.has(r)||t.providers.has(r)||t.asyncProviders.has(r)}getAll(){return new Map(t.store)}reset(){t.instance=null,t.store.clear(),t.providers.clear(),t.asyncProviders.clear(),t.built=!1,t.asyncBuilt=!1}}t.instance=null,t.store=new Map,t.providers=new Map,t.asyncProviders=new Map,t.built=!1,t.asyncBuilt=!1,exports.Config=t;
|
|
1
|
+
"use strict";class t{static forRoot(r="config"){return s=>{s.set(r,()=>(t.instance||(t.instance=new t),t.instance))}}async onInit(){await t.buildAsync()}static register(r,s){return t.providers.set(r,s),t}static registerAsync(r,s){return t.asyncProviders.set(r,s),t}static build(){if(!t.built){for(const[r,s]of t.providers)t.store.has(r)||t.store.set(r,s());t.built=!0}}static async buildAsync(){if(t.build(),!t.asyncBuilt){for(const[r,s]of t.asyncProviders)t.store.has(r)||t.store.set(r,await s());t.asyncBuilt=!0}}get(r,s){return t.build(),t.store.get(r)??s}async getAsync(r,s){return await t.buildAsync(),t.store.get(r)??s}getOrThrow(r){if(t.build(),!t.store.has(r))throw new Error(`[Config] Config key "${r}" not found`);return t.store.get(r)}async getAsyncOrThrow(r){if(await t.buildAsync(),!t.store.has(r))throw new Error(`[Config] Config key "${r}" not found`);return t.store.get(r)}has(r){return t.store.has(r)||t.providers.has(r)||t.asyncProviders.has(r)}getAll(){return new Map(t.store)}reset(){t.instance=null,t.store.clear(),t.providers.clear(),t.asyncProviders.clear(),t.built=!1,t.asyncBuilt=!1}switch(){return this}}t.instance=null,t.store=new Map,t.providers=new Map,t.asyncProviders=new Map,t.built=!1,t.asyncBuilt=!1,exports.Config=t;
|
package/dist/config.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
class
|
|
1
|
+
class t{static forRoot(r="config"){return s=>{s.set(r,()=>(t.instance||(t.instance=new t),t.instance))}}async onInit(){await t.buildAsync()}static register(r,s){return t.providers.set(r,s),t}static registerAsync(r,s){return t.asyncProviders.set(r,s),t}static build(){if(!t.built){for(const[r,s]of t.providers)t.store.has(r)||t.store.set(r,s());t.built=!0}}static async buildAsync(){if(t.build(),!t.asyncBuilt){for(const[r,s]of t.asyncProviders)t.store.has(r)||t.store.set(r,await s());t.asyncBuilt=!0}}get(r,s){return t.build(),t.store.get(r)??s}async getAsync(r,s){return await t.buildAsync(),t.store.get(r)??s}getOrThrow(r){if(t.build(),!t.store.has(r))throw new Error(`[Config] Config key "${r}" not found`);return t.store.get(r)}async getAsyncOrThrow(r){if(await t.buildAsync(),!t.store.has(r))throw new Error(`[Config] Config key "${r}" not found`);return t.store.get(r)}has(r){return t.store.has(r)||t.providers.has(r)||t.asyncProviders.has(r)}getAll(){return new Map(t.store)}reset(){t.instance=null,t.store.clear(),t.providers.clear(),t.asyncProviders.clear(),t.built=!1,t.asyncBuilt=!1}switch(){return this}}t.instance=null,t.store=new Map,t.providers=new Map,t.asyncProviders=new Map,t.built=!1,t.asyncBuilt=!1;export{t as Config};
|
package/dist/decorator.d.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*
|
|
9
9
|
* @module decorator
|
|
10
10
|
*/
|
|
11
|
-
import { ExecuteContext, Filter, Guard, Interceptor } from "./execute";
|
|
11
|
+
import { CoreRequest, ExecuteContext, Filter, Guard, Interceptor } from "./execute";
|
|
12
12
|
import { FeatureInject, Pipe } from "./common";
|
|
13
13
|
/**
|
|
14
14
|
* Result object from decorator functions.
|
|
@@ -234,18 +234,25 @@ export declare function QueryParam(key: string): string | undefined;
|
|
|
234
234
|
/**
|
|
235
235
|
* Extracts the raw Request object.
|
|
236
236
|
*
|
|
237
|
-
* @
|
|
237
|
+
* @template T - The specific request type (e.g., NextRequest, Express.Request)
|
|
238
|
+
* @returns The underlying CoreRequest object, cast to the specified type
|
|
238
239
|
*
|
|
239
240
|
* @example
|
|
240
241
|
* ```ts
|
|
242
|
+
* // Default (CoreRequest)
|
|
241
243
|
* findAll() {
|
|
242
244
|
* const request = Request();
|
|
243
245
|
* const url = request.url;
|
|
244
|
-
*
|
|
246
|
+
* }
|
|
247
|
+
*
|
|
248
|
+
* // With specific type (Next.js)
|
|
249
|
+
* findAll() {
|
|
250
|
+
* const request = Request<NextRequest>();
|
|
251
|
+
* const nextUrl = request.nextUrl; // ✅ Type-safe
|
|
245
252
|
* }
|
|
246
253
|
* ```
|
|
247
254
|
*/
|
|
248
|
-
export declare function Request():
|
|
255
|
+
export declare function Request<T extends CoreRequest = CoreRequest>(): T;
|
|
249
256
|
/**
|
|
250
257
|
* Extracts and parses FormData from the request body.
|
|
251
258
|
*
|
package/dist/execute.d.ts
CHANGED
|
@@ -8,10 +8,226 @@
|
|
|
8
8
|
*
|
|
9
9
|
* @module execute
|
|
10
10
|
*/
|
|
11
|
-
import { NextRequest } from "next/server";
|
|
12
11
|
import { ServerResponse } from "./response";
|
|
13
12
|
import { Feature } from "./feature";
|
|
14
|
-
import { ApplicationInject,
|
|
13
|
+
import { ApplicationInject, InjectEntry, InjectInstanceFactory, InjectRegistry, Pipe, RouteMethod, RouteNextHandler } from "./common";
|
|
14
|
+
/**
|
|
15
|
+
* Core request interface defining the minimal contract for HTTP requests.
|
|
16
|
+
* This abstraction allows @mxweb/core to work with any request implementation
|
|
17
|
+
* (Next.js, Express, Fastify, etc.) as long as it conforms to this interface.
|
|
18
|
+
*
|
|
19
|
+
* @remarks
|
|
20
|
+
* This interface is designed to be compatible with multiple frameworks:
|
|
21
|
+
* - **Next.js**: Uses `nextUrl` for query params
|
|
22
|
+
* - **Express/Fastify**: Uses `url` (string) and `query` (parsed object)
|
|
23
|
+
* - **Fetch API**: Uses `url` (URL object)
|
|
24
|
+
*
|
|
25
|
+
* The framework adapter should populate the appropriate properties.
|
|
26
|
+
* `switchHttp().query()` will use `nextUrl.searchParams` → `url.searchParams` → `query` fallback.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```ts
|
|
30
|
+
* // Next.js Request is compatible with CoreRequest (uses nextUrl)
|
|
31
|
+
* const coreReq: CoreRequest = nextRequest;
|
|
32
|
+
*
|
|
33
|
+
* // Express Request adapter
|
|
34
|
+
* const expressReq: CoreRequest = {
|
|
35
|
+
* url: "/api/users?page=1",
|
|
36
|
+
* query: { page: "1" },
|
|
37
|
+
* headers: new Headers(req.headers),
|
|
38
|
+
* body: null,
|
|
39
|
+
* json: async () => req.body,
|
|
40
|
+
* text: async () => JSON.stringify(req.body),
|
|
41
|
+
* formData: async () => new FormData(),
|
|
42
|
+
* blob: async () => new Blob(),
|
|
43
|
+
* arrayBuffer: async () => new ArrayBuffer(0),
|
|
44
|
+
* };
|
|
45
|
+
*
|
|
46
|
+
* // Fetch Request adapter
|
|
47
|
+
* const fetchReq: CoreRequest = {
|
|
48
|
+
* url: new URL("https://example.com/api/users?page=1"),
|
|
49
|
+
* headers: request.headers,
|
|
50
|
+
* body: request.body,
|
|
51
|
+
* json: () => request.json(),
|
|
52
|
+
* text: () => request.text(),
|
|
53
|
+
* formData: () => request.formData(),
|
|
54
|
+
* blob: () => request.blob(),
|
|
55
|
+
* arrayBuffer: () => request.arrayBuffer(),
|
|
56
|
+
* };
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
export interface CoreRequest {
|
|
60
|
+
/**
|
|
61
|
+
* The NextURL of the request (Next.js specific).
|
|
62
|
+
* Used for extracting query parameters in Next.js applications.
|
|
63
|
+
* Takes priority over `url` when available.
|
|
64
|
+
*/
|
|
65
|
+
readonly nextUrl?: URL | {
|
|
66
|
+
readonly searchParams: URLSearchParams;
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* The URL of the request.
|
|
70
|
+
* Can be:
|
|
71
|
+
* - URL object (Fetch API, custom implementations)
|
|
72
|
+
* - string (Express, Fastify - just the path with query string)
|
|
73
|
+
*/
|
|
74
|
+
readonly url?: URL | string;
|
|
75
|
+
/**
|
|
76
|
+
* Pre-parsed query parameters object (Express/Fastify style).
|
|
77
|
+
* Used as fallback when `nextUrl` and `url` are not available or don't have searchParams.
|
|
78
|
+
*/
|
|
79
|
+
readonly query?: Record<string, string | string[] | undefined>;
|
|
80
|
+
/**
|
|
81
|
+
* The HTTP headers of the request.
|
|
82
|
+
* Must be iterable (for use with Object.fromEntries).
|
|
83
|
+
*/
|
|
84
|
+
readonly headers: Headers;
|
|
85
|
+
/**
|
|
86
|
+
* The body of the request as a ReadableStream, or null if no body.
|
|
87
|
+
*/
|
|
88
|
+
readonly body: ReadableStream<Uint8Array> | null;
|
|
89
|
+
/**
|
|
90
|
+
* Parses the request body as JSON.
|
|
91
|
+
* @returns Promise resolving to the parsed JSON value
|
|
92
|
+
*/
|
|
93
|
+
json(): Promise<unknown>;
|
|
94
|
+
/**
|
|
95
|
+
* Returns the request body as text.
|
|
96
|
+
* @returns Promise resolving to the body text
|
|
97
|
+
*/
|
|
98
|
+
text(): Promise<string>;
|
|
99
|
+
/**
|
|
100
|
+
* Parses the request body as FormData.
|
|
101
|
+
* @returns Promise resolving to the FormData
|
|
102
|
+
*/
|
|
103
|
+
formData(): Promise<FormData>;
|
|
104
|
+
/**
|
|
105
|
+
* Returns the request body as a Blob.
|
|
106
|
+
* @returns Promise resolving to the Blob
|
|
107
|
+
*/
|
|
108
|
+
blob(): Promise<Blob>;
|
|
109
|
+
/**
|
|
110
|
+
* Returns the request body as an ArrayBuffer.
|
|
111
|
+
* @returns Promise resolving to the ArrayBuffer
|
|
112
|
+
*/
|
|
113
|
+
arrayBuffer(): Promise<ArrayBuffer>;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Unified search params class that works with multiple input sources.
|
|
117
|
+
* Provides a consistent API for accessing query parameters regardless of the framework.
|
|
118
|
+
*
|
|
119
|
+
* @remarks
|
|
120
|
+
* This class abstracts the differences between:
|
|
121
|
+
* - URLSearchParams (Fetch API, Next.js)
|
|
122
|
+
* - Query object (Express, Fastify)
|
|
123
|
+
* - Query string (raw URL parsing)
|
|
124
|
+
*
|
|
125
|
+
* @example
|
|
126
|
+
* ```ts
|
|
127
|
+
* // From URLSearchParams
|
|
128
|
+
* const params = new CoreSearchParams(new URLSearchParams("page=1&limit=10"));
|
|
129
|
+
*
|
|
130
|
+
* // From object (Express style)
|
|
131
|
+
* const params = new CoreSearchParams({ page: "1", limit: "10" });
|
|
132
|
+
*
|
|
133
|
+
* // From query string
|
|
134
|
+
* const params = new CoreSearchParams("page=1&limit=10");
|
|
135
|
+
*
|
|
136
|
+
* // Usage
|
|
137
|
+
* params.get("page"); // "1"
|
|
138
|
+
* params.getNumber("page"); // 1
|
|
139
|
+
* params.getAll("tags"); // ["a", "b"]
|
|
140
|
+
* params.toObject(); // { page: "1", limit: "10" }
|
|
141
|
+
* ```
|
|
142
|
+
*/
|
|
143
|
+
export declare class CoreSearchParams {
|
|
144
|
+
private readonly params;
|
|
145
|
+
/**
|
|
146
|
+
* Creates a new CoreSearchParams instance.
|
|
147
|
+
*
|
|
148
|
+
* @param source - The source of query parameters:
|
|
149
|
+
* - URLSearchParams: Used directly
|
|
150
|
+
* - Record<string, string | string[] | undefined>: Object with query values
|
|
151
|
+
* - string: Query string (with or without leading "?")
|
|
152
|
+
* - undefined/null: Empty params
|
|
153
|
+
*/
|
|
154
|
+
constructor(source?: URLSearchParams | Record<string, string | string[] | undefined> | string | null);
|
|
155
|
+
/**
|
|
156
|
+
* Gets the first value for a parameter.
|
|
157
|
+
* @param name - Parameter name
|
|
158
|
+
* @returns The value or null if not found
|
|
159
|
+
*/
|
|
160
|
+
get(name: string): string | null;
|
|
161
|
+
/**
|
|
162
|
+
* Gets all values for a parameter.
|
|
163
|
+
* @param name - Parameter name
|
|
164
|
+
* @returns Array of values (empty if not found)
|
|
165
|
+
*/
|
|
166
|
+
getAll(name: string): string[];
|
|
167
|
+
/**
|
|
168
|
+
* Checks if a parameter exists.
|
|
169
|
+
* @param name - Parameter name
|
|
170
|
+
* @returns true if the parameter exists
|
|
171
|
+
*/
|
|
172
|
+
has(name: string): boolean;
|
|
173
|
+
/**
|
|
174
|
+
* Gets a parameter as a number.
|
|
175
|
+
* @param name - Parameter name
|
|
176
|
+
* @param defaultValue - Default value if not found or not a valid number
|
|
177
|
+
* @returns The parsed number or default value
|
|
178
|
+
*/
|
|
179
|
+
getNumber(name: string, defaultValue?: number): number | undefined;
|
|
180
|
+
/**
|
|
181
|
+
* Gets a parameter as a boolean.
|
|
182
|
+
* Treats "true", "1", "yes" as true; "false", "0", "no" as false.
|
|
183
|
+
* @param name - Parameter name
|
|
184
|
+
* @param defaultValue - Default value if not found
|
|
185
|
+
* @returns The parsed boolean or default value
|
|
186
|
+
*/
|
|
187
|
+
getBoolean(name: string, defaultValue?: boolean): boolean | undefined;
|
|
188
|
+
/**
|
|
189
|
+
* Returns an iterator of all parameter names.
|
|
190
|
+
*/
|
|
191
|
+
keys(): IterableIterator<string>;
|
|
192
|
+
/**
|
|
193
|
+
* Returns an iterator of all parameter values.
|
|
194
|
+
*/
|
|
195
|
+
values(): IterableIterator<string>;
|
|
196
|
+
/**
|
|
197
|
+
* Returns an iterator of all [name, value] pairs.
|
|
198
|
+
*/
|
|
199
|
+
entries(): IterableIterator<[string, string]>;
|
|
200
|
+
/**
|
|
201
|
+
* Executes a callback for each parameter.
|
|
202
|
+
*/
|
|
203
|
+
forEach(callback: (value: string, key: string, parent: URLSearchParams) => void): void;
|
|
204
|
+
/**
|
|
205
|
+
* Converts to a plain object (first value only for each key).
|
|
206
|
+
* @returns Object with string values
|
|
207
|
+
*/
|
|
208
|
+
toObject(): Record<string, string>;
|
|
209
|
+
/**
|
|
210
|
+
* Converts to a plain object (all values as arrays).
|
|
211
|
+
* @returns Object with string array values
|
|
212
|
+
*/
|
|
213
|
+
toObjectAll(): Record<string, string[]>;
|
|
214
|
+
/**
|
|
215
|
+
* Returns the underlying URLSearchParams.
|
|
216
|
+
*/
|
|
217
|
+
toURLSearchParams(): URLSearchParams;
|
|
218
|
+
/**
|
|
219
|
+
* Converts to query string (without leading "?").
|
|
220
|
+
*/
|
|
221
|
+
toString(): string;
|
|
222
|
+
/**
|
|
223
|
+
* Returns the number of parameters (counting duplicates).
|
|
224
|
+
*/
|
|
225
|
+
get size(): number;
|
|
226
|
+
/**
|
|
227
|
+
* Makes the class iterable.
|
|
228
|
+
*/
|
|
229
|
+
[Symbol.iterator](): IterableIterator<[string, string]>;
|
|
230
|
+
}
|
|
15
231
|
/**
|
|
16
232
|
* Container for route-level metadata, guards, filters, interceptors, and pipes.
|
|
17
233
|
* Created from decorator results and attached to each route.
|
|
@@ -83,8 +299,8 @@ export declare class Reflect {
|
|
|
83
299
|
* Created for each request and available throughout the request lifecycle.
|
|
84
300
|
*/
|
|
85
301
|
export interface RequestContext {
|
|
86
|
-
/** The incoming
|
|
87
|
-
req:
|
|
302
|
+
/** The incoming HTTP request (CoreRequest-compatible) */
|
|
303
|
+
req: CoreRequest;
|
|
88
304
|
/** The response builder */
|
|
89
305
|
res: ServerResponse;
|
|
90
306
|
/** HTTP method of the request */
|
|
@@ -176,25 +392,31 @@ export declare class ExecuteContext {
|
|
|
176
392
|
/**
|
|
177
393
|
* Retrieves a global inject by name with lazy initialization.
|
|
178
394
|
* If the inject hasn't been initialized yet, calls the factory to create it.
|
|
395
|
+
* Returns the result of switch() if available, otherwise the raw instance.
|
|
179
396
|
*
|
|
180
|
-
* @template T - Expected type
|
|
397
|
+
* @template T - Expected return type (from switch() or the inject itself)
|
|
181
398
|
* @param name - The name of the inject to retrieve
|
|
182
|
-
* @returns Promise resolving to the
|
|
399
|
+
* @returns Promise resolving to the switched value or undefined if not found
|
|
183
400
|
*
|
|
184
401
|
* @example
|
|
185
402
|
* ```ts
|
|
186
|
-
*
|
|
403
|
+
* // If inject implements switch(), returns the switched value
|
|
404
|
+
* const db = await context.getInject<DatabaseClient>("db");
|
|
405
|
+
* const users = await db.query("SELECT * FROM users");
|
|
406
|
+
*
|
|
407
|
+
* // If inject doesn't implement switch(), returns the inject instance
|
|
187
408
|
* const config = await context.getInject<Config>("config");
|
|
188
409
|
* ```
|
|
189
410
|
*/
|
|
190
|
-
getInject<T
|
|
411
|
+
getInject<T = unknown>(name: string): Promise<T | undefined>;
|
|
191
412
|
/**
|
|
192
413
|
* Retrieves a global inject synchronously (only if already initialized).
|
|
193
414
|
* Returns undefined if the inject hasn't been initialized yet.
|
|
415
|
+
* Returns the result of switch() if available, otherwise the raw instance.
|
|
194
416
|
*
|
|
195
|
-
* @template T - Expected type
|
|
417
|
+
* @template T - Expected return type (from switch() or the inject itself)
|
|
196
418
|
* @param name - The name of the inject to retrieve
|
|
197
|
-
* @returns The
|
|
419
|
+
* @returns The switched value or undefined if not found/not initialized
|
|
198
420
|
*
|
|
199
421
|
* @example
|
|
200
422
|
* ```ts
|
|
@@ -202,7 +424,7 @@ export declare class ExecuteContext {
|
|
|
202
424
|
* const config = context.getInjectSync<Config>("config");
|
|
203
425
|
* ```
|
|
204
426
|
*/
|
|
205
|
-
getInjectSync<T
|
|
427
|
+
getInjectSync<T = unknown>(name: string): T | undefined;
|
|
206
428
|
/**
|
|
207
429
|
* Checks if a global inject factory exists by name.
|
|
208
430
|
*
|
|
@@ -285,8 +507,8 @@ export declare class ExecuteContext {
|
|
|
285
507
|
* ```
|
|
286
508
|
*/
|
|
287
509
|
switchHttp(): {
|
|
288
|
-
/** Returns the
|
|
289
|
-
getRequest: () =>
|
|
510
|
+
/** Returns the CoreRequest object, optionally cast to a specific type */
|
|
511
|
+
getRequest: <T extends CoreRequest = CoreRequest>() => T;
|
|
290
512
|
/** Returns the ServerResponse builder */
|
|
291
513
|
getResponse: () => ServerResponse;
|
|
292
514
|
/** Returns the HTTP method */
|
|
@@ -297,16 +519,16 @@ export declare class ExecuteContext {
|
|
|
297
519
|
params: () => Record<string, string>;
|
|
298
520
|
/** Returns wildcard segments */
|
|
299
521
|
wildcards: () => string[];
|
|
300
|
-
/** Returns query
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
522
|
+
/** Returns CoreSearchParams instance for query parameter access */
|
|
523
|
+
searchParams: () => CoreSearchParams;
|
|
524
|
+
/** Returns query parameters as plain object (first value only) */
|
|
525
|
+
query: () => Record<string, string>;
|
|
304
526
|
/** Returns headers as object */
|
|
305
527
|
headers: () => {
|
|
306
528
|
[k: string]: string;
|
|
307
529
|
};
|
|
308
530
|
/** Returns the raw body ReadableStream */
|
|
309
|
-
body: () => ReadableStream<Uint8Array<
|
|
531
|
+
body: () => ReadableStream<Uint8Array<ArrayBufferLike>> | null;
|
|
310
532
|
/** Parses and returns the JSON body */
|
|
311
533
|
json: <T = unknown>() => Promise<T>;
|
|
312
534
|
/** Returns the body as text */
|
|
@@ -343,10 +565,11 @@ export declare class ExecuteContext {
|
|
|
343
565
|
/**
|
|
344
566
|
* Retrieves a feature-local inject by name with lazy initialization.
|
|
345
567
|
* Falls back to global injects if not found in the feature.
|
|
568
|
+
* Returns the result of switch() if available, otherwise the raw instance.
|
|
346
569
|
*
|
|
347
|
-
* @template T - Expected type
|
|
570
|
+
* @template T - Expected return type (from switch() or the inject itself)
|
|
348
571
|
* @param name - The name of the inject to retrieve
|
|
349
|
-
* @returns Promise resolving to the
|
|
572
|
+
* @returns Promise resolving to the switched value or undefined if not found
|
|
350
573
|
*
|
|
351
574
|
* @example
|
|
352
575
|
* ```ts
|
|
@@ -354,14 +577,15 @@ export declare class ExecuteContext {
|
|
|
354
577
|
* const repo = await context.getLocalInject<ProductRepository>("productRepo");
|
|
355
578
|
* ```
|
|
356
579
|
*/
|
|
357
|
-
getLocalInject<T
|
|
580
|
+
getLocalInject<T = unknown>(name: string): Promise<T | undefined>;
|
|
358
581
|
/**
|
|
359
582
|
* Retrieves a feature-local inject synchronously (only if already initialized).
|
|
360
583
|
* Falls back to global injects if not found in the feature.
|
|
584
|
+
* Returns the result of switch() if available, otherwise the raw instance.
|
|
361
585
|
*
|
|
362
|
-
* @template T - Expected type
|
|
586
|
+
* @template T - Expected return type (from switch() or the inject itself)
|
|
363
587
|
* @param name - The name of the inject to retrieve
|
|
364
|
-
* @returns The
|
|
588
|
+
* @returns The switched value or undefined if not found/not initialized
|
|
365
589
|
*
|
|
366
590
|
* @example
|
|
367
591
|
* ```ts
|
|
@@ -369,7 +593,51 @@ export declare class ExecuteContext {
|
|
|
369
593
|
* const repo = context.getLocalInjectSync<ProductRepository>("productRepo");
|
|
370
594
|
* ```
|
|
371
595
|
*/
|
|
372
|
-
getLocalInjectSync<T
|
|
596
|
+
getLocalInjectSync<T = unknown>(name: string): T | undefined;
|
|
597
|
+
/**
|
|
598
|
+
* Retrieves an inject by name and calls its switch() method.
|
|
599
|
+
* Searches in feature injects first (priority), then falls back to global injects.
|
|
600
|
+
*
|
|
601
|
+
* @template T - Expected return type of the switch() method
|
|
602
|
+
* @param name - The name of the inject to switch to
|
|
603
|
+
* @returns Promise resolving to the result of the inject's switch() method
|
|
604
|
+
* @throws {Error} If the inject is not found or doesn't have a switch() method
|
|
605
|
+
*
|
|
606
|
+
* @example
|
|
607
|
+
* ```ts
|
|
608
|
+
* // In a controller or service
|
|
609
|
+
* const db = await this.context.switch<DatabaseClient>("db");
|
|
610
|
+
* const users = await db.query("SELECT * FROM users");
|
|
611
|
+
*
|
|
612
|
+
* // The inject must implement switch():
|
|
613
|
+
* class Connection implements ApplicationInject {
|
|
614
|
+
* switch<T = DatabaseClient>(): T {
|
|
615
|
+
* return this.client as T;
|
|
616
|
+
* }
|
|
617
|
+
* }
|
|
618
|
+
* ```
|
|
619
|
+
*/
|
|
620
|
+
switch<T = unknown>(name: string): Promise<T>;
|
|
621
|
+
/**
|
|
622
|
+
* Retrieves an inject by name and calls its switch() method (synchronous version).
|
|
623
|
+
* Only works if the inject has already been initialized.
|
|
624
|
+
* Searches in feature injects first (priority), then falls back to global injects.
|
|
625
|
+
*
|
|
626
|
+
* @template T - Expected return type of the switch() method
|
|
627
|
+
* @param name - The name of the inject to switch to
|
|
628
|
+
* @returns The result of the inject's switch() method, or undefined if not initialized
|
|
629
|
+
* @throws {Error} If the inject exists but doesn't have a switch() method
|
|
630
|
+
*
|
|
631
|
+
* @example
|
|
632
|
+
* ```ts
|
|
633
|
+
* // Only use when you're sure the inject is already initialized
|
|
634
|
+
* const db = this.context.switchSync<DatabaseClient>("db");
|
|
635
|
+
* if (db) {
|
|
636
|
+
* const users = await db.query("SELECT * FROM users");
|
|
637
|
+
* }
|
|
638
|
+
* ```
|
|
639
|
+
*/
|
|
640
|
+
switchSync<T = unknown>(name: string): T | undefined;
|
|
373
641
|
}
|
|
374
642
|
/**
|
|
375
643
|
* Interface for guard classes that determine if a request should proceed.
|
|
@@ -474,48 +742,34 @@ export interface ExceptionFilter<Response = unknown> {
|
|
|
474
742
|
*/
|
|
475
743
|
export type Filter<Response = unknown> = new (...args: unknown[]) => ExceptionFilter<Response>;
|
|
476
744
|
/**
|
|
477
|
-
*
|
|
478
|
-
* Interceptors
|
|
745
|
+
* Constructor type for response interceptor classes.
|
|
746
|
+
* Interceptors transform the CoreResponse after the handler returns.
|
|
479
747
|
*
|
|
480
|
-
* @template T - The type of the
|
|
748
|
+
* @template T - The type of the response data
|
|
749
|
+
*
|
|
750
|
+
* @remarks
|
|
751
|
+
* The old `InterceptorHandler` interface with `intercept(context, next)` is deprecated.
|
|
752
|
+
* Use `ResponseInterceptorHandler` from `response.ts` instead for the new pattern.
|
|
481
753
|
*
|
|
482
754
|
* @example
|
|
483
755
|
* ```ts
|
|
484
|
-
*
|
|
485
|
-
*
|
|
486
|
-
*
|
|
487
|
-
*
|
|
488
|
-
* console.log(`
|
|
489
|
-
* return
|
|
756
|
+
* import { ResponseInterceptorHandler, CoreResponse } from "@mxweb/core";
|
|
757
|
+
*
|
|
758
|
+
* class LoggingInterceptor implements ResponseInterceptorHandler {
|
|
759
|
+
* transform(response: CoreResponse): CoreResponse {
|
|
760
|
+
* console.log(`Response: ${response.status} ${response.body.message}`);
|
|
761
|
+
* return response;
|
|
490
762
|
* }
|
|
491
763
|
* }
|
|
492
764
|
*
|
|
493
|
-
* class
|
|
494
|
-
*
|
|
495
|
-
*
|
|
496
|
-
*
|
|
497
|
-
*
|
|
498
|
-
*
|
|
499
|
-
* const result = await next();
|
|
500
|
-
* await cache.set(key, result);
|
|
501
|
-
* return result;
|
|
765
|
+
* class CacheHeaderInterceptor implements ResponseInterceptorHandler {
|
|
766
|
+
* transform(response: CoreResponse): CoreResponse {
|
|
767
|
+
* if (response.status >= 200 && response.status < 300) {
|
|
768
|
+
* response.headers.set("Cache-Control", "max-age=3600");
|
|
769
|
+
* }
|
|
770
|
+
* return response;
|
|
502
771
|
* }
|
|
503
772
|
* }
|
|
504
773
|
* ```
|
|
505
774
|
*/
|
|
506
|
-
export
|
|
507
|
-
/**
|
|
508
|
-
* Intercepts the handler execution.
|
|
509
|
-
*
|
|
510
|
-
* @param context - The execution context for the current request
|
|
511
|
-
* @param next - Function to call the next interceptor or handler
|
|
512
|
-
* @returns The (possibly transformed) result
|
|
513
|
-
*/
|
|
514
|
-
intercept(context: ExecuteContext, next: CallHandler<T>): Promise<T>;
|
|
515
|
-
}
|
|
516
|
-
/**
|
|
517
|
-
* Constructor type for interceptor classes.
|
|
518
|
-
*
|
|
519
|
-
* @template T - The type of the handler result
|
|
520
|
-
*/
|
|
521
|
-
export type Interceptor<T = unknown> = new (...args: unknown[]) => InterceptorHandler<T>;
|
|
775
|
+
export type Interceptor<T = unknown> = new (...args: unknown[]) => import("./response").ResponseInterceptorHandler<T>;
|
package/dist/execute.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var t=require("async_hooks");class e{constructor(){this.storage=new t.AsyncLocalStorage,this._injections=new Map,this._registry=null}static get instance(){return
|
|
1
|
+
"use strict";var t=require("async_hooks");class e{constructor(t){if(t)if(t instanceof URLSearchParams)this.params=t;else if("string"==typeof t){const e=t.startsWith("?")?t.slice(1):t;this.params=new URLSearchParams(e)}else{this.params=new URLSearchParams;for(const[e,r]of Object.entries(t))if(void 0!==r)if(Array.isArray(r))for(const t of r)this.params.append(e,t);else this.params.set(e,r)}else this.params=new URLSearchParams}get(t){return this.params.get(t)}getAll(t){return this.params.getAll(t)}has(t){return this.params.has(t)}getNumber(t,e){const r=this.params.get(t);if(null===r)return e;const n=Number(r);return isNaN(n)?e:n}getBoolean(t,e){const r=this.params.get(t);if(null===r)return e;const n=r.toLowerCase();return!!["true","1","yes"].includes(n)||!["false","0","no"].includes(n)&&e}keys(){return this.params.keys()}values(){return this.params.values()}entries(){return this.params.entries()}forEach(t){this.params.forEach(t)}toObject(){const t={};for(const e of this.params.keys())t[e]=this.params.get(e);return t}toObjectAll(){const t={};for(const e of this.params.keys())t[e]||(t[e]=this.params.getAll(e));return t}toURLSearchParams(){return this.params}toString(){return this.params.toString()}get size(){let t=0;return this.params.forEach(()=>t++),t}[Symbol.iterator](){return this.params.entries()}}class r{constructor(){this.storage=new t.AsyncLocalStorage,this._injections=new Map,this._registry=null}static get instance(){return r._instance||(r._instance=new r),r._instance}setRegistry(t){this._registry=t}get injections(){return this._injections}setInject(t,e){this._injections.set(t,{factory:e})}async getInject(t){const e=this._injections.get(t);if(e){if(!e.instance){if(!this._registry)throw new Error(`[ExecuteContext] Registry not set. Cannot initialize inject '${t}'.`);e.instance=await e.factory(this._registry),"function"==typeof e.instance.onInit&&await e.instance.onInit()}return"function"==typeof e.instance.switch?e.instance.switch():e.instance}}getInjectSync(t){const e=this._injections.get(t);if(e?.instance)return"function"==typeof e.instance.switch?e.instance.switch():e.instance}hasInject(t){return this._injections.has(t)}isInjectInitialized(t){const e=this._injections.get(t);return!!e?.instance}clearInjections(){this._injections.clear()}run(t,e){return this.storage.run(t,e)}getContext(){return this.storage.getStore()}getContextOrThrow(){const t=this.storage.getStore();if(!t)throw new Error("[ExecuteContext] No context available. Make sure you're inside a request handler.");return t}switchHttp(){const t=this.getContextOrThrow();let r=null;const n=()=>(r||(r=(()=>{if(t.req.nextUrl){const r=(t.req.nextUrl,URL,t.req.nextUrl.searchParams);return new e(r)}if(t.req.url instanceof URL)return new e(t.req.url.searchParams);if("string"==typeof t.req.url&&t.req.url.includes("?")){const r=t.req.url.split("?")[1];return new e(r)}return t.req.query?new e(t.req.query):new e})()),r);return{getRequest:()=>t.req,getResponse:()=>t.res,getMethod:()=>t.method,getPath:()=>t.path,params:()=>t.params,wildcards:()=>t.wildcards,searchParams:n,query:()=>n().toObject(),headers:()=>Object.fromEntries(t.req.headers),body:()=>t.req.body,json:()=>t.req.json(),text:()=>t.req.text(),formData:()=>t.req.formData(),blob:()=>t.req.blob(),arrayBuffer:()=>t.req.arrayBuffer()}}getReflect(){return this.getContext()?.reflect}getMetadata(t){return this.getContext()?.reflect.getMetadata(t)}getFeature(){return this.getContext()?.feature}async getLocalInject(t){const e=this.getContext()?.feature;if(e?.hasInject(t)){const r=await e.getInject(t);if(!r)return;return"function"==typeof r.switch?r.switch():r}return this.getInject(t)}getLocalInjectSync(t){const e=this.getContext()?.feature;if(e?.hasInject(t)){const r=e.getInjectSync(t);if(!r)return;return"function"==typeof r.switch?r.switch():r}return this.getInjectSync(t)}async switch(t){const e=this.getContext()?.feature;if(e?.hasInject(t)){return await e.getInject(t)}const r=this._injections.get(t);if(!r)throw new Error(`[ExecuteContext] Inject '${t}' not found.`);if(!r.instance){if(!this._registry)throw new Error(`[ExecuteContext] Registry not set. Cannot initialize inject '${t}'.`);r.instance=await r.factory(this._registry),"function"==typeof r.instance.onInit&&await r.instance.onInit()}if("function"!=typeof r.instance.switch)throw new Error(`[ExecuteContext] Inject '${t}' does not implement switch() method.`);return r.instance.switch()}switchSync(t){const e=this.getContext()?.feature;let r;if(r=e?.hasInject(t)?e.getInjectSync(t):this.getInjectSync(t),r){if("function"!=typeof r.switch)throw new Error(`[ExecuteContext] Inject '${t}' does not implement switch() method.`);return r.switch()}}}r._instance=null,exports.CoreSearchParams=e,exports.ExecuteContext=r,exports.Reflect=class{constructor(t,e,r,n,s){this.metadata=t,this.guards=e,this.filters=r,this.interceptors=n,this.pipes=s}getGuards(){return this.guards}getFilters(){return this.filters}getInterceptors(){return this.interceptors}getPipes(){return this.pipes}getMetadata(t){return this.metadata.get(t)}getAllMetadata(){return this.metadata}};
|
package/dist/execute.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{AsyncLocalStorage as t}from"async_hooks";class e{constructor(t,e,n,r,s){this.metadata=t,this.guards=e,this.filters=
|
|
1
|
+
import{AsyncLocalStorage as t}from"async_hooks";class e{constructor(t){if(t)if(t instanceof URLSearchParams)this.params=t;else if("string"==typeof t){const e=t.startsWith("?")?t.slice(1):t;this.params=new URLSearchParams(e)}else{this.params=new URLSearchParams;for(const[e,r]of Object.entries(t))if(void 0!==r)if(Array.isArray(r))for(const t of r)this.params.append(e,t);else this.params.set(e,r)}else this.params=new URLSearchParams}get(t){return this.params.get(t)}getAll(t){return this.params.getAll(t)}has(t){return this.params.has(t)}getNumber(t,e){const r=this.params.get(t);if(null===r)return e;const n=Number(r);return isNaN(n)?e:n}getBoolean(t,e){const r=this.params.get(t);if(null===r)return e;const n=r.toLowerCase();return!!["true","1","yes"].includes(n)||!["false","0","no"].includes(n)&&e}keys(){return this.params.keys()}values(){return this.params.values()}entries(){return this.params.entries()}forEach(t){this.params.forEach(t)}toObject(){const t={};for(const e of this.params.keys())t[e]=this.params.get(e);return t}toObjectAll(){const t={};for(const e of this.params.keys())t[e]||(t[e]=this.params.getAll(e));return t}toURLSearchParams(){return this.params}toString(){return this.params.toString()}get size(){let t=0;return this.params.forEach(()=>t++),t}[Symbol.iterator](){return this.params.entries()}}class r{constructor(t,e,r,n,s){this.metadata=t,this.guards=e,this.filters=r,this.interceptors=n,this.pipes=s}getGuards(){return this.guards}getFilters(){return this.filters}getInterceptors(){return this.interceptors}getPipes(){return this.pipes}getMetadata(t){return this.metadata.get(t)}getAllMetadata(){return this.metadata}}class n{constructor(){this.storage=new t,this._injections=new Map,this._registry=null}static get instance(){return n._instance||(n._instance=new n),n._instance}setRegistry(t){this._registry=t}get injections(){return this._injections}setInject(t,e){this._injections.set(t,{factory:e})}async getInject(t){const e=this._injections.get(t);if(e){if(!e.instance){if(!this._registry)throw new Error(`[ExecuteContext] Registry not set. Cannot initialize inject '${t}'.`);e.instance=await e.factory(this._registry),"function"==typeof e.instance.onInit&&await e.instance.onInit()}return"function"==typeof e.instance.switch?e.instance.switch():e.instance}}getInjectSync(t){const e=this._injections.get(t);if(e?.instance)return"function"==typeof e.instance.switch?e.instance.switch():e.instance}hasInject(t){return this._injections.has(t)}isInjectInitialized(t){const e=this._injections.get(t);return!!e?.instance}clearInjections(){this._injections.clear()}run(t,e){return this.storage.run(t,e)}getContext(){return this.storage.getStore()}getContextOrThrow(){const t=this.storage.getStore();if(!t)throw new Error("[ExecuteContext] No context available. Make sure you're inside a request handler.");return t}switchHttp(){const t=this.getContextOrThrow();let r=null;const n=()=>(r||(r=(()=>{if(t.req.nextUrl){const r=(t.req.nextUrl,URL,t.req.nextUrl.searchParams);return new e(r)}if(t.req.url instanceof URL)return new e(t.req.url.searchParams);if("string"==typeof t.req.url&&t.req.url.includes("?")){const r=t.req.url.split("?")[1];return new e(r)}return t.req.query?new e(t.req.query):new e})()),r);return{getRequest:()=>t.req,getResponse:()=>t.res,getMethod:()=>t.method,getPath:()=>t.path,params:()=>t.params,wildcards:()=>t.wildcards,searchParams:n,query:()=>n().toObject(),headers:()=>Object.fromEntries(t.req.headers),body:()=>t.req.body,json:()=>t.req.json(),text:()=>t.req.text(),formData:()=>t.req.formData(),blob:()=>t.req.blob(),arrayBuffer:()=>t.req.arrayBuffer()}}getReflect(){return this.getContext()?.reflect}getMetadata(t){return this.getContext()?.reflect.getMetadata(t)}getFeature(){return this.getContext()?.feature}async getLocalInject(t){const e=this.getContext()?.feature;if(e?.hasInject(t)){const r=await e.getInject(t);if(!r)return;return"function"==typeof r.switch?r.switch():r}return this.getInject(t)}getLocalInjectSync(t){const e=this.getContext()?.feature;if(e?.hasInject(t)){const r=e.getInjectSync(t);if(!r)return;return"function"==typeof r.switch?r.switch():r}return this.getInjectSync(t)}async switch(t){const e=this.getContext()?.feature;if(e?.hasInject(t)){return await e.getInject(t)}const r=this._injections.get(t);if(!r)throw new Error(`[ExecuteContext] Inject '${t}' not found.`);if(!r.instance){if(!this._registry)throw new Error(`[ExecuteContext] Registry not set. Cannot initialize inject '${t}'.`);r.instance=await r.factory(this._registry),"function"==typeof r.instance.onInit&&await r.instance.onInit()}if("function"!=typeof r.instance.switch)throw new Error(`[ExecuteContext] Inject '${t}' does not implement switch() method.`);return r.instance.switch()}switchSync(t){const e=this.getContext()?.feature;let r;if(r=e?.hasInject(t)?e.getInjectSync(t):this.getInjectSync(t),r){if("function"!=typeof r.switch)throw new Error(`[ExecuteContext] Inject '${t}' does not implement switch() method.`);return r.switch()}}}n._instance=null;export{e as CoreSearchParams,n as ExecuteContext,r as Reflect};
|
package/dist/feature.d.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
import { ControllerConstructor } from "./controller";
|
|
11
11
|
import { RouteMatched, Router } from "./router";
|
|
12
12
|
import { FeatureHooks, FeatureHooksOptions } from "./hooks";
|
|
13
|
-
import {
|
|
13
|
+
import { FeatureInjectFactory, RouteMethod } from "./common";
|
|
14
14
|
/**
|
|
15
15
|
* Type for feature-specific dependency injection configuration.
|
|
16
16
|
* Array of factory functions that register injects.
|
|
@@ -208,25 +208,27 @@ export declare class Feature {
|
|
|
208
208
|
/**
|
|
209
209
|
* Retrieves a feature-specific inject by name (async - lazy initialization).
|
|
210
210
|
* If instance doesn't exist, calls factory to create it and runs onFeature().
|
|
211
|
+
* Returns the result of switch() if available, otherwise the raw instance.
|
|
211
212
|
*
|
|
212
|
-
* @template T - Expected type
|
|
213
|
+
* @template T - Expected return type (from switch() or the inject itself)
|
|
213
214
|
* @param name - The name of the inject to retrieve
|
|
214
|
-
* @returns Promise resolving to the
|
|
215
|
+
* @returns Promise resolving to the switched value or undefined if not found
|
|
215
216
|
*
|
|
216
217
|
* @example
|
|
217
218
|
* ```ts
|
|
218
219
|
* const repo = await feature.getInject<ProductRepository>("productRepo");
|
|
219
220
|
* ```
|
|
220
221
|
*/
|
|
221
|
-
getInject<T
|
|
222
|
+
getInject<T = unknown>(name: string): Promise<T | undefined>;
|
|
222
223
|
/**
|
|
223
224
|
* Retrieves a feature-specific inject synchronously (only if already initialized).
|
|
225
|
+
* Returns the result of switch() if available, otherwise the raw instance.
|
|
224
226
|
*
|
|
225
|
-
* @template T - Expected type
|
|
227
|
+
* @template T - Expected return type (from switch() or the inject itself)
|
|
226
228
|
* @param name - The name of the inject to retrieve
|
|
227
|
-
* @returns The
|
|
229
|
+
* @returns The switched value or undefined if not found/not initialized
|
|
228
230
|
*/
|
|
229
|
-
getInjectSync<T
|
|
231
|
+
getInjectSync<T = unknown>(name: string): T | undefined;
|
|
230
232
|
/**
|
|
231
233
|
* Checks if a feature-specific inject factory is registered by name.
|
|
232
234
|
*
|
package/dist/feature.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var t=require("./hooks.js");class e{constructor(e,s,i){this.options=e,this.ControllerContructor=s,this.router=i,this.routeMatched=null,this.controller=null,this.injects=new Map,this.factoriesRegistered=!1,this.importsLoaded=!1,this.hooks=new t.FeatureHooks(this.options),this.registry=this.createInjectRegistry()}createInjectRegistry(){return{get:t=>this.getInject(t),set:(t,e)=>{this.injects.set(t,{factory:e})}}}static create(t){return new e(t,t.controller,t.router)}async loadImports(){if(this.importsLoaded)return;this.importsLoaded=!0;const{imports:t}=this.options;if(!t)return;"function"==typeof t&&await t()}async loadInjects(){if(await this.loadImports(),this.factoriesRegistered)return;this.factoriesRegistered=!0;const{injects:t}=this.options;if(t&&t.length)for(const e of t)await e(this.registry)}async destroyInjects(){for(const[t,e]of this.injects)if(e.instance&&e.instance.onFeatureDestroy)try{await e.instance.onFeatureDestroy()}catch(t){}this.injects.clear(),this.factoriesRegistered=!1}async getInject(t){const e=this.injects.get(t);if(e)return e.instance||(e.instance=await e.factory(this.registry),"function"==typeof e.instance.onFeature&&await e.instance.onFeature()),e.instance}getInjectSync(t){const e=this.injects.get(t);return e
|
|
1
|
+
"use strict";var t=require("./hooks.js");class e{constructor(e,s,i){this.options=e,this.ControllerContructor=s,this.router=i,this.routeMatched=null,this.controller=null,this.injects=new Map,this.factoriesRegistered=!1,this.importsLoaded=!1,this.hooks=new t.FeatureHooks(this.options),this.registry=this.createInjectRegistry()}createInjectRegistry(){return{get:t=>this.getInject(t),set:(t,e)=>{this.injects.set(t,{factory:e})}}}static create(t){return new e(t,t.controller,t.router)}async loadImports(){if(this.importsLoaded)return;this.importsLoaded=!0;const{imports:t}=this.options;if(!t)return;"function"==typeof t&&await t()}async loadInjects(){if(await this.loadImports(),this.factoriesRegistered)return;this.factoriesRegistered=!0;const{injects:t}=this.options;if(t&&t.length)for(const e of t)await e(this.registry)}async destroyInjects(){for(const[t,e]of this.injects)if(e.instance&&e.instance.onFeatureDestroy)try{await e.instance.onFeatureDestroy()}catch(t){}this.injects.clear(),this.factoriesRegistered=!1}async getInject(t){const e=this.injects.get(t);if(e)return e.instance||(e.instance=await e.factory(this.registry),"function"==typeof e.instance.onFeature&&await e.instance.onFeature()),"function"==typeof e.instance.switch?e.instance.switch():e.instance}getInjectSync(t){const e=this.injects.get(t);if(e?.instance)return"function"==typeof e.instance.switch?e.instance.switch():e.instance}hasInject(t){return this.injects.has(t)}isInjectInitialized(t){const e=this.injects.get(t);return!!e?.instance}getController(){if(!this.controller){const t=this.ControllerContructor;this.controller=new t}return this.controller}getHooks(){return this.hooks}matchRoute(t,e){return this.routeMatched=this.router.match(t,e),this.routeMatched}}exports.Feature=e;
|