@fabricorg/platform 1.10.0 → 1.10.1

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 (209) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/README.md +31 -2
  3. package/dist/actions/index.cjs +45 -26
  4. package/dist/actions/index.cjs.map +1 -1
  5. package/dist/actions/index.d.cts +225 -226
  6. package/dist/actions/index.d.ts +225 -226
  7. package/dist/actions/index.js +41 -2
  8. package/dist/actions/index.js.map +1 -1
  9. package/dist/adapters/index.cjs +696 -66
  10. package/dist/adapters/index.cjs.map +1 -1
  11. package/dist/adapters/index.d.cts +367 -365
  12. package/dist/adapters/index.d.ts +367 -365
  13. package/dist/adapters/index.js +682 -2
  14. package/dist/adapters/index.js.map +1 -1
  15. package/dist/agent-hitl/index.cjs +21 -10
  16. package/dist/agent-hitl/index.cjs.map +1 -1
  17. package/dist/agent-hitl/index.d.cts +30 -30
  18. package/dist/agent-hitl/index.d.ts +30 -30
  19. package/dist/agent-hitl/index.js +21 -2
  20. package/dist/agent-hitl/index.js.map +1 -1
  21. package/dist/certification/index.cjs +109 -24
  22. package/dist/certification/index.cjs.map +1 -1
  23. package/dist/certification/index.d.cts +33 -39
  24. package/dist/certification/index.d.ts +33 -39
  25. package/dist/certification/index.js +107 -8
  26. package/dist/certification/index.js.map +1 -1
  27. package/dist/discovery/index.cjs +12 -10
  28. package/dist/discovery/index.cjs.map +1 -1
  29. package/dist/discovery/index.d.cts +2 -10
  30. package/dist/discovery/index.d.ts +2 -10
  31. package/dist/discovery/index.js +12 -2
  32. package/dist/discovery/index.js.map +1 -1
  33. package/dist/engine-B4csEOEc.js +223 -0
  34. package/dist/engine-B4csEOEc.js.map +1 -0
  35. package/dist/engine-BqScuhrT.cjs +246 -0
  36. package/dist/engine-BqScuhrT.cjs.map +1 -0
  37. package/dist/events/index.cjs +39 -10
  38. package/dist/events/index.cjs.map +1 -1
  39. package/dist/events/index.d.cts +43 -43
  40. package/dist/events/index.d.ts +43 -43
  41. package/dist/events/index.js +39 -2
  42. package/dist/events/index.js.map +1 -1
  43. package/dist/evidence/index.cjs +12 -50
  44. package/dist/evidence/index.d.cts +2 -229
  45. package/dist/evidence/index.d.ts +2 -229
  46. package/dist/evidence/index.js +1 -5
  47. package/dist/evidence-BuCICb0c.js +516 -0
  48. package/dist/evidence-BuCICb0c.js.map +1 -0
  49. package/dist/evidence-Cq48eDvA.cjs +575 -0
  50. package/dist/evidence-Cq48eDvA.cjs.map +1 -0
  51. package/dist/governance/index.cjs +24 -18
  52. package/dist/governance/index.cjs.map +1 -1
  53. package/dist/governance/index.d.cts +80 -83
  54. package/dist/governance/index.d.ts +80 -83
  55. package/dist/governance/index.js +22 -2
  56. package/dist/governance/index.js.map +1 -1
  57. package/dist/ids/index.cjs +52 -22
  58. package/dist/ids/index.cjs.map +1 -1
  59. package/dist/ids/index.d.cts +17 -17
  60. package/dist/ids/index.d.ts +17 -17
  61. package/dist/ids/index.js +49 -2
  62. package/dist/ids/index.js.map +1 -1
  63. package/dist/index-9jasmw76.d.cts +124 -0
  64. package/dist/index-BXpeFdk2.d.cts +190 -0
  65. package/dist/index-BXpeFdk2.d.ts +190 -0
  66. package/dist/index-BnbsKZsT.d.cts +231 -0
  67. package/dist/index-CIl1rYRv.d.cts +11 -0
  68. package/dist/index-CIl1rYRv.d.ts +11 -0
  69. package/dist/index-CVHA1ypT.d.cts +262 -0
  70. package/dist/index-DZ4mnNb7.d.cts +78 -0
  71. package/dist/index-DZ4mnNb7.d.ts +78 -0
  72. package/dist/index-IqcDvl69.d.ts +124 -0
  73. package/dist/index-fmUiRBXu.d.cts +57 -0
  74. package/dist/index-fmUiRBXu.d.ts +57 -0
  75. package/dist/index-sPUPs8pr.d.ts +262 -0
  76. package/dist/index-z9-CYOIo.d.ts +231 -0
  77. package/dist/index.cjs +111 -393
  78. package/dist/index.d.cts +18 -17
  79. package/dist/index.d.ts +18 -17
  80. package/dist/index.js +19 -20
  81. package/dist/manifest/index.cjs +224 -35
  82. package/dist/manifest/index.cjs.map +1 -1
  83. package/dist/manifest/index.d.cts +130 -131
  84. package/dist/manifest/index.d.ts +130 -131
  85. package/dist/manifest/index.js +219 -7
  86. package/dist/manifest/index.js.map +1 -1
  87. package/dist/modules/index.cjs +281 -42
  88. package/dist/modules/index.cjs.map +1 -1
  89. package/dist/modules/index.d.cts +157 -159
  90. package/dist/modules/index.d.ts +157 -159
  91. package/dist/modules/index.js +274 -6
  92. package/dist/modules/index.js.map +1 -1
  93. package/dist/objects/index.cjs +355 -22
  94. package/dist/objects/index.cjs.map +1 -1
  95. package/dist/objects/index.d.cts +2 -77
  96. package/dist/objects/index.d.ts +2 -77
  97. package/dist/objects/index.js +352 -2
  98. package/dist/objects/index.js.map +1 -1
  99. package/dist/policies/index.cjs +14 -56
  100. package/dist/policies/index.d.cts +2 -261
  101. package/dist/policies/index.d.ts +2 -261
  102. package/dist/policies/index.js +1 -3
  103. package/dist/policies-DH_GCXQ-.js +627 -0
  104. package/dist/policies-DH_GCXQ-.js.map +1 -0
  105. package/dist/policies-Nxbp1CH8.cjs +698 -0
  106. package/dist/policies-Nxbp1CH8.cjs.map +1 -0
  107. package/dist/privacy/index.cjs +26 -43
  108. package/dist/privacy/index.cjs.map +1 -1
  109. package/dist/privacy/index.d.cts +2 -189
  110. package/dist/privacy/index.d.ts +2 -189
  111. package/dist/privacy/index.js +18 -3
  112. package/dist/privacy/index.js.map +1 -1
  113. package/dist/projections/index.cjs +241 -23
  114. package/dist/projections/index.cjs.map +1 -1
  115. package/dist/projections/index.d.cts +2 -125
  116. package/dist/projections/index.d.ts +2 -125
  117. package/dist/projections/index.js +238 -3
  118. package/dist/projections/index.js.map +1 -1
  119. package/dist/state-machines/index.cjs +76 -18
  120. package/dist/state-machines/index.cjs.map +1 -1
  121. package/dist/state-machines/index.d.cts +2 -55
  122. package/dist/state-machines/index.d.ts +2 -55
  123. package/dist/state-machines/index.js +74 -2
  124. package/dist/state-machines/index.js.map +1 -1
  125. package/dist/testing/index.cjs +27 -19
  126. package/dist/testing/index.cjs.map +1 -1
  127. package/dist/testing/index.d.cts +17 -19
  128. package/dist/testing/index.d.ts +17 -19
  129. package/dist/testing/index.js +25 -3
  130. package/dist/testing/index.js.map +1 -1
  131. package/package.json +6 -5
  132. package/dist/chunk-2AE6TMAX.cjs +0 -44
  133. package/dist/chunk-2AE6TMAX.cjs.map +0 -1
  134. package/dist/chunk-6HY35TKB.cjs +0 -491
  135. package/dist/chunk-6HY35TKB.cjs.map +0 -1
  136. package/dist/chunk-6UGEIDLC.cjs +0 -26
  137. package/dist/chunk-6UGEIDLC.cjs.map +0 -1
  138. package/dist/chunk-7GAWSUOG.js +0 -64
  139. package/dist/chunk-7GAWSUOG.js.map +0 -1
  140. package/dist/chunk-A42JJIPL.cjs +0 -699
  141. package/dist/chunk-A42JJIPL.cjs.map +0 -1
  142. package/dist/chunk-AFXKSIVI.cjs +0 -540
  143. package/dist/chunk-AFXKSIVI.cjs.map +0 -1
  144. package/dist/chunk-B5DOGDPG.js +0 -42
  145. package/dist/chunk-B5DOGDPG.js.map +0 -1
  146. package/dist/chunk-BJGZE3GE.js +0 -20
  147. package/dist/chunk-BJGZE3GE.js.map +0 -1
  148. package/dist/chunk-CRZXTZ36.cjs +0 -258
  149. package/dist/chunk-CRZXTZ36.cjs.map +0 -1
  150. package/dist/chunk-D4SWRBUH.cjs +0 -22
  151. package/dist/chunk-D4SWRBUH.cjs.map +0 -1
  152. package/dist/chunk-DBTAUI6C.cjs +0 -395
  153. package/dist/chunk-DBTAUI6C.cjs.map +0 -1
  154. package/dist/chunk-EMSAFNPX.js +0 -98
  155. package/dist/chunk-EMSAFNPX.js.map +0 -1
  156. package/dist/chunk-F3E5SXPN.cjs +0 -28
  157. package/dist/chunk-F3E5SXPN.cjs.map +0 -1
  158. package/dist/chunk-HEYMMVDP.js +0 -480
  159. package/dist/chunk-HEYMMVDP.js.map +0 -1
  160. package/dist/chunk-IFW43ELT.cjs +0 -331
  161. package/dist/chunk-IFW43ELT.cjs.map +0 -1
  162. package/dist/chunk-LFE74IJX.js +0 -20
  163. package/dist/chunk-LFE74IJX.js.map +0 -1
  164. package/dist/chunk-LZSE6QGQ.cjs +0 -60
  165. package/dist/chunk-LZSE6QGQ.cjs.map +0 -1
  166. package/dist/chunk-MCWSUGB3.cjs +0 -102
  167. package/dist/chunk-MCWSUGB3.cjs.map +0 -1
  168. package/dist/chunk-MLBALEUR.js +0 -290
  169. package/dist/chunk-MLBALEUR.js.map +0 -1
  170. package/dist/chunk-NNXQZPB3.cjs +0 -31
  171. package/dist/chunk-NNXQZPB3.cjs.map +0 -1
  172. package/dist/chunk-OFCCZ27Z.js +0 -26
  173. package/dist/chunk-OFCCZ27Z.js.map +0 -1
  174. package/dist/chunk-PDN5DOLQ.js +0 -242
  175. package/dist/chunk-PDN5DOLQ.js.map +0 -1
  176. package/dist/chunk-PIDZQAEL.js +0 -50
  177. package/dist/chunk-PIDZQAEL.js.map +0 -1
  178. package/dist/chunk-PXD7NG6X.js +0 -686
  179. package/dist/chunk-PXD7NG6X.js.map +0 -1
  180. package/dist/chunk-Q4Q4JPR3.js +0 -524
  181. package/dist/chunk-Q4Q4JPR3.js.map +0 -1
  182. package/dist/chunk-RALMUSOX.js +0 -55
  183. package/dist/chunk-RALMUSOX.js.map +0 -1
  184. package/dist/chunk-SNTV45LH.cjs +0 -295
  185. package/dist/chunk-SNTV45LH.cjs.map +0 -1
  186. package/dist/chunk-TBS2S5AX.cjs +0 -40
  187. package/dist/chunk-TBS2S5AX.cjs.map +0 -1
  188. package/dist/chunk-TYNIFC7J.js +0 -253
  189. package/dist/chunk-TYNIFC7J.js.map +0 -1
  190. package/dist/chunk-UGWGHTNC.cjs +0 -56
  191. package/dist/chunk-UGWGHTNC.cjs.map +0 -1
  192. package/dist/chunk-WI7CWNYI.cjs +0 -68
  193. package/dist/chunk-WI7CWNYI.cjs.map +0 -1
  194. package/dist/chunk-WNZP53GI.js +0 -386
  195. package/dist/chunk-WNZP53GI.js.map +0 -1
  196. package/dist/chunk-WQ3BYI7T.cjs +0 -249
  197. package/dist/chunk-WQ3BYI7T.cjs.map +0 -1
  198. package/dist/chunk-Y2PJLRIY.js +0 -36
  199. package/dist/chunk-Y2PJLRIY.js.map +0 -1
  200. package/dist/chunk-ZAEVQSB5.js +0 -326
  201. package/dist/chunk-ZAEVQSB5.js.map +0 -1
  202. package/dist/chunk-ZMQTV5OJ.js +0 -27
  203. package/dist/chunk-ZMQTV5OJ.js.map +0 -1
  204. package/dist/evidence/index.cjs.map +0 -1
  205. package/dist/evidence/index.js.map +0 -1
  206. package/dist/index.cjs.map +0 -1
  207. package/dist/index.js.map +0 -1
  208. package/dist/policies/index.cjs.map +0 -1
  209. package/dist/policies/index.js.map +0 -1
@@ -1,540 +0,0 @@
1
- 'use strict';
2
-
3
- // adapters/circuit-breaker.ts
4
- function classifyCircuitBreakerOutcome(kind) {
5
- switch (kind) {
6
- case "success":
7
- return "success";
8
- case "permanent_failure":
9
- return "ignored";
10
- case "transient_failure":
11
- case "timeout":
12
- case "ambiguous":
13
- return "failure";
14
- default:
15
- return "failure";
16
- }
17
- }
18
- var MANUAL_OVERRIDES = ["force_open", "force_closed"];
19
- function assertAdapterCircuitBreakerConfig(config) {
20
- if (!config || typeof config !== "object") {
21
- throw new RangeError("Adapter circuit breaker config must be an object.");
22
- }
23
- if (config.mode !== "monitor" && config.mode !== "enforce") {
24
- throw new RangeError(`Adapter circuit breaker mode must be "monitor" or "enforce"; got ${JSON.stringify(config.mode)}.`);
25
- }
26
- if (!Number.isInteger(config.failureThreshold) || config.failureThreshold < 1) {
27
- throw new RangeError(`Adapter circuit breaker failureThreshold must be a positive integer; got ${String(config.failureThreshold)}.`);
28
- }
29
- if (typeof config.windowMs !== "number" || !Number.isFinite(config.windowMs) || config.windowMs <= 0) {
30
- throw new RangeError(`Adapter circuit breaker windowMs must be a positive number of milliseconds; got ${String(config.windowMs)}.`);
31
- }
32
- if (typeof config.cooldownMs !== "number" || !Number.isFinite(config.cooldownMs) || config.cooldownMs < 0) {
33
- throw new RangeError(`Adapter circuit breaker cooldownMs must be a non-negative number of milliseconds; got ${String(config.cooldownMs)}.`);
34
- }
35
- if (config.minimumSamples !== void 0 && (!Number.isInteger(config.minimumSamples) || config.minimumSamples < 1)) {
36
- throw new RangeError(`Adapter circuit breaker minimumSamples must be a positive integer; got ${String(config.minimumSamples)}.`);
37
- }
38
- if (config.probeLeaseMs !== void 0 && (typeof config.probeLeaseMs !== "number" || !Number.isFinite(config.probeLeaseMs) || config.probeLeaseMs <= 0)) {
39
- throw new RangeError(`Adapter circuit breaker probeLeaseMs must be a positive number of milliseconds; got ${String(config.probeLeaseMs)}.`);
40
- }
41
- if (config.manualOverride !== void 0 && !MANUAL_OVERRIDES.includes(config.manualOverride)) {
42
- throw new RangeError(`Adapter circuit breaker manualOverride must be "force_open" or "force_closed"; got ${JSON.stringify(config.manualOverride)}.`);
43
- }
44
- }
45
- var InMemoryAdapterCircuitBreaker = class {
46
- key;
47
- mode;
48
- config;
49
- now;
50
- onEvent;
51
- probeLeaseMs;
52
- samples = [];
53
- state = "closed";
54
- openedAt = 0;
55
- probeIssuedAt;
56
- /** Advances on every state change, manual override change and probe grant. */
57
- generation = 0;
58
- manualOverride;
59
- /** Telemetry waiting for the current operation to commit. */
60
- outbox = [];
61
- operationDepth = 0;
62
- flushing = false;
63
- constructor(options) {
64
- assertAdapterCircuitBreakerConfig(options.config);
65
- this.key = options.key;
66
- this.config = { ...options.config };
67
- this.mode = options.config.mode;
68
- this.now = options.now ?? Date.now;
69
- this.onEvent = options.onEvent;
70
- this.manualOverride = options.config.manualOverride;
71
- this.probeLeaseMs = options.config.probeLeaseMs ?? Math.max(options.config.cooldownMs, options.config.windowMs);
72
- }
73
- getState() {
74
- this.settle(this.now());
75
- return this.reportedState();
76
- }
77
- getManualOverride() {
78
- return this.manualOverride;
79
- }
80
- /**
81
- * Set (`force_open` / `force_closed`) or clear (`undefined`) the manual
82
- * override. Clearing returns the breaker to `closed` with its window intact.
83
- */
84
- setManualOverride(override) {
85
- if (override !== void 0 && !MANUAL_OVERRIDES.includes(override)) {
86
- throw new RangeError(`Adapter circuit breaker manualOverride must be "force_open" or "force_closed"; got ${JSON.stringify(override)}.`);
87
- }
88
- const now = this.now();
89
- this.settle(now);
90
- if (override === this.manualOverride) return;
91
- this.operation(() => {
92
- const from = this.reportedState();
93
- this.manualOverride = override;
94
- this.generation++;
95
- if (override === void 0) {
96
- this.state = "closed";
97
- this.releaseProbe();
98
- }
99
- this.emit({
100
- type: "state_change",
101
- key: this.key,
102
- mode: this.mode,
103
- at: now,
104
- from,
105
- to: this.reportedState(),
106
- reason: override === void 0 ? "manual_override_cleared" : "manual_override",
107
- ...override ? { manualOverride: override } : {}
108
- });
109
- });
110
- }
111
- check() {
112
- return this.decide(false, this.now());
113
- }
114
- acquire() {
115
- const now = this.now();
116
- this.settle(now);
117
- return this.operation(() => this.decide(true, now));
118
- }
119
- record(outcome, admission) {
120
- const now = this.now();
121
- this.settle(now);
122
- this.operation(() => this.applyOutcome(outcome, admission, now));
123
- }
124
- applyOutcome(outcome, admission, now) {
125
- const generation = admission?.generation;
126
- if (generation !== void 0 && generation !== this.generation) return;
127
- const resolvesProbe = this.state === "half_open" && this.probeIssuedAt !== void 0 && (generation === void 0 || admission?.probe === true);
128
- if (outcome === "ignored") {
129
- if (resolvesProbe) this.releaseProbe();
130
- return;
131
- }
132
- this.prune(now);
133
- this.samples.push({ at: now, failure: outcome === "failure" });
134
- if (this.manualOverride) return;
135
- if (resolvesProbe) {
136
- this.releaseProbe();
137
- if (outcome === "success") {
138
- this.samples = [];
139
- this.transition("closed", "probe_succeeded", now);
140
- } else {
141
- this.openedAt = now;
142
- this.transition("open", "probe_failed", now);
143
- }
144
- return;
145
- }
146
- if (this.state === "closed" && outcome === "failure" && this.shouldTrip()) {
147
- this.openedAt = now;
148
- this.transition("open", "failure_threshold", now);
149
- }
150
- }
151
- /**
152
- * `take` is false for {@link check}: a pure preview that sees an elapsed
153
- * cooldown without committing it, takes no probe and emits nothing.
154
- */
155
- decide(take, now) {
156
- if (this.manualOverride === "force_closed") {
157
- return { allowed: true, state: "closed", probe: false, manualOverride: "force_closed", generation: this.generation };
158
- }
159
- if (this.manualOverride === "force_open") {
160
- return this.refuse(take, { state: "open", manualOverride: "force_open" });
161
- }
162
- const cooldownElapsed = this.state === "open" && now - this.openedAt >= this.config.cooldownMs;
163
- if (take) this.advance(now);
164
- const state = !take && cooldownElapsed ? "half_open" : this.state;
165
- if (state === "closed") return { allowed: true, state: "closed", probe: false, generation: this.generation };
166
- if (state === "open") {
167
- return this.refuse(take, {
168
- state: "open",
169
- retryAfterMs: Math.max(0, this.openedAt + this.config.cooldownMs - now)
170
- });
171
- }
172
- const probeFree = !take && cooldownElapsed || this.probeIssuedAt === void 0 || now - this.probeIssuedAt >= this.probeLeaseMs;
173
- if (!probeFree) return this.refuse(take, { state: "half_open" });
174
- if (!take) return { allowed: true, state: "half_open", probe: true, generation: this.generation };
175
- this.probeIssuedAt = now;
176
- this.generation++;
177
- return { allowed: true, state: "half_open", probe: true, generation: this.generation };
178
- }
179
- refuse(take, detail) {
180
- const enforce = this.mode === "enforce";
181
- if (take) {
182
- this.emit({
183
- type: enforce ? "rejected" : "would_reject",
184
- key: this.key,
185
- mode: this.mode,
186
- at: this.now(),
187
- ...detail
188
- });
189
- }
190
- const generation = this.generation;
191
- return enforce ? { allowed: false, probe: false, ...detail, generation } : { allowed: true, probe: false, wouldReject: true, ...detail, generation };
192
- }
193
- releaseProbe() {
194
- this.probeIssuedAt = void 0;
195
- }
196
- /** Apply the time-based open → half_open transition. */
197
- advance(now) {
198
- if (this.state === "open" && now - this.openedAt >= this.config.cooldownMs) {
199
- this.releaseProbe();
200
- this.transition("half_open", "cooldown_elapsed", now);
201
- }
202
- }
203
- shouldTrip() {
204
- const minimumSamples = this.config.minimumSamples ?? this.config.failureThreshold;
205
- const total = this.samples.length;
206
- if (total < minimumSamples) return false;
207
- let consecutive = 0;
208
- for (let index = total - 1; index >= 0 && this.samples[index].failure; index--) consecutive++;
209
- if (consecutive >= this.config.failureThreshold) return true;
210
- const failures = this.samples.reduce((count, sample) => count + (sample.failure ? 1 : 0), 0);
211
- return failures / total >= this.config.failureThreshold / minimumSamples;
212
- }
213
- prune(now) {
214
- const cutoff = now - this.config.windowMs;
215
- let drop = 0;
216
- while (drop < this.samples.length && this.samples[drop].at < cutoff) drop++;
217
- if (drop > 0) this.samples.splice(0, drop);
218
- }
219
- transition(to, reason, at) {
220
- const from = this.state;
221
- if (from === to) return;
222
- this.state = to;
223
- this.generation++;
224
- this.emit({ type: "state_change", key: this.key, mode: this.mode, at, from, to, reason });
225
- }
226
- reportedState() {
227
- if (this.manualOverride) return this.manualOverride === "force_open" ? "open" : "closed";
228
- return this.state;
229
- }
230
- /**
231
- * Commit an elapsed cooldown as an operation of its own, delivering its
232
- * event before the caller's operation reads state.
233
- */
234
- settle(now) {
235
- if (this.manualOverride) return;
236
- this.operation(() => this.advance(now));
237
- }
238
- /**
239
- * Run `step` to completion, then deliver the telemetry it produced. The
240
- * return value is fixed before any listener runs.
241
- */
242
- operation(step) {
243
- this.operationDepth++;
244
- try {
245
- return step();
246
- } finally {
247
- this.operationDepth--;
248
- if (this.operationDepth === 0) this.flush();
249
- }
250
- }
251
- emit(event) {
252
- if (this.onEvent) this.outbox.push(event);
253
- }
254
- /**
255
- * Deliver buffered events in order. A listener that calls back into the
256
- * breaker queues its own events; this loop delivers them after it returns
257
- * instead of recursing.
258
- */
259
- flush() {
260
- if (this.flushing) return;
261
- this.flushing = true;
262
- try {
263
- for (let event = this.outbox.shift(); event; event = this.outbox.shift()) this.deliver(event);
264
- } finally {
265
- this.flushing = false;
266
- }
267
- }
268
- deliver(event) {
269
- const listener = this.onEvent;
270
- if (!listener) return;
271
- try {
272
- const result = listener(event);
273
- if (result && typeof result.then === "function") {
274
- result.then(void 0, () => void 0);
275
- }
276
- } catch {
277
- }
278
- }
279
- };
280
- function scopedAdapterCircuitBreakerKey(adapter, scope) {
281
- return [
282
- scope === void 0 ? "unscoped" : `tenant=${encodeURIComponent(scope.tenantId)}`,
283
- scope?.spaceId === void 0 ? "space" : `space=${encodeURIComponent(scope.spaceId)}`,
284
- adapter.vendor === void 0 ? "vendor" : `vendor=${encodeURIComponent(adapter.vendor)}`,
285
- encodeURIComponent(adapter.adapterType),
286
- encodeURIComponent(adapter.operation)
287
- ].join(":");
288
- }
289
- var AdapterCircuitBreakerRegistry = class {
290
- constructor(options = {}) {
291
- this.options = options;
292
- }
293
- options;
294
- breakers = /* @__PURE__ */ new Map();
295
- forAdapter(adapter, scope) {
296
- if (!adapter.circuitBreaker) return void 0;
297
- const key = this.options.key?.(adapter, scope) ?? `${adapter.adapterType}:${adapter.operation}`;
298
- let breaker = this.breakers.get(key);
299
- if (!breaker) {
300
- breaker = new InMemoryAdapterCircuitBreaker({
301
- key,
302
- config: adapter.circuitBreaker,
303
- ...this.options.now ? { now: this.options.now } : {},
304
- ...this.options.onEvent ? { onEvent: this.options.onEvent } : {}
305
- });
306
- this.breakers.set(key, breaker);
307
- }
308
- return breaker;
309
- }
310
- /** Looks up the default `adapterType:operation` key without creating a breaker. */
311
- get(adapterType, operation) {
312
- return this.getByKey(`${adapterType}:${operation}`);
313
- }
314
- /** Looks up an exact key, including a custom key, without creating a breaker. */
315
- getByKey(key) {
316
- return this.breakers.get(key);
317
- }
318
- };
319
- var AdapterCircuitOpenError = class extends Error {
320
- name = "AdapterCircuitOpenError";
321
- code = "ADAPTER_CIRCUIT_OPEN";
322
- reason = "circuit_open";
323
- adapterKey;
324
- state;
325
- /** The attempt number that was refused (1 = refused before any call). */
326
- attempt;
327
- retryAfterMs;
328
- manualOverride;
329
- /** Error of the previous attempt, when the breaker opened mid-retry. */
330
- lastError;
331
- constructor(input) {
332
- const after = input.retryAfterMs !== void 0 ? `; retry after ${input.retryAfterMs} ms` : "";
333
- super(`Adapter circuit is ${input.state === "half_open" ? "half-open with its probe in flight" : "open"} for ${input.adapterKey}; the call was not attempted${after}.`);
334
- this.adapterKey = input.adapterKey;
335
- this.state = input.state;
336
- this.attempt = input.attempt;
337
- if (input.retryAfterMs !== void 0) this.retryAfterMs = input.retryAfterMs;
338
- if (input.manualOverride !== void 0) this.manualOverride = input.manualOverride;
339
- if (input.lastError !== void 0) this.lastError = input.lastError;
340
- }
341
- };
342
- function isAdapterCircuitOpenError(error) {
343
- if (error instanceof AdapterCircuitOpenError) return true;
344
- return typeof error === "object" && error !== null && error.name === "AdapterCircuitOpenError" && error.code === "ADAPTER_CIRCUIT_OPEN";
345
- }
346
-
347
- // adapters/index.ts
348
- function adapterKey(adapterType, operation) {
349
- return `${adapterType}:${operation}`;
350
- }
351
- var MissingAdapterRegistrationError = class extends Error {
352
- constructor(adapterType, operation) {
353
- super(`No adapter registered for adapterType "${adapterType}" and operation "${operation}"`);
354
- this.name = "MissingAdapterRegistrationError";
355
- }
356
- };
357
- var AdapterRegistry = class {
358
- adapters = /* @__PURE__ */ new Map();
359
- register(adapter) {
360
- const key = adapterKey(adapter.adapterType, adapter.operation);
361
- if (this.adapters.has(key)) {
362
- throw new Error(
363
- `Adapter already registered for adapterType "${adapter.adapterType}" and operation "${adapter.operation}"`
364
- );
365
- }
366
- this.adapters.set(key, adapter);
367
- }
368
- resolve(adapterType, operation) {
369
- return this.adapters.get(adapterKey(adapterType, operation));
370
- }
371
- require(adapterType, operation) {
372
- const adapter = this.resolve(adapterType, operation);
373
- if (!adapter) {
374
- throw new MissingAdapterRegistrationError(adapterType, operation);
375
- }
376
- return adapter;
377
- }
378
- };
379
- var DEFAULT_RETRY_POLICY = {
380
- maxAttempts: 3,
381
- initialDelayMs: 100,
382
- backoffMultiplier: 2,
383
- maxDelayMs: 1e3
384
- };
385
- var NO_RETRY_POLICY = {
386
- idempotent: false,
387
- maxAttempts: 1,
388
- initialDelayMs: 0,
389
- backoffMultiplier: 1,
390
- maxDelayMs: 0
391
- };
392
- function resolveAdapterRetryPolicy(policy, defaultIdempotent) {
393
- const idempotent = policy?.idempotent ?? defaultIdempotent;
394
- if (!idempotent) {
395
- return NO_RETRY_POLICY;
396
- }
397
- return {
398
- idempotent: true,
399
- maxAttempts: Math.max(1, Math.min(policy?.maxAttempts ?? DEFAULT_RETRY_POLICY.maxAttempts, 5)),
400
- initialDelayMs: Math.max(0, policy?.initialDelayMs ?? DEFAULT_RETRY_POLICY.initialDelayMs),
401
- backoffMultiplier: Math.max(
402
- 1,
403
- policy?.backoffMultiplier ?? DEFAULT_RETRY_POLICY.backoffMultiplier
404
- ),
405
- maxDelayMs: Math.max(0, policy?.maxDelayMs ?? DEFAULT_RETRY_POLICY.maxDelayMs)
406
- };
407
- }
408
- function getRetryDelayMs(attempt, policy) {
409
- const exponentialDelay = policy.initialDelayMs * policy.backoffMultiplier ** Math.max(0, attempt - 1);
410
- return Math.min(exponentialDelay, policy.maxDelayMs);
411
- }
412
- function classifyAdapterOutcome(result) {
413
- if (result.outcome) {
414
- assertAdapterOutcomeConsistency(result);
415
- return result.outcome;
416
- }
417
- return result.success ? "success" : "transient_failure";
418
- }
419
- function shouldRetryAdapterOutcome(kind, idempotent) {
420
- return kind === "transient_failure" && idempotent;
421
- }
422
- function assertAdapterOutcomeConsistency(result) {
423
- if (result.success && result.outcome && result.outcome !== "success") {
424
- throw new Error(
425
- `Adapter returned success=true with contradictory outcome "${result.outcome}"; a successful result must not declare a non-success outcome.`
426
- );
427
- }
428
- }
429
- function recordCircuitOutcome(breaker, outcome, admission) {
430
- if (!breaker) return;
431
- try {
432
- breaker.record(outcome, admission);
433
- } catch {
434
- }
435
- }
436
- function circuitOpenError(breaker, admission, attempt, lastError) {
437
- return new AdapterCircuitOpenError({
438
- adapterKey: breaker.key,
439
- state: admission.state,
440
- attempt,
441
- ...admission.retryAfterMs !== void 0 ? { retryAfterMs: admission.retryAfterMs } : {},
442
- ...admission.manualOverride !== void 0 ? { manualOverride: admission.manualOverride } : {},
443
- ...lastError !== void 0 ? { lastError } : {}
444
- });
445
- }
446
- async function executeWithAdapterRetry(options) {
447
- const policy = resolveAdapterRetryPolicy(options.policy, options.defaultIdempotent);
448
- const sleep = options.sleep ?? ((delayMs) => new Promise((resolve) => setTimeout(resolve, delayMs)));
449
- const breaker = options.circuitBreaker;
450
- let lastError;
451
- for (let attempt = 1; attempt <= policy.maxAttempts; attempt++) {
452
- let admission;
453
- let executed = false;
454
- let recorded = false;
455
- const record = (outcome) => {
456
- if (!executed || recorded) return;
457
- recorded = true;
458
- recordCircuitOutcome(breaker, outcome, admission);
459
- };
460
- let refusal;
461
- async function handleThrown(error) {
462
- lastError = error instanceof Error ? error.message : String(error);
463
- const thrownOutcome = options.classifyThrownError ? options.classifyThrownError(error) : "transient_failure";
464
- record(classifyCircuitBreakerOutcome(thrownOutcome));
465
- let willRetry = shouldRetryAdapterOutcome(thrownOutcome, policy.idempotent) && attempt < policy.maxAttempts;
466
- const blocked = willRetry ? refusedRetry(breaker) : void 0;
467
- if (blocked) willRetry = false;
468
- const nextDelayMs = willRetry ? getRetryDelayMs(attempt, policy) : void 0;
469
- await options.onAttempt?.({ attempt, error: lastError, willRetry, nextDelayMs });
470
- if (blocked) return blocked;
471
- if (!willRetry) return "rethrow";
472
- await sleep(nextDelayMs ?? 0);
473
- return "retry";
474
- }
475
- try {
476
- if (options.prepareAttempt) await options.prepareAttempt(attempt, policy.maxAttempts);
477
- } catch (error) {
478
- const decision = await handleThrown(error);
479
- if (decision === "rethrow") throw error;
480
- if (decision === "retry") continue;
481
- refusal = decision;
482
- }
483
- if (!refusal) {
484
- if (breaker) {
485
- admission = breaker.acquire();
486
- if (!admission.allowed) throw circuitOpenError(breaker, admission, attempt, lastError);
487
- }
488
- try {
489
- executed = true;
490
- const result = await options.execute(attempt, policy.maxAttempts);
491
- if (options.isSuccessful(result)) {
492
- record("success");
493
- await options.onAttempt?.({ attempt, result, willRetry: false });
494
- return result;
495
- }
496
- lastError = options.getError(result) ?? "Adapter returned unsuccessful result";
497
- const outcome = options.classifyOutcome ? options.classifyOutcome(result) : "transient_failure";
498
- record(classifyCircuitBreakerOutcome(outcome));
499
- let willRetry = shouldRetryAdapterOutcome(outcome, policy.idempotent) && attempt < policy.maxAttempts;
500
- refusal = willRetry ? refusedRetry(breaker) : void 0;
501
- if (refusal) willRetry = false;
502
- const nextDelayMs = willRetry ? getRetryDelayMs(attempt, policy) : void 0;
503
- await options.onAttempt?.({ attempt, result, error: lastError, willRetry, nextDelayMs });
504
- if (!willRetry && !refusal) {
505
- return result;
506
- }
507
- if (!refusal) await sleep(nextDelayMs ?? 0);
508
- } catch (error) {
509
- const decision = await handleThrown(error);
510
- if (decision === "rethrow") throw error;
511
- refusal = decision === "retry" ? void 0 : decision;
512
- }
513
- }
514
- if (refusal && breaker) throw circuitOpenError(breaker, refusal, attempt + 1, lastError);
515
- }
516
- throw new Error(lastError ?? "Adapter retry exhausted");
517
- }
518
- function refusedRetry(breaker) {
519
- if (!breaker) return void 0;
520
- const preview = breaker.check();
521
- return preview.allowed ? void 0 : preview;
522
- }
523
-
524
- exports.AdapterCircuitBreakerRegistry = AdapterCircuitBreakerRegistry;
525
- exports.AdapterCircuitOpenError = AdapterCircuitOpenError;
526
- exports.AdapterRegistry = AdapterRegistry;
527
- exports.InMemoryAdapterCircuitBreaker = InMemoryAdapterCircuitBreaker;
528
- exports.MissingAdapterRegistrationError = MissingAdapterRegistrationError;
529
- exports.assertAdapterCircuitBreakerConfig = assertAdapterCircuitBreakerConfig;
530
- exports.assertAdapterOutcomeConsistency = assertAdapterOutcomeConsistency;
531
- exports.classifyAdapterOutcome = classifyAdapterOutcome;
532
- exports.classifyCircuitBreakerOutcome = classifyCircuitBreakerOutcome;
533
- exports.executeWithAdapterRetry = executeWithAdapterRetry;
534
- exports.getRetryDelayMs = getRetryDelayMs;
535
- exports.isAdapterCircuitOpenError = isAdapterCircuitOpenError;
536
- exports.resolveAdapterRetryPolicy = resolveAdapterRetryPolicy;
537
- exports.scopedAdapterCircuitBreakerKey = scopedAdapterCircuitBreakerKey;
538
- exports.shouldRetryAdapterOutcome = shouldRetryAdapterOutcome;
539
- //# sourceMappingURL=chunk-AFXKSIVI.cjs.map
540
- //# sourceMappingURL=chunk-AFXKSIVI.cjs.map