@moostjs/event-http 0.6.2 → 0.6.3

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 CHANGED
@@ -76,6 +76,49 @@ class UsersController { ... }
76
76
 
77
77
  Supported transports: `bearer`, `basic`, `apiKey` (header/query/cookie), `cookie`.
78
78
 
79
+ ## Programmatic Fetch (SSR)
80
+
81
+ `MoostHttp` exposes `fetch()` and `request()` methods for in-process route invocation with the full Moost pipeline (DI, interceptors, pipes, validation) — no TCP round-trip.
82
+
83
+ ```ts
84
+ const http = new MoostHttp()
85
+ app.adapter(http)
86
+ await app.init()
87
+
88
+ // Web Standard fetch API
89
+ const response = await http.fetch(new Request('http://localhost/api/hello/world'))
90
+
91
+ // Convenience form
92
+ const response = await http.request('/api/hello/world')
93
+ const response = await http.request('/api/users', {
94
+ method: 'POST',
95
+ body: JSON.stringify({ name: 'Alice' }),
96
+ headers: { 'content-type': 'application/json' },
97
+ })
98
+ ```
99
+
100
+ Returns `Response | null` — `null` means no route matched.
101
+
102
+ When called from within an existing HTTP context (e.g. during SSR), identity headers (`authorization`, `cookie`) are automatically forwarded.
103
+
104
+ ### `enableLocalFetch`
105
+
106
+ Patches `globalThis.fetch` so that local paths are routed in-process through Moost. External URLs pass through to the original `fetch`. Falls back to original `fetch` if no route matches.
107
+
108
+ ```ts
109
+ import { enableLocalFetch } from '@moostjs/event-http'
110
+
111
+ const teardown = enableLocalFetch(http)
112
+
113
+ // Now any fetch('/api/...') goes through Moost in-process
114
+ const res = await fetch('/api/hello/world')
115
+
116
+ // Restore original fetch
117
+ teardown()
118
+ ```
119
+
120
+ This is wired up automatically by `@moostjs/vite` (see `ssrFetch` option).
121
+
79
122
  ## [Official Documentation](https://moost.org/webapp/)
80
123
 
81
124
  ## AI Agent Skills
package/dist/index.cjs CHANGED
@@ -597,8 +597,27 @@ const CONTEXT_TYPE = "HTTP";
597
597
  getHttpApp() {
598
598
  return this.httpApp;
599
599
  }
600
- getServerCb() {
601
- return this.httpApp.getServerCb();
600
+ getServerCb(onNoMatch) {
601
+ return this.httpApp.getServerCb(onNoMatch);
602
+ }
603
+ /**
604
+ * Programmatic route invocation using the Web Standard fetch API.
605
+ * Goes through the full Moost pipeline: DI scoping, interceptors,
606
+ * argument resolution, pipes, validation, and handler execution.
607
+ *
608
+ * When called from within an existing HTTP context (e.g. during SSR),
609
+ * identity headers (authorization, cookie) are automatically forwarded.
610
+ */ fetch(request) {
611
+ return this.httpApp.fetch(request);
612
+ }
613
+ /**
614
+ * Convenience wrapper for programmatic route invocation.
615
+ * Accepts a URL string (relative paths auto-prefixed with `http://localhost`),
616
+ * URL object, or Request, plus optional `RequestInit`.
617
+ *
618
+ * Returns `null` when no route matches the request.
619
+ */ request(input, init) {
620
+ return this.httpApp.request(input, init);
602
621
  }
603
622
  listen(port, hostname, backlog, listeningListener) {
604
623
  return this.httpApp.listen(port, hostname, backlog, listeningListener);
@@ -675,7 +694,7 @@ const CONTEXT_TYPE = "HTTP";
675
694
  image: "https://moost.org/moost-full-logo.svg",
676
695
  link: "https://moost.org/",
677
696
  poweredBy: "moostjs",
678
- version: "0.6.1"
697
+ version: "0.6.2"
679
698
  });
680
699
  if (httpApp && httpApp instanceof __wooksjs_event_http.WooksHttp) this.httpApp = httpApp;
681
700
  else if (httpApp) this.httpApp = (0, __wooksjs_event_http.createHttpApp)({
@@ -686,6 +705,47 @@ const CONTEXT_TYPE = "HTTP";
686
705
  }
687
706
  };
688
707
 
708
+ //#endregion
709
+ //#region packages/event-http/src/local-fetch.ts
710
+ /**
711
+ * Patches `globalThis.fetch` so that requests to local paths (starting with `/`)
712
+ * are routed through `MoostHttp` in-process instead of making a network request.
713
+ * Falls back to the original `fetch` when no Moost route matches.
714
+ *
715
+ * Useful for SSR scenarios where server-side code needs to call its own API endpoints
716
+ * without the overhead of a TCP round-trip.
717
+ *
718
+ * @returns A teardown function that restores the original `globalThis.fetch`.
719
+ */ function enableLocalFetch(http$1) {
720
+ const originalFetch = globalThis.fetch;
721
+ globalThis.fetch = async (input, init) => {
722
+ if (typeof input === "string") {
723
+ if (input.startsWith("/")) {
724
+ const response = await http$1.request(input, init);
725
+ if (response) return response;
726
+ }
727
+ } else if (input instanceof URL) {
728
+ if (isLocalOrigin(input)) {
729
+ const response = await http$1.request(input, init);
730
+ if (response) return response;
731
+ }
732
+ } else {
733
+ const url = new URL(input.url);
734
+ if (isLocalOrigin(url)) {
735
+ const response = await http$1.fetch(input);
736
+ if (response) return response;
737
+ }
738
+ }
739
+ return originalFetch(input, init);
740
+ };
741
+ return () => {
742
+ globalThis.fetch = originalFetch;
743
+ };
744
+ }
745
+ function isLocalOrigin(url) {
746
+ return url.hostname === "localhost" || url.hostname === "127.0.0.1";
747
+ }
748
+
689
749
  //#endregion
690
750
  exports.All = All;
691
751
  Object.defineProperty(exports, 'AuthGuard', {
@@ -733,6 +793,7 @@ exports.StatusRef = StatusRef;
733
793
  exports.Upgrade = Upgrade;
734
794
  exports.Url = Url;
735
795
  exports.defineAuthGuard = defineAuthGuard;
796
+ exports.enableLocalFetch = enableLocalFetch;
736
797
  exports.extractTransports = extractTransports;
737
798
  exports.globalBodyReadTimeoutMs = globalBodyReadTimeoutMs;
738
799
  exports.globalBodySizeLimit = globalBodySizeLimit;
package/dist/index.d.ts CHANGED
@@ -400,7 +400,24 @@ declare class MoostHttp implements TMoostAdapter<THttpHandlerMeta> {
400
400
  protected httpApp: WooksHttp;
401
401
  constructor(httpApp?: WooksHttp | TWooksHttpOptions);
402
402
  getHttpApp(): WooksHttp;
403
- getServerCb(): (req: http.IncomingMessage, res: http.ServerResponse) => void;
403
+ getServerCb(onNoMatch?: (req: http.IncomingMessage, res: http.ServerResponse) => void): (req: http.IncomingMessage, res: http.ServerResponse) => void;
404
+ /**
405
+ * Programmatic route invocation using the Web Standard fetch API.
406
+ * Goes through the full Moost pipeline: DI scoping, interceptors,
407
+ * argument resolution, pipes, validation, and handler execution.
408
+ *
409
+ * When called from within an existing HTTP context (e.g. during SSR),
410
+ * identity headers (authorization, cookie) are automatically forwarded.
411
+ */
412
+ fetch(request: Request): Promise<Response | null>;
413
+ /**
414
+ * Convenience wrapper for programmatic route invocation.
415
+ * Accepts a URL string (relative paths auto-prefixed with `http://localhost`),
416
+ * URL object, or Request, plus optional `RequestInit`.
417
+ *
418
+ * Returns `null` when no route matches the request.
419
+ */
420
+ request(input: string | URL | Request, init?: RequestInit): Promise<Response | null>;
404
421
  listen(port?: number, hostname?: string, backlog?: number, listeningListener?: () => void): Promise<void>;
405
422
  listen(port?: number, hostname?: string, listeningListener?: () => void): Promise<void>;
406
423
  listen(port?: number, backlog?: number, listeningListener?: () => void): Promise<void>;
@@ -425,5 +442,17 @@ declare class MoostHttp implements TMoostAdapter<THttpHandlerMeta> {
425
442
  bindHandler<T extends object = object>(opts: TMoostAdapterOptions<THttpHandlerMeta, T>): void;
426
443
  }
427
444
 
428
- export { All, AuthGuard, Authenticate, Authorization, Body, BodyReadTimeoutMs, BodySizeLimit, CompressedBodySizeLimit, Cookie, CookieAttrsRef, CookieRef, Delete, Get, Header, HeaderRef, HttpMethod, Ip, IpList, Method, MoostHttp, Patch, Post, Put, Query, RawBody, Req, ReqId, Res, SetCookie, SetHeader, SetStatus, StatusRef, Upgrade, Url, defineAuthGuard, extractTransports, globalBodyReadTimeoutMs, globalBodySizeLimit, globalCompressedBodySizeLimit };
445
+ /**
446
+ * Patches `globalThis.fetch` so that requests to local paths (starting with `/`)
447
+ * are routed through `MoostHttp` in-process instead of making a network request.
448
+ * Falls back to the original `fetch` when no Moost route matches.
449
+ *
450
+ * Useful for SSR scenarios where server-side code needs to call its own API endpoints
451
+ * without the overhead of a TCP round-trip.
452
+ *
453
+ * @returns A teardown function that restores the original `globalThis.fetch`.
454
+ */
455
+ declare function enableLocalFetch(http: MoostHttp): () => void;
456
+
457
+ export { All, AuthGuard, Authenticate, Authorization, Body, BodyReadTimeoutMs, BodySizeLimit, CompressedBodySizeLimit, Cookie, CookieAttrsRef, CookieRef, Delete, Get, Header, HeaderRef, HttpMethod, Ip, IpList, Method, MoostHttp, Patch, Post, Put, Query, RawBody, Req, ReqId, Res, SetCookie, SetHeader, SetStatus, StatusRef, Upgrade, Url, defineAuthGuard, enableLocalFetch, extractTransports, globalBodyReadTimeoutMs, globalBodySizeLimit, globalCompressedBodySizeLimit };
429
458
  export type { TAuthGuardClass, TAuthGuardDef, TAuthGuardHandler, TAuthTransportApiKey, TAuthTransportBasic, TAuthTransportBearer, TAuthTransportCookie, TAuthTransportDeclaration, TAuthTransportValues, TCookieAttributes, TCookieRef, THeaderRef, THttpHandlerMeta, TStatusRef };
package/dist/index.mjs CHANGED
@@ -574,8 +574,27 @@ const CONTEXT_TYPE = "HTTP";
574
574
  getHttpApp() {
575
575
  return this.httpApp;
576
576
  }
577
- getServerCb() {
578
- return this.httpApp.getServerCb();
577
+ getServerCb(onNoMatch) {
578
+ return this.httpApp.getServerCb(onNoMatch);
579
+ }
580
+ /**
581
+ * Programmatic route invocation using the Web Standard fetch API.
582
+ * Goes through the full Moost pipeline: DI scoping, interceptors,
583
+ * argument resolution, pipes, validation, and handler execution.
584
+ *
585
+ * When called from within an existing HTTP context (e.g. during SSR),
586
+ * identity headers (authorization, cookie) are automatically forwarded.
587
+ */ fetch(request) {
588
+ return this.httpApp.fetch(request);
589
+ }
590
+ /**
591
+ * Convenience wrapper for programmatic route invocation.
592
+ * Accepts a URL string (relative paths auto-prefixed with `http://localhost`),
593
+ * URL object, or Request, plus optional `RequestInit`.
594
+ *
595
+ * Returns `null` when no route matches the request.
596
+ */ request(input, init) {
597
+ return this.httpApp.request(input, init);
579
598
  }
580
599
  listen(port, hostname, backlog, listeningListener) {
581
600
  return this.httpApp.listen(port, hostname, backlog, listeningListener);
@@ -652,7 +671,7 @@ const CONTEXT_TYPE = "HTTP";
652
671
  image: "https://moost.org/moost-full-logo.svg",
653
672
  link: "https://moost.org/",
654
673
  poweredBy: "moostjs",
655
- version: "0.6.1"
674
+ version: "0.6.2"
656
675
  });
657
676
  if (httpApp && httpApp instanceof WooksHttp) this.httpApp = httpApp;
658
677
  else if (httpApp) this.httpApp = createHttpApp({
@@ -664,4 +683,45 @@ const CONTEXT_TYPE = "HTTP";
664
683
  };
665
684
 
666
685
  //#endregion
667
- export { All, AuthGuard, Authenticate, Authorization, Body, BodyReadTimeoutMs, BodySizeLimit, CompressedBodySizeLimit, Cookie, CookieAttrsRef, CookieRef, Delete, Get, Header, HeaderRef, HttpError, HttpMethod, Ip, IpList, Method, MoostHttp, Patch, Post, Put, Query, RawBody, Req, ReqId, Res, SetCookie, SetHeader, SetStatus, StatusRef, Upgrade, Url, defineAuthGuard, extractTransports, globalBodyReadTimeoutMs, globalBodySizeLimit, globalCompressedBodySizeLimit, httpKind, useHttpContext };
686
+ //#region packages/event-http/src/local-fetch.ts
687
+ /**
688
+ * Patches `globalThis.fetch` so that requests to local paths (starting with `/`)
689
+ * are routed through `MoostHttp` in-process instead of making a network request.
690
+ * Falls back to the original `fetch` when no Moost route matches.
691
+ *
692
+ * Useful for SSR scenarios where server-side code needs to call its own API endpoints
693
+ * without the overhead of a TCP round-trip.
694
+ *
695
+ * @returns A teardown function that restores the original `globalThis.fetch`.
696
+ */ function enableLocalFetch(http) {
697
+ const originalFetch = globalThis.fetch;
698
+ globalThis.fetch = async (input, init) => {
699
+ if (typeof input === "string") {
700
+ if (input.startsWith("/")) {
701
+ const response = await http.request(input, init);
702
+ if (response) return response;
703
+ }
704
+ } else if (input instanceof URL) {
705
+ if (isLocalOrigin(input)) {
706
+ const response = await http.request(input, init);
707
+ if (response) return response;
708
+ }
709
+ } else {
710
+ const url = new URL(input.url);
711
+ if (isLocalOrigin(url)) {
712
+ const response = await http.fetch(input);
713
+ if (response) return response;
714
+ }
715
+ }
716
+ return originalFetch(input, init);
717
+ };
718
+ return () => {
719
+ globalThis.fetch = originalFetch;
720
+ };
721
+ }
722
+ function isLocalOrigin(url) {
723
+ return url.hostname === "localhost" || url.hostname === "127.0.0.1";
724
+ }
725
+
726
+ //#endregion
727
+ export { All, AuthGuard, Authenticate, Authorization, Body, BodyReadTimeoutMs, BodySizeLimit, CompressedBodySizeLimit, Cookie, CookieAttrsRef, CookieRef, Delete, Get, Header, HeaderRef, HttpError, HttpMethod, Ip, IpList, Method, MoostHttp, Patch, Post, Put, Query, RawBody, Req, ReqId, Res, SetCookie, SetHeader, SetStatus, StatusRef, Upgrade, Url, defineAuthGuard, enableLocalFetch, extractTransports, globalBodyReadTimeoutMs, globalBodySizeLimit, globalCompressedBodySizeLimit, httpKind, useHttpContext };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moostjs/event-http",
3
- "version": "0.6.2",
3
+ "version": "0.6.3",
4
4
  "description": "@moostjs/event-http",
5
5
  "keywords": [
6
6
  "composables",
@@ -43,16 +43,16 @@
43
43
  }
44
44
  },
45
45
  "dependencies": {
46
- "@wooksjs/event-http": "^0.7.4",
47
- "@wooksjs/http-body": "^0.7.4"
46
+ "@wooksjs/event-http": "^0.7.7",
47
+ "@wooksjs/http-body": "^0.7.7"
48
48
  },
49
49
  "devDependencies": {
50
50
  "vitest": "3.2.4"
51
51
  },
52
52
  "peerDependencies": {
53
53
  "@prostojs/infact": "^0.4.1",
54
- "@wooksjs/event-core": "^0.7.4",
55
- "moost": "^0.6.2"
54
+ "@wooksjs/event-core": "^0.7.7",
55
+ "moost": "^0.6.3"
56
56
  },
57
57
  "scripts": {
58
58
  "pub": "pnpm publish --access public",