@moostjs/event-http 0.5.33 → 0.6.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/README.md +67 -3
- package/dist/index.cjs +261 -83
- package/dist/index.d.ts +123 -22
- package/dist/index.mjs +248 -86
- package/package.json +40 -34
- package/scripts/setup-skills.js +76 -0
- package/skills/moostjs-event-http/SKILL.md +32 -0
- package/skills/moostjs-event-http/auth.md +275 -0
- package/skills/moostjs-event-http/core.md +193 -0
- package/skills/moostjs-event-http/request.md +230 -0
- package/skills/moostjs-event-http/response.md +287 -0
- package/skills/moostjs-event-http/routing.md +210 -0
package/dist/index.mjs
CHANGED
|
@@ -1,41 +1,202 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { current } from "@wooksjs/event-core";
|
|
2
|
+
import { HttpError, HttpError as HttpError$1, WooksHttp, WooksHttpResponse, createHttpApp, httpKind, useAuthorization, useCookies, useHeaders, useHttpContext, useRequest, useResponse, useUrlParams } from "@wooksjs/event-http";
|
|
3
|
+
import { Before, Intercept, Interceptor, Overtake, Resolve, TInterceptorPriority, defineBeforeInterceptor, defineMoostEventHandler, getMoostMate } from "moost";
|
|
4
4
|
import { useBody } from "@wooksjs/http-body";
|
|
5
5
|
import { createProvideRegistry } from "@prostojs/infact";
|
|
6
6
|
import { Server } from "http";
|
|
7
7
|
import { Server as Server$1 } from "https";
|
|
8
8
|
|
|
9
|
+
//#region packages/event-http/src/auth-guard.ts
|
|
10
|
+
function _define_property$1(obj, key, value) {
|
|
11
|
+
if (key in obj) Object.defineProperty(obj, key, {
|
|
12
|
+
value,
|
|
13
|
+
enumerable: true,
|
|
14
|
+
configurable: true,
|
|
15
|
+
writable: true
|
|
16
|
+
});
|
|
17
|
+
else obj[key] = value;
|
|
18
|
+
return obj;
|
|
19
|
+
}
|
|
20
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
21
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
22
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
23
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
24
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
25
|
+
}
|
|
26
|
+
function _ts_metadata(k, v) {
|
|
27
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
28
|
+
}
|
|
29
|
+
function _ts_param(paramIndex, decorator) {
|
|
30
|
+
return function(target, key) {
|
|
31
|
+
decorator(target, key, paramIndex);
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/** Extracts auth credentials from the current request based on transport declarations. Throws 401 if none found. */ function extractTransports(declaration) {
|
|
35
|
+
const ctx = current();
|
|
36
|
+
const result = {};
|
|
37
|
+
let found = false;
|
|
38
|
+
if (declaration.bearer) {
|
|
39
|
+
const auth = useAuthorization(ctx);
|
|
40
|
+
if (auth.is("bearer")) {
|
|
41
|
+
result.bearer = auth.credentials();
|
|
42
|
+
found = true;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (declaration.basic) {
|
|
46
|
+
const auth = useAuthorization(ctx);
|
|
47
|
+
if (auth.is("basic")) {
|
|
48
|
+
result.basic = auth.basicCredentials();
|
|
49
|
+
found = true;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
if (declaration.cookie) {
|
|
53
|
+
const { getCookie } = useCookies(ctx);
|
|
54
|
+
const val = getCookie(declaration.cookie.name);
|
|
55
|
+
if (val) {
|
|
56
|
+
result.cookie = val;
|
|
57
|
+
found = true;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (declaration.apiKey) {
|
|
61
|
+
const { name, in: location } = declaration.apiKey;
|
|
62
|
+
if (location === "header") {
|
|
63
|
+
const headers = useHeaders(ctx);
|
|
64
|
+
if (headers[name.toLowerCase()]) {
|
|
65
|
+
result.apiKey = headers[name.toLowerCase()];
|
|
66
|
+
found = true;
|
|
67
|
+
}
|
|
68
|
+
} else if (location === "query") {
|
|
69
|
+
const { params } = useUrlParams(ctx);
|
|
70
|
+
const val = params().get(name);
|
|
71
|
+
if (val) {
|
|
72
|
+
result.apiKey = String(val);
|
|
73
|
+
found = true;
|
|
74
|
+
}
|
|
75
|
+
} else if (location === "cookie") {
|
|
76
|
+
const { getCookie } = useCookies(ctx);
|
|
77
|
+
const val = getCookie(name);
|
|
78
|
+
if (val) {
|
|
79
|
+
result.apiKey = val;
|
|
80
|
+
found = true;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if (!found) throw new HttpError$1(401, "No authentication credentials provided");
|
|
85
|
+
return result;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Creates a functional auth guard interceptor.
|
|
89
|
+
* Extracts credentials from declared transports and passes them to the handler.
|
|
90
|
+
* Return a value from the handler to short-circuit with that response.
|
|
91
|
+
*/ function defineAuthGuard(transports, handler) {
|
|
92
|
+
const def = defineBeforeInterceptor((reply) => {
|
|
93
|
+
const extracted = extractTransports(transports);
|
|
94
|
+
const result = handler(extracted);
|
|
95
|
+
if (result !== null && result !== void 0 && typeof result.then === "function") return result.then((r) => {
|
|
96
|
+
if (r !== void 0) reply(r);
|
|
97
|
+
return void 0;
|
|
98
|
+
});
|
|
99
|
+
if (result !== void 0) reply(result);
|
|
100
|
+
}, TInterceptorPriority.GUARD);
|
|
101
|
+
return Object.assign(def, { __authTransports: transports });
|
|
102
|
+
}
|
|
103
|
+
var AuthGuard = class {
|
|
104
|
+
__intercept(reply) {
|
|
105
|
+
const ctor = this.constructor;
|
|
106
|
+
const extracted = extractTransports(ctor.transports);
|
|
107
|
+
const result = this.handle(extracted);
|
|
108
|
+
if (result !== null && result !== void 0 && typeof result.then === "function") return result.then((r) => {
|
|
109
|
+
if (r !== void 0) reply(r);
|
|
110
|
+
return void 0;
|
|
111
|
+
});
|
|
112
|
+
if (result !== void 0) reply(result);
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
_define_property$1(AuthGuard, "transports", void 0);
|
|
116
|
+
_define_property$1(AuthGuard, "priority", TInterceptorPriority.GUARD);
|
|
117
|
+
_ts_decorate([
|
|
118
|
+
Before(),
|
|
119
|
+
_ts_param(0, Overtake()),
|
|
120
|
+
_ts_metadata("design:type", Function),
|
|
121
|
+
_ts_metadata("design:paramtypes", [typeof TOvertakeFn === "undefined" ? Object : TOvertakeFn]),
|
|
122
|
+
_ts_metadata("design:returntype", void 0)
|
|
123
|
+
], AuthGuard.prototype, "__intercept", null);
|
|
124
|
+
AuthGuard = _ts_decorate([Interceptor(TInterceptorPriority.GUARD)], AuthGuard);
|
|
125
|
+
/**
|
|
126
|
+
* Registers an auth guard as an interceptor and stores its transport
|
|
127
|
+
* declarations in metadata for swagger auto-discovery.
|
|
128
|
+
*
|
|
129
|
+
* Accepts either a functional guard from `defineAuthGuard()` or a
|
|
130
|
+
* class-based guard extending `AuthGuard`.
|
|
131
|
+
*/ function Authenticate(handler) {
|
|
132
|
+
const mate = getMoostMate();
|
|
133
|
+
const isClass = typeof handler === "function";
|
|
134
|
+
const transports = isClass ? handler.transports : handler.__authTransports;
|
|
135
|
+
const priority = isClass ? handler.priority : handler.priority || TInterceptorPriority.GUARD;
|
|
136
|
+
const name = isClass ? handler.name : "AuthGuard";
|
|
137
|
+
return mate.apply(mate.decorate("interceptors", {
|
|
138
|
+
handler,
|
|
139
|
+
priority,
|
|
140
|
+
name
|
|
141
|
+
}, true), mate.decorate("authTransports", transports));
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
//#endregion
|
|
9
145
|
//#region packages/event-http/src/decorators/http-method.decorator.ts
|
|
10
|
-
function HttpMethod(method, path) {
|
|
146
|
+
/** Base decorator for registering an HTTP route handler with an explicit method. */ function HttpMethod(method, path) {
|
|
11
147
|
return getMoostMate().decorate("handlers", {
|
|
12
148
|
method,
|
|
13
149
|
path,
|
|
14
150
|
type: "HTTP"
|
|
15
151
|
}, true);
|
|
16
152
|
}
|
|
17
|
-
const All = (path) => HttpMethod("*", path);
|
|
18
|
-
const Get = (path) => HttpMethod("GET", path);
|
|
19
|
-
const Post = (path) => HttpMethod("POST", path);
|
|
20
|
-
const Put = (path) => HttpMethod("PUT", path);
|
|
21
|
-
const Delete = (path) => HttpMethod("DELETE", path);
|
|
22
|
-
const Patch = (path) => HttpMethod("PATCH", path);
|
|
153
|
+
/** Register a catch-all route handler matching any HTTP method. */ const All = (path) => HttpMethod("*", path);
|
|
154
|
+
/** Register a GET route handler. */ const Get = (path) => HttpMethod("GET", path);
|
|
155
|
+
/** Register a POST route handler. */ const Post = (path) => HttpMethod("POST", path);
|
|
156
|
+
/** Register a PUT route handler. */ const Put = (path) => HttpMethod("PUT", path);
|
|
157
|
+
/** Register a DELETE route handler. */ const Delete = (path) => HttpMethod("DELETE", path);
|
|
158
|
+
/** Register a PATCH route handler. */ const Patch = (path) => HttpMethod("PATCH", path);
|
|
159
|
+
/**
|
|
160
|
+
* Register an UPGRADE route handler for WebSocket upgrade requests.
|
|
161
|
+
*
|
|
162
|
+
* Use together with `WooksWs` (injected via DI) to complete the handshake:
|
|
163
|
+
* ```ts
|
|
164
|
+
* @Upgrade('/ws')
|
|
165
|
+
* handleUpgrade(ws: WooksWs) {
|
|
166
|
+
* return ws.upgrade()
|
|
167
|
+
* }
|
|
168
|
+
* ```
|
|
169
|
+
*/ const Upgrade = (path) => HttpMethod("UPGRADE", path);
|
|
23
170
|
|
|
24
171
|
//#endregion
|
|
25
172
|
//#region packages/event-http/src/decorators/resolve.decorator.ts
|
|
173
|
+
function createHook(getter, setter) {
|
|
174
|
+
return new Proxy({}, {
|
|
175
|
+
get: (_target, prop) => prop === "value" ? getter() : void 0,
|
|
176
|
+
set: (_target, prop, v) => {
|
|
177
|
+
if (prop === "value") setter(v);
|
|
178
|
+
return true;
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
}
|
|
26
182
|
/**
|
|
27
183
|
* Hook to the Response Status
|
|
28
184
|
* @decorator
|
|
29
185
|
* @paramType TStatusHook
|
|
30
186
|
*/ const StatusHook = () => Resolve((metas, level) => {
|
|
31
|
-
const
|
|
32
|
-
if (level === "PARAM") return
|
|
187
|
+
const response = useResponse();
|
|
188
|
+
if (level === "PARAM") return createHook(() => response.status, (v) => {
|
|
189
|
+
response.status = v;
|
|
190
|
+
});
|
|
33
191
|
if (level === "PROP" && metas.instance && metas.key) {
|
|
34
192
|
const initialValue = metas.instance[metas.key];
|
|
35
|
-
|
|
36
|
-
get: () =>
|
|
37
|
-
set: (v) =>
|
|
38
|
-
|
|
193
|
+
Object.defineProperty(metas.instance, metas.key, {
|
|
194
|
+
get: () => response.status,
|
|
195
|
+
set: (v) => {
|
|
196
|
+
response.status = v;
|
|
197
|
+
},
|
|
198
|
+
configurable: true
|
|
199
|
+
});
|
|
39
200
|
return typeof initialValue === "number" ? initialValue : 200;
|
|
40
201
|
}
|
|
41
202
|
}, "statusCode");
|
|
@@ -45,14 +206,15 @@ const Patch = (path) => HttpMethod("PATCH", path);
|
|
|
45
206
|
* @param name - header name
|
|
46
207
|
* @paramType THeaderHook
|
|
47
208
|
*/ const HeaderHook = (name) => Resolve((metas, level) => {
|
|
48
|
-
const
|
|
49
|
-
if (level === "PARAM") return
|
|
209
|
+
const response = useResponse();
|
|
210
|
+
if (level === "PARAM") return createHook(() => response.getHeader(name), (v) => response.setHeader(name, v));
|
|
50
211
|
if (level === "PROP" && metas.instance && metas.key) {
|
|
51
212
|
const initialValue = metas.instance[metas.key];
|
|
52
|
-
|
|
53
|
-
get: () =>
|
|
54
|
-
set: (v) =>
|
|
55
|
-
|
|
213
|
+
Object.defineProperty(metas.instance, metas.key, {
|
|
214
|
+
get: () => response.getHeader(name),
|
|
215
|
+
set: (v) => response.setHeader(name, v),
|
|
216
|
+
configurable: true
|
|
217
|
+
});
|
|
56
218
|
return typeof initialValue === "string" ? initialValue : "";
|
|
57
219
|
}
|
|
58
220
|
}, name);
|
|
@@ -62,14 +224,15 @@ const Patch = (path) => HttpMethod("PATCH", path);
|
|
|
62
224
|
* @param name - cookie name
|
|
63
225
|
* @paramType TCookieHook
|
|
64
226
|
*/ const CookieHook = (name) => Resolve((metas, level) => {
|
|
65
|
-
const
|
|
66
|
-
if (level === "PARAM") return
|
|
227
|
+
const response = useResponse();
|
|
228
|
+
if (level === "PARAM") return createHook(() => response.getCookie(name)?.value, (v) => response.setCookie(name, v ?? ""));
|
|
67
229
|
if (level === "PROP" && metas.instance && metas.key) {
|
|
68
230
|
const initialValue = metas.instance[metas.key];
|
|
69
|
-
|
|
70
|
-
get: () =>
|
|
71
|
-
set: (v) =>
|
|
72
|
-
|
|
231
|
+
Object.defineProperty(metas.instance, metas.key, {
|
|
232
|
+
get: () => response.getCookie(name)?.value,
|
|
233
|
+
set: (v) => response.setCookie(name, v ?? ""),
|
|
234
|
+
configurable: true
|
|
235
|
+
});
|
|
73
236
|
return typeof initialValue === "string" ? initialValue : "";
|
|
74
237
|
}
|
|
75
238
|
}, name);
|
|
@@ -79,17 +242,20 @@ const Patch = (path) => HttpMethod("PATCH", path);
|
|
|
79
242
|
* @param name - cookie name
|
|
80
243
|
* @paramType TCookieAttributes
|
|
81
244
|
*/ const CookieAttrsHook = (name) => Resolve((metas, level) => {
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
245
|
+
const response = useResponse();
|
|
246
|
+
const getAttrs = () => response.getCookie(name)?.attrs;
|
|
247
|
+
const setAttrs = (v) => {
|
|
248
|
+
const existing = response.getCookie(name);
|
|
249
|
+
response.setCookie(name, existing?.value ?? "", v);
|
|
250
|
+
};
|
|
251
|
+
if (level === "PARAM") return createHook(getAttrs, setAttrs);
|
|
87
252
|
if (level === "PROP" && metas.instance && metas.key) {
|
|
88
253
|
const initialValue = metas.instance[metas.key];
|
|
89
|
-
|
|
90
|
-
get:
|
|
91
|
-
set:
|
|
92
|
-
|
|
254
|
+
Object.defineProperty(metas.instance, metas.key, {
|
|
255
|
+
get: getAttrs,
|
|
256
|
+
set: setAttrs,
|
|
257
|
+
configurable: true
|
|
258
|
+
});
|
|
93
259
|
return typeof initialValue === "object" ? initialValue : {};
|
|
94
260
|
}
|
|
95
261
|
}, name);
|
|
@@ -102,11 +268,11 @@ const Patch = (path) => HttpMethod("PATCH", path);
|
|
|
102
268
|
return Resolve(() => {
|
|
103
269
|
const auth = useAuthorization();
|
|
104
270
|
switch (name) {
|
|
105
|
-
case "username": return auth.
|
|
106
|
-
case "password": return auth.
|
|
107
|
-
case "bearer": return auth.
|
|
108
|
-
case "raw": return auth.
|
|
109
|
-
case "type": return auth.
|
|
271
|
+
case "username": return auth.is("basic") ? auth.basicCredentials()?.username : void 0;
|
|
272
|
+
case "password": return auth.is("basic") ? auth.basicCredentials()?.password : void 0;
|
|
273
|
+
case "bearer": return auth.is("bearer") ? auth.authorization : void 0;
|
|
274
|
+
case "raw": return auth.credentials();
|
|
275
|
+
case "type": return auth.type();
|
|
110
276
|
default: return void 0;
|
|
111
277
|
}
|
|
112
278
|
}, "authorization");
|
|
@@ -139,13 +305,13 @@ const Patch = (path) => HttpMethod("PATCH", path);
|
|
|
139
305
|
const isItem = !!name;
|
|
140
306
|
const _name = isItem ? name : "Query";
|
|
141
307
|
return getMoostMate().apply(getMoostMate().decorate("paramSource", isItem ? "QUERY_ITEM" : "QUERY"), getMoostMate().decorate("paramName", _name), Resolve(() => {
|
|
142
|
-
const {
|
|
308
|
+
const { toJson, params } = useUrlParams();
|
|
143
309
|
if (isItem) {
|
|
144
|
-
const p =
|
|
310
|
+
const p = params();
|
|
145
311
|
const value = p.get(name);
|
|
146
312
|
return value === null ? void 0 : value;
|
|
147
313
|
}
|
|
148
|
-
const json =
|
|
314
|
+
const json = toJson();
|
|
149
315
|
return Object.keys(json).length > 0 ? json : void 0;
|
|
150
316
|
}, _name));
|
|
151
317
|
}
|
|
@@ -168,7 +334,7 @@ const Patch = (path) => HttpMethod("PATCH", path);
|
|
|
168
334
|
* @decorator
|
|
169
335
|
* @paramType IncomingMessage
|
|
170
336
|
*/ function Req() {
|
|
171
|
-
return Resolve(() => useRequest().
|
|
337
|
+
return Resolve(() => useRequest().raw, "request");
|
|
172
338
|
}
|
|
173
339
|
/**
|
|
174
340
|
* Get Raw Response Instance
|
|
@@ -176,7 +342,7 @@ const Patch = (path) => HttpMethod("PATCH", path);
|
|
|
176
342
|
* @param opts (optional) { passthrough: boolean }
|
|
177
343
|
* @paramType ServerResponse
|
|
178
344
|
*/ function Res(opts) {
|
|
179
|
-
return Resolve(() => useResponse().
|
|
345
|
+
return Resolve(() => useResponse().getRawRes(opts?.passthrough), "response");
|
|
180
346
|
}
|
|
181
347
|
/**
|
|
182
348
|
* Get Request Unique Identificator (UUID)
|
|
@@ -217,17 +383,14 @@ const Patch = (path) => HttpMethod("PATCH", path);
|
|
|
217
383
|
//#endregion
|
|
218
384
|
//#region packages/event-http/src/decorators/set.decorator.ts
|
|
219
385
|
const setHeaderInterceptor = (name, value, opts) => {
|
|
220
|
-
const
|
|
221
|
-
const
|
|
222
|
-
|
|
223
|
-
const cb = () => {
|
|
224
|
-
if ((!h.value || opts?.force) && (!opts?.status || opts.status === status.value)) h.value = value;
|
|
225
|
-
};
|
|
226
|
-
if (opts?.when !== "error") after(cb);
|
|
227
|
-
if (opts?.when === "always" || opts?.when === "error") onError(cb);
|
|
386
|
+
const cb = () => {
|
|
387
|
+
const response = useResponse();
|
|
388
|
+
if ((!response.getHeader(name) || opts?.force) && (!opts?.status || opts.status === response.status)) response.setHeader(name, value);
|
|
228
389
|
};
|
|
229
|
-
|
|
230
|
-
|
|
390
|
+
const def = { priority: TInterceptorPriority.AFTER_ALL };
|
|
391
|
+
if (opts?.when !== "error") def.after = cb;
|
|
392
|
+
if (opts?.when === "always" || opts?.when === "error") def.error = cb;
|
|
393
|
+
return def;
|
|
231
394
|
};
|
|
232
395
|
/**
|
|
233
396
|
* Set Header for Request Handler
|
|
@@ -268,16 +431,13 @@ const setHeaderInterceptor = (name, value, opts) => {
|
|
|
268
431
|
*/ function SetHeader(...args) {
|
|
269
432
|
return Intercept(setHeaderInterceptor(...args));
|
|
270
433
|
}
|
|
271
|
-
const setCookieInterceptor = (name, value, attrs) => {
|
|
272
|
-
|
|
273
|
-
const
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
fn.priority = TInterceptorPriority.AFTER_ALL;
|
|
279
|
-
return fn;
|
|
280
|
-
};
|
|
434
|
+
const setCookieInterceptor = (name, value, attrs) => ({
|
|
435
|
+
after() {
|
|
436
|
+
const response = useResponse();
|
|
437
|
+
if (!response.getCookie(name)) response.setCookie(name, value, attrs);
|
|
438
|
+
},
|
|
439
|
+
priority: TInterceptorPriority.AFTER_ALL
|
|
440
|
+
});
|
|
281
441
|
/**
|
|
282
442
|
* Set Cookie for Request Handler
|
|
283
443
|
* ```ts
|
|
@@ -301,11 +461,12 @@ const setCookieInterceptor = (name, value, attrs) => {
|
|
|
301
461
|
*/ function SetCookie(...args) {
|
|
302
462
|
return Intercept(setCookieInterceptor(...args));
|
|
303
463
|
}
|
|
304
|
-
const setStatusInterceptor = (code, opts) =>
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
if (!status
|
|
308
|
-
}
|
|
464
|
+
const setStatusInterceptor = (code, opts) => ({
|
|
465
|
+
after() {
|
|
466
|
+
const response = useResponse();
|
|
467
|
+
if (!response.status || opts?.force) response.status = code;
|
|
468
|
+
},
|
|
469
|
+
priority: TInterceptorPriority.AFTER_ALL
|
|
309
470
|
});
|
|
310
471
|
/**
|
|
311
472
|
* Set Response Status for Request Handler
|
|
@@ -335,24 +496,24 @@ const setStatusInterceptor = (code, opts) => defineInterceptorFn((before, after)
|
|
|
335
496
|
* Creates an interceptor that sets the maximum allowed inflated body size in bytes.
|
|
336
497
|
*
|
|
337
498
|
* @param n - Maximum body size in bytes after decompression.
|
|
338
|
-
* @returns Interceptor
|
|
339
|
-
*/ const globalBodySizeLimit = (n) =>
|
|
499
|
+
* @returns Interceptor def to enforce the limit.
|
|
500
|
+
*/ const globalBodySizeLimit = (n) => defineBeforeInterceptor(() => {
|
|
340
501
|
useRequest().setMaxInflated(n);
|
|
341
502
|
}, TInterceptorPriority.BEFORE_ALL);
|
|
342
503
|
/**
|
|
343
504
|
* Creates an interceptor that sets the maximum allowed compressed body size in bytes.
|
|
344
505
|
*
|
|
345
506
|
* @param n - Maximum body size in bytes before decompression.
|
|
346
|
-
* @returns Interceptor
|
|
347
|
-
*/ const globalCompressedBodySizeLimit = (n) =>
|
|
507
|
+
* @returns Interceptor def to enforce the limit.
|
|
508
|
+
*/ const globalCompressedBodySizeLimit = (n) => defineBeforeInterceptor(() => {
|
|
348
509
|
useRequest().setMaxCompressed(n);
|
|
349
510
|
}, TInterceptorPriority.BEFORE_ALL);
|
|
350
511
|
/**
|
|
351
512
|
* Creates an interceptor that sets the timeout for reading the request body.
|
|
352
513
|
*
|
|
353
514
|
* @param n - Timeout in milliseconds.
|
|
354
|
-
* @returns Interceptor
|
|
355
|
-
*/ const globalBodyReadTimeoutMs = (n) =>
|
|
515
|
+
* @returns Interceptor def to enforce the timeout.
|
|
516
|
+
*/ const globalBodyReadTimeoutMs = (n) => defineBeforeInterceptor(() => {
|
|
356
517
|
useRequest().setReadTimeoutMs(n);
|
|
357
518
|
}, TInterceptorPriority.BEFORE_ALL);
|
|
358
519
|
/**
|
|
@@ -444,23 +605,24 @@ const CONTEXT_TYPE = "HTTP";
|
|
|
444
605
|
if (handler.type !== "HTTP") continue;
|
|
445
606
|
const httpPath = handler.path;
|
|
446
607
|
const path = typeof httpPath === "string" ? httpPath : typeof opts.method === "string" ? opts.method : "";
|
|
447
|
-
const targetPath = `${`${opts.prefix || ""}/${path}`.
|
|
608
|
+
const targetPath = `${`${opts.prefix || ""}/${path}`.replaceAll(/\/\/+/g, "/")}${path.endsWith("//") ? "/" : ""}`;
|
|
448
609
|
fn = defineMoostEventHandler({
|
|
449
610
|
contextType: CONTEXT_TYPE,
|
|
450
611
|
loggerTitle: LOGGER_TITLE,
|
|
451
612
|
getIterceptorHandler: opts.getIterceptorHandler,
|
|
452
613
|
getControllerInstance: opts.getInstance,
|
|
453
614
|
controllerMethod: opts.method,
|
|
615
|
+
controllerName: opts.controllerName,
|
|
454
616
|
resolveArgs: opts.resolveArgs,
|
|
455
617
|
manualUnscope: true,
|
|
456
618
|
hooks: { init: ({ unscope }) => {
|
|
457
|
-
const {
|
|
458
|
-
|
|
619
|
+
const { raw } = useRequest();
|
|
620
|
+
raw.on("end", unscope);
|
|
459
621
|
} },
|
|
460
622
|
targetPath,
|
|
461
623
|
handlerType: handler.type
|
|
462
624
|
});
|
|
463
|
-
const routerBinding = this.httpApp.on(handler.method, targetPath, fn);
|
|
625
|
+
const routerBinding = handler.method === "UPGRADE" ? this.httpApp.upgrade(targetPath, fn) : this.httpApp.on(handler.method, targetPath, fn);
|
|
464
626
|
const { getPath: pathBuilder } = routerBinding;
|
|
465
627
|
const methodMeta = getMoostMate().read(opts.fakeInstance, opts.method) || {};
|
|
466
628
|
const id = methodMeta.id || opts.method;
|
|
@@ -486,11 +648,11 @@ const CONTEXT_TYPE = "HTTP";
|
|
|
486
648
|
_define_property(this, "httpApp", void 0);
|
|
487
649
|
_define_property(this, "pathBuilders", {});
|
|
488
650
|
_define_property(this, "moost", void 0);
|
|
489
|
-
|
|
490
|
-
image: "https://moost.org/moost-full-logo.
|
|
651
|
+
WooksHttpResponse.registerFramework({
|
|
652
|
+
image: "https://moost.org/moost-full-logo.svg",
|
|
491
653
|
link: "https://moost.org/",
|
|
492
654
|
poweredBy: "moostjs",
|
|
493
|
-
version: "0.5.
|
|
655
|
+
version: "0.5.33"
|
|
494
656
|
});
|
|
495
657
|
if (httpApp && httpApp instanceof WooksHttp) this.httpApp = httpApp;
|
|
496
658
|
else if (httpApp) this.httpApp = createHttpApp({
|
|
@@ -502,4 +664,4 @@ const CONTEXT_TYPE = "HTTP";
|
|
|
502
664
|
};
|
|
503
665
|
|
|
504
666
|
//#endregion
|
|
505
|
-
export { All, Authorization, Body, BodyReadTimeoutMs, BodySizeLimit, CompressedBodySizeLimit, Cookie, CookieAttrsHook, CookieHook, Delete, Get, Header, HeaderHook, HttpError, HttpMethod, Ip, IpList, Method, MoostHttp, Patch, Post, Put, Query, RawBody, Req, ReqId, Res, SetCookie, SetHeader, SetStatus, StatusHook, Url, globalBodyReadTimeoutMs, globalBodySizeLimit, globalCompressedBodySizeLimit, useHttpContext };
|
|
667
|
+
export { All, AuthGuard, Authenticate, Authorization, Body, BodyReadTimeoutMs, BodySizeLimit, CompressedBodySizeLimit, Cookie, CookieAttrsHook, CookieHook, Delete, Get, Header, HeaderHook, HttpError, HttpMethod, Ip, IpList, Method, MoostHttp, Patch, Post, Put, Query, RawBody, Req, ReqId, Res, SetCookie, SetHeader, SetStatus, StatusHook, Upgrade, Url, defineAuthGuard, extractTransports, globalBodyReadTimeoutMs, globalBodySizeLimit, globalCompressedBodySizeLimit, httpKind, useHttpContext };
|
package/package.json
CHANGED
|
@@ -1,12 +1,39 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@moostjs/event-http",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "@moostjs/event-http",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"composables",
|
|
7
|
+
"framework",
|
|
8
|
+
"moost",
|
|
9
|
+
"moostjs",
|
|
10
|
+
"prostojs",
|
|
11
|
+
"wooksjs"
|
|
12
|
+
],
|
|
13
|
+
"homepage": "https://github.com/moostjs/moostjs/tree/main/packages/event-http#readme",
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/moostjs/moostjs/issues"
|
|
16
|
+
},
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"author": "Artem Maltsev",
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "git+https://github.com/moostjs/moostjs.git",
|
|
22
|
+
"directory": "packages/event-http"
|
|
23
|
+
},
|
|
24
|
+
"bin": {
|
|
25
|
+
"moostjs-event-http-skill": "./scripts/setup-skills.js"
|
|
26
|
+
},
|
|
27
|
+
"files": [
|
|
28
|
+
"dist",
|
|
29
|
+
"skills",
|
|
30
|
+
"scripts/setup-skills.js"
|
|
31
|
+
],
|
|
32
|
+
"type": "module",
|
|
33
|
+
"sideEffects": false,
|
|
5
34
|
"main": "dist/index.cjs",
|
|
6
35
|
"module": "dist/index.mjs",
|
|
7
36
|
"types": "dist/index.d.ts",
|
|
8
|
-
"sideEffects": false,
|
|
9
|
-
"type": "module",
|
|
10
37
|
"exports": {
|
|
11
38
|
"./package.json": "./package.json",
|
|
12
39
|
".": {
|
|
@@ -15,43 +42,22 @@
|
|
|
15
42
|
"require": "./dist/index.cjs"
|
|
16
43
|
}
|
|
17
44
|
},
|
|
18
|
-
"files": [
|
|
19
|
-
"dist"
|
|
20
|
-
],
|
|
21
|
-
"repository": {
|
|
22
|
-
"type": "git",
|
|
23
|
-
"url": "git+https://github.com/moostjs/moostjs.git",
|
|
24
|
-
"directory": "packages/event-http"
|
|
25
|
-
},
|
|
26
|
-
"keywords": [
|
|
27
|
-
"moost",
|
|
28
|
-
"moostjs",
|
|
29
|
-
"composables",
|
|
30
|
-
"framework",
|
|
31
|
-
"wooksjs",
|
|
32
|
-
"prostojs"
|
|
33
|
-
],
|
|
34
|
-
"author": "Artem Maltsev",
|
|
35
|
-
"license": "MIT",
|
|
36
|
-
"bugs": {
|
|
37
|
-
"url": "https://github.com/moostjs/moostjs/issues"
|
|
38
|
-
},
|
|
39
|
-
"homepage": "https://github.com/moostjs/moostjs/tree/main/packages/event-http#readme",
|
|
40
|
-
"peerDependencies": {
|
|
41
|
-
"@wooksjs/event-core": "^0.6.2",
|
|
42
|
-
"@prostojs/infact": "^0.3.3",
|
|
43
|
-
"@prostojs/router": "^0.2.1",
|
|
44
|
-
"moost": "^0.5.33"
|
|
45
|
-
},
|
|
46
45
|
"dependencies": {
|
|
47
|
-
"@wooksjs/event-http": "^0.
|
|
48
|
-
"@wooksjs/http-body": "^0.
|
|
46
|
+
"@wooksjs/event-http": "^0.7.3",
|
|
47
|
+
"@wooksjs/http-body": "^0.7.3"
|
|
49
48
|
},
|
|
50
49
|
"devDependencies": {
|
|
51
50
|
"vitest": "3.2.4"
|
|
52
51
|
},
|
|
52
|
+
"peerDependencies": {
|
|
53
|
+
"@prostojs/infact": "^0.4.1",
|
|
54
|
+
"@prostojs/router": "^0.3.2",
|
|
55
|
+
"@wooksjs/event-core": "^0.7.3",
|
|
56
|
+
"moost": "^0.6.0"
|
|
57
|
+
},
|
|
53
58
|
"scripts": {
|
|
54
59
|
"pub": "pnpm publish --access public",
|
|
55
|
-
"test": "vitest"
|
|
60
|
+
"test": "vitest",
|
|
61
|
+
"setup-skills": "node ./scripts/setup-skills.js"
|
|
56
62
|
}
|
|
57
63
|
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/* prettier-ignore */
|
|
3
|
+
import fs from 'fs'
|
|
4
|
+
import path from 'path'
|
|
5
|
+
import os from 'os'
|
|
6
|
+
import { fileURLToPath } from 'url'
|
|
7
|
+
|
|
8
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
9
|
+
|
|
10
|
+
const SKILL_NAME = 'moostjs-event-http'
|
|
11
|
+
const SKILL_SRC = path.join(__dirname, '..', 'skills', SKILL_NAME)
|
|
12
|
+
|
|
13
|
+
if (!fs.existsSync(SKILL_SRC)) {
|
|
14
|
+
console.error(`No skills found at ${SKILL_SRC}`)
|
|
15
|
+
console.error('Add your SKILL.md files to the skills/' + SKILL_NAME + '/ directory first.')
|
|
16
|
+
process.exit(1)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const AGENTS = {
|
|
20
|
+
'Claude Code': { dir: '.claude/skills', global: path.join(os.homedir(), '.claude', 'skills') },
|
|
21
|
+
'Cursor': { dir: '.cursor/skills', global: path.join(os.homedir(), '.cursor', 'skills') },
|
|
22
|
+
'Windsurf': { dir: '.windsurf/skills', global: path.join(os.homedir(), '.windsurf', 'skills') },
|
|
23
|
+
'Codex': { dir: '.codex/skills', global: path.join(os.homedir(), '.codex', 'skills') },
|
|
24
|
+
'OpenCode': { dir: '.opencode/skills', global: path.join(os.homedir(), '.opencode', 'skills') },
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const args = process.argv.slice(2)
|
|
28
|
+
const isGlobal = args.includes('--global') || args.includes('-g')
|
|
29
|
+
const isPostinstall = args.includes('--postinstall')
|
|
30
|
+
let installed = 0, skipped = 0
|
|
31
|
+
const installedDirs = []
|
|
32
|
+
|
|
33
|
+
for (const [agentName, cfg] of Object.entries(AGENTS)) {
|
|
34
|
+
const targetBase = isGlobal ? cfg.global : path.join(process.cwd(), cfg.dir)
|
|
35
|
+
const agentRootDir = path.dirname(cfg.global)
|
|
36
|
+
|
|
37
|
+
if (isPostinstall || isGlobal) {
|
|
38
|
+
if (!fs.existsSync(agentRootDir)) { skipped++; continue }
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const dest = path.join(targetBase, SKILL_NAME)
|
|
42
|
+
try {
|
|
43
|
+
fs.mkdirSync(dest, { recursive: true })
|
|
44
|
+
fs.cpSync(SKILL_SRC, dest, { recursive: true })
|
|
45
|
+
console.log(`[${SKILL_NAME}] installed to ${dest}`)
|
|
46
|
+
installed++
|
|
47
|
+
if (!isGlobal) installedDirs.push(cfg.dir + '/' + SKILL_NAME)
|
|
48
|
+
} catch (err) {
|
|
49
|
+
console.warn(`[${SKILL_NAME}] failed — ${err.message}`)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (!isGlobal && installedDirs.length > 0) {
|
|
54
|
+
const gitignorePath = path.join(process.cwd(), '.gitignore')
|
|
55
|
+
let gitignoreContent = ''
|
|
56
|
+
try { gitignoreContent = fs.readFileSync(gitignorePath, 'utf8') } catch {}
|
|
57
|
+
const linesToAdd = installedDirs.filter(d => !gitignoreContent.includes(d))
|
|
58
|
+
if (linesToAdd.length > 0) {
|
|
59
|
+
const hasHeader = gitignoreContent.includes('# AI agent skills')
|
|
60
|
+
const block = (gitignoreContent && !gitignoreContent.endsWith('\n') ? '\n' : '')
|
|
61
|
+
+ (hasHeader ? '' : '\n# AI agent skills (auto-generated by setup-skills)\n')
|
|
62
|
+
+ linesToAdd.join('\n') + '\n'
|
|
63
|
+
fs.appendFileSync(gitignorePath, block)
|
|
64
|
+
console.log(`[${SKILL_NAME}] added entries to .gitignore`)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (installed === 0 && isPostinstall) {
|
|
69
|
+
// Silence is fine — no agents present, nothing to do
|
|
70
|
+
} else if (installed === 0 && skipped === Object.keys(AGENTS).length) {
|
|
71
|
+
console.log('No agent directories detected. Try --global or run without it for project-local install.')
|
|
72
|
+
} else if (installed === 0) {
|
|
73
|
+
console.log('Nothing installed. Run without --global to install project-locally.')
|
|
74
|
+
} else {
|
|
75
|
+
console.log(`Done! Restart your AI agent to pick up the "${SKILL_NAME}" skill.`)
|
|
76
|
+
}
|