@adonis-agora/payments 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (346) hide show
  1. package/CHANGELOG.md +2375 -0
  2. package/dist/assets/spa/assets/index-B7rU8eIL.css +2 -0
  3. package/dist/assets/spa/assets/index-BcM2VH5k.js +10 -0
  4. package/dist/assets/spa/assets/index-BcM2VH5k.js.map +1 -0
  5. package/dist/assets/spa/index.html +20 -0
  6. package/dist/commands/main.d.ts +4 -3
  7. package/dist/commands/main.d.ts.map +1 -1
  8. package/dist/commands/main.js +9 -2
  9. package/dist/commands/main.js.map +1 -1
  10. package/dist/commands/make_billable.d.ts.map +1 -1
  11. package/dist/commands/make_billable.js +1 -1
  12. package/dist/commands/make_billable.js.map +1 -1
  13. package/dist/commands/make_webhook_handler.d.ts.map +1 -1
  14. package/dist/commands/make_webhook_handler.js +1 -1
  15. package/dist/commands/make_webhook_handler.js.map +1 -1
  16. package/dist/commands/payments_health.d.ts +31 -0
  17. package/dist/commands/payments_health.d.ts.map +1 -0
  18. package/dist/commands/payments_health.js +113 -0
  19. package/dist/commands/payments_health.js.map +1 -0
  20. package/dist/commands/payments_sync.d.ts +18 -4
  21. package/dist/commands/payments_sync.d.ts.map +1 -1
  22. package/dist/commands/payments_sync.js +136 -40
  23. package/dist/commands/payments_sync.js.map +1 -1
  24. package/dist/commands/payments_webhook.d.ts.map +1 -1
  25. package/dist/commands/payments_webhook.js.map +1 -1
  26. package/dist/configure.d.ts +12 -5
  27. package/dist/configure.d.ts.map +1 -1
  28. package/dist/configure.js +18 -5
  29. package/dist/configure.js.map +1 -1
  30. package/dist/providers/dashboard_provider.d.ts +97 -0
  31. package/dist/providers/dashboard_provider.d.ts.map +1 -0
  32. package/dist/providers/dashboard_provider.js +430 -0
  33. package/dist/providers/dashboard_provider.js.map +1 -0
  34. package/dist/providers/payments_client_provider.d.ts +41 -0
  35. package/dist/providers/payments_client_provider.d.ts.map +1 -0
  36. package/dist/providers/payments_client_provider.js +95 -0
  37. package/dist/providers/payments_client_provider.js.map +1 -0
  38. package/dist/providers/payments_provider.d.ts +35 -0
  39. package/dist/providers/payments_provider.d.ts.map +1 -1
  40. package/dist/providers/payments_provider.js +250 -36
  41. package/dist/providers/payments_provider.js.map +1 -1
  42. package/dist/src/billing/billing_health.d.ts +85 -0
  43. package/dist/src/billing/billing_health.d.ts.map +1 -0
  44. package/dist/src/billing/billing_health.js +155 -0
  45. package/dist/src/billing/billing_health.js.map +1 -0
  46. package/dist/src/billing/billing_overview.d.ts +4 -3
  47. package/dist/src/billing/billing_overview.d.ts.map +1 -1
  48. package/dist/src/billing/billing_overview.js +14 -5
  49. package/dist/src/billing/billing_overview.js.map +1 -1
  50. package/dist/src/billing/billing_store.d.ts +634 -5
  51. package/dist/src/billing/billing_store.d.ts.map +1 -1
  52. package/dist/src/billing/billing_store.js +18 -1
  53. package/dist/src/billing/billing_store.js.map +1 -1
  54. package/dist/src/billing/index.d.ts +4 -3
  55. package/dist/src/billing/index.d.ts.map +1 -1
  56. package/dist/src/billing/index.js +2 -1
  57. package/dist/src/billing/index.js.map +1 -1
  58. package/dist/src/billing/list_query.d.ts +16 -0
  59. package/dist/src/billing/list_query.d.ts.map +1 -0
  60. package/dist/src/billing/list_query.js +28 -0
  61. package/dist/src/billing/list_query.js.map +1 -0
  62. package/dist/src/billing/lucid_billing_store.d.ts +122 -4
  63. package/dist/src/billing/lucid_billing_store.d.ts.map +1 -1
  64. package/dist/src/billing/lucid_billing_store.js +811 -13
  65. package/dist/src/billing/lucid_billing_store.js.map +1 -1
  66. package/dist/src/billing/mixins/index.d.ts +5 -2
  67. package/dist/src/billing/mixins/index.d.ts.map +1 -1
  68. package/dist/src/billing/mixins/index.js +5 -2
  69. package/dist/src/billing/mixins/index.js.map +1 -1
  70. package/dist/src/billing/mixins/with_audit_event.d.ts +48 -0
  71. package/dist/src/billing/mixins/with_audit_event.d.ts.map +1 -0
  72. package/dist/src/billing/mixins/with_audit_event.js +77 -0
  73. package/dist/src/billing/mixins/with_audit_event.js.map +1 -0
  74. package/dist/src/billing/mixins/with_billable.d.ts.map +1 -1
  75. package/dist/src/billing/mixins/with_customer.d.ts +39 -0
  76. package/dist/src/billing/mixins/with_customer.d.ts.map +1 -0
  77. package/dist/src/billing/mixins/with_customer.js +68 -0
  78. package/dist/src/billing/mixins/with_customer.js.map +1 -0
  79. package/dist/src/billing/mixins/with_dispute.d.ts +68 -0
  80. package/dist/src/billing/mixins/with_dispute.d.ts.map +1 -0
  81. package/dist/src/billing/mixins/with_dispute.js +83 -0
  82. package/dist/src/billing/mixins/with_dispute.js.map +1 -0
  83. package/dist/src/billing/mixins/with_payment.d.ts +42 -0
  84. package/dist/src/billing/mixins/with_payment.d.ts.map +1 -1
  85. package/dist/src/billing/mixins/with_payment.js +29 -3
  86. package/dist/src/billing/mixins/with_payment.js.map +1 -1
  87. package/dist/src/billing/mixins/with_subscription.d.ts +7 -0
  88. package/dist/src/billing/mixins/with_subscription.d.ts.map +1 -1
  89. package/dist/src/billing/mixins/with_subscription.js +15 -1
  90. package/dist/src/billing/mixins/with_subscription.js.map +1 -1
  91. package/dist/src/billing/mixins/with_usage_event.d.ts +7 -0
  92. package/dist/src/billing/mixins/with_usage_event.d.ts.map +1 -1
  93. package/dist/src/billing/mixins/with_usage_event.js +15 -1
  94. package/dist/src/billing/mixins/with_usage_event.js.map +1 -1
  95. package/dist/src/billing/mixins/with_webhook_event.d.ts +18 -0
  96. package/dist/src/billing/mixins/with_webhook_event.d.ts.map +1 -1
  97. package/dist/src/billing/mixins/with_webhook_event.js +18 -1
  98. package/dist/src/billing/mixins/with_webhook_event.js.map +1 -1
  99. package/dist/src/billing/resolve_dispatch.d.ts +22 -0
  100. package/dist/src/billing/resolve_dispatch.d.ts.map +1 -0
  101. package/dist/src/billing/resolve_dispatch.js +44 -0
  102. package/dist/src/billing/resolve_dispatch.js.map +1 -0
  103. package/dist/src/billing/resolve_store.d.ts +18 -0
  104. package/dist/src/billing/resolve_store.d.ts.map +1 -0
  105. package/dist/src/billing/resolve_store.js +35 -0
  106. package/dist/src/billing/resolve_store.js.map +1 -0
  107. package/dist/src/billing/schema.d.ts +108 -0
  108. package/dist/src/billing/schema.d.ts.map +1 -0
  109. package/dist/src/billing/schema.js +350 -0
  110. package/dist/src/billing/schema.js.map +1 -0
  111. package/dist/src/billing/webhook_dispatcher.d.ts +95 -16
  112. package/dist/src/billing/webhook_dispatcher.d.ts.map +1 -1
  113. package/dist/src/billing/webhook_dispatcher.js +186 -33
  114. package/dist/src/billing/webhook_dispatcher.js.map +1 -1
  115. package/dist/src/billing/webhook_events.d.ts +67 -1
  116. package/dist/src/billing/webhook_events.d.ts.map +1 -1
  117. package/dist/src/billing/webhook_events.js +15 -0
  118. package/dist/src/billing/webhook_events.js.map +1 -1
  119. package/dist/src/billing/webhook_processor.d.ts.map +1 -1
  120. package/dist/src/billing/webhook_processor.js +325 -5
  121. package/dist/src/billing/webhook_processor.js.map +1 -1
  122. package/dist/src/client/define_config.d.ts +150 -0
  123. package/dist/src/client/define_config.d.ts.map +1 -0
  124. package/dist/src/client/define_config.js +98 -0
  125. package/dist/src/client/define_config.js.map +1 -0
  126. package/dist/src/client/handlers.d.ts +71 -0
  127. package/dist/src/client/handlers.d.ts.map +1 -0
  128. package/dist/src/client/handlers.js +119 -0
  129. package/dist/src/client/handlers.js.map +1 -0
  130. package/dist/src/client/index.d.ts +15 -0
  131. package/dist/src/client/index.d.ts.map +1 -0
  132. package/dist/src/client/index.js +12 -0
  133. package/dist/src/client/index.js.map +1 -0
  134. package/dist/src/client/statuses.d.ts +38 -0
  135. package/dist/src/client/statuses.d.ts.map +1 -0
  136. package/dist/src/client/statuses.js +42 -0
  137. package/dist/src/client/statuses.js.map +1 -0
  138. package/dist/src/dashboard/actions.d.ts +143 -0
  139. package/dist/src/dashboard/actions.d.ts.map +1 -0
  140. package/dist/src/dashboard/actions.js +112 -0
  141. package/dist/src/dashboard/actions.js.map +1 -0
  142. package/dist/src/dashboard/auth.d.ts +136 -0
  143. package/dist/src/dashboard/auth.d.ts.map +1 -0
  144. package/dist/src/dashboard/auth.js +152 -0
  145. package/dist/src/dashboard/auth.js.map +1 -0
  146. package/dist/src/dashboard/define_config.d.ts +80 -0
  147. package/dist/src/dashboard/define_config.d.ts.map +1 -0
  148. package/dist/src/dashboard/define_config.js +83 -0
  149. package/dist/src/dashboard/define_config.js.map +1 -0
  150. package/dist/src/dashboard/handlers.d.ts +281 -0
  151. package/dist/src/dashboard/handlers.d.ts.map +1 -0
  152. package/dist/src/dashboard/handlers.js +960 -0
  153. package/dist/src/dashboard/handlers.js.map +1 -0
  154. package/dist/src/dashboard/index.d.ts +17 -0
  155. package/dist/src/dashboard/index.d.ts.map +1 -0
  156. package/dist/src/dashboard/index.js +13 -0
  157. package/dist/src/dashboard/index.js.map +1 -0
  158. package/dist/src/dashboard/login_page.d.ts +23 -0
  159. package/dist/src/dashboard/login_page.d.ts.map +1 -0
  160. package/dist/src/dashboard/login_page.js +170 -0
  161. package/dist/src/dashboard/login_page.js.map +1 -0
  162. package/dist/src/dashboard/period.d.ts +31 -0
  163. package/dist/src/dashboard/period.d.ts.map +1 -0
  164. package/dist/src/dashboard/period.js +44 -0
  165. package/dist/src/dashboard/period.js.map +1 -0
  166. package/dist/src/dashboard/session_cookie.d.ts +42 -0
  167. package/dist/src/dashboard/session_cookie.d.ts.map +1 -0
  168. package/dist/src/dashboard/session_cookie.js +97 -0
  169. package/dist/src/dashboard/session_cookie.js.map +1 -0
  170. package/dist/src/dashboard/spa.d.ts +24 -0
  171. package/dist/src/dashboard/spa.d.ts.map +1 -0
  172. package/dist/src/dashboard/spa.js +52 -0
  173. package/dist/src/dashboard/spa.js.map +1 -0
  174. package/dist/src/define_config.d.ts +245 -10
  175. package/dist/src/define_config.d.ts.map +1 -1
  176. package/dist/src/define_config.js +97 -1
  177. package/dist/src/define_config.js.map +1 -1
  178. package/dist/src/diagnostics.d.ts +287 -7
  179. package/dist/src/diagnostics.d.ts.map +1 -1
  180. package/dist/src/diagnostics.js +317 -1
  181. package/dist/src/diagnostics.js.map +1 -1
  182. package/dist/src/driver.d.ts +139 -5
  183. package/dist/src/driver.d.ts.map +1 -1
  184. package/dist/src/drivers/abacate.d.ts +13 -3
  185. package/dist/src/drivers/abacate.d.ts.map +1 -1
  186. package/dist/src/drivers/abacate.js +112 -19
  187. package/dist/src/drivers/abacate.js.map +1 -1
  188. package/dist/src/drivers/adyen.d.ts +164 -0
  189. package/dist/src/drivers/adyen.d.ts.map +1 -0
  190. package/dist/src/drivers/adyen.js +678 -0
  191. package/dist/src/drivers/adyen.js.map +1 -0
  192. package/dist/src/drivers/asaas.d.ts +53 -3
  193. package/dist/src/drivers/asaas.d.ts.map +1 -1
  194. package/dist/src/drivers/asaas.js +364 -29
  195. package/dist/src/drivers/asaas.js.map +1 -1
  196. package/dist/src/drivers/dodo.d.ts +135 -0
  197. package/dist/src/drivers/dodo.d.ts.map +1 -0
  198. package/dist/src/drivers/dodo.js +864 -0
  199. package/dist/src/drivers/dodo.js.map +1 -0
  200. package/dist/src/drivers/efi.d.ts +98 -0
  201. package/dist/src/drivers/efi.d.ts.map +1 -0
  202. package/dist/src/drivers/efi.js +628 -0
  203. package/dist/src/drivers/efi.js.map +1 -0
  204. package/dist/src/drivers/infinitepay.d.ts +156 -0
  205. package/dist/src/drivers/infinitepay.d.ts.map +1 -0
  206. package/dist/src/drivers/infinitepay.js +321 -0
  207. package/dist/src/drivers/infinitepay.js.map +1 -0
  208. package/dist/src/drivers/lemonsqueezy.d.ts +125 -0
  209. package/dist/src/drivers/lemonsqueezy.d.ts.map +1 -0
  210. package/dist/src/drivers/lemonsqueezy.js +632 -0
  211. package/dist/src/drivers/lemonsqueezy.js.map +1 -0
  212. package/dist/src/drivers/mercadopago.d.ts +97 -0
  213. package/dist/src/drivers/mercadopago.d.ts.map +1 -0
  214. package/dist/src/drivers/mercadopago.js +844 -0
  215. package/dist/src/drivers/mercadopago.js.map +1 -0
  216. package/dist/src/drivers/mollie.d.ts +125 -0
  217. package/dist/src/drivers/mollie.d.ts.map +1 -0
  218. package/dist/src/drivers/mollie.js +812 -0
  219. package/dist/src/drivers/mollie.js.map +1 -0
  220. package/dist/src/drivers/paddle.d.ts +148 -0
  221. package/dist/src/drivers/paddle.d.ts.map +1 -0
  222. package/dist/src/drivers/paddle.js +738 -0
  223. package/dist/src/drivers/paddle.js.map +1 -0
  224. package/dist/src/drivers/pagarme.d.ts +97 -0
  225. package/dist/src/drivers/pagarme.d.ts.map +1 -0
  226. package/dist/src/drivers/pagarme.js +829 -0
  227. package/dist/src/drivers/pagarme.js.map +1 -0
  228. package/dist/src/drivers/pagbank.d.ts +57 -0
  229. package/dist/src/drivers/pagbank.d.ts.map +1 -0
  230. package/dist/src/drivers/pagbank.js +499 -0
  231. package/dist/src/drivers/pagbank.js.map +1 -0
  232. package/dist/src/drivers/paypal.d.ts +120 -0
  233. package/dist/src/drivers/paypal.d.ts.map +1 -0
  234. package/dist/src/drivers/paypal.js +891 -0
  235. package/dist/src/drivers/paypal.js.map +1 -0
  236. package/dist/src/drivers/polar.d.ts +118 -0
  237. package/dist/src/drivers/polar.d.ts.map +1 -0
  238. package/dist/src/drivers/polar.js +604 -0
  239. package/dist/src/drivers/polar.js.map +1 -0
  240. package/dist/src/drivers/razorpay.d.ts +103 -0
  241. package/dist/src/drivers/razorpay.d.ts.map +1 -0
  242. package/dist/src/drivers/razorpay.js +867 -0
  243. package/dist/src/drivers/razorpay.js.map +1 -0
  244. package/dist/src/drivers/shared.d.ts +33 -0
  245. package/dist/src/drivers/shared.d.ts.map +1 -0
  246. package/dist/src/drivers/shared.js +37 -0
  247. package/dist/src/drivers/shared.js.map +1 -0
  248. package/dist/src/drivers/square.d.ts +133 -0
  249. package/dist/src/drivers/square.d.ts.map +1 -0
  250. package/dist/src/drivers/square.js +905 -0
  251. package/dist/src/drivers/square.js.map +1 -0
  252. package/dist/src/drivers/stripe.d.ts +41 -4
  253. package/dist/src/drivers/stripe.d.ts.map +1 -1
  254. package/dist/src/drivers/stripe.js +823 -26
  255. package/dist/src/drivers/stripe.js.map +1 -1
  256. package/dist/src/drivers/woovi.d.ts +11 -4
  257. package/dist/src/drivers/woovi.d.ts.map +1 -1
  258. package/dist/src/drivers/woovi.js +162 -29
  259. package/dist/src/drivers/woovi.js.map +1 -1
  260. package/dist/src/ensure_customer.d.ts +34 -1
  261. package/dist/src/ensure_customer.d.ts.map +1 -1
  262. package/dist/src/ensure_customer.js +29 -4
  263. package/dist/src/ensure_customer.js.map +1 -1
  264. package/dist/src/hooks/webhook_handlers.d.ts.map +1 -1
  265. package/dist/src/hooks/webhook_handlers.js.map +1 -1
  266. package/dist/src/http.d.ts +37 -3
  267. package/dist/src/http.d.ts.map +1 -1
  268. package/dist/src/http.js +69 -5
  269. package/dist/src/http.js.map +1 -1
  270. package/dist/src/index.d.ts +54 -26
  271. package/dist/src/index.d.ts.map +1 -1
  272. package/dist/src/index.js +29 -12
  273. package/dist/src/index.js.map +1 -1
  274. package/dist/src/invoice/drivers/asaas.d.ts.map +1 -1
  275. package/dist/src/invoice/drivers/asaas.js.map +1 -1
  276. package/dist/src/invoice/drivers/enotas.d.ts.map +1 -1
  277. package/dist/src/invoice/drivers/enotas.js.map +1 -1
  278. package/dist/src/invoice/drivers/focus.d.ts.map +1 -1
  279. package/dist/src/invoice/drivers/focus.js.map +1 -1
  280. package/dist/src/invoice/drivers/plugnotas.d.ts.map +1 -1
  281. package/dist/src/invoice/drivers/plugnotas.js.map +1 -1
  282. package/dist/src/invoice/drivers/tecnospeed.d.ts.map +1 -1
  283. package/dist/src/invoice/drivers/tecnospeed.js.map +1 -1
  284. package/dist/src/invoice/emit_invoice.d.ts.map +1 -1
  285. package/dist/src/invoice/emit_invoice.js +31 -11
  286. package/dist/src/invoice/emit_invoice.js.map +1 -1
  287. package/dist/src/invoice/invoice_manager.d.ts.map +1 -1
  288. package/dist/src/money.d.ts +23 -5
  289. package/dist/src/money.d.ts.map +1 -1
  290. package/dist/src/money.js +72 -7
  291. package/dist/src/money.js.map +1 -1
  292. package/dist/src/payments_manager.d.ts +8 -1
  293. package/dist/src/payments_manager.d.ts.map +1 -1
  294. package/dist/src/payments_manager.js +168 -6
  295. package/dist/src/payments_manager.js.map +1 -1
  296. package/dist/src/services/main.d.ts +38 -0
  297. package/dist/src/services/main.d.ts.map +1 -1
  298. package/dist/src/services/main.js +130 -0
  299. package/dist/src/services/main.js.map +1 -1
  300. package/dist/src/telescope/index.d.ts +2 -0
  301. package/dist/src/telescope/index.d.ts.map +1 -1
  302. package/dist/src/telescope/index.js +1 -0
  303. package/dist/src/telescope/index.js.map +1 -1
  304. package/dist/src/telescope/payments_watcher.d.ts +10 -4
  305. package/dist/src/telescope/payments_watcher.d.ts.map +1 -1
  306. package/dist/src/telescope/payments_watcher.js +66 -14
  307. package/dist/src/telescope/payments_watcher.js.map +1 -1
  308. package/dist/src/telescope/register.d.ts +62 -0
  309. package/dist/src/telescope/register.d.ts.map +1 -0
  310. package/dist/src/telescope/register.js +48 -0
  311. package/dist/src/telescope/register.js.map +1 -0
  312. package/dist/src/testing/fake_payments.d.ts +62 -0
  313. package/dist/src/testing/fake_payments.d.ts.map +1 -0
  314. package/dist/src/testing/fake_payments.js +82 -0
  315. package/dist/src/testing/fake_payments.js.map +1 -0
  316. package/dist/src/testing/fake_payments_driver.d.ts +1 -1
  317. package/dist/src/testing/fake_payments_driver.d.ts.map +1 -1
  318. package/dist/src/testing/fake_payments_driver.js.map +1 -1
  319. package/dist/src/testing/in_memory_billing_store.d.ts +151 -2
  320. package/dist/src/testing/in_memory_billing_store.d.ts.map +1 -1
  321. package/dist/src/testing/in_memory_billing_store.js +517 -4
  322. package/dist/src/testing/in_memory_billing_store.js.map +1 -1
  323. package/dist/src/testing/index.d.ts +3 -2
  324. package/dist/src/testing/index.d.ts.map +1 -1
  325. package/dist/src/testing/index.js +1 -0
  326. package/dist/src/testing/index.js.map +1 -1
  327. package/dist/src/testing/mutable_clock.d.ts.map +1 -1
  328. package/dist/src/types.d.ts +161 -5
  329. package/dist/src/types.d.ts.map +1 -1
  330. package/dist/src/types.js +30 -1
  331. package/dist/src/types.js.map +1 -1
  332. package/dist/src/webhook_handlers.d.ts +96 -2
  333. package/dist/src/webhook_handlers.d.ts.map +1 -1
  334. package/dist/src/webhook_handlers.js +91 -10
  335. package/dist/src/webhook_handlers.js.map +1 -1
  336. package/dist/src/webhook_security.d.ts +94 -3
  337. package/dist/src/webhook_security.d.ts.map +1 -1
  338. package/dist/src/webhook_security.js +173 -9
  339. package/dist/src/webhook_security.js.map +1 -1
  340. package/dist/stubs/config/payments.stub +13 -0
  341. package/dist/stubs/config/payments_client.stub +42 -0
  342. package/dist/stubs/config/payments_dashboard.stub +38 -0
  343. package/dist/stubs/database/migrations/create_billing_tables.stub +35 -77
  344. package/dist/stubs/main.js.map +1 -1
  345. package/dist/stubs/make/webhook_handler/main.stub +29 -11
  346. package/package.json +67 -32
@@ -0,0 +1,85 @@
1
+ import { type BillingStore, type DisputeListItem, type WebhookEventBreakdownLine } from './billing_store.js';
2
+ export interface BillingHealthOptions {
3
+ /** Milliseconds an event may sit in `received` before it counts as stuck. Default 15 min. */
4
+ stuckAfter?: number;
5
+ /** Milliseconds a `pending` payment may age before it counts as unconfirmed. Default 2 h. */
6
+ unconfirmedAfter?: number;
7
+ /** The window `failed` events are counted over. Default 24 h. */
8
+ failedWithin?: number;
9
+ /**
10
+ * How far ahead to look for a dispute whose evidence window is about to close. Default 72 h.
11
+ *
12
+ * In milliseconds like every other threshold here, though the store's read takes hours —
13
+ * the conversion happens once, at the call.
14
+ */
15
+ disputeDueWithin?: number;
16
+ /** The window rejected deliveries are counted over. Default 24 h. */
17
+ rejectedWithin?: number;
18
+ /** Overridable clock — the tests pass a fixed instant. Defaults to now. */
19
+ now?: Date;
20
+ }
21
+ export interface BillingHealthCheck {
22
+ key: 'stuck_webhooks' | 'failed_webhooks' | 'unconfirmed_payments' | 'disputes_due' | 'open_disputes' | 'rejected_deliveries';
23
+ label: string;
24
+ count: number;
25
+ /** `true` when `count` is zero — every check here is a "should be nothing" check. */
26
+ healthy: boolean;
27
+ /** What a non-zero count means, and what to do about it. */
28
+ hint: string;
29
+ }
30
+ export interface BillingHealth {
31
+ /** `false` when any check is non-zero — the exit code `payments:health` returns. */
32
+ healthy: boolean;
33
+ checkedAt: Date;
34
+ checks: BillingHealthCheck[];
35
+ /** Which provider/event pairs make up `failed_webhooks`, worst first. */
36
+ failures: WebhookEventBreakdownLine[];
37
+ /**
38
+ * The disputes behind `disputes_due`, soonest deadline first — WHICH windows are closing,
39
+ * not just how many. Capped at {@link DISPUTE_DEADLINE_SAMPLE}; `disputes_due.count` is the
40
+ * full number, so a report can name twenty and still say there are fifty.
41
+ */
42
+ deadlines: DisputeListItem[];
43
+ /**
44
+ * The disputes behind `open_disputes`, OLDEST first — the ones nobody has answered, whether or
45
+ * not a deadline was ever published for them. Capped at {@link OPEN_DISPUTE_SAMPLE}.
46
+ *
47
+ * Overlaps `deadlines` on purpose: a dispute that has both a deadline and no answer belongs in
48
+ * both lists, and suppressing it from one of them to keep them disjoint would make the
49
+ * deadline-free check quietly incomplete on exactly the install it exists for.
50
+ */
51
+ openDisputes: DisputeListItem[];
52
+ }
53
+ /**
54
+ * The six operational questions about a billing install that nothing else answers, asked
55
+ * through the store instead of by hand against the tables.
56
+ *
57
+ * Each is a silent failure — the kind where the endpoint keeps returning `200` and revenue
58
+ * quietly stops landing:
59
+ *
60
+ * - **Stuck events**: claimed in the ledger, never finished. Almost always the worker the
61
+ * dispatcher depends on (`durable:work` / `queue:listen`) is not running.
62
+ * - **Failed events**: the handler threw and retries were exhausted, so the effect that
63
+ * event described — the grant, the activation — never happened.
64
+ * - **Unconfirmed charges**: created and never confirmed. This is what a webhook endpoint
65
+ * that stopped being reachable looks like from the inside, and nothing errors.
66
+ * - **Closing dispute windows**: an open chargeback whose evidence deadline is inside the
67
+ * next three days. This is the only check here that alerts on a CLOCK rather than on a
68
+ * failure — nothing is broken, and the money is lost anyway if the window closes
69
+ * unanswered, by default rather than on the merits.
70
+ * - **Open disputes**: the same money, without the clock. `disputes_due` can only ever see a
71
+ * dispute whose gateway PUBLISHED a deadline, and most do not — Asaas' comes from
72
+ * `chargeback.deadlineToSendDisputeDocuments`, which no published webhook example contains.
73
+ * On such an install the deadline check is zero forever while a chargeback sits open with the
74
+ * money already pulled back, and the report says healthy. This one asks the question the
75
+ * deadline cannot.
76
+ * - **Rejected deliveries**: gateway calls the endpoint REFUSED — a bad signature, an unparsable
77
+ * body, a provider nobody configured. They never become ledger rows, so a rotated webhook
78
+ * token used to look exactly like a quiet week: zero events, zero failures, every check green.
79
+ * `unconfirmed_payments` eventually notices, but only for charges the app itself created;
80
+ * refunds, chargebacks and dispute closures produce no pending payment and simply vanish.
81
+ *
82
+ * Pure store reads, no gateway calls — safe to run on a schedule and to alert on.
83
+ */
84
+ export declare function billingHealth(store: BillingStore, options?: BillingHealthOptions): Promise<BillingHealth>;
85
+ //# sourceMappingURL=billing_health.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"billing_health.d.ts","sourceRoot":"","sources":["../../../src/billing/billing_health.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,yBAAyB,EAC/B,MAAM,oBAAoB,CAAC;AAkC5B,MAAM,WAAW,oBAAoB;IACnC,6FAA6F;IAC7F,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6FAA6F;IAC7F,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,iEAAiE;IACjE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,qEAAqE;IACrE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,2EAA2E;IAC3E,GAAG,CAAC,EAAE,IAAI,CAAC;CACZ;AAED,MAAM,WAAW,kBAAkB;IACjC,GAAG,EACC,gBAAgB,GAChB,iBAAiB,GACjB,sBAAsB,GACtB,cAAc,GACd,eAAe,GACf,qBAAqB,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,qFAAqF;IACrF,OAAO,EAAE,OAAO,CAAC;IACjB,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,oFAAoF;IACpF,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,IAAI,CAAC;IAChB,MAAM,EAAE,kBAAkB,EAAE,CAAC;IAC7B,yEAAyE;IACzE,QAAQ,EAAE,yBAAyB,EAAE,CAAC;IACtC;;;;OAIG;IACH,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B;;;;;;;OAOG;IACH,YAAY,EAAE,eAAe,EAAE,CAAC;CACjC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAsB,aAAa,CACjC,KAAK,EAAE,YAAY,EACnB,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,aAAa,CAAC,CA6FxB"}
@@ -0,0 +1,155 @@
1
+ import { AUDIT_ACTIONS, } from './billing_store.js';
2
+ /** 15 minutes — an event claimed but unfinished for longer is not slow, it is abandoned. */
3
+ const DEFAULT_STUCK_AFTER = 15 * 60 * 1000;
4
+ /** 2 hours — every gateway confirms or fails a charge well inside this. */
5
+ const DEFAULT_UNCONFIRMED_AFTER = 2 * 60 * 60 * 1000;
6
+ /** 24 hours — the window failures are counted over. */
7
+ const DEFAULT_FAILED_WITHIN = 24 * 60 * 60 * 1000;
8
+ /**
9
+ * 72 hours — how far ahead a closing evidence window is worth shouting about.
10
+ *
11
+ * Gateways give between 7 and 21 days to respond, so three days is late enough that the
12
+ * check is not permanently red and early enough that somebody can still gather a receipt, a
13
+ * delivery confirmation and an IP log before the window shuts. Past-due disputes stay
14
+ * counted: the window closing is what makes it urgent, not what makes it finished.
15
+ */
16
+ const DEFAULT_DISPUTE_DUE_WITHIN = 72 * 60 * 60 * 1000;
17
+ /**
18
+ * 24 hours — the window rejected deliveries are counted over.
19
+ *
20
+ * A rejection is not a slow-burning condition like a stuck event: a rotated webhook token, a
21
+ * secret that never made it into the deploy, a gateway pointed at the wrong route, all produce
22
+ * rejections immediately and continuously. A day is long enough to survive a redeploy and short
23
+ * enough that the number means "right now".
24
+ */
25
+ const DEFAULT_REJECTED_WITHIN = 24 * 60 * 60 * 1000;
26
+ /** How many closing windows the report NAMES. The count is unbounded; this is the list. */
27
+ const DISPUTE_DEADLINE_SAMPLE = 20;
28
+ /** How many open disputes the report NAMES, oldest first. The count is unbounded. */
29
+ const OPEN_DISPUTE_SAMPLE = 20;
30
+ /**
31
+ * The six operational questions about a billing install that nothing else answers, asked
32
+ * through the store instead of by hand against the tables.
33
+ *
34
+ * Each is a silent failure — the kind where the endpoint keeps returning `200` and revenue
35
+ * quietly stops landing:
36
+ *
37
+ * - **Stuck events**: claimed in the ledger, never finished. Almost always the worker the
38
+ * dispatcher depends on (`durable:work` / `queue:listen`) is not running.
39
+ * - **Failed events**: the handler threw and retries were exhausted, so the effect that
40
+ * event described — the grant, the activation — never happened.
41
+ * - **Unconfirmed charges**: created and never confirmed. This is what a webhook endpoint
42
+ * that stopped being reachable looks like from the inside, and nothing errors.
43
+ * - **Closing dispute windows**: an open chargeback whose evidence deadline is inside the
44
+ * next three days. This is the only check here that alerts on a CLOCK rather than on a
45
+ * failure — nothing is broken, and the money is lost anyway if the window closes
46
+ * unanswered, by default rather than on the merits.
47
+ * - **Open disputes**: the same money, without the clock. `disputes_due` can only ever see a
48
+ * dispute whose gateway PUBLISHED a deadline, and most do not — Asaas' comes from
49
+ * `chargeback.deadlineToSendDisputeDocuments`, which no published webhook example contains.
50
+ * On such an install the deadline check is zero forever while a chargeback sits open with the
51
+ * money already pulled back, and the report says healthy. This one asks the question the
52
+ * deadline cannot.
53
+ * - **Rejected deliveries**: gateway calls the endpoint REFUSED — a bad signature, an unparsable
54
+ * body, a provider nobody configured. They never become ledger rows, so a rotated webhook
55
+ * token used to look exactly like a quiet week: zero events, zero failures, every check green.
56
+ * `unconfirmed_payments` eventually notices, but only for charges the app itself created;
57
+ * refunds, chargebacks and dispute closures produce no pending payment and simply vanish.
58
+ *
59
+ * Pure store reads, no gateway calls — safe to run on a schedule and to alert on.
60
+ */
61
+ export async function billingHealth(store, options = {}) {
62
+ const now = options.now ?? new Date();
63
+ const stuckAfter = options.stuckAfter ?? DEFAULT_STUCK_AFTER;
64
+ const unconfirmedAfter = options.unconfirmedAfter ?? DEFAULT_UNCONFIRMED_AFTER;
65
+ const failedWithin = options.failedWithin ?? DEFAULT_FAILED_WITHIN;
66
+ const disputeDueWithin = options.disputeDueWithin ?? DEFAULT_DISPUTE_DUE_WITHIN;
67
+ const rejectedWithin = options.rejectedWithin ?? DEFAULT_REJECTED_WITHIN;
68
+ const since = (ms) => new Date(now.getTime() - ms);
69
+ // The store's deadline read takes HOURS; every other threshold here is milliseconds.
70
+ const withinHours = disputeDueWithin / 3_600_000;
71
+ const [stuck, failed, unconfirmed, failures, disputesDue, deadlines, openDisputeCount, openDisputes, rejected,] = await Promise.all([
72
+ store.countWebhookEvents({ status: 'received', createdBefore: since(stuckAfter) }),
73
+ store.countWebhookEvents({ status: 'failed', createdAfter: since(failedWithin) }),
74
+ store.countPayments({ status: 'pending', createdBefore: since(unconfirmedAfter) }),
75
+ store.webhookEventBreakdown({ status: 'failed', createdAfter: since(failedWithin) }),
76
+ // Counted separately from the list, and unbounded: a count taken from a capped page
77
+ // saturates at the cap, and this number is what the exit code is decided on.
78
+ store.countDisputesDueWithin({ withinHours, now }),
79
+ store.listDisputesDueWithin({ withinHours, now, limit: DISPUTE_DEADLINE_SAMPLE }),
80
+ // No window and no deadline: an open dispute is unanswered however old it is, and on a
81
+ // gateway that publishes no deadline this is the ONLY read that can see it at all.
82
+ store.countOpenDisputes({}),
83
+ store.listOpenDisputes({ limit: OPEN_DISPUTE_SAMPLE }),
84
+ store.countAuditEvents({
85
+ action: AUDIT_ACTIONS.webhookRejected,
86
+ createdAfter: since(rejectedWithin),
87
+ }),
88
+ ]);
89
+ const checks = [
90
+ {
91
+ key: 'stuck_webhooks',
92
+ label: `Events claimed but unfinished for over ${formatDuration(stuckAfter)}`,
93
+ count: stuck,
94
+ healthy: stuck === 0,
95
+ hint: 'Nothing is consuming the dispatcher. Check that the worker is running (durable:work / queue:listen).',
96
+ },
97
+ {
98
+ key: 'failed_webhooks',
99
+ label: `Events the dispatcher gave up on in the last ${formatDuration(failedWithin)}`,
100
+ count: failed,
101
+ healthy: failed === 0,
102
+ hint: 'Handlers threw and retries ran out; those events never took effect. Read the errors with listWebhookEvents({ status: "failed" }), fix the cause, then replay them from the gateway dashboard.',
103
+ },
104
+ {
105
+ key: 'unconfirmed_payments',
106
+ label: `Charges created over ${formatDuration(unconfirmedAfter)} ago and still pending`,
107
+ count: unconfirmed,
108
+ healthy: unconfirmed === 0,
109
+ hint: 'Charges are being created but never confirmed — the shape of a webhook endpoint that stopped being reachable. Check the gateway dashboard delivery log.',
110
+ },
111
+ {
112
+ key: 'disputes_due',
113
+ label: `Open disputes whose evidence window closes within ${formatDuration(disputeDueWithin)}`,
114
+ count: disputesDue,
115
+ healthy: disputesDue === 0,
116
+ hint: 'A chargeback window is closing. Past it the dispute is lost by default rather than on the merits, and nothing can be done — submit evidence at the gateway, or refund if it is cheaper than the fee. Rows already past their deadline are counted here too: they are still open, and still unanswered.',
117
+ },
118
+ {
119
+ key: 'open_disputes',
120
+ label: 'Disputes still open and unanswered',
121
+ count: openDisputeCount,
122
+ healthy: openDisputeCount === 0,
123
+ hint: 'A chargeback is open and the money is already out of the account. This check does NOT need a deadline, which is the point: most gateways publish none, and on those installs the deadline check reports zero forever. Answer it at the gateway, then close it here (POST <dashboard>/api/disputes/:gatewayId/resolve) — several gateways never send a lost-dispute event, so nothing else will ever close the row.',
124
+ },
125
+ {
126
+ key: 'rejected_deliveries',
127
+ label: `Gateway deliveries refused in the last ${formatDuration(rejectedWithin)}`,
128
+ count: rejected,
129
+ healthy: rejected === 0,
130
+ hint: 'The webhook endpoint answered 400: a signature that did not verify, a body it could not parse, or a provider nobody configured. The usual cause is a rotated webhook secret that never reached the deployment — and the deliveries lost that way are invisible everywhere else, because a rejected delivery never becomes a ledger row. Read them with listAuditEvents({ action: "webhook.rejected" }).',
131
+ },
132
+ ];
133
+ return {
134
+ healthy: checks.every((check) => check.healthy),
135
+ checkedAt: now,
136
+ checks,
137
+ failures,
138
+ deadlines,
139
+ openDisputes,
140
+ };
141
+ }
142
+ /** `900000` reads as nothing in a label; `15m` reads as a threshold. */
143
+ function formatDuration(ms) {
144
+ const minutes = Math.round(ms / 60_000);
145
+ if (minutes < 60)
146
+ return `${minutes}m`;
147
+ const hours = minutes / 60;
148
+ if (hours < 24)
149
+ return `${trim(hours)}h`;
150
+ return `${trim(hours / 24)}d`;
151
+ }
152
+ function trim(value) {
153
+ return Number.isInteger(value) ? String(value) : value.toFixed(1);
154
+ }
155
+ //# sourceMappingURL=billing_health.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"billing_health.js","sourceRoot":"","sources":["../../../src/billing/billing_health.ts"],"names":[],"mappings":"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"}
@@ -15,9 +15,10 @@ export interface BillingOverview {
15
15
  }
16
16
  /**
17
17
  * Compute a billing overview from the store — the data foundation a billing dashboard
18
- * (Agora dashboard pattern) renders. Aggregates KPIs over a `from`/`to` window: revenue
19
- * (sum of paid payments), active subscriptions, and usage per meter. Pure store queries
20
- * (no gateway calls), so it works headless and is trivially testable.
18
+ * (Agora dashboard pattern) renders. Aggregates KPIs over a `from`/`to` window: revenue —
19
+ * BOTH gross (`revenue`, the sum of paid payments) and net of refunds (`net_revenue`,
20
+ * `amount - refunded_amount` over the same rows) — active subscriptions, and usage per meter.
21
+ * Pure store queries (no gateway calls), so it works headless and is trivially testable.
21
22
  */
22
23
  export declare function billingOverview(store: BillingStore, options: {
23
24
  from: Date;
@@ -1 +1 @@
1
- {"version":3,"file":"billing_overview.d.ts","sourceRoot":"","sources":["../../../src/billing/billing_overview.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,kDAAkD;AAClD,MAAM,WAAW,qBAAqB;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,mEAAmE;AACnE,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,EAAE,EAAE,IAAI,CAAA;KAAE,CAAC;IACjC,OAAO,EAAE,qBAAqB,EAAE,CAAC;CAClC;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,EAAE,EAAE,IAAI,CAAA;CAAE,GAChC,OAAO,CAAC,eAAe,CAAC,CAqB1B"}
1
+ {"version":3,"file":"billing_overview.d.ts","sourceRoot":"","sources":["../../../src/billing/billing_overview.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,kDAAkD;AAClD,MAAM,WAAW,qBAAqB;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,mEAAmE;AACnE,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,EAAE,EAAE,IAAI,CAAA;KAAE,CAAC;IACjC,OAAO,EAAE,qBAAqB,EAAE,CAAC;CAClC;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,EAAE,EAAE,IAAI,CAAA;CAAE,GAChC,OAAO,CAAC,eAAe,CAAC,CA6B1B"}
@@ -1,18 +1,27 @@
1
1
  /**
2
2
  * Compute a billing overview from the store — the data foundation a billing dashboard
3
- * (Agora dashboard pattern) renders. Aggregates KPIs over a `from`/`to` window: revenue
4
- * (sum of paid payments), active subscriptions, and usage per meter. Pure store queries
5
- * (no gateway calls), so it works headless and is trivially testable.
3
+ * (Agora dashboard pattern) renders. Aggregates KPIs over a `from`/`to` window: revenue —
4
+ * BOTH gross (`revenue`, the sum of paid payments) and net of refunds (`net_revenue`,
5
+ * `amount - refunded_amount` over the same rows) — active subscriptions, and usage per meter.
6
+ * Pure store queries (no gateway calls), so it works headless and is trivially testable.
6
7
  */
7
8
  export async function billingOverview(store, options) {
8
9
  const { from, to } = options;
9
- const [revenue, activeSubscriptions, usage] = await Promise.all([
10
+ const [revenue, netRevenue, activeSubscriptions, usage] = await Promise.all([
10
11
  store.revenue({ from, to }),
12
+ store.netRevenue({ from, to }),
11
13
  store.countActiveSubscriptions(),
12
14
  store.usageReport({ from, to }),
13
15
  ]);
14
16
  const metrics = [
15
- { key: 'revenue', label: 'Revenue (cents)', value: revenue },
17
+ // Two money lines, and the labels are load-bearing. `revenue` was the only one for two
18
+ // releases, and it is GROSS: a charge that was half refunded counts at its full value in
19
+ // it. Nothing on the screen said so, so a partial refund was invisible in the console's
20
+ // headline number. Both figures are legitimate — gross is what was collected, net is what
21
+ // was kept — and the fix is to publish both under names that cannot be confused, not to
22
+ // quietly redefine the one apps already read.
23
+ { key: 'revenue', label: 'Revenue, gross (cents)', value: revenue },
24
+ { key: 'net_revenue', label: 'Revenue, net of refunds (cents)', value: netRevenue },
16
25
  { key: 'active_subscriptions', label: 'Active subscriptions', value: activeSubscriptions },
17
26
  ];
18
27
  for (const line of usage) {
@@ -1 +1 @@
1
- {"version":3,"file":"billing_overview.js","sourceRoot":"","sources":["../../../src/billing/billing_overview.ts"],"names":[],"mappings":"AAeA;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,KAAmB,EACnB,OAAiC;IAEjC,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC;IAC7B,MAAM,CAAC,OAAO,EAAE,mBAAmB,EAAE,KAAK,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC9D,KAAK,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;QAC3B,KAAK,CAAC,wBAAwB,EAAE;QAChC,KAAK,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;KAChC,CAAC,CAAC;IAEH,MAAM,OAAO,GAA4B;QACvC,EAAE,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,iBAAiB,EAAE,KAAK,EAAE,OAAO,EAAE;QAC5D,EAAE,GAAG,EAAE,sBAAsB,EAAE,KAAK,EAAE,sBAAsB,EAAE,KAAK,EAAE,mBAAmB,EAAE;KAC3F,CAAC;IACF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,OAAO,CAAC,IAAI,CAAC;YACX,GAAG,EAAE,SAAS,IAAI,CAAC,KAAK,EAAE;YAC1B,KAAK,EAAE,WAAW,IAAI,CAAC,KAAK,EAAE;YAC9B,KAAK,EAAE,IAAI,CAAC,QAAQ;SACrB,CAAC,CAAC;IACL,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC;AAC3C,CAAC"}
1
+ {"version":3,"file":"billing_overview.js","sourceRoot":"","sources":["../../../src/billing/billing_overview.ts"],"names":[],"mappings":"AAeA;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,KAAmB,EACnB,OAAiC;IAEjC,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC;IAC7B,MAAM,CAAC,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,KAAK,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC1E,KAAK,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;QAC3B,KAAK,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;QAC9B,KAAK,CAAC,wBAAwB,EAAE;QAChC,KAAK,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;KAChC,CAAC,CAAC;IAEH,MAAM,OAAO,GAA4B;QACvC,uFAAuF;QACvF,yFAAyF;QACzF,wFAAwF;QACxF,0FAA0F;QAC1F,wFAAwF;QACxF,8CAA8C;QAC9C,EAAE,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,wBAAwB,EAAE,KAAK,EAAE,OAAO,EAAE;QACnE,EAAE,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,iCAAiC,EAAE,KAAK,EAAE,UAAU,EAAE;QACnF,EAAE,GAAG,EAAE,sBAAsB,EAAE,KAAK,EAAE,sBAAsB,EAAE,KAAK,EAAE,mBAAmB,EAAE;KAC3F,CAAC;IACF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,OAAO,CAAC,IAAI,CAAC;YACX,GAAG,EAAE,SAAS,IAAI,CAAC,KAAK,EAAE;YAC1B,KAAK,EAAE,WAAW,IAAI,CAAC,KAAK,EAAE;YAC9B,KAAK,EAAE,IAAI,CAAC,QAAQ;SACrB,CAAC,CAAC;IACL,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC;AAC3C,CAAC"}