@classytic/revenue 1.0.2 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +603 -486
- package/dist/application/services/index.d.ts +6 -0
- package/dist/application/services/index.js +3288 -0
- package/dist/application/services/index.js.map +1 -0
- package/dist/core/events.d.ts +455 -0
- package/dist/core/events.js +122 -0
- package/dist/core/events.js.map +1 -0
- package/dist/core/index.d.ts +12 -889
- package/dist/core/index.js +2361 -705
- package/dist/core/index.js.map +1 -1
- package/dist/enums/index.d.ts +54 -25
- package/dist/enums/index.js +143 -14
- package/dist/enums/index.js.map +1 -1
- package/dist/escrow.enums-CE0VQsfe.d.ts +76 -0
- package/dist/{index-BnJWVXuw.d.ts → index-DxIK0UmZ.d.ts} +281 -26
- package/dist/index-EnfKzDbs.d.ts +806 -0
- package/dist/{index-ChVD3P9k.d.ts → index-cLJBLUvx.d.ts} +55 -81
- package/dist/index.d.ts +16 -15
- package/dist/index.js +2583 -2066
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/plugins/index.d.ts +267 -0
- package/dist/infrastructure/plugins/index.js +292 -0
- package/dist/infrastructure/plugins/index.js.map +1 -0
- package/dist/money-widWVD7r.d.ts +111 -0
- package/dist/payment.enums-C1BiGlRa.d.ts +69 -0
- package/dist/plugin-Bb9HOE10.d.ts +336 -0
- package/dist/providers/index.d.ts +19 -6
- package/dist/providers/index.js +22 -3
- package/dist/providers/index.js.map +1 -1
- package/dist/reconciliation/index.d.ts +215 -0
- package/dist/reconciliation/index.js +140 -0
- package/dist/reconciliation/index.js.map +1 -0
- package/dist/{retry-80lBCmSe.d.ts → retry-D4hFUwVk.d.ts} +1 -41
- package/dist/schemas/index.d.ts +1927 -166
- package/dist/schemas/index.js +357 -40
- package/dist/schemas/index.js.map +1 -1
- package/dist/schemas/validation.d.ts +87 -12
- package/dist/schemas/validation.js +71 -17
- package/dist/schemas/validation.js.map +1 -1
- package/dist/settlement.enums-ByC1x0ye.d.ts +130 -0
- package/dist/settlement.schema-CpamV7ZY.d.ts +343 -0
- package/dist/split.enums-DG3TxQf9.d.ts +42 -0
- package/dist/tax-CV8A0sxl.d.ts +60 -0
- package/dist/utils/index.d.ts +487 -13
- package/dist/utils/index.js +370 -235
- package/dist/utils/index.js.map +1 -1
- package/package.json +27 -13
- package/dist/actions-CwG-b7fR.d.ts +0 -519
- package/dist/services/index.d.ts +0 -3
- package/dist/services/index.js +0 -1632
- package/dist/services/index.js.map +0 -1
- package/dist/split.enums-Bh24jw8p.d.ts +0 -255
- package/dist/split.schema-DYVP7Wu2.d.ts +0 -958
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/core/errors.ts","../../../src/shared/utils/resilience/retry.ts","../../../src/enums/transaction.enums.ts","../../../src/shared/utils/validators/category-resolver.ts","../../../src/shared/utils/calculators/commission.ts","../../../src/infrastructure/config/resolver.ts","../../../src/enums/monetization.enums.ts","../../../src/core/state-machine/StateMachine.ts","../../../src/enums/subscription.enums.ts","../../../src/enums/settlement.enums.ts","../../../src/enums/escrow.enums.ts","../../../src/enums/split.enums.ts","../../../src/core/state-machine/definitions.ts","../../../src/infrastructure/audit/types.ts","../../../src/application/services/monetization.service.ts","../../../src/application/services/payment.service.ts","../../../src/application/services/transaction.service.ts","../../../src/shared/utils/calculators/commission-split.ts","../../../src/application/services/escrow.service.ts","../../../src/application/services/settlement.service.ts"],"names":["result","nanoid","auditEvent","retry"],"mappings":";;;;;;AAeO,IAAM,YAAA,GAAN,cAA2B,KAAA,CAAM;AAAA,EACtB,IAAA;AAAA,EACA,SAAA;AAAA,EACA,QAAA;AAAA,EAEhB,WAAA,CACE,OAAA,EACA,IAAA,EACA,OAAA,GAA+B,EAAC,EAChC;AACA,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,KAAK,WAAA,CAAY,IAAA;AAC7B,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AACZ,IAAA,IAAA,CAAK,SAAA,GAAY,QAAQ,SAAA,IAAa,KAAA;AACtC,IAAA,IAAA,CAAK,QAAA,GAAW,OAAA,CAAQ,QAAA,IAAY,EAAC;AACrC,IAAA,KAAA,CAAM,iBAAA,CAAkB,IAAA,EAAM,IAAA,CAAK,WAAW,CAAA;AAAA,EAChD;AAAA,EAEA,MAAA,GAAkC;AAChC,IAAA,OAAO;AAAA,MACL,MAAM,IAAA,CAAK,IAAA;AAAA,MACX,SAAS,IAAA,CAAK,OAAA;AAAA,MACd,MAAM,IAAA,CAAK,IAAA;AAAA,MACX,WAAW,IAAA,CAAK,SAAA;AAAA,MAChB,UAAU,IAAA,CAAK;AAAA,KACjB;AAAA,EACF;AACF,CAAA;AAKO,IAAM,kBAAA,GAAN,cAAiC,YAAA,CAAa;AAAA,EACnD,WAAA,CAAY,OAAA,EAAiB,QAAA,GAAoC,EAAC,EAAG;AACnE,IAAA,KAAA,CAAM,SAAS,qBAAA,EAAuB,EAAE,SAAA,EAAW,KAAA,EAAO,UAAU,CAAA;AAAA,EACtE;AACF,CAAA;AAEO,IAAM,uBAAA,GAAN,cAAsC,kBAAA,CAAmB;AAAA,EAC9D,YAAY,SAAA,EAAmB;AAC7B,IAAA,KAAA;AAAA,MACE,CAAA,OAAA,EAAU,SAAS,CAAA,+DAAA,EAAkE,SAAS,CAAA,UAAA,CAAA;AAAA,MAC9F,EAAE,SAAA;AAAU,KACd;AAAA,EACF;AACF,CAAA;AAKO,IAAM,aAAA,GAAN,cAA4B,YAAA,CAAa;AAAA,EAC9C,WAAA,CACE,OAAA,EACA,IAAA,EACA,OAAA,GAA+B,EAAC,EAChC;AACA,IAAA,KAAA,CAAM,OAAA,EAAS,MAAM,OAAO,CAAA;AAAA,EAC9B;AACF,CAAA;AAEO,IAAM,qBAAA,GAAN,cAAoC,aAAA,CAAc;AAAA,EACvD,WAAA,CAAY,YAAA,EAAsB,kBAAA,GAA+B,EAAC,EAAG;AACnE,IAAA,KAAA;AAAA,MACE,qBAAqB,YAAY,CAAA,wBAAA,EAA2B,kBAAA,CAAmB,IAAA,CAAK,IAAI,CAAC,CAAA,CAAA;AAAA,MACzF,oBAAA;AAAA,MACA,EAAE,SAAA,EAAW,KAAA,EAAO,UAAU,EAAE,YAAA,EAAc,oBAAmB;AAAE,KACrE;AAAA,EACF;AACF,CAAA;AAEO,IAAM,uBAAA,GAAN,cAAsC,aAAA,CAAc;AAAA,EACzD,WAAA,CAAY,cAAsB,UAAA,EAAoB;AACpD,IAAA,KAAA;AAAA,MACE,CAAA,UAAA,EAAa,YAAY,CAAA,mBAAA,EAAsB,UAAU,CAAA,CAAA;AAAA,MACzD,mCAAA;AAAA,MACA,EAAE,SAAA,EAAW,KAAA,EAAO,UAAU,EAAE,YAAA,EAAc,YAAW;AAAE,KAC7D;AAAA,EACF;AACF,CAAA;AAEO,IAAM,0BAAA,GAAN,cAAyC,aAAA,CAAc;AAAA,EAC5D,WAAA,CAAY,cAAsB,aAAA,EAAsB;AACtD,IAAA,KAAA;AAAA,MACE,CAAA,+CAAA,EAAkD,YAAY,CAAA,GAAA,EAAM,aAAA,CAAc,OAAO,CAAA,CAAA;AAAA,MACzF,gCAAA;AAAA,MACA,EAAE,WAAW,IAAA,EAAM,QAAA,EAAU,EAAE,YAAA,EAAc,aAAA,EAAe,aAAA,CAAc,OAAA,EAAQ;AAAE,KACtF;AAAA,EACF;AACF,CAAA;AAEO,IAAM,wBAAA,GAAN,cAAuC,aAAA,CAAc;AAAA,EAC1D,WAAA,CAAY,iBAAyB,MAAA,EAAgB;AACnD,IAAA,KAAA;AAAA,MACE,CAAA,wCAAA,EAA2C,eAAe,CAAA,GAAA,EAAM,MAAM,CAAA,CAAA;AAAA,MACtE,6BAAA;AAAA,MACA,EAAE,SAAA,EAAW,IAAA,EAAM,UAAU,EAAE,eAAA,EAAiB,QAAO;AAAE,KAC3D;AAAA,EACF;AACF,CAAA;AAKO,IAAM,aAAA,GAAN,cAA4B,YAAA,CAAa;AAAA,EAC9C,WAAA,CACE,OAAA,EACA,IAAA,EACA,QAAA,GAAoC,EAAC,EACrC;AACA,IAAA,KAAA,CAAM,SAAS,IAAA,EAAM,EAAE,SAAA,EAAW,KAAA,EAAO,UAAU,CAAA;AAAA,EACrD;AACF,CAAA;AAEO,IAAM,yBAAA,GAAN,cAAwC,aAAA,CAAc;AAAA,EAC3D,YAAY,cAAA,EAAwB;AAClC,IAAA,KAAA;AAAA,MACE,2BAA2B,cAAc,CAAA,CAAA;AAAA,MACzC,wBAAA;AAAA,MACA,EAAE,cAAA;AAAe,KACnB;AAAA,EACF;AACF,CAAA;AAEO,IAAM,wBAAA,GAAN,cAAuC,aAAA,CAAc;AAAA,EAC1D,YAAY,aAAA,EAAuB;AACjC,IAAA,KAAA;AAAA,MACE,0BAA0B,aAAa,CAAA,CAAA;AAAA,MACvC,uBAAA;AAAA,MACA,EAAE,aAAA;AAAc,KAClB;AAAA,EACF;AACF,CAAA;AAKO,IAAM,eAAA,GAAN,cAA8B,YAAA,CAAa;AAAA,EAChD,WAAA,CAAY,OAAA,EAAiB,QAAA,GAAoC,EAAC,EAAG;AACnE,IAAA,KAAA,CAAM,SAAS,kBAAA,EAAoB,EAAE,SAAA,EAAW,KAAA,EAAO,UAAU,CAAA;AAAA,EACnE;AACF,CAAA;AAEO,IAAM,kBAAA,GAAN,cAAiC,eAAA,CAAgB;AAAA,EACtD,WAAA,CAAY,QAAgB,OAAA,EAAkB;AAC5C,IAAA,KAAA;AAAA,MACE,OAAA,IAAW,mBAAmB,MAAM,CAAA,6BAAA,CAAA;AAAA,MACpC,EAAE,MAAA;AAAO,KACX;AAAA,EACF;AACF,CAAA;AAEO,IAAM,yBAAA,GAAN,cAAwC,eAAA,CAAgB;AAAA,EAC7D,YAAY,SAAA,EAAmB;AAC7B,IAAA,KAAA,CAAM,CAAA,wBAAA,EAA2B,SAAS,CAAA,CAAA,EAAI,EAAE,WAAW,CAAA;AAAA,EAC7D;AACF,CAAA;AAKO,IAAM,UAAA,GAAN,cAAyB,YAAA,CAAa;AAAA,EAC3C,WAAA,CACE,OAAA,EACA,IAAA,EACA,QAAA,GAAoC,EAAC,EACrC;AACA,IAAA,KAAA,CAAM,SAAS,IAAA,EAAM,EAAE,SAAA,EAAW,KAAA,EAAO,UAAU,CAAA;AAAA,EACrD;AACF,CAAA;AAEO,IAAM,oBAAA,GAAN,cAAmC,UAAA,CAAW;AAAA,EACnD,YAAY,aAAA,EAAuB;AACjC,IAAA,KAAA;AAAA,MACE,eAAe,aAAa,CAAA,oBAAA,CAAA;AAAA,MAC5B,kBAAA;AAAA,MACA,EAAE,aAAA;AAAc,KAClB;AAAA,EACF;AACF,CAAA;AAEO,IAAM,2BAAA,GAAN,cAA0C,UAAA,CAAW;AAAA,EAC1D,WAAA,CACE,YAAA,EACA,UAAA,EACA,SAAA,EACA,OAAA,EACA;AACA,IAAA,KAAA;AAAA,MACE,gCAAgC,YAAY,CAAA,CAAA,EAAI,UAAU,CAAA,EAAA,EAAK,SAAS,WAAM,OAAO,CAAA,CAAA;AAAA,MACrF,0BAAA;AAAA,MACA,EAAE,YAAA,EAAc,UAAA,EAAY,SAAA,EAAW,OAAA;AAAQ,KACjD;AAAA,EACF;AACF,CAAA;AAEO,IAAM,0BAAA,GAAN,cAAyC,UAAA,CAAW;AAAA,EACzD,WAAA,CAAY,gBAAwB,OAAA,EAAkB;AACpD,IAAA,KAAA;AAAA,MACE,OAAA,IAAW,gBAAgB,cAAc,CAAA,cAAA,CAAA;AAAA,MACzC,yBAAA;AAAA,MACA,EAAE,cAAA;AAAe,KACnB;AAAA,EACF;AACF,CAAA;AAKO,IAAM,cAAA,GAAN,cAA6B,YAAA,CAAa;AAAA,EAC/C,WAAA,CACE,OAAA,EACA,IAAA,EACA,OAAA,GAA+B,EAAC,EAChC;AACA,IAAA,KAAA,CAAM,OAAA,EAAS,MAAM,OAAO,CAAA;AAAA,EAC9B;AACF,CAAA;AAEO,IAAM,uBAAA,GAAN,cAAsC,cAAA,CAAe;AAAA,EAC1D,YAAY,YAAA,EAAsB;AAChC,IAAA,KAAA;AAAA,MACE,0CAA0C,YAAY,CAAA,CAAA,CAAA;AAAA,MACtD,sBAAA;AAAA,MACA,EAAE,SAAA,EAAW,KAAA,EAAO,QAAA,EAAU,EAAE,cAAa;AAAE,KACjD;AAAA,EACF;AACF,CAAA;AAEO,IAAM,WAAA,GAAN,cAA0B,cAAA,CAAe;AAAA,EAC9C,WAAA,CAAY,eAAuB,MAAA,EAAgB;AACjD,IAAA,KAAA;AAAA,MACE,CAAA,8BAAA,EAAiC,aAAa,CAAA,EAAA,EAAK,MAAM,CAAA,CAAA;AAAA,MACzD,eAAA;AAAA,MACA,EAAE,SAAA,EAAW,IAAA,EAAM,UAAU,EAAE,aAAA,EAAe,QAAO;AAAE,KACzD;AAAA,EACF;AACF,CAAA;;;ACtNA,IAAM,cAAA,GAA8B;AAAA,EAClC,WAAA,EAAa,CAAA;AAAA,EACb,SAAA,EAAW,GAAA;AAAA,EACX,QAAA,EAAU,GAAA;AAAA,EACV,iBAAA,EAAmB,CAAA;AAAA,EACnB,MAAA,EAAQ,GAAA;AAAA,EACR,OAAA,EAAS;AACX,CAAA;AAOO,SAAS,cAAA,CACd,SACA,MAAA,EACQ;AAER,EAAA,MAAM,mBAAmB,MAAA,CAAO,SAAA,GAAY,KAAK,GAAA,CAAI,MAAA,CAAO,mBAAmB,OAAO,CAAA;AAGtF,EAAA,MAAM,WAAA,GAAc,IAAA,CAAK,GAAA,CAAI,gBAAA,EAAkB,OAAO,QAAQ,CAAA;AAG9D,EAAA,MAAM,WAAA,GAAc,cAAc,MAAA,CAAO,MAAA;AACzC,EAAA,MAAM,MAAA,GAAS,IAAA,CAAK,MAAA,EAAO,GAAI,cAAc,CAAA,GAAI,WAAA;AAEjD,EAAA,OAAO,KAAK,KAAA,CAAM,IAAA,CAAK,IAAI,CAAA,EAAG,WAAA,GAAc,MAAM,CAAC,CAAA;AACrD;AAKO,SAAS,MAAM,EAAA,EAA2B;AAC/C,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAA,OAAA,KAAW,UAAA,CAAW,OAAA,EAAS,EAAE,CAAC,CAAA;AACvD;AAKO,SAAS,iBAAiB,KAAA,EAAyB;AACxD,EAAA,IAAI,EAAE,KAAA,YAAiB,KAAA,CAAA,EAAQ,OAAO,KAAA;AAGtC,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,QAAA,CAAS,cAAc,GAAG,OAAO,IAAA;AACnD,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,QAAA,CAAS,WAAW,GAAG,OAAO,IAAA;AAChD,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,QAAA,CAAS,WAAW,GAAG,OAAO,IAAA;AAChD,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,QAAA,CAAS,SAAS,GAAG,OAAO,IAAA;AAC9C,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,QAAA,CAAS,SAAS,GAAG,OAAO,IAAA;AAG9C,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,QAAA,CAAS,KAAK,GAAG,OAAO,IAAA;AAC1C,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,QAAA,CAAS,YAAY,GAAG,OAAO,IAAA;AAGjD,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,QAAA,CAAS,KAAK,GAAG,OAAO,IAAA;AAC1C,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,QAAA,CAAS,KAAK,GAAG,OAAO,IAAA;AAC1C,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,QAAA,CAAS,KAAK,GAAG,OAAO,IAAA;AAC1C,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,QAAA,CAAS,KAAK,GAAG,OAAO,IAAA;AAG1C,EAAA,IAAI,WAAA,IAAe,KAAA,IAAU,KAAA,CAAc,SAAA,KAAc,MAAM,OAAO,IAAA;AAEtE,EAAA,OAAO,KAAA;AACT;AAKA,eAAsB,KAAA,CACpB,SAAA,EACA,MAAA,GAA+B,EAAC,EACpB;AACZ,EAAA,MAAM,UAAA,GAA0B,EAAE,GAAG,cAAA,EAAgB,GAAG,MAAA,EAAO;AAC/D,EAAA,MAAM,KAAA,GAAoB;AAAA,IACxB,OAAA,EAAS,CAAA;AAAA,IACT,UAAA,EAAY,CAAA;AAAA,IACZ,QAAQ;AAAC,GACX;AAEA,EAAA,OAAO,KAAA,CAAM,OAAA,GAAU,UAAA,CAAW,WAAA,EAAa;AAC7C,IAAA,IAAI;AACF,MAAA,OAAO,MAAM,SAAA,EAAU;AAAA,IACzB,SAAS,KAAA,EAAO;AACd,MAAA,KAAA,CAAM,MAAA,CAAO,IAAA,CAAK,KAAA,YAAiB,KAAA,GAAQ,KAAA,GAAQ,IAAI,KAAA,CAAM,MAAA,CAAO,KAAK,CAAC,CAAC,CAAA;AAC3E,MAAA,KAAA,CAAM,OAAA,EAAA;AAGN,MAAA,MAAM,cAAc,UAAA,CAAW,OAAA,GAAU,KAAK,CAAA,IAAK,iBAAiB,KAAK,CAAA;AAEzE,MAAA,IAAI,CAAC,WAAA,IAAe,KAAA,CAAM,OAAA,IAAW,WAAW,WAAA,EAAa;AAC3D,QAAA,MAAM,IAAI,mBAAA;AAAA,UACR,CAAA,uBAAA,EAA0B,MAAM,OAAO,CAAA,SAAA,CAAA;AAAA,UACvC,KAAA,CAAM;AAAA,SACR;AAAA,MACF;AAGA,MAAA,MAAM,KAAA,GAAQ,cAAA,CAAe,KAAA,CAAM,OAAA,GAAU,GAAG,UAAU,CAAA;AAC1D,MAAA,KAAA,CAAM,UAAA,IAAc,KAAA;AAGpB,MAAA,UAAA,CAAW,OAAA,GAAU,KAAA,EAAO,KAAA,CAAM,OAAA,EAAS,KAAK,CAAA;AAGhD,MAAA,MAAM,MAAM,KAAK,CAAA;AAAA,IACnB;AAAA,EACF;AAGA,EAAA,MAAM,IAAI,mBAAA;AAAA,IACR,CAAA,uBAAA,EAA0B,MAAM,OAAO,CAAA,SAAA,CAAA;AAAA,IACvC,KAAA,CAAM;AAAA,GACR;AACF;AA2BO,IAAM,mBAAA,GAAN,cAAkC,KAAA,CAAM;AAAA,EAC7B,QAAA;AAAA,EACA,MAAA;AAAA,EAEhB,WAAA,CAAY,SAAiB,MAAA,EAAiB;AAC5C,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,qBAAA;AACZ,IAAA,IAAA,CAAK,WAAW,MAAA,CAAO,MAAA;AACvB,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,SAAA,GAA+B;AACjC,IAAA,OAAO,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,MAAA,CAAO,SAAS,CAAC,CAAA;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,UAAA,GAAgC;AAClC,IAAA,OAAO,IAAA,CAAK,OAAO,CAAC,CAAA;AAAA,EACtB;AACF,CAAA;;;AC9KO,IAAM,gBAAA,GAAmB;AAAA,EAC9B,MAAA,EAAQ,QAAA;AAAA,EACR,OAAA,EAAS;AACX,CAAA;AAOO,IAAM,0BAA0B,MAAA,CAAO,MAAA;AAAA,EAC5C;AACF,CAAA;AAaO,IAAM,kBAAA,GAAqB;AAAA,EAChC,OAAA,EAAS,SAAA;AAAA,EACT,iBAAA,EAAmB,mBAAA;AAAA,EACnB,UAAA,EAAY,YAAA;AAAA,EACZ,eAAA,EAAiB,iBAAA;AAAA,EACjB,QAAA,EAAU,UAAA;AAAA,EACV,SAAA,EAAW,WAAA;AAAA,EACX,MAAA,EAAQ,QAAA;AAAA,EACR,SAAA,EAAW,WAAA;AAAA,EACX,OAAA,EAAS,SAAA;AAAA,EACT,QAAA,EAAU,UAAA;AAAA,EACV,kBAAA,EAAoB;AACtB,CAAA;AAIO,IAAM,4BAA4B,MAAA,CAAO,MAAA;AAAA,EAC9C;AACF,CAAA;AAqBO,IAAM,kBAAA,GAAqB;AAAA,EAChC,YAAA,EAAc,cAAA;AAAA,EACd,QAAA,EAAU;AACZ,CAAA;AAIO,IAAM,0BAA0B,MAAA,CAAO,MAAA;AAAA,EAC5C;AACF,CAAA;AAE2B,IAAI,GAAA,CAA0B,uBAAuB;AACnD,IAAI,GAAA;AAAA,EAC/B;AACF;AAC2B,IAAI,GAAA,CAA0B,uBAAuB;;;AC/DzE,SAAS,eAAA,CACd,MAAA,EACA,gBAAA,EACA,gBAAA,GAA2C,EAAC,EACpC;AAER,EAAA,IAAI,MAAA,IAAU,gBAAA,CAAiB,MAAM,CAAA,EAAG;AACtC,IAAA,OAAO,iBAAiB,MAAM,CAAA;AAAA,EAChC;AAGA,EAAA,QAAQ,gBAAA;AAAkB,IACxB,KAAK,cAAA;AACH,MAAA,OAAO,kBAAA,CAAmB,YAAA;AAAA;AAAA,IAC5B,KAAK,UAAA;AACH,MAAA,OAAO,kBAAA,CAAmB,QAAA;AAAA;AAAA,IAC5B;AACE,MAAA,OAAO,kBAAA,CAAmB,YAAA;AAAA;AAEhC;;;AC9CO,SAAS,mBAAA,CACd,MAAA,EACA,cAAA,EACA,cAAA,GAAyB,CAAA,EACF;AAEvB,EAAA,IAAI,CAAC,cAAA,IAAkB,cAAA,IAAkB,CAAA,EAAG;AAC1C,IAAA,OAAO,IAAA;AAAA,EACT;AAGA,EAAA,IAAI,SAAS,CAAA,EAAG;AACd,IAAA,MAAM,IAAI,MAAM,uCAAuC,CAAA;AAAA,EACzD;AAEA,EAAA,IAAI,cAAA,GAAiB,CAAA,IAAK,cAAA,GAAiB,CAAA,EAAG;AAC5C,IAAA,MAAM,IAAI,MAAM,yCAAyC,CAAA;AAAA,EAC3D;AAEA,EAAA,IAAI,cAAA,GAAiB,CAAA,IAAK,cAAA,GAAiB,CAAA,EAAG;AAC5C,IAAA,MAAM,IAAI,MAAM,0CAA0C,CAAA;AAAA,EAC5D;AAGA,EAAA,MAAM,WAAA,GAAc,IAAA,CAAK,KAAA,CAAM,MAAA,GAAS,cAAc,CAAA;AACtD,EAAA,MAAM,gBAAA,GAAmB,IAAA,CAAK,KAAA,CAAM,MAAA,GAAS,cAAc,CAAA;AAC3D,EAAA,MAAM,SAAA,GAAY,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,cAAc,gBAAgB,CAAA;AAE5D,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,cAAA;AAAA,IACN,WAAA;AAAA,IACA,cAAA;AAAA,IACA,gBAAA;AAAA,IACA,SAAA;AAAA,IACA,MAAA,EAAQ;AAAA,GACV;AACF;AAUO,SAAS,iBAAA,CACd,kBAAA,EACA,cAAA,EACA,YAAA,EACuB;AACvB,EAAA,IAAI,CAAC,oBAAoB,SAAA,EAAW;AAClC,IAAA,OAAO,IAAA;AAAA,EACT;AAGA,EAAA,IAAI,CAAC,cAAA,IAAkB,cAAA,IAAkB,CAAA,EAAG;AAC1C,IAAA,MAAM,IAAI,eAAA,CAAgB,wCAAA,EAA0C,EAAE,gBAAgB,CAAA;AAAA,EACxF;AAEA,EAAA,IAAI,eAAe,CAAA,EAAG;AACpB,IAAA,MAAM,IAAI,eAAA,CAAgB,kCAAA,EAAoC,EAAE,cAAc,CAAA;AAAA,EAChF;AAEA,EAAA,IAAI,eAAe,cAAA,EAAgB;AACjC,IAAA,MAAM,IAAI,eAAA;AAAA,MACR,CAAA,eAAA,EAAkB,YAAY,CAAA,2BAAA,EAA8B,cAAc,CAAA,CAAA,CAAA;AAAA,MAC1E,EAAE,cAAc,cAAA;AAAe,KACjC;AAAA,EACF;AAGA,EAAA,MAAM,cAAc,YAAA,GAAe,cAAA;AACnC,EAAA,MAAM,iBAAA,GAAoB,IAAA,CAAK,KAAA,CAAM,kBAAA,CAAmB,YAAY,WAAW,CAAA;AAC/E,EAAA,MAAM,mBAAA,GAAsB,IAAA,CAAK,KAAA,CAAM,kBAAA,CAAmB,cAAc,WAAW,CAAA;AACnF,EAAA,MAAM,kBAAA,GAAqB,IAAA,CAAK,KAAA,CAAM,kBAAA,CAAmB,mBAAmB,WAAW,CAAA;AAEvF,EAAA,OAAO;AAAA,IACL,MAAM,kBAAA,CAAmB,IAAA;AAAA,IACzB,WAAA,EAAa,mBAAA;AAAA,IACb,gBAAgB,kBAAA,CAAmB,cAAA;AAAA,IACnC,gBAAA,EAAkB,kBAAA;AAAA,IAClB,SAAA,EAAW,iBAAA;AAAA,IACX,MAAA,EAAQ;AAAA;AAAA,GACV;AACF;;;ACvBO,SAAS,iBAAA,CACd,QACA,QAAA,EACQ;AACR,EAAA,IAAI,CAAC,MAAA,EAAQ,eAAA,EAAiB,OAAO,CAAA;AAGrC,EAAA,IAAI,QAAA,IAAY,OAAO,eAAA,EAAiB;AACtC,IAAA,OAAO,MAAA,CAAO,gBAAgB,QAAQ,CAAA;AAAA,EACxC;AAGA,EAAA,OAAO,MAAA,CAAO,eAAA,CAAgB,GAAG,CAAA,IAAK,CAAA;AACxC;AAWO,SAAS,iBAAA,CACd,QACA,OAAA,EACQ;AACR,EAAA,IAAI,CAAC,MAAA,EAAQ,eAAA,EAAiB,OAAO,CAAA;AAGrC,EAAA,IAAI,OAAA,IAAW,OAAO,eAAA,EAAiB;AACrC,IAAA,OAAO,MAAA,CAAO,gBAAgB,OAAO,CAAA;AAAA,EACvC;AAGA,EAAA,OAAO,MAAA,CAAO,eAAA,CAAgB,GAAG,CAAA,IAAK,CAAA;AACxC;;;AC7GO,IAAM,kBAAA,GAAqB;AAAA,EAChC,IAAA,EAAM,MAAA;AAAA,EACN,QAAA,EAAU,UAAA;AAAA,EACV,YAAA,EAAc;AAChB,CAAA;AAIO,IAAM,2BAA2B,MAAA,CAAO,MAAA;AAAA,EAC7C;AACF,CAAA;AAE4B,IAAI,GAAA,CAA2B,wBAAwB;;;ACiB5E,IAAM,eAAN,MAA0C;AAAA;AAAA;AAAA;AAAA;AAAA,EAK/C,WAAA,CACmB,aACA,YAAA,EACjB;AAFiB,IAAA,IAAA,CAAA,WAAA,GAAA,WAAA;AACA,IAAA,IAAA,CAAA,YAAA,GAAA,YAAA;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAqBH,QAAA,CACE,IAAA,EACA,EAAA,EACA,UAAA,EACM;AACN,IAAA,MAAM,kBAAA,GAAqB,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,IAAI,CAAA;AAEpD,IAAA,IAAI,CAAC,kBAAA,EAAoB,GAAA,CAAI,EAAE,CAAA,EAAG;AAChC,MAAA,MAAM,IAAI,2BAAA;AAAA,QACR,IAAA,CAAK,YAAA;AAAA,QACL,UAAA;AAAA,QACA,IAAA;AAAA,QACA;AAAA,OACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,aAAA,CAAc,MAAc,EAAA,EAAqB;AAC/C,IAAA,OAAO,KAAK,WAAA,CAAY,GAAA,CAAI,IAAI,CAAA,EAAG,GAAA,CAAI,EAAE,CAAA,IAAK,KAAA;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,sBAAsB,IAAA,EAAwB;AAC5C,IAAA,OAAO,KAAA,CAAM,KAAK,IAAA,CAAK,WAAA,CAAY,IAAI,IAAI,CAAA,IAAK,EAAE,CAAA;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,gBAAgB,KAAA,EAAwB;AACtC,IAAA,MAAM,WAAA,GAAc,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,KAAK,CAAA;AAC9C,IAAA,OAAO,CAAC,WAAA,IAAe,WAAA,CAAY,IAAA,KAAS,CAAA;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,eAAA,GAA0B;AACxB,IAAA,OAAO,IAAA,CAAK,YAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAyCA,2BAAA,CACE,IAAA,EACA,EAAA,EACA,UAAA,EACA,OAAA,EAK0B;AAE1B,IAAA,IAAA,CAAK,QAAA,CAAS,IAAA,EAAM,EAAA,EAAI,UAAU,CAAA;AAGlC,IAAA,OAAO;AAAA,MACL,cAAc,IAAA,CAAK,YAAA;AAAA,MACnB,UAAA;AAAA,MACA,SAAA,EAAW,IAAA;AAAA,MACX,OAAA,EAAS,EAAA;AAAA,MACT,SAAA,sBAAe,IAAA,EAAK;AAAA,MACpB,WAAW,OAAA,EAAS,SAAA;AAAA,MACpB,QAAQ,OAAA,EAAS,MAAA;AAAA,MACjB,UAAU,OAAA,EAAS;AAAA,KACrB;AAAA,EACF;AACF,CAAA;;;ACrMO,IAAM,mBAAA,GAAsB;AAAA,EACjC,MAAA,EAAQ,QAAA;AAAA,EACR,MAAA,EAAQ,QAAA;AAAA,EACR,SAAA,EAAW,WAAA;AAAA,EACX,OAAA,EAAS,SAAA;AAAA,EACT,OAAA,EAAS,SAAA;AAAA,EACT,eAAA,EAAiB,iBAAA;AAAA,EACjB,QAAA,EAAU;AACZ,CAAA;AAIO,IAAM,6BAA6B,MAAA,CAAO,MAAA;AAAA,EAC/C;AACF,CAAA;AAMO,IAAM,SAAA,GAAY;AAAA,EACvB,OAAA,EAAS,SAAA;AAAA,EACT,SAAA,EAAW,WAAA;AAAA,EACX,MAAA,EAAQ;AACV,CAAA;AAIO,IAAM,eAAA,GAAkB,MAAA,CAAO,MAAA,CAAO,SAAS,CAAA;AAExB,IAAI,GAAA;AAAA,EAChC;AACF;AACmB,IAAI,GAAA,CAAkB,eAAe;;;ACnCjD,IAAM,iBAAA,GAAoB;AAAA,EAC/B,OAAA,EAAS,SAAA;AAAA,EACT,UAAA,EAAY,YAAA;AAAA,EACZ,SAAA,EAAW,WAAA;AAAA,EACX,MAAA,EAAQ,QAAA;AAAA,EACR,SAAA,EAAW;AACb,CAAA;AAgBO,IAAM,eAAA,GAAkB;AAAA,EAC7B,YAAA,EAAc,cAIhB,CAAA;;;AC7BO,IAAM,WAAA,GAAc;AAAA,EACzB,OAAA,EAAS,SAAA;AAAA,EACT,IAAA,EAAM,MAAA;AAAA,EACN,QAAA,EAAU,UAAA;AAAA,EACV,SAAA,EAAW,WAAA;AAAA,EACX,OAAA,EAAS,SAAA;AAAA,EACT,kBAAA,EAAoB;AACtB,CAAA;AAIO,IAAM,kBAAA,GAAqB,MAAA,CAAO,MAAA,CAAO,WAAW,CAAA;AAEpD,IAAM,cAAA,GAAiB;AAAA,EAC5B,gBAAA,EAAkB,kBAAA;AAAA,EAClB,cAAA,EAAgB,gBAAA;AAAA,EAChB,YAAA,EAAc,cAAA;AAAA,EACd,gBAAA,EAAkB;AACpB,CAAA;AAIO,IAAM,wBAAwB,MAAA,CAAO,MAAA;AAAA,EAC1C;AACF,CAAA;AAEO,IAAM,WAAA,GAAc;AAAA,EACzB,oBAAA,EAAsB,sBAAA;AAAA,EACtB,WAAA,EAAa,aAAA;AAAA,EACb,aAAA,EAAe,eAAA;AAAA,EACf,OAAA,EAAS,SAAA;AAAA,EACT,UAAA,EAAY;AACd,CAAA;AAIO,IAAM,kBAAA,GAAqB,MAAA,CAAO,MAAA,CAAO,WAAW,CAAA;AAErC,IAAI,GAAA,CAAqB,kBAAkB;AACxC,IAAI,GAAA,CAAwB,qBAAqB;AACpD,IAAI,GAAA,CAAqB,kBAAkB;;;ACxC1D,IAAM,UAAA,GAAa;AAAA,EACxB,mBAAA,EAAqB,qBAAA;AAAA,EACrB,oBAAA,EAAsB,sBAAA;AAAA,EACtB,mBAAA,EAAqB,qBAAA;AAAA,EACrB,kBAAA,EAAoB,oBAAA;AAAA,EACpB,MAAA,EAAQ;AACV,CAAA;AAIO,IAAM,iBAAA,GAAoB,MAAA,CAAO,MAAA,CAAO,UAAU,CAAA;AAElD,IAAM,YAAA,GAAe;AAAA,EAC1B,OAAA,EAAS,SAAA;AAAA,EACT,GAAA,EAAK,KAAA;AAAA,EACL,IAAA,EAAM,MAAA;AAAA,EACN,MAAA,EAAQ,QAAA;AAAA,EACR,SAAA,EAAW;AACb,CAAA;AAIO,IAAM,sBAAsB,MAAA,CAAO,MAAA;AAAA,EACxC;AACF,CAAA;AAEO,IAAM,aAAA,GAAgB;AAAA,EAC3B,aAAA,EAAe,eAAA;AAAA,EACf,aAAA,EAAe,eAAA;AAAA,EACf,gBAAA,EAAkB,kBAAA;AAAA,EAClB,MAAA,EAAQ,QAAA;AAAA,EACR,KAAA,EAAO,OAAA;AAAA,EACP,MAAA,EAAQ;AACV,CAAA;AAIO,IAAM,oBAAA,GAAuB,MAAA,CAAO,MAAA,CAAO,aAAa,CAAA;AAE1C,IAAI,GAAA,CAAoB,iBAAiB;AACvC,IAAI,GAAA,CAAsB,mBAAmB;AAC5C,IAAI,GAAA,CAAuB,oBAAoB;;;ACJhE,IAAM,4BAA4B,IAAI,YAAA;AAAA,sBACvC,GAAA,CAAyD;AAAA,IAC3D;AAAA,MACE,kBAAA,CAAmB,OAAA;AAAA,0BACf,GAAA,CAAI;AAAA,QACN,kBAAA,CAAmB,iBAAA;AAAA,QACnB,kBAAA,CAAmB,UAAA;AAAA,QACnB,kBAAA,CAAmB,QAAA;AAAA;AAAA,QACnB,kBAAA,CAAmB,MAAA;AAAA,QACnB,kBAAA,CAAmB;AAAA,OACpB;AAAA,KACH;AAAA,IACA;AAAA,MACE,kBAAA,CAAmB,iBAAA;AAAA,0BACf,GAAA,CAAI;AAAA,QACN,kBAAA,CAAmB,UAAA;AAAA,QACnB,kBAAA,CAAmB,QAAA;AAAA;AAAA,QACnB,kBAAA,CAAmB,eAAA;AAAA,QACnB,kBAAA,CAAmB,MAAA;AAAA,QACnB,kBAAA,CAAmB;AAAA,OACpB;AAAA,KACH;AAAA,IACA;AAAA,MACE,kBAAA,CAAmB,UAAA;AAAA,0BACf,GAAA,CAAI;AAAA,QACN,kBAAA,CAAmB,QAAA;AAAA,QACnB,kBAAA,CAAmB,eAAA;AAAA,QACnB,kBAAA,CAAmB;AAAA,OACpB;AAAA,KACH;AAAA,IACA;AAAA,MACE,kBAAA,CAAmB,eAAA;AAAA,0BACf,GAAA,CAAI;AAAA,QACN,kBAAA,CAAmB,QAAA;AAAA,QACnB,kBAAA,CAAmB,MAAA;AAAA,QACnB,kBAAA,CAAmB,SAAA;AAAA,QACnB,kBAAA,CAAmB;AAAA,OACpB;AAAA,KACH;AAAA,IACA;AAAA,MACE,kBAAA,CAAmB,QAAA;AAAA,0BACf,GAAA,CAAI;AAAA,QACN,kBAAA,CAAmB,SAAA;AAAA,QACnB,kBAAA,CAAmB,QAAA;AAAA,QACnB,kBAAA,CAAmB,kBAAA;AAAA,QACnB,kBAAA,CAAmB;AAAA,OACpB;AAAA,KACH;AAAA,IACA;AAAA,MACE,kBAAA,CAAmB,SAAA;AAAA,0BACf,GAAA,CAAI;AAAA,QACN,kBAAA,CAAmB,QAAA;AAAA,QACnB,kBAAA,CAAmB;AAAA,OACpB;AAAA,KACH;AAAA,IACA;AAAA,MACE,kBAAA,CAAmB,kBAAA;AAAA,sBACnB,IAAI,GAAA,CAAI,CAAC,kBAAA,CAAmB,QAAQ,CAAC;AAAA,KACvC;AAAA;AAAA,IAEA,CAAC,kBAAA,CAAmB,MAAA,sBAAY,GAAA,CAAI,EAAE,CAAC,CAAA;AAAA,IACvC,CAAC,kBAAA,CAAmB,QAAA,sBAAc,GAAA,CAAI,EAAE,CAAC,CAAA;AAAA,IACzC,CAAC,kBAAA,CAAmB,SAAA,sBAAe,GAAA,CAAI,EAAE,CAAC,CAAA;AAAA,IAC1C,CAAC,kBAAA,CAAmB,OAAA,sBAAa,GAAA,CAAI,EAAE,CAAC;AAAA,GACzC,CAAA;AAAA,EACD;AACF,CAAA;AAgBO,IAAM,6BAA6B,IAAI,YAAA;AAAA,sBACxC,GAAA,CAA2D;AAAA,IAC7D;AAAA,MACE,mBAAA,CAAoB,OAAA;AAAA,0BAChB,GAAA,CAAI;AAAA,QACN,mBAAA,CAAoB,MAAA;AAAA,QACpB,mBAAA,CAAoB;AAAA,OACrB;AAAA,KACH;AAAA,IACA;AAAA,MACE,mBAAA,CAAoB,MAAA;AAAA,0BAChB,GAAA,CAAI;AAAA,QACN,mBAAA,CAAoB,MAAA;AAAA,QACpB,mBAAA,CAAoB,eAAA;AAAA,QACpB,mBAAA,CAAoB,SAAA;AAAA,QACpB,mBAAA,CAAoB;AAAA,OACrB;AAAA,KACH;AAAA,IACA;AAAA,MACE,mBAAA,CAAoB,eAAA;AAAA,0BAChB,GAAA,CAAI;AAAA,QACN,mBAAA,CAAoB,MAAA;AAAA,QACpB,mBAAA,CAAoB,SAAA;AAAA,QACpB,mBAAA,CAAoB;AAAA,OACrB;AAAA,KACH;AAAA,IACA;AAAA,MACE,mBAAA,CAAoB,MAAA;AAAA,0BAChB,GAAA,CAAI;AAAA,QACN,mBAAA,CAAoB,MAAA;AAAA,QACpB,mBAAA,CAAoB;AAAA,OACrB;AAAA,KACH;AAAA,IACA;AAAA,MACE,mBAAA,CAAoB,QAAA;AAAA,0BAChB,GAAA,CAAI;AAAA,QACN,mBAAA,CAAoB,MAAA;AAAA,QACpB,mBAAA,CAAoB;AAAA,OACrB;AAAA,KACH;AAAA;AAAA,IAEA,CAAC,mBAAA,CAAoB,SAAA,sBAAe,GAAA,CAAI,EAAE,CAAC,CAAA;AAAA,IAC3C,CAAC,mBAAA,CAAoB,OAAA,sBAAa,GAAA,CAAI,EAAE,CAAC;AAAA,GAC1C,CAAA;AAAA,EACD;AACF,CAAA;AAeO,IAAM,2BAA2B,IAAI,YAAA;AAAA,sBACtC,GAAA,CAAuD;AAAA,IACzD;AAAA,MACE,iBAAA,CAAkB,OAAA;AAAA,0BACd,GAAA,CAAI;AAAA,QACN,iBAAA,CAAkB,UAAA;AAAA,QAClB,iBAAA,CAAkB;AAAA,OACnB;AAAA,KACH;AAAA,IACA;AAAA,MACE,iBAAA,CAAkB,UAAA;AAAA,0BACd,GAAA,CAAI;AAAA,QACN,iBAAA,CAAkB,SAAA;AAAA,QAClB,iBAAA,CAAkB;AAAA,OACnB;AAAA,KACH;AAAA,IACA;AAAA,MACE,iBAAA,CAAkB,MAAA;AAAA,0BACd,GAAA,CAAI;AAAA,QACN,iBAAA,CAAkB,OAAA;AAAA;AAAA,QAClB,iBAAA,CAAkB;AAAA,OACnB;AAAA,KACH;AAAA;AAAA,IAEA,CAAC,iBAAA,CAAkB,SAAA,sBAAe,GAAA,CAAI,EAAE,CAAC,CAAA;AAAA,IACzC,CAAC,iBAAA,CAAkB,SAAA,sBAAe,GAAA,CAAI,EAAE,CAAC;AAAA,GAC1C,CAAA;AAAA,EACD;AACF,CAAA;AAcO,IAAM,qBAAqB,IAAI,YAAA;AAAA,sBAChC,GAAA,CAA2C;AAAA,IAC7C;AAAA,MACE,WAAA,CAAY,IAAA;AAAA,0BACR,GAAA,CAAI;AAAA,QACN,WAAA,CAAY,QAAA;AAAA,QACZ,WAAA,CAAY,kBAAA;AAAA,QACZ,WAAA,CAAY,SAAA;AAAA,QACZ,WAAA,CAAY;AAAA,OACb;AAAA,KACH;AAAA,IACA;AAAA,MACE,WAAA,CAAY,kBAAA;AAAA,0BACR,GAAA,CAAI;AAAA,QACN,WAAA,CAAY,QAAA;AAAA,QACZ,WAAA,CAAY;AAAA,OACb;AAAA,KACH;AAAA;AAAA,IAEA,CAAC,WAAA,CAAY,QAAA,sBAAc,GAAA,CAAI,EAAE,CAAC,CAAA;AAAA,IAClC,CAAC,WAAA,CAAY,SAAA,sBAAe,GAAA,CAAI,EAAE,CAAC,CAAA;AAAA,IACnC,CAAC,WAAA,CAAY,OAAA,sBAAa,GAAA,CAAI,EAAE,CAAC;AAAA,GAClC,CAAA;AAAA,EACD;AACF,CAAA;;;AC7KO,SAAS,gBAAA,CACd,UACA,KAAA,EACG;AACH,EAAA,MAAM,YAAA,GAAe,QAAA,CAAS,QAAA,EAAU,YAAA,IAAgB,EAAC;AAEzD,EAAA,OAAO;AAAA,IACL,GAAG,QAAA;AAAA,IACH,QAAA,EAAU;AAAA,MACR,GAAG,QAAA,CAAS,QAAA;AAAA,MACZ,YAAA,EAAc,CAAC,GAAG,YAAA,EAAc,KAAK;AAAA;AACvC,GACF;AACF;;;ACnCO,IAAM,sBAAN,MAA0B;AAAA,EACd,MAAA;AAAA,EACA,SAAA;AAAA,EACA,MAAA;AAAA,EACA,OAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EACA,WAAA;AAAA,EACA,cAAA;AAAA,EAEjB,YAAY,SAAA,EAAsB;AAChC,IAAA,IAAA,CAAK,MAAA,GAAS,SAAA,CAAU,GAAA,CAAoB,QAAQ,CAAA;AACpD,IAAA,IAAA,CAAK,SAAA,GAAY,SAAA,CAAU,GAAA,CAAuB,WAAW,CAAA;AAC7D,IAAA,IAAA,CAAK,MAAA,GAAS,SAAA,CAAU,GAAA,CAAmB,QAAQ,CAAA;AACnD,IAAA,IAAA,CAAK,OAAA,GAAU,SAAA,CAAU,GAAA,CAAmB,SAAS,CAAA;AACrD,IAAA,IAAA,CAAK,MAAA,GAAS,SAAA,CAAU,GAAA,CAAY,QAAQ,CAAA;AAC5C,IAAA,IAAA,CAAK,MAAA,GAAS,SAAA,CAAU,GAAA,CAAc,QAAQ,CAAA;AAC9C,IAAA,IAAA,CAAK,WAAA,GAAc,SAAA,CAAU,GAAA,CAA0B,aAAa,CAAA;AACpE,IAAA,IAAA,CAAK,cAAA,GAAiB,SAAA,CAAU,GAAA,CAA2B,gBAAgB,CAAA;AAAA,EAC7E;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,iBAAiB,cAAA,EAA+C;AACtE,IAAA,OAAO;AAAA,MACL,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,OAAA,sBAAa,GAAA,EAAI;AAAA,MACjB,IAAA,EAAM;AAAA,QACJ,gBAAgB,cAAA,IAAkB,MAAA;AAAA,QAClC,WAAW,MAAA,EAAO;AAAA,QAClB,SAAA,sBAAe,IAAA;AAAK;AACtB,KACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,mBAAA,CACZ,SAAA,EACA,aAAA,EACY;AAEZ,IAAA,MAAM,kBAAA,GAAqB,KAAK,cAAA,GAC5B,MAAM,KAAK,cAAA,CAAgB,OAAA,CAAQ,SAAS,CAAA,GAC5C,SAAA;AAGJ,IAAA,IAAI,IAAA,CAAK,eAAe,MAAA,CAAO,IAAA,CAAK,KAAK,WAAW,CAAA,CAAE,SAAS,CAAA,EAAG;AAChE,MAAA,OAAO,MAAM,kBAAA,EAAoB;AAAA,QAC/B,GAAG,IAAA,CAAK,WAAA;AAAA,QACR,OAAA,EAAS,CAAC,KAAA,EAAO,OAAA,EAAS,KAAA,KAAU;AAClC,UAAA,IAAA,CAAK,MAAA,CAAO,IAAA;AAAA,YACV,CAAA,CAAA,EAAI,aAAa,CAAA,gBAAA,EAAmB,OAAO,UAAU,KAAK,CAAA,GAAA,CAAA;AAAA,YAC1D;AAAA,WACF;AACA,UAAA,IAAA,CAAK,WAAA,CAAY,OAAA,GAAU,KAAA,EAAO,OAAA,EAAS,KAAK,CAAA;AAAA,QAClD;AAAA,OACD,CAAA;AAAA,IACH;AAEA,IAAA,OAAO,kBAAA,EAAmB;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsCA,MAAM,OAAO,MAAA,EAAqE;AAEhF,IAAA,OAAO,KAAK,OAAA,CAAQ,WAAA;AAAA,MAClB,4BAAA;AAAA,MACA,IAAA,CAAK,gBAAA,CAAiB,MAAA,CAAO,cAAc,CAAA;AAAA,MAC3C,MAAA;AAAA,MACA,YAAY;AACV,QAAA,MAAM;AAAA,UACJ,IAAA;AAAA,UACA,OAAA;AAAA,UACA,MAAA;AAAA,UACA,QAAA,GAAW,KAAA;AAAA,UACX,OAAA,GAAU,QAAA;AAAA,UACV,MAAA,GAAS,IAAA;AAAA,UACT,mBAAmB,kBAAA,CAAmB,YAAA;AAAA,UACtC,WAAA;AAAA,UACA,WAAW,EAAC;AAAA,UACZ,cAAA,GAAiB;AAAA,SACnB,GAAI,MAAA;AAKJ,QAAA,IAAI,CAAC,OAAA,EAAS;AACZ,UAAA,MAAM,IAAI,0BAA0B,SAAS,CAAA;AAAA,QAC/C;AAEA,QAAA,IAAI,SAAS,CAAA,EAAG;AACd,UAAA,MAAM,IAAI,mBAAmB,MAAM,CAAA;AAAA,QACrC;AAEA,QAAA,MAAM,SAAS,MAAA,KAAW,CAAA;AAG9B,QAAA,MAAM,QAAA,GAAW,IAAA,CAAK,SAAA,CAAU,OAAO,CAAA;AACvC,QAAA,IAAI,CAAC,QAAA,EAAU;AACb,UAAA,MAAM,IAAI,qBAAA,CAAsB,OAAA,EAAS,OAAO,IAAA,CAAK,IAAA,CAAK,SAAS,CAAC,CAAA;AAAA,QACtE;AAGA,QAAA,IAAI,aAAA,GAA0C,IAAA;AAC9C,QAAA,IAAI,WAAA,GAA0C,IAAA;AAE9C,QAAA,IAAI,CAAC,MAAA,EAAQ;AAEX,UAAA,IAAI;AACF,YAAA,aAAA,GAAgB,MAAM,IAAA,CAAK,mBAAA;AAAA,cACzB,MAAM,SAAS,YAAA,CAAa;AAAA,gBAC1B,MAAA;AAAA,gBACA,QAAA;AAAA,gBACA,QAAA,EAAU;AAAA,kBACR,GAAG,QAAA;AAAA,kBACH,IAAA,EAAM,cAAA;AAAA,kBACN;AAAA;AACF,eACD,CAAA;AAAA,cACD,GAAG,OAAO,CAAA,aAAA;AAAA,aACZ;AAAA,UACF,SAAS,KAAA,EAAO;AACd,YAAA,MAAM,IAAI,0BAAA,CAA2B,OAAA,EAAS,KAAc,CAAA;AAAA,UAC9D;AAGA,UAAA,MAAM,WAAW,eAAA,CAAgB,MAAA,EAAQ,gBAAA,EAAkB,IAAA,CAAK,OAAO,gBAAgB,CAAA;AAGvF,UAAA,MAAM,eAAA,GACJ,IAAA,CAAK,MAAA,CAAO,sBAAA,GAAyB,QAAQ,CAAA,IAC7C,IAAA,CAAK,MAAA,CAAO,sBAAA,GAAyB,gBAAgB,CAAA,IACrD,gBAAA,CAAiB,MAAA;AAGnB,UAAA,MAAM,cAAA,GAAiB,iBAAA,CAAkB,IAAA,CAAK,MAAA,EAAQ,QAAQ,CAAA;AAC9D,UAAA,MAAM,cAAA,GAAiB,iBAAA,CAAkB,IAAA,CAAK,MAAA,EAAQ,OAAO,CAAA;AAC7D,UAAA,MAAM,UAAA,GAAa,mBAAA,CAAoB,MAAA,EAAQ,cAAA,EAAgB,cAAc,CAAA;AAG7E,UAAA,MAAM,MAAM,MAAA,CAAO,GAAA;AAGnB,UAAA,MAAM,gBAAA,GAAmB,KAAK,MAAA,CAAO,WAAA;AAIrC,UAAA,MAAM,UAAA,GAAa,GAAA,EAAK,gBAAA,GAAmB,GAAA,CAAI,UAAA,GAAa,MAAA;AAC5D,UAAA,MAAM,SAAA,GAAY,YAAY,gBAAA,IAAoB,CAAA;AAClD,UAAA,MAAM,SAAA,GAAY,KAAK,SAAA,IAAa,CAAA;AACpC,UAAA,MAAM,SAAA,GAAY,aAAa,SAAA,GAAY,SAAA;AAE3C,UAAA,WAAA,GAAc,MAAM,iBAAiB,MAAA,CAAO;AAAA,YAC1C,gBAAgB,IAAA,CAAK,cAAA;AAAA,YACrB,UAAA,EAAY,KAAK,UAAA,IAAc,IAAA;AAAA;AAAA,YAG/B,IAAA,EAAM,QAAA;AAAA;AAAA,YACN,IAAA,EAAM,eAAA;AAAA;AAAA;AAAA,YAGN,MAAM,QAAA,KAAa,cAAA,GAAiB,CAAC,WAAA,EAAa,cAAc,IAAI,EAAC;AAAA;AAAA;AAAA,YAIrE,MAAA,EAAQ,UAAA;AAAA,YACR,QAAA;AAAA,YACA,GAAA,EAAK,SAAA;AAAA,YACL,GAAA,EAAK,SAAA;AAAA,YACL,GAAA,EAAK,SAAA;AAAA;AAAA,YAGL,GAAI,GAAA,IAAO;AAAA,cACT,UAAA,EAAY;AAAA,gBACV,IAAA,EAAM,IAAI,IAAA,KAAS,WAAA,GAAc,cAAe,GAAA,CAAI,IAAA,KAAS,SAAS,KAAA,GAAQ,MAAA;AAAA,gBAC9E,IAAA,EAAM,IAAI,IAAA,IAAQ,CAAA;AAAA,gBAClB,WAAA,EAAa,IAAI,gBAAA,IAAoB;AAAA;AACvC,aACF;AAAA,YAEA,MAAA,EAAU,aAAyC,MAAA,IAAqB,QAAA;AAAA,YACxE,MAAA,EAAQ,aAAA,CAAc,MAAA,KAAW,WAAA,GAAc,UAAA,GAAa,SAAA;AAAA;AAAA,YAE5D,OAAA,EAAS;AAAA,cACP,IAAA,EAAM,OAAA;AAAA;AAAA,cACN,QAAA,EAAU,OAAA;AAAA,cACV,WAAW,aAAA,CAAc,SAAA;AAAA,cACzB,iBAAiB,aAAA,CAAc,eAAA;AAAA,cAC/B,UAAU,aAAA,CAAc,EAAA;AAAA,cACxB,UAAU,aAAA,CAAc;AAAA,aAC1B;AAAA,YAEA,cAAA,EAAgB;AAAA,cACd,GAAG;AAAA,aACL;AAAA;AAAA,YAGA,GAAI,UAAA,IAAc,EAAE,UAAA,EAAW;AAAA;AAAA,YAG/B,GAAI,IAAA,CAAK,QAAA,IAAY,EAAE,QAAA,EAAU,KAAK,QAAA,EAAS;AAAA,YAC/C,GAAI,IAAA,CAAK,WAAA,IAAe,EAAE,WAAA,EAAa,KAAK,WAAA,EAAY;AAAA,YAExD,QAAA,EAAU;AAAA,cACR,GAAG,QAAA;AAAA,cACH,OAAA;AAAA,cACA,MAAA;AAAA,cACA,gBAAA;AAAA,cACA,iBAAiB,aAAA,CAAc;AAAA,aACjC;AAAA,YAEA,cAAA,EAAgB,cAAA,IAAkB,CAAA,IAAA,EAAO,MAAA,CAAO,EAAE,CAAC,CAAA;AAAA,WACpD,CAAA;AAAA,QACH;AAGA,QAAA,IAAI,YAAA,GAA4C,IAAA;AAChD,QAAA,IAAI,IAAA,CAAK,OAAO,YAAA,EAAc;AAC5B,UAAA,MAAM,iBAAA,GAAoB,KAAK,MAAA,CAAO,YAAA;AAGtC,UAAA,MAAMA,OAAAA,GAAS,MAAM,IAAA,CAAK,OAAA,CAAQ,WAAA;AAAA,YAChC,4BAAA;AAAA,YACA,IAAA,CAAK,iBAAiB,cAAc,CAAA;AAAA,YACpC;AAAA,cACE,cAAA,EAAgB,MAAA;AAAA;AAAA,cAChB,OAAA;AAAA,cACA,YAAY,IAAA,CAAK,UAAA;AAAA,cACjB,gBAAgB,IAAA,CAAK,cAAA;AAAA,cACrB;AAAA,aACF;AAAA,YACA,YAAY;AAEV,cAAA,MAAM,gBAAA,GAAmB;AAAA,gBACvB,gBAAgB,IAAA,CAAK,cAAA;AAAA,gBACrB,UAAA,EAAY,KAAK,UAAA,IAAc,IAAA;AAAA,gBAC/B,OAAA;AAAA,gBACA,MAAA;AAAA,gBACA,QAAA;AAAA,gBACA,MAAA,EAAQ,SAAS,QAAA,GAAW,SAAA;AAAA,gBAC5B,QAAA,EAAU,MAAA;AAAA,gBACV,OAAA;AAAA,gBACA,aAAA,EAAe,aAAa,GAAA,IAAO,IAAA;AAAA,gBACnC,eAAA,EAAiB,eAAe,EAAA,IAAM,IAAA;AAAA,gBACtC,QAAA,EAAU;AAAA,kBACR,GAAG,QAAA;AAAA,kBACH,MAAA;AAAA,kBACA,MAAA;AAAA,kBACA;AAAA,iBACF;AAAA,gBACA,GAAG;AAAA,eACL;AAGA,cAAA,OAAO,gBAAA,CAAiB,QAAA;AACxB,cAAA,OAAO,gBAAA,CAAiB,WAAA;AAExB,cAAA,MAAM,GAAA,GAAM,MAAM,iBAAA,CAAkB,MAAA,CAAO,gBAAgB,CAAA;AAG3D,cAAA,MAAM,KAAK,OAAA,CAAQ,WAAA;AAAA,gBACjB,2BAAA;AAAA,gBACA,IAAA,CAAK,iBAAiB,cAAc,CAAA;AAAA,gBACpC;AAAA,kBACE,cAAA,EAAgB,GAAA,CAAI,GAAA,CAAI,QAAA,EAAS;AAAA,kBACjC,OAAA;AAAA,kBACA,YAAY,IAAA,CAAK,UAAA;AAAA,kBACjB,gBAAgB,IAAA,CAAK,cAAA;AAAA,kBACrB;AAAA,iBACF;AAAA,gBACA,aAAa,EAAE,YAAA,EAAc,GAAA,EAAK,WAAA,EAAY;AAAA,eAChD;AAEA,cAAA,OAAO,EAAE,YAAA,EAAc,GAAA,EAAK,WAAA,EAAY;AAAA,YAC1C;AAAA,WACF;AAEA,UAAA,YAAA,GAAeA,OAAAA,CAAO,YAAA;AAAA,QACxB;AAGA,QAAA,IAAA,CAAK,MAAA,CAAO,KAAK,sBAAA,EAAwB;AAAA,UACvC,gBAAA;AAAA,UACA,cAAc,YAAA,IAAgB,MAAA;AAAA,UAC9B,aAAa,WAAA,IAAe,MAAA;AAAA,UAC5B,eAAe,aAAA,IAAiB;AAAA,SACjC,CAAA;AAGD,QAAA,IAAI,gBAAA,KAAqB,mBAAmB,QAAA,EAAU;AAEpD,UAAA,IAAI,WAAA,EAAa;AACf,YAAA,IAAA,CAAK,MAAA,CAAO,KAAK,kBAAA,EAAoB;AAAA,cACnC,gBAAA;AAAA,cACA,cAAc,YAAA,IAAgB,MAAA;AAAA,cAC9B,WAAA;AAAA,cACA,eAAe,aAAA,IAAiB;AAAA,aACjC,CAAA;AAAA,UACH;AAAA,QACF,CAAA,MAAA,IAAW,gBAAA,KAAqB,kBAAA,CAAmB,YAAA,EAAc;AAE/D,UAAA,IAAI,YAAA,EAAc;AAChB,YAAA,IAAA,CAAK,MAAA,CAAO,KAAK,sBAAA,EAAwB;AAAA,cACvC,cAAA,EAAgB,YAAA,CAAa,GAAA,CAAI,QAAA,EAAS;AAAA,cAC1C,YAAA;AAAA,cACA,aAAA,EAAe,WAAA,EAAa,GAAA,EAAK,QAAA;AAAS,aAC3C,CAAA;AAAA,UACH;AAAA,QACF,CAAA,MAAA,IAAW,gBAAA,KAAqB,kBAAA,CAAmB,IAAA,EAAM;AAEvD,UAAA,IAAA,CAAK,MAAA,CAAO,KAAK,cAAA,EAAgB;AAAA,YAC/B,gBAAA;AAAA,YACA,cAAc,YAAA,IAAgB,MAAA;AAAA,YAC9B,aAAa,WAAA,IAAe,MAAA;AAAA,YAC5B,eAAe,aAAA,IAAiB;AAAA,WACjC,CAAA;AAAA,QACH;AAEA,QAAA,MAAM,MAAA,GAAS;AAAA,UACb,YAAA;AAAA,UACA,WAAA;AAAA,UACA;AAAA,SACF;AAGA,QAAA,OAAO,KAAK,OAAA,CAAQ,WAAA;AAAA,UAClB,2BAAA;AAAA,UACA,IAAA,CAAK,gBAAA,CAAiB,MAAA,CAAO,cAAc,CAAA;AAAA,UAC3C,MAAA;AAAA,UACA,YAAY;AAAA,SACd;AAAA,MACE;AAAA,KACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,QAAA,CACJ,cAAA,EACA,OAAA,GAA2B,EAAC,EACG;AAE/B,IAAA,OAAO,KAAK,OAAA,CAAQ,WAAA;AAAA,MAClB,8BAAA;AAAA,MACA,KAAK,gBAAA,EAAiB;AAAA,MACtB,EAAE,cAAA,EAAgB,GAAG,OAAA,EAAQ;AAAA,MAC7B,YAAY;AACV,QAAA,MAAM,EAAE,SAAA,mBAAY,IAAI,IAAA,IAAO,GAAI,OAAA;AAEnC,QAAA,IAAI,CAAC,IAAA,CAAK,MAAA,CAAO,YAAA,EAAc;AAC7B,UAAA,MAAM,IAAI,wBAAwB,cAAc,CAAA;AAAA,QAClD;AAEA,QAAA,MAAM,iBAAA,GAAoB,KAAK,MAAA,CAAO,YAAA;AACtC,QAAA,MAAM,YAAA,GAAe,MAAM,iBAAA,CAAkB,QAAA,CAAS,cAAc,CAAA;AAEpE,QAAA,IAAI,CAAC,YAAA,EAAc;AACjB,UAAA,MAAM,IAAI,0BAA0B,cAAc,CAAA;AAAA,QACpD;AAEA,QAAA,IAAI,aAAa,QAAA,EAAU;AACzB,UAAA,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,6BAAA,EAA+B,EAAE,gBAAgB,CAAA;AAClE,UAAA,OAAO,YAAA;AAAA,QACT;AAGA,QAAA,MAAM,SAAA,GAAY,IAAA,CAAK,mBAAA,CAAoB,YAAA,CAAa,SAAS,SAAS,CAAA;AAG1E,QAAA,MAAM,aAAa,0BAAA,CAA2B,2BAAA;AAAA,UAC5C,YAAA,CAAa,MAAA;AAAA,UACb,QAAA;AAAA,UACA,YAAA,CAAa,IAAI,QAAA,EAAS;AAAA,UAC1B;AAAA,YACE,SAAA,EAAW,QAAA;AAAA,YACX,MAAA,EAAQ,CAAA,iCAAA,EAAoC,YAAA,CAAa,OAAO,CAAA,CAAA;AAAA,YAChE,QAAA,EAAU,EAAE,OAAA,EAAS,YAAA,CAAa,SAAS,SAAA,EAAW,SAAA,EAAW,SAAS,SAAA;AAAU;AACtF,SACF;AAGA,QAAA,YAAA,CAAa,QAAA,GAAW,IAAA;AACxB,QAAA,YAAA,CAAa,MAAA,GAAS,QAAA;AACtB,QAAA,YAAA,CAAa,SAAA,GAAY,SAAA;AACzB,QAAA,YAAA,CAAa,OAAA,GAAU,SAAA;AACvB,QAAA,YAAA,CAAa,WAAA,GAAc,SAAA;AAG3B,QAAA,MAAA,CAAO,MAAA,CAAO,YAAA,EAAc,gBAAA,CAAiB,YAAA,EAAc,UAAU,CAAC,CAAA;AAEtE,QAAA,MAAM,aAAa,IAAA,EAAK;AAGxB,QAAA,IAAA,CAAK,MAAA,CAAO,KAAK,wBAAA,EAA0B;AAAA,UACzC,YAAA;AAAA,UACA,WAAA,EAAa;AAAA,SACd,CAAA;AAGD,QAAA,OAAO,KAAK,OAAA,CAAQ,WAAA;AAAA,UAClB,6BAAA;AAAA,UACA,KAAK,gBAAA,EAAiB;AAAA,UACtB,EAAE,cAAA,EAAgB,GAAG,OAAA,EAAQ;AAAA,UAC7B,YAAY;AAAA,SACd;AAAA,MACF;AAAA,KACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,KAAA,CACJ,cAAA,EACA,MAAA,GAAwB,EAAC,EACU;AACnC,IAAA,MAAM;AAAA,MACJ,OAAA,GAAU,QAAA;AAAA,MACV,MAAA,GAAS,IAAA;AAAA,MACT,WAAA;AAAA,MACA,WAAW,EAAC;AAAA,MACZ,cAAA,GAAiB;AAAA,KACnB,GAAI,MAAA;AAEJ,IAAA,IAAI,CAAC,IAAA,CAAK,MAAA,CAAO,YAAA,EAAc;AAC7B,MAAA,MAAM,IAAI,wBAAwB,cAAc,CAAA;AAAA,IAClD;AAEA,IAAA,MAAM,iBAAA,GAAoB,KAAK,MAAA,CAAO,YAAA;AACtC,IAAA,MAAM,YAAA,GAAe,MAAM,iBAAA,CAAkB,QAAA,CAAS,cAAc,CAAA;AAEpE,IAAA,IAAI,CAAC,YAAA,EAAc;AACjB,MAAA,MAAM,IAAI,0BAA0B,cAAc,CAAA;AAAA,IACpD;AAEA,IAAA,IAAI,YAAA,CAAa,WAAW,CAAA,EAAG;AAC7B,MAAA,MAAM,IAAI,kBAAA,CAAmB,CAAA,EAAG,2CAA2C,CAAA;AAAA,IAC7E;AAGA,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,SAAA,CAAU,OAAO,CAAA;AACvC,IAAA,IAAI,CAAC,QAAA,EAAU;AACb,MAAA,MAAM,IAAI,qBAAA,CAAsB,OAAA,EAAS,OAAO,IAAA,CAAK,IAAA,CAAK,SAAS,CAAC,CAAA;AAAA,IACtE;AAGA,IAAA,IAAI,aAAA,GAA0C,IAAA;AAC9C,IAAA,IAAI;AACF,MAAA,aAAA,GAAgB,MAAM,SAAS,YAAA,CAAa;AAAA,QAC1C,QAAQ,YAAA,CAAa,MAAA;AAAA,QACrB,QAAA,EAAU,aAAa,QAAA,IAAY,KAAA;AAAA,QACnC,QAAA,EAAU;AAAA,UACR,GAAG,QAAA;AAAA,UACH,IAAA,EAAM,sBAAA;AAAA,UACN,cAAA,EAAgB,YAAA,CAAa,GAAA,CAAI,QAAA;AAAS;AAC5C,OACD,CAAA;AAAA,IACH,SAAS,KAAA,EAAO;AACd,MAAA,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,8CAAA,EAAgD,KAAK,CAAA;AACvE,MAAA,MAAM,IAAI,0BAAA,CAA2B,OAAA,EAAS,KAAc,CAAA;AAAA,IAC9D;AAGA,IAAA,MAAM,eAAA,GAAkB,MAAA,IAAW,YAAA,CAAa,QAAA,EAAsC,MAAA;AACtF,IAAA,MAAM,yBAAA,GACF,YAAA,CAAa,QAAA,EAAsC,gBAAA,IAA+B,kBAAA,CAAmB,YAAA;AACzG,IAAA,MAAM,WAAW,eAAA,CAAgB,eAAA,EAAiB,yBAAA,EAAmE,IAAA,CAAK,OAAO,gBAAgB,CAAA;AAGjJ,IAAA,MAAM,eAAA,GACJ,IAAA,CAAK,MAAA,CAAO,sBAAA,GAAyB,QAAQ,CAAA,IAC7C,IAAA,CAAK,MAAA,CAAO,sBAAA,EAAwB,wBACpC,IAAA,CAAK,MAAA,CAAO,sBAAA,GAAyB,yBAAyB,KAC9D,gBAAA,CAAiB,MAAA;AAGnB,IAAA,MAAM,cAAA,GAAiB,iBAAA,CAAkB,IAAA,CAAK,MAAA,EAAQ,QAAQ,CAAA;AAC9D,IAAA,MAAM,cAAA,GAAiB,iBAAA,CAAkB,IAAA,CAAK,MAAA,EAAQ,OAAO,CAAA;AAC7D,IAAA,MAAM,UAAA,GAAa,mBAAA,CAAoB,YAAA,CAAa,MAAA,EAAQ,gBAAgB,cAAc,CAAA;AAG1F,IAAA,MAAM,SAAA,GAAY,YAAY,gBAAA,IAAoB,CAAA;AAClD,IAAA,MAAM,SAAA,GAAY,aAAa,MAAA,GAAS,SAAA;AAGxC,IAAA,MAAM,gBAAA,GAAmB,KAAK,MAAA,CAAO,WAAA;AACrC,IAAA,MAAM,WAAA,GAAc,MAAM,gBAAA,CAAiB,MAAA,CAAO;AAAA,MAChD,gBAAgB,YAAA,CAAa,cAAA;AAAA,MAC7B,YAAY,YAAA,CAAa,UAAA;AAAA;AAAA,MAGzB,IAAA,EAAM,QAAA;AAAA;AAAA,MACN,IAAA,EAAM,eAAA;AAAA;AAAA,MACN,IAAA,EAAM,CAAC,WAAA,EAAa,cAAA,EAAgB,SAAS,CAAA;AAAA;AAAA,MAG7C,QAAQ,YAAA,CAAa,MAAA;AAAA,MACrB,QAAA,EAAU,aAAa,QAAA,IAAY,KAAA;AAAA,MACnC,GAAA,EAAK,SAAA;AAAA,MACL,GAAA,EAAK,CAAA;AAAA;AAAA,MACL,GAAA,EAAK,SAAA;AAAA,MAEL,MAAA,EAAU,aAAyC,MAAA,IAAqB,QAAA;AAAA,MACxE,MAAA,EAAQ,aAAA,CAAc,MAAA,KAAW,WAAA,GAAc,UAAA,GAAa,SAAA;AAAA;AAAA,MAE5D,OAAA,EAAS;AAAA,QACP,QAAA,EAAU,OAAA;AAAA,QACV,WAAW,aAAA,CAAc,SAAA;AAAA,QACzB,iBAAiB,aAAA,CAAc,eAAA;AAAA,QAC/B,UAAU,aAAA,CAAc,EAAA;AAAA,QACxB,UAAU,aAAA,CAAc;AAAA,OAC1B;AAAA,MACA,cAAA,EAAgB;AAAA,QACd,QAAA,EAAU,OAAA;AAAA,QACV,GAAG;AAAA,OACL;AAAA;AAAA,MAEA,GAAI,UAAA,IAAc,EAAE,UAAA,EAAW;AAAA;AAAA,MAG/B,UAAU,YAAA,CAAa,GAAA;AAAA,MACvB,WAAA,EAAa,cAAA;AAAA,MACb,QAAA,EAAU;AAAA,QACR,GAAG,QAAA;AAAA,QACH,cAAA,EAAgB,YAAA,CAAa,GAAA,CAAI,QAAA,EAAS;AAAA;AAAA,QAC1C,MAAA,EAAQ,eAAA;AAAA,QACR,gBAAA,EAAkB,yBAAA;AAAA,QAClB,SAAA,EAAW,IAAA;AAAA,QACX,iBAAiB,aAAA,CAAc;AAAA,OACjC;AAAA,MACA,cAAA,EAAgB,cAAA,IAAkB,CAAA,QAAA,EAAW,MAAA,CAAO,EAAE,CAAC,CAAA;AAAA,KACxD,CAAA;AAGD,IAAA,YAAA,CAAa,MAAA,GAAS,iBAAA;AACtB,IAAA,YAAA,CAAa,uBAAuB,WAAA,CAAY,GAAA;AAChD,IAAA,YAAA,CAAa,YAAA,GAAA,CAAgB,YAAA,CAAa,YAAA,IAAgB,CAAA,IAAK,CAAA;AAC/D,IAAA,MAAM,aAAa,IAAA,EAAK;AAGxB,IAAA,IAAA,CAAK,MAAA,CAAO,KAAK,sBAAA,EAAwB;AAAA,MACvC,YAAA;AAAA,MACA,WAAA;AAAA,MACA,eAAe,aAAA,IAAiB,MAAA;AAAA,MAChC,cAAc,YAAA,CAAa;AAAA,KAC5B,CAAA;AAED,IAAA,OAAO;AAAA,MACL,YAAA;AAAA,MACA,WAAA;AAAA,MACA;AAAA,KACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,MAAA,CACJ,cAAA,EACA,OAAA,GAAyB,EAAC,EACK;AAE/B,IAAA,OAAO,KAAK,OAAA,CAAQ,WAAA;AAAA,MAClB,4BAAA;AAAA,MACA,KAAK,gBAAA,EAAiB;AAAA,MACtB,EAAE,cAAA,EAAgB,GAAG,OAAA,EAAQ;AAAA,MAC7B,YAAY;AACV,QAAA,MAAM,EAAE,SAAA,GAAY,KAAA,EAAO,MAAA,GAAS,MAAK,GAAI,OAAA;AAE7C,QAAA,IAAI,CAAC,IAAA,CAAK,MAAA,CAAO,YAAA,EAAc;AAC7B,UAAA,MAAM,IAAI,wBAAwB,cAAc,CAAA;AAAA,QAClD;AAEA,QAAA,MAAM,iBAAA,GAAoB,KAAK,MAAA,CAAO,YAAA;AACtC,QAAA,MAAM,YAAA,GAAe,MAAM,iBAAA,CAAkB,QAAA,CAAS,cAAc,CAAA;AAEpE,QAAA,IAAI,CAAC,YAAA,EAAc;AACjB,UAAA,MAAM,IAAI,0BAA0B,cAAc,CAAA;AAAA,QACpD;AAEA,QAAA,MAAM,GAAA,uBAAU,IAAA,EAAK;AAErB,QAAA,IAAI,SAAA,EAAW;AAEb,UAAA,MAAM,aAAa,0BAAA,CAA2B,2BAAA;AAAA,YAC5C,YAAA,CAAa,MAAA;AAAA,YACb,WAAA;AAAA,YACA,YAAA,CAAa,IAAI,QAAA,EAAS;AAAA,YAC1B;AAAA,cACE,SAAA,EAAW,QAAA;AAAA,cACX,MAAA,EAAQ,CAAA,kCAAA,EAAqC,MAAA,GAAS,IAAA,GAAO,SAAS,EAAE,CAAA,CAAA;AAAA,cACxE,QAAA,EAAU,EAAE,kBAAA,EAAoB,MAAA,EAAQ,WAAW,IAAA;AAAK;AAC1D,WACF;AAEA,UAAA,YAAA,CAAa,QAAA,GAAW,KAAA;AACxB,UAAA,YAAA,CAAa,MAAA,GAAS,WAAA;AACtB,UAAA,YAAA,CAAa,UAAA,GAAa,GAAA;AAC1B,UAAA,YAAA,CAAa,kBAAA,GAAqB,MAAA;AAGlC,UAAA,MAAA,CAAO,MAAA,CAAO,YAAA,EAAc,gBAAA,CAAiB,YAAA,EAAc,UAAU,CAAC,CAAA;AAAA,QACxE,CAAA,MAAO;AAEL,UAAA,YAAA,CAAa,QAAA,GAAW,aAAa,OAAA,IAAW,GAAA;AAChD,UAAA,YAAA,CAAa,kBAAA,GAAqB,MAAA;AAAA,QACpC;AAEA,QAAA,MAAM,aAAa,IAAA,EAAK;AAGxB,QAAA,IAAA,CAAK,MAAA,CAAO,KAAK,wBAAA,EAA0B;AAAA,UACzC,YAAA;AAAA,UACA,SAAA;AAAA,UACA,QAAQ,MAAA,IAAU,MAAA;AAAA,UAClB,UAAA,EAAY,SAAA,GAAY,GAAA,GAAM,YAAA,CAAa;AAAA,SAC5C,CAAA;AAGD,QAAA,OAAO,KAAK,OAAA,CAAQ,WAAA;AAAA,UAClB,2BAAA;AAAA,UACA,KAAK,gBAAA,EAAiB;AAAA,UACtB,EAAE,cAAA,EAAgB,GAAG,OAAA,EAAQ;AAAA,UAC7B,YAAY;AAAA,SACd;AAAA,MACF;AAAA,KACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,KAAA,CACJ,cAAA,EACA,OAAA,GAAwB,EAAC,EACM;AAE/B,IAAA,OAAO,KAAK,OAAA,CAAQ,WAAA;AAAA,MAClB,2BAAA;AAAA,MACA,KAAK,gBAAA,EAAiB;AAAA,MACtB,EAAE,cAAA,EAAgB,GAAG,OAAA,EAAQ;AAAA,MAC7B,YAAY;AACV,QAAA,MAAM,EAAE,MAAA,GAAS,IAAA,EAAK,GAAI,OAAA;AAE1B,QAAA,IAAI,CAAC,IAAA,CAAK,MAAA,CAAO,YAAA,EAAc;AAC7B,UAAA,MAAM,IAAI,wBAAwB,cAAc,CAAA;AAAA,QAClD;AAEA,QAAA,MAAM,iBAAA,GAAoB,KAAK,MAAA,CAAO,YAAA;AACtC,QAAA,MAAM,YAAA,GAAe,MAAM,iBAAA,CAAkB,QAAA,CAAS,cAAc,CAAA;AAEpE,QAAA,IAAI,CAAC,YAAA,EAAc;AACjB,UAAA,MAAM,IAAI,0BAA0B,cAAc,CAAA;AAAA,QACpD;AAEA,QAAA,IAAI,CAAC,aAAa,QAAA,EAAU;AAC1B,UAAA,MAAM,IAAI,0BAAA,CAA2B,cAAA,EAAgB,yCAAyC,CAAA;AAAA,QAChG;AAEA,QAAA,MAAM,QAAA,uBAAe,IAAA,EAAK;AAG1B,QAAA,MAAM,aAAa,0BAAA,CAA2B,2BAAA;AAAA,UAC5C,YAAA,CAAa,MAAA;AAAA,UACb,QAAA;AAAA,UACA,YAAA,CAAa,IAAI,QAAA,EAAS;AAAA,UAC1B;AAAA,YACE,SAAA,EAAW,QAAA;AAAA,YACX,MAAA,EAAQ,CAAA,mBAAA,EAAsB,MAAA,GAAS,IAAA,GAAO,SAAS,EAAE,CAAA,CAAA;AAAA,YACzD,QAAA,EAAU,EAAE,WAAA,EAAa,MAAA,EAAQ,QAAA;AAAS;AAC5C,SACF;AAEA,QAAA,YAAA,CAAa,QAAA,GAAW,KAAA;AACxB,QAAA,YAAA,CAAa,MAAA,GAAS,QAAA;AACtB,QAAA,YAAA,CAAa,QAAA,GAAW,QAAA;AACxB,QAAA,YAAA,CAAa,WAAA,GAAc,MAAA;AAG3B,QAAA,MAAA,CAAO,MAAA,CAAO,YAAA,EAAc,gBAAA,CAAiB,YAAA,EAAc,UAAU,CAAC,CAAA;AAEtE,QAAA,MAAM,aAAa,IAAA,EAAK;AAGxB,QAAA,IAAA,CAAK,MAAA,CAAO,KAAK,qBAAA,EAAuB;AAAA,UACtC,YAAA;AAAA,UACA,QAAQ,MAAA,IAAU,MAAA;AAAA,UAClB;AAAA,SACD,CAAA;AAGD,QAAA,OAAO,KAAK,OAAA,CAAQ,WAAA;AAAA,UAClB,0BAAA;AAAA,UACA,KAAK,gBAAA,EAAiB;AAAA,UACtB,EAAE,cAAA,EAAgB,GAAG,OAAA,EAAQ;AAAA,UAC7B,YAAY;AAAA,SACd;AAAA,MACF;AAAA,KACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,MAAA,CACJ,cAAA,EACA,OAAA,GAAyB,EAAC,EACK;AAE/B,IAAA,OAAO,KAAK,OAAA,CAAQ,WAAA;AAAA,MAClB,4BAAA;AAAA,MACA,KAAK,gBAAA,EAAiB;AAAA,MACtB,EAAE,cAAA,EAAgB,GAAG,OAAA,EAAQ;AAAA,MAC7B,YAAY;AACV,QAAA,MAAM,EAAE,YAAA,GAAe,KAAA,EAAM,GAAI,OAAA;AAEjC,QAAA,IAAI,CAAC,IAAA,CAAK,MAAA,CAAO,YAAA,EAAc;AAC7B,UAAA,MAAM,IAAI,wBAAwB,cAAc,CAAA;AAAA,QAClD;AAEA,QAAA,MAAM,iBAAA,GAAoB,KAAK,MAAA,CAAO,YAAA;AACtC,QAAA,MAAM,YAAA,GAAe,MAAM,iBAAA,CAAkB,QAAA,CAAS,cAAc,CAAA;AAEpE,QAAA,IAAI,CAAC,YAAA,EAAc;AACjB,UAAA,MAAM,IAAI,0BAA0B,cAAc,CAAA;AAAA,QACpD;AAEA,QAAA,IAAI,CAAC,aAAa,QAAA,EAAU;AAC1B,UAAA,MAAM,IAAI,2BAAA;AAAA,YACR,QAAA;AAAA,YACA,QAAA;AAAA,YACA,YAAA,CAAa,MAAA;AAAA,YACb;AAAA,WACF;AAAA,QACF;AAEA,QAAA,MAAM,GAAA,uBAAU,IAAA,EAAK;AACrB,QAAA,MAAM,QAAA,GAAW,IAAI,IAAA,CAAK,YAAA,CAAa,QAAQ,CAAA;AAC/C,QAAA,MAAM,aAAA,GAAgB,GAAA,CAAI,OAAA,EAAQ,GAAI,SAAS,OAAA,EAAQ;AAGvD,QAAA,MAAM,aAAa,0BAAA,CAA2B,2BAAA;AAAA,UAC5C,YAAA,CAAa,MAAA;AAAA,UACb,QAAA;AAAA,UACA,YAAA,CAAa,IAAI,QAAA,EAAS;AAAA,UAC1B;AAAA,YACE,SAAA,EAAW,QAAA;AAAA,YACX,MAAA,EAAQ,wCAAA;AAAA,YACR,QAAA,EAAU;AAAA,cACR,QAAA;AAAA,cACA,aAAA;AAAA,cACA,YAAA;AAAA,cACA,UAAA,EAAY,YAAA,IAAgB,YAAA,CAAa,OAAA,GAAU,IAAI,IAAA,CAAK,IAAI,IAAA,CAAK,YAAA,CAAa,OAAO,CAAA,CAAE,OAAA,EAAQ,GAAI,aAAa,CAAA,GAAI;AAAA;AAC1H;AACF,SACF;AAEA,QAAA,YAAA,CAAa,QAAA,GAAW,IAAA;AACxB,QAAA,YAAA,CAAa,MAAA,GAAS,QAAA;AACtB,QAAA,YAAA,CAAa,QAAA,GAAW,IAAA;AACxB,QAAA,YAAA,CAAa,WAAA,GAAc,IAAA;AAG3B,QAAA,IAAI,YAAA,IAAgB,aAAa,OAAA,EAAS;AACxC,UAAA,MAAM,UAAA,GAAa,IAAI,IAAA,CAAK,YAAA,CAAa,OAAO,CAAA;AAChD,UAAA,YAAA,CAAa,UAAU,IAAI,IAAA,CAAK,UAAA,CAAW,OAAA,KAAY,aAAa,CAAA;AAAA,QACtE;AAGA,QAAA,MAAA,CAAO,MAAA,CAAO,YAAA,EAAc,gBAAA,CAAiB,YAAA,EAAc,UAAU,CAAC,CAAA;AAEtE,QAAA,MAAM,aAAa,IAAA,EAAK;AAGxB,QAAA,IAAA,CAAK,MAAA,CAAO,KAAK,sBAAA,EAAwB;AAAA,UACvC,YAAA;AAAA,UACA,YAAA;AAAA,UACA,aAAA;AAAA,UACA,SAAA,EAAW;AAAA,SACZ,CAAA;AAGD,QAAA,OAAO,KAAK,OAAA,CAAQ,WAAA;AAAA,UAClB,2BAAA;AAAA,UACA,KAAK,gBAAA,EAAiB;AAAA,UACtB,EAAE,cAAA,EAAgB,GAAG,OAAA,EAAQ;AAAA,UAC7B,YAAY;AAAA,SACd;AAAA,MACF;AAAA,KACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,IAAA,CACJ,OAAA,GAAmC,EAAC,EACpC,OAAA,GAAuB,EAAC,EACS;AACjC,IAAA,IAAI,CAAC,IAAA,CAAK,MAAA,CAAO,YAAA,EAAc;AAC7B,MAAA,MAAM,IAAI,wBAAwB,cAAc,CAAA;AAAA,IAClD;AAEA,IAAA,MAAM,iBAAA,GAAoB,KAAK,MAAA,CAAO,YAAA;AACtC,IAAA,MAAM,EAAE,KAAA,GAAQ,EAAA,EAAI,IAAA,GAAO,CAAA,EAAG,OAAO,EAAE,SAAA,EAAW,EAAA,EAAG,EAAE,GAAI,OAAA;AAE3D,IAAA,MAAM,aAAA,GAAgB,MAAO,iBAAA,CAG1B,IAAA,CAAK,OAAO,CAAA,CACZ,KAAA,CAAM,KAAK,CAAA,CACX,IAAA,CAAK,IAAI,CAAA,CACT,KAAK,IAAI,CAAA;AAEZ,IAAA,OAAO,aAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,IAAI,cAAA,EAAuD;AAC/D,IAAA,IAAI,CAAC,IAAA,CAAK,MAAA,CAAO,YAAA,EAAc;AAC7B,MAAA,MAAM,IAAI,wBAAwB,cAAc,CAAA;AAAA,IAClD;AAEA,IAAA,MAAM,iBAAA,GAAoB,KAAK,MAAA,CAAO,YAAA;AACtC,IAAA,MAAM,YAAA,GAAe,MAAM,iBAAA,CAAkB,QAAA,CAAS,cAAc,CAAA;AAEpE,IAAA,IAAI,CAAC,YAAA,EAAc;AACjB,MAAA,MAAM,IAAI,0BAA0B,cAAc,CAAA;AAAA,IACpD;AAEA,IAAA,OAAO,YAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,mBAAA,CAAoB,OAAA,EAAiB,SAAA,mBAAkB,IAAI,MAAK,EAAS;AAC/E,IAAA,MAAM,KAAA,GAAQ,IAAI,IAAA,CAAK,SAAS,CAAA;AAChC,IAAA,MAAM,GAAA,GAAM,IAAI,IAAA,CAAK,KAAK,CAAA;AAE1B,IAAA,QAAQ,OAAA;AAAS,MACf,KAAK,SAAA;AACH,QAAA,GAAA,CAAI,QAAA,CAAS,GAAA,CAAI,QAAA,EAAS,GAAI,CAAC,CAAA;AAC/B,QAAA;AAAA,MACF,KAAK,WAAA;AACH,QAAA,GAAA,CAAI,QAAA,CAAS,GAAA,CAAI,QAAA,EAAS,GAAI,CAAC,CAAA;AAC/B,QAAA;AAAA,MACF,KAAK,QAAA;AACH,QAAA,GAAA,CAAI,WAAA,CAAY,GAAA,CAAI,WAAA,EAAY,GAAI,CAAC,CAAA;AACrC,QAAA;AAAA,MACF;AAEE,QAAA,GAAA,CAAI,OAAA,CAAQ,GAAA,CAAI,OAAA,EAAQ,GAAI,EAAE,CAAA;AAAA;AAGlC,IAAA,OAAO,GAAA;AAAA,EACT;AACF;ACl6BO,IAAM,iBAAN,MAAqB;AAAA,EACT,MAAA;AAAA,EACA,SAAA;AAAA,EACA,MAAA;AAAA,EACA,OAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EACA,WAAA;AAAA,EACA,cAAA;AAAA,EAEjB,YAAY,SAAA,EAAsB;AAChC,IAAA,IAAA,CAAK,MAAA,GAAS,SAAA,CAAU,GAAA,CAAoB,QAAQ,CAAA;AACpD,IAAA,IAAA,CAAK,SAAA,GAAY,SAAA,CAAU,GAAA,CAAuB,WAAW,CAAA;AAC7D,IAAA,IAAA,CAAK,MAAA,GAAS,SAAA,CAAU,GAAA,CAAmB,QAAQ,CAAA;AACnD,IAAA,IAAA,CAAK,OAAA,GAAU,SAAA,CAAU,GAAA,CAAmB,SAAS,CAAA;AACrD,IAAA,IAAA,CAAK,MAAA,GAAS,SAAA,CAAU,GAAA,CAAY,QAAQ,CAAA;AAC5C,IAAA,IAAA,CAAK,MAAA,GAAS,SAAA,CAAU,GAAA,CAAc,QAAQ,CAAA;AAC9C,IAAA,IAAA,CAAK,WAAA,GAAc,SAAA,CAAU,GAAA,CAA0B,aAAa,CAAA;AACpE,IAAA,IAAA,CAAK,cAAA,GAAiB,SAAA,CAAU,GAAA,CAA2B,gBAAgB,CAAA;AAAA,EAC7E;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,iBAAiB,cAAA,EAAwC;AAC/D,IAAA,OAAO;AAAA,MACL,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,OAAA,sBAAa,GAAA,EAAI;AAAA,MACjB,IAAA,EAAM;AAAA,QACJ,cAAA;AAAA,QACA,WAAWC,MAAAA,EAAO;AAAA,QAClB,SAAA,sBAAe,IAAA;AAAK;AACtB,KACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,mBAAA,CACZ,SAAA,EACA,aAAA,EACY;AAEZ,IAAA,MAAM,kBAAA,GAAqB,KAAK,cAAA,GAC5B,MAAM,KAAK,cAAA,CAAgB,OAAA,CAAQ,SAAS,CAAA,GAC5C,SAAA;AAGJ,IAAA,IAAI,IAAA,CAAK,eAAe,MAAA,CAAO,IAAA,CAAK,KAAK,WAAW,CAAA,CAAE,SAAS,CAAA,EAAG;AAChE,MAAA,OAAO,MAAM,kBAAA,EAAoB;AAAA,QAC/B,GAAG,IAAA,CAAK,WAAA;AAAA,QACR,OAAA,EAAS,CAAC,KAAA,EAAO,OAAA,EAAS,KAAA,KAAU;AAClC,UAAA,IAAA,CAAK,MAAA,CAAO,IAAA;AAAA,YACV,CAAA,CAAA,EAAI,aAAa,CAAA,gBAAA,EAAmB,OAAO,UAAU,KAAK,CAAA,GAAA,CAAA;AAAA,YAC1D;AAAA,WACF;AACA,UAAA,IAAA,CAAK,WAAA,CAAY,OAAA,GAAU,KAAA,EAAO,OAAA,EAAS,KAAK,CAAA;AAAA,QAClD;AAAA,OACD,CAAA;AAAA,IACH;AAEA,IAAA,OAAO,kBAAA,EAAmB;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,MAAA,CACJ,eAAA,EACA,OAAA,GAAgC,EAAC,EACH;AAE9B,IAAA,OAAO,KAAK,OAAA,CAAQ,WAAA;AAAA,MAClB,uBAAA;AAAA,MACA,KAAK,gBAAA,EAAiB;AAAA,MACtB,EAAE,EAAA,EAAI,eAAA,EAAiB,GAAG,OAAA,EAAQ;AAAA,MAClC,YAAY;AACV,QAAA,MAAM,EAAE,UAAA,GAAa,IAAA,EAAK,GAAI,OAAA;AAE9B,QAAA,MAAM,gBAAA,GAAmB,KAAK,MAAA,CAAO,WAAA;AACrC,QAAA,MAAM,WAAA,GAAc,MAAM,IAAA,CAAK,gBAAA,CAAiB,kBAAkB,eAAe,CAAA;AAErF,QAAA,IAAI,CAAC,WAAA,EAAa;AAChB,UAAA,MAAM,IAAI,yBAAyB,eAAe,CAAA;AAAA,QACpD;AAEA,QAAA,IAAI,WAAA,CAAY,MAAA,KAAW,UAAA,IAAc,WAAA,CAAY,WAAW,WAAA,EAAa;AAC3E,UAAA,MAAM,IAAI,oBAAA,CAAqB,WAAA,CAAY,GAAA,CAAI,UAAU,CAAA;AAAA,QAC3D;AAGA,QAAA,MAAM,WAAA,GAAc,WAAA,CAAY,OAAA,EAAS,IAAA,IAAQ,QAAA;AACjD,QAAA,MAAM,QAAA,GAAW,IAAA,CAAK,SAAA,CAAU,WAAW,CAAA;AAE3C,QAAA,IAAI,CAAC,QAAA,EAAU;AACb,UAAA,MAAM,IAAI,qBAAA,CAAsB,WAAA,EAAa,OAAO,IAAA,CAAK,IAAA,CAAK,SAAS,CAAC,CAAA;AAAA,QAC1E;AAGA,QAAA,IAAI,aAAA,GAA0C,IAAA;AAC9C,QAAA,IAAI;AAEF,UAAA,MAAM,iBAAiB,WAAA,CAAY,OAAA,EAAS,eAAA,IAAmB,WAAA,CAAY,SAAS,SAAA,IAAa,eAAA;AACjG,UAAA,aAAA,GAAgB,MAAM,IAAA,CAAK,mBAAA;AAAA,YACzB,MAAM,QAAA,CAAS,aAAA,CAAc,cAAc,CAAA;AAAA,YAC3C,GAAG,WAAW,CAAA,cAAA;AAAA,WAChB;AAAA,QACF,SAAS,KAAA,EAAO;AACd,UAAA,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,8BAAA,EAAgC,KAAK,CAAA;AAGvD,UAAA,MAAMC,cAAa,yBAAA,CAA0B,2BAAA;AAAA,YAC3C,WAAA,CAAY,MAAA;AAAA,YACZ,QAAA;AAAA,YACA,WAAA,CAAY,IAAI,QAAA,EAAS;AAAA,YACzB;AAAA,cACE,SAAA,EAAW,QAAA;AAAA,cACX,MAAA,EAAQ,CAAA,6BAAA,EAAiC,KAAA,CAAgB,OAAO,CAAA,CAAA;AAAA,cAChE,QAAA,EAAU,EAAE,KAAA,EAAQ,KAAA,CAAgB,OAAA;AAAQ;AAC9C,WACF;AAGA,UAAA,WAAA,CAAY,MAAA,GAAS,QAAA;AACrB,UAAA,WAAA,CAAY,gBAAiB,KAAA,CAAgB,OAAA;AAG7C,UAAA,MAAA,CAAO,MAAA,CAAO,WAAA,EAAa,gBAAA,CAAiB,WAAA,EAAaA,WAAU,CAAC,CAAA;AAEpE,UAAA,WAAA,CAAY,QAAA,GAAW;AAAA,YACrB,GAAG,WAAA,CAAY,QAAA;AAAA,YACf,mBAAoB,KAAA,CAAgB,OAAA;AAAA,YACpC,QAAA,EAAA,iBAAU,IAAI,IAAA,EAAK,EAAE,WAAA;AAAY,WACnC;AACA,UAAA,MAAM,YAAY,IAAA,EAAK;AAGvB,UAAA,IAAA,CAAK,MAAA,CAAO,KAAK,gBAAA,EAAkB;AAAA,YACjC,WAAA;AAAA,YACA,OAAQ,KAAA,CAAgB,OAAA;AAAA,YACxB,QAAA,EAAU,WAAA;AAAA,YACV;AAAA,WACD,CAAA;AAED,UAAA,MAAM,IAAI,wBAAA,CAAyB,eAAA,EAAkB,KAAA,CAAgB,OAAO,CAAA;AAAA,QAC9E;AAGA,QAAA,IAAI,aAAA,CAAc,MAAA,IAAU,aAAA,CAAc,MAAA,KAAW,YAAY,MAAA,EAAQ;AACvE,UAAA,MAAM,IAAI,eAAA;AAAA,YACR,CAAA,0BAAA,EAA6B,WAAA,CAAY,MAAM,CAAA,MAAA,EAAS,cAAc,MAAM,CAAA,CAAA;AAAA,YAC5E,EAAE,QAAA,EAAU,WAAA,CAAY,MAAA,EAAQ,MAAA,EAAQ,cAAc,MAAA;AAAO,WAC/D;AAAA,QACF;AAEA,QAAA,IAAI,aAAA,CAAc,YAAY,aAAA,CAAc,QAAA,CAAS,aAAY,KAAM,WAAA,CAAY,QAAA,CAAS,WAAA,EAAY,EAAG;AACzG,UAAA,MAAM,IAAI,eAAA;AAAA,YACR,CAAA,4BAAA,EAA+B,WAAA,CAAY,QAAQ,CAAA,MAAA,EAAS,cAAc,QAAQ,CAAA,CAAA;AAAA,YAClF,EAAE,QAAA,EAAU,WAAA,CAAY,QAAA,EAAU,MAAA,EAAQ,cAAc,QAAA;AAAS,WACnE;AAAA,QACF;AAGA,QAAA,MAAM,SAAA,GAAY,aAAA,CAAc,MAAA,KAAW,WAAA,GAAc,aAAa,aAAA,CAAc,MAAA;AAGpF,QAAA,MAAM,aAAa,yBAAA,CAA0B,2BAAA;AAAA,UAC3C,WAAA,CAAY,MAAA;AAAA,UACZ,SAAA;AAAA,UACA,WAAA,CAAY,IAAI,QAAA,EAAS;AAAA,UACzB;AAAA,YACE,WAAW,UAAA,IAAc,QAAA;AAAA,YACzB,QAAQ,CAAA,qBAAA,EAAwB,aAAA,CAAc,WAAW,WAAA,GAAc,WAAA,GAAc,yBAAyB,SAAS,CAAA,CAAA;AAAA,YACvH,QAAA,EAAU,EAAE,aAAA,EAAe,aAAA,CAAc,QAAA;AAAS;AACpD,SACF;AAEA,QAAA,WAAA,CAAY,MAAA,GAAS,SAAA;AACrB,QAAA,WAAA,CAAY,UAAA,GAAa,aAAA,CAAc,MAAA,oBAAU,IAAI,IAAA,EAAK;AAC1D,QAAA,WAAA,CAAY,UAAA,GAAa,UAAA;AACzB,QAAA,WAAA,CAAY,OAAA,GAAU;AAAA,UACpB,GAAG,WAAA,CAAY,OAAA;AAAA,UACf,IAAA,EAAM,WAAA,CAAY,OAAA,EAAS,IAAA,IAAQ,QAAA;AAAA,UACnC,kBAAkB,aAAA,CAAc;AAAA,SAClC;AAGA,QAAA,MAAA,CAAO,MAAA,CAAO,WAAA,EAAa,gBAAA,CAAiB,WAAA,EAAa,UAAU,CAAC,CAAA;AAEpE,QAAA,MAAM,YAAY,IAAA,EAAK;AAGnB,QAAA,IAAI,cAAc,UAAA,EAAY;AAC5B,UAAA,IAAA,CAAK,MAAA,CAAO,KAAK,kBAAA,EAAoB;AAAA,YACnC,WAAA;AAAA,YACA,aAAA;AAAA,YACA,YAAY,UAAA,IAAc;AAAA,WAC3B,CAAA;AAAA,QACH,CAAA,MAAA,IAAW,cAAc,QAAA,EAAU;AACjC,UAAA,IAAA,CAAK,MAAA,CAAO,KAAK,gBAAA,EAAkB;AAAA,YACjC,WAAA;AAAA,YACA,KAAA,EAAO,aAAA,CAAc,QAAA,EAAU,YAAA,IAA0B,6BAAA;AAAA,YACzD,QAAA,EAAU,WAAA;AAAA,YACV,iBAAiB,WAAA,CAAY,OAAA,EAAS,eAAA,IAAmB,WAAA,CAAY,SAAS,SAAA,IAAa;AAAA,WAC5F,CAAA;AAAA,QACH,CAAA,MAAA,IAAW,cAAc,iBAAA,EAAmB;AAC1C,UAAA,IAAA,CAAK,MAAA,CAAO,KAAK,yBAAA,EAA2B;AAAA,YAC1C,WAAA;AAAA,YACA,aAAA;AAAA,YACA,MAAA,EAAQ,cAAc,QAAA,EAAU;AAAA,WACjC,CAAA;AAAA,QACH,CAAA,MAAA,IAAW,cAAc,YAAA,EAAc;AACrC,UAAA,IAAA,CAAK,MAAA,CAAO,KAAK,oBAAA,EAAsB;AAAA,YACrC,WAAA;AAAA,YACA;AAAA,WACD,CAAA;AAAA,QACH;AAEA,QAAA,MAAM,MAAA,GAAS;AAAA,UACb,WAAA;AAAA,UACA,aAAA;AAAA,UACA,QAAQ,WAAA,CAAY;AAAA,SACtB;AAGA,QAAA,OAAO,KAAK,OAAA,CAAQ,WAAA;AAAA,UAClB,sBAAA;AAAA,UACA,KAAK,gBAAA,EAAiB;AAAA,UACtB,EAAE,EAAA,EAAI,eAAA,EAAiB,GAAG,OAAA,EAAQ;AAAA,UAClC,YAAY;AAAA,SACd;AAAA,MACF;AAAA,KACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,UAAU,eAAA,EAAuD;AACrE,IAAA,MAAM,gBAAA,GAAmB,KAAK,MAAA,CAAO,WAAA;AACrC,IAAA,MAAM,WAAA,GAAc,MAAM,IAAA,CAAK,gBAAA,CAAiB,kBAAkB,eAAe,CAAA;AAEjF,IAAA,IAAI,CAAC,WAAA,EAAa;AAChB,MAAA,MAAM,IAAI,yBAAyB,eAAe,CAAA;AAAA,IACpD;AAGA,IAAA,MAAM,WAAA,GAAc,WAAA,CAAY,OAAA,EAAS,IAAA,IAAQ,QAAA;AACjD,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,SAAA,CAAU,WAAW,CAAA;AAE3C,IAAA,IAAI,CAAC,QAAA,EAAU;AACb,MAAA,MAAM,IAAI,qBAAA,CAAsB,WAAA,EAAa,OAAO,IAAA,CAAK,IAAA,CAAK,SAAS,CAAC,CAAA;AAAA,IAC1E;AAGA,IAAA,IAAI,aAAA,GAA0C,IAAA;AAC9C,IAAA,IAAI;AAEF,MAAA,MAAM,iBAAiB,WAAA,CAAY,OAAA,EAAS,eAAA,IAAmB,WAAA,CAAY,SAAS,SAAA,IAAa,eAAA;AACjG,MAAA,aAAA,GAAgB,MAAM,IAAA,CAAK,mBAAA;AAAA,QACzB,MAAM,QAAA,CAAS,SAAA,CAAU,cAAc,CAAA;AAAA,QACvC,GAAG,WAAW,CAAA,UAAA;AAAA,OAChB;AAAA,IACF,SAAS,KAAA,EAAO;AACd,MAAA,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,6CAAA,EAA+C,KAAK,CAAA;AAErE,MAAA,OAAO;AAAA,QACL,WAAA;AAAA,QACA,QAAQ,WAAA,CAAY,MAAA;AAAA,QACpB,QAAA,EAAU;AAAA,OACZ;AAAA,IACF;AAEA,IAAA,OAAO;AAAA,MACL,WAAA;AAAA,MACA,aAAA;AAAA,MACA,QAAQ,aAAA,CAAc,MAAA;AAAA,MACtB,QAAA,EAAU;AAAA,KACZ;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,MAAA,CACJ,SAAA,EACA,SAAwB,IAAA,EACxB,OAAA,GAAyB,EAAC,EACI;AAE9B,IAAA,OAAO,KAAK,OAAA,CAAQ,WAAA;AAAA,MAClB,uBAAA;AAAA,MACA,KAAK,gBAAA,EAAiB;AAAA,MACtB,EAAE,aAAA,EAAe,SAAA,EAAW,MAAA,EAAQ,GAAG,OAAA,EAAQ;AAAA,MAC/C,YAAY;AACV,QAAA,MAAM,EAAE,MAAA,GAAS,IAAA,EAAK,GAAI,OAAA;AAE1B,QAAA,MAAM,gBAAA,GAAmB,KAAK,MAAA,CAAO,WAAA;AACrC,QAAA,MAAM,WAAA,GAAc,MAAM,IAAA,CAAK,gBAAA,CAAiB,kBAAkB,SAAS,CAAA;AAE/E,QAAA,IAAI,CAAC,WAAA,EAAa;AAChB,UAAA,MAAM,IAAI,yBAAyB,SAAS,CAAA;AAAA,QAC9C;AAEA,QAAA,IACE,WAAA,CAAY,WAAW,UAAA,IACvB,WAAA,CAAY,WAAW,WAAA,IACvB,WAAA,CAAY,WAAW,oBAAA,EACvB;AACA,UAAA,MAAM,IAAI,2BAAA;AAAA,YACR,aAAA;AAAA,YACA,WAAA,CAAY,IAAI,QAAA,EAAS;AAAA,YACzB,WAAA,CAAY,MAAA;AAAA,YACZ;AAAA,WACF;AAAA,QACF;AAGA,QAAA,MAAM,WAAA,GAAc,WAAA,CAAY,OAAA,EAAS,IAAA,IAAQ,QAAA;AACjD,QAAA,MAAM,QAAA,GAAW,IAAA,CAAK,SAAA,CAAU,WAAW,CAAA;AAE3C,QAAA,IAAI,CAAC,QAAA,EAAU;AACb,UAAA,MAAM,IAAI,qBAAA,CAAsB,WAAA,EAAa,OAAO,IAAA,CAAK,IAAA,CAAK,SAAS,CAAC,CAAA;AAAA,QAC1E;AAGA,QAAA,MAAM,YAAA,GAAe,SAAS,eAAA,EAAgB;AAC9C,QAAA,IAAI,CAAC,aAAa,eAAA,EAAiB;AACjC,UAAA,MAAM,IAAI,wBAAwB,WAAW,CAAA;AAAA,QAC/C;AAGA,QAAA,MAAM,aAAA,GAAgB,YAAY,cAAA,IAAkB,CAAA;AACpD,QAAA,MAAM,gBAAA,GAAmB,YAAY,MAAA,GAAS,aAAA;AAC9C,QAAA,MAAM,eAAe,MAAA,IAAU,gBAAA;AAG/B,QAAA,IAAI,gBAAgB,CAAA,EAAG;AACrB,UAAA,MAAM,IAAI,eAAA,CAAgB,CAAA,oCAAA,EAAuC,YAAY,CAAA,CAAE,CAAA;AAAA,QACjF;AAEA,QAAA,IAAI,eAAe,gBAAA,EAAkB;AACnC,UAAA,MAAM,IAAI,eAAA;AAAA,YACR,CAAA,eAAA,EAAkB,YAAY,CAAA,8BAAA,EAAiC,gBAAgB,CAAA,CAAA,CAAA;AAAA,YAC/E,EAAE,YAAA,EAAc,gBAAA,EAAkB,eAAA,EAAiB,aAAA;AAAc,WACnE;AAAA,QACF;AAGA,QAAA,IAAI,YAAA;AAEJ,QAAA,IAAI;AAEF,UAAA,MAAM,iBAAiB,WAAA,CAAY,OAAA,EAAS,eAAA,IAAmB,WAAA,CAAY,SAAS,SAAA,IAAa,SAAA;AACjG,UAAA,YAAA,GAAe,MAAM,IAAA,CAAK,mBAAA;AAAA,YACxB,MAAM,SAAS,MAAA,CAAO,cAAA,EAAgB,cAAc,EAAE,MAAA,EAAQ,MAAA,IAAU,KAAA,CAAA,EAAW,CAAA;AAAA,YACnF,GAAG,WAAW,CAAA,OAAA;AAAA,WAChB;AAAA,QACF,SAAS,KAAA,EAAO;AACd,UAAA,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,gBAAA,EAAkB,KAAK,CAAA;AACzC,UAAA,MAAM,IAAI,WAAA,CAAY,SAAA,EAAY,KAAA,CAAgB,OAAO,CAAA;AAAA,QAC3D;AAIA,QAAA,MAAM,UAAA,GACJ,IAAA,CAAK,MAAA,CAAO,sBAAA,EAAwB,UAAU,gBAAA,CAAiB,OAAA;AAGjE,QAAA,MAAM,gBAAA,GAAmB,YAAY,UAAA,GACjC,iBAAA,CAAkB,YAAY,UAAA,EAAY,WAAA,CAAY,MAAA,EAAQ,YAAY,CAAA,GAC1E,IAAA;AAIJ,QAAA,IAAI,eAAA,GAAkB,CAAA;AACtB,QAAA,IAAI,WAAA,CAAY,GAAA,IAAO,WAAA,CAAY,GAAA,GAAM,CAAA,EAAG;AAE1C,UAAA,IAAI,WAAA,CAAY,SAAS,CAAA,EAAG;AAC1B,YAAA,MAAM,KAAA,GAAQ,eAAe,WAAA,CAAY,MAAA;AACzC,YAAA,eAAA,GAAkB,IAAA,CAAK,KAAA,CAAM,WAAA,CAAY,GAAA,GAAM,KAAK,CAAA;AAAA,UACtD;AAAA,QACF;AAGA,QAAA,MAAM,eAAA,GAAkB,kBAAkB,gBAAA,IAAoB,CAAA;AAC9D,QAAA,MAAM,eAAA,GAAkB,eAAe,eAAA,GAAkB,eAAA;AAEzD,QAAA,MAAM,iBAAA,GAAoB,MAAM,gBAAA,CAAiB,MAAA,CAAO;AAAA,UACtD,gBAAgB,WAAA,CAAY,cAAA;AAAA,UAC5B,YAAY,WAAA,CAAY,UAAA;AAAA;AAAA,UAGxB,IAAA,EAAM,QAAA;AAAA;AAAA,UACN,IAAA,EAAM,UAAA;AAAA;AAAA,UACN,IAAA,EAAM,CAAC,QAAQ,CAAA;AAAA;AAAA,UAGf,MAAA,EAAQ,YAAA;AAAA,UACR,UAAU,WAAA,CAAY,QAAA;AAAA,UACtB,GAAA,EAAK,eAAA;AAAA,UACL,GAAA,EAAK,eAAA;AAAA,UACL,GAAA,EAAK,eAAA;AAAA;AAAA,UAGL,GAAI,YAAY,UAAA,IAAc;AAAA,YAC5B,YAAY,WAAA,CAAY;AAAA,WAC1B;AAAA,UAEA,MAAA,EAAQ,YAAY,MAAA,IAAU,QAAA;AAAA,UAC9B,MAAA,EAAQ,WAAA;AAAA,UAER,OAAA,EAAS;AAAA,YACP,QAAA,EAAU,WAAA,CAAY,OAAA,EAAS,QAAA,IAAY,QAAA;AAAA,YAC3C,iBAAiB,YAAA,CAAa,EAAA;AAAA,YAC9B,UAAU,YAAA,CAAa;AAAA,WACzB;AAAA,UAEA,gBAAgB,WAAA,CAAY,cAAA;AAAA;AAAA,UAG5B,GAAI,gBAAA,IAAoB,EAAE,UAAA,EAAY,gBAAA,EAAiB;AAAA;AAAA,UAGvD,GAAI,WAAA,CAAY,QAAA,IAAY,EAAE,QAAA,EAAU,YAAY,QAAA,EAAS;AAAA,UAC7D,GAAI,WAAA,CAAY,WAAA,IAAe,EAAE,WAAA,EAAa,YAAY,WAAA,EAAY;AAAA,UACtE,sBAAsB,WAAA,CAAY,GAAA;AAAA;AAAA,UAElC,QAAA,EAAU;AAAA,YACR,GAAG,WAAA,CAAY,QAAA;AAAA,YACf,QAAA,EAAU,IAAA;AAAA,YACV,qBAAA,EAAuB,WAAA,CAAY,GAAA,CAAI,QAAA,EAAS;AAAA,YAChD,YAAA,EAAc,MAAA;AAAA,YACd,cAAc,YAAA,CAAa;AAAA,WAC7B;AAAA,UAEA,gBAAgB,CAAA,OAAA,EAAU,WAAA,CAAY,GAAG,CAAA,CAAA,EAAI,IAAA,CAAK,KAAK,CAAA;AAAA,SACxD,CAAA;AAGD,QAAA,MAAM,kBAAkB,YAAA,GAAe,gBAAA;AACvC,QAAA,MAAM,YAAA,GAAe,kBAAkB,oBAAA,GAAuB,UAAA;AAG9D,QAAA,MAAM,aAAa,yBAAA,CAA0B,2BAAA;AAAA,UAC3C,WAAA,CAAY,MAAA;AAAA,UACZ,YAAA;AAAA,UACA,WAAA,CAAY,IAAI,QAAA,EAAS;AAAA,UACzB;AAAA,YACE,SAAA,EAAW,QAAA;AAAA,YACX,MAAA,EAAQ,CAAA,kBAAA,EAAqB,eAAA,GAAkB,SAAA,GAAY,MAAM,CAAA,WAAA,EAAc,YAAY,CAAA,EAAG,MAAA,GAAS,KAAA,GAAQ,MAAA,GAAS,EAAE,CAAA,CAAA;AAAA,YAC1H,QAAA,EAAU;AAAA,cACR,YAAA;AAAA,cACA,eAAA;AAAA,cACA,mBAAA,EAAqB,iBAAA,CAAkB,GAAA,CAAI,QAAA;AAAS;AACtD;AACF,SACF;AAEA,QAAA,WAAA,CAAY,MAAA,GAAS,YAAA;AACrB,QAAA,WAAA,CAAY,cAAA,GAAA,CAAkB,WAAA,CAAY,cAAA,IAAkB,CAAA,IAAK,YAAA;AACjE,QAAA,WAAA,CAAY,UAAA,GAAa,YAAA,CAAa,UAAA,oBAAc,IAAI,IAAA,EAAK;AAG7D,QAAA,MAAA,CAAO,MAAA,CAAO,WAAA,EAAa,gBAAA,CAAiB,WAAA,EAAa,UAAU,CAAC,CAAA;AAEpE,QAAA,WAAA,CAAY,QAAA,GAAW;AAAA,UACrB,GAAG,WAAA,CAAY,QAAA;AAAA,UACf,mBAAA,EAAqB,iBAAA,CAAkB,GAAA,CAAI,QAAA,EAAS;AAAA,UACpD,YAAA,EAAc;AAAA,SAChB;AAEA,QAAA,MAAM,YAAY,IAAA,EAAK;AAGnB,QAAA,IAAA,CAAK,MAAA,CAAO,KAAK,kBAAA,EAAoB;AAAA,UACnC,WAAA;AAAA,UACA,iBAAA;AAAA,UACA,YAAA,EAAc;AAAA,YACZ,GAAG,YAAA;AAAA,YACH,QAAA,EAAU,aAAa,QAAA,IAAY,KAAA;AAAA,YACnC,QAAA,EAAU,YAAA,CAAa,QAAA,IAAY;AAAC,WACtC;AAAA,UACA,YAAA;AAAA,UACA,QAAQ,MAAA,IAAU,MAAA;AAAA,UAClB;AAAA,SACD,CAAA;AAED,QAAA,MAAM,MAAA,GAAS;AAAA,UACb,WAAA;AAAA,UACA,iBAAA;AAAA,UACA,YAAA;AAAA,UACA,QAAQ,WAAA,CAAY;AAAA,SACtB;AAGA,QAAA,OAAO,KAAK,OAAA,CAAQ,WAAA;AAAA,UAClB,sBAAA;AAAA,UACA,KAAK,gBAAA,EAAiB;AAAA,UACtB,EAAE,aAAA,EAAe,SAAA,EAAW,MAAA,EAAQ,GAAG,OAAA,EAAQ;AAAA,UAC/C,YAAY;AAAA,SACd;AAAA,MACF;AAAA,KACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,aAAA,CACJ,YAAA,EACA,OAAA,EACA,OAAA,GAAkC,EAAC,EACX;AACxB,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,SAAA,CAAU,YAAY,CAAA;AAE5C,IAAA,IAAI,CAAC,QAAA,EAAU;AACb,MAAA,MAAM,IAAI,qBAAA,CAAsB,YAAA,EAAc,OAAO,IAAA,CAAK,IAAA,CAAK,SAAS,CAAC,CAAA;AAAA,IAC3E;AAGA,IAAA,MAAM,YAAA,GAAe,SAAS,eAAA,EAAgB;AAC9C,IAAA,IAAI,CAAC,aAAa,gBAAA,EAAkB;AAClC,MAAA,MAAM,IAAI,uBAAA,CAAwB,YAAA,EAAc,UAAU,CAAA;AAAA,IAC5D;AAGA,IAAA,IAAI,YAAA;AACJ,IAAA,IAAI;AACF,MAAA,YAAA,GAAe,MAAM,IAAA,CAAK,mBAAA;AAAA,QACxB,MAAM,QAAA,CAAS,aAAA,CAAc,OAAA,EAAS,OAAO,CAAA;AAAA,QAC7C,GAAG,YAAY,CAAA,cAAA;AAAA,OACjB;AAAA,IACF,SAAS,KAAA,EAAO;AACd,MAAA,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,4BAAA,EAA8B,KAAK,CAAA;AACrD,MAAA,MAAM,IAAI,aAAA;AAAA,QACR,CAAA,8BAAA,EAAiC,YAAY,CAAA,EAAA,EAAM,KAAA,CAAgB,OAAO,CAAA,CAAA;AAAA,QAC1E,2BAAA;AAAA,QACA,EAAE,WAAW,KAAA;AAAM,OACrB;AAAA,IACF;AAGA,IAAA,IAAI,CAAC,YAAA,EAAc,IAAA,EAAM,aAAa,CAAC,YAAA,EAAc,MAAM,eAAA,EAAiB;AAC1E,MAAA,MAAM,IAAI,eAAA;AAAA,QACR,wCAAwC,YAAY,CAAA,sCAAA,CAAA;AAAA,QACpD,EAAE,QAAA,EAAU,YAAA,EAAc,SAAA,EAAW,cAAc,IAAA;AAAK,OAC1D;AAAA,IACF;AAGA,IAAA,MAAM,gBAAA,GAAmB,KAAK,MAAA,CAAO,WAAA;AACrC,IAAA,IAAI,WAAA,GAA0C,IAAA;AAE9C,IAAA,IAAI,YAAA,CAAa,KAAK,SAAA,EAAW;AAC/B,MAAA,WAAA,GAAc,MAAO,iBAElB,OAAA,CAAQ;AAAA,QACT,mBAAA,EAAqB,aAAa,IAAA,CAAK;AAAA,OACxC,CAAA;AAAA,IACH;AAEA,IAAA,IAAI,CAAC,WAAA,IAAe,YAAA,CAAa,IAAA,CAAK,eAAA,EAAiB;AACrD,MAAA,WAAA,GAAc,MAAO,iBAElB,OAAA,CAAQ;AAAA,QACT,yBAAA,EAA2B,aAAa,IAAA,CAAK;AAAA,OAC9C,CAAA;AAAA,IACH;AAEA,IAAA,IAAI,CAAC,WAAA,EAAa;AAChB,MAAA,IAAA,CAAK,MAAA,CAAO,KAAK,yCAAA,EAA2C;AAAA,QAC1D,QAAA,EAAU,YAAA;AAAA,QACV,SAAS,YAAA,CAAa,EAAA;AAAA,QACtB,SAAA,EAAW,aAAa,IAAA,CAAK,SAAA;AAAA,QAC7B,eAAA,EAAiB,aAAa,IAAA,CAAK;AAAA,OACpC,CAAA;AACD,MAAA,MAAM,IAAI,wBAAA;AAAA,QACR,YAAA,CAAa,IAAA,CAAK,SAAA,IAAa,YAAA,CAAa,KAAK,eAAA,IAAmB;AAAA,OACtE;AAAA,IACF;AAGA,IAAA,IAAI,aAAa,IAAA,CAAK,SAAA,IAAa,CAAC,WAAA,CAAY,SAAS,SAAA,EAAW;AAClE,MAAA,WAAA,CAAY,OAAA,GAAU;AAAA,QACpB,GAAG,WAAA,CAAY,OAAA;AAAA,QACf,IAAA,EAAM,WAAA,CAAY,OAAA,EAAS,IAAA,IAAQ,QAAA;AAAA,QACnC,SAAA,EAAW,aAAa,IAAA,CAAK;AAAA,OAC/B;AAAA,IACF;AACA,IAAA,IAAI,aAAa,IAAA,CAAK,eAAA,IAAmB,CAAC,WAAA,CAAY,SAAS,eAAA,EAAiB;AAC9E,MAAA,WAAA,CAAY,OAAA,GAAU;AAAA,QACpB,GAAG,WAAA,CAAY,OAAA;AAAA,QACf,IAAA,EAAM,WAAA,CAAY,OAAA,EAAS,IAAA,IAAQ,QAAA;AAAA,QACnC,eAAA,EAAiB,aAAa,IAAA,CAAK;AAAA,OACrC;AAAA,IACF;AAGA,IAAA,IAAI,YAAY,OAAA,EAAS,OAAA,KAAY,aAAa,EAAA,IAAM,WAAA,CAAY,SAAS,WAAA,EAAa;AACxF,MAAA,IAAA,CAAK,MAAA,CAAO,KAAK,2BAAA,EAA6B;AAAA,QAC5C,eAAe,WAAA,CAAY,GAAA;AAAA,QAC3B,SAAS,YAAA,CAAa;AAAA,OACvB,CAAA;AACD,MAAA,OAAO;AAAA,QACL,KAAA,EAAO,YAAA;AAAA,QACP,WAAA;AAAA,QACA,MAAA,EAAQ;AAAA,OACV;AAAA,IACF;AAGA,IAAA,WAAA,CAAY,OAAA,GAAU;AAAA,MACpB,SAAS,YAAA,CAAa,EAAA;AAAA,MACtB,WAAW,YAAA,CAAa,IAAA;AAAA,MACxB,UAAA,sBAAgB,IAAA,EAAK;AAAA,MACrB,WAAA,sBAAiB,IAAA,EAAK;AAAA,MACtB,MAAM,YAAA,CAAa;AAAA,KACrB;AAGA,IAAA,IAAI,YAAY,WAAA,CAAY,MAAA;AAC5B,IAAA,IAAI,YAAA,CAAa,SAAS,mBAAA,EAAqB;AAC7C,MAAA,SAAA,GAAY,UAAA;AAAA,IACd,CAAA,MAAA,IAAW,YAAA,CAAa,IAAA,KAAS,gBAAA,EAAkB;AACjD,MAAA,SAAA,GAAY,QAAA;AAAA,IACd,CAAA,MAAA,IAAW,YAAA,CAAa,IAAA,KAAS,kBAAA,EAAoB;AACnD,MAAA,SAAA,GAAY,UAAA;AAAA,IACd;AAGA,IAAA,IAAI,SAAA,KAAc,YAAY,MAAA,EAAQ;AACpC,MAAA,MAAM,aAAa,yBAAA,CAA0B,2BAAA;AAAA,QAC3C,WAAA,CAAY,MAAA;AAAA,QACZ,SAAA;AAAA,QACA,WAAA,CAAY,IAAI,QAAA,EAAS;AAAA,QACzB;AAAA,UACE,SAAA,EAAW,SAAA;AAAA,UACX,MAAA,EAAQ,CAAA,eAAA,EAAkB,YAAA,CAAa,IAAI,CAAA,CAAA;AAAA,UAC3C,QAAA,EAAU;AAAA,YACR,WAAW,YAAA,CAAa,EAAA;AAAA,YACxB,aAAa,YAAA,CAAa,IAAA;AAAA,YAC1B,aAAa,YAAA,CAAa;AAAA;AAC5B;AACF,OACF;AAEA,MAAA,WAAA,CAAY,MAAA,GAAS,SAAA;AAGrB,MAAA,IAAI,cAAc,UAAA,EAAY;AAC5B,QAAA,WAAA,CAAY,aAAa,YAAA,CAAa,SAAA;AAAA,MACxC,CAAA,MAAA,IAAW,cAAc,UAAA,EAAY;AACnC,QAAA,WAAA,CAAY,aAAa,YAAA,CAAa,SAAA;AAAA,MACxC,CAAA,MAAA,IAAW,cAAc,QAAA,EAAU;AACjC,QAAA,WAAA,CAAY,WAAW,YAAA,CAAa,SAAA;AAAA,MACtC;AAGA,MAAA,MAAA,CAAO,MAAA,CAAO,WAAA,EAAa,gBAAA,CAAiB,WAAA,EAAa,UAAU,CAAC,CAAA;AAAA,IAKtE;AAEA,IAAA,MAAM,YAAY,IAAA,EAAK;AAGvB,IAAA,IAAA,CAAK,MAAA,CAAO,KAAK,mBAAA,EAAqB;AAAA,MACpC,aAAa,YAAA,CAAa,IAAA;AAAA,MAC1B,UAAU,YAAA,CAAa,QAAA;AAAA,MACvB,KAAA,EAAO,YAAA;AAAA,MACP,WAAA;AAAA,MACA,WAAA,sBAAiB,IAAA;AAAK,KACvB,CAAA;AAED,IAAA,OAAO;AAAA,MACL,KAAA,EAAO,YAAA;AAAA,MACP,WAAA;AAAA,MACA,MAAA,EAAQ;AAAA,KACV;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,IAAA,CACJ,OAAA,GAAmC,EAAC,EACpC,OAAA,GAAuB,EAAC,EACQ;AAChC,IAAA,MAAM,gBAAA,GAAmB,KAAK,MAAA,CAAO,WAAA;AACrC,IAAA,MAAM,EAAE,KAAA,GAAQ,EAAA,EAAI,IAAA,GAAO,CAAA,EAAG,OAAO,EAAE,SAAA,EAAW,EAAA,EAAG,EAAE,GAAI,OAAA;AAE3D,IAAA,MAAM,YAAA,GAAe,MAAO,gBAAA,CAGzB,IAAA,CAAK,OAAO,CAAA,CACZ,KAAA,CAAM,KAAK,CAAA,CACX,IAAA,CAAK,IAAI,CAAA,CACT,KAAK,IAAI,CAAA;AAEZ,IAAA,OAAO,YAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,IAAI,aAAA,EAAqD;AAC7D,IAAA,MAAM,gBAAA,GAAmB,KAAK,MAAA,CAAO,WAAA;AACrC,IAAA,MAAM,WAAA,GAAc,MAAM,gBAAA,CAAiB,QAAA,CAAS,aAAa,CAAA;AAEjE,IAAA,IAAI,CAAC,WAAA,EAAa;AAChB,MAAA,MAAM,IAAI,yBAAyB,aAAa,CAAA;AAAA,IAClD;AAEA,IAAA,OAAO,WAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,YAAY,YAAA,EAAgD;AAC1D,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,SAAA,CAAU,YAAY,CAAA;AAC5C,IAAA,IAAI,CAAC,QAAA,EAAU;AACb,MAAA,MAAM,IAAI,qBAAA,CAAsB,YAAA,EAAc,OAAO,IAAA,CAAK,IAAA,CAAK,SAAS,CAAC,CAAA;AAAA,IAC3E;AACA,IAAA,OAAO,QAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,gBAAA,CACZ,gBAAA,EACA,UAAA,EACqC;AACrC,IAAA,IAAI,WAAA,GAAc,MAAO,gBAAA,CAEtB,OAAA,CAAQ;AAAA,MACT,mBAAA,EAAqB;AAAA,KACtB,CAAA;AAED,IAAA,IAAI,CAAC,WAAA,EAAa;AAChB,MAAA,WAAA,GAAc,MAAO,iBAElB,OAAA,CAAQ;AAAA,QACT,yBAAA,EAA2B;AAAA,OAC5B,CAAA;AAAA,IACH;AAEA,IAAA,IAAI,CAAC,WAAA,EAAa;AAChB,MAAA,WAAA,GAAc,MAAM,gBAAA,CAAiB,QAAA,CAAS,UAAU,CAAA;AAAA,IAC1D;AAEA,IAAA,OAAO,WAAA;AAAA,EACT;AACF;AC3yBO,IAAM,qBAAN,MAAyB;AAAA,EACb,MAAA;AAAA,EACA,OAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EAEjB,YAAY,SAAA,EAAsB;AAChC,IAAA,IAAA,CAAK,MAAA,GAAS,SAAA,CAAU,GAAA,CAAoB,QAAQ,CAAA;AACpD,IAAA,IAAA,CAAK,OAAA,GAAU,SAAA,CAAU,GAAA,CAAmB,SAAS,CAAA;AACrD,IAAA,IAAA,CAAK,MAAA,GAAS,SAAA,CAAU,GAAA,CAAc,QAAQ,CAAA;AAC9C,IAAA,IAAA,CAAK,MAAA,GAAS,SAAA,CAAU,GAAA,CAAY,QAAQ,CAAA;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,gBAAA,GAAkC;AACxC,IAAA,OAAO;AAAA,MACL,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,OAAA,sBAAa,GAAA,EAAI;AAAA,MACjB,IAAA,EAAM;AAAA,QACJ,WAAWD,MAAAA,EAAO;AAAA,QAClB,SAAA,sBAAe,IAAA;AAAK;AACtB,KACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,IAAI,aAAA,EAAqD;AAC7D,IAAA,MAAM,gBAAA,GAAmB,KAAK,MAAA,CAAO,WAAA;AACrC,IAAA,MAAM,WAAA,GAAc,MAAM,gBAAA,CAAiB,QAAA,CAAS,aAAa,CAAA;AAEjE,IAAA,IAAI,CAAC,WAAA,EAAa;AAChB,MAAA,MAAM,IAAI,yBAAyB,aAAa,CAAA;AAAA,IAClD;AAEA,IAAA,OAAO,WAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,IAAA,CACJ,OAAA,GAAmC,EAAC,EACpC,OAAA,GAAuB,EAAC,EACQ;AAChC,IAAA,MAAM,gBAAA,GAAmB,KAAK,MAAA,CAAO,WAAA;AACrC,IAAA,MAAM;AAAA,MACJ,KAAA,GAAQ,EAAA;AAAA,MACR,IAAA,GAAO,CAAA;AAAA,MACP,IAAA,GAAO,IAAA;AAAA,MACP,IAAA,GAAO,EAAE,SAAA,EAAW,EAAA,EAAG;AAAA,MACvB,WAAW;AAAC,KACd,GAAI,OAAA;AAGJ,IAAA,MAAM,UAAA,GAAa,IAAA,GAAA,CAAQ,IAAA,GAAO,CAAA,IAAK,KAAA,GAAQ,IAAA;AAY/C,IAAA,IAAI,KAAA,GAAS,gBAAA,CAEV,IAAA,CAAK,OAAO,CAAA,CACZ,KAAA,CAAM,KAAK,CAAA,CACX,IAAA,CAAK,UAAU,CAAA,CACf,IAAA,CAAK,IAAI,CAAA;AAGZ,IAAA,IAAI,SAAS,MAAA,GAAS,CAAA,IAAK,OAAO,KAAA,CAAM,aAAa,UAAA,EAAY;AAC/D,MAAA,QAAA,CAAS,OAAA,CAAQ,CAAC,KAAA,KAAU;AAC1B,QAAA,KAAA,GAAQ,KAAA,CAAM,SAAS,KAAK,CAAA;AAAA,MAC9B,CAAC,CAAA;AAAA,IACH;AAEA,IAAA,MAAM,eAAe,MAAM,KAAA;AAQ3B,IAAA,MAAM,KAAA,GAAQ,gBAAA;AACd,IAAA,MAAM,KAAA,GAAQ,OAAO,KAAA,CAAM,cAAA,GACvB,KAAA,CAAM,cAAA,CAAe,OAAO,CAAA,GAC5B,KAAA,CAAM,KAAA,GAAQ,OAAO,CAAA,CAAA,IAAM,CAAA;AAE/B,IAAA,OAAO;AAAA,MACL,YAAA;AAAA,MACA,KAAA;AAAA,MACA,MAAM,IAAA,IAAQ,IAAA,CAAK,KAAA,CAAM,UAAA,GAAa,KAAK,CAAA,GAAI,CAAA;AAAA,MAC/C,KAAA;AAAA,MACA,KAAA,EAAO,IAAA,CAAK,IAAA,CAAK,KAAA,GAAQ,KAAK;AAAA,KAChC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,MAAA,CACJ,aAAA,EACA,OAAA,EAC8B;AAC9B,IAAA,MAAM,SAAA,GAAY,EAAE,aAAA,EAAe,OAAA,EAAQ;AAE3C,IAAA,OAAO,KAAK,OAAA,CAAQ,WAAA;AAAA,MAClB,2BAAA;AAAA,MACA,KAAK,gBAAA,EAAiB;AAAA,MACtB,SAAA;AAAA,MACA,YAAY;AACV,QAAA,MAAM,gBAAA,GAAmB,KAAK,MAAA,CAAO,WAAA;AACrC,QAAA,MAAM,mBAAmB,SAAA,CAAU,OAAA;AAQnC,QAAA,MAAM,KAAA,GAAQ,gBAAA;AACd,QAAA,IAAI,WAAA;AAEJ,QAAA,IAAI,OAAO,KAAA,CAAM,MAAA,KAAW,UAAA,EAAY;AAEtC,UAAA,WAAA,GAAc,MAAM,KAAA,CAAM,MAAA,CAAO,aAAA,EAAe,gBAAgB,CAAA;AAAA,QAClE,CAAA,MAAA,IAAW,OAAO,KAAA,CAAM,iBAAA,KAAsB,UAAA,EAAY;AAExD,UAAA,WAAA,GAAc,MAAM,KAAA,CAAM,iBAAA;AAAA,YACxB,aAAA;AAAA,YACA,EAAE,MAAM,gBAAA,EAAiB;AAAA,YACzB,EAAE,KAAK,IAAA;AAAK,WACd;AAAA,QACF,CAAA,MAAO;AACL,UAAA,MAAM,IAAI,MAAM,sDAAsD,CAAA;AAAA,QACxE;AAEA,QAAA,IAAI,CAAC,WAAA,EAAa;AAChB,UAAA,MAAM,IAAI,yBAAyB,aAAa,CAAA;AAAA,QAClD;AAGA,QAAA,IAAA,CAAK,MAAA,CAAO,KAAK,qBAAA,EAAuB;AAAA,UACtC,WAAA;AAAA,UACA,OAAA,EAAS;AAAA,SACV,CAAA;AAED,QAAA,OAAO,KAAK,OAAA,CAAQ,WAAA;AAAA,UAClB,0BAAA;AAAA,UACA,KAAK,gBAAA,EAAiB;AAAA,UACtB,EAAE,aAAA,EAAe,OAAA,EAAS,gBAAA,EAAiB;AAAA,UAC3C,YAAY;AAAA,SACd;AAAA,MACF;AAAA,KACF;AAAA,EACF;AACF;;;AChLO,SAAS,gBACd,MAAA,EACA,UAAA,GAA0B,EAAC,EAC3B,iBAAyB,CAAA,EACZ;AACb,EAAA,IAAI,CAAC,UAAA,IAAc,UAAA,CAAW,MAAA,KAAW,CAAA,EAAG;AAC1C,IAAA,OAAO,EAAC;AAAA,EACV;AAEA,EAAA,IAAI,SAAS,CAAA,EAAG;AACd,IAAA,MAAM,IAAI,MAAM,uCAAuC,CAAA;AAAA,EACzD;AAEA,EAAA,IAAI,cAAA,GAAiB,CAAA,IAAK,cAAA,GAAiB,CAAA,EAAG;AAC5C,IAAA,MAAM,IAAI,MAAM,0CAA0C,CAAA;AAAA,EAC5D;AAEA,EAAA,MAAM,SAAA,GAAY,WAAW,MAAA,CAAO,CAAC,KAAK,IAAA,KAAS,GAAA,GAAM,IAAA,CAAK,IAAA,EAAM,CAAC,CAAA;AACrE,EAAA,IAAI,YAAY,CAAA,EAAG;AACjB,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,kBAAA,EAAqB,SAAS,CAAA,mBAAA,CAAqB,CAAA;AAAA,EACrE;AAEA,EAAA,OAAO,UAAA,CAAW,GAAA,CAAI,CAAC,IAAA,EAAM,KAAA,KAAU;AACrC,IAAA,IAAI,IAAA,CAAK,IAAA,GAAO,CAAA,IAAK,IAAA,CAAK,OAAO,CAAA,EAAG;AAClC,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,6CAAA,EAAgD,KAAK,CAAA,CAAE,CAAA;AAAA,IACzE;AAEA,IAAA,MAAM,WAAA,GAAc,IAAA,CAAK,KAAA,CAAM,MAAA,GAAS,KAAK,IAAI,CAAA;AAEjD,IAAA,MAAM,gBAAA,GAAmB,UAAU,CAAA,IAAK,cAAA,GAAiB,IACrD,IAAA,CAAK,KAAA,CAAM,MAAA,GAAS,cAAc,CAAA,GAClC,CAAA;AAEJ,IAAA,MAAM,SAAA,GAAY,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,cAAc,gBAAgB,CAAA;AAE5D,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,IAAA,CAAK,IAAA,IAAQ,UAAA,CAAW,MAAA;AAAA,MAC9B,aAAa,IAAA,CAAK,WAAA;AAAA,MAClB,eAAe,IAAA,CAAK,aAAA;AAAA,MACpB,MAAM,IAAA,CAAK,IAAA;AAAA,MACX,WAAA;AAAA,MACA,cAAA,EAAgB,gBAAA,GAAmB,CAAA,GAAI,cAAA,GAAiB,CAAA;AAAA,MACxD,gBAAA;AAAA,MACA,SAAA;AAAA,MACA,QAAQ,YAAA,CAAa,OAAA;AAAA,MACrB,OAAA,EAAS,KAAK,OAAA,IAAW,IAAA;AAAA,MACzB,QAAA,EAAU,IAAA,CAAK,QAAA,IAAY;AAAC,KAC9B;AAAA,EACF,CAAC,CAAA;AACH;AASO,SAAS,2BAAA,CACd,MAAA,EACA,MAAA,GAAsB,EAAC,EACf;AACR,EAAA,MAAM,gBAAA,GAAmB,OAAO,MAAA,CAAO,CAAC,KAAK,KAAA,KAAU,GAAA,GAAM,KAAA,CAAM,WAAA,EAAa,CAAC,CAAA;AACjF,EAAA,OAAO,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,MAAA,GAAS,gBAAgB,CAAA;AAC9C;;;AC3DO,IAAM,gBAAN,MAAoB;AAAA,EACR,MAAA;AAAA,EACA,OAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EAEjB,YAAY,SAAA,EAAsB;AAChC,IAAA,IAAA,CAAK,MAAA,GAAS,SAAA,CAAU,GAAA,CAAoB,QAAQ,CAAA;AACpD,IAAA,IAAA,CAAK,OAAA,GAAU,SAAA,CAAU,GAAA,CAAmB,SAAS,CAAA;AACrD,IAAA,IAAA,CAAK,MAAA,GAAS,SAAA,CAAU,GAAA,CAAY,QAAQ,CAAA;AAC5C,IAAA,IAAA,CAAK,MAAA,GAAS,SAAA,CAAU,GAAA,CAAc,QAAQ,CAAA;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,gBAAA,GAAkC;AACxC,IAAA,OAAO;AAAA,MACL,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,OAAA,sBAAa,GAAA,EAAI;AAAA,MACjB,IAAA,EAAM;AAAA,QACJ,WAAWA,MAAAA,EAAO;AAAA,QAClB,SAAA,sBAAe,IAAA;AAAK;AACtB,KACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,IAAA,CACJ,aAAA,EACA,OAAA,GAAuB,EAAC,EACM;AAE9B,IAAA,OAAO,KAAK,OAAA,CAAQ,WAAA;AAAA,MAClB,oBAAA;AAAA,MACA,KAAK,gBAAA,EAAiB;AAAA,MACtB,EAAE,aAAA,EAAe,GAAG,OAAA,EAAQ;AAAA,MAC5B,YAAY;AACV,QAAA,MAAM;AAAA,UACJ,SAAS,WAAA,CAAY,oBAAA;AAAA,UACrB,SAAA,GAAY,IAAA;AAAA,UACZ,WAAW;AAAC,SACd,GAAI,OAAA;AAEJ,QAAA,MAAM,gBAAA,GAAmB,KAAK,MAAA,CAAO,WAAA;AACrC,QAAA,MAAM,WAAA,GAAc,MAAM,gBAAA,CAAiB,QAAA,CAAS,aAAa,CAAA;AAErE,QAAA,IAAI,CAAC,WAAA,EAAa;AAChB,UAAA,MAAM,IAAI,yBAAyB,aAAa,CAAA;AAAA,QAClD;AAEA,QAAA,IAAI,WAAA,CAAY,MAAA,KAAW,kBAAA,CAAmB,QAAA,EAAU;AACtD,UAAA,MAAM,IAAI,2BAAA;AAAA,YACR,aAAA;AAAA,YACA,WAAA,CAAY,IAAI,QAAA,EAAS;AAAA,YACzB,WAAA,CAAY,MAAA;AAAA,YACZ,kBAAA,CAAmB;AAAA,WACrB;AAAA,QACF;AAGA,QAAA,MAAM,aAAa,WAAA,CAAY,MAAA;AAE/B,QAAA,WAAA,CAAY,IAAA,GAAO;AAAA,UACjB,QAAQ,WAAA,CAAY,IAAA;AAAA,UACpB,UAAA;AAAA,UACA,cAAA,EAAgB,CAAA;AAAA,UAChB,MAAA;AAAA,UACA,MAAA,sBAAY,IAAA,EAAK;AAAA,UACjB,GAAI,SAAA,IAAa,EAAE,SAAA,EAAU;AAAA,UAC7B,UAAU,EAAC;AAAA,UACX;AAAA,SACF;AAEI,QAAA,MAAM,YAAY,IAAA,EAAK;AAEvB,QAAA,IAAA,CAAK,MAAA,CAAO,KAAK,aAAA,EAAe;AAAA,UAC9B,WAAA;AAAA,UACA,UAAA;AAAA,UACA;AAAA,SACD,CAAA;AAGD,QAAA,OAAO,KAAK,OAAA,CAAQ,WAAA;AAAA,UAClB,mBAAA;AAAA,UACA,KAAK,gBAAA,EAAiB;AAAA,UACtB,EAAE,aAAA,EAAe,GAAG,OAAA,EAAQ;AAAA,UAC5B,YAAY;AAAA,SACd;AAAA,MACF;AAAA,KACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,OAAA,CACJ,aAAA,EACA,OAAA,EACwB;AAExB,IAAA,OAAO,KAAK,OAAA,CAAQ,WAAA;AAAA,MAClB,uBAAA;AAAA,MACA,KAAK,gBAAA,EAAiB;AAAA,MACtB,EAAE,aAAA,EAAe,GAAG,OAAA,EAAQ;AAAA,MAC5B,YAAY;AACV,QAAA,MAAM;AAAA,UACJ,MAAA,GAAS,IAAA;AAAA,UACT,WAAA;AAAA,UACA,aAAA,GAAgB,cAAA;AAAA,UAChB,SAAS,cAAA,CAAe,gBAAA;AAAA,UACxB,UAAA,GAAa,IAAA;AAAA,UACb,iBAAA,GAAoB,IAAA;AAAA,UACpB,WAAW;AAAC,SACd,GAAI,OAAA;AAEJ,QAAA,MAAM,gBAAA,GAAmB,KAAK,MAAA,CAAO,WAAA;AACrC,QAAA,MAAM,WAAA,GAAc,MAAM,gBAAA,CAAiB,QAAA,CAAS,aAAa,CAAA;AAErE,QAAA,IAAI,CAAC,WAAA,EAAa;AAChB,UAAA,MAAM,IAAI,yBAAyB,aAAa,CAAA;AAAA,QAClD;AAEA,QAAA,IAAI,CAAC,WAAA,CAAY,IAAA,IAAQ,YAAY,IAAA,CAAK,MAAA,KAAW,YAAY,IAAA,EAAM;AACrE,UAAA,MAAM,IAAI,2BAAA;AAAA,YACR,aAAA;AAAA,YACA,WAAA,CAAY,IAAI,QAAA,EAAS;AAAA,YACzB,WAAA,CAAY,MAAM,MAAA,IAAU,MAAA;AAAA,YAC5B,WAAA,CAAY;AAAA,WACd;AAAA,QACF;AAEA,QAAA,IAAI,CAAC,WAAA,EAAa;AAChB,UAAA,MAAM,IAAI,eAAA,CAAgB,qCAAA,EAAuC,EAAE,eAAe,CAAA;AAAA,QACpF;AAEA,QAAA,MAAM,gBAAgB,MAAA,IAAW,WAAA,CAAY,IAAA,CAAK,UAAA,GAAa,YAAY,IAAA,CAAK,cAAA;AAChF,QAAA,MAAM,eAAA,GAAkB,WAAA,CAAY,IAAA,CAAK,UAAA,GAAa,YAAY,IAAA,CAAK,cAAA;AAEvE,QAAA,IAAI,gBAAgB,eAAA,EAAiB;AACnC,UAAA,MAAM,IAAI,eAAA;AAAA,YACR,CAAA,gBAAA,EAAmB,aAAa,CAAA,iCAAA,EAAoC,eAAe,CAAA,CAAA,CAAA;AAAA,YACnF,EAAE,aAAA,EAAe,eAAA,EAAiB,aAAA;AAAc,WAClD;AAAA,QACF;AAEA,QAAA,MAAM,aAAA,GAAgB;AAAA,UACpB,MAAA,EAAQ,aAAA;AAAA,UACR,WAAA;AAAA,UACA,aAAA;AAAA,UACA,UAAA,sBAAgB,IAAA,EAAK;AAAA,UACrB,UAAA;AAAA,UACA,MAAA;AAAA,UACA;AAAA,SACF;AAEA,QAAA,WAAA,CAAY,IAAA,CAAK,QAAA,CAAS,IAAA,CAAK,aAAa,CAAA;AAC5C,QAAA,WAAA,CAAY,KAAK,cAAA,IAAkB,aAAA;AAEnC,QAAA,MAAM,aAAA,GAAgB,WAAA,CAAY,IAAA,CAAK,cAAA,IAAkB,YAAY,IAAA,CAAK,UAAA;AAC1E,QAAA,MAAM,gBAAA,GAAmB,YAAY,IAAA,CAAK,cAAA,GAAiB,KAAK,WAAA,CAAY,IAAA,CAAK,cAAA,GAAiB,WAAA,CAAY,IAAA,CAAK,UAAA;AAEnH,QAAA,IAAI,aAAA,EAAe;AAEjB,UAAA,MAAM,iBAAiB,kBAAA,CAAmB,2BAAA;AAAA,YACxC,YAAY,IAAA,CAAK,MAAA;AAAA,YACjB,WAAA,CAAY,QAAA;AAAA,YACZ,WAAA,CAAY,IAAI,QAAA,EAAS;AAAA,YACzB;AAAA,cACE,WAAW,UAAA,IAAc,QAAA;AAAA,cACzB,MAAA,EAAQ,+BAA+B,aAAa,CAAA,IAAA,EAAO,WAAW,CAAA,EAAG,MAAA,GAAS,KAAA,GAAQ,MAAA,GAAS,EAAE,CAAA,CAAA;AAAA,cACrG,QAAA,EAAU,EAAE,aAAA,EAAe,WAAA,EAAa,eAAe,MAAA;AAAO;AAChE,WACF;AAEA,UAAA,WAAA,CAAY,IAAA,CAAK,SAAS,WAAA,CAAY,QAAA;AACtC,UAAA,WAAA,CAAY,IAAA,CAAK,UAAA,mBAAa,IAAI,IAAA,EAAK;AAGvC,UAAA,MAAM,wBAAwB,yBAAA,CAA0B,2BAAA;AAAA,YACtD,WAAA,CAAY,MAAA;AAAA,YACZ,kBAAA,CAAmB,SAAA;AAAA,YACnB,WAAA,CAAY,IAAI,QAAA,EAAS;AAAA,YACzB;AAAA,cACE,WAAW,UAAA,IAAc,QAAA;AAAA,cACzB,MAAA,EAAQ,CAAA,+CAAA,CAAA;AAAA,cACR,QAAA,EAAU,EAAE,aAAA,EAAe,WAAA;AAAY;AACzC,WACF;AAEA,UAAA,WAAA,CAAY,SAAS,kBAAA,CAAmB,SAAA;AAGxC,UAAA,MAAA,CAAO,MAAA,CAAO,WAAA,EAAa,gBAAA,CAAiB,WAAA,EAAa,cAAc,CAAC,CAAA;AACxE,UAAA,MAAA,CAAO,MAAA,CAAO,WAAA,EAAa,gBAAA,CAAiB,WAAA,EAAa,qBAAqB,CAAC,CAAA;AAAA,QACjF,WAAW,gBAAA,EAAkB;AAE3B,UAAA,MAAM,aAAa,kBAAA,CAAmB,2BAAA;AAAA,YACpC,YAAY,IAAA,CAAK,MAAA;AAAA,YACjB,WAAA,CAAY,kBAAA;AAAA,YACZ,WAAA,CAAY,IAAI,QAAA,EAAS;AAAA,YACzB;AAAA,cACE,WAAW,UAAA,IAAc,QAAA;AAAA,cACzB,MAAA,EAAQ,CAAA,wBAAA,EAA2B,aAAa,CAAA,IAAA,EAAO,WAAA,CAAY,IAAA,CAAK,UAAU,CAAA,IAAA,EAAO,WAAW,CAAA,EAAG,MAAA,GAAS,KAAA,GAAQ,SAAS,EAAE,CAAA,CAAA;AAAA,cACnI,QAAA,EAAU;AAAA,gBACR,aAAA;AAAA,gBACA,WAAA;AAAA,gBACA,aAAA,EAAe,MAAA;AAAA,gBACf,aAAA,EAAe,WAAA,CAAY,IAAA,CAAK,UAAA,GAAa,YAAY,IAAA,CAAK;AAAA;AAChE;AACF,WACF;AAEA,UAAA,WAAA,CAAY,IAAA,CAAK,SAAS,WAAA,CAAY,kBAAA;AAGtC,UAAA,MAAA,CAAO,MAAA,CAAO,WAAA,EAAa,gBAAA,CAAiB,WAAA,EAAa,UAAU,CAAC,CAAA;AAAA,QACtE;AAEA,QAAA,IAAI,kBAAkB,WAAA,EAAa;AACjC,UAAC,WAAA,CAAyD,aAAa,MAAM,CAAA;AAAA,QAC/E;AAEA,QAAA,MAAM,YAAY,IAAA,EAAK;AAGvB,QAAA,IAAI,gBAAA,GAAmB,CAAA;AAEvB,QAAA,IAAI,WAAA,CAAY,GAAA,IAAO,WAAA,CAAY,GAAA,GAAM,CAAA,EAAG;AAG1C,UAAA,IAAI,aAAA,KAAkB,eAAA,IAAmB,CAAC,MAAA,EAAQ;AAEhD,YAAA,MAAM,gBAAA,GAAmB,WAAA,CAAY,IAAA,CAAK,iBAAA,IAAqB,CAAA;AAC/D,YAAA,gBAAA,GAAmB,YAAY,GAAA,GAAM,gBAAA;AAAA,UACvC,CAAA,MAAO;AAGL,YAAA,MAAM,WAAA,GAAc,WAAA,CAAY,MAAA,GAAS,WAAA,CAAY,GAAA;AACrD,YAAA,IAAI,cAAc,CAAA,EAAG;AACnB,cAAA,MAAM,QAAA,GAAW,YAAY,GAAA,GAAM,WAAA;AACnC,cAAA,gBAAA,GAAmB,IAAA,CAAK,KAAA,CAAM,aAAA,GAAgB,QAAQ,CAAA;AAAA,YACxD;AAAA,UACF;AAAA,QACF;AAGA,QAAA,MAAM,mBAAmB,aAAA,GAAgB,gBAAA;AAEzC,QAAA,IAAI,kBAAA,GAAiD,IAAA;AACrD,QAAA,IAAI,iBAAA,EAAmB;AACrB,UAAA,kBAAA,GAAqB,MAAM,iBAAiB,MAAA,CAAO;AAAA,YACjD,gBAAgB,WAAA,CAAY,cAAA;AAAA,YAC5B,UAAA,EAAY,WAAA;AAAA;AAAA,YAGZ,IAAA,EAAM,gBAAA;AAAA,YACN,IAAA,EAAM,QAAA;AAAA,YACN,IAAA,EAAM,CAAC,QAAA,EAAU,SAAS,CAAA;AAAA;AAAA,YAG1B,MAAA,EAAQ,aAAA;AAAA,YACR,UAAU,WAAA,CAAY,QAAA;AAAA,YACtB,GAAA,EAAK,CAAA;AAAA;AAAA,YACL,GAAA,EAAK,gBAAA;AAAA;AAAA,YACL,GAAA,EAAK,gBAAA;AAAA;AAAA,YAGL,GAAI,YAAY,UAAA,IAAc;AAAA,cAC5B,YAAY,WAAA,CAAY;AAAA,aAC1B;AAAA,YAEA,QAAQ,WAAA,CAAY,MAAA;AAAA,YACpB,MAAA,EAAQ,WAAA;AAAA,YACR,SAAS,WAAA,CAAY,OAAA;AAAA;AAAA,YAGrB,UAAU,WAAA,CAAY,GAAA;AAAA,YACtB,WAAA,EAAa,aAAA;AAAA,YACb,sBAAsB,WAAA,CAAY,GAAA;AAAA,YAElC,QAAA,EAAU;AAAA,cACR,GAAG,QAAA;AAAA,cACH,SAAA,EAAW,IAAA;AAAA,cACX,iBAAA,EAAmB,WAAA,CAAY,GAAA,CAAI,QAAA,EAAS;AAAA,cAC5C,aAAA,EAAe,MAAA;AAAA,cACf,aAAA;AAAA;AAAA,cAEA,kBAAkB,WAAA,CAAY;AAAA,aAChC;AAAA,YACA,gBAAgB,CAAA,QAAA,EAAW,WAAA,CAAY,GAAG,CAAA,CAAA,EAAI,IAAA,CAAK,KAAK,CAAA;AAAA,WACzD,CAAA;AAAA,QACH;AAEI,QAAA,IAAA,CAAK,MAAA,CAAO,KAAK,iBAAA,EAAmB;AAAA,UAClC,WAAA;AAAA,UACA,kBAAA;AAAA,UACA,aAAA;AAAA,UACA,WAAA;AAAA,UACA,aAAA;AAAA,UACA,MAAA;AAAA,UACA,aAAA;AAAA,UACA;AAAA,SACD,CAAA;AAED,QAAA,MAAM,MAAA,GAAS;AAAA,UACb,WAAA;AAAA,UACA,kBAAA;AAAA,UACA,aAAA;AAAA,UACA,aAAA;AAAA,UACA;AAAA,SACF;AAGA,QAAA,OAAO,KAAK,OAAA,CAAQ,WAAA;AAAA,UAClB,sBAAA;AAAA,UACA,KAAK,gBAAA,EAAiB;AAAA,UACtB,EAAE,aAAA,EAAe,GAAG,OAAA,EAAQ;AAAA,UAC5B,YAAY;AAAA,SACd;AAAA,MACF;AAAA,KACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,MAAA,CACJ,aAAA,EACA,OAAA,GAA6B,EAAC,EACA;AAC9B,IAAA,MAAM,EAAE,MAAA,GAAS,gBAAA,EAAkB,QAAA,GAAW,IAAG,GAAI,OAAA;AAErD,IAAA,MAAM,gBAAA,GAAmB,KAAK,MAAA,CAAO,WAAA;AACrC,IAAA,MAAM,WAAA,GAAc,MAAM,gBAAA,CAAiB,QAAA,CAAS,aAAa,CAAA;AAEjE,IAAA,IAAI,CAAC,WAAA,EAAa;AAChB,MAAA,MAAM,IAAI,yBAAyB,aAAa,CAAA;AAAA,IAClD;AAEA,IAAA,IAAI,CAAC,WAAA,CAAY,IAAA,IAAQ,YAAY,IAAA,CAAK,MAAA,KAAW,YAAY,IAAA,EAAM;AACrE,MAAA,MAAM,IAAI,2BAAA;AAAA,QACR,aAAA;AAAA,QACA,WAAA,CAAY,IAAI,QAAA,EAAS;AAAA,QACzB,WAAA,CAAY,MAAM,MAAA,IAAU,MAAA;AAAA,QAC5B,WAAA,CAAY;AAAA,OACd;AAAA,IACF;AAGA,IAAA,MAAM,iBAAiB,kBAAA,CAAmB,2BAAA;AAAA,MACxC,YAAY,IAAA,CAAK,MAAA;AAAA,MACjB,WAAA,CAAY,SAAA;AAAA,MACZ,WAAA,CAAY,IAAI,QAAA,EAAS;AAAA,MACzB;AAAA,QACE,SAAA,EAAW,QAAA;AAAA,QACX,MAAA,EAAQ,CAAA,qBAAA,EAAwB,MAAA,GAAS,IAAA,GAAO,SAAS,EAAE,CAAA,CAAA;AAAA,QAC3D,QAAA,EAAU,EAAE,YAAA,EAAc,MAAA,EAAQ,GAAG,QAAA;AAAS;AAChD,KACF;AAEA,IAAA,WAAA,CAAY,IAAA,CAAK,SAAS,WAAA,CAAY,SAAA;AACtC,IAAA,WAAA,CAAY,IAAA,CAAK,WAAA,mBAAc,IAAI,IAAA,EAAK;AACxC,IAAA,WAAA,CAAY,KAAK,QAAA,GAAW;AAAA,MAC1B,GAAG,YAAY,IAAA,CAAK,QAAA;AAAA,MACpB,GAAG,QAAA;AAAA,MACH,YAAA,EAAc;AAAA,KAChB;AAGA,IAAA,MAAM,wBAAwB,yBAAA,CAA0B,2BAAA;AAAA,MACtD,WAAA,CAAY,MAAA;AAAA,MACZ,kBAAA,CAAmB,SAAA;AAAA,MACnB,WAAA,CAAY,IAAI,QAAA,EAAS;AAAA,MACzB;AAAA,QACE,SAAA,EAAW,QAAA;AAAA,QACX,MAAA,EAAQ,CAAA,qDAAA,CAAA;AAAA,QACR,QAAA,EAAU,EAAE,YAAA,EAAc,MAAA;AAAO;AACnC,KACF;AAEA,IAAA,WAAA,CAAY,SAAS,kBAAA,CAAmB,SAAA;AAGxC,IAAA,MAAA,CAAO,MAAA,CAAO,WAAA,EAAa,gBAAA,CAAiB,WAAA,EAAa,cAAc,CAAC,CAAA;AACxE,IAAA,MAAA,CAAO,MAAA,CAAO,WAAA,EAAa,gBAAA,CAAiB,WAAA,EAAa,qBAAqB,CAAC,CAAA;AAE/E,IAAA,IAAI,kBAAkB,WAAA,EAAa;AACjC,MAAC,WAAA,CAAyD,aAAa,MAAM,CAAA;AAAA,IAC/E;AAEA,IAAA,MAAM,YAAY,IAAA,EAAK;AAEvB,IAAA,IAAA,CAAK,MAAA,CAAO,KAAK,kBAAA,EAAoB;AAAA,MACnC,WAAA;AAAA,MACA;AAAA,KACD,CAAA;AAED,IAAA,OAAO,WAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,KAAA,CACJ,aAAA,EACA,UAAA,GAA0B,EAAC,EACL;AACtB,IAAA,MAAM,gBAAA,GAAmB,KAAK,MAAA,CAAO,WAAA;AACrC,IAAA,MAAM,WAAA,GAAc,MAAM,gBAAA,CAAiB,QAAA,CAAS,aAAa,CAAA;AAEjE,IAAA,IAAI,CAAC,WAAA,EAAa;AAChB,MAAA,MAAM,IAAI,yBAAyB,aAAa,CAAA;AAAA,IAClD;AAEA,IAAA,IAAI,CAAC,WAAA,CAAY,IAAA,IAAQ,YAAY,IAAA,CAAK,MAAA,KAAW,YAAY,IAAA,EAAM;AACrE,MAAA,MAAM,IAAI,2BAAA;AAAA,QACR,aAAA;AAAA,QACA,WAAA,CAAY,IAAI,QAAA,EAAS;AAAA,QACzB,WAAA,CAAY,MAAM,MAAA,IAAU,MAAA;AAAA,QAC5B,WAAA,CAAY;AAAA,OACd;AAAA,IACF;AAEA,IAAA,IAAI,CAAC,UAAA,IAAc,UAAA,CAAW,MAAA,KAAW,CAAA,EAAG;AAC1C,MAAA,MAAM,IAAI,eAAA,CAAgB,4BAAA,EAA8B,EAAE,eAAe,CAAA;AAAA,IAC3E;AAEA,IAAA,MAAM,MAAA,GAAS,eAAA;AAAA,MACb,WAAA,CAAY,MAAA;AAAA,MACZ,UAAA;AAAA,MACA,WAAA,CAAY,YAAY,cAAA,IAAkB;AAAA,KAC5C;AAEA,IAAA,WAAA,CAAY,MAAA,GAAS,MAAA;AACrB,IAAA,MAAM,YAAY,IAAA,EAAK;AAEvB,IAAA,MAAM,oBAA2C,EAAC;AAClD,IAAA,MAAM,QAAA,GAAW,YAAY,GAAA,IAAO,CAAA;AACpC,IAAA,MAAM,kBAAkB,WAAA,CAAY,MAAA;AACpC,IAAA,IAAI,kBAAA,GAAqB,CAAA;AACzB,IAAA,MAAM,eAAA,GAAkB,MAAA,CAAO,GAAA,CAAI,CAAC,KAAA,KAAU;AAC5C,MAAA,IAAI,CAAC,QAAA,IAAY,eAAA,IAAmB,CAAA,EAAG;AACrC,QAAA,OAAO,CAAA;AAAA,MACT;AACA,MAAA,MAAM,KAAA,GAAQ,MAAM,WAAA,GAAc,eAAA;AAClC,MAAA,MAAM,SAAA,GAAY,IAAA,CAAK,KAAA,CAAM,QAAA,GAAW,KAAK,CAAA;AAC7C,MAAA,kBAAA,IAAsB,SAAA;AACtB,MAAA,OAAO,SAAA;AAAA,IACT,CAAC,CAAA;AAED,IAAA,KAAA,MAAW,CAAC,KAAA,EAAO,KAAK,CAAA,IAAK,MAAA,CAAO,SAAQ,EAAG;AAE7C,MAAA,MAAM,iBAAiB,QAAA,GAAW,CAAA,GAAI,eAAA,CAAgB,KAAK,KAAK,CAAA,GAAI,CAAA;AAGpE,MAAA,MAAM,cAAA,GAAiB,KAAA,CAAM,WAAA,GAAc,KAAA,CAAM,gBAAA,GAAmB,cAAA;AAEpE,MAAA,MAAM,gBAAA,GAAmB,MAAM,gBAAA,CAAiB,MAAA,CAAO;AAAA,QACrD,gBAAgB,WAAA,CAAY,cAAA;AAAA,QAC5B,YAAY,KAAA,CAAM,WAAA;AAAA;AAAA,QAGlB,MAAM,KAAA,CAAM,IAAA;AAAA,QACZ,IAAA,EAAM,SAAA;AAAA;AAAA,QACN,IAAA,EAAM,CAAC,OAAA,EAAS,YAAY,CAAA;AAAA;AAAA,QAG5B,QAAQ,KAAA,CAAM,WAAA;AAAA;AAAA,QACd,UAAU,WAAA,CAAY,QAAA;AAAA,QACtB,KAAK,KAAA,CAAM,gBAAA;AAAA,QACX,GAAA,EAAK,cAAA;AAAA;AAAA,QACL,GAAA,EAAK,cAAA;AAAA;AAAA;AAAA,QAGL,GAAI,WAAA,CAAY,UAAA,IAAc,cAAA,GAAiB,CAAA,IAAK;AAAA,UAClD,YAAY,WAAA,CAAY;AAAA,SAC1B;AAAA,QAEA,QAAQ,WAAA,CAAY,MAAA;AAAA,QACpB,MAAA,EAAQ,WAAA;AAAA,QACR,SAAS,WAAA,CAAY,OAAA;AAAA;AAAA,QAGrB,UAAU,WAAA,CAAY,GAAA;AAAA,QACtB,WAAA,EAAa,aAAA;AAAA,QACb,sBAAsB,WAAA,CAAY,GAAA;AAAA,QAElC,QAAA,EAAU;AAAA,UACR,OAAA,EAAS,IAAA;AAAA,UACT,WAAW,KAAA,CAAM,IAAA;AAAA,UACjB,eAAe,KAAA,CAAM,aAAA;AAAA,UACrB,qBAAA,EAAuB,WAAA,CAAY,GAAA,CAAI,QAAA,EAAS;AAAA;AAAA,UAEhD,kBAAkB,KAAA,CAAM,WAAA;AAAA,UACxB,gBAAgB,KAAA,CAAM,SAAA;AAAA;AAAA,UACtB,kBAAkB,KAAA,CAAM;AAAA,SAC1B;AAAA,QACA,cAAA,EAAgB,CAAA,MAAA,EAAS,WAAA,CAAY,GAAG,CAAA,CAAA,EAAI,MAAM,WAAW,CAAA,CAAA,EAAI,IAAA,CAAK,GAAA,EAAK,CAAA;AAAA,OAC5E,CAAA;AAED,MAAC,KAAA,CAAuD,mBAAA,GAAsB,gBAAA,CAAiB,GAAA,CAAI,QAAA,EAAS;AAC5G,MAAA,KAAA,CAAM,SAAS,YAAA,CAAa,IAAA;AAC5B,MAAC,KAAA,CAA0C,QAAA,mBAAW,IAAI,IAAA,EAAK;AAE/D,MAAA,iBAAA,CAAkB,KAAK,gBAAgB,CAAA;AAAA,IACzC;AAEA,IAAA,MAAM,YAAY,IAAA,EAAK;AAEvB,IAAA,MAAM,kBAAA,GAAqB,2BAAA,CAA4B,WAAA,CAAY,MAAA,EAAQ,MAAM,CAAA;AACjF,IAAA,MAAM,qBAAA,GAAwB,WAAW,CAAA,GACrC,IAAA,CAAK,IAAI,CAAA,EAAG,QAAA,GAAW,kBAAkB,CAAA,GACzC,CAAA;AACJ,IAAA,MAAM,uBAAA,GAA0B,QAAA,GAAW,CAAA,GACvC,kBAAA,GAAqB,qBAAA,GACrB,kBAAA;AAEJ,IAAA,MAAM,uBAAA,GAA0B,MAAM,IAAA,CAAK,OAAA,CAAQ,aAAA,EAAe;AAAA,MAChE,MAAA,EAAQ,uBAAA;AAAA,MACR,WAAA,EAAa,WAAA,CAAY,cAAA,EAAgB,QAAA,EAAS,IAAK,EAAA;AAAA,MACvD,aAAA,EAAe,cAAA;AAAA,MACf,QAAQ,cAAA,CAAe,gBAAA;AAAA,MACvB,iBAAA,EAAmB,IAAA;AAAA,MACnB,QAAA,EAAU;AAAA,QACR,WAAA,EAAa,IAAA;AAAA,QACb,aAAa,MAAA,CAAO,MAAA;AAAA,QACpB,gBAAA,EAAkB,YAAY,MAAA,GAAS;AAAA;AACzC,KACD,CAAA;AAED,IAAA,IAAA,CAAK,MAAA,CAAO,KAAK,cAAA,EAAgB;AAAA,MAC/B,WAAA;AAAA,MACA,MAAA;AAAA,MACA,iBAAA;AAAA,MACA,yBAAyB,uBAAA,CAAwB,kBAAA;AAAA,MACjD;AAAA,KACD,CAAA;AAED,IAAA,OAAO;AAAA,MACL,WAAA;AAAA,MACA,MAAA;AAAA,MACA,iBAAA;AAAA,MACA,yBAAyB,uBAAA,CAAwB,kBAAA;AAAA,MACjD;AAAA,KACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,UAAU,aAAA,EAAoD;AAClE,IAAA,MAAM,gBAAA,GAAmB,KAAK,MAAA,CAAO,WAAA;AACrC,IAAA,MAAM,WAAA,GAAc,MAAM,gBAAA,CAAiB,QAAA,CAAS,aAAa,CAAA;AAEjE,IAAA,IAAI,CAAC,WAAA,EAAa;AAChB,MAAA,MAAM,IAAI,yBAAyB,aAAa,CAAA;AAAA,IAClD;AAEA,IAAA,OAAO;AAAA,MACL,WAAA;AAAA,MACA,IAAA,EAAM,YAAY,IAAA,IAAQ,IAAA;AAAA,MAC1B,MAAA,EAAQ,WAAA,CAAY,MAAA,IAAU,EAAC;AAAA,MAC/B,OAAA,EAAS,CAAC,CAAC,WAAA,CAAY,IAAA;AAAA,MACvB,WAAW,WAAA,CAAY,MAAA,GAAS,WAAA,CAAY,MAAA,CAAO,SAAS,CAAA,GAAI;AAAA,KAClE;AAAA,EACF;AAEF;;;ACndO,IAAM,oBAAN,MAAwB;AAAA,EACZ,MAAA;AAAA,EACA,OAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EAEjB,YAAY,SAAA,EAAsB;AAChC,IAAA,IAAA,CAAK,MAAA,GAAS,SAAA,CAAU,GAAA,CAAoB,QAAQ,CAAA;AACpD,IAAA,IAAA,CAAK,OAAA,GAAU,SAAA,CAAU,GAAA,CAAmB,SAAS,CAAA;AACrD,IAAA,IAAA,CAAK,MAAA,GAAS,SAAA,CAAU,GAAA,CAAY,QAAQ,CAAA;AAC5C,IAAA,IAAA,CAAK,MAAA,GAAS,SAAA,CAAU,GAAA,CAAc,QAAQ,CAAA;AAG9C,IAAA,KAAK,IAAA,CAAK,OAAA;AAAA,EACZ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,gBAAA,CACJ,aAAA,EACA,OAAA,GAAmC,EAAC,EACL;AAC/B,IAAA,MAAM;AAAA,MACJ,WAAA,uBAAkB,IAAA,EAAK;AAAA,MACvB,YAAA,GAAe,eAAA;AAAA,MACf,WAAW;AAAC,KACd,GAAI,OAAA;AAGJ,IAAA,IAAI,CAAC,IAAA,CAAK,MAAA,CAAO,UAAA,EAAY;AAC3B,MAAA,MAAM,IAAI,wBAAwB,YAAY,CAAA;AAAA,IAChD;AAGA,IAAA,MAAM,gBAAA,GAAmB,KAAK,MAAA,CAAO,WAAA;AACrC,IAAA,MAAM,WAAA,GAAc,MAAM,gBAAA,CAAiB,QAAA,CAAS,aAAa,CAAA;AAEjE,IAAA,IAAI,CAAC,WAAA,EAAa;AAChB,MAAA,MAAM,IAAI,yBAAyB,aAAa,CAAA;AAAA,IAClD;AAGA,IAAA,IAAI,CAAC,WAAA,CAAY,MAAA,IAAU,WAAA,CAAY,MAAA,CAAO,WAAW,CAAA,EAAG;AAC1D,MAAA,MAAM,IAAI,eAAA,CAAgB,qCAAA,EAAuC,EAAE,eAAe,CAAA;AAAA,IACpF;AAGA,IAAA,MAAM,eAAA,GAAkB,KAAK,MAAA,CAAO,UAAA;AACpC,IAAA,MAAM,cAAoC,EAAC;AAE3C,IAAA,KAAA,MAAW,KAAA,IAAS,YAAY,MAAA,EAAQ;AAEtC,MAAA,IAAI,KAAA,CAAM,WAAW,MAAA,EAAQ;AAC3B,QAAA,IAAA,CAAK,OAAO,IAAA,CAAK,8BAAA,EAAgC,EAAE,OAAA,EAAS,KAAA,CAAM,KAAK,CAAA;AACvE,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,UAAA,GAAa,MAAM,eAAA,CAAgB,MAAA,CAAO;AAAA,QAC9C,gBAAgB,WAAA,CAAY,cAAA;AAAA,QAC5B,aAAa,KAAA,CAAM,WAAA;AAAA,QACnB,eAAe,KAAA,CAAM,aAAA;AAAA,QACrB,MAAM,eAAA,CAAgB,YAAA;AAAA,QACtB,QAAQ,iBAAA,CAAkB,OAAA;AAAA,QAC1B,YAAA;AAAA,QACA,QAAQ,KAAA,CAAM,SAAA;AAAA,QACd,UAAU,WAAA,CAAY,QAAA;AAAA,QACtB,oBAAA,EAAsB,CAAC,WAAA,CAAY,GAAG,CAAA;AAAA,QACtC,gBAAgB,CAAC,KAAA,CAAM,GAAA,EAAK,QAAA,MAAc,EAAE,CAAA;AAAA,QAC5C,WAAA;AAAA,QACA,QAAA,EAAU;AAAA,UACR,GAAG,QAAA;AAAA,UACH,WAAW,KAAA,CAAM,IAAA;AAAA,UACjB,qBAAqB,WAAA,CAAY;AAAA;AACnC,OACD,CAAA;AAED,MAAA,WAAA,CAAY,KAAK,UAAU,CAAA;AAAA,IAC7B;AAGA,IAAA,IAAA,CAAK,MAAA,CAAO,KAAK,oBAAA,EAAsB;AAAA,MACrC,WAAA;AAAA,MACA,aAAA;AAAA,MACA,OAAO,WAAA,CAAY;AAAA,KACpB,CAAA;AAED,IAAA,IAAA,CAAK,MAAA,CAAO,KAAK,iCAAA,EAAmC;AAAA,MAClD,aAAA;AAAA,MACA,OAAO,WAAA,CAAY;AAAA,KACpB,CAAA;AAED,IAAA,OAAO,WAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,SAAS,MAAA,EAA+D;AAC5E,IAAA,IAAI,CAAC,IAAA,CAAK,MAAA,CAAO,UAAA,EAAY;AAC3B,MAAA,MAAM,IAAI,wBAAwB,YAAY,CAAA;AAAA,IAChD;AAEA,IAAA,MAAM;AAAA,MACJ,cAAA;AAAA,MACA,WAAA;AAAA,MACA,aAAA;AAAA,MACA,IAAA;AAAA,MACA,MAAA;AAAA,MACA,QAAA,GAAW,KAAA;AAAA,MACX,YAAA;AAAA,MACA,uBAAuB,EAAC;AAAA,MACxB,iBAAiB,EAAC;AAAA,MAClB,WAAA,uBAAkB,IAAA,EAAK;AAAA,MACvB,mBAAA;AAAA,MACA,mBAAA;AAAA,MACA,aAAA;AAAA,MACA,KAAA;AAAA,MACA,WAAW;AAAC,KACd,GAAI,MAAA;AAGJ,IAAA,IAAI,UAAU,CAAA,EAAG;AACf,MAAA,MAAM,IAAI,eAAA,CAAgB,oCAAA,EAAsC,EAAE,QAAQ,CAAA;AAAA,IAC5E;AAEA,IAAA,MAAM,eAAA,GAAkB,KAAK,MAAA,CAAO,UAAA;AACpC,IAAA,MAAM,UAAA,GAAa,MAAM,eAAA,CAAgB,MAAA,CAAO;AAAA,MAC9C,cAAA;AAAA,MACA,WAAA;AAAA,MACA,aAAA;AAAA,MACA,IAAA;AAAA,MACA,QAAQ,iBAAA,CAAkB,OAAA;AAAA,MAC1B,YAAA;AAAA,MACA,MAAA;AAAA,MACA,QAAA;AAAA,MACA,oBAAA;AAAA,MACA,cAAA;AAAA,MACA,WAAA;AAAA,MACA,mBAAA;AAAA,MACA,mBAAA;AAAA,MACA,aAAA;AAAA,MACA,KAAA;AAAA,MACA;AAAA,KACD,CAAA;AAGD,IAAA,IAAA,CAAK,MAAA,CAAO,KAAK,sBAAA,EAAwB;AAAA,MACvC,UAAA;AAAA,MACA;AAAA,KACD,CAAA;AAED,IAAA,IAAA,CAAK,MAAA,CAAO,KAAK,sBAAA,EAAwB;AAAA,MACvC,cAAc,UAAA,CAAW,GAAA;AAAA,MACzB,WAAA;AAAA,MACA;AAAA,KACD,CAAA;AAED,IAAA,OAAO,UAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,cAAA,CAAe,OAAA,GAA0B,EAAC,EAA2B;AACzE,IAAA,IAAI,CAAC,IAAA,CAAK,MAAA,CAAO,UAAA,EAAY;AAC3B,MAAA,MAAM,IAAI,wBAAwB,YAAY,CAAA;AAAA,IAChD;AAEA,IAAA,MAAM;AAAA,MACJ,KAAA,GAAQ,GAAA;AAAA,MACR,cAAA;AAAA,MACA,YAAA;AAAA,MACA,MAAA,GAAS;AAAA,KACX,GAAI,OAAA;AAEJ,IAAA,MAAM,eAAA,GAAkB,KAAK,MAAA,CAAO,UAAA;AAGpC,IAAA,MAAM,KAAA,GAAiC;AAAA,MACrC,QAAQ,iBAAA,CAAkB,OAAA;AAAA,MAC1B,WAAA,EAAa,EAAE,IAAA,kBAAM,IAAI,MAAK;AAAE,KAClC;AAEA,IAAA,IAAI,cAAA,QAAsB,cAAA,GAAiB,cAAA;AAC3C,IAAA,IAAI,YAAA,QAAoB,YAAA,GAAe,YAAA;AAGvC,IAAA,MAAM,WAAA,GAAc,MAAO,eAAA,CAGxB,IAAA,CAAK,KAAK,CAAA,CACV,KAAA,CAAM,KAAK,CAAA,CACX,IAAA,CAAK,EAAE,WAAA,EAAa,GAAG,CAAA;AAE1B,IAAA,MAAM,MAAA,GAAwB;AAAA,MAC5B,SAAA,EAAW,CAAA;AAAA,MACX,SAAA,EAAW,CAAA;AAAA,MACX,MAAA,EAAQ,CAAA;AAAA,MACR,aAAa,EAAC;AAAA,MACd,QAAQ;AAAC,KACX;AAEA,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,IAAA,CAAK,OAAO,IAAA,CAAK,oCAAA,EAAsC,EAAE,KAAA,EAAO,WAAA,CAAY,QAAQ,CAAA;AACpF,MAAA,MAAA,CAAO,WAAA,GAAc,WAAA;AACrB,MAAA,OAAO,MAAA;AAAA,IACT;AAGA,IAAA,KAAA,MAAW,cAAc,WAAA,EAAa;AACpC,MAAA,MAAA,CAAO,SAAA,EAAA;AAEP,MAAA,IAAI;AAEF,QAAA,MAAM,aAAa,wBAAA,CAAyB,2BAAA;AAAA,UAC1C,UAAA,CAAW,MAAA;AAAA,UACX,iBAAA,CAAkB,UAAA;AAAA,UAClB,UAAA,CAAW,IAAI,QAAA,EAAS;AAAA,UACxB;AAAA,YACE,SAAA,EAAW,QAAA;AAAA,YACX,MAAA,EAAQ,+BAAA;AAAA,YACR,UAAU,EAAE,WAAA,EAAa,WAAW,WAAA,EAAa,MAAA,EAAQ,WAAW,MAAA;AAAO;AAC7E,SACF;AAGA,QAAA,UAAA,CAAW,SAAS,iBAAA,CAAkB,UAAA;AACtC,QAAA,UAAA,CAAW,WAAA,uBAAkB,IAAA,EAAK;AAGlC,QAAA,MAAA,CAAO,MAAA,CAAO,UAAA,EAAY,gBAAA,CAAiB,UAAA,EAAY,UAAU,CAAC,CAAA;AAElE,QAAA,MAAM,WAAW,IAAA,EAAK;AAMtB,QAAA,MAAA,CAAO,SAAA,EAAA;AACP,QAAA,MAAA,CAAO,WAAA,CAAY,KAAK,UAAU,CAAA;AAElC,QAAA,IAAA,CAAK,MAAA,CAAO,KAAK,uBAAA,EAAyB;AAAA,UACxC,UAAA;AAAA,UACA,aAAa,UAAA,CAAW;AAAA,SACzB,CAAA;AAAA,MACH,SAAS,KAAA,EAAO;AACd,QAAA,MAAA,CAAO,MAAA,EAAA;AACP,QAAA,MAAA,CAAO,OAAO,IAAA,CAAK;AAAA,UACjB,YAAA,EAAc,UAAA,CAAW,GAAA,CAAI,QAAA,EAAS;AAAA,UACtC,OAAQ,KAAA,CAAgB;AAAA,SACzB,CAAA;AAED,QAAA,IAAA,CAAK,MAAA,CAAO,MAAM,8BAAA,EAAgC;AAAA,UAChD,cAAc,UAAA,CAAW,GAAA;AAAA,UACzB;AAAA,SACD,CAAA;AAAA,MACH;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,uBAAA,EAAyB,MAAM,CAAA;AAEhD,IAAA,OAAO,MAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,QAAA,CACJ,YAAA,EACA,OAAA,GAA6B,EAAC,EACD;AAC7B,IAAA,IAAI,CAAC,IAAA,CAAK,MAAA,CAAO,UAAA,EAAY;AAC3B,MAAA,MAAM,IAAI,wBAAwB,YAAY,CAAA;AAAA,IAChD;AAEA,IAAA,MAAM,eAAA,GAAkB,KAAK,MAAA,CAAO,UAAA;AACpC,IAAA,MAAM,UAAA,GAAa,MAAM,eAAA,CAAgB,QAAA,CAAS,YAAY,CAAA;AAE9D,IAAA,IAAI,CAAC,UAAA,EAAY;AACf,MAAA,MAAM,IAAI,eAAA,CAAgB,sBAAA,EAAwB,EAAE,cAAc,CAAA;AAAA,IACpE;AAGA,IAAA,IAAI,WAAW,MAAA,KAAW,iBAAA,CAAkB,cAAc,UAAA,CAAW,MAAA,KAAW,kBAAkB,OAAA,EAAS;AACzG,MAAA,MAAM,IAAI,2BAAA;AAAA,QACR,UAAA;AAAA,QACA,iBAAA,CAAkB,UAAA;AAAA,QAClB,UAAA,CAAW,MAAA;AAAA,QACX;AAAA,OACF;AAAA,IACF;AAEA,IAAA,MAAM;AAAA,MACJ,iBAAA;AAAA,MACA,aAAA,uBAAoB,IAAA,EAAK;AAAA,MACzB,eAAA;AAAA,MACA,KAAA;AAAA,MACA,WAAW;AAAC,KACd,GAAI,OAAA;AAGJ,IAAA,MAAM,aAAa,wBAAA,CAAyB,2BAAA;AAAA,MAC1C,UAAA,CAAW,MAAA;AAAA,MACX,iBAAA,CAAkB,SAAA;AAAA,MAClB,UAAA,CAAW,IAAI,QAAA,EAAS;AAAA,MACxB;AAAA,QACE,SAAA,EAAW,QAAA;AAAA,QACX,MAAA,EAAQ,mCAAA;AAAA,QACR,QAAA,EAAU;AAAA,UACR,iBAAA;AAAA,UACA,aAAA;AAAA,UACA,eAAA;AAAA,UACA,cAAc,UAAA,CAAW,YAAA;AAAA,UACzB,QAAQ,UAAA,CAAW;AAAA;AACrB;AACF,KACF;AAGA,IAAA,UAAA,CAAW,SAAS,iBAAA,CAAkB,SAAA;AACtC,IAAA,UAAA,CAAW,WAAA,uBAAkB,IAAA,EAAK;AAGlC,IAAA,IAAI,UAAA,CAAW,YAAA,KAAiB,eAAA,IAAmB,iBAAA,EAAmB;AACpE,MAAA,UAAA,CAAW,mBAAA,GAAsB;AAAA,QAC/B,GAAG,UAAA,CAAW,mBAAA;AAAA,QACd,iBAAA;AAAA,QACA;AAAA,OACF;AAAA,IACF,CAAA,MAAA,IAAW,UAAA,CAAW,YAAA,KAAiB,QAAA,IAAY,eAAA,EAAiB;AAClE,MAAA,UAAA,CAAW,aAAA,GAAgB;AAAA,QACzB,GAAG,UAAA,CAAW,aAAA;AAAA,QACd,eAAA;AAAA,QACA;AAAA,OACF;AAAA,IACF,CAAA,MAAA,IAAW,UAAA,CAAW,YAAA,KAAiB,eAAA,EAAiB;AACtD,MAAA,UAAA,CAAW,mBAAA,GAAsB;AAAA,QAC/B,GAAG,UAAA,CAAW,mBAAA;AAAA,QACd;AAAA,OACF;AAAA,IACF,CAAA,MAAA,IAAW,UAAA,CAAW,YAAA,KAAiB,kBAAA,EAAoB;AACzD,MAAA,UAAA,CAAW,sBAAA,GAAyB;AAAA,QAClC,GAAG,UAAA,CAAW,sBAAA;AAAA,QACd,SAAA,EAAW;AAAA,OACb;AAAA,IACF;AAEA,IAAA,IAAI,KAAA,aAAkB,KAAA,GAAQ,KAAA;AAC9B,IAAA,UAAA,CAAW,WAAW,EAAE,GAAG,UAAA,CAAW,QAAA,EAAU,GAAG,QAAA,EAAS;AAG5D,IAAA,MAAA,CAAO,MAAA,CAAO,UAAA,EAAY,gBAAA,CAAiB,UAAA,EAAY,UAAU,CAAC,CAAA;AAElE,IAAA,MAAM,WAAW,IAAA,EAAK;AAGtB,IAAA,IAAA,CAAK,MAAA,CAAO,KAAK,sBAAA,EAAwB;AAAA,MACvC,UAAA;AAAA,MACA,aAAa,UAAA,CAAW;AAAA,KACzB,CAAA;AAED,IAAA,IAAA,CAAK,MAAA,CAAO,KAAK,sBAAA,EAAwB;AAAA,MACvC,cAAc,UAAA,CAAW,GAAA;AAAA,MACzB,aAAa,UAAA,CAAW,WAAA;AAAA,MACxB,QAAQ,UAAA,CAAW;AAAA,KACpB,CAAA;AAED,IAAA,OAAO,UAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,IAAA,CACJ,YAAA,EACA,MAAA,EACA,OAAA,GAA8C,EAAC,EAClB;AAC7B,IAAA,IAAI,CAAC,IAAA,CAAK,MAAA,CAAO,UAAA,EAAY;AAC3B,MAAA,MAAM,IAAI,wBAAwB,YAAY,CAAA;AAAA,IAChD;AAEA,IAAA,MAAM,eAAA,GAAkB,KAAK,MAAA,CAAO,UAAA;AACpC,IAAA,MAAM,UAAA,GAAa,MAAM,eAAA,CAAgB,QAAA,CAAS,YAAY,CAAA;AAE9D,IAAA,IAAI,CAAC,UAAA,EAAY;AACf,MAAA,MAAM,IAAI,eAAA,CAAgB,sBAAA,EAAwB,EAAE,cAAc,CAAA;AAAA,IACpE;AAEA,IAAA,MAAM,EAAE,IAAA,EAAM,KAAA,EAAAE,MAAAA,GAAQ,OAAM,GAAI,OAAA;AAGhC,IAAA,IAAIA,MAAAA,EAAO;AAET,MAAA,MAAM,aAAa,wBAAA,CAAyB,2BAAA;AAAA,QAC1C,UAAA,CAAW,MAAA;AAAA,QACX,iBAAA,CAAkB,OAAA;AAAA,QAClB,UAAA,CAAW,IAAI,QAAA,EAAS;AAAA,QACxB;AAAA,UACE,SAAA,EAAW,QAAA;AAAA,UACX,MAAA,EAAQ,gCAAgC,MAAM,CAAA,CAAA;AAAA,UAC9C,QAAA,EAAU;AAAA,YACR,aAAA,EAAe,MAAA;AAAA,YACf,WAAA,EAAa,IAAA;AAAA,YACb,UAAA,EAAA,CAAa,UAAA,CAAW,UAAA,IAAc,CAAA,IAAK,CAAA;AAAA,YAC3C,WAAA,EAAa,IAAI,IAAA,CAAK,IAAA,CAAK,KAAI,GAAI,EAAA,GAAK,KAAK,GAAI;AAAA;AACnD;AACF,OACF;AAGA,MAAA,UAAA,CAAW,SAAS,iBAAA,CAAkB,OAAA;AACtC,MAAA,UAAA,CAAW,UAAA,GAAA,CAAc,UAAA,CAAW,UAAA,IAAc,CAAA,IAAK,CAAA;AACvD,MAAA,UAAA,CAAW,WAAA,GAAc,IAAI,IAAA,CAAK,IAAA,CAAK,KAAI,GAAI,EAAA,GAAK,KAAK,GAAI,CAAA;AAG7D,MAAA,MAAA,CAAO,MAAA,CAAO,UAAA,EAAY,gBAAA,CAAiB,UAAA,EAAY,UAAU,CAAC,CAAA;AAAA,IACpE,CAAA,MAAO;AAEL,MAAA,MAAM,aAAa,wBAAA,CAAyB,2BAAA;AAAA,QAC1C,UAAA,CAAW,MAAA;AAAA,QACX,iBAAA,CAAkB,MAAA;AAAA,QAClB,UAAA,CAAW,IAAI,QAAA,EAAS;AAAA,QACxB;AAAA,UACE,SAAA,EAAW,QAAA;AAAA,UACX,MAAA,EAAQ,sBAAsB,MAAM,CAAA,CAAA;AAAA,UACpC,QAAA,EAAU;AAAA,YACR,aAAA,EAAe,MAAA;AAAA,YACf,WAAA,EAAa;AAAA;AACf;AACF,OACF;AAEA,MAAA,UAAA,CAAW,SAAS,iBAAA,CAAkB,MAAA;AACtC,MAAA,UAAA,CAAW,QAAA,uBAAe,IAAA,EAAK;AAG/B,MAAA,MAAA,CAAO,MAAA,CAAO,UAAA,EAAY,gBAAA,CAAiB,UAAA,EAAY,UAAU,CAAC,CAAA;AAAA,IACpE;AAEA,IAAA,UAAA,CAAW,aAAA,GAAgB,MAAA;AAC3B,IAAA,IAAI,IAAA,aAAiB,WAAA,GAAc,IAAA;AAEnC,IAAA,MAAM,WAAW,IAAA,EAAK;AAGtB,IAAA,IAAA,CAAK,MAAA,CAAO,KAAK,mBAAA,EAAqB;AAAA,MACpC,UAAA;AAAA,MACA,MAAA;AAAA,MACA,IAAA;AAAA,MACA,KAAA,EAAAA;AAAA,KACD,CAAA;AAED,IAAA,IAAA,CAAK,MAAA,CAAO,KAAK,mBAAA,EAAqB;AAAA,MACpC,cAAc,UAAA,CAAW,GAAA;AAAA,MACzB,MAAA;AAAA,MACA,KAAA,EAAAA;AAAA,KACD,CAAA;AAED,IAAA,OAAO,UAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,IAAA,CAAK,OAAA,GAA6B,EAAC,EAAkC;AACzE,IAAA,IAAI,CAAC,IAAA,CAAK,MAAA,CAAO,UAAA,EAAY;AAC3B,MAAA,MAAM,IAAI,wBAAwB,YAAY,CAAA;AAAA,IAChD;AAEA,IAAA,MAAM,eAAA,GAAkB,KAAK,MAAA,CAAO,UAAA;AACpC,IAAA,MAAM;AAAA,MACJ,cAAA;AAAA,MACA,WAAA;AAAA,MACA,MAAA;AAAA,MACA,IAAA;AAAA,MACA,YAAA;AAAA,MACA,cAAA;AAAA,MACA,eAAA;AAAA,MACA,KAAA,GAAQ,EAAA;AAAA,MACR,IAAA,GAAO,CAAA;AAAA,MACP,IAAA,GAAO,EAAE,SAAA,EAAW,EAAA;AAAG,KACzB,GAAI,OAAA;AAGJ,IAAA,MAAM,QAAiC,EAAC;AAExC,IAAA,IAAI,cAAA,QAAsB,cAAA,GAAiB,cAAA;AAC3C,IAAA,IAAI,WAAA,QAAmB,WAAA,GAAc,WAAA;AACrC,IAAA,IAAI,MAAA,EAAQ,KAAA,CAAM,MAAA,GAAS,KAAA,CAAM,OAAA,CAAQ,MAAM,CAAA,GAAI,EAAE,GAAA,EAAK,MAAA,EAAO,GAAI,MAAA;AACrE,IAAA,IAAI,IAAA,QAAY,IAAA,GAAO,IAAA;AACvB,IAAA,IAAI,YAAA,QAAoB,YAAA,GAAe,YAAA;AAEvC,IAAA,IAAI,kBAAkB,eAAA,EAAiB;AACrC,MAAA,KAAA,CAAM,cAAc,EAAC;AACrB,MAAA,IAAI,cAAA,EAAiB,KAAA,CAAM,WAAA,CAAwC,IAAA,GAAO,cAAA;AAC1E,MAAA,IAAI,eAAA,EAAkB,KAAA,CAAM,WAAA,CAAwC,IAAA,GAAO,eAAA;AAAA,IAC7E;AAEA,IAAA,MAAM,WAAA,GAAc,MAAO,eAAA,CAKxB,IAAA,CAAK,KAAK,CAAA,CACV,KAAA,CAAM,KAAK,CAAA,CACX,IAAA,CAAK,IAAI,CAAA,CACT,KAAK,IAAI,CAAA;AAEZ,IAAA,OAAO,WAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,UAAA,CACJ,WAAA,EACA,OAAA,GAA0B,EAAC,EACC;AAC5B,IAAA,IAAI,CAAC,IAAA,CAAK,MAAA,CAAO,UAAA,EAAY;AAC3B,MAAA,MAAM,IAAI,wBAAwB,YAAY,CAAA;AAAA,IAChD;AAEA,IAAA,MAAM,EAAE,cAAA,EAAgB,SAAA,EAAW,OAAA,EAAQ,GAAI,OAAA;AAE/C,IAAA,MAAM,eAAA,GAAkB,KAAK,MAAA,CAAO,UAAA;AAGpC,IAAA,MAAM,KAAA,GAAiC,EAAE,WAAA,EAAY;AACrD,IAAA,IAAI,cAAA,QAAsB,cAAA,GAAiB,cAAA;AAE3C,IAAA,IAAI,aAAa,OAAA,EAAS;AACxB,MAAA,KAAA,CAAM,YAAY,EAAC;AACnB,MAAA,IAAI,SAAA,EAAY,KAAA,CAAM,SAAA,CAAsC,IAAA,GAAO,SAAA;AACnE,MAAA,IAAI,OAAA,EAAU,KAAA,CAAM,SAAA,CAAsC,IAAA,GAAO,OAAA;AAAA,IACnE;AAGA,IAAA,MAAM,WAAA,GAAc,MAAO,eAAA,CAExB,IAAA,CAAK,KAAK,CAAA;AAGb,IAAA,MAAM,OAAA,GAA6B;AAAA,MACjC,WAAA;AAAA,MACA,YAAA,EAAc,CAAA;AAAA,MACd,eAAA,EAAiB,CAAA;AAAA,MACjB,cAAA,EAAgB,CAAA;AAAA,MAChB,WAAA,EAAa,CAAA;AAAA,MACb,aAAA,EAAe,CAAA;AAAA,MACf,eAAA,EAAiB,CAAA;AAAA,MACjB,YAAA,EAAc,CAAA;AAAA,MACd,QAAA,EAAU,WAAA,CAAY,CAAC,CAAA,EAAG,QAAA,IAAY,KAAA;AAAA,MACtC,WAAA,EAAa;AAAA,QACX,OAAA,EAAS,CAAA;AAAA,QACT,UAAA,EAAY,CAAA;AAAA,QACZ,SAAA,EAAW,CAAA;AAAA,QACX,MAAA,EAAQ,CAAA;AAAA,QACR,SAAA,EAAW;AAAA;AACb,KACF;AAEA,IAAA,KAAA,MAAW,cAAc,WAAA,EAAa;AACpC,MAAA,OAAA,CAAQ,WAAA,CAAY,WAAW,MAA0C,CAAA,EAAA;AAEzE,MAAA,IAAI,UAAA,CAAW,MAAA,KAAW,iBAAA,CAAkB,OAAA,EAAS;AACnD,QAAA,OAAA,CAAQ,YAAA,EAAA;AACR,QAAA,OAAA,CAAQ,iBAAiB,UAAA,CAAW,MAAA;AAAA,MACtC,CAAA,MAAA,IAAW,UAAA,CAAW,MAAA,KAAW,iBAAA,CAAkB,UAAA,EAAY;AAC7D,QAAA,OAAA,CAAQ,eAAA,EAAA;AAAA,MACV,CAAA,MAAA,IAAW,UAAA,CAAW,MAAA,KAAW,iBAAA,CAAkB,SAAA,EAAW;AAC5D,QAAA,OAAA,CAAQ,cAAA,EAAA;AACR,QAAA,OAAA,CAAQ,mBAAmB,UAAA,CAAW,MAAA;AACtC,QAAA,IAAI,CAAC,OAAA,CAAQ,kBAAA,IAAsB,UAAA,CAAW,WAAA,GAAe,QAAQ,kBAAA,EAAoB;AACvF,UAAA,OAAA,CAAQ,qBAAqB,UAAA,CAAW,WAAA;AAAA,QAC1C;AAAA,MACF,CAAA,MAAA,IAAW,UAAA,CAAW,MAAA,KAAW,iBAAA,CAAkB,MAAA,EAAQ;AACzD,QAAA,OAAA,CAAQ,WAAA,EAAA;AACR,QAAA,OAAA,CAAQ,gBAAgB,UAAA,CAAW,MAAA;AAAA,MACrC;AAAA,IACF;AAEA,IAAA,OAAO,OAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,IAAI,YAAA,EAAmD;AAC3D,IAAA,IAAI,CAAC,IAAA,CAAK,MAAA,CAAO,UAAA,EAAY;AAC3B,MAAA,MAAM,IAAI,wBAAwB,YAAY,CAAA;AAAA,IAChD;AAEA,IAAA,MAAM,eAAA,GAAkB,KAAK,MAAA,CAAO,UAAA;AACpC,IAAA,MAAM,UAAA,GAAa,MAAM,eAAA,CAAgB,QAAA,CAAS,YAAY,CAAA;AAE9D,IAAA,IAAI,CAAC,UAAA,EAAY;AACf,MAAA,MAAM,IAAI,eAAA,CAAgB,sBAAA,EAAwB,EAAE,cAAc,CAAA;AAAA,IACpE;AAEA,IAAA,OAAO,UAAA;AAAA,EACT;AAEF","file":"index.js","sourcesContent":["/**\n * Revenue Error Classes\n * @classytic/revenue\n *\n * Typed errors with codes for better error handling\n */\n\nexport interface RevenueErrorOptions {\n retryable?: boolean;\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Base Revenue Error\n */\nexport class RevenueError extends Error {\n public readonly code: string;\n public readonly retryable: boolean;\n public readonly metadata: Record<string, unknown>;\n\n constructor(\n message: string,\n code: string,\n options: RevenueErrorOptions = {}\n ) {\n super(message);\n this.name = this.constructor.name;\n this.code = code;\n this.retryable = options.retryable ?? false;\n this.metadata = options.metadata ?? {};\n Error.captureStackTrace(this, this.constructor);\n }\n\n toJSON(): Record<string, unknown> {\n return {\n name: this.name,\n message: this.message,\n code: this.code,\n retryable: this.retryable,\n metadata: this.metadata,\n };\n }\n}\n\n/**\n * Configuration Errors\n */\nexport class ConfigurationError extends RevenueError {\n constructor(message: string, metadata: Record<string, unknown> = {}) {\n super(message, 'CONFIGURATION_ERROR', { retryable: false, metadata });\n }\n}\n\nexport class ModelNotRegisteredError extends ConfigurationError {\n constructor(modelName: string) {\n super(\n `Model \"${modelName}\" is not registered. Register it via createRevenue({ models: { ${modelName}: ... } })`,\n { modelName }\n );\n }\n}\n\n/**\n * Provider Errors\n */\nexport class ProviderError extends RevenueError {\n constructor(\n message: string,\n code: string,\n options: RevenueErrorOptions = {}\n ) {\n super(message, code, options);\n }\n}\n\nexport class ProviderNotFoundError extends ProviderError {\n constructor(providerName: string, availableProviders: string[] = []) {\n super(\n `Payment provider \"${providerName}\" not found. Available: ${availableProviders.join(', ')}`,\n 'PROVIDER_NOT_FOUND',\n { retryable: false, metadata: { providerName, availableProviders } }\n );\n }\n}\n\nexport class ProviderCapabilityError extends ProviderError {\n constructor(providerName: string, capability: string) {\n super(\n `Provider \"${providerName}\" does not support ${capability}`,\n 'PROVIDER_CAPABILITY_NOT_SUPPORTED',\n { retryable: false, metadata: { providerName, capability } }\n );\n }\n}\n\nexport class PaymentIntentCreationError extends ProviderError {\n constructor(providerName: string, originalError: Error) {\n super(\n `Failed to create payment intent with provider \"${providerName}\": ${originalError.message}`,\n 'PAYMENT_INTENT_CREATION_FAILED',\n { retryable: true, metadata: { providerName, originalError: originalError.message } }\n );\n }\n}\n\nexport class PaymentVerificationError extends ProviderError {\n constructor(paymentIntentId: string, reason: string) {\n super(\n `Payment verification failed for intent \"${paymentIntentId}\": ${reason}`,\n 'PAYMENT_VERIFICATION_FAILED',\n { retryable: true, metadata: { paymentIntentId, reason } }\n );\n }\n}\n\n/**\n * Resource Not Found Errors\n */\nexport class NotFoundError extends RevenueError {\n constructor(\n message: string,\n code: string,\n metadata: Record<string, unknown> = {}\n ) {\n super(message, code, { retryable: false, metadata });\n }\n}\n\nexport class SubscriptionNotFoundError extends NotFoundError {\n constructor(subscriptionId: string) {\n super(\n `Subscription not found: ${subscriptionId}`,\n 'SUBSCRIPTION_NOT_FOUND',\n { subscriptionId }\n );\n }\n}\n\nexport class TransactionNotFoundError extends NotFoundError {\n constructor(transactionId: string) {\n super(\n `Transaction not found: ${transactionId}`,\n 'TRANSACTION_NOT_FOUND',\n { transactionId }\n );\n }\n}\n\n/**\n * Validation Errors\n */\nexport class ValidationError extends RevenueError {\n constructor(message: string, metadata: Record<string, unknown> = {}) {\n super(message, 'VALIDATION_ERROR', { retryable: false, metadata });\n }\n}\n\nexport class InvalidAmountError extends ValidationError {\n constructor(amount: number, message?: string) {\n super(\n message ?? `Invalid amount: ${amount}. Amount must be non-negative`,\n { amount }\n );\n }\n}\n\nexport class MissingRequiredFieldError extends ValidationError {\n constructor(fieldName: string) {\n super(`Missing required field: ${fieldName}`, { fieldName });\n }\n}\n\n/**\n * State Errors\n */\nexport class StateError extends RevenueError {\n constructor(\n message: string,\n code: string,\n metadata: Record<string, unknown> = {}\n ) {\n super(message, code, { retryable: false, metadata });\n }\n}\n\nexport class AlreadyVerifiedError extends StateError {\n constructor(transactionId: string) {\n super(\n `Transaction ${transactionId} is already verified`,\n 'ALREADY_VERIFIED',\n { transactionId }\n );\n }\n}\n\nexport class InvalidStateTransitionError extends StateError {\n constructor(\n resourceType: string,\n resourceId: string,\n fromState: string,\n toState: string\n ) {\n super(\n `Invalid state transition for ${resourceType} ${resourceId}: ${fromState} → ${toState}`,\n 'INVALID_STATE_TRANSITION',\n { resourceType, resourceId, fromState, toState }\n );\n }\n}\n\nexport class SubscriptionNotActiveError extends StateError {\n constructor(subscriptionId: string, message?: string) {\n super(\n message ?? `Subscription ${subscriptionId} is not active`,\n 'SUBSCRIPTION_NOT_ACTIVE',\n { subscriptionId }\n );\n }\n}\n\n/**\n * Operation Errors\n */\nexport class OperationError extends RevenueError {\n constructor(\n message: string,\n code: string,\n options: RevenueErrorOptions = {}\n ) {\n super(message, code, options);\n }\n}\n\nexport class RefundNotSupportedError extends OperationError {\n constructor(providerName: string) {\n super(\n `Refunds are not supported by provider \"${providerName}\"`,\n 'REFUND_NOT_SUPPORTED',\n { retryable: false, metadata: { providerName } }\n );\n }\n}\n\nexport class RefundError extends OperationError {\n constructor(transactionId: string, reason: string) {\n super(\n `Refund failed for transaction ${transactionId}: ${reason}`,\n 'REFUND_FAILED',\n { retryable: true, metadata: { transactionId, reason } }\n );\n }\n}\n\n/**\n * Error Code Constants\n */\nexport const ERROR_CODES = {\n // Configuration\n CONFIGURATION_ERROR: 'CONFIGURATION_ERROR',\n MODEL_NOT_REGISTERED: 'MODEL_NOT_REGISTERED',\n\n // Provider\n PROVIDER_NOT_FOUND: 'PROVIDER_NOT_FOUND',\n PROVIDER_CAPABILITY_NOT_SUPPORTED: 'PROVIDER_CAPABILITY_NOT_SUPPORTED',\n PAYMENT_INTENT_CREATION_FAILED: 'PAYMENT_INTENT_CREATION_FAILED',\n PAYMENT_VERIFICATION_FAILED: 'PAYMENT_VERIFICATION_FAILED',\n\n // Not Found\n SUBSCRIPTION_NOT_FOUND: 'SUBSCRIPTION_NOT_FOUND',\n TRANSACTION_NOT_FOUND: 'TRANSACTION_NOT_FOUND',\n\n // Validation\n VALIDATION_ERROR: 'VALIDATION_ERROR',\n INVALID_AMOUNT: 'INVALID_AMOUNT',\n MISSING_REQUIRED_FIELD: 'MISSING_REQUIRED_FIELD',\n\n // State\n ALREADY_VERIFIED: 'ALREADY_VERIFIED',\n INVALID_STATE_TRANSITION: 'INVALID_STATE_TRANSITION',\n SUBSCRIPTION_NOT_ACTIVE: 'SUBSCRIPTION_NOT_ACTIVE',\n\n // Operations\n REFUND_NOT_SUPPORTED: 'REFUND_NOT_SUPPORTED',\n REFUND_FAILED: 'REFUND_FAILED',\n} as const;\n\nexport type ErrorCode = typeof ERROR_CODES[keyof typeof ERROR_CODES];\n\n/**\n * Check if error is retryable\n */\nexport function isRetryable(error: unknown): boolean {\n return error instanceof RevenueError && error.retryable;\n}\n\n/**\n * Check if error is from revenue package\n */\nexport function isRevenueError(error: unknown): error is RevenueError {\n return error instanceof RevenueError;\n}\n\n","/**\n * Retry Utilities\n * @classytic/revenue\n *\n * Exponential backoff with jitter for resilient operations\n * Inspired by: AWS SDK retry, Netflix Hystrix, resilience4j\n */\n\nimport { Result, ok, err } from '../../../core/result.js';\n\n// ============ TYPES ============\n\nexport interface RetryConfig {\n /** Maximum number of retry attempts (default: 3) */\n maxAttempts: number;\n /** Base delay in milliseconds (default: 1000) */\n baseDelay: number;\n /** Maximum delay in milliseconds (default: 30000) */\n maxDelay: number;\n /** Backoff multiplier (default: 2) */\n backoffMultiplier: number;\n /** Jitter factor 0-1 (default: 0.1) */\n jitter: number;\n /** Which errors are retryable */\n retryIf?: (error: unknown) => boolean;\n /** Callback on each retry */\n onRetry?: (error: unknown, attempt: number, delay: number) => void;\n}\n\nexport interface RetryState {\n attempt: number;\n totalDelay: number;\n errors: Error[];\n}\n\n// ============ DEFAULT CONFIG ============\n\nconst DEFAULT_CONFIG: RetryConfig = {\n maxAttempts: 3,\n baseDelay: 1000,\n maxDelay: 30000,\n backoffMultiplier: 2,\n jitter: 0.1,\n retryIf: isRetryableError,\n};\n\n// ============ RETRY LOGIC ============\n\n/**\n * Calculate delay with exponential backoff and jitter\n */\nexport function calculateDelay(\n attempt: number,\n config: RetryConfig\n): number {\n // Exponential backoff: baseDelay * multiplier^attempt\n const exponentialDelay = config.baseDelay * Math.pow(config.backoffMultiplier, attempt);\n \n // Cap at maxDelay\n const cappedDelay = Math.min(exponentialDelay, config.maxDelay);\n \n // Add jitter (random variance)\n const jitterRange = cappedDelay * config.jitter;\n const jitter = Math.random() * jitterRange * 2 - jitterRange;\n \n return Math.round(Math.max(0, cappedDelay + jitter));\n}\n\n/**\n * Sleep for specified milliseconds\n */\nexport function sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n\n/**\n * Check if error is retryable by default\n */\nexport function isRetryableError(error: unknown): boolean {\n if (!(error instanceof Error)) return false;\n\n // Network errors\n if (error.message.includes('ECONNREFUSED')) return true;\n if (error.message.includes('ETIMEDOUT')) return true;\n if (error.message.includes('ENOTFOUND')) return true;\n if (error.message.includes('network')) return true;\n if (error.message.includes('timeout')) return true;\n\n // Rate limiting\n if (error.message.includes('429')) return true;\n if (error.message.includes('rate limit')) return true;\n\n // Server errors (5xx)\n if (error.message.includes('500')) return true;\n if (error.message.includes('502')) return true;\n if (error.message.includes('503')) return true;\n if (error.message.includes('504')) return true;\n\n // Check for retryable property\n if ('retryable' in error && (error as any).retryable === true) return true;\n\n return false;\n}\n\n/**\n * Execute operation with retry logic\n */\nexport async function retry<T>(\n operation: () => Promise<T>,\n config: Partial<RetryConfig> = {}\n): Promise<T> {\n const fullConfig: RetryConfig = { ...DEFAULT_CONFIG, ...config };\n const state: RetryState = {\n attempt: 0,\n totalDelay: 0,\n errors: [],\n };\n\n while (state.attempt < fullConfig.maxAttempts) {\n try {\n return await operation();\n } catch (error) {\n state.errors.push(error instanceof Error ? error : new Error(String(error)));\n state.attempt++;\n\n // Check if we should retry\n const shouldRetry = fullConfig.retryIf?.(error) ?? isRetryableError(error);\n \n if (!shouldRetry || state.attempt >= fullConfig.maxAttempts) {\n throw new RetryExhaustedError(\n `Operation failed after ${state.attempt} attempts`,\n state.errors\n );\n }\n\n // Calculate delay\n const delay = calculateDelay(state.attempt - 1, fullConfig);\n state.totalDelay += delay;\n\n // Callback\n fullConfig.onRetry?.(error, state.attempt, delay);\n\n // Wait before retry\n await sleep(delay);\n }\n }\n\n // Should never reach here, but TypeScript needs it\n throw new RetryExhaustedError(\n `Operation failed after ${state.attempt} attempts`,\n state.errors\n );\n}\n\n/**\n * Execute operation with retry, returning Result instead of throwing\n */\nexport async function retryWithResult<T>(\n operation: () => Promise<T>,\n config: Partial<RetryConfig> = {}\n): Promise<Result<T, RetryExhaustedError>> {\n try {\n const result = await retry(operation, config);\n return ok(result);\n } catch (error) {\n if (error instanceof RetryExhaustedError) {\n return err(error);\n }\n return err(new RetryExhaustedError('Operation failed', [\n error instanceof Error ? error : new Error(String(error))\n ]));\n }\n}\n\n// ============ ERROR CLASSES ============\n\n/**\n * Error thrown when all retries are exhausted\n */\nexport class RetryExhaustedError extends Error {\n public readonly attempts: number;\n public readonly errors: Error[];\n\n constructor(message: string, errors: Error[]) {\n super(message);\n this.name = 'RetryExhaustedError';\n this.attempts = errors.length;\n this.errors = errors;\n }\n\n /**\n * Get the last error\n */\n get lastError(): Error | undefined {\n return this.errors[this.errors.length - 1];\n }\n\n /**\n * Get the first error\n */\n get firstError(): Error | undefined {\n return this.errors[0];\n }\n}\n\n// ============ CIRCUIT BREAKER ============\n\nexport type CircuitState = 'closed' | 'open' | 'half-open';\n\nexport interface CircuitBreakerConfig {\n /** Number of failures before opening circuit */\n failureThreshold: number;\n /** Time in ms to wait before half-opening */\n resetTimeout: number;\n /** Number of successes in half-open to close circuit */\n successThreshold: number;\n /** Monitor window in ms */\n monitorWindow: number;\n}\n\nconst DEFAULT_CIRCUIT_CONFIG: CircuitBreakerConfig = {\n failureThreshold: 5,\n resetTimeout: 30000,\n successThreshold: 3,\n monitorWindow: 60000,\n};\n\n/**\n * Circuit breaker for preventing cascade failures\n * Inspired by: Netflix Hystrix, resilience4j\n */\nexport class CircuitBreaker {\n private state: CircuitState = 'closed';\n private failures: Date[] = [];\n private successes = 0;\n private lastFailure?: Date;\n private config: CircuitBreakerConfig;\n\n constructor(config: Partial<CircuitBreakerConfig> = {}) {\n this.config = { ...DEFAULT_CIRCUIT_CONFIG, ...config };\n }\n\n /**\n * Execute operation through circuit breaker\n */\n async execute<T>(operation: () => Promise<T>): Promise<T> {\n // Check circuit state\n if (this.state === 'open') {\n if (this.shouldAttemptReset()) {\n this.state = 'half-open';\n } else {\n throw new CircuitOpenError('Circuit is open, request rejected');\n }\n }\n\n try {\n const result = await operation();\n this.onSuccess();\n return result;\n } catch (error) {\n this.onFailure();\n throw error;\n }\n }\n\n /**\n * Execute with Result type\n */\n async executeWithResult<T>(\n operation: () => Promise<T>\n ): Promise<Result<T, CircuitOpenError | Error>> {\n try {\n const result = await this.execute(operation);\n return ok(result);\n } catch (error) {\n return err(error as Error);\n }\n }\n\n private onSuccess(): void {\n if (this.state === 'half-open') {\n this.successes++;\n if (this.successes >= this.config.successThreshold) {\n this.reset();\n }\n }\n // Clean old failures outside monitor window\n this.cleanOldFailures();\n }\n\n private onFailure(): void {\n this.failures.push(new Date());\n this.lastFailure = new Date();\n this.successes = 0;\n\n // Clean old failures\n this.cleanOldFailures();\n\n // Check if we should open circuit\n if (this.failures.length >= this.config.failureThreshold) {\n this.state = 'open';\n }\n }\n\n private shouldAttemptReset(): boolean {\n if (!this.lastFailure) return true;\n return Date.now() - this.lastFailure.getTime() >= this.config.resetTimeout;\n }\n\n private cleanOldFailures(): void {\n const cutoff = Date.now() - this.config.monitorWindow;\n this.failures = this.failures.filter(f => f.getTime() > cutoff);\n }\n\n private reset(): void {\n this.state = 'closed';\n this.failures = [];\n this.successes = 0;\n }\n\n /**\n * Get current circuit state\n */\n getState(): CircuitState {\n return this.state;\n }\n\n /**\n * Manually reset circuit\n */\n forceReset(): void {\n this.reset();\n }\n\n /**\n * Get circuit statistics\n */\n getStats(): {\n state: CircuitState;\n failures: number;\n successes: number;\n lastFailure?: Date;\n } {\n return {\n state: this.state,\n failures: this.failures.length,\n successes: this.successes,\n lastFailure: this.lastFailure,\n };\n }\n}\n\n/**\n * Error thrown when circuit is open\n */\nexport class CircuitOpenError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'CircuitOpenError';\n }\n}\n\n/**\n * Create a circuit breaker\n */\nexport function createCircuitBreaker(\n config?: Partial<CircuitBreakerConfig>\n): CircuitBreaker {\n return new CircuitBreaker(config);\n}\n\n// ============ COMBINED RETRY WITH CIRCUIT BREAKER ============\n\n/**\n * Execute with both retry and circuit breaker\n */\nexport async function resilientExecute<T>(\n operation: () => Promise<T>,\n options: {\n retry?: Partial<RetryConfig>;\n circuitBreaker?: CircuitBreaker;\n } = {}\n): Promise<T> {\n const { retry: retryConfig, circuitBreaker } = options;\n\n const wrappedOperation = async () => {\n if (circuitBreaker) {\n return circuitBreaker.execute(operation);\n }\n return operation();\n };\n\n if (retryConfig) {\n return retry(wrappedOperation, retryConfig);\n }\n\n return wrappedOperation();\n}\n\nexport default retry;\n\n","/**\n * Transaction Enums\n * @classytic/revenue\n *\n * Library-managed transaction enums only.\n * Users should define their own categories and merge with these.\n */\n\n// ============ TRANSACTION FLOW ============\n/**\n * Transaction Flow - Directional money movement\n *\n * INFLOW: Money coming in (payments, subscriptions, purchases, receipts)\n * OUTFLOW: Money going out (refunds, payouts, expenses, disbursements)\n *\n * Industry-standard terminology compatible with QuickBooks, Xero, and other accounting systems.\n * Users can map categories to flow directions via transactionTypeMapping config.\n *\n * @example\n * // Revenue platform\n * { type: 'subscription', flow: 'inflow' }\n *\n * // Payroll platform\n * { type: 'salary', flow: 'outflow' }\n *\n * // Marketplace\n * { type: 'commission', flow: 'outflow' } // Paying sellers\n * { type: 'platform_fee', flow: 'inflow' } // Platform revenue\n */\nexport const TRANSACTION_FLOW = {\n INFLOW: 'inflow',\n OUTFLOW: 'outflow',\n} as const;\n\n/** @deprecated Use TRANSACTION_FLOW instead */\nexport const TRANSACTION_TYPE = TRANSACTION_FLOW;\n\nexport type TransactionFlow = typeof TRANSACTION_FLOW;\nexport type TransactionFlowValue = TransactionFlow[keyof TransactionFlow];\nexport const TRANSACTION_FLOW_VALUES = Object.values(\n TRANSACTION_FLOW,\n) as TransactionFlowValue[];\n\n/** @deprecated Use TransactionFlow instead */\nexport type TransactionType = TransactionFlow;\n/** @deprecated Use TransactionFlowValue instead */\nexport type TransactionTypeValue = TransactionFlowValue;\n/** @deprecated Use TRANSACTION_FLOW_VALUES instead */\nexport const TRANSACTION_TYPE_VALUES = TRANSACTION_FLOW_VALUES;\n\n// ============ TRANSACTION STATUS ============\n/**\n * Transaction Status - Library-managed states\n */\nexport const TRANSACTION_STATUS = {\n PENDING: 'pending',\n PAYMENT_INITIATED: 'payment_initiated',\n PROCESSING: 'processing',\n REQUIRES_ACTION: 'requires_action',\n VERIFIED: 'verified',\n COMPLETED: 'completed',\n FAILED: 'failed',\n CANCELLED: 'cancelled',\n EXPIRED: 'expired',\n REFUNDED: 'refunded',\n PARTIALLY_REFUNDED: 'partially_refunded',\n} as const;\n\nexport type TransactionStatus = typeof TRANSACTION_STATUS;\nexport type TransactionStatusValue = TransactionStatus[keyof TransactionStatus];\nexport const TRANSACTION_STATUS_VALUES = Object.values(\n TRANSACTION_STATUS,\n) as TransactionStatusValue[];\n\n// ============ LIBRARY CATEGORIES ============\n/**\n * Categories managed by this library\n *\n * SUBSCRIPTION: Recurring subscription payments\n * PURCHASE: One-time purchases\n *\n * Users should spread these into their own category enums:\n *\n * @example\n * import { LIBRARY_CATEGORIES } from '@classytic/revenue';\n *\n * export const MY_CATEGORIES = {\n * ...LIBRARY_CATEGORIES,\n * SALARY: 'salary',\n * RENT: 'rent',\n * EQUIPMENT: 'equipment',\n * } as const;\n */\nexport const LIBRARY_CATEGORIES = {\n SUBSCRIPTION: 'subscription',\n PURCHASE: 'purchase',\n} as const;\n\nexport type LibraryCategories = typeof LIBRARY_CATEGORIES;\nexport type LibraryCategoryValue = LibraryCategories[keyof LibraryCategories];\nexport const LIBRARY_CATEGORY_VALUES = Object.values(\n LIBRARY_CATEGORIES,\n) as LibraryCategoryValue[];\n\nconst transactionFlowSet = new Set<TransactionFlowValue>(TRANSACTION_FLOW_VALUES);\nconst transactionStatusSet = new Set<TransactionStatusValue>(\n TRANSACTION_STATUS_VALUES,\n);\nconst libraryCategorySet = new Set<LibraryCategoryValue>(LIBRARY_CATEGORY_VALUES);\n\nexport function isLibraryCategory(value: unknown): value is LibraryCategoryValue {\n return typeof value === 'string' && libraryCategorySet.has(value as LibraryCategoryValue);\n}\n\nexport function isTransactionFlow(value: unknown): value is TransactionFlowValue {\n return typeof value === 'string' && transactionFlowSet.has(value as TransactionFlowValue);\n}\n\n/** @deprecated Use isTransactionFlow instead */\nexport function isTransactionType(value: unknown): value is TransactionTypeValue {\n return isTransactionFlow(value);\n}\n\nexport function isTransactionStatus(\n value: unknown,\n): value is TransactionStatusValue {\n return typeof value === 'string' && transactionStatusSet.has(value as TransactionStatusValue);\n}\n","/**\n * Category Resolver Utility\n * @classytic/revenue\n *\n * Resolves transaction category based on categoryMappings\n */\n\nimport { LIBRARY_CATEGORIES } from '../../../enums/transaction.enums.js';\nimport type { MonetizationTypeValue } from '../../types/index.js';\n\n/**\n * Resolve category for a transaction based on entity and monetizationType\n *\n * Resolution Logic:\n * 1. If categoryMappings[entity] exists → use it\n * 2. Otherwise → fall back to default library category\n *\n * @param entity - The logical entity/identifier (e.g., 'Order', 'PlatformSubscription', 'Membership')\n * NOTE: This is NOT a database model name - it's just a logical identifier\n * @param monetizationType - The monetization type ('subscription', 'purchase', 'free')\n * @param categoryMappings - User-defined category mappings from config\n * @returns Category name for the transaction\n *\n * @example\n * // With mapping defined\n * resolveCategory('Order', 'subscription', { Order: 'order_subscription' })\n * // Returns: 'order_subscription'\n *\n * @example\n * // Without mapping, falls back to library default\n * resolveCategory('Order', 'subscription', {})\n * // Returns: 'subscription'\n *\n * @example\n * // Different entities with different mappings\n * const mappings = {\n * Order: 'order_subscription',\n * PlatformSubscription: 'platform_subscription',\n * TenantUpgrade: 'tenant_upgrade',\n * Membership: 'gym_membership',\n * Enrollment: 'course_enrollment',\n * };\n * resolveCategory('PlatformSubscription', 'subscription', mappings)\n * // Returns: 'platform_subscription'\n */\nexport function resolveCategory(\n entity: string | null | undefined,\n monetizationType: MonetizationTypeValue,\n categoryMappings: Record<string, string> = {}\n): string {\n // If user has defined a custom mapping for this entity, use it\n if (entity && categoryMappings[entity]) {\n return categoryMappings[entity];\n }\n\n // Otherwise, fall back to library default based on monetization type\n switch (monetizationType) {\n case 'subscription':\n return LIBRARY_CATEGORIES.SUBSCRIPTION; // 'subscription'\n case 'purchase':\n return LIBRARY_CATEGORIES.PURCHASE; // 'purchase'\n default:\n return LIBRARY_CATEGORIES.SUBSCRIPTION; // Default to subscription\n }\n}\n\n/**\n * Validate that a category is defined in user's Transaction model enum\n * This is informational - actual validation happens at Mongoose schema level\n *\n * @param category - Category to validate\n * @param allowedCategories - List of allowed categories\n * @returns Whether category is valid\n */\nexport function isCategoryValid(\n category: string,\n allowedCategories: string[] = []\n): boolean {\n return allowedCategories.includes(category);\n}\n\nexport default resolveCategory;\n","/**\n * Commission Calculation Utility\n * @classytic/revenue\n *\n * Handles platform commission calculation with gateway fee deduction\n */\n\nimport type { CommissionInfo } from '../../types/index.js';\nimport { ValidationError } from '../../../core/errors.js';\n\n/**\n * Build commission object for transaction\n *\n * @param amount - Transaction amount\n * @param commissionRate - Commission rate (0 to 1, e.g., 0.10 for 10%)\n * @param gatewayFeeRate - Gateway fee rate (0 to 1, e.g., 0.018 for 1.8%)\n * @returns Commission object or null\n */\nexport function calculateCommission(\n amount: number,\n commissionRate: number,\n gatewayFeeRate: number = 0\n): CommissionInfo | null {\n // No commission if rate is 0 or negative\n if (!commissionRate || commissionRate <= 0) {\n return null;\n }\n\n // Validate inputs\n if (amount < 0) {\n throw new Error('Transaction amount cannot be negative');\n }\n\n if (commissionRate < 0 || commissionRate > 1) {\n throw new Error('Commission rate must be between 0 and 1');\n }\n\n if (gatewayFeeRate < 0 || gatewayFeeRate > 1) {\n throw new Error('Gateway fee rate must be between 0 and 1');\n }\n\n // Calculate commission (integer-only math, amounts are in smallest currency unit)\n const grossAmount = Math.round(amount * commissionRate);\n const gatewayFeeAmount = Math.round(amount * gatewayFeeRate);\n const netAmount = Math.max(0, grossAmount - gatewayFeeAmount);\n\n return {\n rate: commissionRate,\n grossAmount,\n gatewayFeeRate,\n gatewayFeeAmount,\n netAmount,\n status: 'pending',\n };\n}\n\n/**\n * Reverse commission on refund (proportional)\n *\n * @param originalCommission - Original commission object\n * @param originalAmount - Original transaction amount\n * @param refundAmount - Amount being refunded\n * @returns Reversed commission or null\n */\nexport function reverseCommission(\n originalCommission: CommissionInfo | null | undefined,\n originalAmount: number,\n refundAmount: number\n): CommissionInfo | null {\n if (!originalCommission?.netAmount) {\n return null;\n }\n\n // Edge case validations\n if (!originalAmount || originalAmount <= 0) {\n throw new ValidationError('Original amount must be greater than 0', { originalAmount });\n }\n\n if (refundAmount < 0) {\n throw new ValidationError('Refund amount cannot be negative', { refundAmount });\n }\n\n if (refundAmount > originalAmount) {\n throw new ValidationError(\n `Refund amount (${refundAmount}) exceeds original amount (${originalAmount})`,\n { refundAmount, originalAmount }\n );\n }\n\n // Calculate proportional refund (integer-only math)\n const refundRatio = refundAmount / originalAmount;\n const reversedNetAmount = Math.round(originalCommission.netAmount * refundRatio);\n const reversedGrossAmount = Math.round(originalCommission.grossAmount * refundRatio);\n const reversedGatewayFee = Math.round(originalCommission.gatewayFeeAmount * refundRatio);\n\n return {\n rate: originalCommission.rate,\n grossAmount: reversedGrossAmount,\n gatewayFeeRate: originalCommission.gatewayFeeRate,\n gatewayFeeAmount: reversedGatewayFee,\n netAmount: reversedNetAmount,\n status: 'waived', // Commission waived due to refund\n };\n}\n\nexport default {\n calculateCommission,\n reverseCommission,\n};\n\n","/**\n * Config Resolver\n * @classytic/revenue\n *\n * Resolves configuration from builder options to service-ready format\n * Inspired by Stripe's tiered config pattern: global defaults → specific overrides\n */\n\nimport type { RevenueOptions } from '../../core/revenue.js';\nimport type { RevenueConfig } from '../../shared/types/index.js';\n\n/**\n * Resolve builder options to service config\n *\n * Converts singular commission rates to category/gateway maps\n * Uses '*' as global default key (applies to all categories/gateways)\n *\n * @param options - Builder options\n * @returns Service-ready config\n *\n * @example\n * ```typescript\n * const options = {\n * commissionRate: 0.10, // 10% global default\n * gatewayFeeRate: 0.029, // 2.9% global default\n * };\n *\n * const config = resolveConfig(options);\n * // {\n * // commissionRates: { '*': 0.10 },\n * // gatewayFeeRates: { '*': 0.029 }\n * // }\n *\n * // Services can then:\n * const rate = config.commissionRates?.['course_purchase']\n * ?? config.commissionRates?.['*'] // Fallback to global default\n * ?? 0;\n * ```\n */\nexport function resolveConfig(options: Partial<RevenueOptions>): Partial<RevenueConfig> {\n const config: Partial<RevenueConfig> = {\n targetModels: [],\n categoryMappings: {},\n };\n\n // Convert singular commission rate to global default map\n if (options.commissionRate !== undefined) {\n config.commissionRates = {\n '*': options.commissionRate, // Global default for all categories\n };\n }\n\n // Convert singular gateway fee rate to global default map\n if (options.gatewayFeeRate !== undefined) {\n config.gatewayFeeRates = {\n '*': options.gatewayFeeRate, // Global default for all gateways\n };\n }\n\n return config;\n}\n\n/**\n * Get commission rate for a category\n *\n * Follows precedence: specific category → global default → 0\n *\n * @param config - Revenue config\n * @param category - Transaction category\n * @returns Commission rate (0-1)\n *\n * @example\n * ```typescript\n * const rate = getCommissionRate(config, 'course_purchase');\n * // Checks:\n * // 1. config.commissionRates?.['course_purchase']\n * // 2. config.commissionRates?.['*']\n * // 3. 0 (fallback)\n * ```\n */\nexport function getCommissionRate(\n config: Partial<RevenueConfig> | undefined,\n category: string\n): number {\n if (!config?.commissionRates) return 0;\n\n // Try specific category first\n if (category in config.commissionRates) {\n return config.commissionRates[category];\n }\n\n // Fallback to global default\n return config.commissionRates['*'] ?? 0;\n}\n\n/**\n * Get gateway fee rate for a gateway\n *\n * Follows precedence: specific gateway → global default → 0\n *\n * @param config - Revenue config\n * @param gateway - Gateway name (e.g., 'stripe', 'paypal')\n * @returns Gateway fee rate (0-1)\n */\nexport function getGatewayFeeRate(\n config: Partial<RevenueConfig> | undefined,\n gateway: string\n): number {\n if (!config?.gatewayFeeRates) return 0;\n\n // Try specific gateway first\n if (gateway in config.gatewayFeeRates) {\n return config.gatewayFeeRates[gateway];\n }\n\n // Fallback to global default\n return config.gatewayFeeRates['*'] ?? 0;\n}\n\n/**\n * Merge config with overrides\n *\n * Allows per-category/per-gateway overrides while preserving global defaults\n *\n * @param baseConfig - Base config (from builder)\n * @param overrides - Override maps\n * @returns Merged config\n *\n * @example\n * ```typescript\n * const config = resolveConfig({ commissionRate: 0.10 });\n * const merged = mergeConfig(config, {\n * commissionRates: {\n * 'premium_course': 0.05, // Lower rate for premium courses\n * },\n * gatewayFeeRates: {\n * 'crypto': 0.01, // Lower fee for crypto gateway\n * },\n * });\n * // Result:\n * // commissionRates: { '*': 0.10, 'premium_course': 0.05 }\n * // gatewayFeeRates: { '*': 0.029, 'crypto': 0.01 }\n * ```\n */\nexport function mergeConfig(\n baseConfig: Partial<RevenueConfig>,\n overrides: Partial<RevenueConfig>\n): Partial<RevenueConfig> {\n return {\n ...baseConfig,\n commissionRates: {\n ...baseConfig.commissionRates,\n ...overrides.commissionRates,\n },\n gatewayFeeRates: {\n ...baseConfig.gatewayFeeRates,\n ...overrides.gatewayFeeRates,\n },\n categoryMappings: {\n ...baseConfig.categoryMappings,\n ...overrides.categoryMappings,\n },\n targetModels: overrides.targetModels ?? baseConfig.targetModels,\n transactionTypeMapping: {\n ...baseConfig.transactionTypeMapping,\n ...overrides.transactionTypeMapping,\n },\n };\n}\n","/**\n * Monetization Enums\n * @classytic/revenue\n *\n * General monetization enums and constants\n */\n\n// ============ MONETIZATION TYPES ============\nexport const MONETIZATION_TYPES = {\n FREE: 'free',\n PURCHASE: 'purchase',\n SUBSCRIPTION: 'subscription',\n} as const;\n\nexport type MonetizationTypes = typeof MONETIZATION_TYPES;\nexport type MonetizationTypeValue = MonetizationTypes[keyof MonetizationTypes];\nexport const MONETIZATION_TYPE_VALUES = Object.values(\n MONETIZATION_TYPES,\n) as MonetizationTypeValue[];\n\nconst monetizationTypeSet = new Set<MonetizationTypeValue>(MONETIZATION_TYPE_VALUES);\n\nexport function isMonetizationType(\n value: unknown,\n): value is MonetizationTypeValue {\n return (\n typeof value === 'string' &&\n monetizationTypeSet.has(value as MonetizationTypeValue)\n );\n}\n","/**\n * Generic State Machine Validator\n * @classytic/revenue\n *\n * Inspired by Stripe's state transition validation\n * Provides centralized, type-safe state transition management\n */\n\nimport { InvalidStateTransitionError } from '../errors.js';\nimport type { StateChangeEvent } from '../../infrastructure/audit/types.js';\n\n/**\n * Generic State Machine for validating state transitions\n *\n * @template TState - The state type (typically a union of string literals)\n *\n * @example\n * ```typescript\n * const stateMachine = new StateMachine(\n * new Map([\n * ['pending', new Set(['processing', 'failed'])],\n * ['processing', new Set(['completed', 'failed'])],\n * ['completed', new Set([])], // Terminal state\n * ['failed', new Set([])], // Terminal state\n * ]),\n * 'payment'\n * );\n *\n * // Validate transition\n * stateMachine.validate('pending', 'processing', 'pay_123'); // ✅ OK\n * stateMachine.validate('completed', 'pending', 'pay_123'); // ❌ Throws InvalidStateTransitionError\n *\n * // Check without throwing\n * stateMachine.canTransition('pending', 'processing'); // true\n * stateMachine.canTransition('completed', 'pending'); // false\n * ```\n */\nexport class StateMachine<TState extends string> {\n /**\n * @param transitions - Map of state → allowed next states\n * @param resourceType - Type of resource (for error messages)\n */\n constructor(\n private readonly transitions: Map<TState, Set<TState>>,\n private readonly resourceType: string\n ) {}\n\n /**\n * Validate state transition is allowed\n *\n * @param from - Current state\n * @param to - Target state\n * @param resourceId - ID of the resource being transitioned\n * @throws InvalidStateTransitionError if transition is invalid\n *\n * @example\n * ```typescript\n * try {\n * stateMachine.validate('pending', 'completed', 'tx_123');\n * } catch (error) {\n * if (error instanceof InvalidStateTransitionError) {\n * console.error('Invalid transition:', error.message);\n * }\n * }\n * ```\n */\n validate(\n from: TState,\n to: TState,\n resourceId: string\n ): void {\n const allowedTransitions = this.transitions.get(from);\n\n if (!allowedTransitions?.has(to)) {\n throw new InvalidStateTransitionError(\n this.resourceType,\n resourceId,\n from,\n to\n );\n }\n }\n\n /**\n * Check if transition is valid (non-throwing)\n *\n * @param from - Current state\n * @param to - Target state\n * @returns true if transition is allowed\n *\n * @example\n * ```typescript\n * if (stateMachine.canTransition('pending', 'processing')) {\n * // Safe to proceed with transition\n * transaction.status = 'processing';\n * }\n * ```\n */\n canTransition(from: TState, to: TState): boolean {\n return this.transitions.get(from)?.has(to) ?? false;\n }\n\n /**\n * Get all allowed next states from current state\n *\n * @param from - Current state\n * @returns Array of allowed next states\n *\n * @example\n * ```typescript\n * const nextStates = stateMachine.getAllowedTransitions('pending');\n * console.log(nextStates); // ['processing', 'failed']\n * ```\n */\n getAllowedTransitions(from: TState): TState[] {\n return Array.from(this.transitions.get(from) ?? []);\n }\n\n /**\n * Check if state is terminal (no outgoing transitions)\n *\n * @param state - State to check\n * @returns true if state has no outgoing transitions\n *\n * @example\n * ```typescript\n * stateMachine.isTerminalState('completed'); // true\n * stateMachine.isTerminalState('pending'); // false\n * ```\n */\n isTerminalState(state: TState): boolean {\n const transitions = this.transitions.get(state);\n return !transitions || transitions.size === 0;\n }\n\n /**\n * Get the resource type this state machine manages\n *\n * @returns Resource type string\n */\n getResourceType(): string {\n return this.resourceType;\n }\n\n /**\n * Validate state transition and create audit event\n *\n * This is a convenience method that combines validation with audit event creation.\n * Use this when you want to both validate a transition and record it in the audit trail.\n *\n * @param from - Current state\n * @param to - Target state\n * @param resourceId - ID of the resource being transitioned\n * @param context - Optional audit context (who, why, metadata)\n * @returns StateChangeEvent ready to be appended to document metadata\n * @throws InvalidStateTransitionError if transition is invalid\n *\n * @example\n * ```typescript\n * import { appendAuditEvent } from '@classytic/revenue';\n *\n * // Validate and create audit event\n * const auditEvent = TRANSACTION_STATE_MACHINE.validateAndCreateAuditEvent(\n * transaction.status,\n * 'verified',\n * transaction._id.toString(),\n * {\n * changedBy: 'admin_123',\n * reason: 'Payment verified by payment gateway',\n * metadata: { verificationId: 'ver_abc' }\n * }\n * );\n *\n * // Apply state change\n * transaction.status = 'verified';\n *\n * // Append audit event to metadata\n * Object.assign(transaction, appendAuditEvent(transaction, auditEvent));\n *\n * // Save\n * await transaction.save();\n * ```\n */\n validateAndCreateAuditEvent(\n from: TState,\n to: TState,\n resourceId: string,\n context?: {\n changedBy?: string;\n reason?: string;\n metadata?: Record<string, unknown>;\n }\n ): StateChangeEvent<TState> {\n // First validate the transition (throws if invalid)\n this.validate(from, to, resourceId);\n\n // Then create and return the audit event\n return {\n resourceType: this.resourceType,\n resourceId,\n fromState: from,\n toState: to,\n changedAt: new Date(),\n changedBy: context?.changedBy,\n reason: context?.reason,\n metadata: context?.metadata,\n };\n }\n}\n","/**\n * Subscription Enums\n * @classytic/revenue\n *\n * All subscription-related enums and constants\n */\n\n// ============ SUBSCRIPTION STATUS ============\n/**\n * Subscription Status\n */\nexport const SUBSCRIPTION_STATUS = {\n ACTIVE: 'active',\n PAUSED: 'paused',\n CANCELLED: 'cancelled',\n EXPIRED: 'expired',\n PENDING: 'pending',\n PENDING_RENEWAL: 'pending_renewal',\n INACTIVE: 'inactive',\n} as const;\n\nexport type SubscriptionStatus = typeof SUBSCRIPTION_STATUS;\nexport type SubscriptionStatusValue = SubscriptionStatus[keyof SubscriptionStatus];\nexport const SUBSCRIPTION_STATUS_VALUES = Object.values(\n SUBSCRIPTION_STATUS,\n) as SubscriptionStatusValue[];\n\n// ============ PLAN KEYS ============\n/**\n * Supported plan intervals\n */\nexport const PLAN_KEYS = {\n MONTHLY: 'monthly',\n QUARTERLY: 'quarterly',\n YEARLY: 'yearly',\n} as const;\n\nexport type PlanKeys = typeof PLAN_KEYS;\nexport type PlanKeyValue = PlanKeys[keyof PlanKeys];\nexport const PLAN_KEY_VALUES = Object.values(PLAN_KEYS) as PlanKeyValue[];\n\nconst subscriptionStatusSet = new Set<SubscriptionStatusValue>(\n SUBSCRIPTION_STATUS_VALUES,\n);\nconst planKeySet = new Set<PlanKeyValue>(PLAN_KEY_VALUES);\n\nexport function isSubscriptionStatus(\n value: unknown,\n): value is SubscriptionStatusValue {\n return (\n typeof value === 'string' &&\n subscriptionStatusSet.has(value as SubscriptionStatusValue)\n );\n}\n\nexport function isPlanKey(value: unknown): value is PlanKeyValue {\n return typeof value === 'string' && planKeySet.has(value as PlanKeyValue);\n}\n","/**\n * Settlement Enums\n * @classytic/revenue\n *\n * Enums for settlement/payout tracking\n */\n\n// ============ SETTLEMENT STATUS ============\n\nexport const SETTLEMENT_STATUS = {\n PENDING: 'pending',\n PROCESSING: 'processing',\n COMPLETED: 'completed',\n FAILED: 'failed',\n CANCELLED: 'cancelled',\n} as const;\n\nexport type SettlementStatus = typeof SETTLEMENT_STATUS;\nexport type SettlementStatusValue = SettlementStatus[keyof SettlementStatus];\n\nexport const SETTLEMENT_STATUS_VALUES = Object.values(SETTLEMENT_STATUS);\n\n/**\n * Type guard for settlement status\n */\nexport function isSettlementStatus(value: unknown): value is SettlementStatusValue {\n return typeof value === 'string' && SETTLEMENT_STATUS_VALUES.includes(value as SettlementStatusValue);\n}\n\n// ============ SETTLEMENT TYPE ============\n\nexport const SETTLEMENT_TYPE = {\n SPLIT_PAYOUT: 'split_payout', // Payout to split recipient (vendor/affiliate)\n PLATFORM_WITHDRAWAL: 'platform_withdrawal', // Platform withdraws commission\n MANUAL_PAYOUT: 'manual_payout', // Manual vendor payout\n ESCROW_RELEASE: 'escrow_release', // Release from escrow hold\n} as const;\n\nexport type SettlementType = typeof SETTLEMENT_TYPE;\nexport type SettlementTypeValue = SettlementType[keyof SettlementType];\n\nexport const SETTLEMENT_TYPE_VALUES = Object.values(SETTLEMENT_TYPE);\n\n/**\n * Type guard for settlement type\n */\nexport function isSettlementType(value: unknown): value is SettlementTypeValue {\n return typeof value === 'string' && SETTLEMENT_TYPE_VALUES.includes(value as SettlementTypeValue);\n}\n\n// ============ EXPORTS ============\n\nexport default {\n SETTLEMENT_STATUS,\n SETTLEMENT_STATUS_VALUES,\n SETTLEMENT_TYPE,\n SETTLEMENT_TYPE_VALUES,\n isSettlementStatus,\n isSettlementType,\n};\n","/**\n * Escrow/Hold Enums\n * @classytic/revenue\n *\n * Enums for platform-as-intermediary payment flow\n */\n\nexport const HOLD_STATUS = {\n PENDING: 'pending',\n HELD: 'held',\n RELEASED: 'released',\n CANCELLED: 'cancelled',\n EXPIRED: 'expired',\n PARTIALLY_RELEASED: 'partially_released',\n} as const;\n\nexport type HoldStatus = typeof HOLD_STATUS;\nexport type HoldStatusValue = HoldStatus[keyof HoldStatus];\nexport const HOLD_STATUS_VALUES = Object.values(HOLD_STATUS) as HoldStatusValue[];\n\nexport const RELEASE_REASON = {\n PAYMENT_VERIFIED: 'payment_verified',\n MANUAL_RELEASE: 'manual_release',\n AUTO_RELEASE: 'auto_release',\n DISPUTE_RESOLVED: 'dispute_resolved',\n} as const;\n\nexport type ReleaseReason = typeof RELEASE_REASON;\nexport type ReleaseReasonValue = ReleaseReason[keyof ReleaseReason];\nexport const RELEASE_REASON_VALUES = Object.values(\n RELEASE_REASON,\n) as ReleaseReasonValue[];\n\nexport const HOLD_REASON = {\n PAYMENT_VERIFICATION: 'payment_verification',\n FRAUD_CHECK: 'fraud_check',\n MANUAL_REVIEW: 'manual_review',\n DISPUTE: 'dispute',\n COMPLIANCE: 'compliance',\n} as const;\n\nexport type HoldReason = typeof HOLD_REASON;\nexport type HoldReasonValue = HoldReason[keyof HoldReason];\nexport const HOLD_REASON_VALUES = Object.values(HOLD_REASON) as HoldReasonValue[];\n\nconst holdStatusSet = new Set<HoldStatusValue>(HOLD_STATUS_VALUES);\nconst releaseReasonSet = new Set<ReleaseReasonValue>(RELEASE_REASON_VALUES);\nconst holdReasonSet = new Set<HoldReasonValue>(HOLD_REASON_VALUES);\n\nexport function isHoldStatus(value: unknown): value is HoldStatusValue {\n return typeof value === 'string' && holdStatusSet.has(value as HoldStatusValue);\n}\n\nexport function isReleaseReason(value: unknown): value is ReleaseReasonValue {\n return (\n typeof value === 'string' &&\n releaseReasonSet.has(value as ReleaseReasonValue)\n );\n}\n\nexport function isHoldReason(value: unknown): value is HoldReasonValue {\n return typeof value === 'string' && holdReasonSet.has(value as HoldReasonValue);\n}\n","/**\n * Split Payment Enums\n * @classytic/revenue\n *\n * Enums for multi-party commission splits\n */\n\nexport const SPLIT_TYPE = {\n PLATFORM_COMMISSION: 'platform_commission',\n AFFILIATE_COMMISSION: 'affiliate_commission',\n REFERRAL_COMMISSION: 'referral_commission',\n PARTNER_COMMISSION: 'partner_commission',\n CUSTOM: 'custom',\n} as const;\n\nexport type SplitType = typeof SPLIT_TYPE;\nexport type SplitTypeValue = SplitType[keyof SplitType];\nexport const SPLIT_TYPE_VALUES = Object.values(SPLIT_TYPE) as SplitTypeValue[];\n\nexport const SPLIT_STATUS = {\n PENDING: 'pending',\n DUE: 'due',\n PAID: 'paid',\n WAIVED: 'waived',\n CANCELLED: 'cancelled',\n} as const;\n\nexport type SplitStatus = typeof SPLIT_STATUS;\nexport type SplitStatusValue = SplitStatus[keyof SplitStatus];\nexport const SPLIT_STATUS_VALUES = Object.values(\n SPLIT_STATUS,\n) as SplitStatusValue[];\n\nexport const PAYOUT_METHOD = {\n BANK_TRANSFER: 'bank_transfer',\n MOBILE_WALLET: 'mobile_wallet',\n PLATFORM_BALANCE: 'platform_balance',\n CRYPTO: 'crypto',\n CHECK: 'check',\n MANUAL: 'manual',\n} as const;\n\nexport type PayoutMethod = typeof PAYOUT_METHOD;\nexport type PayoutMethodValue = PayoutMethod[keyof PayoutMethod];\nexport const PAYOUT_METHOD_VALUES = Object.values(PAYOUT_METHOD) as PayoutMethodValue[];\n\nconst splitTypeSet = new Set<SplitTypeValue>(SPLIT_TYPE_VALUES);\nconst splitStatusSet = new Set<SplitStatusValue>(SPLIT_STATUS_VALUES);\nconst payoutMethodSet = new Set<PayoutMethodValue>(PAYOUT_METHOD_VALUES);\n\nexport function isSplitType(value: unknown): value is SplitTypeValue {\n return typeof value === 'string' && splitTypeSet.has(value as SplitTypeValue);\n}\n\nexport function isSplitStatus(value: unknown): value is SplitStatusValue {\n return (\n typeof value === 'string' &&\n splitStatusSet.has(value as SplitStatusValue)\n );\n}\n\nexport function isPayoutMethod(value: unknown): value is PayoutMethodValue {\n return (\n typeof value === 'string' &&\n payoutMethodSet.has(value as PayoutMethodValue)\n );\n}\n","/**\n * State Machine Definitions\n * @classytic/revenue\n *\n * Centralized state transition rules for all entities\n * Inspired by Stripe, PayPal, and Shopify state management patterns\n */\n\nimport { StateMachine } from './StateMachine.js';\nimport {\n TRANSACTION_STATUS,\n type TransactionStatusValue,\n} from '../../enums/transaction.enums.js';\nimport {\n SUBSCRIPTION_STATUS,\n type SubscriptionStatusValue,\n} from '../../enums/subscription.enums.js';\nimport {\n SETTLEMENT_STATUS,\n type SettlementStatusValue,\n} from '../../enums/settlement.enums.js';\nimport {\n HOLD_STATUS,\n type HoldStatusValue,\n} from '../../enums/escrow.enums.js';\nimport {\n SPLIT_STATUS,\n type SplitStatusValue,\n} from '../../enums/split.enums.js';\n\n/**\n * Transaction State Machine\n *\n * Flow:\n * ```\n * pending → payment_initiated → processing → verified → completed\n * ↓ ↓ ↓\n * failed requires_action refunded\n * ↓ partially_refunded\n * failed\n * ```\n *\n * Terminal states: failed, refunded, cancelled, expired\n */\nexport const TRANSACTION_STATE_MACHINE = new StateMachine<TransactionStatusValue>(\n new Map<TransactionStatusValue, Set<TransactionStatusValue>>([\n [\n TRANSACTION_STATUS.PENDING,\n new Set([\n TRANSACTION_STATUS.PAYMENT_INITIATED,\n TRANSACTION_STATUS.PROCESSING,\n TRANSACTION_STATUS.VERIFIED, // Allow direct verification (manual payments)\n TRANSACTION_STATUS.FAILED,\n TRANSACTION_STATUS.CANCELLED,\n ]),\n ],\n [\n TRANSACTION_STATUS.PAYMENT_INITIATED,\n new Set([\n TRANSACTION_STATUS.PROCESSING,\n TRANSACTION_STATUS.VERIFIED, // Allow direct verification (webhook/instant payments)\n TRANSACTION_STATUS.REQUIRES_ACTION,\n TRANSACTION_STATUS.FAILED,\n TRANSACTION_STATUS.CANCELLED,\n ]),\n ],\n [\n TRANSACTION_STATUS.PROCESSING,\n new Set([\n TRANSACTION_STATUS.VERIFIED,\n TRANSACTION_STATUS.REQUIRES_ACTION,\n TRANSACTION_STATUS.FAILED,\n ]),\n ],\n [\n TRANSACTION_STATUS.REQUIRES_ACTION,\n new Set([\n TRANSACTION_STATUS.VERIFIED,\n TRANSACTION_STATUS.FAILED,\n TRANSACTION_STATUS.CANCELLED,\n TRANSACTION_STATUS.EXPIRED,\n ]),\n ],\n [\n TRANSACTION_STATUS.VERIFIED,\n new Set([\n TRANSACTION_STATUS.COMPLETED,\n TRANSACTION_STATUS.REFUNDED,\n TRANSACTION_STATUS.PARTIALLY_REFUNDED,\n TRANSACTION_STATUS.CANCELLED,\n ]),\n ],\n [\n TRANSACTION_STATUS.COMPLETED,\n new Set([\n TRANSACTION_STATUS.REFUNDED,\n TRANSACTION_STATUS.PARTIALLY_REFUNDED,\n ]),\n ],\n [\n TRANSACTION_STATUS.PARTIALLY_REFUNDED,\n new Set([TRANSACTION_STATUS.REFUNDED]),\n ],\n // Terminal states\n [TRANSACTION_STATUS.FAILED, new Set([])],\n [TRANSACTION_STATUS.REFUNDED, new Set([])],\n [TRANSACTION_STATUS.CANCELLED, new Set([])],\n [TRANSACTION_STATUS.EXPIRED, new Set([])],\n ]),\n 'transaction'\n);\n\n/**\n * Subscription State Machine\n *\n * Flow:\n * ```\n * pending → active → paused → active\n * ↓ ↓\n * cancelled cancelled\n * ↓\n * expired\n * ```\n *\n * Terminal states: cancelled, expired\n */\nexport const SUBSCRIPTION_STATE_MACHINE = new StateMachine<SubscriptionStatusValue>(\n new Map<SubscriptionStatusValue, Set<SubscriptionStatusValue>>([\n [\n SUBSCRIPTION_STATUS.PENDING,\n new Set([\n SUBSCRIPTION_STATUS.ACTIVE,\n SUBSCRIPTION_STATUS.CANCELLED,\n ]),\n ],\n [\n SUBSCRIPTION_STATUS.ACTIVE,\n new Set([\n SUBSCRIPTION_STATUS.PAUSED,\n SUBSCRIPTION_STATUS.PENDING_RENEWAL,\n SUBSCRIPTION_STATUS.CANCELLED,\n SUBSCRIPTION_STATUS.EXPIRED,\n ]),\n ],\n [\n SUBSCRIPTION_STATUS.PENDING_RENEWAL,\n new Set([\n SUBSCRIPTION_STATUS.ACTIVE,\n SUBSCRIPTION_STATUS.CANCELLED,\n SUBSCRIPTION_STATUS.EXPIRED,\n ]),\n ],\n [\n SUBSCRIPTION_STATUS.PAUSED,\n new Set([\n SUBSCRIPTION_STATUS.ACTIVE,\n SUBSCRIPTION_STATUS.CANCELLED,\n ]),\n ],\n [\n SUBSCRIPTION_STATUS.INACTIVE,\n new Set([\n SUBSCRIPTION_STATUS.ACTIVE,\n SUBSCRIPTION_STATUS.CANCELLED,\n ]),\n ],\n // Terminal states\n [SUBSCRIPTION_STATUS.CANCELLED, new Set([])],\n [SUBSCRIPTION_STATUS.EXPIRED, new Set([])],\n ]),\n 'subscription'\n);\n\n/**\n * Settlement State Machine\n *\n * Flow:\n * ```\n * pending → processing → completed\n * ↓\n * failed → pending (retry allowed)\n * ```\n *\n * Terminal states: completed, cancelled\n * Note: failed can retry to pending\n */\nexport const SETTLEMENT_STATE_MACHINE = new StateMachine<SettlementStatusValue>(\n new Map<SettlementStatusValue, Set<SettlementStatusValue>>([\n [\n SETTLEMENT_STATUS.PENDING,\n new Set([\n SETTLEMENT_STATUS.PROCESSING,\n SETTLEMENT_STATUS.CANCELLED,\n ]),\n ],\n [\n SETTLEMENT_STATUS.PROCESSING,\n new Set([\n SETTLEMENT_STATUS.COMPLETED,\n SETTLEMENT_STATUS.FAILED,\n ]),\n ],\n [\n SETTLEMENT_STATUS.FAILED,\n new Set([\n SETTLEMENT_STATUS.PENDING, // Allow retry\n SETTLEMENT_STATUS.CANCELLED,\n ]),\n ],\n // Terminal states\n [SETTLEMENT_STATUS.COMPLETED, new Set([])],\n [SETTLEMENT_STATUS.CANCELLED, new Set([])],\n ]),\n 'settlement'\n);\n\n/**\n * Escrow Hold State Machine\n *\n * Flow:\n * ```\n * held → partially_released → released\n * ↓\n * cancelled\n * ```\n *\n * Terminal states: released, cancelled, expired\n */\nexport const HOLD_STATE_MACHINE = new StateMachine<HoldStatusValue>(\n new Map<HoldStatusValue, Set<HoldStatusValue>>([\n [\n HOLD_STATUS.HELD,\n new Set([\n HOLD_STATUS.RELEASED,\n HOLD_STATUS.PARTIALLY_RELEASED,\n HOLD_STATUS.CANCELLED,\n HOLD_STATUS.EXPIRED,\n ]),\n ],\n [\n HOLD_STATUS.PARTIALLY_RELEASED,\n new Set([\n HOLD_STATUS.RELEASED,\n HOLD_STATUS.CANCELLED,\n ]),\n ],\n // Terminal states\n [HOLD_STATUS.RELEASED, new Set([])],\n [HOLD_STATUS.CANCELLED, new Set([])],\n [HOLD_STATUS.EXPIRED, new Set([])],\n ]),\n 'escrow_hold'\n);\n\n/**\n * Split Payment State Machine\n *\n * Flow:\n * ```\n * pending → due → paid\n * ↓\n * waived\n * cancelled\n * ```\n *\n * Terminal states: paid, waived, cancelled\n */\nexport const SPLIT_STATE_MACHINE = new StateMachine<SplitStatusValue>(\n new Map<SplitStatusValue, Set<SplitStatusValue>>([\n [\n SPLIT_STATUS.PENDING,\n new Set([\n SPLIT_STATUS.DUE,\n SPLIT_STATUS.PAID,\n SPLIT_STATUS.WAIVED,\n SPLIT_STATUS.CANCELLED,\n ]),\n ],\n [\n SPLIT_STATUS.DUE,\n new Set([\n SPLIT_STATUS.PAID,\n SPLIT_STATUS.WAIVED,\n SPLIT_STATUS.CANCELLED,\n ]),\n ],\n // Terminal states\n [SPLIT_STATUS.PAID, new Set([])],\n [SPLIT_STATUS.WAIVED, new Set([])],\n [SPLIT_STATUS.CANCELLED, new Set([])],\n ]),\n 'split'\n);\n","/**\n * Audit Trail Types\n * @classytic/revenue\n *\n * State change tracking for compliance and debugging\n * Stored in document.metadata.stateHistory array\n */\n\n/**\n * State Change Audit Event\n * Records who changed what, when, and why\n *\n * Example usage:\n * ```typescript\n * const event: StateChangeEvent = {\n * resourceType: 'transaction',\n * resourceId: 'tx_123',\n * fromState: 'pending',\n * toState: 'verified',\n * changedAt: new Date(),\n * changedBy: 'admin_user_id',\n * reason: 'Payment verified by payment gateway',\n * metadata: { verificationId: 'ver_abc' }\n * };\n * ```\n */\nexport interface StateChangeEvent<TState = string> {\n /** Type of resource (e.g., 'transaction', 'subscription') */\n resourceType: string;\n\n /** Unique identifier of the resource */\n resourceId: string;\n\n /** State before the transition */\n fromState: TState;\n\n /** State after the transition */\n toState: TState;\n\n /** Timestamp when the change occurred */\n changedAt: Date;\n\n /** User ID or system identifier who triggered the change */\n changedBy?: string;\n\n /** Human-readable reason for the state change */\n reason?: string;\n\n /** Additional contextual data */\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Helper to append audit event to document metadata\n *\n * This is a metadata-based approach that stores audit trail\n * directly in the document's metadata.stateHistory array.\n *\n * Example:\n * ```typescript\n * const transaction = await Transaction.findById(id);\n *\n * const auditEvent = {\n * resourceType: 'transaction',\n * resourceId: transaction._id.toString(),\n * fromState: 'pending',\n * toState: 'verified',\n * changedAt: new Date(),\n * changedBy: 'admin_123',\n * };\n *\n * const updated = appendAuditEvent(transaction, auditEvent);\n * await updated.save();\n * ```\n *\n * @param document - Mongoose document or plain object with optional metadata field\n * @param event - State change event to append\n * @returns Updated document with event in metadata.stateHistory\n */\nexport function appendAuditEvent<T extends { metadata?: any }>(\n document: T,\n event: StateChangeEvent\n): T {\n const stateHistory = document.metadata?.stateHistory ?? [];\n\n return {\n ...document,\n metadata: {\n ...document.metadata,\n stateHistory: [...stateHistory, event],\n },\n };\n}\n\n/**\n * Helper to get audit trail from document metadata\n *\n * Example:\n * ```typescript\n * const transaction = await Transaction.findById(id);\n * const history = getAuditTrail(transaction);\n *\n * console.log(history);\n * // [\n * // { fromState: 'pending', toState: 'processing', changedAt: ... },\n * // { fromState: 'processing', toState: 'verified', changedAt: ... },\n * // ]\n * ```\n *\n * @param document - Document to extract audit trail from\n * @returns Array of state change events (empty array if none)\n */\nexport function getAuditTrail<T extends { metadata?: any }>(\n document: T\n): StateChangeEvent[] {\n return document.metadata?.stateHistory ?? [];\n}\n\n/**\n * Helper to get the last state change from audit trail\n *\n * @param document - Document to extract last change from\n * @returns Last state change event or undefined if none\n */\nexport function getLastStateChange<T extends { metadata?: any }>(\n document: T\n): StateChangeEvent | undefined {\n const history = getAuditTrail(document);\n return history[history.length - 1];\n}\n\n/**\n * Helper to find state changes by criteria\n *\n * Example:\n * ```typescript\n * const transaction = await Transaction.findById(id);\n *\n * // Find all changes made by a specific user\n * const userChanges = filterAuditTrail(transaction, {\n * changedBy: 'admin_123'\n * });\n *\n * // Find all transitions to 'failed' state\n * const failures = filterAuditTrail(transaction, {\n * toState: 'failed'\n * });\n * ```\n *\n * @param document - Document to filter audit trail from\n * @param criteria - Filter criteria\n * @returns Filtered array of state change events\n */\nexport function filterAuditTrail<T extends { metadata?: any }>(\n document: T,\n criteria: Partial<StateChangeEvent>\n): StateChangeEvent[] {\n const history = getAuditTrail(document);\n\n return history.filter((event) => {\n return Object.entries(criteria).every(([key, value]) => {\n return event[key as keyof StateChangeEvent] === value;\n });\n });\n}\n","/**\n * Monetization Service\n * @classytic/revenue\n *\n * Framework-agnostic monetization management service with DI\n * Handles purchases, subscriptions, and free items using provider system\n */\n\nimport { nanoid } from 'nanoid';\nimport {\n MissingRequiredFieldError,\n InvalidAmountError,\n ProviderNotFoundError,\n SubscriptionNotFoundError,\n ModelNotRegisteredError,\n SubscriptionNotActiveError,\n PaymentIntentCreationError,\n InvalidStateTransitionError,\n} from '../../core/errors.js';\nimport { retry, type RetryConfig, type CircuitBreaker } from '../../shared/utils/resilience/retry.js';\nimport { resolveCategory } from '../../shared/utils/validators/category-resolver.js';\nimport { calculateCommission } from '../../shared/utils/calculators/commission.js';\nimport { getCommissionRate, getGatewayFeeRate } from '../../infrastructure/config/resolver.js';\nimport { MONETIZATION_TYPES } from '../../enums/monetization.enums.js';\nimport { TRANSACTION_FLOW } from '../../enums/transaction.enums.js';\nimport { SUBSCRIPTION_STATE_MACHINE } from '../../core/state-machine/index.js';\nimport { appendAuditEvent } from '../../infrastructure/audit/index.js';\nimport type { Container } from '../../core/container.js';\nimport type { EventBus } from '../../core/events.js';\nimport type { PluginManager, PluginContext } from '../../core/plugin.js';\nimport type {\n ModelsRegistry,\n ProvidersRegistry,\n RevenueConfig,\n Logger,\n MonetizationCreateParams,\n MonetizationCreateResult,\n ActivateOptions,\n RenewalParams,\n CancelOptions,\n PauseOptions,\n ResumeOptions,\n ListOptions,\n SubscriptionDocument,\n TransactionDocument,\n PaymentIntentData,\n TransactionFlowValue,\n} from '../../shared/types/index.js';\n\n/**\n * Monetization Service\n * Uses DI container for all dependencies\n *\n * Architecture:\n * - PluginManager: Wraps operations with lifecycle hooks (before/after)\n * - EventBus: Fire-and-forget notifications for completed operations\n */\nexport class MonetizationService {\n private readonly models: ModelsRegistry;\n private readonly providers: ProvidersRegistry;\n private readonly config: RevenueConfig;\n private readonly plugins: PluginManager;\n private readonly logger: Logger;\n private readonly events: EventBus;\n private readonly retryConfig: Partial<RetryConfig>;\n private readonly circuitBreaker: CircuitBreaker | null;\n\n constructor(container: Container) {\n this.models = container.get<ModelsRegistry>('models');\n this.providers = container.get<ProvidersRegistry>('providers');\n this.config = container.get<RevenueConfig>('config');\n this.plugins = container.get<PluginManager>('plugins');\n this.logger = container.get<Logger>('logger');\n this.events = container.get<EventBus>('events');\n this.retryConfig = container.get<Partial<RetryConfig>>('retryConfig');\n this.circuitBreaker = container.get<CircuitBreaker | null>('circuitBreaker');\n }\n\n /**\n * Create plugin context for hook execution\n * @private\n */\n private getPluginContext(idempotencyKey?: string | null): PluginContext {\n return {\n events: this.events,\n logger: this.logger,\n storage: new Map(),\n meta: {\n idempotencyKey: idempotencyKey ?? undefined,\n requestId: nanoid(),\n timestamp: new Date(),\n },\n };\n }\n\n /**\n * Execute provider call with retry and circuit breaker protection\n * @private\n */\n private async executeProviderCall<T>(\n operation: () => Promise<T>,\n operationName: string\n ): Promise<T> {\n // Wrap with circuit breaker if configured\n const withCircuitBreaker = this.circuitBreaker\n ? () => this.circuitBreaker!.execute(operation)\n : operation;\n\n // Wrap with retry if configured\n if (this.retryConfig && Object.keys(this.retryConfig).length > 0) {\n return retry(withCircuitBreaker, {\n ...this.retryConfig,\n onRetry: (error, attempt, delay) => {\n this.logger.warn(\n `[${operationName}] Retry attempt ${attempt} after ${delay}ms:`,\n error\n );\n this.retryConfig.onRetry?.(error, attempt, delay);\n },\n });\n }\n\n return withCircuitBreaker();\n }\n\n /**\n * Create a new monetization (purchase, subscription, or free item)\n *\n * @param params - Monetization parameters\n *\n * @example\n * // One-time purchase\n * await revenue.monetization.create({\n * data: {\n * organizationId: '...',\n * customerId: '...',\n * sourceId: order._id,\n * sourceModel: 'Order',\n * },\n * planKey: 'one_time',\n * monetizationType: 'purchase',\n * gateway: 'bkash',\n * amount: 1500,\n * });\n *\n * // Recurring subscription\n * await revenue.monetization.create({\n * data: {\n * organizationId: '...',\n * customerId: '...',\n * sourceId: subscription._id,\n * sourceModel: 'Subscription',\n * },\n * planKey: 'monthly',\n * monetizationType: 'subscription',\n * gateway: 'stripe',\n * amount: 2000,\n * });\n *\n * @returns Result with subscription, transaction, and paymentIntent\n */\n async create(params: MonetizationCreateParams): Promise<MonetizationCreateResult> {\n // Execute before hooks, then operation, then after hooks\n return this.plugins.executeHook(\n 'monetization.create.before',\n this.getPluginContext(params.idempotencyKey),\n params,\n async () => {\n const {\n data,\n planKey,\n amount,\n currency = 'BDT',\n gateway = 'manual',\n entity = null,\n monetizationType = MONETIZATION_TYPES.SUBSCRIPTION,\n paymentData,\n metadata = {},\n idempotencyKey = null,\n } = params;\n\n // Validate required fields\n // Note: organizationId is OPTIONAL (only needed for multi-tenant)\n\n if (!planKey) {\n throw new MissingRequiredFieldError('planKey');\n }\n\n if (amount < 0) {\n throw new InvalidAmountError(amount);\n }\n\n const isFree = amount === 0;\n\n // Get provider\n const provider = this.providers[gateway];\n if (!provider) {\n throw new ProviderNotFoundError(gateway, Object.keys(this.providers));\n }\n\n // Create payment intent if not free\n let paymentIntent: PaymentIntentData | null = null;\n let transaction: TransactionDocument | null = null;\n\n if (!isFree) {\n // Create payment intent via provider\n try {\n paymentIntent = await this.executeProviderCall(\n () => provider.createIntent({\n amount,\n currency,\n metadata: {\n ...metadata,\n type: 'subscription',\n planKey,\n },\n }),\n `${gateway}.createIntent`\n );\n } catch (error) {\n throw new PaymentIntentCreationError(gateway, error as Error);\n }\n\n // Resolve category based on entity and monetizationType\n const category = resolveCategory(entity, monetizationType, this.config.categoryMappings);\n\n // Resolve transaction type using config mapping or default to 'income'\n const transactionFlow: TransactionFlowValue =\n this.config.transactionTypeMapping?.[category] ??\n this.config.transactionTypeMapping?.[monetizationType] ??\n TRANSACTION_FLOW.INFLOW;\n\n // Calculate commission using global defaults with category/gateway-specific overrides\n const commissionRate = getCommissionRate(this.config, category);\n const gatewayFeeRate = getGatewayFeeRate(this.config, gateway);\n const commission = calculateCommission(amount, commissionRate, gatewayFeeRate);\n\n // Read tax if injected by tax plugin (clean, type-safe access)\n const tax = params.tax;\n\n // Create transaction record with unified fields\n const TransactionModel = this.models.Transaction;\n\n // Calculate amounts for unified structure\n // When tax is inclusive, amount should be the base amount (not the total)\n const baseAmount = tax?.pricesIncludeTax ? tax.baseAmount : amount;\n const feeAmount = commission?.gatewayFeeAmount || 0;\n const taxAmount = tax?.taxAmount || 0;\n const netAmount = baseAmount - feeAmount - taxAmount;\n\n transaction = await TransactionModel.create({\n organizationId: data.organizationId,\n customerId: data.customerId ?? null,\n\n // ✅ UNIFIED: Use category as type directly\n type: category, // 'subscription', 'purchase', etc.\n flow: transactionFlow, // ✅ Use config-driven transaction type\n\n // Auto-tagging (middleware will handle, but we can set explicitly)\n tags: category === 'subscription' ? ['recurring', 'subscription'] : [],\n\n // ✅ UNIFIED: Amount structure\n // When prices include tax, use baseAmount (tax already extracted)\n amount: baseAmount,\n currency,\n fee: feeAmount,\n tax: taxAmount,\n net: netAmount,\n\n // ✅ UNIFIED: Tax details (if tax plugin used)\n ...(tax && {\n taxDetails: {\n type: tax.type === 'collected' ? 'sales_tax' : (tax.type === 'paid' ? 'vat' : 'none'),\n rate: tax.rate || 0,\n isInclusive: tax.pricesIncludeTax || false,\n }\n }),\n\n method: ((paymentData as Record<string, unknown>)?.method as string) ?? 'manual',\n status: paymentIntent.status === 'succeeded' ? 'verified' : 'pending', // ✅ Map 'succeeded' to valid TransactionStatusValue\n\n gateway: {\n type: gateway, // Gateway/provider type (e.g., 'stripe', 'manual')\n provider: gateway,\n sessionId: paymentIntent.sessionId,\n paymentIntentId: paymentIntent.paymentIntentId,\n chargeId: paymentIntent.id,\n metadata: paymentIntent.metadata,\n },\n\n paymentDetails: {\n ...paymentData,\n },\n\n // Commission (for marketplace/splits)\n ...(commission && { commission }),\n\n // ✅ UNIFIED: Source reference (renamed from reference)\n ...(data.sourceId && { sourceId: data.sourceId }),\n ...(data.sourceModel && { sourceModel: data.sourceModel }),\n\n metadata: {\n ...metadata,\n planKey,\n entity,\n monetizationType,\n paymentIntentId: paymentIntent.id,\n },\n\n idempotencyKey: idempotencyKey ?? `sub_${nanoid(16)}`,\n }) as TransactionDocument;\n }\n\n // Create subscription record (if Subscription model exists)\n let subscription: SubscriptionDocument | null = null;\n if (this.models.Subscription) {\n const SubscriptionModel = this.models.Subscription;\n\n // Execute subscription.create hooks\n const result = await this.plugins.executeHook(\n 'subscription.create.before',\n this.getPluginContext(idempotencyKey),\n {\n subscriptionId: undefined, // Not yet created - populated in after hook\n planKey,\n customerId: data.customerId,\n organizationId: data.organizationId,\n entity,\n },\n async () => {\n // Create subscription with proper reference tracking\n const subscriptionData = {\n organizationId: data.organizationId,\n customerId: data.customerId ?? null,\n planKey,\n amount,\n currency,\n status: isFree ? 'active' : 'pending',\n isActive: isFree,\n gateway,\n transactionId: transaction?._id ?? null,\n paymentIntentId: paymentIntent?.id ?? null,\n metadata: {\n ...metadata,\n isFree,\n entity,\n monetizationType,\n },\n ...data,\n } as Record<string, unknown>;\n\n // Remove sourceId/sourceModel from subscription (they're for transactions)\n delete subscriptionData.sourceId;\n delete subscriptionData.sourceModel;\n\n const sub = await SubscriptionModel.create(subscriptionData) as SubscriptionDocument;\n\n // Execute after hooks\n await this.plugins.executeHook(\n 'subscription.create.after',\n this.getPluginContext(idempotencyKey),\n {\n subscriptionId: sub._id.toString(),\n planKey,\n customerId: data.customerId,\n organizationId: data.organizationId,\n entity,\n },\n async () => ({ subscription: sub, transaction })\n );\n\n return { subscription: sub, transaction };\n }\n );\n\n subscription = result.subscription;\n }\n\n // Emit general monetization.created event (catch-all)\n this.events.emit('monetization.created', {\n monetizationType,\n subscription: subscription ?? undefined,\n transaction: transaction ?? undefined,\n paymentIntent: paymentIntent ?? undefined,\n });\n\n // Emit specific event based on monetization type\n if (monetizationType === MONETIZATION_TYPES.PURCHASE) {\n // Purchase always requires a transaction\n if (transaction) {\n this.events.emit('purchase.created', {\n monetizationType,\n subscription: subscription ?? undefined,\n transaction,\n paymentIntent: paymentIntent ?? undefined,\n });\n }\n } else if (monetizationType === MONETIZATION_TYPES.SUBSCRIPTION) {\n // Subscription event requires subscription to exist\n if (subscription) {\n this.events.emit('subscription.created', {\n subscriptionId: subscription._id.toString(),\n subscription,\n transactionId: transaction?._id?.toString(),\n });\n }\n } else if (monetizationType === MONETIZATION_TYPES.FREE) {\n // Free can emit even without transaction (amount === 0)\n this.events.emit('free.created', {\n monetizationType,\n subscription: subscription ?? undefined,\n transaction: transaction ?? undefined,\n paymentIntent: paymentIntent ?? undefined,\n });\n }\n\n const result = {\n subscription,\n transaction,\n paymentIntent,\n };\n\n // Execute after hooks\n return this.plugins.executeHook(\n 'monetization.create.after',\n this.getPluginContext(params.idempotencyKey),\n params,\n async () => result\n );\n }\n );\n }\n\n /**\n * Activate subscription after payment verification\n *\n * @param subscriptionId - Subscription ID or transaction ID\n * @param options - Activation options\n * @returns Updated subscription\n */\n async activate(\n subscriptionId: string,\n options: ActivateOptions = {}\n ): Promise<SubscriptionDocument> {\n // Execute before hooks, then operation, then after hooks\n return this.plugins.executeHook(\n 'subscription.activate.before',\n this.getPluginContext(),\n { subscriptionId, ...options },\n async () => {\n const { timestamp = new Date() } = options;\n\n if (!this.models.Subscription) {\n throw new ModelNotRegisteredError('Subscription');\n }\n\n const SubscriptionModel = this.models.Subscription;\n const subscription = await SubscriptionModel.findById(subscriptionId) as SubscriptionDocument | null;\n\n if (!subscription) {\n throw new SubscriptionNotFoundError(subscriptionId);\n }\n\n if (subscription.isActive) {\n this.logger.warn('Subscription already active', { subscriptionId });\n return subscription;\n }\n\n // Calculate period dates based on plan\n const periodEnd = this._calculatePeriodEnd(subscription.planKey, timestamp);\n\n // Validate state transition and create audit event\n const auditEvent = SUBSCRIPTION_STATE_MACHINE.validateAndCreateAuditEvent(\n subscription.status,\n 'active',\n subscription._id.toString(),\n {\n changedBy: 'system',\n reason: `Subscription activated for plan: ${subscription.planKey}`,\n metadata: { planKey: subscription.planKey, startDate: timestamp, endDate: periodEnd }\n }\n );\n\n // Update subscription\n subscription.isActive = true;\n subscription.status = 'active';\n subscription.startDate = timestamp;\n subscription.endDate = periodEnd;\n subscription.activatedAt = timestamp;\n\n // Append audit event to metadata\n Object.assign(subscription, appendAuditEvent(subscription, auditEvent));\n\n await subscription.save();\n\n // Emit event\n this.events.emit('subscription.activated', {\n subscription,\n activatedAt: timestamp,\n });\n\n // Execute after hooks\n return this.plugins.executeHook(\n 'subscription.activate.after',\n this.getPluginContext(),\n { subscriptionId, ...options },\n async () => subscription\n );\n }\n );\n }\n\n /**\n * Renew subscription\n *\n * @param subscriptionId - Subscription ID\n * @param params - Renewal parameters\n * @returns { subscription, transaction, paymentIntent }\n */\n async renew(\n subscriptionId: string,\n params: RenewalParams = {}\n ): Promise<MonetizationCreateResult> {\n const {\n gateway = 'manual',\n entity = null,\n paymentData,\n metadata = {},\n idempotencyKey = null,\n } = params;\n\n if (!this.models.Subscription) {\n throw new ModelNotRegisteredError('Subscription');\n }\n\n const SubscriptionModel = this.models.Subscription;\n const subscription = await SubscriptionModel.findById(subscriptionId) as SubscriptionDocument | null;\n\n if (!subscription) {\n throw new SubscriptionNotFoundError(subscriptionId);\n }\n\n if (subscription.amount === 0) {\n throw new InvalidAmountError(0, 'Free subscriptions do not require renewal');\n }\n\n // Get provider\n const provider = this.providers[gateway];\n if (!provider) {\n throw new ProviderNotFoundError(gateway, Object.keys(this.providers));\n }\n\n // Create payment intent\n let paymentIntent: PaymentIntentData | null = null;\n try {\n paymentIntent = await provider.createIntent({\n amount: subscription.amount,\n currency: subscription.currency ?? 'BDT',\n metadata: {\n ...metadata,\n type: 'subscription_renewal',\n subscriptionId: subscription._id.toString(),\n },\n });\n } catch (error) {\n this.logger.error('Failed to create payment intent for renewal:', error);\n throw new PaymentIntentCreationError(gateway, error as Error);\n }\n\n // Resolve category - use provided entity or inherit from subscription metadata\n const effectiveEntity = entity ?? (subscription.metadata as Record<string, unknown>)?.entity as string | null;\n const effectiveMonetizationType = \n ((subscription.metadata as Record<string, unknown>)?.monetizationType as string) ?? MONETIZATION_TYPES.SUBSCRIPTION;\n const category = resolveCategory(effectiveEntity, effectiveMonetizationType as 'subscription' | 'purchase' | 'free', this.config.categoryMappings);\n\n // Resolve transaction type using config mapping or default to 'income'\n const transactionFlow: TransactionFlowValue =\n this.config.transactionTypeMapping?.[category] ??\n this.config.transactionTypeMapping?.subscription_renewal ??\n this.config.transactionTypeMapping?.[effectiveMonetizationType] ??\n TRANSACTION_FLOW.INFLOW;\n\n // Calculate commission using global defaults with category/gateway-specific overrides\n const commissionRate = getCommissionRate(this.config, category);\n const gatewayFeeRate = getGatewayFeeRate(this.config, gateway);\n const commission = calculateCommission(subscription.amount, commissionRate, gatewayFeeRate);\n\n // Calculate amounts for unified structure\n const feeAmount = commission?.gatewayFeeAmount || 0;\n const netAmount = subscription.amount - feeAmount;\n\n // Create transaction with unified fields\n const TransactionModel = this.models.Transaction;\n const transaction = await TransactionModel.create({\n organizationId: subscription.organizationId,\n customerId: subscription.customerId,\n\n // ✅ UNIFIED: Use category as type directly\n type: category, // 'subscription', etc.\n flow: transactionFlow, // ✅ Use config-driven transaction type\n tags: ['recurring', 'subscription', 'renewal'],\n\n // ✅ UNIFIED: Amount structure\n amount: subscription.amount,\n currency: subscription.currency ?? 'BDT',\n fee: feeAmount,\n tax: 0, // Tax plugin would add this\n net: netAmount,\n\n method: ((paymentData as Record<string, unknown>)?.method as string) ?? 'manual',\n status: paymentIntent.status === 'succeeded' ? 'verified' : 'pending', // ✅ Map 'succeeded' to valid TransactionStatusValue\n\n gateway: {\n provider: gateway,\n sessionId: paymentIntent.sessionId,\n paymentIntentId: paymentIntent.paymentIntentId,\n chargeId: paymentIntent.id,\n metadata: paymentIntent.metadata,\n },\n paymentDetails: {\n provider: gateway,\n ...paymentData,\n },\n // Commission (for marketplace/splits)\n ...(commission && { commission }),\n\n // ✅ UNIFIED: Source reference (renamed from reference)\n sourceId: subscription._id,\n sourceModel: 'Subscription',\n metadata: {\n ...metadata,\n subscriptionId: subscription._id.toString(), // Keep for backward compat\n entity: effectiveEntity,\n monetizationType: effectiveMonetizationType,\n isRenewal: true,\n paymentIntentId: paymentIntent.id,\n },\n idempotencyKey: idempotencyKey ?? `renewal_${nanoid(16)}`,\n }) as TransactionDocument;\n\n // Update subscription\n subscription.status = 'pending_renewal' as SubscriptionDocument['status'];\n subscription.renewalTransactionId = transaction._id;\n subscription.renewalCount = (subscription.renewalCount ?? 0) + 1;\n await subscription.save();\n\n // Emit event\n this.events.emit('subscription.renewed', {\n subscription,\n transaction,\n paymentIntent: paymentIntent ?? undefined,\n renewalCount: subscription.renewalCount,\n });\n\n return {\n subscription,\n transaction,\n paymentIntent,\n };\n }\n\n /**\n * Cancel subscription\n *\n * @param subscriptionId - Subscription ID\n * @param options - Cancellation options\n * @returns Updated subscription\n */\n async cancel(\n subscriptionId: string,\n options: CancelOptions = {}\n ): Promise<SubscriptionDocument> {\n // Execute before hooks, then operation, then after hooks\n return this.plugins.executeHook(\n 'subscription.cancel.before',\n this.getPluginContext(),\n { subscriptionId, ...options },\n async () => {\n const { immediate = false, reason = null } = options;\n\n if (!this.models.Subscription) {\n throw new ModelNotRegisteredError('Subscription');\n }\n\n const SubscriptionModel = this.models.Subscription;\n const subscription = await SubscriptionModel.findById(subscriptionId) as SubscriptionDocument | null;\n\n if (!subscription) {\n throw new SubscriptionNotFoundError(subscriptionId);\n }\n\n const now = new Date();\n\n if (immediate) {\n // Validate state transition and create audit event\n const auditEvent = SUBSCRIPTION_STATE_MACHINE.validateAndCreateAuditEvent(\n subscription.status,\n 'cancelled',\n subscription._id.toString(),\n {\n changedBy: 'system',\n reason: `Subscription cancelled immediately${reason ? ': ' + reason : ''}`,\n metadata: { cancellationReason: reason, immediate: true }\n }\n );\n\n subscription.isActive = false;\n subscription.status = 'cancelled';\n subscription.canceledAt = now;\n subscription.cancellationReason = reason;\n\n // Append audit event to metadata\n Object.assign(subscription, appendAuditEvent(subscription, auditEvent));\n } else {\n // Schedule cancellation at period end\n subscription.cancelAt = subscription.endDate ?? now;\n subscription.cancellationReason = reason;\n }\n\n await subscription.save();\n\n // Emit event\n this.events.emit('subscription.cancelled', {\n subscription,\n immediate,\n reason: reason ?? undefined,\n canceledAt: immediate ? now : subscription.cancelAt!,\n });\n\n // Execute after hooks\n return this.plugins.executeHook(\n 'subscription.cancel.after',\n this.getPluginContext(),\n { subscriptionId, ...options },\n async () => subscription\n );\n }\n );\n }\n\n /**\n * Pause subscription\n *\n * @param subscriptionId - Subscription ID\n * @param options - Pause options\n * @returns Updated subscription\n */\n async pause(\n subscriptionId: string,\n options: PauseOptions = {}\n ): Promise<SubscriptionDocument> {\n // Execute before hooks, then operation, then after hooks\n return this.plugins.executeHook(\n 'subscription.pause.before',\n this.getPluginContext(),\n { subscriptionId, ...options },\n async () => {\n const { reason = null } = options;\n\n if (!this.models.Subscription) {\n throw new ModelNotRegisteredError('Subscription');\n }\n\n const SubscriptionModel = this.models.Subscription;\n const subscription = await SubscriptionModel.findById(subscriptionId) as SubscriptionDocument | null;\n\n if (!subscription) {\n throw new SubscriptionNotFoundError(subscriptionId);\n }\n\n if (!subscription.isActive) {\n throw new SubscriptionNotActiveError(subscriptionId, 'Only active subscriptions can be paused');\n }\n\n const pausedAt = new Date();\n\n // Validate state transition and create audit event\n const auditEvent = SUBSCRIPTION_STATE_MACHINE.validateAndCreateAuditEvent(\n subscription.status,\n 'paused',\n subscription._id.toString(),\n {\n changedBy: 'system',\n reason: `Subscription paused${reason ? ': ' + reason : ''}`,\n metadata: { pauseReason: reason, pausedAt }\n }\n );\n\n subscription.isActive = false;\n subscription.status = 'paused';\n subscription.pausedAt = pausedAt;\n subscription.pauseReason = reason;\n\n // Append audit event to metadata\n Object.assign(subscription, appendAuditEvent(subscription, auditEvent));\n\n await subscription.save();\n\n // Emit event\n this.events.emit('subscription.paused', {\n subscription,\n reason: reason ?? undefined,\n pausedAt,\n });\n\n // Execute after hooks\n return this.plugins.executeHook(\n 'subscription.pause.after',\n this.getPluginContext(),\n { subscriptionId, ...options },\n async () => subscription\n );\n }\n );\n }\n\n /**\n * Resume subscription\n *\n * @param subscriptionId - Subscription ID\n * @param options - Resume options\n * @returns Updated subscription\n */\n async resume(\n subscriptionId: string,\n options: ResumeOptions = {}\n ): Promise<SubscriptionDocument> {\n // Execute before hooks, then operation, then after hooks\n return this.plugins.executeHook(\n 'subscription.resume.before',\n this.getPluginContext(),\n { subscriptionId, ...options },\n async () => {\n const { extendPeriod = false } = options;\n\n if (!this.models.Subscription) {\n throw new ModelNotRegisteredError('Subscription');\n }\n\n const SubscriptionModel = this.models.Subscription;\n const subscription = await SubscriptionModel.findById(subscriptionId) as SubscriptionDocument | null;\n\n if (!subscription) {\n throw new SubscriptionNotFoundError(subscriptionId);\n }\n\n if (!subscription.pausedAt) {\n throw new InvalidStateTransitionError(\n 'resume',\n 'paused',\n subscription.status,\n 'Only paused subscriptions can be resumed'\n );\n }\n\n const now = new Date();\n const pausedAt = new Date(subscription.pausedAt);\n const pauseDuration = now.getTime() - pausedAt.getTime();\n\n // Validate state transition and create audit event\n const auditEvent = SUBSCRIPTION_STATE_MACHINE.validateAndCreateAuditEvent(\n subscription.status,\n 'active',\n subscription._id.toString(),\n {\n changedBy: 'system',\n reason: 'Subscription resumed from paused state',\n metadata: {\n pausedAt,\n pauseDuration,\n extendPeriod,\n newEndDate: extendPeriod && subscription.endDate ? new Date(new Date(subscription.endDate).getTime() + pauseDuration) : undefined\n }\n }\n );\n\n subscription.isActive = true;\n subscription.status = 'active';\n subscription.pausedAt = null;\n subscription.pauseReason = null;\n\n // Optionally extend period by pause duration\n if (extendPeriod && subscription.endDate) {\n const currentEnd = new Date(subscription.endDate);\n subscription.endDate = new Date(currentEnd.getTime() + pauseDuration);\n }\n\n // Append audit event to metadata\n Object.assign(subscription, appendAuditEvent(subscription, auditEvent));\n\n await subscription.save();\n\n // Emit event\n this.events.emit('subscription.resumed', {\n subscription,\n extendPeriod,\n pauseDuration,\n resumedAt: now,\n });\n\n // Execute after hooks\n return this.plugins.executeHook(\n 'subscription.resume.after',\n this.getPluginContext(),\n { subscriptionId, ...options },\n async () => subscription\n );\n }\n );\n }\n\n /**\n * List subscriptions with filters\n *\n * @param filters - Query filters\n * @param options - Query options (limit, skip, sort)\n * @returns Subscriptions\n */\n async list(\n filters: Record<string, unknown> = {},\n options: ListOptions = {}\n ): Promise<SubscriptionDocument[]> {\n if (!this.models.Subscription) {\n throw new ModelNotRegisteredError('Subscription');\n }\n\n const SubscriptionModel = this.models.Subscription;\n const { limit = 50, skip = 0, sort = { createdAt: -1 } } = options;\n\n const subscriptions = await (SubscriptionModel as unknown as {\n find(filter: object): { limit(n: number): { skip(n: number): { sort(s: object): Promise<SubscriptionDocument[]> } } };\n })\n .find(filters)\n .limit(limit)\n .skip(skip)\n .sort(sort);\n\n return subscriptions;\n }\n\n /**\n * Get subscription by ID\n *\n * @param subscriptionId - Subscription ID\n * @returns Subscription\n */\n async get(subscriptionId: string): Promise<SubscriptionDocument> {\n if (!this.models.Subscription) {\n throw new ModelNotRegisteredError('Subscription');\n }\n\n const SubscriptionModel = this.models.Subscription;\n const subscription = await SubscriptionModel.findById(subscriptionId) as SubscriptionDocument | null;\n\n if (!subscription) {\n throw new SubscriptionNotFoundError(subscriptionId);\n }\n\n return subscription;\n }\n\n /**\n * Calculate period end date based on plan key\n * @private\n */\n private _calculatePeriodEnd(planKey: string, startDate: Date = new Date()): Date {\n const start = new Date(startDate);\n const end = new Date(start);\n\n switch (planKey) {\n case 'monthly':\n end.setMonth(end.getMonth() + 1);\n break;\n case 'quarterly':\n end.setMonth(end.getMonth() + 3);\n break;\n case 'yearly':\n end.setFullYear(end.getFullYear() + 1);\n break;\n default:\n // Default to 30 days\n end.setDate(end.getDate() + 30);\n }\n\n return end;\n }\n}\n\nexport default MonetizationService;\n","/**\n * Payment Service\n * @classytic/revenue\n *\n * Framework-agnostic payment verification and management service with DI\n * Handles payment verification, refunds, and status updates\n */\n\nimport {\n TransactionNotFoundError,\n ProviderNotFoundError,\n ProviderError,\n AlreadyVerifiedError,\n PaymentVerificationError,\n RefundNotSupportedError,\n RefundError,\n ProviderCapabilityError,\n ValidationError,\n InvalidStateTransitionError,\n} from '../../core/errors.js';\nimport { reverseCommission } from '../../shared/utils/calculators/commission.js';\nimport { TRANSACTION_FLOW } from '../../enums/transaction.enums.js';\nimport { TRANSACTION_STATE_MACHINE } from '../../core/state-machine/index.js';\nimport { appendAuditEvent } from '../../infrastructure/audit/index.js';\nimport { retry, type RetryConfig, type CircuitBreaker } from '../../shared/utils/resilience/retry.js';\nimport { nanoid } from 'nanoid';\nimport type { Container } from '../../core/container.js';\nimport type { EventBus } from '../../core/events.js';\nimport type { PluginManager, PluginContext } from '../../core/plugin.js';\nimport type {\n ModelsRegistry,\n ProvidersRegistry,\n RevenueConfig,\n Logger,\n TransactionDocument,\n PaymentVerifyOptions,\n PaymentVerifyResult,\n PaymentStatusResult,\n RefundOptions,\n PaymentRefundResult,\n WebhookResult,\n ListOptions,\n PaymentResultData,\n PaymentProviderInterface,\n TransactionFlowValue,\n MongooseModel,\n} from '../../shared/types/index.js';\n\n/**\n * Payment Service\n * Uses DI container for all dependencies\n *\n * Architecture:\n * - PluginManager: Wraps operations with lifecycle hooks (before/after)\n * - EventBus: Fire-and-forget notifications for completed operations\n */\nexport class PaymentService {\n private readonly models: ModelsRegistry;\n private readonly providers: ProvidersRegistry;\n private readonly config: RevenueConfig;\n private readonly plugins: PluginManager;\n private readonly logger: Logger;\n private readonly events: EventBus;\n private readonly retryConfig: Partial<RetryConfig>;\n private readonly circuitBreaker: CircuitBreaker | null;\n\n constructor(container: Container) {\n this.models = container.get<ModelsRegistry>('models');\n this.providers = container.get<ProvidersRegistry>('providers');\n this.config = container.get<RevenueConfig>('config');\n this.plugins = container.get<PluginManager>('plugins');\n this.logger = container.get<Logger>('logger');\n this.events = container.get<EventBus>('events');\n this.retryConfig = container.get<Partial<RetryConfig>>('retryConfig');\n this.circuitBreaker = container.get<CircuitBreaker | null>('circuitBreaker');\n }\n\n /**\n * Create plugin context for hook execution\n * @private\n */\n private getPluginContext(idempotencyKey?: string): PluginContext {\n return {\n events: this.events,\n logger: this.logger,\n storage: new Map(),\n meta: {\n idempotencyKey,\n requestId: nanoid(),\n timestamp: new Date(),\n },\n };\n }\n\n /**\n * Execute provider call with retry and circuit breaker protection\n * @private\n */\n private async executeProviderCall<T>(\n operation: () => Promise<T>,\n operationName: string\n ): Promise<T> {\n // Wrap with circuit breaker if configured\n const withCircuitBreaker = this.circuitBreaker\n ? () => this.circuitBreaker!.execute(operation)\n : operation;\n\n // Wrap with retry if configured\n if (this.retryConfig && Object.keys(this.retryConfig).length > 0) {\n return retry(withCircuitBreaker, {\n ...this.retryConfig,\n onRetry: (error, attempt, delay) => {\n this.logger.warn(\n `[${operationName}] Retry attempt ${attempt} after ${delay}ms:`,\n error\n );\n this.retryConfig.onRetry?.(error, attempt, delay);\n },\n });\n }\n\n return withCircuitBreaker();\n }\n\n /**\n * Verify a payment\n *\n * @param paymentIntentId - Payment intent ID, session ID, or transaction ID\n * @param options - Verification options\n * @returns { transaction, status }\n */\n async verify(\n paymentIntentId: string,\n options: PaymentVerifyOptions = {}\n ): Promise<PaymentVerifyResult> {\n // Execute before hooks, then operation, then after hooks\n return this.plugins.executeHook(\n 'payment.verify.before',\n this.getPluginContext(),\n { id: paymentIntentId, ...options },\n async () => {\n const { verifiedBy = null } = options;\n\n const TransactionModel = this.models.Transaction;\n const transaction = await this._findTransaction(TransactionModel, paymentIntentId);\n\n if (!transaction) {\n throw new TransactionNotFoundError(paymentIntentId);\n }\n\n if (transaction.status === 'verified' || transaction.status === 'completed') {\n throw new AlreadyVerifiedError(transaction._id.toString());\n }\n\n // Get provider for verification\n const gatewayType = transaction.gateway?.type ?? 'manual';\n const provider = this.providers[gatewayType];\n\n if (!provider) {\n throw new ProviderNotFoundError(gatewayType, Object.keys(this.providers));\n }\n\n // Verify payment with provider\n let paymentResult: PaymentResultData | null = null;\n try {\n // Use the actual payment intent ID from the transaction's gateway info\n const actualIntentId = transaction.gateway?.paymentIntentId || transaction.gateway?.sessionId || paymentIntentId;\n paymentResult = await this.executeProviderCall(\n () => provider.verifyPayment(actualIntentId),\n `${gatewayType}.verifyPayment`\n );\n } catch (error) {\n this.logger.error('Payment verification failed:', error);\n\n // Validate state transition and create audit event\n const auditEvent = TRANSACTION_STATE_MACHINE.validateAndCreateAuditEvent(\n transaction.status,\n 'failed',\n transaction._id.toString(),\n {\n changedBy: 'system',\n reason: `Payment verification failed: ${(error as Error).message}`,\n metadata: { error: (error as Error).message }\n }\n );\n\n // Update transaction as failed\n transaction.status = 'failed';\n transaction.failureReason = (error as Error).message;\n\n // Append audit event to metadata\n Object.assign(transaction, appendAuditEvent(transaction, auditEvent));\n\n transaction.metadata = {\n ...transaction.metadata,\n verificationError: (error as Error).message,\n failedAt: new Date().toISOString(),\n };\n await transaction.save();\n\n // Emit payment.failed event\n this.events.emit('payment.failed', {\n transaction,\n error: (error as Error).message,\n provider: gatewayType,\n paymentIntentId,\n });\n\n throw new PaymentVerificationError(paymentIntentId, (error as Error).message);\n }\n\n // Validate amount and currency match\n if (paymentResult.amount && paymentResult.amount !== transaction.amount) {\n throw new ValidationError(\n `Amount mismatch: expected ${transaction.amount}, got ${paymentResult.amount}`,\n { expected: transaction.amount, actual: paymentResult.amount }\n );\n }\n\n if (paymentResult.currency && paymentResult.currency.toUpperCase() !== transaction.currency.toUpperCase()) {\n throw new ValidationError(\n `Currency mismatch: expected ${transaction.currency}, got ${paymentResult.currency}`,\n { expected: transaction.currency, actual: paymentResult.currency }\n );\n }\n\n // Update transaction based on verification result\n const newStatus = paymentResult.status === 'succeeded' ? 'verified' : paymentResult.status;\n\n // Validate state transition and create audit event\n const auditEvent = TRANSACTION_STATE_MACHINE.validateAndCreateAuditEvent(\n transaction.status,\n newStatus,\n transaction._id.toString(),\n {\n changedBy: verifiedBy ?? 'system',\n reason: `Payment verification ${paymentResult.status === 'succeeded' ? 'succeeded' : 'resulted in status: ' + newStatus}`,\n metadata: { paymentResult: paymentResult.metadata }\n }\n );\n\n transaction.status = newStatus;\n transaction.verifiedAt = paymentResult.paidAt ?? new Date();\n transaction.verifiedBy = verifiedBy;\n transaction.gateway = {\n ...transaction.gateway,\n type: transaction.gateway?.type ?? 'manual',\n verificationData: paymentResult.metadata,\n };\n\n // Append audit event to metadata\n Object.assign(transaction, appendAuditEvent(transaction, auditEvent));\n\n await transaction.save();\n\n // Emit appropriate event based on actual status\n if (newStatus === 'verified') {\n this.events.emit('payment.verified', {\n transaction,\n paymentResult,\n verifiedBy: verifiedBy || undefined,\n });\n } else if (newStatus === 'failed') {\n this.events.emit('payment.failed', {\n transaction,\n error: paymentResult.metadata?.errorMessage as string || 'Payment verification failed',\n provider: gatewayType,\n paymentIntentId: transaction.gateway?.paymentIntentId || transaction.gateway?.sessionId || paymentIntentId,\n });\n } else if (newStatus === 'requires_action') {\n this.events.emit('payment.requires_action', {\n transaction,\n paymentResult,\n action: paymentResult.metadata?.requiredAction as string | Record<string, unknown> | undefined,\n });\n } else if (newStatus === 'processing') {\n this.events.emit('payment.processing', {\n transaction,\n paymentResult,\n });\n }\n\n const result = {\n transaction,\n paymentResult,\n status: transaction.status,\n };\n\n // Execute after hooks\n return this.plugins.executeHook(\n 'payment.verify.after',\n this.getPluginContext(),\n { id: paymentIntentId, ...options },\n async () => result\n );\n }\n );\n }\n\n /**\n * Get payment status\n *\n * @param paymentIntentId - Payment intent ID, session ID, or transaction ID\n * @returns { transaction, status }\n */\n async getStatus(paymentIntentId: string): Promise<PaymentStatusResult> {\n const TransactionModel = this.models.Transaction;\n const transaction = await this._findTransaction(TransactionModel, paymentIntentId);\n\n if (!transaction) {\n throw new TransactionNotFoundError(paymentIntentId);\n }\n\n // Get provider\n const gatewayType = transaction.gateway?.type ?? 'manual';\n const provider = this.providers[gatewayType];\n\n if (!provider) {\n throw new ProviderNotFoundError(gatewayType, Object.keys(this.providers));\n }\n\n // Get status from provider\n let paymentResult: PaymentResultData | null = null;\n try {\n // Use the actual payment intent ID from the transaction's gateway info\n const actualIntentId = transaction.gateway?.paymentIntentId || transaction.gateway?.sessionId || paymentIntentId;\n paymentResult = await this.executeProviderCall(\n () => provider.getStatus(actualIntentId),\n `${gatewayType}.getStatus`\n );\n } catch (error) {\n this.logger.warn('Failed to get payment status from provider:', error);\n // Return transaction status as fallback\n return {\n transaction,\n status: transaction.status,\n provider: gatewayType,\n };\n }\n\n return {\n transaction,\n paymentResult,\n status: paymentResult.status,\n provider: gatewayType,\n };\n }\n\n /**\n * Refund a payment\n *\n * @param paymentId - Payment intent ID, session ID, or transaction ID\n * @param amount - Amount to refund (optional, full refund if not provided)\n * @param options - Refund options\n * @returns { transaction, refundResult }\n */\n async refund(\n paymentId: string,\n amount: number | null = null,\n options: RefundOptions = {}\n ): Promise<PaymentRefundResult> {\n // Execute before hooks, then operation, then after hooks\n return this.plugins.executeHook(\n 'payment.refund.before',\n this.getPluginContext(),\n { transactionId: paymentId, amount, ...options },\n async () => {\n const { reason = null } = options;\n\n const TransactionModel = this.models.Transaction;\n const transaction = await this._findTransaction(TransactionModel, paymentId);\n\n if (!transaction) {\n throw new TransactionNotFoundError(paymentId);\n }\n\n if (\n transaction.status !== 'verified' &&\n transaction.status !== 'completed' &&\n transaction.status !== 'partially_refunded'\n ) {\n throw new InvalidStateTransitionError(\n 'transaction',\n transaction._id.toString(),\n transaction.status,\n 'verified, completed, or partially_refunded'\n );\n }\n\n // Get provider\n const gatewayType = transaction.gateway?.type ?? 'manual';\n const provider = this.providers[gatewayType];\n\n if (!provider) {\n throw new ProviderNotFoundError(gatewayType, Object.keys(this.providers));\n }\n\n // Check if provider supports refunds\n const capabilities = provider.getCapabilities();\n if (!capabilities.supportsRefunds) {\n throw new RefundNotSupportedError(gatewayType);\n }\n\n // Calculate refundable amount\n const refundedSoFar = transaction.refundedAmount ?? 0;\n const refundableAmount = transaction.amount - refundedSoFar;\n const refundAmount = amount ?? refundableAmount;\n\n // Validate refund amount\n if (refundAmount <= 0) {\n throw new ValidationError(`Refund amount must be positive, got ${refundAmount}`);\n }\n\n if (refundAmount > refundableAmount) {\n throw new ValidationError(\n `Refund amount (${refundAmount}) exceeds refundable balance (${refundableAmount})`,\n { refundAmount, refundableAmount, alreadyRefunded: refundedSoFar }\n );\n }\n\n // Refund via provider\n let refundResult;\n\n try {\n // Use the actual payment intent ID from the transaction's gateway info\n const actualIntentId = transaction.gateway?.paymentIntentId || transaction.gateway?.sessionId || paymentId;\n refundResult = await this.executeProviderCall(\n () => provider.refund(actualIntentId, refundAmount, { reason: reason ?? undefined }),\n `${gatewayType}.refund`\n );\n } catch (error) {\n this.logger.error('Refund failed:', error);\n throw new RefundError(paymentId, (error as Error).message);\n }\n\n // Create separate refund transaction (EXPENSE) for proper accounting\n // ✅ Resolve flow direction from config (not category!)\n const refundFlow: TransactionFlowValue =\n this.config.transactionTypeMapping?.refund ?? TRANSACTION_FLOW.OUTFLOW;\n\n // Reverse commission proportionally for refund\n const refundCommission = transaction.commission\n ? reverseCommission(transaction.commission, transaction.amount, refundAmount)\n : null;\n\n // Reverse tax proportionally for refund (if tax exists)\n // Note: refundAmount is the base amount (before tax), not total\n let refundTaxAmount = 0;\n if (transaction.tax && transaction.tax > 0) {\n // Simple proportional calculation\n if (transaction.amount > 0) {\n const ratio = refundAmount / transaction.amount;\n refundTaxAmount = Math.round(transaction.tax * ratio);\n }\n }\n\n // Calculate amounts for unified structure\n const refundFeeAmount = refundCommission?.gatewayFeeAmount || 0;\n const refundNetAmount = refundAmount - refundFeeAmount - refundTaxAmount;\n\n const refundTransaction = await TransactionModel.create({\n organizationId: transaction.organizationId,\n customerId: transaction.customerId,\n\n // ✅ UNIFIED: Type = category (semantic), Flow = direction (from config)\n type: 'refund', // Category: this is a refund transaction\n flow: refundFlow, // Direction: income or expense (from config)\n tags: ['refund'],\n\n // ✅ UNIFIED: Amount structure\n amount: refundAmount,\n currency: transaction.currency,\n fee: refundFeeAmount,\n tax: refundTaxAmount,\n net: refundNetAmount,\n\n // Tax details (if tax existed on original)\n ...(transaction.taxDetails && {\n taxDetails: transaction.taxDetails\n }),\n\n method: transaction.method ?? 'manual',\n status: 'completed',\n\n gateway: {\n provider: transaction.gateway?.provider ?? 'manual',\n paymentIntentId: refundResult.id,\n chargeId: refundResult.id,\n },\n\n paymentDetails: transaction.paymentDetails,\n\n // Reversed commission\n ...(refundCommission && { commission: refundCommission }),\n\n // ✅ UNIFIED: Source reference + related transaction\n ...(transaction.sourceId && { sourceId: transaction.sourceId }),\n ...(transaction.sourceModel && { sourceModel: transaction.sourceModel }),\n relatedTransactionId: transaction._id, // Link to original transaction\n\n metadata: {\n ...transaction.metadata,\n isRefund: true,\n originalTransactionId: transaction._id.toString(),\n refundReason: reason,\n refundResult: refundResult.metadata,\n },\n\n idempotencyKey: `refund_${transaction._id}_${Date.now()}`,\n }) as TransactionDocument;\n\n // Update original transaction status\n const isPartialRefund = refundAmount < refundableAmount;\n const refundStatus = isPartialRefund ? 'partially_refunded' : 'refunded';\n\n // Validate state transition and create audit event\n const auditEvent = TRANSACTION_STATE_MACHINE.validateAndCreateAuditEvent(\n transaction.status,\n refundStatus,\n transaction._id.toString(),\n {\n changedBy: 'system',\n reason: `Refund processed: ${isPartialRefund ? 'partial' : 'full'} refund of ${refundAmount}${reason ? ' - ' + reason : ''}`,\n metadata: {\n refundAmount,\n isPartialRefund,\n refundTransactionId: refundTransaction._id.toString()\n }\n }\n );\n\n transaction.status = refundStatus;\n transaction.refundedAmount = (transaction.refundedAmount ?? 0) + refundAmount;\n transaction.refundedAt = refundResult.refundedAt ?? new Date();\n\n // Append audit event to metadata\n Object.assign(transaction, appendAuditEvent(transaction, auditEvent));\n\n transaction.metadata = {\n ...transaction.metadata,\n refundTransactionId: refundTransaction._id.toString(),\n refundReason: reason,\n };\n\n await transaction.save();\n\n // Emit payment.refunded event\n this.events.emit('payment.refunded', {\n transaction,\n refundTransaction,\n refundResult: {\n ...refundResult,\n currency: refundResult.currency ?? 'USD',\n metadata: refundResult.metadata ?? {},\n },\n refundAmount,\n reason: reason ?? undefined,\n isPartialRefund,\n });\n\n const result = {\n transaction,\n refundTransaction,\n refundResult,\n status: transaction.status,\n };\n\n // Execute after hooks\n return this.plugins.executeHook(\n 'payment.refund.after',\n this.getPluginContext(),\n { transactionId: paymentId, amount, ...options },\n async () => result\n );\n }\n );\n }\n\n /**\n * Handle webhook from payment provider\n *\n * @param provider - Provider name\n * @param payload - Webhook payload\n * @param headers - Request headers\n * @returns { event, transaction }\n */\n async handleWebhook(\n providerName: string,\n payload: unknown,\n headers: Record<string, string> = {}\n ): Promise<WebhookResult> {\n const provider = this.providers[providerName];\n\n if (!provider) {\n throw new ProviderNotFoundError(providerName, Object.keys(this.providers));\n }\n\n // Check if provider supports webhooks\n const capabilities = provider.getCapabilities();\n if (!capabilities.supportsWebhooks) {\n throw new ProviderCapabilityError(providerName, 'webhooks');\n }\n\n // Process webhook via provider\n let webhookEvent;\n try {\n webhookEvent = await this.executeProviderCall(\n () => provider.handleWebhook(payload, headers),\n `${providerName}.handleWebhook`\n );\n } catch (error) {\n this.logger.error('Webhook processing failed:', error);\n throw new ProviderError(\n `Webhook processing failed for ${providerName}: ${(error as Error).message}`,\n 'WEBHOOK_PROCESSING_FAILED',\n { retryable: false }\n );\n }\n\n // Validate webhook event structure\n if (!webhookEvent?.data?.sessionId && !webhookEvent?.data?.paymentIntentId) {\n throw new ValidationError(\n `Invalid webhook event structure from ${providerName}: missing sessionId or paymentIntentId`,\n { provider: providerName, eventType: webhookEvent?.type }\n );\n }\n\n // Find transaction by sessionId first (for checkout flows), then paymentIntentId\n const TransactionModel = this.models.Transaction;\n let transaction: TransactionDocument | null = null;\n\n if (webhookEvent.data.sessionId) {\n transaction = await (TransactionModel as unknown as {\n findOne(filter: object): Promise<TransactionDocument | null>;\n }).findOne({\n 'gateway.sessionId': webhookEvent.data.sessionId,\n });\n }\n\n if (!transaction && webhookEvent.data.paymentIntentId) {\n transaction = await (TransactionModel as unknown as {\n findOne(filter: object): Promise<TransactionDocument | null>;\n }).findOne({\n 'gateway.paymentIntentId': webhookEvent.data.paymentIntentId,\n });\n }\n\n if (!transaction) {\n this.logger.warn('Transaction not found for webhook event', {\n provider: providerName,\n eventId: webhookEvent.id,\n sessionId: webhookEvent.data.sessionId,\n paymentIntentId: webhookEvent.data.paymentIntentId,\n });\n throw new TransactionNotFoundError(\n webhookEvent.data.sessionId ?? webhookEvent.data.paymentIntentId ?? 'unknown'\n );\n }\n\n // Update gateway with complete information from webhook\n if (webhookEvent.data.sessionId && !transaction.gateway?.sessionId) {\n transaction.gateway = {\n ...transaction.gateway,\n type: transaction.gateway?.type ?? 'manual',\n sessionId: webhookEvent.data.sessionId,\n };\n }\n if (webhookEvent.data.paymentIntentId && !transaction.gateway?.paymentIntentId) {\n transaction.gateway = {\n ...transaction.gateway,\n type: transaction.gateway?.type ?? 'manual',\n paymentIntentId: webhookEvent.data.paymentIntentId,\n };\n }\n\n // Check for duplicate webhook processing (idempotency)\n if (transaction.webhook?.eventId === webhookEvent.id && transaction.webhook?.processedAt) {\n this.logger.warn('Webhook already processed', {\n transactionId: transaction._id,\n eventId: webhookEvent.id,\n });\n return {\n event: webhookEvent,\n transaction,\n status: 'already_processed',\n };\n }\n\n // Update transaction based on webhook event\n transaction.webhook = {\n eventId: webhookEvent.id,\n eventType: webhookEvent.type,\n receivedAt: new Date(),\n processedAt: new Date(),\n data: webhookEvent.data,\n };\n\n // Determine new status based on webhook type\n let newStatus = transaction.status;\n if (webhookEvent.type === 'payment.succeeded') {\n newStatus = 'verified';\n } else if (webhookEvent.type === 'payment.failed') {\n newStatus = 'failed';\n } else if (webhookEvent.type === 'refund.succeeded') {\n newStatus = 'refunded';\n }\n\n // Validate state transition and create audit event\n if (newStatus !== transaction.status) {\n const auditEvent = TRANSACTION_STATE_MACHINE.validateAndCreateAuditEvent(\n transaction.status,\n newStatus,\n transaction._id.toString(),\n {\n changedBy: 'webhook',\n reason: `Webhook event: ${webhookEvent.type}`,\n metadata: {\n webhookId: webhookEvent.id,\n webhookType: webhookEvent.type,\n webhookData: webhookEvent.data,\n }\n }\n );\n\n transaction.status = newStatus;\n\n // Set appropriate timestamp fields\n if (newStatus === 'verified') {\n transaction.verifiedAt = webhookEvent.createdAt;\n } else if (newStatus === 'refunded') {\n transaction.refundedAt = webhookEvent.createdAt;\n } else if (newStatus === 'failed') {\n transaction.failedAt = webhookEvent.createdAt;\n }\n\n // Append audit event to metadata\n Object.assign(transaction, appendAuditEvent(transaction, auditEvent));\n\n // Note: We don't emit payment lifecycle events from webhooks because\n // webhookEvent.data doesn't contain all required fields (PaymentResult, RefundResult, etc.)\n // Consumers should listen to 'webhook.processed' if they need webhook-driven updates\n }\n\n await transaction.save();\n\n // Emit typed webhook event\n this.events.emit('webhook.processed', {\n webhookType: webhookEvent.type,\n provider: webhookEvent.provider,\n event: webhookEvent,\n transaction,\n processedAt: new Date(),\n });\n\n return {\n event: webhookEvent,\n transaction,\n status: 'processed',\n };\n }\n\n /**\n * List payments/transactions with filters\n *\n * @param filters - Query filters\n * @param options - Query options (limit, skip, sort)\n * @returns Transactions\n */\n async list(\n filters: Record<string, unknown> = {},\n options: ListOptions = {}\n ): Promise<TransactionDocument[]> {\n const TransactionModel = this.models.Transaction;\n const { limit = 50, skip = 0, sort = { createdAt: -1 } } = options;\n\n const transactions = await (TransactionModel as unknown as {\n find(filter: object): { limit(n: number): { skip(n: number): { sort(s: object): Promise<TransactionDocument[]> } } };\n })\n .find(filters)\n .limit(limit)\n .skip(skip)\n .sort(sort);\n\n return transactions;\n }\n\n /**\n * Get payment/transaction by ID\n *\n * @param transactionId - Transaction ID\n * @returns Transaction\n */\n async get(transactionId: string): Promise<TransactionDocument> {\n const TransactionModel = this.models.Transaction;\n const transaction = await TransactionModel.findById(transactionId) as TransactionDocument | null;\n\n if (!transaction) {\n throw new TransactionNotFoundError(transactionId);\n }\n\n return transaction;\n }\n\n /**\n * Get provider instance\n *\n * @param providerName - Provider name\n * @returns Provider instance\n */\n getProvider(providerName: string): PaymentProviderInterface {\n const provider = this.providers[providerName];\n if (!provider) {\n throw new ProviderNotFoundError(providerName, Object.keys(this.providers));\n }\n return provider;\n }\n\n /**\n * Find transaction by sessionId, paymentIntentId, or transaction ID\n * @private\n */\n private async _findTransaction(\n TransactionModel: MongooseModel<TransactionDocument>,\n identifier: string\n ): Promise<TransactionDocument | null> {\n let transaction = await (TransactionModel as unknown as {\n findOne(filter: object): Promise<TransactionDocument | null>;\n }).findOne({\n 'gateway.sessionId': identifier,\n });\n\n if (!transaction) {\n transaction = await (TransactionModel as unknown as {\n findOne(filter: object): Promise<TransactionDocument | null>;\n }).findOne({\n 'gateway.paymentIntentId': identifier,\n });\n }\n\n if (!transaction) {\n transaction = await TransactionModel.findById(identifier) as TransactionDocument | null;\n }\n\n return transaction;\n }\n}\n\nexport default PaymentService;\n","/**\n * Transaction Service\n * @classytic/revenue\n *\n * Thin, focused transaction service for core operations\n * Users handle their own analytics, exports, and complex queries\n *\n * Works with ANY model implementation:\n * - Plain Mongoose models\n * - @classytic/mongokit Repository instances\n * - Any other abstraction with compatible interface\n */\n\nimport { nanoid } from 'nanoid';\nimport { TransactionNotFoundError } from '../../core/errors.js';\nimport type { Container } from '../../core/container.js';\nimport type { EventBus } from '../../core/events.js';\nimport type { PluginManager, PluginContext } from '../../core/plugin.js';\nimport type {\n ModelsRegistry,\n TransactionDocument,\n TransactionListResult,\n ListOptions,\n Logger,\n} from '../../shared/types/index.js';\n\n/**\n * Transaction Service\n * Focused on core transaction lifecycle operations\n *\n * Architecture:\n * - PluginManager: Wraps operations with lifecycle hooks (before/after)\n * - EventBus: Fire-and-forget notifications for completed operations\n */\nexport class TransactionService {\n private readonly models: ModelsRegistry;\n private readonly plugins: PluginManager;\n private readonly events: EventBus;\n private readonly logger: Logger;\n\n constructor(container: Container) {\n this.models = container.get<ModelsRegistry>('models');\n this.plugins = container.get<PluginManager>('plugins');\n this.events = container.get<EventBus>('events');\n this.logger = container.get<Logger>('logger');\n }\n\n /**\n * Create plugin context for hook execution\n * @private\n */\n private getPluginContext(): PluginContext {\n return {\n events: this.events,\n logger: this.logger,\n storage: new Map(),\n meta: {\n requestId: nanoid(),\n timestamp: new Date(),\n },\n };\n }\n\n /**\n * Get transaction by ID\n *\n * @param transactionId - Transaction ID\n * @returns Transaction\n */\n async get(transactionId: string): Promise<TransactionDocument> {\n const TransactionModel = this.models.Transaction;\n const transaction = await TransactionModel.findById(transactionId) as TransactionDocument | null;\n\n if (!transaction) {\n throw new TransactionNotFoundError(transactionId);\n }\n\n return transaction;\n }\n\n /**\n * List transactions with filters\n *\n * @param filters - Query filters\n * @param options - Query options (limit, skip, sort, populate)\n * @returns { transactions, total, page, limit }\n */\n async list(\n filters: Record<string, unknown> = {},\n options: ListOptions = {}\n ): Promise<TransactionListResult> {\n const TransactionModel = this.models.Transaction;\n const {\n limit = 50,\n skip = 0,\n page = null,\n sort = { createdAt: -1 },\n populate = [],\n } = options;\n\n // Calculate pagination\n const actualSkip = page ? (page - 1) * limit : skip;\n\n // Build query\n type QueryBuilder = {\n find(filter: object): QueryBuilder;\n limit(n: number): QueryBuilder;\n skip(n: number): QueryBuilder;\n sort(s: object): QueryBuilder;\n populate(field: string): QueryBuilder;\n then<T>(resolve: (value: TransactionDocument[]) => T): Promise<T>;\n };\n\n let query = (TransactionModel as unknown as {\n find(filter: object): QueryBuilder;\n }).find(filters)\n .limit(limit)\n .skip(actualSkip)\n .sort(sort);\n\n // Apply population if supported\n if (populate.length > 0 && typeof query.populate === 'function') {\n populate.forEach((field) => {\n query = query.populate(field);\n });\n }\n\n const transactions = await query as unknown as TransactionDocument[];\n\n // Count documents (works with both Mongoose and Repository)\n type ModelWithCount = {\n countDocuments?(filter: object): Promise<number>;\n count?(filter: object): Promise<number>;\n };\n\n const model = TransactionModel as unknown as ModelWithCount;\n const total = await (model.countDocuments\n ? model.countDocuments(filters)\n : model.count?.(filters)) ?? 0;\n\n return {\n transactions,\n total,\n page: page ?? Math.floor(actualSkip / limit) + 1,\n limit,\n pages: Math.ceil(total / limit),\n };\n }\n\n /**\n * Update transaction\n *\n * @param transactionId - Transaction ID\n * @param updates - Fields to update\n * @returns Updated transaction\n */\n async update(\n transactionId: string,\n updates: Partial<TransactionDocument>\n ): Promise<TransactionDocument> {\n const hookInput = { transactionId, updates };\n\n return this.plugins.executeHook(\n 'transaction.update.before',\n this.getPluginContext(),\n hookInput,\n async () => {\n const TransactionModel = this.models.Transaction;\n const effectiveUpdates = hookInput.updates;\n\n // Support both Repository pattern and Mongoose\n type ModelWithUpdate = {\n update?(id: string, data: object): Promise<TransactionDocument | null>;\n findByIdAndUpdate?(id: string, data: object, options?: object): Promise<TransactionDocument | null>;\n };\n\n const model = TransactionModel as unknown as ModelWithUpdate;\n let transaction: TransactionDocument | null;\n\n if (typeof model.update === 'function') {\n // Repository pattern\n transaction = await model.update(transactionId, effectiveUpdates);\n } else if (typeof model.findByIdAndUpdate === 'function') {\n // Plain Mongoose\n transaction = await model.findByIdAndUpdate(\n transactionId,\n { $set: effectiveUpdates },\n { new: true }\n );\n } else {\n throw new Error('Transaction model does not support update operations');\n }\n\n if (!transaction) {\n throw new TransactionNotFoundError(transactionId);\n }\n\n // Emit event (fire-and-forget, non-blocking)\n this.events.emit('transaction.updated', {\n transaction,\n updates: effectiveUpdates,\n });\n\n return this.plugins.executeHook(\n 'transaction.update.after',\n this.getPluginContext(),\n { transactionId, updates: effectiveUpdates },\n async () => transaction as TransactionDocument\n );\n }\n );\n }\n}\n\nexport default TransactionService;\n","/**\n * Commission Split Utilities\n * @classytic/revenue\n *\n * Multi-party commission split calculation for affiliate/referral systems\n */\n\nimport { SPLIT_TYPE, SPLIT_STATUS } from '../../../enums/split.enums.js';\nimport type {\n SplitRule,\n SplitInfo,\n CommissionInfo,\n CommissionWithSplitsOptions,\n} from '../../types/index.js';\nimport { ValidationError } from '../../../core/errors.js';\n\n/**\n * Calculate multi-party commission splits\n *\n * @param amount - Transaction amount\n * @param splitRules - Split configuration\n * @param gatewayFeeRate - Gateway fee rate (optional)\n * @returns Split objects\n *\n * @example\n * calculateSplits(1000, [\n * { type: 'platform_commission', recipientId: 'platform', recipientType: 'platform', rate: 0.10 },\n * { type: 'affiliate_commission', recipientId: 'affiliate-123', recipientType: 'user', rate: 0.02 },\n * ], 0.018);\n *\n * Returns:\n * [\n * { type: 'platform_commission', recipientId: 'platform', grossAmount: 100, gatewayFeeAmount: 18, netAmount: 82, ... },\n * { type: 'affiliate_commission', recipientId: 'affiliate-123', grossAmount: 20, gatewayFeeAmount: 0, netAmount: 20, ... },\n * ]\n */\nexport function calculateSplits(\n amount: number,\n splitRules: SplitRule[] = [],\n gatewayFeeRate: number = 0\n): SplitInfo[] {\n if (!splitRules || splitRules.length === 0) {\n return [];\n }\n\n if (amount < 0) {\n throw new Error('Transaction amount cannot be negative');\n }\n\n if (gatewayFeeRate < 0 || gatewayFeeRate > 1) {\n throw new Error('Gateway fee rate must be between 0 and 1');\n }\n\n const totalRate = splitRules.reduce((sum, rule) => sum + rule.rate, 0);\n if (totalRate > 1) {\n throw new Error(`Total split rate (${totalRate}) cannot exceed 1.0`);\n }\n\n return splitRules.map((rule, index) => {\n if (rule.rate < 0 || rule.rate > 1) {\n throw new Error(`Split rate must be between 0 and 1 for split ${index}`);\n }\n\n const grossAmount = Math.round(amount * rule.rate);\n\n const gatewayFeeAmount = index === 0 && gatewayFeeRate > 0\n ? Math.round(amount * gatewayFeeRate)\n : 0;\n\n const netAmount = Math.max(0, grossAmount - gatewayFeeAmount);\n\n return {\n type: rule.type ?? SPLIT_TYPE.CUSTOM,\n recipientId: rule.recipientId,\n recipientType: rule.recipientType,\n rate: rule.rate,\n grossAmount,\n gatewayFeeRate: gatewayFeeAmount > 0 ? gatewayFeeRate : 0,\n gatewayFeeAmount,\n netAmount,\n status: SPLIT_STATUS.PENDING,\n dueDate: rule.dueDate ?? null,\n metadata: rule.metadata ?? {},\n };\n });\n}\n\n/**\n * Calculate organization payout after splits\n *\n * @param amount - Total transaction amount\n * @param splits - Calculated splits\n * @returns Amount organization receives\n */\nexport function calculateOrganizationPayout(\n amount: number,\n splits: SplitInfo[] = []\n): number {\n const totalSplitAmount = splits.reduce((sum, split) => sum + split.grossAmount, 0);\n return Math.max(0, amount - totalSplitAmount);\n}\n\n/**\n * Reverse splits proportionally on refund\n *\n * @param originalSplits - Original split objects\n * @param originalAmount - Original transaction amount\n * @param refundAmount - Amount being refunded\n * @returns Reversed splits\n */\nexport function reverseSplits(\n originalSplits: SplitInfo[] | undefined | null,\n originalAmount: number,\n refundAmount: number\n): SplitInfo[] {\n if (!originalSplits || originalSplits.length === 0) {\n return [];\n }\n\n // Edge case validations\n if (!originalAmount || originalAmount <= 0) {\n throw new ValidationError('Original amount must be greater than 0', { originalAmount });\n }\n\n if (refundAmount < 0) {\n throw new ValidationError('Refund amount cannot be negative', { refundAmount });\n }\n\n if (refundAmount > originalAmount) {\n throw new ValidationError(\n `Refund amount (${refundAmount}) exceeds original amount (${originalAmount})`,\n { refundAmount, originalAmount }\n );\n }\n\n const refundRatio = refundAmount / originalAmount;\n\n return originalSplits.map((split) => ({\n ...split,\n grossAmount: Math.round(split.grossAmount * refundRatio),\n gatewayFeeAmount: Math.round(split.gatewayFeeAmount * refundRatio),\n netAmount: Math.round(split.netAmount * refundRatio),\n status: SPLIT_STATUS.WAIVED,\n }));\n}\n\n/**\n * Build commission object with splits support\n * Backward compatible with existing calculateCommission\n *\n * @param amount - Transaction amount\n * @param commissionRate - Platform commission rate\n * @param gatewayFeeRate - Gateway fee rate\n * @param options - Additional options\n * @returns Commission with optional splits\n */\nexport function calculateCommissionWithSplits(\n amount: number,\n commissionRate: number,\n gatewayFeeRate: number = 0,\n options: CommissionWithSplitsOptions = {}\n): CommissionInfo | null {\n const { affiliateRate = 0, affiliateId = null, affiliateType = 'user' } = options;\n\n if (commissionRate <= 0 && affiliateRate <= 0) {\n return null;\n }\n\n const splitRules: SplitRule[] = [];\n\n if (commissionRate > 0) {\n splitRules.push({\n type: SPLIT_TYPE.PLATFORM_COMMISSION,\n recipientId: 'platform',\n recipientType: 'platform',\n rate: commissionRate,\n });\n }\n\n if (affiliateRate > 0 && affiliateId) {\n splitRules.push({\n type: SPLIT_TYPE.AFFILIATE_COMMISSION,\n recipientId: affiliateId,\n recipientType: affiliateType,\n rate: affiliateRate,\n });\n }\n\n const splits = calculateSplits(amount, splitRules, gatewayFeeRate);\n\n const platformSplit = splits.find((s) => s.type === SPLIT_TYPE.PLATFORM_COMMISSION);\n const affiliateSplit = splits.find((s) => s.type === SPLIT_TYPE.AFFILIATE_COMMISSION);\n\n return {\n rate: commissionRate,\n grossAmount: platformSplit?.grossAmount ?? 0,\n gatewayFeeRate: platformSplit?.gatewayFeeRate ?? 0,\n gatewayFeeAmount: platformSplit?.gatewayFeeAmount ?? 0,\n netAmount: platformSplit?.netAmount ?? 0,\n status: 'pending',\n ...(splits.length > 0 && { splits }),\n ...(affiliateSplit && {\n affiliate: {\n recipientId: affiliateSplit.recipientId,\n recipientType: affiliateSplit.recipientType,\n rate: affiliateSplit.rate,\n grossAmount: affiliateSplit.grossAmount,\n netAmount: affiliateSplit.netAmount,\n },\n }),\n };\n}\n\nexport default {\n calculateSplits,\n calculateOrganizationPayout,\n reverseSplits,\n calculateCommissionWithSplits,\n};\n\n","/**\n * Escrow Service\n * @classytic/revenue\n *\n * Platform-as-intermediary payment flow\n * Hold funds → Verify → Split/Deduct → Release to organization\n */\n\nimport { nanoid } from 'nanoid';\nimport { TransactionNotFoundError, InvalidStateTransitionError, ValidationError } from '../../core/errors.js';\nimport { HOLD_STATUS, RELEASE_REASON, HOLD_REASON } from '../../enums/escrow.enums.js';\nimport { TRANSACTION_STATUS } from '../../enums/transaction.enums.js';\nimport { SPLIT_STATUS } from '../../enums/split.enums.js';\nimport { TRANSACTION_STATE_MACHINE, HOLD_STATE_MACHINE } from '../../core/state-machine/index.js';\nimport { appendAuditEvent } from '../../infrastructure/audit/index.js';\nimport { calculateSplits, calculateOrganizationPayout } from '../../shared/utils/calculators/commission-split.js';\nimport type { Container } from '../../core/container.js';\nimport type { EventBus } from '../../core/events.js';\nimport type { PluginManager, PluginContext } from '../../core/plugin.js';\nimport type {\n ModelsRegistry,\n Logger,\n TransactionDocument,\n HoldOptions,\n ReleaseOptions,\n ReleaseResult,\n CancelHoldOptions,\n SplitResult,\n EscrowStatusResult,\n SplitRule,\n SplitInfo,\n} from '../../shared/types/index.js';\n\n/**\n * Escrow Service\n * Uses DI container for all dependencies\n *\n * Architecture:\n * - PluginManager: Wraps operations with lifecycle hooks (before/after)\n * - EventBus: Fire-and-forget notifications for completed operations\n */\nexport class EscrowService {\n private readonly models: ModelsRegistry;\n private readonly plugins: PluginManager;\n private readonly logger: Logger;\n private readonly events: EventBus;\n\n constructor(container: Container) {\n this.models = container.get<ModelsRegistry>('models');\n this.plugins = container.get<PluginManager>('plugins');\n this.logger = container.get<Logger>('logger');\n this.events = container.get<EventBus>('events');\n }\n\n /**\n * Create plugin context for hook execution\n * @private\n */\n private getPluginContext(): PluginContext {\n return {\n events: this.events,\n logger: this.logger,\n storage: new Map(),\n meta: {\n requestId: nanoid(),\n timestamp: new Date(),\n },\n };\n }\n\n /**\n * Hold funds in escrow\n *\n * @param transactionId - Transaction to hold\n * @param options - Hold options\n * @returns Updated transaction\n */\n async hold(\n transactionId: string,\n options: HoldOptions = {}\n ): Promise<TransactionDocument> {\n // Execute before hooks, then operation, then after hooks\n return this.plugins.executeHook(\n 'escrow.hold.before',\n this.getPluginContext(),\n { transactionId, ...options },\n async () => {\n const {\n reason = HOLD_REASON.PAYMENT_VERIFICATION,\n holdUntil = null,\n metadata = {},\n } = options;\n\n const TransactionModel = this.models.Transaction;\n const transaction = await TransactionModel.findById(transactionId) as TransactionDocument | null;\n\n if (!transaction) {\n throw new TransactionNotFoundError(transactionId);\n }\n\n if (transaction.status !== TRANSACTION_STATUS.VERIFIED) {\n throw new InvalidStateTransitionError(\n 'transaction',\n transaction._id.toString(),\n transaction.status,\n TRANSACTION_STATUS.VERIFIED\n );\n }\n\n // Calculate held amount (base amount only, tax is tracked separately in transaction.tax)\n const heldAmount = transaction.amount;\n\n transaction.hold = {\n status: HOLD_STATUS.HELD,\n heldAmount,\n releasedAmount: 0,\n reason,\n heldAt: new Date(),\n ...(holdUntil && { holdUntil }),\n releases: [],\n metadata,\n };\n\n await transaction.save();\n\n this.events.emit('escrow.held', {\n transaction,\n heldAmount,\n reason,\n });\n\n // Execute after hooks\n return this.plugins.executeHook(\n 'escrow.hold.after',\n this.getPluginContext(),\n { transactionId, ...options },\n async () => transaction\n );\n }\n );\n }\n\n /**\n * Release funds from escrow to recipient\n *\n * @param transactionId - Transaction to release\n * @param options - Release options\n * @returns { transaction, releaseTransaction }\n */\n async release(\n transactionId: string,\n options: ReleaseOptions\n ): Promise<ReleaseResult> {\n // Execute before hooks, then operation, then after hooks\n return this.plugins.executeHook(\n 'escrow.release.before',\n this.getPluginContext(),\n { transactionId, ...options },\n async () => {\n const {\n amount = null,\n recipientId,\n recipientType = 'organization',\n reason = RELEASE_REASON.PAYMENT_VERIFIED,\n releasedBy = null,\n createTransaction = true,\n metadata = {},\n } = options;\n\n const TransactionModel = this.models.Transaction;\n const transaction = await TransactionModel.findById(transactionId) as TransactionDocument | null;\n\n if (!transaction) {\n throw new TransactionNotFoundError(transactionId);\n }\n\n if (!transaction.hold || transaction.hold.status !== HOLD_STATUS.HELD) {\n throw new InvalidStateTransitionError(\n 'escrow_hold',\n transaction._id.toString(),\n transaction.hold?.status ?? 'none',\n HOLD_STATUS.HELD\n );\n }\n\n if (!recipientId) {\n throw new ValidationError('recipientId is required for release', { transactionId });\n }\n\n const releaseAmount = amount ?? (transaction.hold.heldAmount - transaction.hold.releasedAmount);\n const availableAmount = transaction.hold.heldAmount - transaction.hold.releasedAmount;\n\n if (releaseAmount > availableAmount) {\n throw new ValidationError(\n `Release amount (${releaseAmount}) exceeds available held amount (${availableAmount})`,\n { releaseAmount, availableAmount, transactionId }\n );\n }\n\n const releaseRecord = {\n amount: releaseAmount,\n recipientId,\n recipientType,\n releasedAt: new Date(),\n releasedBy,\n reason,\n metadata,\n };\n\n transaction.hold.releases.push(releaseRecord);\n transaction.hold.releasedAmount += releaseAmount;\n\n const isFullRelease = transaction.hold.releasedAmount >= transaction.hold.heldAmount;\n const isPartialRelease = transaction.hold.releasedAmount > 0 && transaction.hold.releasedAmount < transaction.hold.heldAmount;\n\n if (isFullRelease) {\n // Validate hold state transition and create audit event\n const holdAuditEvent = HOLD_STATE_MACHINE.validateAndCreateAuditEvent(\n transaction.hold.status,\n HOLD_STATUS.RELEASED,\n transaction._id.toString(),\n {\n changedBy: releasedBy ?? 'system',\n reason: `Escrow hold fully released: ${releaseAmount} to ${recipientId}${reason ? ' - ' + reason : ''}`,\n metadata: { releaseAmount, recipientId, releaseReason: reason }\n }\n );\n\n transaction.hold.status = HOLD_STATUS.RELEASED;\n transaction.hold.releasedAt = new Date();\n\n // Validate transaction state transition and create audit event\n const transactionAuditEvent = TRANSACTION_STATE_MACHINE.validateAndCreateAuditEvent(\n transaction.status,\n TRANSACTION_STATUS.COMPLETED,\n transaction._id.toString(),\n {\n changedBy: releasedBy ?? 'system',\n reason: `Transaction completed after full escrow release`,\n metadata: { releaseAmount, recipientId }\n }\n );\n\n transaction.status = TRANSACTION_STATUS.COMPLETED;\n\n // Append both audit events to metadata\n Object.assign(transaction, appendAuditEvent(transaction, holdAuditEvent));\n Object.assign(transaction, appendAuditEvent(transaction, transactionAuditEvent));\n } else if (isPartialRelease) {\n // Validate hold state transition and create audit event\n const auditEvent = HOLD_STATE_MACHINE.validateAndCreateAuditEvent(\n transaction.hold.status,\n HOLD_STATUS.PARTIALLY_RELEASED,\n transaction._id.toString(),\n {\n changedBy: releasedBy ?? 'system',\n reason: `Partial escrow release: ${releaseAmount} of ${transaction.hold.heldAmount} to ${recipientId}${reason ? ' - ' + reason : ''}`,\n metadata: {\n releaseAmount,\n recipientId,\n releaseReason: reason,\n remainingHeld: transaction.hold.heldAmount - transaction.hold.releasedAmount\n }\n }\n );\n\n transaction.hold.status = HOLD_STATUS.PARTIALLY_RELEASED;\n\n // Append audit event to metadata\n Object.assign(transaction, appendAuditEvent(transaction, auditEvent));\n }\n\n if ('markModified' in transaction) {\n (transaction as { markModified: (path: string) => void }).markModified('hold');\n }\n\n await transaction.save();\n\n // ✅ UNIFIED TRANSACTION: Calculate proportional tax for release\n let releaseTaxAmount = 0;\n\n if (transaction.tax && transaction.tax > 0) {\n // Calculate tax for release\n // Check if this is a full release (releaseAmount equals available held amount)\n if (releaseAmount === availableAmount && !amount) {\n // Full release - release all remaining tax\n const releasedTaxSoFar = transaction.hold.releasedTaxAmount ?? 0;\n releaseTaxAmount = transaction.tax - releasedTaxSoFar;\n } else {\n // Partial release - releaseAmount includes both base + tax\n // Extract tax proportionally from total release amount\n const totalAmount = transaction.amount + transaction.tax;\n if (totalAmount > 0) {\n const taxRatio = transaction.tax / totalAmount;\n releaseTaxAmount = Math.round(releaseAmount * taxRatio);\n }\n }\n }\n\n // Calculate net (no gateway fees on escrow releases)\n const releaseNetAmount = releaseAmount - releaseTaxAmount;\n\n let releaseTransaction: TransactionDocument | null = null;\n if (createTransaction) {\n releaseTransaction = await TransactionModel.create({\n organizationId: transaction.organizationId,\n customerId: recipientId,\n\n // ✅ UNIFIED: Use 'escrow_release' as type, inflow\n type: 'escrow_release',\n flow: 'inflow',\n tags: ['escrow', 'release'],\n\n // ✅ UNIFIED: Amount structure\n amount: releaseAmount,\n currency: transaction.currency,\n fee: 0, // No processing fees on releases\n tax: releaseTaxAmount, // ✅ Top-level number\n net: releaseNetAmount,\n\n // Copy tax details from original transaction\n ...(transaction.taxDetails && {\n taxDetails: transaction.taxDetails\n }),\n\n method: transaction.method,\n status: 'completed',\n gateway: transaction.gateway,\n\n // ✅ UNIFIED: Source reference (link to held transaction)\n sourceId: transaction._id,\n sourceModel: 'Transaction',\n relatedTransactionId: transaction._id,\n\n metadata: {\n ...metadata,\n isRelease: true,\n heldTransactionId: transaction._id.toString(),\n releaseReason: reason,\n recipientType,\n // Store original category for reference\n originalCategory: transaction.category,\n },\n idempotencyKey: `release_${transaction._id}_${Date.now()}`,\n }) as TransactionDocument;\n }\n\n this.events.emit('escrow.released', {\n transaction,\n releaseTransaction,\n releaseAmount,\n recipientId,\n recipientType,\n reason,\n isFullRelease,\n isPartialRelease,\n });\n\n const result = {\n transaction,\n releaseTransaction,\n releaseAmount,\n isFullRelease,\n isPartialRelease,\n };\n\n // Execute after hooks\n return this.plugins.executeHook(\n 'escrow.release.after',\n this.getPluginContext(),\n { transactionId, ...options },\n async () => result\n );\n }\n );\n }\n\n /**\n * Cancel hold and release back to customer\n *\n * @param transactionId - Transaction to cancel hold\n * @param options - Cancel options\n * @returns Updated transaction\n */\n async cancel(\n transactionId: string,\n options: CancelHoldOptions = {}\n ): Promise<TransactionDocument> {\n const { reason = 'Hold cancelled', metadata = {} } = options;\n\n const TransactionModel = this.models.Transaction;\n const transaction = await TransactionModel.findById(transactionId) as TransactionDocument | null;\n\n if (!transaction) {\n throw new TransactionNotFoundError(transactionId);\n }\n\n if (!transaction.hold || transaction.hold.status !== HOLD_STATUS.HELD) {\n throw new InvalidStateTransitionError(\n 'escrow_hold',\n transaction._id.toString(),\n transaction.hold?.status ?? 'none',\n HOLD_STATUS.HELD\n );\n }\n\n // Validate hold state transition and create audit event\n const holdAuditEvent = HOLD_STATE_MACHINE.validateAndCreateAuditEvent(\n transaction.hold.status,\n HOLD_STATUS.CANCELLED,\n transaction._id.toString(),\n {\n changedBy: 'system',\n reason: `Escrow hold cancelled${reason ? ': ' + reason : ''}`,\n metadata: { cancelReason: reason, ...metadata }\n }\n );\n\n transaction.hold.status = HOLD_STATUS.CANCELLED;\n transaction.hold.cancelledAt = new Date();\n transaction.hold.metadata = {\n ...transaction.hold.metadata,\n ...metadata,\n cancelReason: reason,\n };\n\n // Validate transaction state transition and create audit event\n const transactionAuditEvent = TRANSACTION_STATE_MACHINE.validateAndCreateAuditEvent(\n transaction.status,\n TRANSACTION_STATUS.CANCELLED,\n transaction._id.toString(),\n {\n changedBy: 'system',\n reason: `Transaction cancelled due to escrow hold cancellation`,\n metadata: { cancelReason: reason }\n }\n );\n\n transaction.status = TRANSACTION_STATUS.CANCELLED;\n\n // Append both audit events to metadata\n Object.assign(transaction, appendAuditEvent(transaction, holdAuditEvent));\n Object.assign(transaction, appendAuditEvent(transaction, transactionAuditEvent));\n\n if ('markModified' in transaction) {\n (transaction as { markModified: (path: string) => void }).markModified('hold');\n }\n\n await transaction.save();\n\n this.events.emit('escrow.cancelled', {\n transaction,\n reason,\n });\n\n return transaction;\n }\n\n /**\n * Split payment to multiple recipients\n * Deducts splits from held amount and releases remainder to organization\n *\n * @param transactionId - Transaction to split\n * @param splitRules - Split configuration\n * @returns { transaction, splitTransactions, organizationTransaction }\n */\n async split(\n transactionId: string,\n splitRules: SplitRule[] = []\n ): Promise<SplitResult> {\n const TransactionModel = this.models.Transaction;\n const transaction = await TransactionModel.findById(transactionId) as TransactionDocument | null;\n\n if (!transaction) {\n throw new TransactionNotFoundError(transactionId);\n }\n\n if (!transaction.hold || transaction.hold.status !== HOLD_STATUS.HELD) {\n throw new InvalidStateTransitionError(\n 'escrow_hold',\n transaction._id.toString(),\n transaction.hold?.status ?? 'none',\n HOLD_STATUS.HELD\n );\n }\n\n if (!splitRules || splitRules.length === 0) {\n throw new ValidationError('splitRules cannot be empty', { transactionId });\n }\n\n const splits = calculateSplits(\n transaction.amount,\n splitRules,\n transaction.commission?.gatewayFeeRate ?? 0\n );\n\n transaction.splits = splits;\n await transaction.save();\n\n const splitTransactions: TransactionDocument[] = [];\n const totalTax = transaction.tax ?? 0;\n const totalBaseAmount = transaction.amount;\n let allocatedTaxAmount = 0;\n const splitTaxAmounts = splits.map((split) => {\n if (!totalTax || totalBaseAmount <= 0) {\n return 0;\n }\n const ratio = split.grossAmount / totalBaseAmount;\n const taxAmount = Math.round(totalTax * ratio);\n allocatedTaxAmount += taxAmount;\n return taxAmount;\n });\n\n for (const [index, split] of splits.entries()) {\n // ✅ UNIFIED: Tax amount as number (proportional to split)\n const splitTaxAmount = totalTax > 0 ? splitTaxAmounts[index] ?? 0 : 0;\n\n // ✅ UNIFIED: Calculate net = gross - fee - tax\n const splitNetAmount = split.grossAmount - split.gatewayFeeAmount - splitTaxAmount;\n\n const splitTransaction = await TransactionModel.create({\n organizationId: transaction.organizationId,\n customerId: split.recipientId,\n\n // ✅ UNIFIED: Use split type directly (commission, platform_fee, etc.)\n type: split.type,\n flow: 'outflow', // Splits are money going out\n tags: ['split', 'commission'],\n\n // ✅ UNIFIED: Amount structure (gross, fee, tax, net)\n amount: split.grossAmount, // ✅ Gross amount (before deductions)\n currency: transaction.currency,\n fee: split.gatewayFeeAmount,\n tax: splitTaxAmount, // ✅ Top-level number\n net: splitNetAmount, // ✅ Net = gross - fee - tax\n\n // Copy tax details from original transaction (if applicable)\n ...(transaction.taxDetails && splitTaxAmount > 0 && {\n taxDetails: transaction.taxDetails\n }),\n\n method: transaction.method,\n status: 'completed',\n gateway: transaction.gateway,\n\n // ✅ UNIFIED: Source reference (link to original transaction)\n sourceId: transaction._id,\n sourceModel: 'Transaction',\n relatedTransactionId: transaction._id,\n\n metadata: {\n isSplit: true,\n splitType: split.type,\n recipientType: split.recipientType,\n originalTransactionId: transaction._id.toString(),\n // Store split details for reference\n splitGrossAmount: split.grossAmount,\n splitNetAmount: split.netAmount, // Original calculation\n gatewayFeeAmount: split.gatewayFeeAmount,\n },\n idempotencyKey: `split_${transaction._id}_${split.recipientId}_${Date.now()}`,\n }) as TransactionDocument;\n\n (split as SplitInfo & { payoutTransactionId?: string }).payoutTransactionId = splitTransaction._id.toString();\n split.status = SPLIT_STATUS.PAID;\n (split as SplitInfo & { paidDate?: Date }).paidDate = new Date();\n\n splitTransactions.push(splitTransaction);\n }\n\n await transaction.save();\n\n const organizationPayout = calculateOrganizationPayout(transaction.amount, splits);\n const organizationTaxAmount = totalTax > 0\n ? Math.max(0, totalTax - allocatedTaxAmount)\n : 0;\n const organizationPayoutTotal = totalTax > 0\n ? organizationPayout + organizationTaxAmount\n : organizationPayout;\n\n const organizationTransaction = await this.release(transactionId, {\n amount: organizationPayoutTotal,\n recipientId: transaction.organizationId?.toString() ?? '',\n recipientType: 'organization',\n reason: RELEASE_REASON.PAYMENT_VERIFIED,\n createTransaction: true,\n metadata: {\n afterSplits: true,\n totalSplits: splits.length,\n totalSplitAmount: transaction.amount - organizationPayout,\n },\n });\n\n this.events.emit('escrow.split', {\n transaction,\n splits,\n splitTransactions,\n organizationTransaction: organizationTransaction.releaseTransaction,\n organizationPayout,\n });\n\n return {\n transaction,\n splits,\n splitTransactions,\n organizationTransaction: organizationTransaction.releaseTransaction,\n organizationPayout,\n };\n }\n\n /**\n * Get escrow status\n *\n * @param transactionId - Transaction ID\n * @returns Escrow status\n */\n async getStatus(transactionId: string): Promise<EscrowStatusResult> {\n const TransactionModel = this.models.Transaction;\n const transaction = await TransactionModel.findById(transactionId) as TransactionDocument | null;\n\n if (!transaction) {\n throw new TransactionNotFoundError(transactionId);\n }\n\n return {\n transaction,\n hold: transaction.hold ?? null,\n splits: transaction.splits ?? [],\n hasHold: !!transaction.hold,\n hasSplits: transaction.splits ? transaction.splits.length > 0 : false,\n };\n }\n\n}\n\nexport default EscrowService;\n","/**\n * Settlement Service\n * @classytic/revenue\n *\n * Tracks payouts from platform to vendors/affiliates/partners\n * Manages the flow: Transaction → Split → Settlement → Bank Transfer\n */\n\nimport type { Container } from '../../core/container.js';\nimport type { EventBus } from '../../core/events.js';\nimport type { PluginManager } from '../../core/plugin.js';\nimport type {\n ModelsRegistry,\n Logger,\n TransactionDocument,\n} from '../../shared/types/index.js';\nimport {\n ModelNotRegisteredError,\n TransactionNotFoundError,\n InvalidStateTransitionError,\n ValidationError,\n} from '../../core/errors.js';\nimport { SETTLEMENT_STATUS, SETTLEMENT_TYPE } from '../../enums/settlement.enums.js';\nimport { SETTLEMENT_STATE_MACHINE } from '../../core/state-machine/index.js';\nimport { appendAuditEvent } from '../../infrastructure/audit/index.js';\nimport type { SettlementDocument } from '../../schemas/settlement/settlement.schema.js';\n\n// ============ TYPES ============\n\nexport interface CreateFromSplitsOptions {\n scheduledAt?: Date;\n payoutMethod?: 'bank_transfer' | 'mobile_wallet' | 'platform_balance' | 'crypto' | 'manual';\n metadata?: Record<string, unknown>;\n}\n\nexport interface ScheduleSettlementParams {\n organizationId: string;\n recipientId: string;\n recipientType: 'platform' | 'organization' | 'user' | 'affiliate' | 'partner';\n type: 'split_payout' | 'platform_withdrawal' | 'manual_payout' | 'escrow_release';\n amount: number;\n currency?: string;\n payoutMethod: 'bank_transfer' | 'mobile_wallet' | 'platform_balance' | 'crypto' | 'manual';\n sourceTransactionIds?: string[];\n sourceSplitIds?: string[];\n scheduledAt?: Date;\n bankTransferDetails?: {\n accountNumber?: string;\n accountName?: string;\n bankName?: string;\n routingNumber?: string;\n swiftCode?: string;\n iban?: string;\n };\n mobileWalletDetails?: {\n provider?: string;\n phoneNumber?: string;\n accountNumber?: string;\n };\n cryptoDetails?: {\n network?: string;\n walletAddress?: string;\n };\n notes?: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface ProcessOptions {\n limit?: number;\n organizationId?: string;\n payoutMethod?: string;\n dryRun?: boolean;\n}\n\nexport interface ProcessResult {\n processed: number;\n succeeded: number;\n failed: number;\n settlements: SettlementDocument[];\n errors: Array<{ settlementId: string; error: string }>;\n}\n\nexport interface CompletionDetails {\n transferReference?: string;\n transferredAt?: Date;\n transactionHash?: string;\n notes?: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface SettlementFilters {\n organizationId?: string;\n recipientId?: string;\n status?: string | string[];\n type?: string;\n payoutMethod?: string;\n scheduledAfter?: Date;\n scheduledBefore?: Date;\n limit?: number;\n skip?: number;\n sort?: Record<string, 1 | -1>;\n}\n\nexport interface SummaryOptions {\n organizationId?: string;\n startDate?: Date;\n endDate?: Date;\n}\n\nexport interface SettlementSummary {\n recipientId: string;\n totalPending: number;\n totalProcessing: number;\n totalCompleted: number;\n totalFailed: number;\n amountPending: number;\n amountCompleted: number;\n amountFailed: number;\n currency: string;\n lastSettlementDate?: Date;\n settlements: {\n pending: number;\n processing: number;\n completed: number;\n failed: number;\n cancelled: number;\n };\n}\n\n// ============ SERVICE ============\n\n/**\n * Settlement Service\n *\n * Handles payout tracking after splits are released from escrow:\n *\n * Flow:\n * 1. Transaction has splits → 2. Escrow released → 3. Create settlements → 4. Process payouts → 5. Mark complete\n *\n * @example\n * ```typescript\n * // Auto-create settlements from transaction splits\n * await revenue.settlement.createFromSplits(transactionId);\n *\n * // Schedule a manual payout\n * await revenue.settlement.schedule({\n * recipientId: vendorId,\n * amount: 8500,\n * payoutMethod: 'bank_transfer',\n * });\n *\n * // Process pending payouts\n * const result = await revenue.settlement.processPending({ limit: 100 });\n *\n * // Mark as completed after bank confirms\n * await revenue.settlement.complete(settlementId, { transferReference: 'TRF123' });\n * ```\n */\n/**\n * Settlement Service\n * Uses DI container for all dependencies\n *\n * Architecture:\n * - PluginManager: Wraps operations with lifecycle hooks (before/after)\n * - EventBus: Fire-and-forget notifications for completed operations\n */\nexport class SettlementService {\n private readonly models: ModelsRegistry;\n private readonly plugins: PluginManager;\n private readonly logger: Logger;\n private readonly events: EventBus;\n\n constructor(container: Container) {\n this.models = container.get<ModelsRegistry>('models');\n this.plugins = container.get<PluginManager>('plugins');\n this.logger = container.get<Logger>('logger');\n this.events = container.get<EventBus>('events');\n\n // Settlements don't have hooks yet - future enhancement\n void this.plugins;\n }\n\n /**\n * Create settlements from transaction splits\n * Typically called after escrow is released\n *\n * @param transactionId - Transaction ID with splits\n * @param options - Creation options\n * @returns Array of created settlements\n */\n async createFromSplits(\n transactionId: string,\n options: CreateFromSplitsOptions = {}\n ): Promise<SettlementDocument[]> {\n const {\n scheduledAt = new Date(),\n payoutMethod = 'bank_transfer',\n metadata = {},\n } = options;\n\n // Get Settlement model\n if (!this.models.Settlement) {\n throw new ModelNotRegisteredError('Settlement');\n }\n\n // Get transaction\n const TransactionModel = this.models.Transaction;\n const transaction = await TransactionModel.findById(transactionId) as TransactionDocument | null;\n\n if (!transaction) {\n throw new TransactionNotFoundError(transactionId);\n }\n\n // Check if transaction has splits\n if (!transaction.splits || transaction.splits.length === 0) {\n throw new ValidationError('Transaction has no splits to settle', { transactionId });\n }\n\n // Create a settlement for each split\n const SettlementModel = this.models.Settlement;\n const settlements: SettlementDocument[] = [];\n\n for (const split of transaction.splits) {\n // Skip if already paid\n if (split.status === 'paid') {\n this.logger.info('Split already paid, skipping', { splitId: split._id });\n continue;\n }\n\n const settlement = await SettlementModel.create({\n organizationId: transaction.organizationId,\n recipientId: split.recipientId,\n recipientType: split.recipientType,\n type: SETTLEMENT_TYPE.SPLIT_PAYOUT,\n status: SETTLEMENT_STATUS.PENDING,\n payoutMethod,\n amount: split.netAmount,\n currency: transaction.currency,\n sourceTransactionIds: [transaction._id],\n sourceSplitIds: [split._id?.toString() || ''],\n scheduledAt,\n metadata: {\n ...metadata,\n splitType: split.type,\n transactionCategory: transaction.category,\n },\n }) as SettlementDocument;\n\n settlements.push(settlement);\n }\n\n // Trigger hook\n this.events.emit('settlement.created', {\n settlements,\n transactionId,\n count: settlements.length,\n });\n\n this.logger.info('Created settlements from splits', {\n transactionId,\n count: settlements.length,\n });\n\n return settlements;\n }\n\n /**\n * Schedule a payout\n *\n * @param params - Settlement parameters\n * @returns Created settlement\n */\n async schedule(params: ScheduleSettlementParams): Promise<SettlementDocument> {\n if (!this.models.Settlement) {\n throw new ModelNotRegisteredError('Settlement');\n }\n\n const {\n organizationId,\n recipientId,\n recipientType,\n type,\n amount,\n currency = 'USD',\n payoutMethod,\n sourceTransactionIds = [],\n sourceSplitIds = [],\n scheduledAt = new Date(),\n bankTransferDetails,\n mobileWalletDetails,\n cryptoDetails,\n notes,\n metadata = {},\n } = params;\n\n // Validate amount\n if (amount <= 0) {\n throw new ValidationError('Settlement amount must be positive', { amount });\n }\n\n const SettlementModel = this.models.Settlement;\n const settlement = await SettlementModel.create({\n organizationId,\n recipientId,\n recipientType,\n type,\n status: SETTLEMENT_STATUS.PENDING,\n payoutMethod,\n amount,\n currency,\n sourceTransactionIds,\n sourceSplitIds,\n scheduledAt,\n bankTransferDetails,\n mobileWalletDetails,\n cryptoDetails,\n notes,\n metadata,\n }) as SettlementDocument;\n\n // Trigger hook\n this.events.emit('settlement.scheduled', {\n settlement,\n scheduledAt,\n });\n\n this.logger.info('Settlement scheduled', {\n settlementId: settlement._id,\n recipientId,\n amount,\n });\n\n return settlement;\n }\n\n /**\n * Process pending settlements\n * Batch process settlements that are due\n *\n * @param options - Processing options\n * @returns Processing result\n */\n async processPending(options: ProcessOptions = {}): Promise<ProcessResult> {\n if (!this.models.Settlement) {\n throw new ModelNotRegisteredError('Settlement');\n }\n\n const {\n limit = 100,\n organizationId,\n payoutMethod,\n dryRun = false,\n } = options;\n\n const SettlementModel = this.models.Settlement;\n\n // Build query\n const query: Record<string, unknown> = {\n status: SETTLEMENT_STATUS.PENDING,\n scheduledAt: { $lte: new Date() },\n };\n\n if (organizationId) query.organizationId = organizationId;\n if (payoutMethod) query.payoutMethod = payoutMethod;\n\n // Get pending settlements\n const settlements = await (SettlementModel as unknown as {\n find(filter: object): { limit(n: number): { sort(s: object): Promise<SettlementDocument[]> } };\n })\n .find(query)\n .limit(limit)\n .sort({ scheduledAt: 1 });\n\n const result: ProcessResult = {\n processed: 0,\n succeeded: 0,\n failed: 0,\n settlements: [],\n errors: [],\n };\n\n if (dryRun) {\n this.logger.info('Dry run: would process settlements', { count: settlements.length });\n result.settlements = settlements;\n return result;\n }\n\n // Process each settlement\n for (const settlement of settlements) {\n result.processed++;\n\n try {\n // Validate state transition and create audit event\n const auditEvent = SETTLEMENT_STATE_MACHINE.validateAndCreateAuditEvent(\n settlement.status,\n SETTLEMENT_STATUS.PROCESSING,\n settlement._id.toString(),\n {\n changedBy: 'system',\n reason: 'Settlement processing started',\n metadata: { recipientId: settlement.recipientId, amount: settlement.amount }\n }\n );\n\n // Update to processing\n settlement.status = SETTLEMENT_STATUS.PROCESSING;\n settlement.processedAt = new Date();\n\n // Append audit event to metadata\n Object.assign(settlement, appendAuditEvent(settlement, auditEvent));\n\n await settlement.save();\n\n // Here you would integrate with your payout provider\n // For now, we just mark as processing\n // In production: call bank API, wallet API, etc.\n\n result.succeeded++;\n result.settlements.push(settlement);\n\n this.events.emit('settlement.processing', {\n settlement,\n processedAt: settlement.processedAt,\n });\n } catch (error) {\n result.failed++;\n result.errors.push({\n settlementId: settlement._id.toString(),\n error: (error as Error).message,\n });\n\n this.logger.error('Failed to process settlement', {\n settlementId: settlement._id,\n error,\n });\n }\n }\n\n this.logger.info('Processed settlements', result);\n\n return result;\n }\n\n /**\n * Mark settlement as completed\n * Call this after bank confirms the transfer\n *\n * @param settlementId - Settlement ID\n * @param details - Completion details\n * @returns Updated settlement\n */\n async complete(\n settlementId: string,\n details: CompletionDetails = {}\n ): Promise<SettlementDocument> {\n if (!this.models.Settlement) {\n throw new ModelNotRegisteredError('Settlement');\n }\n\n const SettlementModel = this.models.Settlement;\n const settlement = await SettlementModel.findById(settlementId) as SettlementDocument | null;\n\n if (!settlement) {\n throw new ValidationError('Settlement not found', { settlementId });\n }\n\n // Validate state transition\n if (settlement.status !== SETTLEMENT_STATUS.PROCESSING && settlement.status !== SETTLEMENT_STATUS.PENDING) {\n throw new InvalidStateTransitionError(\n 'complete',\n SETTLEMENT_STATUS.PROCESSING,\n settlement.status,\n 'Only processing or pending settlements can be completed'\n );\n }\n\n const {\n transferReference,\n transferredAt = new Date(),\n transactionHash,\n notes,\n metadata = {},\n } = details;\n\n // Validate state transition and create audit event\n const auditEvent = SETTLEMENT_STATE_MACHINE.validateAndCreateAuditEvent(\n settlement.status,\n SETTLEMENT_STATUS.COMPLETED,\n settlement._id.toString(),\n {\n changedBy: 'system',\n reason: 'Settlement completed successfully',\n metadata: {\n transferReference,\n transferredAt,\n transactionHash,\n payoutMethod: settlement.payoutMethod,\n amount: settlement.amount\n }\n }\n );\n\n // Update settlement\n settlement.status = SETTLEMENT_STATUS.COMPLETED;\n settlement.completedAt = new Date();\n\n // Update payout method details\n if (settlement.payoutMethod === 'bank_transfer' && transferReference) {\n settlement.bankTransferDetails = {\n ...settlement.bankTransferDetails,\n transferReference,\n transferredAt,\n };\n } else if (settlement.payoutMethod === 'crypto' && transactionHash) {\n settlement.cryptoDetails = {\n ...settlement.cryptoDetails,\n transactionHash,\n transferredAt,\n };\n } else if (settlement.payoutMethod === 'mobile_wallet') {\n settlement.mobileWalletDetails = {\n ...settlement.mobileWalletDetails,\n transferredAt,\n };\n } else if (settlement.payoutMethod === 'platform_balance') {\n settlement.platformBalanceDetails = {\n ...settlement.platformBalanceDetails,\n appliedAt: transferredAt,\n };\n }\n\n if (notes) settlement.notes = notes;\n settlement.metadata = { ...settlement.metadata, ...metadata };\n\n // Append audit event to metadata\n Object.assign(settlement, appendAuditEvent(settlement, auditEvent));\n\n await settlement.save();\n\n // Trigger hook\n this.events.emit('settlement.completed', {\n settlement,\n completedAt: settlement.completedAt,\n });\n\n this.logger.info('Settlement completed', {\n settlementId: settlement._id,\n recipientId: settlement.recipientId,\n amount: settlement.amount,\n });\n\n return settlement;\n }\n\n /**\n * Mark settlement as failed\n *\n * @param settlementId - Settlement ID\n * @param reason - Failure reason\n * @returns Updated settlement\n */\n async fail(\n settlementId: string,\n reason: string,\n options: { code?: string; retry?: boolean } = {}\n ): Promise<SettlementDocument> {\n if (!this.models.Settlement) {\n throw new ModelNotRegisteredError('Settlement');\n }\n\n const SettlementModel = this.models.Settlement;\n const settlement = await SettlementModel.findById(settlementId) as SettlementDocument | null;\n\n if (!settlement) {\n throw new ValidationError('Settlement not found', { settlementId });\n }\n\n const { code, retry = false } = options;\n\n // Update settlement\n if (retry) {\n // Validate state transition to pending (for retry) and create audit event\n const auditEvent = SETTLEMENT_STATE_MACHINE.validateAndCreateAuditEvent(\n settlement.status,\n SETTLEMENT_STATUS.PENDING,\n settlement._id.toString(),\n {\n changedBy: 'system',\n reason: `Settlement failed, retrying: ${reason}`,\n metadata: {\n failureReason: reason,\n failureCode: code,\n retryCount: (settlement.retryCount || 0) + 1,\n scheduledAt: new Date(Date.now() + 60 * 60 * 1000)\n }\n }\n );\n\n // Reset to pending for retry\n settlement.status = SETTLEMENT_STATUS.PENDING;\n settlement.retryCount = (settlement.retryCount || 0) + 1;\n settlement.scheduledAt = new Date(Date.now() + 60 * 60 * 1000); // Retry in 1 hour\n\n // Append audit event to metadata\n Object.assign(settlement, appendAuditEvent(settlement, auditEvent));\n } else {\n // Validate state transition to failed and create audit event\n const auditEvent = SETTLEMENT_STATE_MACHINE.validateAndCreateAuditEvent(\n settlement.status,\n SETTLEMENT_STATUS.FAILED,\n settlement._id.toString(),\n {\n changedBy: 'system',\n reason: `Settlement failed: ${reason}`,\n metadata: {\n failureReason: reason,\n failureCode: code\n }\n }\n );\n\n settlement.status = SETTLEMENT_STATUS.FAILED;\n settlement.failedAt = new Date();\n\n // Append audit event to metadata\n Object.assign(settlement, appendAuditEvent(settlement, auditEvent));\n }\n\n settlement.failureReason = reason;\n if (code) settlement.failureCode = code;\n\n await settlement.save();\n\n // Trigger hook\n this.events.emit('settlement.failed', {\n settlement,\n reason,\n code,\n retry,\n });\n\n this.logger.warn('Settlement failed', {\n settlementId: settlement._id,\n reason,\n retry,\n });\n\n return settlement;\n }\n\n /**\n * List settlements with filters\n *\n * @param filters - Query filters\n * @returns Settlements\n */\n async list(filters: SettlementFilters = {}): Promise<SettlementDocument[]> {\n if (!this.models.Settlement) {\n throw new ModelNotRegisteredError('Settlement');\n }\n\n const SettlementModel = this.models.Settlement;\n const {\n organizationId,\n recipientId,\n status,\n type,\n payoutMethod,\n scheduledAfter,\n scheduledBefore,\n limit = 50,\n skip = 0,\n sort = { createdAt: -1 },\n } = filters;\n\n // Build query\n const query: Record<string, unknown> = {};\n\n if (organizationId) query.organizationId = organizationId;\n if (recipientId) query.recipientId = recipientId;\n if (status) query.status = Array.isArray(status) ? { $in: status } : status;\n if (type) query.type = type;\n if (payoutMethod) query.payoutMethod = payoutMethod;\n\n if (scheduledAfter || scheduledBefore) {\n query.scheduledAt = {};\n if (scheduledAfter) (query.scheduledAt as Record<string, unknown>).$gte = scheduledAfter;\n if (scheduledBefore) (query.scheduledAt as Record<string, unknown>).$lte = scheduledBefore;\n }\n\n const settlements = await (SettlementModel as unknown as {\n find(filter: object): {\n limit(n: number): { skip(n: number): { sort(s: object): Promise<SettlementDocument[]> } };\n };\n })\n .find(query)\n .limit(limit)\n .skip(skip)\n .sort(sort);\n\n return settlements;\n }\n\n /**\n * Get payout summary for recipient\n *\n * @param recipientId - Recipient ID\n * @param options - Summary options\n * @returns Settlement summary\n */\n async getSummary(\n recipientId: string,\n options: SummaryOptions = {}\n ): Promise<SettlementSummary> {\n if (!this.models.Settlement) {\n throw new ModelNotRegisteredError('Settlement');\n }\n\n const { organizationId, startDate, endDate } = options;\n\n const SettlementModel = this.models.Settlement;\n\n // Build query\n const query: Record<string, unknown> = { recipientId };\n if (organizationId) query.organizationId = organizationId;\n\n if (startDate || endDate) {\n query.createdAt = {};\n if (startDate) (query.createdAt as Record<string, unknown>).$gte = startDate;\n if (endDate) (query.createdAt as Record<string, unknown>).$lte = endDate;\n }\n\n // Get all settlements for recipient\n const settlements = await (SettlementModel as unknown as {\n find(filter: object): Promise<SettlementDocument[]>;\n }).find(query);\n\n // Calculate summary\n const summary: SettlementSummary = {\n recipientId,\n totalPending: 0,\n totalProcessing: 0,\n totalCompleted: 0,\n totalFailed: 0,\n amountPending: 0,\n amountCompleted: 0,\n amountFailed: 0,\n currency: settlements[0]?.currency || 'USD',\n settlements: {\n pending: 0,\n processing: 0,\n completed: 0,\n failed: 0,\n cancelled: 0,\n },\n };\n\n for (const settlement of settlements) {\n summary.settlements[settlement.status as keyof typeof summary.settlements]++;\n\n if (settlement.status === SETTLEMENT_STATUS.PENDING) {\n summary.totalPending++;\n summary.amountPending += settlement.amount;\n } else if (settlement.status === SETTLEMENT_STATUS.PROCESSING) {\n summary.totalProcessing++;\n } else if (settlement.status === SETTLEMENT_STATUS.COMPLETED) {\n summary.totalCompleted++;\n summary.amountCompleted += settlement.amount;\n if (!summary.lastSettlementDate || settlement.completedAt! > summary.lastSettlementDate) {\n summary.lastSettlementDate = settlement.completedAt!;\n }\n } else if (settlement.status === SETTLEMENT_STATUS.FAILED) {\n summary.totalFailed++;\n summary.amountFailed += settlement.amount;\n }\n }\n\n return summary;\n }\n\n /**\n * Get settlement by ID\n *\n * @param settlementId - Settlement ID\n * @returns Settlement\n */\n async get(settlementId: string): Promise<SettlementDocument> {\n if (!this.models.Settlement) {\n throw new ModelNotRegisteredError('Settlement');\n }\n\n const SettlementModel = this.models.Settlement;\n const settlement = await SettlementModel.findById(settlementId) as SettlementDocument | null;\n\n if (!settlement) {\n throw new ValidationError('Settlement not found', { settlementId });\n }\n\n return settlement;\n }\n\n}\n\nexport default SettlementService;\n"]}
|