@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/dist/index.mjs CHANGED
@@ -1,41 +1,202 @@
1
- import { Intercept, Resolve, TInterceptorPriority, defineInterceptorFn, defineMoostEventHandler, getMoostMate } from "moost";
2
- import { attachHook } from "@wooksjs/event-core";
3
- import { HttpError, HttpError as HttpError$1, HttpErrorRenderer, WooksHttp, createHttpApp, useAuthorization, useCookies, useHeaders, useHttpContext, useRequest, useResponse, useSearchParams, useSetCookie, useSetCookies, useSetHeader, useStatus } from "@wooksjs/event-http";
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 hook = useStatus();
32
- if (level === "PARAM") return hook;
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
- attachHook(metas.instance, {
36
- get: () => hook.value,
37
- set: (v) => hook.value = v
38
- }, metas.key);
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 hook = useSetHeader(name);
49
- if (level === "PARAM") return hook;
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
- attachHook(metas.instance, {
53
- get: () => hook.value,
54
- set: (v) => hook.value = v
55
- }, metas.key);
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 hook = useSetCookie(name);
66
- if (level === "PARAM") return hook;
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
- attachHook(metas.instance, {
70
- get: () => hook.value,
71
- set: (v) => hook.value = v
72
- }, metas.key);
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 hook = useSetCookie(name);
83
- if (level === "PARAM") return attachHook({}, {
84
- get: () => hook.attrs,
85
- set: (v) => hook.attrs = v
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
- attachHook(metas.instance, {
90
- get: () => hook.attrs,
91
- set: (v) => hook.attrs = v
92
- }, metas.key);
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.isBasic() ? auth.basicCredentials()?.username : void 0;
106
- case "password": return auth.isBasic() ? auth.basicCredentials()?.password : void 0;
107
- case "bearer": return auth.isBearer() ? auth.authorization : void 0;
108
- case "raw": return auth.authRawCredentials();
109
- case "type": return auth.authType();
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 { jsonSearchParams, urlSearchParams } = useSearchParams();
308
+ const { toJson, params } = useUrlParams();
143
309
  if (isItem) {
144
- const p = urlSearchParams();
310
+ const p = params();
145
311
  const value = p.get(name);
146
312
  return value === null ? void 0 : value;
147
313
  }
148
- const json = jsonSearchParams();
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().rawRequest, "request");
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().rawResponse(opts), "response");
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 fn = (_before, after, onError) => {
221
- const h = useSetHeader(name);
222
- const status = useStatus();
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
- fn.priority = TInterceptorPriority.AFTER_ALL;
230
- return fn;
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
- const fn = (before, after) => {
273
- const { setCookie, getCookie } = useSetCookies();
274
- after(() => {
275
- if (!getCookie(name)) setCookie(name, value, attrs);
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) => defineInterceptorFn((before, after) => {
305
- const status = useStatus();
306
- after(() => {
307
- if (!status.isDefined || opts?.force) status.value = code;
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 function to enforce the limit.
339
- */ const globalBodySizeLimit = (n) => defineInterceptorFn(() => {
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 function to enforce the limit.
347
- */ const globalCompressedBodySizeLimit = (n) => defineInterceptorFn(() => {
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 function to enforce the timeout.
355
- */ const globalBodyReadTimeoutMs = (n) => defineInterceptorFn(() => {
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}`.replace(/\/\/+/g, "/")}${path.endsWith("//") ? "/" : ""}`;
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 { rawRequest } = useRequest();
458
- rawRequest.on("end", unscope);
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
- HttpErrorRenderer.registerFramework({
490
- image: "https://moost.org/moost-full-logo.png",
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.32"
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.5.33",
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.6.2",
48
- "@wooksjs/http-body": "^0.6.2"
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
+ }