@venizia/ignis-worker 0.2.0-2

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 (89) hide show
  1. package/dist/cjs/applications/index.d.ts +2 -0
  2. package/dist/cjs/applications/index.d.ts.map +1 -0
  3. package/dist/cjs/applications/index.js +18 -0
  4. package/dist/cjs/applications/index.js.map +1 -0
  5. package/dist/cjs/applications/worker.d.ts +67 -0
  6. package/dist/cjs/applications/worker.d.ts.map +1 -0
  7. package/dist/cjs/applications/worker.js +175 -0
  8. package/dist/cjs/applications/worker.js.map +1 -0
  9. package/dist/cjs/envelope/encode.d.ts +61 -0
  10. package/dist/cjs/envelope/encode.d.ts.map +1 -0
  11. package/dist/cjs/envelope/encode.js +116 -0
  12. package/dist/cjs/envelope/encode.js.map +1 -0
  13. package/dist/cjs/envelope/index.d.ts +3 -0
  14. package/dist/cjs/envelope/index.d.ts.map +1 -0
  15. package/dist/cjs/envelope/index.js +19 -0
  16. package/dist/cjs/envelope/index.js.map +1 -0
  17. package/dist/cjs/envelope/types.d.ts +37 -0
  18. package/dist/cjs/envelope/types.d.ts.map +1 -0
  19. package/dist/cjs/envelope/types.js +3 -0
  20. package/dist/cjs/envelope/types.js.map +1 -0
  21. package/dist/cjs/index.d.ts +5 -0
  22. package/dist/cjs/index.d.ts.map +1 -0
  23. package/dist/cjs/index.js +21 -0
  24. package/dist/cjs/index.js.map +1 -0
  25. package/dist/cjs/transport/common/index.d.ts +2 -0
  26. package/dist/cjs/transport/common/index.d.ts.map +1 -0
  27. package/dist/cjs/transport/common/index.js +18 -0
  28. package/dist/cjs/transport/common/index.js.map +1 -0
  29. package/dist/cjs/transport/common/types.d.ts +6 -0
  30. package/dist/cjs/transport/common/types.d.ts.map +1 -0
  31. package/dist/cjs/transport/common/types.js +3 -0
  32. package/dist/cjs/transport/common/types.js.map +1 -0
  33. package/dist/cjs/transport/in-process.d.ts +22 -0
  34. package/dist/cjs/transport/in-process.d.ts.map +1 -0
  35. package/dist/cjs/transport/in-process.js +45 -0
  36. package/dist/cjs/transport/in-process.js.map +1 -0
  37. package/dist/cjs/transport/index.d.ts +4 -0
  38. package/dist/cjs/transport/index.d.ts.map +1 -0
  39. package/dist/cjs/transport/index.js +20 -0
  40. package/dist/cjs/transport/index.js.map +1 -0
  41. package/dist/cjs/transport/worker.d.ts +48 -0
  42. package/dist/cjs/transport/worker.d.ts.map +1 -0
  43. package/dist/cjs/transport/worker.js +165 -0
  44. package/dist/cjs/transport/worker.js.map +1 -0
  45. package/dist/esm/applications/index.d.ts +2 -0
  46. package/dist/esm/applications/index.d.ts.map +1 -0
  47. package/dist/esm/applications/index.js +2 -0
  48. package/dist/esm/applications/index.js.map +1 -0
  49. package/dist/esm/applications/worker.d.ts +67 -0
  50. package/dist/esm/applications/worker.d.ts.map +1 -0
  51. package/dist/esm/applications/worker.js +171 -0
  52. package/dist/esm/applications/worker.js.map +1 -0
  53. package/dist/esm/envelope/encode.d.ts +61 -0
  54. package/dist/esm/envelope/encode.d.ts.map +1 -0
  55. package/dist/esm/envelope/encode.js +112 -0
  56. package/dist/esm/envelope/encode.js.map +1 -0
  57. package/dist/esm/envelope/index.d.ts +3 -0
  58. package/dist/esm/envelope/index.d.ts.map +1 -0
  59. package/dist/esm/envelope/index.js +3 -0
  60. package/dist/esm/envelope/index.js.map +1 -0
  61. package/dist/esm/envelope/types.d.ts +37 -0
  62. package/dist/esm/envelope/types.d.ts.map +1 -0
  63. package/dist/esm/envelope/types.js +2 -0
  64. package/dist/esm/envelope/types.js.map +1 -0
  65. package/dist/esm/index.d.ts +5 -0
  66. package/dist/esm/index.d.ts.map +1 -0
  67. package/dist/esm/index.js +5 -0
  68. package/dist/esm/index.js.map +1 -0
  69. package/dist/esm/transport/common/index.d.ts +2 -0
  70. package/dist/esm/transport/common/index.d.ts.map +1 -0
  71. package/dist/esm/transport/common/index.js +2 -0
  72. package/dist/esm/transport/common/index.js.map +1 -0
  73. package/dist/esm/transport/common/types.d.ts +6 -0
  74. package/dist/esm/transport/common/types.d.ts.map +1 -0
  75. package/dist/esm/transport/common/types.js +2 -0
  76. package/dist/esm/transport/common/types.js.map +1 -0
  77. package/dist/esm/transport/in-process.d.ts +22 -0
  78. package/dist/esm/transport/in-process.d.ts.map +1 -0
  79. package/dist/esm/transport/in-process.js +41 -0
  80. package/dist/esm/transport/in-process.js.map +1 -0
  81. package/dist/esm/transport/index.d.ts +4 -0
  82. package/dist/esm/transport/index.d.ts.map +1 -0
  83. package/dist/esm/transport/index.js +4 -0
  84. package/dist/esm/transport/index.js.map +1 -0
  85. package/dist/esm/transport/worker.d.ts +48 -0
  86. package/dist/esm/transport/worker.d.ts.map +1 -0
  87. package/dist/esm/transport/worker.js +161 -0
  88. package/dist/esm/transport/worker.js.map +1 -0
  89. package/package.json +94 -0
@@ -0,0 +1,61 @@
1
+ import type { ApplicationError } from '@venizia/ignis-helpers/core';
2
+ import type { IBffErrorEnvelope, IBffRequestEnvelope, IBffResponseEnvelope } from './types.js';
3
+ /**
4
+ * Every request built inside the Worker uses this origin. Never `self.location.href`: a `blob:`
5
+ * worker origin is opaque and `new URL(path, blobUrl)` throws, and Hono's `getPath()` mis-parses
6
+ * `file://`. Hono never resolves the host - it string-scans from `indexOf(':') + 4`.
7
+ */
8
+ export declare const BFF_SYNTHETIC_ORIGIN = "http://ignis.internal";
9
+ /** Turns `Request`/`Response`/`Error` into plain structured-cloneable shapes and back - none of the three survives `postMessage` as itself. */
10
+ export declare class BffEnvelope {
11
+ /**
12
+ * Statuses the Fetch spec forbids a body on - `new Response(body, { status })` throws if `body`
13
+ * is anything but `null` for one of these, even an empty `ArrayBuffer`.
14
+ */
15
+ private static readonly NULL_BODY_STATUSES;
16
+ /**
17
+ * Moves a URL onto the synthetic origin, keeping everything below it. A caller builds a request
18
+ * against the page's real origin (or a relative path resolved against it); `decodeRequest` on the
19
+ * far side always reconstructs on `BFF_SYNTHETIC_ORIGIN`.
20
+ */
21
+ static toSyntheticUrl(opts: {
22
+ url: string;
23
+ }): string;
24
+ /**
25
+ * `url` overrides the request's own, so the origin rewrite costs nothing: rebuilding the `Request`
26
+ * to change its URL would read the body a second time, and a 10 MB upload would hold 20 MB on the
27
+ * UI thread. Reading the body here disturbs the caller's request exactly as `globalThis.fetch`
28
+ * does with the one it is handed.
29
+ */
30
+ static encodeRequest(opts: {
31
+ request: Request;
32
+ id: string;
33
+ url?: string;
34
+ }): Promise<IBffRequestEnvelope>;
35
+ static decodeRequest(opts: {
36
+ envelope: IBffRequestEnvelope;
37
+ }): Request;
38
+ static encodeResponse(opts: {
39
+ response: Response;
40
+ id: string;
41
+ }): Promise<IBffResponseEnvelope>;
42
+ static decodeResponse(opts: {
43
+ envelope: IBffResponseEnvelope;
44
+ }): Response;
45
+ /**
46
+ * Builds the shape an error crosses `postMessage` as. An `ApplicationError` cannot cross as itself
47
+ * - a custom `Error` subclass loses its name, its own properties and its prototype through
48
+ * structured clone - so it crosses normalised and `decodeError` rebuilds it on the far side.
49
+ *
50
+ * A foreign error gets `500`, matching what the framework's error middleware gives an UNEXPECTED
51
+ * one on the server. Anything reaching here already escaped the whole HTTP layer.
52
+ */
53
+ static encodeError(opts: {
54
+ id: string;
55
+ error: unknown;
56
+ }): IBffErrorEnvelope;
57
+ static decodeError(opts: {
58
+ envelope: IBffErrorEnvelope;
59
+ }): ApplicationError;
60
+ }
61
+ //# sourceMappingURL=encode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encode.d.ts","sourceRoot":"","sources":["../../../src/envelope/encode.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAGpE,OAAO,KAAK,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAE5F;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,0BAA0B,CAAC;AAE5D,+IAA+I;AAC/I,qBAAa,WAAW;IACtB;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAA4B;IAEtE;;;;OAIG;IACH,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM;IAKpD;;;;;OAKG;WACU,aAAa,CAAC,IAAI,EAAE;QAC/B,OAAO,EAAE,OAAO,CAAC;QACjB,EAAE,EAAE,MAAM,CAAC;QACX,GAAG,CAAC,EAAE,MAAM,CAAC;KACd,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAahC,MAAM,CAAC,aAAa,CAAC,IAAI,EAAE;QAAE,QAAQ,EAAE,mBAAmB,CAAA;KAAE,GAAG,OAAO;WAUzD,cAAc,CAAC,IAAI,EAAE;QAChC,QAAQ,EAAE,QAAQ,CAAC;QACnB,EAAE,EAAE,MAAM,CAAC;KACZ,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAajC,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE;QAAE,QAAQ,EAAE,oBAAoB,CAAA;KAAE,GAAG,QAAQ;IAazE;;;;;;;OAOG;IACH,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,GAAG,iBAAiB;IAoB3E,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE;QAAE,QAAQ,EAAE,iBAAiB,CAAA;KAAE,GAAG,gBAAgB;CAc5E"}
@@ -0,0 +1,112 @@
1
+ import { fromError, getError, isApplicationError } from '@venizia/ignis-helpers/core';
2
+ import { HTTP } from '@venizia/ignis-helpers/common';
3
+ /**
4
+ * Every request built inside the Worker uses this origin. Never `self.location.href`: a `blob:`
5
+ * worker origin is opaque and `new URL(path, blobUrl)` throws, and Hono's `getPath()` mis-parses
6
+ * `file://`. Hono never resolves the host - it string-scans from `indexOf(':') + 4`.
7
+ */
8
+ export const BFF_SYNTHETIC_ORIGIN = 'http://ignis.internal';
9
+ /** Turns `Request`/`Response`/`Error` into plain structured-cloneable shapes and back - none of the three survives `postMessage` as itself. */
10
+ export class BffEnvelope {
11
+ /**
12
+ * Statuses the Fetch spec forbids a body on - `new Response(body, { status })` throws if `body`
13
+ * is anything but `null` for one of these, even an empty `ArrayBuffer`.
14
+ */
15
+ static { this.NULL_BODY_STATUSES = new Set([204, 205, 304]); }
16
+ /**
17
+ * Moves a URL onto the synthetic origin, keeping everything below it. A caller builds a request
18
+ * against the page's real origin (or a relative path resolved against it); `decodeRequest` on the
19
+ * far side always reconstructs on `BFF_SYNTHETIC_ORIGIN`.
20
+ */
21
+ static toSyntheticUrl(opts) {
22
+ const url = new URL(opts.url);
23
+ return `${BFF_SYNTHETIC_ORIGIN}${url.pathname}${url.search}${url.hash}`;
24
+ }
25
+ /**
26
+ * `url` overrides the request's own, so the origin rewrite costs nothing: rebuilding the `Request`
27
+ * to change its URL would read the body a second time, and a 10 MB upload would hold 20 MB on the
28
+ * UI thread. Reading the body here disturbs the caller's request exactly as `globalThis.fetch`
29
+ * does with the one it is handed.
30
+ */
31
+ static async encodeRequest(opts) {
32
+ const { request, id, url } = opts;
33
+ const hasBody = request.method !== 'GET' && request.method !== 'HEAD';
34
+ return {
35
+ id,
36
+ method: request.method,
37
+ url: url ?? request.url,
38
+ headers: [...request.headers.entries()],
39
+ body: hasBody ? await request.arrayBuffer() : undefined,
40
+ };
41
+ }
42
+ static decodeRequest(opts) {
43
+ const { envelope } = opts;
44
+ return new Request(envelope.url, {
45
+ method: envelope.method,
46
+ headers: envelope.headers,
47
+ body: envelope.body,
48
+ });
49
+ }
50
+ static async encodeResponse(opts) {
51
+ const { response, id } = opts;
52
+ const hasBody = !BffEnvelope.NULL_BODY_STATUSES.has(response.status);
53
+ return {
54
+ id,
55
+ status: response.status,
56
+ statusText: response.statusText,
57
+ headers: [...response.headers.entries()],
58
+ body: hasBody ? await response.arrayBuffer() : undefined,
59
+ };
60
+ }
61
+ static decodeResponse(opts) {
62
+ const { envelope } = opts;
63
+ const body = BffEnvelope.NULL_BODY_STATUSES.has(envelope.status)
64
+ ? null
65
+ : (envelope.body ?? null);
66
+ return new Response(body, {
67
+ status: envelope.status,
68
+ statusText: envelope.statusText,
69
+ headers: envelope.headers,
70
+ });
71
+ }
72
+ /**
73
+ * Builds the shape an error crosses `postMessage` as. An `ApplicationError` cannot cross as itself
74
+ * - a custom `Error` subclass loses its name, its own properties and its prototype through
75
+ * structured clone - so it crosses normalised and `decodeError` rebuilds it on the far side.
76
+ *
77
+ * A foreign error gets `500`, matching what the framework's error middleware gives an UNEXPECTED
78
+ * one on the server. Anything reaching here already escaped the whole HTTP layer.
79
+ */
80
+ static encodeError(opts) {
81
+ const { id, error } = opts;
82
+ const applicationError = isApplicationError(error)
83
+ ? error
84
+ : getError({
85
+ statusCode: HTTP.ResultCodes.RS_5.InternalServerError,
86
+ message: error instanceof Error ? error.message : String(error),
87
+ });
88
+ return {
89
+ id,
90
+ statusCode: applicationError.statusCode,
91
+ error: {
92
+ text: applicationError.normalized.text,
93
+ code: applicationError.normalized.code,
94
+ args: applicationError.normalized.args,
95
+ },
96
+ };
97
+ }
98
+ static decodeError(opts) {
99
+ const { envelope } = opts;
100
+ return fromError({
101
+ error: {
102
+ statusCode: envelope.statusCode,
103
+ normalized: {
104
+ text: envelope.error.text,
105
+ code: envelope.error.code,
106
+ args: envelope.error.args,
107
+ },
108
+ },
109
+ });
110
+ }
111
+ }
112
+ //# sourceMappingURL=encode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encode.js","sourceRoot":"","sources":["../../../src/envelope/encode.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export * from './encode.js';
2
+ export * from './types.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/envelope/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC"}
@@ -0,0 +1,3 @@
1
+ export * from './encode.js';
2
+ export * from './types.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/envelope/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC"}
@@ -0,0 +1,37 @@
1
+ /** Headers are carried as tuples: a `Headers` instance is not structured-cloneable. */
2
+ export type TEnvelopeHeaders = Array<[string, string]>;
3
+ export interface IBffRequestEnvelope {
4
+ id: string;
5
+ method: string;
6
+ url: string;
7
+ headers: TEnvelopeHeaders;
8
+ /** Buffered, never a stream - `ReadableStream` does not transfer in Safari. */
9
+ body?: ArrayBuffer;
10
+ }
11
+ export interface IBffResponseEnvelope {
12
+ id: string;
13
+ status: number;
14
+ statusText?: string;
15
+ headers: TEnvelopeHeaders;
16
+ body?: ArrayBuffer;
17
+ }
18
+ /**
19
+ * A custom `Error` subclass loses its name, its own properties and its prototype through structured
20
+ * clone, so an `ApplicationError` cannot cross as itself. It crosses as its normalised shape and is
21
+ * rebuilt with `fromError` on the far side.
22
+ */
23
+ export interface IBffErrorEnvelope {
24
+ id: string;
25
+ /**
26
+ * Carried explicitly, because `fromError` defaults a missing one to 400. This envelope is only
27
+ * ever produced when something escaped Hono's `onError` - the 500-class failures a UI must not
28
+ * classify as its own bad request.
29
+ */
30
+ statusCode: number;
31
+ error: {
32
+ text: string;
33
+ code?: string;
34
+ args?: unknown;
35
+ };
36
+ }
37
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/envelope/types.ts"],"names":[],"mappings":"AAAA,uFAAuF;AACvF,MAAM,MAAM,gBAAgB,GAAG,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAEvD,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,gBAAgB,CAAC;IAC1B,+EAA+E;IAC/E,IAAI,CAAC,EAAE,WAAW,CAAC;CACpB;AAED,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,gBAAgB,CAAC;IAC1B,IAAI,CAAC,EAAE,WAAW,CAAC;CACpB;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX;;;;OAIG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CACxD"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/envelope/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,5 @@
1
+ import 'reflect-metadata';
2
+ export * from './applications/index.js';
3
+ export * from './envelope/index.js';
4
+ export * from './transport/index.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAE1B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC"}
@@ -0,0 +1,5 @@
1
+ import 'reflect-metadata';
2
+ export * from './applications/index.js';
3
+ export * from './envelope/index.js';
4
+ export * from './transport/index.js';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAE1B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from './types.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/transport/common/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from './types.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/transport/common/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC"}
@@ -0,0 +1,6 @@
1
+ export interface IBffTransport {
2
+ fetch(opts: {
3
+ request: Request;
4
+ }): Promise<Response>;
5
+ }
6
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/transport/common/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;CACtD"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/transport/common/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,22 @@
1
+ import type { IBffTransport } from './common/types.js';
2
+ /**
3
+ * No worker, no browser - the seam that makes a BFF testable in-process. It still runs the full
4
+ * envelope round trip, and that is the whole point: a bare pass-through lets a route pass here and
5
+ * hang over a real Worker, because only the envelope applies the synthetic origin, buffers a
6
+ * streaming body, and reduces a thrown error to `{ text, code, args }`. A test is worth what its
7
+ * differences from production are worth.
8
+ *
9
+ * What it deliberately does NOT mirror is the timeout: in-process there is no message that can be
10
+ * lost, so a handler either settles or the caller's own test timeout fires.
11
+ */
12
+ export declare class InProcessBffTransport implements IBffTransport {
13
+ private readonly handler;
14
+ private readonly requestIdGenerator;
15
+ constructor(opts: {
16
+ handler: (request: Request) => Promise<Response>;
17
+ });
18
+ fetch(opts: {
19
+ request: Request;
20
+ }): Promise<Response>;
21
+ }
22
+ //# sourceMappingURL=in-process.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"in-process.d.ts","sourceRoot":"","sources":["../../../src/transport/in-process.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEpD;;;;;;;;;GASG;AACH,qBAAa,qBAAsB,YAAW,aAAa;IACzD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA0C;IAClE,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAEhC;gBAES,IAAI,EAAE;QAAE,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;KAAE;IAIhE,KAAK,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,QAAQ,CAAC;CAuB3D"}
@@ -0,0 +1,41 @@
1
+ import { RequestIdGenerator } from '@venizia/ignis-helpers/core';
2
+ import { BffEnvelope } from '../envelope/encode.js';
3
+ /**
4
+ * No worker, no browser - the seam that makes a BFF testable in-process. It still runs the full
5
+ * envelope round trip, and that is the whole point: a bare pass-through lets a route pass here and
6
+ * hang over a real Worker, because only the envelope applies the synthetic origin, buffers a
7
+ * streaming body, and reduces a thrown error to `{ text, code, args }`. A test is worth what its
8
+ * differences from production are worth.
9
+ *
10
+ * What it deliberately does NOT mirror is the timeout: in-process there is no message that can be
11
+ * lost, so a handler either settles or the caller's own test timeout fires.
12
+ */
13
+ export class InProcessBffTransport {
14
+ constructor(opts) {
15
+ this.requestIdGenerator = new RequestIdGenerator({
16
+ scope: InProcessBffTransport.name,
17
+ });
18
+ this.handler = opts.handler;
19
+ }
20
+ async fetch(opts) {
21
+ const id = this.requestIdGenerator.nextId();
22
+ const requestEnvelope = await BffEnvelope.encodeRequest({
23
+ request: opts.request,
24
+ id,
25
+ url: BffEnvelope.toSyntheticUrl({ url: opts.request.url }),
26
+ });
27
+ let responseEnvelope;
28
+ try {
29
+ const response = await this.handler(BffEnvelope.decodeRequest({ envelope: requestEnvelope }));
30
+ responseEnvelope = await BffEnvelope.encodeResponse({ response, id });
31
+ }
32
+ catch (error) {
33
+ // Encoded and decoded rather than rethrown: what a UI receives over a real Worker is a
34
+ // rebuilt `ApplicationError` carrying only the normalised shape - never the original object,
35
+ // its stack or its `extra`.
36
+ throw BffEnvelope.decodeError({ envelope: BffEnvelope.encodeError({ id, error }) });
37
+ }
38
+ return BffEnvelope.decodeResponse({ envelope: responseEnvelope });
39
+ }
40
+ }
41
+ //# sourceMappingURL=in-process.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"in-process.js","sourceRoot":"","sources":["../../../src/transport/in-process.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAIhD;;;;;;;;;GASG;AACH,MAAM,OAAO,qBAAqB;IAMhC,YAAY,IAA0D;QAJrD,uBAAkB,GAAG,IAAI,kBAAkB,CAAC;YAC3D,KAAK,EAAE,qBAAqB,CAAC,IAAI;SAClC,CAAC,CAAC;QAGD,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,IAA0B;QACpC,MAAM,EAAE,GAAG,IAAI,CAAC,kBAAkB,CAAC,MAAM,EAAE,CAAC;QAE5C,MAAM,eAAe,GAAG,MAAM,WAAW,CAAC,aAAa,CAAC;YACtD,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,EAAE;YACF,GAAG,EAAE,WAAW,CAAC,cAAc,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;SAC3D,CAAC,CAAC;QAEH,IAAI,gBAAsC,CAAC;QAE3C,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,aAAa,CAAC,EAAE,QAAQ,EAAE,eAAe,EAAE,CAAC,CAAC,CAAC;YAC9F,gBAAgB,GAAG,MAAM,WAAW,CAAC,cAAc,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC;QACxE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,uFAAuF;YACvF,6FAA6F;YAC7F,4BAA4B;YAC5B,MAAM,WAAW,CAAC,WAAW,CAAC,EAAE,QAAQ,EAAE,WAAW,CAAC,WAAW,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;QACtF,CAAC;QAED,OAAO,WAAW,CAAC,cAAc,CAAC,EAAE,QAAQ,EAAE,gBAAgB,EAAE,CAAC,CAAC;IACpE,CAAC;CACF"}
@@ -0,0 +1,4 @@
1
+ export * from './common/index.js';
2
+ export * from './in-process.js';
3
+ export * from './worker.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/transport/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC"}
@@ -0,0 +1,4 @@
1
+ export * from './common/index.js';
2
+ export * from './in-process.js';
3
+ export * from './worker.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/transport/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC"}
@@ -0,0 +1,48 @@
1
+ import { BaseHelper } from '@venizia/ignis-helpers/core';
2
+ import type { IBffTransport } from './common/types.js';
3
+ /**
4
+ * UI-side half of the BFF: posts an encoded request to a real `Worker` and resolves the matching
5
+ * response by `id` - the far side of `WorkerApplication.listen()`.
6
+ *
7
+ * The three worker listeners are attached ONCE, in the constructor, and every request is tracked in
8
+ * `pendingRequests` instead. Registering them per request looks equivalent and is not: they are
9
+ * scoped to the shared `Worker`, so a single `messageerror` - which means exactly one message
10
+ * failed to deserialise - would fire every in-flight request's handler, rejecting nine healthy
11
+ * requests that are about to be answered normally.
12
+ */
13
+ export declare class WorkerBffTransport extends BaseHelper implements IBffTransport {
14
+ private readonly worker;
15
+ private readonly timeoutMs;
16
+ private readonly requestIdGenerator;
17
+ private readonly pendingRequests;
18
+ constructor(opts: {
19
+ worker: Worker;
20
+ timeoutMs?: number;
21
+ });
22
+ /** Removes a pending request from the map and releases its timer and abort listener, so nothing can settle it twice. */
23
+ private readonly takePending;
24
+ private readonly handleMessage;
25
+ /**
26
+ * A dead or crashed worker never posts anything back, so every in-flight request is lost - this
27
+ * is the one event that legitimately settles all of them, instead of leaving each to time out.
28
+ */
29
+ private readonly handleWorkerError;
30
+ /**
31
+ * `messageerror` means exactly ONE posted message failed to deserialise, and the event carries
32
+ * nothing that says which. With a single request in flight that is unambiguous, so it settles
33
+ * now; with several, the lost answer belongs to one of them and rejecting the rest would be a
34
+ * lie - each then ends on its own timeout, under its own id.
35
+ */
36
+ private readonly handleMessageError;
37
+ fetch(opts: {
38
+ request: Request;
39
+ }): Promise<Response>;
40
+ /** `signal.reason` first, the way `globalThis.fetch` rejects, so `controller.abort(myReason)` still reaches the caller. */
41
+ private toAbortError;
42
+ /**
43
+ * Detaches the three worker listeners and fails whatever is still in flight. The worker itself is
44
+ * left alone - this transport did not create it, and a page may hand the same one to another.
45
+ */
46
+ close(): void;
47
+ }
48
+ //# sourceMappingURL=worker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../../../src/transport/worker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAY,MAAM,6BAA6B,CAAC;AAInE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAiBpD;;;;;;;;;GASG;AACH,qBAAa,kBAAmB,SAAQ,UAAW,YAAW,aAAa;IACzE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAEhC;IACH,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAsC;gBAE1D,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE;IAWxD,wHAAwH;IACxH,OAAO,CAAC,QAAQ,CAAC,WAAW,CAS1B;IAEF,OAAO,CAAC,QAAQ,CAAC,aAAa,CAgC5B;IAEF;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAQhC;IAEF;;;;;OAKG;IACH,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAkBjC;IAEI,KAAK,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,QAAQ,CAAC;IAqD1D,2HAA2H;IAC3H,OAAO,CAAC,YAAY;IAOpB;;;OAGG;IACH,KAAK,IAAI,IAAI;CAad"}
@@ -0,0 +1,161 @@
1
+ import { BaseHelper, getError } from '@venizia/ignis-helpers/core';
2
+ import { RequestIdGenerator } from '@venizia/ignis-helpers/core';
3
+ import { BffEnvelope } from '../envelope/encode.js';
4
+ const DEFAULT_TIMEOUT_MS = 30_000;
5
+ const isErrorEnvelope = (data) => {
6
+ return 'error' in data;
7
+ };
8
+ /**
9
+ * UI-side half of the BFF: posts an encoded request to a real `Worker` and resolves the matching
10
+ * response by `id` - the far side of `WorkerApplication.listen()`.
11
+ *
12
+ * The three worker listeners are attached ONCE, in the constructor, and every request is tracked in
13
+ * `pendingRequests` instead. Registering them per request looks equivalent and is not: they are
14
+ * scoped to the shared `Worker`, so a single `messageerror` - which means exactly one message
15
+ * failed to deserialise - would fire every in-flight request's handler, rejecting nine healthy
16
+ * requests that are about to be answered normally.
17
+ */
18
+ export class WorkerBffTransport extends BaseHelper {
19
+ constructor(opts) {
20
+ super({ scope: WorkerBffTransport.name });
21
+ this.requestIdGenerator = new RequestIdGenerator({
22
+ scope: WorkerBffTransport.name,
23
+ });
24
+ this.pendingRequests = new Map();
25
+ /** Removes a pending request from the map and releases its timer and abort listener, so nothing can settle it twice. */
26
+ this.takePending = (opts) => {
27
+ const pending = this.pendingRequests.get(opts.id);
28
+ if (!pending) {
29
+ return undefined;
30
+ }
31
+ this.pendingRequests.delete(opts.id);
32
+ pending.release();
33
+ return pending;
34
+ };
35
+ this.handleMessage = (event) => {
36
+ // `event.data` is untyped (`any`) until narrowed below - a worker posts to this page for its own
37
+ // reasons too (a dev-server ping, a library handshake), and none of those carry an `id` this
38
+ // transport is waiting on.
39
+ const data = event.data;
40
+ if (!data?.id) {
41
+ return;
42
+ }
43
+ const pending = this.takePending({ id: data.id });
44
+ if (!pending) {
45
+ return;
46
+ }
47
+ if (isErrorEnvelope(data)) {
48
+ pending.reject(BffEnvelope.decodeError({ envelope: data }));
49
+ return;
50
+ }
51
+ // Settled inside its own try: `decodeResponse` throws a `RangeError` for a status outside
52
+ // 200-599 and a `TypeError` on a malformed header tuple, and by this point the timer and the
53
+ // listeners are already gone - a throw that escaped here would leave the promise with nothing
54
+ // left to settle it, ever.
55
+ try {
56
+ pending.resolve(BffEnvelope.decodeResponse({ envelope: data }));
57
+ }
58
+ catch (error) {
59
+ pending.reject(getError({
60
+ message: `[WorkerBffTransport] Failed to decode the response envelope | id: ${data.id} | error: ${error}`,
61
+ }));
62
+ }
63
+ };
64
+ /**
65
+ * A dead or crashed worker never posts anything back, so every in-flight request is lost - this
66
+ * is the one event that legitimately settles all of them, instead of leaving each to time out.
67
+ */
68
+ this.handleWorkerError = (event) => {
69
+ for (const id of [...this.pendingRequests.keys()]) {
70
+ this.takePending({ id })?.reject(getError({
71
+ message: `[WorkerBffTransport] Worker failed while awaiting a response | id: ${id} | event: ${String(event)}`,
72
+ }));
73
+ }
74
+ };
75
+ /**
76
+ * `messageerror` means exactly ONE posted message failed to deserialise, and the event carries
77
+ * nothing that says which. With a single request in flight that is unambiguous, so it settles
78
+ * now; with several, the lost answer belongs to one of them and rejecting the rest would be a
79
+ * lie - each then ends on its own timeout, under its own id.
80
+ */
81
+ this.handleMessageError = (event) => {
82
+ if (this.pendingRequests.size !== 1) {
83
+ this.logger
84
+ .for(this.handleMessageError.name)
85
+ .warn('A worker message could not be deserialised and no single request owns it | inFlight: %d | event: %s', this.pendingRequests.size, String(event));
86
+ return;
87
+ }
88
+ const [id] = [...this.pendingRequests.keys()];
89
+ this.takePending({ id: id })?.reject(getError({
90
+ message: `[WorkerBffTransport] The worker's response could not be deserialised | id: ${id} | event: ${String(event)}`,
91
+ }));
92
+ };
93
+ this.worker = opts.worker;
94
+ this.timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
95
+ this.worker.addEventListener('message', this.handleMessage);
96
+ this.worker.addEventListener('error', this.handleWorkerError);
97
+ this.worker.addEventListener('messageerror', this.handleMessageError);
98
+ }
99
+ async fetch(opts) {
100
+ const { request } = opts;
101
+ const { signal } = request;
102
+ if (signal?.aborted) {
103
+ throw this.toAbortError({ signal });
104
+ }
105
+ const id = this.requestIdGenerator.nextId();
106
+ // The URL is overridden rather than the request rebuilt: rebuilding reads the body once here
107
+ // and once inside `encodeRequest`, and it silently drops `signal` on the way.
108
+ const requestEnvelope = await BffEnvelope.encodeRequest({
109
+ request,
110
+ id,
111
+ url: BffEnvelope.toSyntheticUrl({ url: request.url }),
112
+ });
113
+ return new Promise((resolve, reject) => {
114
+ const timer = setTimeout(() => {
115
+ this.takePending({ id })?.reject(getError({
116
+ message: `[WorkerBffTransport] Timed out waiting for a response | id: ${id} | timeoutMs: ${this.timeoutMs}`,
117
+ }));
118
+ }, this.timeoutMs);
119
+ const handleAbort = () => {
120
+ this.takePending({ id })?.reject(this.toAbortError({ signal }));
121
+ };
122
+ signal?.addEventListener('abort', handleAbort);
123
+ this.pendingRequests.set(id, {
124
+ resolve,
125
+ reject,
126
+ release: () => {
127
+ clearTimeout(timer);
128
+ signal?.removeEventListener('abort', handleAbort);
129
+ },
130
+ });
131
+ // Buffering the body took an await, and `addEventListener('abort')` never fires on a signal
132
+ // that aborted before it was attached - without this re-read that window loses the abort and
133
+ // the caller waits out the whole timeout.
134
+ if (signal?.aborted) {
135
+ handleAbort();
136
+ return;
137
+ }
138
+ this.worker.postMessage(requestEnvelope, requestEnvelope.body ? [requestEnvelope.body] : []);
139
+ });
140
+ }
141
+ /** `signal.reason` first, the way `globalThis.fetch` rejects, so `controller.abort(myReason)` still reaches the caller. */
142
+ toAbortError(opts) {
143
+ return (opts.signal?.reason ??
144
+ getError({ message: '[WorkerBffTransport] The request was aborted by its caller' }));
145
+ }
146
+ /**
147
+ * Detaches the three worker listeners and fails whatever is still in flight. The worker itself is
148
+ * left alone - this transport did not create it, and a page may hand the same one to another.
149
+ */
150
+ close() {
151
+ this.worker.removeEventListener('message', this.handleMessage);
152
+ this.worker.removeEventListener('error', this.handleWorkerError);
153
+ this.worker.removeEventListener('messageerror', this.handleMessageError);
154
+ for (const id of [...this.pendingRequests.keys()]) {
155
+ this.takePending({ id })?.reject(getError({
156
+ message: `[WorkerBffTransport] The transport was closed while awaiting a response | id: ${id}`,
157
+ }));
158
+ }
159
+ }
160
+ }
161
+ //# sourceMappingURL=worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker.js","sourceRoot":"","sources":["../../../src/transport/worker.ts"],"names":[],"mappings":"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"}