@ddd-ts-kit/aspects 0.0.0-stage → 0.1.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 (346) hide show
  1. package/README.md +381 -2
  2. package/dist/aspect/advice-factory.d.ts +9 -0
  3. package/dist/aspect/advice-factory.d.ts.map +1 -0
  4. package/dist/aspect/advice-factory.js +2 -0
  5. package/dist/aspect/advice-factory.js.map +1 -0
  6. package/dist/aspect/advice.d.ts +3 -0
  7. package/dist/aspect/advice.d.ts.map +1 -0
  8. package/dist/aspect/advice.js +2 -0
  9. package/dist/aspect/advice.js.map +1 -0
  10. package/dist/aspect/aspect-info.d.ts +12 -0
  11. package/dist/aspect/aspect-info.d.ts.map +1 -0
  12. package/dist/aspect/aspect-info.js +2 -0
  13. package/dist/aspect/aspect-info.js.map +1 -0
  14. package/dist/aspect/aspect-kind.d.ts +4 -0
  15. package/dist/aspect/aspect-kind.d.ts.map +1 -0
  16. package/dist/aspect/aspect-kind.js +2 -0
  17. package/dist/aspect/aspect-kind.js.map +1 -0
  18. package/dist/aspect/aspect-origins.d.ts +10 -0
  19. package/dist/aspect/aspect-origins.d.ts.map +1 -0
  20. package/dist/aspect/aspect-origins.js +3 -0
  21. package/dist/aspect/aspect-origins.js.map +1 -0
  22. package/dist/aspect/aspect.d.ts +9 -0
  23. package/dist/aspect/aspect.d.ts.map +1 -0
  24. package/dist/aspect/aspect.js +2 -0
  25. package/dist/aspect/aspect.js.map +1 -0
  26. package/dist/aspect/compose.d.ts +7 -0
  27. package/dist/aspect/compose.d.ts.map +1 -0
  28. package/dist/aspect/compose.js +11 -0
  29. package/dist/aspect/compose.js.map +1 -0
  30. package/dist/aspect/define-aspect.d.ts +5 -0
  31. package/dist/aspect/define-aspect.d.ts.map +1 -0
  32. package/dist/aspect/define-aspect.js +17 -0
  33. package/dist/aspect/define-aspect.js.map +1 -0
  34. package/dist/aspect/invocation.d.ts +6 -0
  35. package/dist/aspect/invocation.d.ts.map +1 -0
  36. package/dist/aspect/invocation.js +2 -0
  37. package/dist/aspect/invocation.js.map +1 -0
  38. package/dist/aspect/join-point.d.ts +13 -0
  39. package/dist/aspect/join-point.d.ts.map +1 -0
  40. package/dist/aspect/join-point.js +2 -0
  41. package/dist/aspect/join-point.js.map +1 -0
  42. package/dist/aspect/selector.d.ts +3 -0
  43. package/dist/aspect/selector.d.ts.map +1 -0
  44. package/dist/aspect/selector.js +2 -0
  45. package/dist/aspect/selector.js.map +1 -0
  46. package/dist/aspect/selectors.d.ts +14 -0
  47. package/dist/aspect/selectors.d.ts.map +1 -0
  48. package/dist/aspect/selectors.js +32 -0
  49. package/dist/aspect/selectors.js.map +1 -0
  50. package/dist/aspect/when.d.ts +8 -0
  51. package/dist/aspect/when.d.ts.map +1 -0
  52. package/dist/aspect/when.js +21 -0
  53. package/dist/aspect/when.js.map +1 -0
  54. package/dist/bulkhead/bulkhead-options.d.ts +10 -0
  55. package/dist/bulkhead/bulkhead-options.d.ts.map +1 -0
  56. package/dist/bulkhead/bulkhead-options.js +2 -0
  57. package/dist/bulkhead/bulkhead-options.js.map +1 -0
  58. package/dist/bulkhead/bulkhead.d.ts +11 -0
  59. package/dist/bulkhead/bulkhead.d.ts.map +1 -0
  60. package/dist/bulkhead/bulkhead.js +22 -0
  61. package/dist/bulkhead/bulkhead.js.map +1 -0
  62. package/dist/bulkhead/compartment.d.ts +13 -0
  63. package/dist/bulkhead/compartment.d.ts.map +1 -0
  64. package/dist/bulkhead/compartment.js +40 -0
  65. package/dist/bulkhead/compartment.js.map +1 -0
  66. package/dist/cached/cached.d.ts +26 -0
  67. package/dist/cached/cached.d.ts.map +1 -0
  68. package/dist/cached/cached.js +64 -0
  69. package/dist/cached/cached.js.map +1 -0
  70. package/dist/circuit-breaker/circuit-breaker-options.d.ts +20 -0
  71. package/dist/circuit-breaker/circuit-breaker-options.d.ts.map +1 -0
  72. package/dist/circuit-breaker/circuit-breaker-options.js +2 -0
  73. package/dist/circuit-breaker/circuit-breaker-options.js.map +1 -0
  74. package/dist/circuit-breaker/circuit-breaker.d.ts +11 -0
  75. package/dist/circuit-breaker/circuit-breaker.d.ts.map +1 -0
  76. package/dist/circuit-breaker/circuit-breaker.js +27 -0
  77. package/dist/circuit-breaker/circuit-breaker.js.map +1 -0
  78. package/dist/circuit-breaker/circuit-state-change.d.ts +10 -0
  79. package/dist/circuit-breaker/circuit-state-change.d.ts.map +1 -0
  80. package/dist/circuit-breaker/circuit-state-change.js +2 -0
  81. package/dist/circuit-breaker/circuit-state-change.js.map +1 -0
  82. package/dist/circuit-breaker/circuit-state-gauge.d.ts +8 -0
  83. package/dist/circuit-breaker/circuit-state-gauge.d.ts.map +1 -0
  84. package/dist/circuit-breaker/circuit-state-gauge.js +14 -0
  85. package/dist/circuit-breaker/circuit-state-gauge.js.map +1 -0
  86. package/dist/circuit-breaker/circuit-state.d.ts +2 -0
  87. package/dist/circuit-breaker/circuit-state.d.ts.map +1 -0
  88. package/dist/circuit-breaker/circuit-state.js +2 -0
  89. package/dist/circuit-breaker/circuit-state.js.map +1 -0
  90. package/dist/circuit-breaker/circuit.d.ts +22 -0
  91. package/dist/circuit-breaker/circuit.d.ts.map +1 -0
  92. package/dist/circuit-breaker/circuit.js +79 -0
  93. package/dist/circuit-breaker/circuit.js.map +1 -0
  94. package/dist/decorators/async-method-decorator.d.ts +13 -0
  95. package/dist/decorators/async-method-decorator.d.ts.map +1 -0
  96. package/dist/decorators/async-method-decorator.js +2 -0
  97. package/dist/decorators/async-method-decorator.js.map +1 -0
  98. package/dist/decorators/bulkhead.d.ts +5 -0
  99. package/dist/decorators/bulkhead.d.ts.map +1 -0
  100. package/dist/decorators/bulkhead.js +7 -0
  101. package/dist/decorators/bulkhead.js.map +1 -0
  102. package/dist/decorators/cached.d.ts +5 -0
  103. package/dist/decorators/cached.d.ts.map +1 -0
  104. package/dist/decorators/cached.js +7 -0
  105. package/dist/decorators/cached.js.map +1 -0
  106. package/dist/decorators/circuit-breaker.d.ts +5 -0
  107. package/dist/decorators/circuit-breaker.d.ts.map +1 -0
  108. package/dist/decorators/circuit-breaker.js +7 -0
  109. package/dist/decorators/circuit-breaker.js.map +1 -0
  110. package/dist/decorators/decorator-of.d.ts +9 -0
  111. package/dist/decorators/decorator-of.d.ts.map +1 -0
  112. package/dist/decorators/decorator-of.js +43 -0
  113. package/dist/decorators/decorator-of.js.map +1 -0
  114. package/dist/decorators/logged.d.ts +5 -0
  115. package/dist/decorators/logged.d.ts.map +1 -0
  116. package/dist/decorators/logged.js +7 -0
  117. package/dist/decorators/logged.js.map +1 -0
  118. package/dist/decorators/retry.d.ts +5 -0
  119. package/dist/decorators/retry.d.ts.map +1 -0
  120. package/dist/decorators/retry.js +7 -0
  121. package/dist/decorators/retry.js.map +1 -0
  122. package/dist/decorators/timed.d.ts +5 -0
  123. package/dist/decorators/timed.d.ts.map +1 -0
  124. package/dist/decorators/timed.js +7 -0
  125. package/dist/decorators/timed.js.map +1 -0
  126. package/dist/decorators/timeout.d.ts +5 -0
  127. package/dist/decorators/timeout.d.ts.map +1 -0
  128. package/dist/decorators/timeout.js +7 -0
  129. package/dist/decorators/timeout.js.map +1 -0
  130. package/dist/decorators.d.ts +10 -0
  131. package/dist/decorators.d.ts.map +1 -0
  132. package/dist/decorators.js +9 -0
  133. package/dist/decorators.js.map +1 -0
  134. package/dist/di/aspects.d.ts +19 -0
  135. package/dist/di/aspects.d.ts.map +1 -0
  136. package/dist/di/aspects.js +22 -0
  137. package/dist/di/aspects.js.map +1 -0
  138. package/dist/errors/aspect-not-allowed-error.d.ts +6 -0
  139. package/dist/errors/aspect-not-allowed-error.d.ts.map +1 -0
  140. package/dist/errors/aspect-not-allowed-error.js +9 -0
  141. package/dist/errors/aspect-not-allowed-error.js.map +1 -0
  142. package/dist/errors/bulkhead-full-error.d.ts +7 -0
  143. package/dist/errors/bulkhead-full-error.d.ts.map +1 -0
  144. package/dist/errors/bulkhead-full-error.js +10 -0
  145. package/dist/errors/bulkhead-full-error.js.map +1 -0
  146. package/dist/errors/circuit-open-error.d.ts +11 -0
  147. package/dist/errors/circuit-open-error.d.ts.map +1 -0
  148. package/dist/errors/circuit-open-error.js +14 -0
  149. package/dist/errors/circuit-open-error.js.map +1 -0
  150. package/dist/errors/is-business-refusal.d.ts +3 -0
  151. package/dist/errors/is-business-refusal.d.ts.map +1 -0
  152. package/dist/errors/is-business-refusal.js +6 -0
  153. package/dist/errors/is-business-refusal.js.map +1 -0
  154. package/dist/errors/timeout-error.d.ts +8 -0
  155. package/dist/errors/timeout-error.d.ts.map +1 -0
  156. package/dist/errors/timeout-error.js +12 -0
  157. package/dist/errors/timeout-error.js.map +1 -0
  158. package/dist/index.d.ts +46 -0
  159. package/dist/index.d.ts.map +1 -0
  160. package/dist/index.js +30 -0
  161. package/dist/index.js.map +1 -0
  162. package/dist/observability/log-call.d.ts +13 -0
  163. package/dist/observability/log-call.d.ts.map +1 -0
  164. package/dist/observability/log-call.js +22 -0
  165. package/dist/observability/log-call.js.map +1 -0
  166. package/dist/observability/logged.d.ts +22 -0
  167. package/dist/observability/logged.d.ts.map +1 -0
  168. package/dist/observability/logged.js +38 -0
  169. package/dist/observability/logged.js.map +1 -0
  170. package/dist/observability/logging-middleware.d.ts +13 -0
  171. package/dist/observability/logging-middleware.d.ts.map +1 -0
  172. package/dist/observability/logging-middleware.js +16 -0
  173. package/dist/observability/logging-middleware.js.map +1 -0
  174. package/dist/observability/metrics-middleware.d.ts +10 -0
  175. package/dist/observability/metrics-middleware.d.ts.map +1 -0
  176. package/dist/observability/metrics-middleware.js +12 -0
  177. package/dist/observability/metrics-middleware.js.map +1 -0
  178. package/dist/observability/observed.d.ts +14 -0
  179. package/dist/observability/observed.d.ts.map +1 -0
  180. package/dist/observability/observed.js +27 -0
  181. package/dist/observability/observed.js.map +1 -0
  182. package/dist/observability/safely.d.ts +3 -0
  183. package/dist/observability/safely.d.ts.map +1 -0
  184. package/dist/observability/safely.js +10 -0
  185. package/dist/observability/safely.js.map +1 -0
  186. package/dist/observability/stdout-logger.d.ts +45 -0
  187. package/dist/observability/stdout-logger.d.ts.map +1 -0
  188. package/dist/observability/stdout-logger.js +85 -0
  189. package/dist/observability/stdout-logger.js.map +1 -0
  190. package/dist/observability/time-call.d.ts +10 -0
  191. package/dist/observability/time-call.d.ts.map +1 -0
  192. package/dist/observability/time-call.js +11 -0
  193. package/dist/observability/time-call.js.map +1 -0
  194. package/dist/observability/timed.d.ts +19 -0
  195. package/dist/observability/timed.d.ts.map +1 -0
  196. package/dist/observability/timed.js +33 -0
  197. package/dist/observability/timed.js.map +1 -0
  198. package/dist/retry/backoff.d.ts +12 -0
  199. package/dist/retry/backoff.d.ts.map +1 -0
  200. package/dist/retry/backoff.js +2 -0
  201. package/dist/retry/backoff.js.map +1 -0
  202. package/dist/retry/delay-before-retry.d.ts +4 -0
  203. package/dist/retry/delay-before-retry.d.ts.map +1 -0
  204. package/dist/retry/delay-before-retry.js +10 -0
  205. package/dist/retry/delay-before-retry.js.map +1 -0
  206. package/dist/retry/full-jitter.d.ts +7 -0
  207. package/dist/retry/full-jitter.d.ts.map +1 -0
  208. package/dist/retry/full-jitter.js +8 -0
  209. package/dist/retry/full-jitter.js.map +1 -0
  210. package/dist/retry/is-transient.d.ts +6 -0
  211. package/dist/retry/is-transient.d.ts.map +1 -0
  212. package/dist/retry/is-transient.js +11 -0
  213. package/dist/retry/is-transient.js.map +1 -0
  214. package/dist/retry/jitter.d.ts +3 -0
  215. package/dist/retry/jitter.d.ts.map +1 -0
  216. package/dist/retry/jitter.js +2 -0
  217. package/dist/retry/jitter.js.map +1 -0
  218. package/dist/retry/no-jitter.d.ts +3 -0
  219. package/dist/retry/no-jitter.d.ts.map +1 -0
  220. package/dist/retry/no-jitter.js +2 -0
  221. package/dist/retry/no-jitter.js.map +1 -0
  222. package/dist/retry/retry.d.ts +20 -0
  223. package/dist/retry/retry.d.ts.map +1 -0
  224. package/dist/retry/retry.js +38 -0
  225. package/dist/retry/retry.js.map +1 -0
  226. package/dist/runtime/aspect-runtime-error.d.ts +6 -0
  227. package/dist/runtime/aspect-runtime-error.d.ts.map +1 -0
  228. package/dist/runtime/aspect-runtime-error.js +9 -0
  229. package/dist/runtime/aspect-runtime-error.js.map +1 -0
  230. package/dist/runtime/aspect-runtime.d.ts +15 -0
  231. package/dist/runtime/aspect-runtime.d.ts.map +1 -0
  232. package/dist/runtime/aspect-runtime.js +2 -0
  233. package/dist/runtime/aspect-runtime.js.map +1 -0
  234. package/dist/runtime/cache-or.d.ts +3 -0
  235. package/dist/runtime/cache-or.d.ts.map +1 -0
  236. package/dist/runtime/cache-or.js +6 -0
  237. package/dist/runtime/cache-or.js.map +1 -0
  238. package/dist/runtime/clock-or.d.ts +3 -0
  239. package/dist/runtime/clock-or.d.ts.map +1 -0
  240. package/dist/runtime/clock-or.js +7 -0
  241. package/dist/runtime/clock-or.js.map +1 -0
  242. package/dist/runtime/installed-runtime.d.ts +8 -0
  243. package/dist/runtime/installed-runtime.d.ts.map +1 -0
  244. package/dist/runtime/installed-runtime.js +16 -0
  245. package/dist/runtime/installed-runtime.js.map +1 -0
  246. package/dist/runtime/logger-or.d.ts +3 -0
  247. package/dist/runtime/logger-or.d.ts.map +1 -0
  248. package/dist/runtime/logger-or.js +6 -0
  249. package/dist/runtime/logger-or.js.map +1 -0
  250. package/dist/runtime/metrics-or.d.ts +3 -0
  251. package/dist/runtime/metrics-or.d.ts.map +1 -0
  252. package/dist/runtime/metrics-or.js +6 -0
  253. package/dist/runtime/metrics-or.js.map +1 -0
  254. package/dist/runtime/missing-collaborator.d.ts +2 -0
  255. package/dist/runtime/missing-collaborator.d.ts.map +1 -0
  256. package/dist/runtime/missing-collaborator.js +5 -0
  257. package/dist/runtime/missing-collaborator.js.map +1 -0
  258. package/dist/runtime/scheduler-or.d.ts +3 -0
  259. package/dist/runtime/scheduler-or.d.ts.map +1 -0
  260. package/dist/runtime/scheduler-or.js +6 -0
  261. package/dist/runtime/scheduler-or.js.map +1 -0
  262. package/dist/runtime/scheduler.d.ts +7 -0
  263. package/dist/runtime/scheduler.d.ts.map +1 -0
  264. package/dist/runtime/scheduler.js +5 -0
  265. package/dist/runtime/scheduler.js.map +1 -0
  266. package/dist/runtime/system-scheduler.d.ts +3 -0
  267. package/dist/runtime/system-scheduler.d.ts.map +1 -0
  268. package/dist/runtime/system-scheduler.js +9 -0
  269. package/dist/runtime/system-scheduler.js.map +1 -0
  270. package/dist/state/state-for.d.ts +5 -0
  271. package/dist/state/state-for.d.ts.map +1 -0
  272. package/dist/state/state-for.js +17 -0
  273. package/dist/state/state-for.js.map +1 -0
  274. package/dist/state/state-scope.d.ts +3 -0
  275. package/dist/state/state-scope.d.ts.map +1 -0
  276. package/dist/state/state-scope.js +2 -0
  277. package/dist/state/state-scope.js.map +1 -0
  278. package/dist/testing/create-aspect-fakes.d.ts +13 -0
  279. package/dist/testing/create-aspect-fakes.d.ts.map +1 -0
  280. package/dist/testing/create-aspect-fakes.js +15 -0
  281. package/dist/testing/create-aspect-fakes.js.map +1 -0
  282. package/dist/testing/manual-scheduler.d.ts +14 -0
  283. package/dist/testing/manual-scheduler.d.ts.map +1 -0
  284. package/dist/testing/manual-scheduler.js +30 -0
  285. package/dist/testing/manual-scheduler.js.map +1 -0
  286. package/dist/testing/with-aspect-runtime.d.ts +8 -0
  287. package/dist/testing/with-aspect-runtime.d.ts.map +1 -0
  288. package/dist/testing/with-aspect-runtime.js +10 -0
  289. package/dist/testing/with-aspect-runtime.js.map +1 -0
  290. package/dist/testing.d.ts +4 -0
  291. package/dist/testing.d.ts.map +1 -0
  292. package/dist/testing.js +4 -0
  293. package/dist/testing.js.map +1 -0
  294. package/dist/timeout/timeout.d.ts +21 -0
  295. package/dist/timeout/timeout.d.ts.map +1 -0
  296. package/dist/timeout/timeout.js +42 -0
  297. package/dist/timeout/timeout.js.map +1 -0
  298. package/dist/weaving/advise-method.d.ts +7 -0
  299. package/dist/weaving/advise-method.d.ts.map +1 -0
  300. package/dist/weaving/advise-method.js +19 -0
  301. package/dist/weaving/advise-method.js.map +1 -0
  302. package/dist/weaving/advise-methods.d.ts +13 -0
  303. package/dist/weaving/advise-methods.d.ts.map +1 -0
  304. package/dist/weaving/advise-methods.js +119 -0
  305. package/dist/weaving/advise-methods.js.map +1 -0
  306. package/dist/weaving/advise-prototype-method.d.ts +8 -0
  307. package/dist/weaving/advise-prototype-method.d.ts.map +1 -0
  308. package/dist/weaving/advise-prototype-method.js +30 -0
  309. package/dist/weaving/advise-prototype-method.js.map +1 -0
  310. package/dist/weaving/advised.d.ts +6 -0
  311. package/dist/weaving/advised.d.ts.map +1 -0
  312. package/dist/weaving/advised.js +19 -0
  313. package/dist/weaving/advised.js.map +1 -0
  314. package/dist/weaving/from-outside.d.ts +10 -0
  315. package/dist/weaving/from-outside.d.ts.map +1 -0
  316. package/dist/weaving/from-outside.js +29 -0
  317. package/dist/weaving/from-outside.js.map +1 -0
  318. package/dist/weaving/is-wrappable.d.ts +3 -0
  319. package/dist/weaving/is-wrappable.d.ts.map +1 -0
  320. package/dist/weaving/is-wrappable.js +7 -0
  321. package/dist/weaving/is-wrappable.js.map +1 -0
  322. package/dist/weaving/known-async.d.ts +4 -0
  323. package/dist/weaving/known-async.d.ts.map +1 -0
  324. package/dist/weaving/known-async.js +3 -0
  325. package/dist/weaving/known-async.js.map +1 -0
  326. package/dist/weaving/lifecycle-hooks.d.ts +3 -0
  327. package/dist/weaving/lifecycle-hooks.d.ts.map +1 -0
  328. package/dist/weaving/lifecycle-hooks.js +9 -0
  329. package/dist/weaving/lifecycle-hooks.js.map +1 -0
  330. package/dist/weaving/method.d.ts +2 -0
  331. package/dist/weaving/method.d.ts.map +1 -0
  332. package/dist/weaving/method.js +2 -0
  333. package/dist/weaving/method.js.map +1 -0
  334. package/dist/weaving/named.d.ts +4 -0
  335. package/dist/weaving/named.d.ts.map +1 -0
  336. package/dist/weaving/named.js +7 -0
  337. package/dist/weaving/named.js.map +1 -0
  338. package/dist/weaving/shadowed.d.ts +4 -0
  339. package/dist/weaving/shadowed.d.ts.map +1 -0
  340. package/dist/weaving/shadowed.js +14 -0
  341. package/dist/weaving/shadowed.js.map +1 -0
  342. package/dist/weaving/site-of.d.ts +5 -0
  343. package/dist/weaving/site-of.d.ts.map +1 -0
  344. package/dist/weaving/site-of.js +15 -0
  345. package/dist/weaving/site-of.js.map +1 -0
  346. package/package.json +40 -4
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selector.js","sourceRoot":"","sources":["../../src/aspect/selector.ts"],"names":[],"mappings":""}
@@ -0,0 +1,14 @@
1
+ import type { AspectKind } from './aspect-kind.js';
2
+ import type { Selector } from './selector.js';
3
+ /** Instances bound with `.as(kind)` to one of the kinds. An instance without kind never matches. */
4
+ export declare function forKinds(...kinds: readonly AspectKind[]): Selector;
5
+ /** Methods by name; `*` stands for any run of characters: `find*`, `*ById`, `get*For*`. */
6
+ export declare function forMethods(...patterns: readonly string[]): Selector;
7
+ /** Instances of one of the bounded contexts. */
8
+ export declare function forContext(...contexts: readonly string[]): Selector;
9
+ /** Instances by class name, with the same `*` as `forMethods`: `Http*`, `*Gateway`. */
10
+ export declare function forClasses(...patterns: readonly string[]): Selector;
11
+ export declare function allOf(...selectors: readonly Selector[]): Selector;
12
+ export declare function anyOf(...selectors: readonly Selector[]): Selector;
13
+ export declare function not(selector: Selector): Selector;
14
+ //# sourceMappingURL=selectors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selectors.d.ts","sourceRoot":"","sources":["../../src/aspect/selectors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,oGAAoG;AACpG,wBAAgB,QAAQ,CAAC,GAAG,KAAK,EAAE,SAAS,UAAU,EAAE,GAAG,QAAQ,CAElE;AAED,2FAA2F;AAC3F,wBAAgB,UAAU,CAAC,GAAG,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,QAAQ,CAInE;AAED,gDAAgD;AAChD,wBAAgB,UAAU,CAAC,GAAG,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,QAAQ,CAEnE;AAED,uFAAuF;AACvF,wBAAgB,UAAU,CAAC,GAAG,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,QAAQ,CAInE;AAED,wBAAgB,KAAK,CAAC,GAAG,SAAS,EAAE,SAAS,QAAQ,EAAE,GAAG,QAAQ,CAEjE;AAED,wBAAgB,KAAK,CAAC,GAAG,SAAS,EAAE,SAAS,QAAQ,EAAE,GAAG,QAAQ,CAEjE;AAED,wBAAgB,GAAG,CAAC,QAAQ,EAAE,QAAQ,GAAG,QAAQ,CAEhD"}
@@ -0,0 +1,32 @@
1
+ /** Instances bound with `.as(kind)` to one of the kinds. An instance without kind never matches. */
2
+ export function forKinds(...kinds) {
3
+ return (joinPoint) => joinPoint.kind !== undefined && kinds.includes(joinPoint.kind);
4
+ }
5
+ /** Methods by name; `*` stands for any run of characters: `find*`, `*ById`, `get*For*`. */
6
+ export function forMethods(...patterns) {
7
+ const expressions = patterns.map(expressionOf);
8
+ return (joinPoint) => expressions.some((expression) => expression.test(joinPoint.method));
9
+ }
10
+ /** Instances of one of the bounded contexts. */
11
+ export function forContext(...contexts) {
12
+ return (joinPoint) => joinPoint.context !== undefined && contexts.includes(joinPoint.context);
13
+ }
14
+ /** Instances by class name, with the same `*` as `forMethods`: `Http*`, `*Gateway`. */
15
+ export function forClasses(...patterns) {
16
+ const expressions = patterns.map(expressionOf);
17
+ return (joinPoint) => expressions.some((expression) => expression.test(joinPoint.className));
18
+ }
19
+ export function allOf(...selectors) {
20
+ return (joinPoint) => selectors.every((selector) => selector(joinPoint));
21
+ }
22
+ export function anyOf(...selectors) {
23
+ return (joinPoint) => selectors.some((selector) => selector(joinPoint));
24
+ }
25
+ export function not(selector) {
26
+ return (joinPoint) => !selector(joinPoint);
27
+ }
28
+ function expressionOf(pattern) {
29
+ const literal = pattern.split('*').map((part) => part.replaceAll(/[.+?^${}()|[\]\\]/g, String.raw `\$&`));
30
+ return new RegExp(`^${literal.join('.*')}$`);
31
+ }
32
+ //# sourceMappingURL=selectors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selectors.js","sourceRoot":"","sources":["../../src/aspect/selectors.ts"],"names":[],"mappings":"AAGA,oGAAoG;AACpG,MAAM,UAAU,QAAQ,CAAC,GAAG,KAA4B;IACtD,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,KAAK,SAAS,IAAI,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;AACvF,CAAC;AAED,2FAA2F;AAC3F,MAAM,UAAU,UAAU,CAAC,GAAG,QAA2B;IACvD,MAAM,WAAW,GAAG,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IAE/C,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;AAC5F,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,UAAU,CAAC,GAAG,QAA2B;IACvD,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,OAAO,KAAK,SAAS,IAAI,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;AAChG,CAAC;AAED,uFAAuF;AACvF,MAAM,UAAU,UAAU,CAAC,GAAG,QAA2B;IACvD,MAAM,WAAW,GAAG,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IAE/C,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC;AAC/F,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,GAAG,SAA8B;IACrD,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;AAC3E,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,GAAG,SAA8B;IACrD,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;AAC1E,CAAC;AAED,MAAM,UAAU,GAAG,CAAC,QAAkB;IACpC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;AAC7C,CAAC;AAED,SAAS,YAAY,CAAC,OAAe;IACnC,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,oBAAoB,EAAE,MAAM,CAAC,GAAG,CAAA,KAAK,CAAC,CAAC,CAAC;IAEzG,OAAO,IAAI,MAAM,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { Aspect } from './aspect.js';
2
+ import type { Selector } from './selector.js';
3
+ /**
4
+ * The aspects, for the methods the selector picks only:
5
+ * `when(allOf(forKinds('external'), forMethods('find*')), cached(...))`.
6
+ */
7
+ export declare function when(selector: Selector, ...aspects: readonly Aspect[]): Aspect;
8
+ //# sourceMappingURL=when.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"when.d.ts","sourceRoot":"","sources":["../../src/aspect/when.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAG1C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C;;;GAGG;AACH,wBAAgB,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,GAAG,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAE9E"}
@@ -0,0 +1,21 @@
1
+ import { aspectOrigins } from './aspect-origins.js';
2
+ import { compose } from './compose.js';
3
+ import { defineAspect } from './define-aspect.js';
4
+ /**
5
+ * The aspects, for the methods the selector picks only:
6
+ * `when(allOf(forKinds('external'), forMethods('find*')), cached(...))`.
7
+ */
8
+ export function when(selector, ...aspects) {
9
+ return compose(...aspects.map((aspect) => selecting(selector, aspect)));
10
+ }
11
+ function selecting(selector, aspect) {
12
+ const origin = aspectOrigins.get(aspect);
13
+ if (origin === undefined) {
14
+ throw new TypeError('when() selects methods of aspects made by defineAspect, compose or when: this function was not, so filter inside it');
15
+ }
16
+ if ('parts' in origin) {
17
+ return when(selector, ...origin.parts);
18
+ }
19
+ return defineAspect((joinPoint) => (selector(joinPoint) ? origin.advise(joinPoint) : undefined));
20
+ }
21
+ //# sourceMappingURL=when.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"when.js","sourceRoot":"","sources":["../../src/aspect/when.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGlD;;;GAGG;AACH,MAAM,UAAU,IAAI,CAAC,QAAkB,EAAE,GAAG,OAA0B;IACpE,OAAO,OAAO,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;AAC1E,CAAC;AAED,SAAS,SAAS,CAAC,QAAkB,EAAE,MAAc;IACnD,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAEzC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,MAAM,IAAI,SAAS,CACjB,qHAAqH,CACtH,CAAC;IACJ,CAAC;IAED,IAAI,OAAO,IAAI,MAAM,EAAE,CAAC;QACtB,OAAO,IAAI,CAAC,QAAQ,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IACzC,CAAC;IAED,OAAO,YAAY,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;AACnG,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { StateScope } from '../state/state-scope.js';
2
+ export interface BulkheadOptions {
3
+ /** Calls running at once. */
4
+ readonly maxConcurrent: number;
5
+ /** Calls waiting for a place, in order. Default 0: beyond `maxConcurrent`, refuse at once. */
6
+ readonly maxQueued?: number;
7
+ /** One compartment per method (the default), or one shared by the methods of the instance. */
8
+ readonly scope?: StateScope;
9
+ }
10
+ //# sourceMappingURL=bulkhead-options.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bulkhead-options.d.ts","sourceRoot":"","sources":["../../src/bulkhead/bulkhead-options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAE1D,MAAM,WAAW,eAAe;IAC9B,6BAA6B;IAC7B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,8FAA8F;IAC9F,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,8FAA8F;IAC9F,QAAQ,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;CAC7B"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=bulkhead-options.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bulkhead-options.js","sourceRoot":"","sources":["../../src/bulkhead/bulkhead-options.ts"],"names":[],"mappings":""}
@@ -0,0 +1,11 @@
1
+ import type { AdviceFactory } from '../aspect/advice-factory.js';
2
+ import type { Aspect } from '../aspect/aspect.js';
3
+ import type { BulkheadOptions } from './bulkhead-options.js';
4
+ /**
5
+ * Bounds how many calls run at once, so that one slow dependency cannot take every resource
6
+ * of the process. A call beyond the bound waits when `maxQueued` allows, otherwise it is
7
+ * refused with a `BulkheadFullError`.
8
+ */
9
+ export declare function bulkhead(options: BulkheadOptions): Aspect;
10
+ export declare function bulkheadAdvice(options: BulkheadOptions): AdviceFactory;
11
+ //# sourceMappingURL=bulkhead.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bulkhead.d.ts","sourceRoot":"","sources":["../../src/bulkhead/bulkhead.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAGlD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAG7D;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,CAEzD;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,eAAe,GAAG,aAAa,CAYtE"}
@@ -0,0 +1,22 @@
1
+ import { defineAspect } from '../aspect/define-aspect.js';
2
+ import { stateFor } from '../state/state-for.js';
3
+ import { Compartment } from './compartment.js';
4
+ /**
5
+ * Bounds how many calls run at once, so that one slow dependency cannot take every resource
6
+ * of the process. A call beyond the bound waits when `maxQueued` allows, otherwise it is
7
+ * refused with a `BulkheadFullError`.
8
+ */
9
+ export function bulkhead(options) {
10
+ return defineAspect(bulkheadAdvice(options));
11
+ }
12
+ export function bulkheadAdvice(options) {
13
+ if (!Number.isSafeInteger(options.maxConcurrent) || options.maxConcurrent < 1) {
14
+ throw new RangeError('bulkhead: maxConcurrent is an integer of at least 1');
15
+ }
16
+ const compartmentOf = stateFor(options.scope, () => new Compartment(options));
17
+ return (joinPoint) => {
18
+ const compartment = compartmentOf(joinPoint);
19
+ return ({ proceed }) => compartment.run(`${joinPoint.className}.${joinPoint.method}`, proceed);
20
+ };
21
+ }
22
+ //# sourceMappingURL=bulkhead.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bulkhead.js","sourceRoot":"","sources":["../../src/bulkhead/bulkhead.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CAAC,OAAwB;IAC/C,OAAO,YAAY,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAAwB;IACrD,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,aAAa,CAAC,IAAI,OAAO,CAAC,aAAa,GAAG,CAAC,EAAE,CAAC;QAC9E,MAAM,IAAI,UAAU,CAAC,qDAAqD,CAAC,CAAC;IAC9E,CAAC;IAED,MAAM,aAAa,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,IAAI,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC;IAE9E,OAAO,CAAC,SAAS,EAAE,EAAE;QACnB,MAAM,WAAW,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC;QAE7C,OAAO,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,SAAS,IAAI,SAAS,CAAC,MAAM,EAAE,EAAE,OAAO,CAAC,CAAC;IACjG,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { BulkheadOptions } from './bulkhead-options.js';
2
+ /** The calls one bulkhead lets run at once, and those that wait for a place. */
3
+ export declare class Compartment {
4
+ private readonly options;
5
+ private readonly waiting;
6
+ private running;
7
+ constructor(options: BulkheadOptions);
8
+ run(operation: string, proceed: () => Promise<unknown>): Promise<unknown>;
9
+ private enter;
10
+ /** A waiting call takes the place as it is: the count of running calls does not move. */
11
+ private leave;
12
+ }
13
+ //# sourceMappingURL=compartment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compartment.d.ts","sourceRoot":"","sources":["../../src/bulkhead/compartment.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D,gFAAgF;AAChF,qBAAa,WAAW;IAKV,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsB;IAE9C,OAAO,CAAC,OAAO,CAAK;IAEpB,YAA6B,OAAO,EAAE,eAAe,EAAI;IAEnD,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAQ9E;YAEa,KAAK;IAcnB,yFAAyF;IACzF,OAAO,CAAC,KAAK;CASd"}
@@ -0,0 +1,40 @@
1
+ import { BulkheadFullError } from '../errors/bulkhead-full-error.js';
2
+ /** The calls one bulkhead lets run at once, and those that wait for a place. */
3
+ export class Compartment {
4
+ options;
5
+ waiting = [];
6
+ running = 0;
7
+ constructor(options) {
8
+ this.options = options;
9
+ }
10
+ async run(operation, proceed) {
11
+ await this.enter(operation);
12
+ try {
13
+ return await proceed();
14
+ }
15
+ finally {
16
+ this.leave();
17
+ }
18
+ }
19
+ async enter(operation) {
20
+ if (this.running < this.options.maxConcurrent) {
21
+ this.running += 1;
22
+ return;
23
+ }
24
+ if (this.waiting.length >= (this.options.maxQueued ?? 0)) {
25
+ throw new BulkheadFullError(operation);
26
+ }
27
+ await new Promise((resolve) => this.waiting.push(resolve));
28
+ }
29
+ /** A waiting call takes the place as it is: the count of running calls does not move. */
30
+ leave() {
31
+ const next = this.waiting.shift();
32
+ if (next === undefined) {
33
+ this.running -= 1;
34
+ }
35
+ else {
36
+ next();
37
+ }
38
+ }
39
+ }
40
+ //# sourceMappingURL=compartment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compartment.js","sourceRoot":"","sources":["../../src/bulkhead/compartment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAGrE,gFAAgF;AAChF,MAAM,OAAO,WAAW;IAKO,OAAO;IAJnB,OAAO,GAAmB,EAAE,CAAC;IAEtC,OAAO,GAAG,CAAC,CAAC;IAEpB,YAA6B,OAAwB;uBAAxB,OAAO;IAAoB,CAAC;IAEzD,KAAK,CAAC,GAAG,CAAC,SAAiB,EAAE,OAA+B;QAC1D,MAAM,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAE5B,IAAI,CAAC;YACH,OAAO,MAAM,OAAO,EAAE,CAAC;QACzB,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,KAAK,CAAC,SAAiB;QACnC,IAAI,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;YAC9C,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC;YAElB,OAAO;QACT,CAAC;QAED,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,IAAI,CAAC,CAAC,EAAE,CAAC;YACzD,MAAM,IAAI,iBAAiB,CAAC,SAAS,CAAC,CAAC;QACzC,CAAC;QAED,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IACnE,CAAC;IAED,yFAAyF;IACjF,KAAK;QACX,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QAElC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC;QACpB,CAAC;aAAM,CAAC;YACN,IAAI,EAAE,CAAC;QACT,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,26 @@
1
+ import { type Cache } from '@ddd-ts-kit/kernel';
2
+ import type { AdviceFactory } from '../aspect/advice-factory.js';
3
+ import type { AspectKind } from '../aspect/aspect-kind.js';
4
+ import type { Aspect } from '../aspect/aspect.js';
5
+ export interface CachedOptions {
6
+ /**
7
+ * The cache key of a call, or `undefined` for a call that is not cached. The only place
8
+ * arguments are read: build the key from identifiers, never from personal data.
9
+ */
10
+ readonly key: (method: string, args: readonly unknown[]) => string | undefined;
11
+ readonly ttlMs: number;
12
+ /** Defaults to the cache of the aspect runtime. */
13
+ readonly cache?: Cache;
14
+ /** Kinds to wrap although they are refused by default: `repository`, `use-case`. */
15
+ readonly allowKinds?: readonly AspectKind[];
16
+ }
17
+ /**
18
+ * Answers a read from the cache when it was made recently. For read methods of gateways and
19
+ * external adapters: select them with `when(forMethods('find*'), cached(...))`. Refuses to
20
+ * wrap a repository or a use case unless `allowKinds` says so: an aggregate served from a
21
+ * cache hides that it is stale. Concurrent identical calls share one underlying call;
22
+ * failures are not cached; a cache that fails is treated as a miss.
23
+ */
24
+ export declare function cached(options: CachedOptions): Aspect;
25
+ export declare function cachedAdvice(options: CachedOptions): AdviceFactory;
26
+ //# sourceMappingURL=cached.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cached.d.ts","sourceRoot":"","sources":["../../src/cached/cached.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,KAAK,EAAiB,MAAM,oBAAoB,CAAC;AACzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAMlD,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,QAAQ,CAAC,GAAG,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,OAAO,EAAE,KAAK,MAAM,GAAG,SAAS,CAAC;IAC/E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,mDAAmD;IACnD,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;IACvB,oFAAoF;IACpF,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;CAC7C;AAQD;;;;;;GAMG;AACH,wBAAgB,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,CAErD;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,aAAa,GAAG,aAAa,CA2BlE"}
@@ -0,0 +1,64 @@
1
+ import { cacheKey } from '@ddd-ts-kit/kernel';
2
+ import { defineAspect } from '../aspect/define-aspect.js';
3
+ import { AspectNotAllowedError } from '../errors/aspect-not-allowed-error.js';
4
+ import { cacheOr } from '../runtime/cache-or.js';
5
+ const REFUSED_KINDS = ['repository', 'use-case'];
6
+ /**
7
+ * Answers a read from the cache when it was made recently. For read methods of gateways and
8
+ * external adapters: select them with `when(forMethods('find*'), cached(...))`. Refuses to
9
+ * wrap a repository or a use case unless `allowKinds` says so: an aggregate served from a
10
+ * cache hides that it is stale. Concurrent identical calls share one underlying call;
11
+ * failures are not cached; a cache that fails is treated as a miss.
12
+ */
13
+ export function cached(options) {
14
+ return defineAspect(cachedAdvice(options));
15
+ }
16
+ export function cachedAdvice(options) {
17
+ return (joinPoint) => {
18
+ assertAllowed(joinPoint, options);
19
+ const inFlight = new Map();
20
+ return async ({ args, proceed }) => {
21
+ const id = options.key(joinPoint.method, args);
22
+ if (id === undefined) {
23
+ return proceed();
24
+ }
25
+ const entry = { cache: cacheOr(options.cache), key: keyOf(joinPoint, id), ttlMs: options.ttlMs };
26
+ const hit = await read(entry);
27
+ if (hit !== undefined) {
28
+ return hit.value;
29
+ }
30
+ const pending = inFlight.get(id) ?? loading(entry, proceed).finally(() => inFlight.delete(id));
31
+ inFlight.set(id, pending);
32
+ return pending;
33
+ };
34
+ };
35
+ }
36
+ function assertAllowed(joinPoint, options) {
37
+ const { kind } = joinPoint;
38
+ if (kind === undefined || !REFUSED_KINDS.includes(kind) || options.allowKinds?.includes(kind) === true) {
39
+ return;
40
+ }
41
+ throw new AspectNotAllowedError(`cached refuses to wrap ${joinPoint.className}.${joinPoint.method}, bound as ${kind}: what it would serve may be stale. Select gateways and external adapters with when(forKinds(...)), or pass allowKinds: ['${kind}'] to take the decision.`);
42
+ }
43
+ function keyOf(joinPoint, id) {
44
+ return cacheKey('aspect', joinPoint.className, joinPoint.method, id);
45
+ }
46
+ async function read({ cache, key }) {
47
+ try {
48
+ return await cache.get(key);
49
+ }
50
+ catch {
51
+ return undefined;
52
+ }
53
+ }
54
+ async function loading({ cache, key, ttlMs }, proceed) {
55
+ const value = await proceed();
56
+ try {
57
+ await cache.set(key, { value }, { ttlMs });
58
+ }
59
+ catch {
60
+ return value;
61
+ }
62
+ return value;
63
+ }
64
+ //# sourceMappingURL=cached.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cached.js","sourceRoot":"","sources":["../../src/cached/cached.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type { Clock } from '@ddd-ts-kit/kernel';
2
+ import type { StateScope } from '../state/state-scope.js';
3
+ import type { CircuitStateChange } from './circuit-state-change.js';
4
+ export interface CircuitBreakerOptions {
5
+ /** Consecutive failures that open the circuit. */
6
+ readonly failureThreshold: number;
7
+ /** Time the circuit stays open before a trial call is let through. */
8
+ readonly resetAfterMs: number;
9
+ /** Trial calls let through at once while half-open. Default 1. */
10
+ readonly halfOpenMax?: number;
11
+ /** Defaults to the clock of the aspect runtime. */
12
+ readonly clock?: Clock;
13
+ /** One circuit per method (the default), or one shared by the methods of the instance. */
14
+ readonly scope?: StateScope;
15
+ /** Default: everything but a business refusal, which proves the dependency answers. */
16
+ readonly isFailure?: (error: unknown) => boolean;
17
+ /** Told every transition: see `circuitStateGauge`. */
18
+ readonly onStateChange?: (change: CircuitStateChange) => void;
19
+ }
20
+ //# sourceMappingURL=circuit-breaker-options.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"circuit-breaker-options.d.ts","sourceRoot":"","sources":["../../src/circuit-breaker/circuit-breaker-options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAEpE,MAAM,WAAW,qBAAqB;IACpC,kDAAkD;IAClD,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,sEAAsE;IACtE,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,kEAAkE;IAClE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,mDAAmD;IACnD,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;IACvB,0FAA0F;IAC1F,QAAQ,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;IAC5B,uFAAuF;IACvF,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC;IACjD,sDAAsD;IACtD,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,kBAAkB,KAAK,IAAI,CAAC;CAC/D"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=circuit-breaker-options.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"circuit-breaker-options.js","sourceRoot":"","sources":["../../src/circuit-breaker/circuit-breaker-options.ts"],"names":[],"mappings":""}
@@ -0,0 +1,11 @@
1
+ import type { AdviceFactory } from '../aspect/advice-factory.js';
2
+ import type { Aspect } from '../aspect/aspect.js';
3
+ import type { CircuitBreakerOptions } from './circuit-breaker-options.js';
4
+ /**
5
+ * Stops calling a dependency that keeps failing: after `failureThreshold` consecutive failures
6
+ * the calls are refused with a `CircuitOpenError` for `resetAfterMs`, then a trial call
7
+ * decides whether the circuit closes again.
8
+ */
9
+ export declare function circuitBreaker(options: CircuitBreakerOptions): Aspect;
10
+ export declare function circuitBreakerAdvice(options: CircuitBreakerOptions): AdviceFactory;
11
+ //# sourceMappingURL=circuit-breaker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"circuit-breaker.d.ts","sourceRoot":"","sources":["../../src/circuit-breaker/circuit-breaker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAKlD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAG1E;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,qBAAqB,GAAG,MAAM,CAErE;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,qBAAqB,GAAG,aAAa,CAQlF"}
@@ -0,0 +1,27 @@
1
+ import { defineAspect } from '../aspect/define-aspect.js';
2
+ import { clockOr } from '../runtime/clock-or.js';
3
+ import { stateFor } from '../state/state-for.js';
4
+ import { Circuit } from './circuit.js';
5
+ /**
6
+ * Stops calling a dependency that keeps failing: after `failureThreshold` consecutive failures
7
+ * the calls are refused with a `CircuitOpenError` for `resetAfterMs`, then a trial call
8
+ * decides whether the circuit closes again.
9
+ */
10
+ export function circuitBreaker(options) {
11
+ return defineAspect(circuitBreakerAdvice(options));
12
+ }
13
+ export function circuitBreakerAdvice(options) {
14
+ const circuitOf = stateFor(options.scope, (joinPoint) => new Circuit(options, subjectOf(joinPoint, options)));
15
+ return (joinPoint) => {
16
+ const circuit = circuitOf(joinPoint);
17
+ return ({ proceed }) => circuit.run(clockOr(options.clock), proceed);
18
+ };
19
+ }
20
+ function subjectOf(joinPoint, options) {
21
+ return {
22
+ className: joinPoint.className,
23
+ ...(options.scope === 'instance' ? {} : { method: joinPoint.method }),
24
+ ...(joinPoint.context === undefined ? {} : { context: joinPoint.context }),
25
+ };
26
+ }
27
+ //# sourceMappingURL=circuit-breaker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"circuit-breaker.js","sourceRoot":"","sources":["../../src/circuit-breaker/circuit-breaker.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE1D,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,OAAO,EAAE,OAAO,EAAuB,MAAM,cAAc,CAAC;AAE5D;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,OAA8B;IAC3D,OAAO,YAAY,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,OAA8B;IACjE,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,SAAS,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IAE9G,OAAO,CAAC,SAAS,EAAE,EAAE;QACnB,MAAM,OAAO,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC;QAErC,OAAO,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,CAAC;IACvE,CAAC,CAAC;AACJ,CAAC;AAED,SAAS,SAAS,CAAC,SAAoB,EAAE,OAA8B;IACrE,OAAO;QACL,SAAS,EAAE,SAAS,CAAC,SAAS;QAC9B,GAAG,CAAC,OAAO,CAAC,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,MAAM,EAAE,CAAC;QACrE,GAAG,CAAC,SAAS,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,SAAS,CAAC,OAAO,EAAE,CAAC;KAC3E,CAAC;AACJ,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { CircuitState } from './circuit-state.js';
2
+ export interface CircuitStateChange {
3
+ readonly className: string;
4
+ /** Absent when the circuit is shared by the methods of the instance. */
5
+ readonly method?: string;
6
+ readonly context?: string;
7
+ readonly from: CircuitState;
8
+ readonly to: CircuitState;
9
+ }
10
+ //# sourceMappingURL=circuit-state-change.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"circuit-state-change.d.ts","sourceRoot":"","sources":["../../src/circuit-breaker/circuit-state-change.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,wEAAwE;IACxE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,EAAE,EAAE,YAAY,CAAC;CAC3B"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=circuit-state-change.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"circuit-state-change.js","sourceRoot":"","sources":["../../src/circuit-breaker/circuit-state-change.ts"],"names":[],"mappings":""}
@@ -0,0 +1,8 @@
1
+ import type { Metrics } from '@ddd-ts-kit/kernel';
2
+ import type { CircuitStateChange } from './circuit-state-change.js';
3
+ /**
4
+ * An `onStateChange` that publishes the state as a gauge: 0 closed, 1 half-open, 2 open,
5
+ * labelled `class`, `method` and `context`. The metrics default to those of the aspect runtime.
6
+ */
7
+ export declare function circuitStateGauge(metrics?: Metrics, name?: string): (change: CircuitStateChange) => void;
8
+ //# sourceMappingURL=circuit-state-gauge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"circuit-state-gauge.d.ts","sourceRoot":"","sources":["../../src/circuit-breaker/circuit-state-gauge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAElD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAKpE;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,CAAC,EAAE,OAAO,EACjB,IAAI,SAA0B,GAC7B,CAAC,MAAM,EAAE,kBAAkB,KAAK,IAAI,CAMtC"}
@@ -0,0 +1,14 @@
1
+ import { metricsOr } from '../runtime/metrics-or.js';
2
+ const STATE_VALUES = { closed: 0, 'half-open': 1, open: 2 };
3
+ /**
4
+ * An `onStateChange` that publishes the state as a gauge: 0 closed, 1 half-open, 2 open,
5
+ * labelled `class`, `method` and `context`. The metrics default to those of the aspect runtime.
6
+ */
7
+ export function circuitStateGauge(metrics, name = 'circuit_breaker_state') {
8
+ return (change) => {
9
+ metricsOr(metrics)
10
+ .gauge(name)
11
+ .set(STATE_VALUES[change.to], { class: change.className, method: change.method, context: change.context });
12
+ };
13
+ }
14
+ //# sourceMappingURL=circuit-state-gauge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"circuit-state-gauge.js","sourceRoot":"","sources":["../../src/circuit-breaker/circuit-state-gauge.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAIrD,MAAM,YAAY,GAA2C,EAAE,MAAM,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;AAEpG;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAC/B,OAAiB,EACjB,IAAI,GAAG,uBAAuB;IAE9B,OAAO,CAAC,MAAM,EAAE,EAAE;QAChB,SAAS,CAAC,OAAO,CAAC;aACf,KAAK,CAAC,IAAI,CAAC;aACX,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;IAC/G,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export type CircuitState = 'closed' | 'open' | 'half-open';
2
+ //# sourceMappingURL=circuit-state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"circuit-state.d.ts","sourceRoot":"","sources":["../../src/circuit-breaker/circuit-state.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=circuit-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"circuit-state.js","sourceRoot":"","sources":["../../src/circuit-breaker/circuit-state.ts"],"names":[],"mappings":""}
@@ -0,0 +1,22 @@
1
+ import type { Clock } from '@ddd-ts-kit/kernel';
2
+ import type { CircuitBreakerOptions } from './circuit-breaker-options.js';
3
+ import type { CircuitStateChange } from './circuit-state-change.js';
4
+ /** What a circuit protects, as its transitions name it. */
5
+ export type CircuitSubject = Omit<CircuitStateChange, 'from' | 'to'>;
6
+ /** The state of one circuit: counts the consecutive failures, refuses while open, lets trial calls through after. */
7
+ export declare class Circuit {
8
+ private readonly options;
9
+ private readonly subject;
10
+ private state;
11
+ private failures;
12
+ private openedAt;
13
+ private trials;
14
+ constructor(options: CircuitBreakerOptions, subject: CircuitSubject);
15
+ run(clock: Clock, proceed: () => Promise<unknown>): Promise<unknown>;
16
+ private admit;
17
+ private become;
18
+ private operation;
19
+ private answered;
20
+ private failed;
21
+ }
22
+ //# sourceMappingURL=circuit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"circuit.d.ts","sourceRoot":"","sources":["../../src/circuit-breaker/circuit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAIhD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAC1E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAGpE,2DAA2D;AAC3D,MAAM,MAAM,cAAc,GAAG,IAAI,CAAC,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;AAErE,qHAAqH;AACrH,qBAAa,OAAO;IAUhB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAV1B,OAAO,CAAC,KAAK,CAA0B;IAEvC,OAAO,CAAC,QAAQ,CAAK;IAErB,OAAO,CAAC,QAAQ,CAAK;IAErB,OAAO,CAAC,MAAM,CAAK;IAEnB,YACmB,OAAO,EAAE,qBAAqB,EAC9B,OAAO,EAAE,cAAc,EACtC;IAEE,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAkBzE;IAED,OAAO,CAAC,KAAK;IAkBb,OAAO,CAAC,MAAM;IAad,OAAO,CAAC,SAAS;IAMjB,OAAO,CAAC,QAAQ;IAQhB,OAAO,CAAC,MAAM;CAYf"}
@@ -0,0 +1,79 @@
1
+ import { CircuitOpenError } from '../errors/circuit-open-error.js';
2
+ import { isBusinessRefusal } from '../errors/is-business-refusal.js';
3
+ import { safely } from '../observability/safely.js';
4
+ /** The state of one circuit: counts the consecutive failures, refuses while open, lets trial calls through after. */
5
+ export class Circuit {
6
+ options;
7
+ subject;
8
+ state = 'closed';
9
+ failures = 0;
10
+ openedAt = 0;
11
+ trials = 0;
12
+ constructor(options, subject) {
13
+ this.options = options;
14
+ this.subject = subject;
15
+ }
16
+ async run(clock, proceed) {
17
+ this.admit(clock);
18
+ try {
19
+ const result = await proceed();
20
+ this.answered();
21
+ return result;
22
+ }
23
+ catch (error) {
24
+ if ((this.options.isFailure ?? isFault)(error)) {
25
+ this.failed(clock);
26
+ }
27
+ else {
28
+ this.answered();
29
+ }
30
+ throw error;
31
+ }
32
+ }
33
+ admit(clock) {
34
+ if (this.state === 'closed') {
35
+ return;
36
+ }
37
+ const retryAt = this.openedAt + this.options.resetAfterMs;
38
+ if (this.state === 'open' && clock.now().getTime() >= retryAt) {
39
+ this.become('half-open');
40
+ }
41
+ if (this.state === 'open' || this.trials >= (this.options.halfOpenMax ?? 1)) {
42
+ throw new CircuitOpenError(this.operation(), new Date(retryAt));
43
+ }
44
+ this.trials += 1;
45
+ }
46
+ become(state) {
47
+ const change = { ...this.subject, from: this.state, to: state };
48
+ this.state = state;
49
+ this.trials = 0;
50
+ if (state === 'closed') {
51
+ this.failures = 0;
52
+ }
53
+ safely(() => this.options.onStateChange?.(change));
54
+ }
55
+ operation() {
56
+ const { className, method } = this.subject;
57
+ return method === undefined ? className : `${className}.${method}`;
58
+ }
59
+ answered() {
60
+ this.failures = 0;
61
+ if (this.state === 'half-open') {
62
+ this.become('closed');
63
+ }
64
+ }
65
+ failed(clock) {
66
+ if (this.state === 'open') {
67
+ return;
68
+ }
69
+ this.failures += 1;
70
+ if (this.state === 'half-open' || this.failures >= this.options.failureThreshold) {
71
+ this.openedAt = clock.now().getTime();
72
+ this.become('open');
73
+ }
74
+ }
75
+ }
76
+ function isFault(error) {
77
+ return !isBusinessRefusal(error);
78
+ }
79
+ //# sourceMappingURL=circuit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"circuit.js","sourceRoot":"","sources":["../../src/circuit-breaker/circuit.ts"],"names":[],"mappings":"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"}