@venizia/ignis-worker 0.2.0-2 → 0.2.0-21

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 (103) hide show
  1. package/dist/cjs/envelope/common/index.d.ts +2 -0
  2. package/dist/cjs/envelope/common/index.d.ts.map +1 -0
  3. package/dist/cjs/envelope/common/index.js +18 -0
  4. package/dist/cjs/envelope/common/index.js.map +1 -0
  5. package/dist/cjs/envelope/common/types.d.ts.map +1 -0
  6. package/dist/{esm/envelope → cjs/envelope/common}/types.js.map +1 -1
  7. package/dist/cjs/envelope/encode.d.ts +1 -1
  8. package/dist/cjs/envelope/encode.d.ts.map +1 -1
  9. package/dist/cjs/envelope/index.d.ts +1 -1
  10. package/dist/cjs/envelope/index.d.ts.map +1 -1
  11. package/dist/cjs/envelope/index.js +1 -1
  12. package/dist/cjs/envelope/index.js.map +1 -1
  13. package/dist/cjs/transport/fetch-bridge.d.ts +35 -0
  14. package/dist/cjs/transport/fetch-bridge.d.ts.map +1 -0
  15. package/dist/cjs/transport/fetch-bridge.js +95 -0
  16. package/dist/cjs/transport/fetch-bridge.js.map +1 -0
  17. package/dist/cjs/transport/in-process.d.ts +2 -1
  18. package/dist/cjs/transport/in-process.d.ts.map +1 -1
  19. package/dist/cjs/transport/in-process.js +3 -1
  20. package/dist/cjs/transport/in-process.js.map +1 -1
  21. package/dist/cjs/transport/index.d.ts +2 -0
  22. package/dist/cjs/transport/index.d.ts.map +1 -1
  23. package/dist/cjs/transport/index.js +2 -0
  24. package/dist/cjs/transport/index.js.map +1 -1
  25. package/dist/cjs/transport/shared/common/constants.d.ts +14 -0
  26. package/dist/cjs/transport/shared/common/constants.d.ts.map +1 -0
  27. package/dist/cjs/transport/shared/common/constants.js +19 -0
  28. package/dist/cjs/transport/shared/common/constants.js.map +1 -0
  29. package/dist/cjs/transport/shared/common/index.d.ts +3 -0
  30. package/dist/cjs/transport/shared/common/index.d.ts.map +1 -0
  31. package/dist/cjs/transport/shared/common/index.js +19 -0
  32. package/dist/cjs/transport/shared/common/index.js.map +1 -0
  33. package/dist/cjs/transport/shared/common/types.d.ts +35 -0
  34. package/dist/cjs/transport/shared/common/types.d.ts.map +1 -0
  35. package/dist/cjs/transport/shared/common/types.js +3 -0
  36. package/dist/cjs/transport/shared/common/types.js.map +1 -0
  37. package/dist/cjs/transport/shared/index.d.ts +4 -0
  38. package/dist/cjs/transport/shared/index.d.ts.map +1 -0
  39. package/dist/cjs/transport/shared/index.js +11 -0
  40. package/dist/cjs/transport/shared/index.js.map +1 -0
  41. package/dist/cjs/transport/shared/transport.d.ts +87 -0
  42. package/dist/cjs/transport/shared/transport.d.ts.map +1 -0
  43. package/dist/cjs/transport/shared/transport.js +383 -0
  44. package/dist/cjs/transport/shared/transport.js.map +1 -0
  45. package/dist/cjs/transport/worker.d.ts +16 -2
  46. package/dist/cjs/transport/worker.d.ts.map +1 -1
  47. package/dist/cjs/transport/worker.js +65 -7
  48. package/dist/cjs/transport/worker.js.map +1 -1
  49. package/dist/esm/envelope/common/index.d.ts +2 -0
  50. package/dist/esm/envelope/common/index.d.ts.map +1 -0
  51. package/dist/esm/envelope/common/index.js +2 -0
  52. package/dist/esm/envelope/common/index.js.map +1 -0
  53. package/dist/esm/envelope/common/types.d.ts.map +1 -0
  54. package/dist/{cjs/envelope → esm/envelope/common}/types.js.map +1 -1
  55. package/dist/esm/envelope/encode.d.ts +1 -1
  56. package/dist/esm/envelope/encode.d.ts.map +1 -1
  57. package/dist/esm/envelope/index.d.ts +1 -1
  58. package/dist/esm/envelope/index.d.ts.map +1 -1
  59. package/dist/esm/envelope/index.js +1 -1
  60. package/dist/esm/envelope/index.js.map +1 -1
  61. package/dist/esm/transport/fetch-bridge.d.ts +35 -0
  62. package/dist/esm/transport/fetch-bridge.d.ts.map +1 -0
  63. package/dist/esm/transport/fetch-bridge.js +91 -0
  64. package/dist/esm/transport/fetch-bridge.js.map +1 -0
  65. package/dist/esm/transport/in-process.d.ts +2 -1
  66. package/dist/esm/transport/in-process.d.ts.map +1 -1
  67. package/dist/esm/transport/in-process.js +4 -2
  68. package/dist/esm/transport/in-process.js.map +1 -1
  69. package/dist/esm/transport/index.d.ts +2 -0
  70. package/dist/esm/transport/index.d.ts.map +1 -1
  71. package/dist/esm/transport/index.js +2 -0
  72. package/dist/esm/transport/index.js.map +1 -1
  73. package/dist/esm/transport/shared/common/constants.d.ts +14 -0
  74. package/dist/esm/transport/shared/common/constants.d.ts.map +1 -0
  75. package/dist/esm/transport/shared/common/constants.js +14 -0
  76. package/dist/esm/transport/shared/common/constants.js.map +1 -0
  77. package/dist/esm/transport/shared/common/index.d.ts +3 -0
  78. package/dist/esm/transport/shared/common/index.d.ts.map +1 -0
  79. package/dist/esm/transport/shared/common/index.js +3 -0
  80. package/dist/esm/transport/shared/common/index.js.map +1 -0
  81. package/dist/esm/transport/shared/common/types.d.ts +35 -0
  82. package/dist/esm/transport/shared/common/types.d.ts.map +1 -0
  83. package/dist/esm/transport/shared/common/types.js +2 -0
  84. package/dist/esm/transport/shared/common/types.js.map +1 -0
  85. package/dist/esm/transport/shared/index.d.ts +4 -0
  86. package/dist/esm/transport/shared/index.d.ts.map +1 -0
  87. package/dist/esm/transport/shared/index.js +6 -0
  88. package/dist/esm/transport/shared/index.js.map +1 -0
  89. package/dist/esm/transport/shared/transport.d.ts +87 -0
  90. package/dist/esm/transport/shared/transport.d.ts.map +1 -0
  91. package/dist/esm/transport/shared/transport.js +379 -0
  92. package/dist/esm/transport/shared/transport.js.map +1 -0
  93. package/dist/esm/transport/worker.d.ts +16 -2
  94. package/dist/esm/transport/worker.d.ts.map +1 -1
  95. package/dist/esm/transport/worker.js +65 -7
  96. package/dist/esm/transport/worker.js.map +1 -1
  97. package/package.json +9 -9
  98. package/dist/cjs/envelope/types.d.ts.map +0 -1
  99. package/dist/esm/envelope/types.d.ts.map +0 -1
  100. /package/dist/cjs/envelope/{types.d.ts → common/types.d.ts} +0 -0
  101. /package/dist/cjs/envelope/{types.js → common/types.js} +0 -0
  102. /package/dist/esm/envelope/{types.d.ts → common/types.d.ts} +0 -0
  103. /package/dist/esm/envelope/{types.js → common/types.js} +0 -0
@@ -0,0 +1,2 @@
1
+ export * from './types';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/envelope/common/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC"}
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./types"), exports);
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/envelope/common/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,0CAAwB"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/envelope/common/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"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/envelope/types.ts"],"names":[],"mappings":""}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/envelope/common/types.ts"],"names":[],"mappings":""}
@@ -1,5 +1,5 @@
1
1
  import type { ApplicationError } from '@venizia/ignis-helpers/core';
2
- import type { IBffErrorEnvelope, IBffRequestEnvelope, IBffResponseEnvelope } from './types';
2
+ import type { IBffErrorEnvelope, IBffRequestEnvelope, IBffResponseEnvelope } from './common';
3
3
  /**
4
4
  * Every request built inside the Worker uses this origin. Never `self.location.href`: a `blob:`
5
5
  * worker origin is opaque and `new URL(path, blobUrl)` throws, and Hono's `getPath()` mis-parses
@@ -1 +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"}
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,UAAU,CAAC;AAE7F;;;;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"}
@@ -1,3 +1,3 @@
1
+ export * from './common';
1
2
  export * from './encode';
2
- export * from './types';
3
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/envelope/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/envelope/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC"}
@@ -14,6 +14,6 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./common"), exports);
17
18
  __exportStar(require("./encode"), exports);
18
- __exportStar(require("./types"), exports);
19
19
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/envelope/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAyB;AACzB,0CAAwB"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/envelope/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAyB;AACzB,2CAAyB"}
@@ -0,0 +1,35 @@
1
+ import type { IBffTransport } from './common/types';
2
+ type TFetch = typeof globalThis.fetch;
3
+ /** The carrier whose `fetch` is replaced - `globalThis` in a page, an object a test controls otherwise. */
4
+ interface IFetchCarrier {
5
+ fetch: TFetch;
6
+ }
7
+ export interface IInstallBffFetchOptions {
8
+ /** Anything implementing the transport contract, so an in-process transport works in a test. */
9
+ transport: IBffTransport;
10
+ /**
11
+ * Path prefixes the BFF owns, matched against the request's PATHNAME. Everything else is passed
12
+ * to the original `fetch` untouched.
13
+ */
14
+ basePath: string | Array<string>;
15
+ /** Defaults to `globalThis`. */
16
+ carrier?: IFetchCarrier;
17
+ }
18
+ /**
19
+ * Routes the page's own `fetch` into a BFF transport for anything under `basePath`, and leaves every
20
+ * other call on the network untouched.
21
+ *
22
+ * This is the seam that lets an existing HTTP client talk to an in-browser IGNIS application without
23
+ * knowing one exists. A data provider, an SDK or a generated client reaches the network through the
24
+ * global `fetch` and usually accepts no custom fetcher, so answering that `fetch` is the only place
25
+ * an in-browser backend becomes a drop-in swap rather than a fork of the client.
26
+ *
27
+ * Install it BEFORE the application that will use it boots: a request issued while the original
28
+ * `fetch` is still in place leaves the page and 404s against whatever is serving it.
29
+ *
30
+ * @returns The uninstall function. It restores the previous `fetch` only if this bridge is still the
31
+ * installed one - if something patched `fetch` afterwards, restoring would silently discard that.
32
+ */
33
+ export declare const installBffFetch: (opts: IInstallBffFetchOptions) => (() => void);
34
+ export {};
35
+ //# sourceMappingURL=fetch-bridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch-bridge.d.ts","sourceRoot":"","sources":["../../../src/transport/fetch-bridge.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAQpD,KAAK,MAAM,GAAG,OAAO,UAAU,CAAC,KAAK,CAAC;AAEtC,2GAA2G;AAC3G,UAAU,aAAa;IACrB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,uBAAuB;IACtC,gGAAgG;IAChG,SAAS,EAAE,aAAa,CAAC;IACzB;;;OAGG;IACH,QAAQ,EAAE,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;IACjC,gCAAgC;IAChC,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AA+CD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,eAAe,GAAI,MAAM,uBAAuB,KAAG,CAAC,MAAM,IAAI,CA2C1E,CAAC"}
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.installBffFetch = void 0;
4
+ const core_1 = require("@venizia/ignis-helpers/core");
5
+ /**
6
+ * Marks the patched `fetch` so a second install is refused rather than silently stacking. `Symbol.for`
7
+ * and not a private symbol: two copies of this package in one page must still see each other's mark.
8
+ */
9
+ const BRIDGE_MARKER = Symbol.for('@venizia/ignis-worker/bff-fetch');
10
+ /**
11
+ * Resolves a request's absolute URL WITHOUT constructing a `Request`.
12
+ *
13
+ * This is the whole reason this helper exists rather than one obvious line. `new Request(input)`,
14
+ * where `input` is a `Request` carrying a body, marks that body disturbed - so building one just to
15
+ * read `.url` breaks the very pass-through it is deciding about: the next line hands the same, now
16
+ * unreadable, request to the network.
17
+ *
18
+ * Measured, because the runtimes disagree. Chromium:
19
+ *
20
+ * original.bodyUsed // false
21
+ * new Request(original)
22
+ * original.bodyUsed // true
23
+ * await original.text() // TypeError: body stream already read
24
+ *
25
+ * Bun does NOT disturb it, so the unit tests pass either way and cannot guard this. The browser is
26
+ * where this code runs, so the browser is the behaviour to write for.
27
+ */
28
+ const resolveRequestUrl = (input) => {
29
+ if (typeof input === 'string') {
30
+ return new URL(input, globalThis.location?.href).href;
31
+ }
32
+ if (input instanceof URL) {
33
+ return input.href;
34
+ }
35
+ return input.url;
36
+ };
37
+ const toPrefixList = (basePath) => {
38
+ const prefixes = (Array.isArray(basePath) ? basePath : [basePath]).filter(prefix => prefix.length > 0);
39
+ if (prefixes.length === 0) {
40
+ throw (0, core_1.getError)({
41
+ message: '[installBffFetch] Invalid basePath | At least one non-empty path prefix is required',
42
+ });
43
+ }
44
+ return prefixes;
45
+ };
46
+ /**
47
+ * Routes the page's own `fetch` into a BFF transport for anything under `basePath`, and leaves every
48
+ * other call on the network untouched.
49
+ *
50
+ * This is the seam that lets an existing HTTP client talk to an in-browser IGNIS application without
51
+ * knowing one exists. A data provider, an SDK or a generated client reaches the network through the
52
+ * global `fetch` and usually accepts no custom fetcher, so answering that `fetch` is the only place
53
+ * an in-browser backend becomes a drop-in swap rather than a fork of the client.
54
+ *
55
+ * Install it BEFORE the application that will use it boots: a request issued while the original
56
+ * `fetch` is still in place leaves the page and 404s against whatever is serving it.
57
+ *
58
+ * @returns The uninstall function. It restores the previous `fetch` only if this bridge is still the
59
+ * installed one - if something patched `fetch` afterwards, restoring would silently discard that.
60
+ */
61
+ const installBffFetch = (opts) => {
62
+ const { transport, basePath } = opts;
63
+ const carrier = opts.carrier ?? globalThis;
64
+ const prefixes = toPrefixList(basePath);
65
+ const previousFetch = carrier.fetch;
66
+ if (Object.getOwnPropertyDescriptor(previousFetch, BRIDGE_MARKER)) {
67
+ throw (0, core_1.getError)({
68
+ message: '[installBffFetch] A BFF fetch bridge is already installed | Uninstall it first, or pass every prefix to a single install',
69
+ });
70
+ }
71
+ const networkFetch = previousFetch.bind(carrier);
72
+ const bridged = async (input, init) => {
73
+ const { pathname } = new URL(resolveRequestUrl(input));
74
+ if (!prefixes.some(prefix => pathname.startsWith(prefix))) {
75
+ return networkFetch(input, init);
76
+ }
77
+ // Constructed only now, on the branch that owns the request - so the pass-through above never
78
+ // disturbs a body it is about to hand to the network.
79
+ return transport.fetch({ request: new Request(input, init) });
80
+ };
81
+ // Whatever the runtime hung on `fetch` comes along - Bun puts `preconnect` there, and a
82
+ // replacement that dropped it would break any caller reaching for it. Copying the descriptors is
83
+ // also what makes this satisfy `typeof fetch` rather than merely resembling it.
84
+ Object.defineProperties(bridged, Object.getOwnPropertyDescriptors(previousFetch));
85
+ Object.defineProperty(bridged, BRIDGE_MARKER, { value: true });
86
+ carrier.fetch = bridged;
87
+ return () => {
88
+ if (carrier.fetch !== bridged) {
89
+ return;
90
+ }
91
+ carrier.fetch = previousFetch;
92
+ };
93
+ };
94
+ exports.installBffFetch = installBffFetch;
95
+ //# sourceMappingURL=fetch-bridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch-bridge.js","sourceRoot":"","sources":["../../../src/transport/fetch-bridge.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { BaseHelper } from '@venizia/ignis-helpers/core';
1
2
  import type { IBffTransport } from './common/types';
2
3
  /**
3
4
  * No worker, no browser - the seam that makes a BFF testable in-process. It still runs the full
@@ -9,7 +10,7 @@ import type { IBffTransport } from './common/types';
9
10
  * What it deliberately does NOT mirror is the timeout: in-process there is no message that can be
10
11
  * lost, so a handler either settles or the caller's own test timeout fires.
11
12
  */
12
- export declare class InProcessBffTransport implements IBffTransport {
13
+ export declare class InProcessBffTransport extends BaseHelper implements IBffTransport {
13
14
  private readonly handler;
14
15
  private readonly requestIdGenerator;
15
16
  constructor(opts: {
@@ -1 +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"}
1
+ {"version":3,"file":"in-process.d.ts","sourceRoot":"","sources":["../../../src/transport/in-process.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAsB,MAAM,6BAA6B,CAAC;AAG7E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEpD;;;;;;;;;GASG;AACH,qBAAa,qBAAsB,SAAQ,UAAW,YAAW,aAAa;IAC5E,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;IAMhE,KAAK,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,QAAQ,CAAC;CAyB3D"}
@@ -13,8 +13,9 @@ const encode_1 = require("../envelope/encode");
13
13
  * What it deliberately does NOT mirror is the timeout: in-process there is no message that can be
14
14
  * lost, so a handler either settles or the caller's own test timeout fires.
15
15
  */
16
- class InProcessBffTransport {
16
+ class InProcessBffTransport extends core_1.BaseHelper {
17
17
  constructor(opts) {
18
+ super({ scope: InProcessBffTransport.name });
18
19
  this.requestIdGenerator = new core_1.RequestIdGenerator({
19
20
  scope: InProcessBffTransport.name,
20
21
  });
@@ -33,6 +34,7 @@ class InProcessBffTransport {
33
34
  responseEnvelope = await encode_1.BffEnvelope.encodeResponse({ response, id });
34
35
  }
35
36
  catch (error) {
37
+ this.logger.for(this.fetch.name).error('Handler failed | id: %s | error: %s', id, error);
36
38
  // Encoded and decoded rather than rethrown: what a UI receives over a real Worker is a
37
39
  // rebuilt `ApplicationError` carrying only the normalised shape - never the original object,
38
40
  // its stack or its `extra`.
@@ -1 +1 @@
1
- {"version":3,"file":"in-process.js","sourceRoot":"","sources":["../../../src/transport/in-process.ts"],"names":[],"mappings":";;;AAAA,sDAAiE;AACjE,8CAAgD;AAIhD;;;;;;;;;GASG;AACH,MAAa,qBAAqB;IAMhC,YAAY,IAA0D;QAJrD,uBAAkB,GAAG,IAAI,yBAAkB,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,oBAAW,CAAC,aAAa,CAAC;YACtD,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,EAAE;YACF,GAAG,EAAE,oBAAW,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,oBAAW,CAAC,aAAa,CAAC,EAAE,QAAQ,EAAE,eAAe,EAAE,CAAC,CAAC,CAAC;YAC9F,gBAAgB,GAAG,MAAM,oBAAW,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,oBAAW,CAAC,WAAW,CAAC,EAAE,QAAQ,EAAE,oBAAW,CAAC,WAAW,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;QACtF,CAAC;QAED,OAAO,oBAAW,CAAC,cAAc,CAAC,EAAE,QAAQ,EAAE,gBAAgB,EAAE,CAAC,CAAC;IACpE,CAAC;CACF;AAjCD,sDAiCC"}
1
+ {"version":3,"file":"in-process.js","sourceRoot":"","sources":["../../../src/transport/in-process.ts"],"names":[],"mappings":";;;AAAA,sDAA6E;AAC7E,8CAAgD;AAIhD;;;;;;;;;GASG;AACH,MAAa,qBAAsB,SAAQ,iBAAU;IAMnD,YAAY,IAA0D;QACpE,KAAK,CAAC,EAAE,KAAK,EAAE,qBAAqB,CAAC,IAAI,EAAE,CAAC,CAAC;QAL9B,uBAAkB,GAAG,IAAI,yBAAkB,CAAC;YAC3D,KAAK,EAAE,qBAAqB,CAAC,IAAI;SAClC,CAAC,CAAC;QAKD,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,oBAAW,CAAC,aAAa,CAAC;YACtD,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,EAAE;YACF,GAAG,EAAE,oBAAW,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,oBAAW,CAAC,aAAa,CAAC,EAAE,QAAQ,EAAE,eAAe,EAAE,CAAC,CAAC,CAAC;YAC9F,gBAAgB,GAAG,MAAM,oBAAW,CAAC,cAAc,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC;QACxE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,qCAAqC,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;YAEzF,uFAAuF;YACvF,6FAA6F;YAC7F,4BAA4B;YAC5B,MAAM,oBAAW,CAAC,WAAW,CAAC,EAAE,QAAQ,EAAE,oBAAW,CAAC,WAAW,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;QACtF,CAAC;QAED,OAAO,oBAAW,CAAC,cAAc,CAAC,EAAE,QAAQ,EAAE,gBAAgB,EAAE,CAAC,CAAC;IACpE,CAAC;CACF;AArCD,sDAqCC"}
@@ -1,4 +1,6 @@
1
1
  export * from './common';
2
+ export * from './fetch-bridge';
2
3
  export * from './in-process';
4
+ export * from './shared';
3
5
  export * from './worker';
4
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/transport/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC"}
@@ -15,6 +15,8 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./common"), exports);
18
+ __exportStar(require("./fetch-bridge"), exports);
18
19
  __exportStar(require("./in-process"), exports);
20
+ __exportStar(require("./shared"), exports);
19
21
  __exportStar(require("./worker"), exports);
20
22
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/transport/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAyB;AACzB,+CAA6B;AAC7B,2CAAyB"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/transport/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAyB;AACzB,iDAA+B;AAC/B,+CAA6B;AAC7B,2CAAyB;AACzB,2CAAyB"}
@@ -0,0 +1,14 @@
1
+ export declare const DEFAULT_CHANNEL_NAME = "ignis.bff";
2
+ export declare const DEFAULT_TIMEOUT_MS = 30000;
3
+ /** Which part this tab plays. `ELECTING` is the brief window before the lock answers. */
4
+ export declare class BffRoles {
5
+ static readonly ELECTING = "electing";
6
+ static readonly LEADER = "leader";
7
+ static readonly FOLLOWER = "follower";
8
+ }
9
+ export declare class ChannelMessageKinds {
10
+ static readonly REQUEST = "ignis.bff.request";
11
+ static readonly RESPONSE = "ignis.bff.response";
12
+ static readonly ERROR = "ignis.bff.error";
13
+ }
14
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../../../src/transport/shared/common/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,oBAAoB,cAAc,CAAC;AAChD,eAAO,MAAM,kBAAkB,QAAS,CAAC;AAEzC,yFAAyF;AACzF,qBAAa,QAAQ;IACnB,MAAM,CAAC,QAAQ,CAAC,QAAQ,cAAc;IACtC,MAAM,CAAC,QAAQ,CAAC,MAAM,YAAY;IAClC,MAAM,CAAC,QAAQ,CAAC,QAAQ,cAAc;CACvC;AAED,qBAAa,mBAAmB;IAC9B,MAAM,CAAC,QAAQ,CAAC,OAAO,uBAAuB;IAC9C,MAAM,CAAC,QAAQ,CAAC,QAAQ,wBAAwB;IAChD,MAAM,CAAC,QAAQ,CAAC,KAAK,qBAAqB;CAC3C"}
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ChannelMessageKinds = exports.BffRoles = exports.DEFAULT_TIMEOUT_MS = exports.DEFAULT_CHANNEL_NAME = void 0;
4
+ exports.DEFAULT_CHANNEL_NAME = 'ignis.bff';
5
+ exports.DEFAULT_TIMEOUT_MS = 30_000;
6
+ /** Which part this tab plays. `ELECTING` is the brief window before the lock answers. */
7
+ class BffRoles {
8
+ static { this.ELECTING = 'electing'; }
9
+ static { this.LEADER = 'leader'; }
10
+ static { this.FOLLOWER = 'follower'; }
11
+ }
12
+ exports.BffRoles = BffRoles;
13
+ class ChannelMessageKinds {
14
+ static { this.REQUEST = 'ignis.bff.request'; }
15
+ static { this.RESPONSE = 'ignis.bff.response'; }
16
+ static { this.ERROR = 'ignis.bff.error'; }
17
+ }
18
+ exports.ChannelMessageKinds = ChannelMessageKinds;
19
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../../../src/transport/shared/common/constants.ts"],"names":[],"mappings":";;;AAAa,QAAA,oBAAoB,GAAG,WAAW,CAAC;AACnC,QAAA,kBAAkB,GAAG,MAAM,CAAC;AAEzC,yFAAyF;AACzF,MAAa,QAAQ;aACH,aAAQ,GAAG,UAAU,CAAC;aACtB,WAAM,GAAG,QAAQ,CAAC;aAClB,aAAQ,GAAG,UAAU,CAAC;;AAHxC,4BAIC;AAED,MAAa,mBAAmB;aACd,YAAO,GAAG,mBAAmB,CAAC;aAC9B,aAAQ,GAAG,oBAAoB,CAAC;aAChC,UAAK,GAAG,iBAAiB,CAAC;;AAH5C,kDAIC"}
@@ -0,0 +1,3 @@
1
+ export * from './constants';
2
+ export * from './types';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/transport/shared/common/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC"}
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./constants"), exports);
18
+ __exportStar(require("./types"), exports);
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/transport/shared/common/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8CAA4B;AAC5B,0CAAwB"}
@@ -0,0 +1,35 @@
1
+ import type { TConstValue } from '@venizia/ignis-helpers/common';
2
+ import type { IBffErrorEnvelope, IBffRequestEnvelope, IBffResponseEnvelope } from '../../../envelope/common';
3
+ import { BffRoles, ChannelMessageKinds } from './constants';
4
+ export type TBffRole = TConstValue<typeof BffRoles>;
5
+ /**
6
+ * There is deliberately no "a new leader is ready" broadcast. A follower cannot act on one safely:
7
+ * BroadcastChannel does not order messages across senders, so a request posted around the moment of
8
+ * promotion may well be answered by the new leader - and a follower that failed its in-flight
9
+ * requests on hearing the announcement would turn some of those successes into errors. The request
10
+ * timeout is the one honest answer for that window.
11
+ */
12
+ export type TChannelMessage = {
13
+ kind: typeof ChannelMessageKinds.REQUEST;
14
+ envelope: IBffRequestEnvelope;
15
+ } | {
16
+ kind: typeof ChannelMessageKinds.RESPONSE;
17
+ envelope: IBffResponseEnvelope;
18
+ } | {
19
+ kind: typeof ChannelMessageKinds.ERROR;
20
+ envelope: IBffErrorEnvelope;
21
+ };
22
+ export interface IPendingRequest {
23
+ resolve: (response: Response) => void;
24
+ reject: (error: unknown) => void;
25
+ release: () => void;
26
+ }
27
+ export interface ISharedBffTransportOptions {
28
+ /** Builds the Worker. Called ONLY by whichever tab wins the election - the others never start one. */
29
+ createWorker: () => Worker;
30
+ /** Distinguishes independent BFFs on one origin. The lock name is derived from it. */
31
+ channelName?: string;
32
+ timeoutMs?: number;
33
+ scope?: string;
34
+ }
35
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../src/transport/shared/common/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,KAAK,EACV,iBAAiB,EACjB,mBAAmB,EACnB,oBAAoB,EACrB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAE5D,MAAM,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,QAAQ,CAAC,CAAC;AAEpD;;;;;;GAMG;AACH,MAAM,MAAM,eAAe,GACvB;IAAE,IAAI,EAAE,OAAO,mBAAmB,CAAC,OAAO,CAAC;IAAC,QAAQ,EAAE,mBAAmB,CAAA;CAAE,GAC3E;IAAE,IAAI,EAAE,OAAO,mBAAmB,CAAC,QAAQ,CAAC;IAAC,QAAQ,EAAE,oBAAoB,CAAA;CAAE,GAC7E;IAAE,IAAI,EAAE,OAAO,mBAAmB,CAAC,KAAK,CAAC;IAAC,QAAQ,EAAE,iBAAiB,CAAA;CAAE,CAAC;AAE5E,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,IAAI,CAAC;IACtC,MAAM,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACjC,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,MAAM,WAAW,0BAA0B;IACzC,sGAAsG;IACtG,YAAY,EAAE,MAAM,MAAM,CAAC;IAC3B,sFAAsF;IACtF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../../src/transport/shared/common/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,4 @@
1
+ export { BffRoles } from './common/constants';
2
+ export type { ISharedBffTransportOptions, TBffRole } from './common/types';
3
+ export { SharedBffTransport } from './transport';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/transport/shared/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,YAAY,EAAE,0BAA0B,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SharedBffTransport = exports.BffRoles = void 0;
4
+ // `export * from './common'` would also publish five module-private names - `DEFAULT_CHANNEL_NAME`,
5
+ // `DEFAULT_TIMEOUT_MS`, `ChannelMessageKinds`, `TChannelMessage`, `IPendingRequest` - through
6
+ // `transport/index.ts`.
7
+ var constants_1 = require("./common/constants");
8
+ Object.defineProperty(exports, "BffRoles", { enumerable: true, get: function () { return constants_1.BffRoles; } });
9
+ var transport_1 = require("./transport");
10
+ Object.defineProperty(exports, "SharedBffTransport", { enumerable: true, get: function () { return transport_1.SharedBffTransport; } });
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/transport/shared/index.ts"],"names":[],"mappings":";;;AAAA,oGAAoG;AACpG,8FAA8F;AAC9F,wBAAwB;AACxB,gDAA8C;AAArC,qGAAA,QAAQ,OAAA;AAEjB,yCAAiD;AAAxC,+GAAA,kBAAkB,OAAA"}
@@ -0,0 +1,87 @@
1
+ import { BaseHelper } from '@venizia/ignis-helpers/core';
2
+ import type { IBffTransport } from '../common/types';
3
+ import type { ISharedBffTransportOptions, TBffRole } from './common';
4
+ /**
5
+ * One BFF for every tab of an origin, instead of one per tab.
6
+ *
7
+ * The problem it solves is not a framework limitation, it is a storage one. PGlite in
8
+ * `opfs-ahp://` mode holds an exclusive access handle on the database file, and OPFS access handles
9
+ * are exclusive PER ORIGIN. Measured in Chromium with two tabs of the same page: the first tab
10
+ * works, and the second never boots its database -
11
+ * `Failed to execute 'createSyncAccessHandle' on 'FileSystemFileHandle': Access Handles cannot be
12
+ * created if there is another open Access Handle or Writable stream associated with the same file`.
13
+ * The first tab is unaffected, and closing it lets the second recover on reload - so the failure is
14
+ * contained and self-healing, but the second tab is simply dead until then.
15
+ *
16
+ * So exactly one tab may own the database. This transport elects that tab with the Web Locks API,
17
+ * gives it the Worker, and forwards every other tab's request to it over a `BroadcastChannel`,
18
+ * carried in the same envelope the Worker itself speaks. When the leader's tab closes, the lock is
19
+ * released by the browser and a follower is promoted automatically - no heartbeat, no timeout, no
20
+ * stale-leader window to reason about.
21
+ *
22
+ * A host with no `navigator.locks` runs single-tab, exactly as before. That is not a compromise:
23
+ * measured on a plain-http origin, `navigator.locks` and `navigator.storage.getDirectory` are BOTH
24
+ * undefined, because both are secure-context only. Wherever OPFS works the lock exists, and where it
25
+ * does not the database could not have started either.
26
+ */
27
+ export declare class SharedBffTransport extends BaseHelper implements IBffTransport {
28
+ private readonly createWorker;
29
+ private readonly channel;
30
+ private readonly lockName;
31
+ private readonly timeoutMs;
32
+ private readonly requestIdGenerator;
33
+ private readonly pendingRequests;
34
+ private role;
35
+ private leaderTransport?;
36
+ private isClosed;
37
+ /**
38
+ * Held because THIS class created it. `WorkerBffTransport.close()` deliberately leaves a worker
39
+ * running - it did not create the one it was handed - so without this reference the worker would
40
+ * outlive `close()` still holding the exclusive OPFS access handle, while the lock has already
41
+ * gone to another tab that opens the same database.
42
+ */
43
+ private leaderWorker?;
44
+ /** Set when `createWorker()` throws, so callers get that failure instead of parking forever. */
45
+ private leaderStartupError?;
46
+ /** Resolving this releases the Web Lock, which is what promotes a follower. */
47
+ private releaseLeadership?;
48
+ /** Drops this tab out of the lock QUEUE on close, so a closed transport cannot be promoted. */
49
+ private readonly leadershipQueueAbort;
50
+ /** Callers parked in `fetch()` while the election is still running. */
51
+ private roleWaiters;
52
+ constructor(opts: ISharedBffTransportOptions);
53
+ getRole(): TBffRole;
54
+ fetch(opts: {
55
+ request: Request;
56
+ }): Promise<Response>;
57
+ close(): void;
58
+ private elect;
59
+ private becomeLeader;
60
+ private becomeFollower;
61
+ private heldUntilClosed;
62
+ private whenRoleSettled;
63
+ private settleRoleWaiters;
64
+ /**
65
+ * The caller's `AbortSignal` is honoured HERE as well as in `WorkerBffTransport`. Without it the
66
+ * same page code behaves differently depending on which tab won the lock: abort works in the
67
+ * leader and silently does nothing in every follower, so a data provider that aborts on unmount
68
+ * leaves promises pending for the full timeout in every tab but one.
69
+ *
70
+ * Aborting settles the CALLER. It does not cancel the leader's work - there is no cancel message,
71
+ * and a write already dispatched cannot be taken back.
72
+ */
73
+ private fetchViaLeader;
74
+ /** `signal.reason` first, the way `globalThis.fetch` rejects, so a custom abort reason survives. */
75
+ private toAbortError;
76
+ private takePending;
77
+ private rejectAllPending;
78
+ /**
79
+ * A `BroadcastChannel` never delivers a message to the instance that sent it, so a leader does not
80
+ * hear its own answers and a follower does not hear its own requests. Every tab does hear every
81
+ * OTHER tab, which is why a response is matched by id and silently ignored when it belongs to
82
+ * someone else.
83
+ */
84
+ private readonly handleChannelMessage;
85
+ private serveAsLeader;
86
+ }
87
+ //# sourceMappingURL=transport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../../../src/transport/shared/transport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAgC,MAAM,6BAA6B,CAAC;AAGvF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGrD,OAAO,KAAK,EAEV,0BAA0B,EAC1B,QAAQ,EAET,MAAM,UAAU,CAAC;AAElB;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAAa,kBAAmB,SAAQ,UAAW,YAAW,aAAa;IACzE,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAe;IAC5C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAmB;IAC3C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAqB;IACxD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAsC;IAEtE,OAAO,CAAC,IAAI,CAA+B;IAC3C,OAAO,CAAC,eAAe,CAAC,CAAqB;IAC7C,OAAO,CAAC,QAAQ,CAAS;IAEzB;;;;;OAKG;IACH,OAAO,CAAC,YAAY,CAAC,CAAS;IAE9B,gGAAgG;IAChG,OAAO,CAAC,kBAAkB,CAAC,CAAU;IAErC,+EAA+E;IAC/E,OAAO,CAAC,iBAAiB,CAAC,CAAa;IAEvC,+FAA+F;IAC/F,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAyB;IAE9D,uEAAuE;IACvE,OAAO,CAAC,WAAW,CAAyB;gBAEhC,IAAI,EAAE,0BAA0B;IAkC5C,OAAO,IAAI,QAAQ;IAIb,KAAK,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,QAAQ,CAAC;IAkC1D,KAAK,IAAI,IAAI;YA+BC,KAAK;IA4DnB,OAAO,CAAC,YAAY;IA6BpB,OAAO,CAAC,cAAc;IAKtB,OAAO,CAAC,eAAe;IAMvB,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,iBAAiB;IASzB;;;;;;;;OAQG;YACW,cAAc;IAoD5B,oGAAoG;IACpG,OAAO,CAAC,YAAY;IAOpB,OAAO,CAAC,WAAW;IAWnB,OAAO,CAAC,gBAAgB;IAUxB;;;;;OAKG;IACH,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CA4EnC;YAEY,aAAa;CAyB5B"}