@xfcfam/xf-server-http 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +240 -0
  3. package/dist/index.d.ts +63 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +55 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/src/api/A.d.ts +18 -0
  8. package/dist/src/api/A.d.ts.map +1 -0
  9. package/dist/src/api/A.js +18 -0
  10. package/dist/src/api/A.js.map +1 -0
  11. package/dist/src/api/general/GraphQLService.d.ts +48 -0
  12. package/dist/src/api/general/GraphQLService.d.ts.map +1 -0
  13. package/dist/src/api/general/GraphQLService.js +43 -0
  14. package/dist/src/api/general/GraphQLService.js.map +1 -0
  15. package/dist/src/api/general/ObjectRestService.d.ts +196 -0
  16. package/dist/src/api/general/ObjectRestService.d.ts.map +1 -0
  17. package/dist/src/api/general/ObjectRestService.js +289 -0
  18. package/dist/src/api/general/ObjectRestService.js.map +1 -0
  19. package/dist/src/api/general/RestService.d.ts +62 -0
  20. package/dist/src/api/general/RestService.d.ts.map +1 -0
  21. package/dist/src/api/general/RestService.js +75 -0
  22. package/dist/src/api/general/RestService.js.map +1 -0
  23. package/dist/src/api/general/WebSocketService.d.ts +42 -0
  24. package/dist/src/api/general/WebSocketService.d.ts.map +1 -0
  25. package/dist/src/api/general/WebSocketService.js +45 -0
  26. package/dist/src/api/general/WebSocketService.js.map +1 -0
  27. package/dist/src/api/utils/FileResponseUtils.d.ts +66 -0
  28. package/dist/src/api/utils/FileResponseUtils.d.ts.map +1 -0
  29. package/dist/src/api/utils/FileResponseUtils.js +82 -0
  30. package/dist/src/api/utils/FileResponseUtils.js.map +1 -0
  31. package/dist/src/api/utils/HttpStatusUtils.d.ts +36 -0
  32. package/dist/src/api/utils/HttpStatusUtils.d.ts.map +1 -0
  33. package/dist/src/api/utils/HttpStatusUtils.js +40 -0
  34. package/dist/src/api/utils/HttpStatusUtils.js.map +1 -0
  35. package/dist/src/api/utils/ResponseUtils.d.ts +61 -0
  36. package/dist/src/api/utils/ResponseUtils.d.ts.map +1 -0
  37. package/dist/src/api/utils/ResponseUtils.js +81 -0
  38. package/dist/src/api/utils/ResponseUtils.js.map +1 -0
  39. package/dist/src/api/utils/SchemaValidatorUtils.d.ts +48 -0
  40. package/dist/src/api/utils/SchemaValidatorUtils.d.ts.map +1 -0
  41. package/dist/src/api/utils/SchemaValidatorUtils.js +52 -0
  42. package/dist/src/api/utils/SchemaValidatorUtils.js.map +1 -0
  43. package/dist/src/api/utils/SseUtils.d.ts +57 -0
  44. package/dist/src/api/utils/SseUtils.d.ts.map +1 -0
  45. package/dist/src/api/utils/SseUtils.js +78 -0
  46. package/dist/src/api/utils/SseUtils.js.map +1 -0
  47. package/dist/src/business/B.d.ts +18 -0
  48. package/dist/src/business/B.d.ts.map +1 -0
  49. package/dist/src/business/B.js +18 -0
  50. package/dist/src/business/B.js.map +1 -0
  51. package/dist/src/business/general/HttpServerBusiness.d.ts +190 -0
  52. package/dist/src/business/general/HttpServerBusiness.d.ts.map +1 -0
  53. package/dist/src/business/general/HttpServerBusiness.js +364 -0
  54. package/dist/src/business/general/HttpServerBusiness.js.map +1 -0
  55. package/dist/src/business/transfers/BadRequestException.d.ts +13 -0
  56. package/dist/src/business/transfers/BadRequestException.d.ts.map +1 -0
  57. package/dist/src/business/transfers/BadRequestException.js +16 -0
  58. package/dist/src/business/transfers/BadRequestException.js.map +1 -0
  59. package/dist/src/business/transfers/ForbiddenException.d.ts +13 -0
  60. package/dist/src/business/transfers/ForbiddenException.d.ts.map +1 -0
  61. package/dist/src/business/transfers/ForbiddenException.js +16 -0
  62. package/dist/src/business/transfers/ForbiddenException.js.map +1 -0
  63. package/dist/src/business/transfers/GraphQLConfig.d.ts +25 -0
  64. package/dist/src/business/transfers/GraphQLConfig.d.ts.map +1 -0
  65. package/dist/src/business/transfers/GraphQLConfig.js +2 -0
  66. package/dist/src/business/transfers/GraphQLConfig.js.map +1 -0
  67. package/dist/src/business/transfers/HttpException.d.ts +23 -0
  68. package/dist/src/business/transfers/HttpException.d.ts.map +1 -0
  69. package/dist/src/business/transfers/HttpException.js +27 -0
  70. package/dist/src/business/transfers/HttpException.js.map +1 -0
  71. package/dist/src/business/transfers/HttpMethod.d.ts +7 -0
  72. package/dist/src/business/transfers/HttpMethod.d.ts.map +1 -0
  73. package/dist/src/business/transfers/HttpMethod.js +2 -0
  74. package/dist/src/business/transfers/HttpMethod.js.map +1 -0
  75. package/dist/src/business/transfers/HttpRequest.d.ts +35 -0
  76. package/dist/src/business/transfers/HttpRequest.d.ts.map +1 -0
  77. package/dist/src/business/transfers/HttpRequest.js +2 -0
  78. package/dist/src/business/transfers/HttpRequest.js.map +1 -0
  79. package/dist/src/business/transfers/HttpResponse.d.ts +28 -0
  80. package/dist/src/business/transfers/HttpResponse.d.ts.map +1 -0
  81. package/dist/src/business/transfers/HttpResponse.js +2 -0
  82. package/dist/src/business/transfers/HttpResponse.js.map +1 -0
  83. package/dist/src/business/transfers/InternalServerException.d.ts +13 -0
  84. package/dist/src/business/transfers/InternalServerException.d.ts.map +1 -0
  85. package/dist/src/business/transfers/InternalServerException.js +16 -0
  86. package/dist/src/business/transfers/InternalServerException.js.map +1 -0
  87. package/dist/src/business/transfers/MultipartPart.d.ts +38 -0
  88. package/dist/src/business/transfers/MultipartPart.d.ts.map +1 -0
  89. package/dist/src/business/transfers/MultipartPart.js +2 -0
  90. package/dist/src/business/transfers/MultipartPart.js.map +1 -0
  91. package/dist/src/business/transfers/NotFoundException.d.ts +13 -0
  92. package/dist/src/business/transfers/NotFoundException.d.ts.map +1 -0
  93. package/dist/src/business/transfers/NotFoundException.js +16 -0
  94. package/dist/src/business/transfers/NotFoundException.js.map +1 -0
  95. package/dist/src/business/transfers/Route.d.ts +25 -0
  96. package/dist/src/business/transfers/Route.d.ts.map +1 -0
  97. package/dist/src/business/transfers/Route.js +2 -0
  98. package/dist/src/business/transfers/Route.js.map +1 -0
  99. package/dist/src/business/transfers/UnauthorizedException.d.ts +13 -0
  100. package/dist/src/business/transfers/UnauthorizedException.d.ts.map +1 -0
  101. package/dist/src/business/transfers/UnauthorizedException.js +16 -0
  102. package/dist/src/business/transfers/UnauthorizedException.js.map +1 -0
  103. package/dist/src/business/transfers/WebSocketConnection.d.ts +40 -0
  104. package/dist/src/business/transfers/WebSocketConnection.d.ts.map +1 -0
  105. package/dist/src/business/transfers/WebSocketConnection.js +2 -0
  106. package/dist/src/business/transfers/WebSocketConnection.js.map +1 -0
  107. package/dist/src/repository/R.d.ts +18 -0
  108. package/dist/src/repository/R.d.ts.map +1 -0
  109. package/dist/src/repository/R.js +18 -0
  110. package/dist/src/repository/R.js.map +1 -0
  111. package/package.json +62 -0
@@ -0,0 +1,57 @@
1
+ import type { HttpResponse } from '../../business/transfers/HttpResponse.js';
2
+ /**
3
+ * A single Server-Sent Event. `data` is sent as-is when a string, or
4
+ * JSON-encoded when an object. The optional fields map to the SSE
5
+ * wire fields (`event:`, `id:`, `retry:`).
6
+ */
7
+ export interface ServerSentEvent {
8
+ /** Event payload. Strings are sent verbatim; objects are JSON-encoded. */
9
+ readonly data: string | object;
10
+ /** Named event type (`event:` field). */
11
+ readonly event?: string;
12
+ /** Event id (`id:` field) — clients echo it as `Last-Event-ID` on reconnect. */
13
+ readonly id?: string;
14
+ /** Reconnection hint in milliseconds (`retry:` field). */
15
+ readonly retry?: number;
16
+ }
17
+ /**
18
+ * Interaction-Layer Utility — turn an async stream of events into a
19
+ * `text/event-stream` {@link HttpResponse}.
20
+ *
21
+ * SSE is plain HTTP (a long-lived `GET` whose body is a stream), so it
22
+ * needs no plugin and works on any `RestService`. This helper does the
23
+ * tedious part: setting the right headers and formatting each event per
24
+ * the SSE wire protocol (multi-line `data:`, `event:`, `id:`, `retry:`,
25
+ * blank-line terminator).
26
+ *
27
+ * @example
28
+ * ```ts
29
+ * import { RestService, SseUtils } from '@xfcfam/xf-server-http'
30
+ *
31
+ * export class ClockService extends RestService {
32
+ * override async init() { B.server.get('/clock', this.wrap(this.clock)) }
33
+ *
34
+ * private async clock(): Promise<HttpResponse> {
35
+ * async function* ticks() {
36
+ * while (true) {
37
+ * yield { event: 'tick', data: { now: Date.now() } }
38
+ * await new Promise((r) => setTimeout(r, 1000))
39
+ * }
40
+ * }
41
+ * return SseUtils.stream(ticks())
42
+ * }
43
+ * }
44
+ * ```
45
+ */
46
+ export declare class SseUtils {
47
+ private constructor();
48
+ /**
49
+ * Build a streaming `text/event-stream` response from an async
50
+ * iterable of events. The stream stays open until the source is
51
+ * exhausted or the client disconnects.
52
+ */
53
+ static stream(source: AsyncIterable<ServerSentEvent>, headers?: Readonly<Record<string, string>>): HttpResponse<ReadableStream<Uint8Array>>;
54
+ /** Format a single event into its SSE wire representation. */
55
+ static format(event: ServerSentEvent): string;
56
+ }
57
+ //# sourceMappingURL=SseUtils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SseUtils.d.ts","sourceRoot":"","sources":["../../../../src/api/utils/SseUtils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0CAA0C,CAAA;AAE5E;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,0EAA0E;IAC1E,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;IAC9B,yCAAyC;IACzC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,gFAAgF;IAChF,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAA;IACpB,0DAA0D;IAC1D,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CACxB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,qBAAa,QAAQ;IACnB,OAAO;IAEP;;;;OAIG;IACH,MAAM,CAAC,MAAM,CACX,MAAM,EAAE,aAAa,CAAC,eAAe,CAAC,EACtC,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GACzC,YAAY,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;IA0B3C,8DAA8D;IAC9D,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM;CAS9C"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Interaction-Layer Utility — turn an async stream of events into a
3
+ * `text/event-stream` {@link HttpResponse}.
4
+ *
5
+ * SSE is plain HTTP (a long-lived `GET` whose body is a stream), so it
6
+ * needs no plugin and works on any `RestService`. This helper does the
7
+ * tedious part: setting the right headers and formatting each event per
8
+ * the SSE wire protocol (multi-line `data:`, `event:`, `id:`, `retry:`,
9
+ * blank-line terminator).
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * import { RestService, SseUtils } from '@xfcfam/xf-server-http'
14
+ *
15
+ * export class ClockService extends RestService {
16
+ * override async init() { B.server.get('/clock', this.wrap(this.clock)) }
17
+ *
18
+ * private async clock(): Promise<HttpResponse> {
19
+ * async function* ticks() {
20
+ * while (true) {
21
+ * yield { event: 'tick', data: { now: Date.now() } }
22
+ * await new Promise((r) => setTimeout(r, 1000))
23
+ * }
24
+ * }
25
+ * return SseUtils.stream(ticks())
26
+ * }
27
+ * }
28
+ * ```
29
+ */
30
+ export class SseUtils {
31
+ constructor() { }
32
+ /**
33
+ * Build a streaming `text/event-stream` response from an async
34
+ * iterable of events. The stream stays open until the source is
35
+ * exhausted or the client disconnects.
36
+ */
37
+ static stream(source, headers) {
38
+ const encoder = new TextEncoder();
39
+ const body = new ReadableStream({
40
+ async start(controller) {
41
+ try {
42
+ for await (const event of source) {
43
+ controller.enqueue(encoder.encode(SseUtils.format(event)));
44
+ }
45
+ controller.close();
46
+ }
47
+ catch (err) {
48
+ controller.error(err);
49
+ }
50
+ },
51
+ });
52
+ return {
53
+ status: 200,
54
+ headers: {
55
+ 'content-type': 'text/event-stream',
56
+ 'cache-control': 'no-cache',
57
+ 'connection': 'keep-alive',
58
+ ...headers,
59
+ },
60
+ body,
61
+ };
62
+ }
63
+ /** Format a single event into its SSE wire representation. */
64
+ static format(event) {
65
+ const lines = [];
66
+ if (event.event !== undefined)
67
+ lines.push(`event: ${event.event}`);
68
+ if (event.id !== undefined)
69
+ lines.push(`id: ${event.id}`);
70
+ if (event.retry !== undefined)
71
+ lines.push(`retry: ${event.retry}`);
72
+ const data = typeof event.data === 'string' ? event.data : JSON.stringify(event.data);
73
+ for (const line of data.split('\n'))
74
+ lines.push(`data: ${line}`);
75
+ return `${lines.join('\n')}\n\n`;
76
+ }
77
+ }
78
+ //# sourceMappingURL=SseUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SseUtils.js","sourceRoot":"","sources":["../../../../src/api/utils/SseUtils.ts"],"names":[],"mappings":"AAkBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,OAAO,QAAQ;IACnB,gBAAuB,CAAC;IAExB;;;;OAIG;IACH,MAAM,CAAC,MAAM,CACX,MAAsC,EACtC,OAA0C;QAE1C,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAA;QACjC,MAAM,IAAI,GAAG,IAAI,cAAc,CAAa;YAC1C,KAAK,CAAC,KAAK,CAAC,UAAU;gBACpB,IAAI,CAAC;oBACH,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;wBACjC,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;oBAC5D,CAAC;oBACD,UAAU,CAAC,KAAK,EAAE,CAAA;gBACpB,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;gBACvB,CAAC;YACH,CAAC;SACF,CAAC,CAAA;QACF,OAAO;YACL,MAAM,EAAE,GAAG;YACX,OAAO,EAAE;gBACP,cAAc,EAAE,mBAAmB;gBACnC,eAAe,EAAE,UAAU;gBAC3B,YAAY,EAAE,YAAY;gBAC1B,GAAG,OAAO;aACX;YACD,IAAI;SACL,CAAA;IACH,CAAC;IAED,8DAA8D;IAC9D,MAAM,CAAC,MAAM,CAAC,KAAsB;QAClC,MAAM,KAAK,GAAa,EAAE,CAAA;QAC1B,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS;YAAE,KAAK,CAAC,IAAI,CAAC,UAAU,KAAK,CAAC,KAAK,EAAE,CAAC,CAAA;QAClE,IAAI,KAAK,CAAC,EAAE,KAAK,SAAS;YAAE,KAAK,CAAC,IAAI,CAAC,OAAO,KAAK,CAAC,EAAE,EAAE,CAAC,CAAA;QACzD,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS;YAAE,KAAK,CAAC,IAAI,CAAC,UAAU,KAAK,CAAC,KAAK,EAAE,CAAC,CAAA;QAClE,MAAM,IAAI,GAAG,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;QACrF,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC,CAAA;QAChE,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAA;IAClC,CAAC;CACF"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Business Layer Injection — placeholder.
3
+ *
4
+ * `B` is the canonical injection of the Business Layer. `@xfcfam/xf-server`
5
+ * is a library that contributes Generalizations and Transfer objects to
6
+ * the Interaction Layer ( `ObjectRestService`,
7
+ * `HttpServerBusiness`); it does not own any Logical of this layer, so
8
+ * its own `B` declares no static slots. The class is kept structurally
9
+ * complete (private constructor + empty `init` / `terminate`) so the
10
+ * artefact passes XF validation. It is NOT exported from the package —
11
+ * consumers import `B` from their own artefact.
12
+ */
13
+ export declare class B {
14
+ private constructor();
15
+ static init(): Promise<void>;
16
+ static terminate(): Promise<void>;
17
+ }
18
+ //# sourceMappingURL=B.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"B.d.ts","sourceRoot":"","sources":["../../../src/business/B.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,qBAAa,CAAC;IACZ,OAAO;WACM,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;WACrB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;CACxC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Business Layer Injection — placeholder.
3
+ *
4
+ * `B` is the canonical injection of the Business Layer. `@xfcfam/xf-server`
5
+ * is a library that contributes Generalizations and Transfer objects to
6
+ * the Interaction Layer ( `ObjectRestService`,
7
+ * `HttpServerBusiness`); it does not own any Logical of this layer, so
8
+ * its own `B` declares no static slots. The class is kept structurally
9
+ * complete (private constructor + empty `init` / `terminate`) so the
10
+ * artefact passes XF validation. It is NOT exported from the package —
11
+ * consumers import `B` from their own artefact.
12
+ */
13
+ export class B {
14
+ constructor() { }
15
+ static async init() { }
16
+ static async terminate() { }
17
+ }
18
+ //# sourceMappingURL=B.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"B.js","sourceRoot":"","sources":["../../../src/business/B.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,MAAM,OAAO,CAAC;IACZ,gBAAuB,CAAC;IACxB,MAAM,CAAC,KAAK,CAAC,IAAI,KAAmB,CAAC;IACrC,MAAM,CAAC,KAAK,CAAC,SAAS,KAAmB,CAAC;CAC3C"}
@@ -0,0 +1,190 @@
1
+ import { ServerBusiness, type ServerState } from '@xfcfam/xf-server';
2
+ import { type FastifyInstance } from 'fastify';
3
+ import type { HttpRequest } from '../transfers/HttpRequest.js';
4
+ import type { HttpResponse } from '../transfers/HttpResponse.js';
5
+ import type { HttpMethod } from '../transfers/HttpMethod.js';
6
+ import type { HttpAddress, HttpHandler } from '../transfers/Route.js';
7
+ import type { WebSocketHandler } from '../transfers/WebSocketConnection.js';
8
+ import type { GraphQLConfig } from '../transfers/GraphQLConfig.js';
9
+ /** Internal record of a WebSocket endpoint pushed before `listen()`. */
10
+ interface WsRoute {
11
+ readonly path: string;
12
+ readonly handler: WebSocketHandler;
13
+ }
14
+ /**
15
+ * Multipart upload configuration. Forwarded verbatim to
16
+ * `@fastify/multipart` (consult its docs for the full list). The most
17
+ * common knobs:
18
+ *
19
+ * - `maxFileSize`: per-file size limit in bytes (Fastify default 1 MiB).
20
+ * - `maxFiles`: maximum number of file parts per request.
21
+ * - `maxFields`: maximum number of non-file fields.
22
+ * - `maxFieldsSize`: total size limit for non-file fields.
23
+ */
24
+ export interface MultipartConfig {
25
+ readonly maxFileSize?: number;
26
+ readonly maxFiles?: number;
27
+ readonly maxFields?: number;
28
+ readonly maxFieldsSize?: number;
29
+ }
30
+ /**
31
+ * Configuration accepted by {@link HttpServerBusiness}'s constructor.
32
+ */
33
+ export interface ServerOptions {
34
+ /** TCP port to bind. */
35
+ readonly port: number;
36
+ /** Host to bind. Default `'0.0.0.0'`. */
37
+ readonly host?: string;
38
+ /**
39
+ * Opt-in `multipart/form-data` support. Pass `true` for defaults or
40
+ * a config object to tune limits.
41
+ *
42
+ * When enabled, the server activates multipart handling at `listen()`
43
+ * time and, for any request whose `Content-Type` is
44
+ * `multipart/form-data`, populates `req.body` with a
45
+ * `MultipartPart[]`. All underlying machinery is shipped as part
46
+ * of xf-server-http — the consumer does not install or import any
47
+ * extra package.
48
+ */
49
+ readonly multipart?: boolean | MultipartConfig;
50
+ }
51
+ /**
52
+ * Concrete server state: the abstract route registry plus the Fastify
53
+ * instance and the bind options.
54
+ */
55
+ interface HttpServerState extends ServerState<HttpAddress, HttpRequest, HttpResponse> {
56
+ readonly options: ServerOptions;
57
+ /** The running Fastify instance; `undefined` before `listen()` and after `close()`. */
58
+ fastify: FastifyInstance | undefined;
59
+ /** WebSocket endpoints pushed via `ws()` before `listen()`. */
60
+ readonly wsRoutes: WsRoute[];
61
+ /** GraphQL endpoint pushed via `graphql()`, if any. */
62
+ graphql: GraphQLConfig | undefined;
63
+ }
64
+ /**
65
+ * Business-Layer Generalization for the artefact-level HTTP server
66
+ * orchestrator — the Fastify implementation of the transport-agnostic
67
+ * {@link ServerBusiness} contract from `@xfcfam/xf-server`.
68
+ *
69
+ * It is **technology-aware** (Fastify, HTTP) by design: the Business
70
+ * Layer in XF is the correct home for infrastructure concerns that are
71
+ * not domain rules — the HTTP server is infrastructure, not domain
72
+ * logic. The route registry and the request pipeline come from the
73
+ * core; this class supplies the HTTP address scheme (`{ method, path }`),
74
+ * the Fastify lifecycle (`listen` / `close`), body collection
75
+ * (including multipart) and the error → HTTP-status mapping.
76
+ *
77
+ * **Registration model — push, not pull.** Interaction Services register
78
+ * their routes by calling `B.server.get(path, handler)` (or `post`,
79
+ * `put`, `patch`, `del`, `call`) from within their own `init()`. The
80
+ * server MUST be created and available on `B` before `A.init()` runs;
81
+ * `listen()` is called by the start-point AFTER all services have
82
+ * registered.
83
+ *
84
+ * **Handler contract.** Handlers are `HttpHandler` functions
85
+ * (`(req: HttpRequest) => Promise<HttpResponse> | HttpResponse`). The
86
+ * server calls them with an `HttpRequest` whose `body` is the raw
87
+ * bytes/stream (or a `MultipartPart[]` for multipart requests).
88
+ * Serialisation (object → bytes) and parsing (bytes → object) are the
89
+ * Interaction Layer's responsibility — see `ObjectRestService.object()`.
90
+ *
91
+ * @example
92
+ * ```ts
93
+ * // business/logic/AppServerBusiness.ts
94
+ * import { HttpServerBusiness, type HttpRequest } from '@xfcfam/xf-server-http'
95
+ *
96
+ * export class AppServerBusiness extends HttpServerBusiness {
97
+ * constructor() {
98
+ * super({ port: Number.parseInt(process.env['PORT'] ?? '3000', 10) })
99
+ * }
100
+ *
101
+ * override async onRequest(req: HttpRequest): Promise<HttpRequest> {
102
+ * console.log(`[server] → ${req.method} ${req.path}`)
103
+ * return req
104
+ * }
105
+ * }
106
+ *
107
+ * // business/B.ts
108
+ * export class B {
109
+ * private constructor() {}
110
+ * static readonly server = new AppServerBusiness()
111
+ * static async init() { await B.server.init() }
112
+ * static async terminate() { await B.server.terminate() }
113
+ * }
114
+ *
115
+ * // main.ts (start-point): once the XF element has bootstrapped the
116
+ * // layers R → B → A and the services have pushed their routes, start
117
+ * // the transport explicitly:
118
+ * await B.server.listen() // start Fastify after all routes are in
119
+ * // ...and on shutdown, before the XF element tears the layers down:
120
+ * await B.server.close()
121
+ * ```
122
+ */
123
+ export declare abstract class HttpServerBusiness extends ServerBusiness<HttpAddress, HttpRequest, HttpResponse, HttpServerState> {
124
+ constructor(options: ServerOptions);
125
+ /** Register a GET endpoint. */
126
+ get(path: string, handler: HttpHandler): void;
127
+ /** Register a POST endpoint. */
128
+ post(path: string, handler: HttpHandler): void;
129
+ /** Register a PUT endpoint. */
130
+ put(path: string, handler: HttpHandler): void;
131
+ /** Register a PATCH endpoint. */
132
+ patch(path: string, handler: HttpHandler): void;
133
+ /** Register a DELETE endpoint. */
134
+ del(path: string, handler: HttpHandler): void;
135
+ /**
136
+ * Register an endpoint for an arbitrary HTTP method. Used for
137
+ * `HEAD`, `OPTIONS`, or any verb not covered by the convenience
138
+ * helpers.
139
+ */
140
+ call(method: HttpMethod, path: string, handler: HttpHandler): void;
141
+ /**
142
+ * Register a WebSocket endpoint. The handler receives a
143
+ * {@link WebSocketConnection} once the client upgrade completes. The
144
+ * WebSocket plugin runs on the same Fastify instance and port as the
145
+ * REST routes; like every registration, call this before `listen()`.
146
+ */
147
+ ws(path: string, handler: WebSocketHandler): void;
148
+ /**
149
+ * Register a GraphQL endpoint (schema + resolvers). The GraphQL
150
+ * engine (Mercurius) is mounted on the shared Fastify instance at
151
+ * `config.path` (default `/graphql`). At most one GraphQL endpoint per
152
+ * server; a later call replaces the earlier config.
153
+ */
154
+ graphql(config: GraphQLConfig): void;
155
+ /**
156
+ * Start accepting requests. Creates the Fastify instance, registers
157
+ * multipart support if configured, mounts every route that has been
158
+ * pushed so far, and begins listening.
159
+ *
160
+ * Call this from the start-point AFTER the Interaction layer has
161
+ * registered all routes — no new routes should be pushed after this
162
+ * point.
163
+ */
164
+ listen(): Promise<void>;
165
+ /**
166
+ * Stop accepting requests and release the Fastify instance. Waits
167
+ * for in-flight requests to complete before resolving.
168
+ */
169
+ close(): Promise<void>;
170
+ /**
171
+ * Get the underlying Fastify instance. Throws if `listen()` hasn't
172
+ * run. Exposed so protocol extensions (WebSocket, GraphQL) can
173
+ * register their plugins on the same instance.
174
+ */
175
+ protected fastifyInstance(): FastifyInstance;
176
+ private adapter;
177
+ private static request;
178
+ private static collectMultipart;
179
+ private static collectNodeStream;
180
+ private static registerMultipart;
181
+ private static registerWebSocket;
182
+ private static adaptSocket;
183
+ private static toFrame;
184
+ private static registerGraphQL;
185
+ private static sendResponse;
186
+ private static errorToResponse;
187
+ private static isReadableStream;
188
+ }
189
+ export {};
190
+ //# sourceMappingURL=HttpServerBusiness.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HttpServerBusiness.d.ts","sourceRoot":"","sources":["../../../../src/business/general/HttpServerBusiness.ts"],"names":[],"mappings":"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"}