clear-router 2.5.4 → 2.5.6
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 +5 -0
- package/dist/bindings-CV1e5jho.d.mts +20 -0
- package/dist/bindings-DIanvIVd.mjs +211 -0
- package/dist/bindings-DvV2DXWi.cjs +253 -0
- package/dist/bindings-NV0CdqGl.d.cts +20 -0
- package/dist/core/index.cjs +12 -2
- package/dist/core/index.d.cts +2 -2
- package/dist/core/index.d.mts +2 -2
- package/dist/core/index.mjs +9 -2
- package/dist/decorators/index.cjs +5 -0
- package/dist/decorators/index.d.cts +2 -0
- package/dist/decorators/index.d.mts +2 -0
- package/dist/decorators/index.mjs +3 -0
- package/dist/decorators/setup.cjs +15 -0
- package/dist/decorators/setup.d.cts +2 -0
- package/dist/decorators/setup.d.mts +2 -0
- package/dist/decorators/setup.mjs +13 -0
- package/dist/express/index.cjs +26 -9
- package/dist/express/index.d.cts +1 -1
- package/dist/express/index.d.mts +1 -1
- package/dist/express/index.mjs +26 -9
- package/dist/fastify/index.cjs +24 -8
- package/dist/fastify/index.d.cts +4 -2
- package/dist/fastify/index.d.mts +4 -2
- package/dist/fastify/index.mjs +24 -8
- package/dist/h3/index.cjs +26 -9
- package/dist/h3/index.d.cts +1 -1
- package/dist/h3/index.d.mts +1 -1
- package/dist/h3/index.mjs +26 -9
- package/dist/hono/index.cjs +28 -11
- package/dist/hono/index.d.cts +4 -2
- package/dist/hono/index.d.mts +4 -2
- package/dist/hono/index.mjs +28 -11
- package/dist/index.cjs +308 -28
- package/dist/index.d.cts +112 -18
- package/dist/index.d.mts +112 -18
- package/dist/index.mjs +305 -28
- package/dist/koa/index.cjs +24 -8
- package/dist/koa/index.d.cts +4 -2
- package/dist/koa/index.d.mts +4 -2
- package/dist/koa/index.mjs +24 -8
- package/dist/{responses-B-UirWFf.cjs → responses-JzXstGU5.cjs} +18 -1
- package/dist/{responses-CJaD0ugv.mjs → responses-_II3dOJ5.mjs} +19 -1
- package/dist/{router-BReOXz-F.mjs → router-B3QjblRX.mjs} +159 -48
- package/dist/{router-CS_2XQ7I.d.cts → router-BYZmNzrZ.d.cts} +97 -12
- package/dist/{router-CHg0pZUO.cjs → router-CU4V1kX0.cjs} +159 -48
- package/dist/{router-_w2VzMQF.d.mts → router-DCMtQ_Xi.d.mts} +96 -11
- package/dist/types/basic.d.mts +7 -0
- package/dist/types/core/Request.d.mts +25 -0
- package/dist/types/core/Response.d.mts +21 -0
- package/dist/types/express.d.mts +5 -2
- package/dist/types/fastify.d.mts +5 -2
- package/dist/types/h3.d.mts +5 -2
- package/dist/types/hono.d.mts +5 -2
- package/dist/types/koa.d.mts +5 -2
- package/package.json +16 -2
package/dist/hono/index.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import "../bindings-DIanvIVd.mjs";
|
|
2
|
+
import { t as CoreRouter } from "../router-B3QjblRX.mjs";
|
|
3
|
+
import { n as resolveResponseMeta } from "../responses-_II3dOJ5.mjs";
|
|
3
4
|
|
|
4
5
|
//#region src/hono/router.ts
|
|
5
6
|
/**
|
|
@@ -19,9 +20,13 @@ var Router = class Router extends CoreRouter {
|
|
|
19
20
|
});
|
|
20
21
|
if (!meta) return void 0;
|
|
21
22
|
if (meta.isNativeResponse) return meta.body;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
const headers = meta.headers ? {} : meta.contentType ? { "Content-Type": meta.contentType } : void 0;
|
|
24
|
+
meta.headers?.forEach((headerValue, key) => {
|
|
25
|
+
if (headers) headers[key] = headerValue;
|
|
26
|
+
});
|
|
27
|
+
if (meta.isEmpty) return ctx.body(null, meta.status, headers);
|
|
28
|
+
if (meta.contentType?.startsWith("application/json")) return ctx.body(JSON.stringify(meta.body), meta.status, headers);
|
|
29
|
+
return ctx.body(meta.body, meta.status, headers);
|
|
25
30
|
}
|
|
26
31
|
static getParams(ctx) {
|
|
27
32
|
try {
|
|
@@ -168,10 +173,18 @@ var Router = class Router extends CoreRouter {
|
|
|
168
173
|
for (const route of this.routes) {
|
|
169
174
|
let handlerFunction = null;
|
|
170
175
|
let instance = null;
|
|
176
|
+
let bindingTarget;
|
|
177
|
+
let bindingMethod;
|
|
178
|
+
let bindingHandler;
|
|
179
|
+
let bindingMetadata;
|
|
171
180
|
try {
|
|
172
181
|
const resolved = this.resolveHandler(route);
|
|
173
182
|
handlerFunction = resolved.handlerFunction;
|
|
174
183
|
instance = resolved.instance;
|
|
184
|
+
bindingTarget = resolved.bindingTarget;
|
|
185
|
+
bindingMethod = resolved.bindingMethod;
|
|
186
|
+
bindingHandler = resolved.bindingHandler;
|
|
187
|
+
bindingMetadata = resolved.bindingMetadata;
|
|
175
188
|
} catch (error) {
|
|
176
189
|
console.error(`[ROUTES] Error setting up route ${route.path}:`, error.message);
|
|
177
190
|
throw error;
|
|
@@ -198,11 +211,13 @@ var Router = class Router extends CoreRouter {
|
|
|
198
211
|
Router.bindRequestToInstance(ctx, inst, route, {
|
|
199
212
|
body: reqBody,
|
|
200
213
|
query: ctx.req.query(),
|
|
201
|
-
params: Router.getParams(ctx)
|
|
214
|
+
params: Router.getParams(ctx),
|
|
215
|
+
method
|
|
202
216
|
});
|
|
203
|
-
const result = handlerFunction
|
|
217
|
+
const result = await Router.callHandler(handlerFunction, ctx, bindingTarget, bindingMethod, bindingHandler, bindingMetadata);
|
|
204
218
|
const resolved = await Promise.resolve(result);
|
|
205
|
-
|
|
219
|
+
const outgoing = typeof resolved === "undefined" && ctx.clearResponse?.sent ? ctx.clearResponse : resolved;
|
|
220
|
+
return Router.toResponse(ctx, outgoing, method, route.path);
|
|
206
221
|
});
|
|
207
222
|
if ([
|
|
208
223
|
"put",
|
|
@@ -216,11 +231,13 @@ var Router = class Router extends CoreRouter {
|
|
|
216
231
|
Router.bindRequestToInstance(ctx, inst, route, {
|
|
217
232
|
body: reqBody,
|
|
218
233
|
query: ctx.req.query(),
|
|
219
|
-
params: Router.getParams(ctx)
|
|
234
|
+
params: Router.getParams(ctx),
|
|
235
|
+
method
|
|
220
236
|
});
|
|
221
|
-
const result = handlerFunction
|
|
237
|
+
const result = await Router.callHandler(handlerFunction, ctx, bindingTarget, bindingMethod, bindingHandler, bindingMetadata);
|
|
222
238
|
const resolved = await Promise.resolve(result);
|
|
223
|
-
|
|
239
|
+
const outgoing = typeof resolved === "undefined" && ctx.clearResponse?.sent ? ctx.clearResponse : resolved;
|
|
240
|
+
return Router.toResponse(ctx, outgoing, method, route.path);
|
|
224
241
|
});
|
|
225
242
|
}
|
|
226
243
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -59,6 +59,152 @@ var Route = class {
|
|
|
59
59
|
}
|
|
60
60
|
};
|
|
61
61
|
|
|
62
|
+
//#endregion
|
|
63
|
+
//#region src/core/Request.ts
|
|
64
|
+
var Request = class extends ClearRequest {
|
|
65
|
+
original;
|
|
66
|
+
method = "GET";
|
|
67
|
+
path = "/";
|
|
68
|
+
url = "/";
|
|
69
|
+
headers = {};
|
|
70
|
+
constructor(init) {
|
|
71
|
+
super(init);
|
|
72
|
+
Object.assign(this, init);
|
|
73
|
+
}
|
|
74
|
+
getBody() {
|
|
75
|
+
return this.body ?? {};
|
|
76
|
+
}
|
|
77
|
+
header(name) {
|
|
78
|
+
if (typeof this.headers.get === "function") return this.headers.get(name) || "";
|
|
79
|
+
const headers = this.headers;
|
|
80
|
+
const value = headers[name] ?? headers[name.toLowerCase()];
|
|
81
|
+
return Array.isArray(value) ? String(value[0] ?? "") : String(value ?? "");
|
|
82
|
+
}
|
|
83
|
+
param(name) {
|
|
84
|
+
return this.params?.[name];
|
|
85
|
+
}
|
|
86
|
+
input(name) {
|
|
87
|
+
return this.body?.[name] ?? this.query?.[name] ?? this.params?.[name];
|
|
88
|
+
}
|
|
89
|
+
is(method) {
|
|
90
|
+
return this.method.toLowerCase() === String(method).toLowerCase();
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
//#endregion
|
|
95
|
+
//#region src/core/Response.ts
|
|
96
|
+
var Response = class {
|
|
97
|
+
body;
|
|
98
|
+
headers = new Headers();
|
|
99
|
+
sent = false;
|
|
100
|
+
statusCode = 200;
|
|
101
|
+
constructor(init) {
|
|
102
|
+
Object.assign(this, init);
|
|
103
|
+
if (init?.headers && !(init.headers instanceof Headers)) this.headers = new Headers(init.headers);
|
|
104
|
+
}
|
|
105
|
+
status(code) {
|
|
106
|
+
this.statusCode = code;
|
|
107
|
+
return this;
|
|
108
|
+
}
|
|
109
|
+
code(code) {
|
|
110
|
+
return this.status(code);
|
|
111
|
+
}
|
|
112
|
+
setHeader(name, value) {
|
|
113
|
+
this.headers.set(name, value);
|
|
114
|
+
return this;
|
|
115
|
+
}
|
|
116
|
+
header(name, value) {
|
|
117
|
+
return this.setHeader(name, value);
|
|
118
|
+
}
|
|
119
|
+
set(name, value) {
|
|
120
|
+
return this.setHeader(name, value);
|
|
121
|
+
}
|
|
122
|
+
type(contentType) {
|
|
123
|
+
return this.setHeader("Content-Type", contentType);
|
|
124
|
+
}
|
|
125
|
+
send(body) {
|
|
126
|
+
this.body = body;
|
|
127
|
+
this.sent = true;
|
|
128
|
+
return this;
|
|
129
|
+
}
|
|
130
|
+
json(body) {
|
|
131
|
+
return this.type("application/json; charset=utf-8").send(body);
|
|
132
|
+
}
|
|
133
|
+
html(body) {
|
|
134
|
+
return this.type("text/html; charset=utf-8").send(body);
|
|
135
|
+
}
|
|
136
|
+
text(body) {
|
|
137
|
+
return this.type("text/plain; charset=utf-8").send(body);
|
|
138
|
+
}
|
|
139
|
+
noContent() {
|
|
140
|
+
return this.status(204).send(null);
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
//#endregion
|
|
145
|
+
//#region src/core/plugins.ts
|
|
146
|
+
function definePlugin(plugin) {
|
|
147
|
+
return plugin;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
//#endregion
|
|
151
|
+
//#region src/core/bindings.ts
|
|
152
|
+
const metadataKey = Symbol.for("clear-router:binding-metadata");
|
|
153
|
+
const bindings = /* @__PURE__ */ new WeakMap();
|
|
154
|
+
var Container = class {
|
|
155
|
+
static registry = /* @__PURE__ */ new Map();
|
|
156
|
+
static bind(token, value) {
|
|
157
|
+
this.registry.set(token, value);
|
|
158
|
+
}
|
|
159
|
+
static unbind(token) {
|
|
160
|
+
this.registry.delete(token);
|
|
161
|
+
}
|
|
162
|
+
static clear() {
|
|
163
|
+
this.registry.clear();
|
|
164
|
+
}
|
|
165
|
+
static has(token) {
|
|
166
|
+
return this.registry.has(token);
|
|
167
|
+
}
|
|
168
|
+
static async resolve(token, ctx, autoDiscover = false) {
|
|
169
|
+
if (token === Request) return ctx.clearRequest;
|
|
170
|
+
if (token === Response) return ctx.clearResponse;
|
|
171
|
+
if (this.registry.has(token)) return this.resolveBinding(this.registry.get(token), ctx, autoDiscover);
|
|
172
|
+
if (autoDiscover && typeof token === "function") return new token();
|
|
173
|
+
}
|
|
174
|
+
static async resolveBinding(binding, ctx, autoDiscover) {
|
|
175
|
+
if (!binding) return void 0;
|
|
176
|
+
if (typeof binding !== "function") return binding;
|
|
177
|
+
if (isClass(binding)) return new binding();
|
|
178
|
+
const resolved = await binding(ctx);
|
|
179
|
+
if (typeof resolved === "function" && autoDiscover && isClass(resolved)) return new resolved();
|
|
180
|
+
return resolved;
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
function getStandardMetadata(metadata, propertyKey) {
|
|
184
|
+
const store = metadata && metadata[metadataKey];
|
|
185
|
+
if (!store) return void 0;
|
|
186
|
+
return propertyKey ? store[propertyKey] : void 0;
|
|
187
|
+
}
|
|
188
|
+
function getBindingMetadataFromTargets(targets) {
|
|
189
|
+
for (const { target, propertyKey } of targets) {
|
|
190
|
+
if (!target) continue;
|
|
191
|
+
const metadata = getBindingMetadata(target, propertyKey);
|
|
192
|
+
if (metadata) return metadata;
|
|
193
|
+
const standardMetadata = getStandardMetadata(target[Symbol.metadata], propertyKey);
|
|
194
|
+
if (standardMetadata) return standardMetadata;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
function getBindingMetadata(target, propertyKey) {
|
|
198
|
+
if (propertyKey) return bindings.get(target)?.get(propertyKey);
|
|
199
|
+
return bindings.get(target)?.get("__route_handler__");
|
|
200
|
+
}
|
|
201
|
+
function getDesignParamTypes(target, propertyKey) {
|
|
202
|
+
return Reflect.getMetadata?.("design:paramtypes", target, propertyKey) ?? [];
|
|
203
|
+
}
|
|
204
|
+
function isClass(value) {
|
|
205
|
+
return typeof value === "function" && /^class\s/.test(Function.prototype.toString.call(value));
|
|
206
|
+
}
|
|
207
|
+
|
|
62
208
|
//#endregion
|
|
63
209
|
//#region src/core/router.ts
|
|
64
210
|
/**
|
|
@@ -71,6 +217,41 @@ var CoreRouter = class {
|
|
|
71
217
|
static routerStateNamespace = "clear-router:core";
|
|
72
218
|
static stateStoreKey = Symbol.for("clear-router:router-state");
|
|
73
219
|
static stateBoundKey = Symbol.for("clear-router:router-state-bound");
|
|
220
|
+
static defaultConfigKey = Symbol.for("clear-router:default-config");
|
|
221
|
+
static pluginStoreKey = Symbol.for("clear-router:plugins");
|
|
222
|
+
static createBaseConfig() {
|
|
223
|
+
return {
|
|
224
|
+
methodOverride: {
|
|
225
|
+
enabled: true,
|
|
226
|
+
bodyKeys: ["_method"],
|
|
227
|
+
headerKeys: ["x-http-method"]
|
|
228
|
+
},
|
|
229
|
+
container: {
|
|
230
|
+
enabled: false,
|
|
231
|
+
autoDiscover: false
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
static mergeConfig(target, source) {
|
|
236
|
+
if (!source) return target;
|
|
237
|
+
if (source.methodOverride) target.methodOverride = {
|
|
238
|
+
...target.methodOverride || {},
|
|
239
|
+
...source.methodOverride
|
|
240
|
+
};
|
|
241
|
+
if (source.container) target.container = {
|
|
242
|
+
...target.container || {},
|
|
243
|
+
...source.container
|
|
244
|
+
};
|
|
245
|
+
return target;
|
|
246
|
+
}
|
|
247
|
+
static getDefaultConfig() {
|
|
248
|
+
const g = globalThis;
|
|
249
|
+
if (!g[this.defaultConfigKey]) g[this.defaultConfigKey] = this.createBaseConfig();
|
|
250
|
+
return {
|
|
251
|
+
methodOverride: { ...g[this.defaultConfigKey].methodOverride },
|
|
252
|
+
container: { ...g[this.defaultConfigKey].container }
|
|
253
|
+
};
|
|
254
|
+
}
|
|
74
255
|
static resolveStateNamespace() {
|
|
75
256
|
return String(this.routerStateNamespace || this.name || "clear-router:core");
|
|
76
257
|
}
|
|
@@ -79,13 +260,14 @@ var CoreRouter = class {
|
|
|
79
260
|
if (!g[this.stateStoreKey]) g[this.stateStoreKey] = Object.create(null);
|
|
80
261
|
return g[this.stateStoreKey];
|
|
81
262
|
}
|
|
263
|
+
static getPluginStore() {
|
|
264
|
+
const g = globalThis;
|
|
265
|
+
if (!g[this.pluginStoreKey]) g[this.pluginStoreKey] = /* @__PURE__ */ new Set();
|
|
266
|
+
return g[this.pluginStoreKey];
|
|
267
|
+
}
|
|
82
268
|
static createDefaultState() {
|
|
83
269
|
return {
|
|
84
|
-
config:
|
|
85
|
-
enabled: true,
|
|
86
|
-
bodyKeys: ["_method"],
|
|
87
|
-
headerKeys: ["x-http-method"]
|
|
88
|
-
} },
|
|
270
|
+
config: this.getDefaultConfig(),
|
|
89
271
|
groupContext: new node_async_hooks.AsyncLocalStorage(),
|
|
90
272
|
routes: [],
|
|
91
273
|
routesByPathMethod: {},
|
|
@@ -162,11 +344,47 @@ var CoreRouter = class {
|
|
|
162
344
|
}
|
|
163
345
|
};
|
|
164
346
|
}
|
|
165
|
-
static config = {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
347
|
+
static config = {
|
|
348
|
+
methodOverride: {
|
|
349
|
+
enabled: true,
|
|
350
|
+
bodyKeys: ["_method"],
|
|
351
|
+
headerKeys: ["x-http-method"]
|
|
352
|
+
},
|
|
353
|
+
container: {
|
|
354
|
+
enabled: false,
|
|
355
|
+
autoDiscover: false
|
|
356
|
+
}
|
|
357
|
+
};
|
|
358
|
+
static configureDefaults(options) {
|
|
359
|
+
const g = globalThis;
|
|
360
|
+
const defaults = this.mergeConfig(g[this.defaultConfigKey] || this.createBaseConfig(), options);
|
|
361
|
+
g[this.defaultConfigKey] = defaults;
|
|
362
|
+
const store = this.getStateStore();
|
|
363
|
+
for (const state of Object.values(store)) state.config = this.mergeConfig(state.config || this.createBaseConfig(), options);
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Use a registered plugin
|
|
367
|
+
*
|
|
368
|
+
* @param this
|
|
369
|
+
* @param plugin
|
|
370
|
+
* @param options
|
|
371
|
+
* @returns
|
|
372
|
+
*/
|
|
373
|
+
static use(plugin, options) {
|
|
374
|
+
const name = typeof plugin === "function" ? plugin.name : plugin.name;
|
|
375
|
+
const store = this.getPluginStore();
|
|
376
|
+
if (name && store.has(name)) return;
|
|
377
|
+
const ctx = {
|
|
378
|
+
container: Container,
|
|
379
|
+
bind: Container.bind.bind(Container),
|
|
380
|
+
configure: this.configure.bind(this),
|
|
381
|
+
configureDefaults: this.configureDefaults.bind(this),
|
|
382
|
+
options
|
|
383
|
+
};
|
|
384
|
+
if (typeof plugin === "function") plugin(ctx);
|
|
385
|
+
else plugin.setup(ctx);
|
|
386
|
+
if (name) store.add(name);
|
|
387
|
+
}
|
|
170
388
|
static groupContext = new node_async_hooks.AsyncLocalStorage();
|
|
171
389
|
static routes = [];
|
|
172
390
|
static routesByPathMethod = {};
|
|
@@ -208,11 +426,12 @@ var CoreRouter = class {
|
|
|
208
426
|
*/
|
|
209
427
|
static configure(options) {
|
|
210
428
|
this.ensureState();
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
429
|
+
this.config = this.mergeConfig(this.getDefaultConfig(), this.config);
|
|
430
|
+
const container = options?.container;
|
|
431
|
+
if (container) {
|
|
432
|
+
if (typeof container.enabled === "boolean") this.config.container.enabled = container.enabled;
|
|
433
|
+
if (typeof container.autoDiscover === "boolean") this.config.container.autoDiscover = container.autoDiscover;
|
|
434
|
+
}
|
|
216
435
|
const override = options?.methodOverride;
|
|
217
436
|
if (!override) return;
|
|
218
437
|
if (typeof override.enabled === "boolean") this.config.methodOverride.enabled = override.enabled;
|
|
@@ -449,36 +668,94 @@ var CoreRouter = class {
|
|
|
449
668
|
static resolveHandler(route) {
|
|
450
669
|
let handlerFunction;
|
|
451
670
|
let instance = null;
|
|
452
|
-
|
|
453
|
-
|
|
671
|
+
let bindingTarget;
|
|
672
|
+
let bindingMethod;
|
|
673
|
+
let bindingHandler;
|
|
674
|
+
let bindingMetadata;
|
|
675
|
+
if (typeof route.handler === "function") {
|
|
676
|
+
handlerFunction = route.handler.bind(route);
|
|
677
|
+
bindingTarget = route.handler;
|
|
678
|
+
bindingHandler = route.handler;
|
|
679
|
+
} else if (Array.isArray(route.handler) && route.handler.length === 2) {
|
|
454
680
|
const [ControllerType, method] = route.handler;
|
|
455
681
|
if (["function", "object"].includes(typeof ControllerType) && typeof ControllerType[method] === "function") {
|
|
456
682
|
instance = ControllerType;
|
|
457
683
|
handlerFunction = ControllerType[method].bind(ControllerType);
|
|
684
|
+
bindingTarget = ControllerType;
|
|
685
|
+
bindingMethod = method;
|
|
686
|
+
bindingHandler = ControllerType[method];
|
|
687
|
+
bindingMetadata = ControllerType[Symbol.metadata];
|
|
458
688
|
} else if (typeof ControllerType === "function") {
|
|
459
689
|
instance = new ControllerType();
|
|
460
|
-
if (typeof instance[method] === "function")
|
|
461
|
-
|
|
690
|
+
if (typeof instance[method] === "function") {
|
|
691
|
+
handlerFunction = instance[method].bind(instance);
|
|
692
|
+
bindingTarget = ControllerType.prototype;
|
|
693
|
+
bindingMethod = method;
|
|
694
|
+
bindingHandler = instance[method];
|
|
695
|
+
bindingMetadata = ControllerType[Symbol.metadata];
|
|
696
|
+
} else throw new Error(`Method "${method}" not found in controller instance "${ControllerType.name}"`);
|
|
462
697
|
} else throw new Error(`Invalid controller type for route: ${route.path}`);
|
|
463
698
|
} else throw new Error(`Invalid handler format for route: ${route.path}`);
|
|
464
699
|
return {
|
|
465
700
|
handlerFunction,
|
|
466
|
-
instance
|
|
701
|
+
instance,
|
|
702
|
+
bindingTarget,
|
|
703
|
+
bindingMethod,
|
|
704
|
+
bindingHandler,
|
|
705
|
+
bindingMetadata
|
|
467
706
|
};
|
|
468
707
|
}
|
|
708
|
+
static async callHandler(handlerFunction, ctx, bindingTarget, bindingMethod, bindingHandler, bindingMetadata) {
|
|
709
|
+
if (!this.config.container?.enabled) return handlerFunction(ctx, ctx.clearRequest);
|
|
710
|
+
const metadata = getBindingMetadataFromTargets([
|
|
711
|
+
{
|
|
712
|
+
target: bindingTarget,
|
|
713
|
+
propertyKey: bindingMethod
|
|
714
|
+
},
|
|
715
|
+
{ target: bindingHandler },
|
|
716
|
+
{
|
|
717
|
+
target: bindingTarget,
|
|
718
|
+
propertyKey: "__class__"
|
|
719
|
+
}
|
|
720
|
+
]) ?? getStandardMetadata(bindingMetadata, bindingMethod) ?? getStandardMetadata(bindingMetadata, "__class__");
|
|
721
|
+
if (!metadata) return handlerFunction(ctx, ctx.clearRequest);
|
|
722
|
+
const designTokens = [...bindingTarget ? getDesignParamTypes(bindingTarget, bindingMethod) : [], ...bindingHandler ? getDesignParamTypes(bindingHandler) : []];
|
|
723
|
+
const tokens = metadata.tokens?.length ? metadata.tokens : designTokens;
|
|
724
|
+
if (!tokens.length) return handlerFunction(ctx, ctx.clearRequest);
|
|
725
|
+
const args = [];
|
|
726
|
+
for (const token of tokens) {
|
|
727
|
+
const resolved = await Container.resolve(token, ctx, Boolean(this.config.container?.autoDiscover));
|
|
728
|
+
if (typeof resolved === "undefined") return handlerFunction(ctx, ctx.clearRequest);
|
|
729
|
+
args.push(resolved);
|
|
730
|
+
}
|
|
731
|
+
return handlerFunction(...args);
|
|
732
|
+
}
|
|
469
733
|
static bindRequestToInstance(ctx, instance, route, payload) {
|
|
734
|
+
const clearRequest = ctx.clearRequest instanceof Request ? ctx.clearRequest : new Request({
|
|
735
|
+
ctx,
|
|
736
|
+
route,
|
|
737
|
+
body: payload.body,
|
|
738
|
+
query: payload.query,
|
|
739
|
+
params: payload.params,
|
|
740
|
+
method: String(payload.method || ctx.req?.method || ctx.method || "GET").toUpperCase(),
|
|
741
|
+
path: String(ctx.path || ctx.req?.path || ctx.req?.url || route.path),
|
|
742
|
+
url: String(ctx.url || ctx.req?.url || ctx.req?.originalUrl || route.path),
|
|
743
|
+
headers: ctx.req?.headers || ctx.headers || {},
|
|
744
|
+
original: ctx.req || ctx.request || ctx
|
|
745
|
+
});
|
|
746
|
+
clearRequest.ctx = ctx;
|
|
747
|
+
clearRequest.route = route;
|
|
748
|
+
clearRequest.body = payload.body;
|
|
749
|
+
clearRequest.query = payload.query;
|
|
750
|
+
clearRequest.params = payload.params;
|
|
751
|
+
ctx.clearRequest = clearRequest;
|
|
752
|
+
if (!(ctx.clearResponse instanceof Response)) ctx.clearResponse = new Response();
|
|
470
753
|
if (!instance) return;
|
|
471
754
|
instance.ctx = ctx;
|
|
472
755
|
instance.body = payload.body;
|
|
473
756
|
instance.query = payload.query;
|
|
474
757
|
instance.params = payload.params;
|
|
475
|
-
instance.clearRequest =
|
|
476
|
-
ctx,
|
|
477
|
-
route,
|
|
478
|
-
body: instance.body,
|
|
479
|
-
query: instance.query,
|
|
480
|
-
params: instance.params
|
|
481
|
-
});
|
|
758
|
+
instance.clearRequest = clearRequest;
|
|
482
759
|
}
|
|
483
760
|
};
|
|
484
761
|
|
|
@@ -486,4 +763,7 @@ var CoreRouter = class {
|
|
|
486
763
|
exports.ClearRequest = ClearRequest;
|
|
487
764
|
exports.Controller = Controller;
|
|
488
765
|
exports.CoreRouter = CoreRouter;
|
|
489
|
-
exports.
|
|
766
|
+
exports.Request = Request;
|
|
767
|
+
exports.Response = Response;
|
|
768
|
+
exports.Route = Route;
|
|
769
|
+
exports.definePlugin = definePlugin;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { NextFunction, Request, Response as Response$
|
|
2
|
-
import { Middleware } from "h3";
|
|
1
|
+
import { NextFunction, Request as Request$1, Response as Response$2 } from "express";
|
|
2
|
+
import { Middleware as Middleware$1 } from "h3";
|
|
3
3
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
4
4
|
|
|
5
5
|
//#region types/basic.d.ts
|
|
@@ -26,16 +26,37 @@ interface RouterConfig {
|
|
|
26
26
|
bodyKeys?: string[] | string; /** Keys in the request headers to check for method override */
|
|
27
27
|
headerKeys?: string[] | string;
|
|
28
28
|
};
|
|
29
|
+
/**
|
|
30
|
+
* Optional method binding / container resolution support. Disabled by default.
|
|
31
|
+
*/
|
|
32
|
+
container?: {
|
|
33
|
+
/** Whether decorated handler parameter binding is enabled */enabled?: boolean; /** Whether unknown constructor tokens should be instantiated automatically */
|
|
34
|
+
autoDiscover?: boolean;
|
|
35
|
+
};
|
|
29
36
|
}
|
|
30
37
|
//#endregion
|
|
31
|
-
//#region
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
38
|
+
//#region src/core/Response.d.ts
|
|
39
|
+
declare class Response$1 {
|
|
40
|
+
body: any;
|
|
41
|
+
headers: Headers;
|
|
42
|
+
sent: boolean;
|
|
43
|
+
statusCode: number;
|
|
44
|
+
constructor(init?: Partial<Response$1>);
|
|
45
|
+
status(code: number): this;
|
|
46
|
+
code(code: number): this;
|
|
47
|
+
setHeader(name: string, value: string): this;
|
|
48
|
+
header(name: string, value: string): this;
|
|
49
|
+
set(name: string, value: string): this;
|
|
50
|
+
type(contentType: string): this;
|
|
51
|
+
send(body?: any): this;
|
|
52
|
+
json(body: any): this;
|
|
53
|
+
html(body: string): this;
|
|
54
|
+
text(body: string): this;
|
|
55
|
+
noContent(): this;
|
|
56
|
+
}
|
|
36
57
|
//#endregion
|
|
37
58
|
//#region src/Route.d.ts
|
|
38
|
-
declare class Route<X = any, M = Middleware | Middleware
|
|
59
|
+
declare class Route<X = any, M = Middleware$1 | Middleware, H = any> {
|
|
39
60
|
ctx: X;
|
|
40
61
|
body: RequestData;
|
|
41
62
|
query: RequestData;
|
|
@@ -52,8 +73,34 @@ declare class Route<X = any, M = Middleware | Middleware$1, H = any> {
|
|
|
52
73
|
constructor(methods: HttpMethod[], path: string, handler: H, middlewares?: M[]);
|
|
53
74
|
}
|
|
54
75
|
//#endregion
|
|
76
|
+
//#region src/core/Request.d.ts
|
|
77
|
+
declare class Request<X = any, M = any> extends ClearRequest<X, M> {
|
|
78
|
+
original?: any;
|
|
79
|
+
method: string;
|
|
80
|
+
path: string;
|
|
81
|
+
url: string;
|
|
82
|
+
headers: Headers | Record<string, any>;
|
|
83
|
+
constructor(init?: Partial<Request<X, M>> & {
|
|
84
|
+
body?: RequestData;
|
|
85
|
+
query?: RequestData;
|
|
86
|
+
params?: RequestData;
|
|
87
|
+
route?: Route<X, M>;
|
|
88
|
+
});
|
|
89
|
+
getBody(): RequestData;
|
|
90
|
+
header(name: string): string;
|
|
91
|
+
param(name: string): any;
|
|
92
|
+
input(name: string): any;
|
|
93
|
+
is(method: HttpMethod | string): boolean;
|
|
94
|
+
}
|
|
95
|
+
//#endregion
|
|
96
|
+
//#region types/express.d.ts
|
|
97
|
+
/**
|
|
98
|
+
* Middleware function type
|
|
99
|
+
*/
|
|
100
|
+
type Middleware = (req: Request$1, res: Response$2, next: NextFunction) => any | Promise<any>;
|
|
101
|
+
//#endregion
|
|
55
102
|
//#region src/ClearRequest.d.ts
|
|
56
|
-
declare class ClearRequest<X = any, M = Middleware | Middleware
|
|
103
|
+
declare class ClearRequest<X = any, M = Middleware$1 | Middleware> {
|
|
57
104
|
[key: string]: any;
|
|
58
105
|
/**
|
|
59
106
|
* @param body - Parsed request body
|
|
@@ -81,6 +128,37 @@ declare abstract class Controller<X = any> {
|
|
|
81
128
|
clearRequest: ClearRequest;
|
|
82
129
|
}
|
|
83
130
|
//#endregion
|
|
131
|
+
//#region src/core/bindings.d.ts
|
|
132
|
+
type BindToken<T = any> = abstract new (...args: any[]) => T;
|
|
133
|
+
type BindFactory<T = any> = (ctx: any) => T | Promise<T>;
|
|
134
|
+
type BindValue<T = any> = T | BindFactory<T> | BindToken<T>;
|
|
135
|
+
declare class Container {
|
|
136
|
+
private static readonly registry;
|
|
137
|
+
static bind<T>(token: BindToken<T>, value: BindValue<T>): void;
|
|
138
|
+
static unbind<T>(token: BindToken<T>): void;
|
|
139
|
+
static clear(): void;
|
|
140
|
+
static has<T>(token: BindToken<T>): boolean;
|
|
141
|
+
static resolve<T>(token: BindToken<T>, ctx: any, autoDiscover?: boolean): Promise<T | undefined>;
|
|
142
|
+
private static resolveBinding;
|
|
143
|
+
}
|
|
144
|
+
//#endregion
|
|
145
|
+
//#region src/core/plugins.d.ts
|
|
146
|
+
type PluginSetupResult = void;
|
|
147
|
+
type PluginBind = <T>(token: BindToken<T>, value: BindValue<T>) => void;
|
|
148
|
+
interface ClearRouterPluginContext<Options = any> {
|
|
149
|
+
container: typeof Container;
|
|
150
|
+
bind: PluginBind;
|
|
151
|
+
configure: (options: RouterConfig) => void;
|
|
152
|
+
configureDefaults: (options: RouterConfig) => void;
|
|
153
|
+
options: Options;
|
|
154
|
+
}
|
|
155
|
+
interface ClearRouterPlugin<Options = any> {
|
|
156
|
+
name?: string;
|
|
157
|
+
setup: (ctx: ClearRouterPluginContext<Options>) => PluginSetupResult;
|
|
158
|
+
}
|
|
159
|
+
type ClearRouterPluginInput<Options = any> = ClearRouterPlugin<Options> | ((ctx: ClearRouterPluginContext<Options>) => PluginSetupResult);
|
|
160
|
+
declare function definePlugin<Options = any>(plugin: ClearRouterPlugin<Options>): ClearRouterPlugin<Options>;
|
|
161
|
+
//#endregion
|
|
84
162
|
//#region src/core/router.d.ts
|
|
85
163
|
/**
|
|
86
164
|
* @class clear-router CoreRouter
|
|
@@ -92,16 +170,16 @@ declare abstract class CoreRouter {
|
|
|
92
170
|
protected static routerStateNamespace: string;
|
|
93
171
|
private static readonly stateStoreKey;
|
|
94
172
|
private static readonly stateBoundKey;
|
|
173
|
+
private static readonly defaultConfigKey;
|
|
174
|
+
private static readonly pluginStoreKey;
|
|
175
|
+
protected static createBaseConfig(): RouterConfig;
|
|
176
|
+
protected static mergeConfig(target: RouterConfig, source?: RouterConfig): RouterConfig;
|
|
177
|
+
protected static getDefaultConfig(): RouterConfig;
|
|
95
178
|
protected static resolveStateNamespace(this: any): string;
|
|
96
179
|
protected static getStateStore(): Record<string, any>;
|
|
180
|
+
protected static getPluginStore(): Set<string>;
|
|
97
181
|
protected static createDefaultState(): {
|
|
98
|
-
config:
|
|
99
|
-
methodOverride: {
|
|
100
|
-
enabled: boolean;
|
|
101
|
-
bodyKeys: string[];
|
|
102
|
-
headerKeys: string[];
|
|
103
|
-
};
|
|
104
|
-
};
|
|
182
|
+
config: RouterConfig;
|
|
105
183
|
groupContext: AsyncLocalStorage<{
|
|
106
184
|
prefix: string;
|
|
107
185
|
groupMiddlewares: any[];
|
|
@@ -116,6 +194,16 @@ declare abstract class CoreRouter {
|
|
|
116
194
|
protected static bindStateAccessors(this: any): void;
|
|
117
195
|
protected static createDefaultOptionsHandler(): any;
|
|
118
196
|
static config: RouterConfig;
|
|
197
|
+
static configureDefaults(this: any, options?: RouterConfig): void;
|
|
198
|
+
/**
|
|
199
|
+
* Use a registered plugin
|
|
200
|
+
*
|
|
201
|
+
* @param this
|
|
202
|
+
* @param plugin
|
|
203
|
+
* @param options
|
|
204
|
+
* @returns
|
|
205
|
+
*/
|
|
206
|
+
static use<Options = any>(this: any, plugin: ClearRouterPluginInput<Options>, options?: Options): void;
|
|
119
207
|
protected static groupContext: AsyncLocalStorage<{
|
|
120
208
|
prefix: string;
|
|
121
209
|
groupMiddlewares: any[];
|
|
@@ -265,14 +353,20 @@ declare abstract class CoreRouter {
|
|
|
265
353
|
*/
|
|
266
354
|
static allRoutes(this: any, type: 'method'): { [method in Uppercase<HttpMethod>]?: Array<Route<any, any, any>> };
|
|
267
355
|
protected static resolveHandler(route: Route<any, any, any>): {
|
|
268
|
-
handlerFunction: ((ctx: any, req:
|
|
356
|
+
handlerFunction: ((ctx: any, req: Request) => any | Promise<any>) | null;
|
|
269
357
|
instance: Controller<any> | null;
|
|
358
|
+
bindingTarget?: object;
|
|
359
|
+
bindingMethod?: PropertyKey;
|
|
360
|
+
bindingHandler?: object;
|
|
361
|
+
bindingMetadata?: object;
|
|
270
362
|
};
|
|
363
|
+
protected static callHandler(this: any, handlerFunction: (ctx: any, req: Request) => any | Promise<any>, ctx: any, bindingTarget?: object, bindingMethod?: PropertyKey, bindingHandler?: object, bindingMetadata?: object): Promise<any>;
|
|
271
364
|
protected static bindRequestToInstance(ctx: any, instance: Controller<any> | Route<any, any, any> | null, route: Route<any, any, any>, payload: {
|
|
272
365
|
body: Record<string, any>;
|
|
273
366
|
query: Record<string, any>;
|
|
274
367
|
params: Record<string, any>;
|
|
368
|
+
method?: HttpMethod | string;
|
|
275
369
|
}): void;
|
|
276
370
|
}
|
|
277
371
|
//#endregion
|
|
278
|
-
export { ClearRequest, Controller, CoreRouter, Route };
|
|
372
|
+
export { ClearRequest, ClearRouterPlugin, ClearRouterPluginContext, ClearRouterPluginInput, Controller, CoreRouter, PluginBind, PluginSetupResult, Request, Response$1 as Response, Route, definePlugin };
|