@relaybus/rabbitmq 0.4.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/errors.ts","../src/confirmed-publishing.ts","../src/abortable-sleep.ts","../src/connection-supervisor.ts","../src/json-payload.ts","../src/wire-format.ts","../src/inbound-decoders.ts","../src/codecs.ts","../src/redelivery.ts","../src/options.ts","../src/topology.ts","../src/queue-consumer.ts","../src/serial-queue.ts","../src/rabbitmq-transport.ts"],"names":["RelayBusError","NonRetryableError","schedule","systemClock","toErrorInfo","computeRetryDelay","writeStructuredCloudEvent","MILLISECONDS_PER_SECOND","createCloudEventReaders","SPEC_VERSION","mediaTypeOf","isJsonObject","parseTime","assertEventType","DecodedEventReader","text","observeRejection","createJsonEnvelopeFormat","ConfigurationError","NonEmptyText","PositiveInteger","createRetryPolicy","Milliseconds","isRetryableError","error","SubscribingTransport"],"mappings":";;;;;;AAOO,IAAM,wBAAA,GAAN,cAAuCA,kBAAA,CAAc;AAAA,EACjD,IAAA,GAAO,0BAAA;AAAA,EACE,IAAA,GAAe,+BAAA;AACnC;AAGO,IAAM,4BAAA,GAAN,cAA2CA,kBAAA,CAAc;AAAA,EACrD,IAAA,GAAO,8BAAA;AAAA,EACE,IAAA,GAAe,oCAAA;AACnC;AAMO,IAAM,sBAAA,GAAN,cAAqCA,kBAAA,CAAc;AAAA,EAC/C,IAAA,GAAO,wBAAA;AAAA,EACE,IAAA,GAAe,sCAAA;AACnC;AAGO,IAAM,qBAAA,GAAN,cAAoCA,kBAAA,CAAc;AAAA,EAC9C,IAAA,GAAO,uBAAA;AAAA,EACE,IAAA,GAAe,qCAAA;AACnC;AAOO,IAAM,0BAAA,GAAN,cAAyCC,sBAAA,CAAkB;AAAA,EACvD,IAAA,GAAO,4BAAA;AAAA,EACE,IAAA,GAAe,0CAAA;AACnC;AAMO,IAAM,sBAAA,GAAN,cAAqCA,sBAAA,CAAkB;AAAA,EACnD,IAAA,GAAO,wBAAA;AAAA,EACE,IAAA,GAAe,uCAAA;AACnC;AAMO,IAAM,6BAAA,GAAN,cAA4CA,sBAAA,CAAkB;AAAA,EAC1D,IAAA,GAAO,+BAAA;AAAA,EACE,IAAA,GAAe,qCAAA;AACnC;AC/BA,IAAM,YAAA,GAAe,gBAAA;AAmBd,IAAM,sBAAN,MAA0B;AAAA,EACtB,cAAA;AAAA,EACA,iBAAA;AAAA,EAET,WAAA,CAAY,eAAuB,gBAAA,EAA0B;AAC3D,IAAA,IAAA,CAAK,cAAA,GAAiB,aAAA;AACtB,IAAA,IAAA,CAAK,iBAAA,GAAoB,gBAAA;AAAA,EAC3B;AAAA,EAEA,MAAM,OAAA,CAAQ,SAAA,EAAkC,KAAA,EAA6C;AAC3F,IAAA,MAAM,EAAE,QAAA,EAAU,UAAA,EAAY,OAAA,EAAS,OAAA,EAAS,WAAU,GAAI,KAAA;AAC9D,IAAA,MAAM,OAAA,GAAU,QAAQ,SAAA,IAAa,SAAA;AACrC,IAAA,IAAI,cAAc,MAAA,EAAW;AAC3B,MAAA,MAAM,IAAI,wBAAA;AAAA,QACR,CAAA,qEAAA,EAAwE,IAAA,CAAK,cAAc,CAAA,aAAA,EAAgB,UAAU,CAAA;AAAA,OACvH;AAAA,IACF;AACA,IAAA,MAAM,SAAA,GAAY,aAAA,CAAc,OAAA,CAAQ,SAAA,EAAW,UAAU,CAAA;AAC7D,IAAA,MAAM,MAAA,GAAS,EAAE,OAAA,EAAS,WAAA,EAAa,UAAA,EAAW;AAClD,IAAA,MAAM,IAAI,OAAA,CAAc,CAAC,OAAA,EAAS,MAAA,KAAW;AAC3C,MAAA,MAAM,aAAA,GAAgB,IAAA,CAAK,aAAA,CAAc,MAAA,EAAQ,MAAM,CAAA;AACvD,MAAA,MAAM,OAAA,GAAU,EAAE,GAAG,MAAA,EAAQ,WAAW,SAAA,EAAW,aAAA,EAAe,SAAS,MAAA,EAAO;AAClF,MAAA,IAAI;AACF,QAAA,SAAA,CAAU,OAAA,CAAQ,OAAA;AAAA,UAChB,QAAA;AAAA,UACA,UAAA;AAAA,UACA,OAAA;AAAA,UACA,EAAE,GAAG,OAAA,EAAS,SAAA,EAAU;AAAA,UACxB,CAAC,KAAA,KAAU,IAAA,CAAK,UAAA,CAAW,SAAS,KAAK;AAAA,SAC3C;AAAA,MACF,SAAS,KAAA,EAAO;AACd,QAAA,aAAA,EAAc;AACd,QAAA,MAAA,CAAO,IAAA,CAAK,eAAA,CAAgB,KAAA,EAAO,MAAM,CAAC,CAAA;AAAA,MAC5C;AAAA,IACF,CAAC,CAAA;AAAA,EACH;AAAA,EAEA,aAAA,CACE,EAAE,OAAA,EAAS,WAAA,IACX,MAAA,EACa;AACb,IAAA,OAAOC,kBAASC,gBAAA,EAAa;AAAA,MAC3B,KAAK,MAAM;AACT,QAAA,MAAA;AAAA,UACE,IAAI,wBAAA;AAAA,YACF,CAAA,sDAAA,EAAyD,KAAK,iBAAiB,CAAA,eAAA,EAAkB,KAAK,cAAc,CAAA,SAAA,EAAY,OAAO,CAAA,aAAA,EAAgB,WAAW,CAAA;AAAA;AACpK,SACF;AAAA,MACF,CAAA;AAAA,MACA,SAAS,IAAA,CAAK;AAAA,KACf,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,UAAA,CAAW,SAAyB,KAAA,EAAuC;AACzE,IAAA,OAAA,CAAQ,aAAA,EAAc;AACtB,IAAA,MAAM,WAAW,cAAA,CAAe,OAAA,CAAQ,SAAA,CAAU,UAAA,EAAY,QAAQ,SAAS,CAAA;AAC/E,IAAA,IAAI,KAAA,EAAO;AACT,MAAA,OAAA,CAAQ,MAAA,CAAO,IAAA,CAAK,eAAA,CAAgB,KAAA,EAAO,OAAO,CAAC,CAAA;AAAA,IACrD,WAAW,QAAA,EAAU;AACnB,MAAA,OAAA,CAAQ,MAAA;AAAA,QACN,IAAI,sBAAA;AAAA,UACF,CAAA,8EAAA,EAAiF,KAAK,cAAc,CAAA,SAAA,EAAY,QAAQ,OAAO,CAAA,aAAA,EAAgB,QAAQ,WAAW,CAAA;AAAA;AACpK,OACF;AAAA,IACF,CAAA,MAAO;AACL,MAAA,OAAA,CAAQ,OAAA,EAAQ;AAAA,IAClB;AAAA,EACF;AAAA,EAEA,eAAA,CAAgB,KAAA,EAAgB,EAAE,OAAA,EAAS,aAAY,EAAyB;AAC9E,IAAA,MAAM,EAAE,OAAA,EAAQ,GAAIC,gBAAA,CAAY,KAAK,CAAA;AACrC,IAAA,MAAM,MAAA,GAAS,aAAa,IAAA,CAAK,cAAc,YAAY,OAAO,CAAA,aAAA,EAAgB,WAAW,CAAA,OAAA,EAAU,OAAO,CAAA,CAAA;AAC9G,IAAA,OAAO,OAAA,KAAY,eACf,IAAI,4BAAA;AAAA,MACF,4DAA4D,MAAM,CAAA,CAAA;AAAA,MAClE,EAAE,OAAO,KAAA;AAAM,KACjB,GACA,IAAI,wBAAA,CAAyB,CAAA,8CAAA,EAAiD,MAAM,CAAA,CAAA,EAAI;AAAA,MACtF,KAAA,EAAO;AAAA,KACR,CAAA;AAAA,EACP;AACF,CAAA;AAGO,SAAS,aAAA,CAAc,WAAoB,UAAA,EAA4B;AAC5E,EAAA,OAAO,CAAA,EAAG,MAAA,CAAO,SAAS,CAAC;AAAA,EAAK,UAAU,CAAA,CAAA;AAC5C;AAEO,SAAS,gBAAA,CAAiB,YAAiC,GAAA,EAAmB;AACnF,EAAA,UAAA,CAAW,IAAI,GAAA,EAAA,CAAM,UAAA,CAAW,IAAI,GAAG,CAAA,IAAK,KAAK,CAAC,CAAA;AACpD;AAEA,SAAS,cAAA,CAAe,YAAiC,GAAA,EAAsB;AAC7E,EAAA,MAAM,KAAA,GAAQ,UAAA,CAAW,GAAA,CAAI,GAAG,CAAA;AAChC,EAAA,IAAI,UAAU,MAAA,EAAW;AACvB,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,IAAI,UAAU,CAAA,EAAG;AACf,IAAA,UAAA,CAAW,OAAO,GAAG,CAAA;AAAA,EACvB,CAAA,MAAO;AACL,IAAA,UAAA,CAAW,GAAA,CAAI,GAAA,EAAK,KAAA,GAAQ,CAAC,CAAA;AAAA,EAC/B;AACA,EAAA,OAAO,IAAA;AACT;ACnJO,SAAS,cAAA,CAAe,cAAsB,MAAA,EAAoC;AACvF,EAAA,IAAI,OAAO,OAAA,EAAS;AAClB,IAAA,OAAO,QAAQ,OAAA,EAAQ;AAAA,EACzB;AACA,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,KAAY;AAC9B,IAAA,MAAM,SAAS,MAAY;AACzB,MAAA,MAAA,EAAO;AACP,MAAA,MAAA,CAAO,mBAAA,CAAoB,SAAS,MAAM,CAAA;AAC1C,MAAA,OAAA,EAAQ;AAAA,IACV,CAAA;AACA,IAAA,MAAM,MAAA,GAASF,kBAASC,gBAAAA,EAAa,EAAE,KAAK,MAAA,EAAQ,OAAA,EAAS,cAAc,CAAA;AAC3E,IAAA,MAAA,CAAO,iBAAiB,OAAA,EAAS,MAAA,EAAQ,EAAE,IAAA,EAAM,MAAM,CAAA;AAAA,EACzD,CAAC,CAAA;AACH;;;ACYO,IAAM,uBAAN,MAA2B;AAAA,EACvB,SAAA;AAAA,EACA,KAAA,GAAQ,IAAI,eAAA,EAAgB;AAAA;AAAA,EAE5B,MAAA,GAAS,IAAI,eAAA,EAAgB;AAAA;AAAA,EAE7B,QAAA,GAAW,IAAI,OAAA,CAAc,CAAC,OAAA,KAAY;AACjD,IAAA,IAAA,CAAK,MAAA,CAAO,MAAA,CAAO,gBAAA,CAAiB,OAAA,EAAS,MAAM,SAAQ,EAAG,EAAE,IAAA,EAAM,IAAA,EAAM,CAAA;AAAA,EAC9E,CAAC,CAAA;AAAA,EACD,QAAA;AAAA;AAAA,EAES,QAAA,uBAAe,GAAA,EAAoB;AAAA;AAAA,EAE5C,OAAA,GAAU,KAAA;AAAA,EACV,MAAA,GAAS,KAAA;AAAA,EACT,QAAA,GAAW,KAAA;AAAA,EACX,OAAA,GAAU,KAAA;AAAA,EACV,aAAA;AAAA,EAEA,YAAY,QAAA,EAAwC;AAClD,IAAA,IAAA,CAAK,SAAA,GAAY,QAAA;AAAA,EACnB;AAAA;AAAA,EAGA,WAAA,GAAuB;AACrB,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,MAAM,WAAA,EAAqC;AAC/C,IAAA,IAAI,KAAK,QAAA,EAAU;AACjB,MAAA;AAAA,IACF;AACA,IAAA,IAAI,KAAK,OAAA,EAAS;AAChB,MAAA,MAAM,IAAI,yBAAyB,mDAAmD,CAAA;AAAA,IACxF;AACA,IAAA,IAAI;AACF,MAAA,MAAM,KAAK,UAAA,EAAW;AACtB,MAAA,IAAA,CAAK,QAAA,GAAW,IAAA;AAAA,IAClB,SAAS,KAAA,EAAO;AACd,MAAA,IAAI,WAAA,EAAa;AACf,QAAA,MAAM,KAAA;AAAA,MACR;AACA,MAAA,IAAA,CAAK,UAAU,MAAA,CAAO,IAAA;AAAA,QACpB,CAAA,qFAAA,EAAwFC,gBAAAA,CAAY,KAAK,CAAA,CAAE,OAAO,CAAA;AAAA,OACpH;AACA,MAAA,IAAA,CAAK,QAAA,GAAW,IAAA;AAChB,MAAA,IAAA,CAAK,kBAAA,EAAmB;AAAA,IAC1B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,QAAQ,MAAA,EAAsB;AAC5B,IAAA,MAAM,aAAa,IAAA,CAAK,QAAA;AACxB,IAAA,IAAI,eAAe,MAAA,EAAW;AAC5B,MAAA;AAAA,IACF;AACA,IAAA,IAAA,CAAK,WAAA,CAAY,YAAY,MAAM,CAAA;AACnC,IAAA,KAAK,IAAA,CAAK,iBAAiB,UAAU,CAAA;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,MAAM,gBAAA,EAAsD;AAChE,IAAA,IAAA,CAAK,OAAA,GAAU,IAAA;AACf,IAAA,IAAA,CAAK,MAAM,KAAA,EAAM;AAEjB,IAAA,MAAM,QAAQ,IAAA,CAAK,CAAC,KAAK,aAAA,EAAe,IAAA,CAAK,QAAQ,CAAC,CAAA;AACtD,IAAA,IAAI;AACF,MAAA,MAAM,QAAQ,IAAA,CAAK,CAAC,kBAAiB,EAAG,IAAA,CAAK,QAAQ,CAAC,CAAA;AAAA,IACxD,CAAA,SAAE;AACA,MAAA,MAAM,aAAa,IAAA,CAAK,QAAA;AACxB,MAAA,IAAA,CAAK,QAAA,GAAW,MAAA;AAChB,MAAA,IAAA,CAAK,MAAA,GAAS,KAAA;AACd,MAAA,IAAI,eAAe,MAAA,EAAW;AAC5B,QAAA,MAAM,IAAA,CAAK,iBAAiB,UAAU,CAAA;AAAA,MACxC;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,UAAA,GAAmB;AACjB,IAAA,IAAA,CAAK,OAAA,GAAU,IAAA;AACf,IAAA,IAAA,CAAK,OAAA,GAAU,IAAA;AACf,IAAA,IAAA,CAAK,MAAM,KAAA,EAAM;AACjB,IAAA,IAAA,CAAK,OAAO,KAAA,EAAM;AAClB,IAAA,KAAA,MAAW,cAAc,CAAC,IAAA,CAAK,UAAU,GAAG,IAAA,CAAK,QAAQ,CAAA,EAAG;AAC1D,MAAA,IAAI,eAAe,MAAA,EAAW;AAC5B,QAAA,aAAA,CAAc,UAAU,CAAA;AAAA,MAC1B;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,iBAAiB,UAAA,EAA2C;AAChE,IAAA,IAAI,KAAK,OAAA,EAAS;AAChB,MAAA,aAAA,CAAc,UAAU,CAAA;AACxB,MAAA;AAAA,IACF;AACA,IAAA,IAAA,CAAK,QAAA,CAAS,IAAI,UAAU,CAAA;AAC5B,IAAA,MAAM,UAAA,CAAW,KAAA,EAAM,CAAE,KAAA,CAAM,MAAM,MAAS,CAAA;AAC9C,IAAA,IAAA,CAAK,QAAA,CAAS,OAAO,UAAU,CAAA;AAAA,EACjC;AAAA,EAEA,MAAM,UAAA,GAA4B;AAChC,IAAA,MAAM,UAAA,GAAa,MAAM,IAAA,CAAK,SAAA,CAAU,OAAA,CAAQ,EAAE,MAAA,EAAQ,IAAA,CAAK,MAAA,CAAO,MAAA,EAAQ,CAAA;AAE9E,IAAA,UAAA,CAAW,EAAA,CAAG,OAAA,EAAS,CAAC,KAAA,KAAiB;AACvC,MAAA,IAAA,CAAK,UAAU,MAAA,CAAO,IAAA;AAAA,QACpB,CAAA,2DAAA,EAA8D,MAAM,OAAO,CAAA;AAAA,OAC7E;AAAA,IACF,CAAC,CAAA;AACD,IAAA,IAAI,KAAK,OAAA,EAAS;AAEhB,MAAA,MAAM,IAAA,CAAK,iBAAiB,UAAU,CAAA;AACtC,MAAA,MAAM,IAAI,yBAAyB,uDAAuD,CAAA;AAAA,IAC5F;AACA,IAAA,UAAA,CAAW,EAAA,CAAG,OAAA,EAAS,CAAC,KAAA,KAAkB;AACxC,MAAA,IAAA,CAAK,WAAA,CAAY,UAAA,EAAY,KAAA,EAAO,OAAA,IAAW,gBAAgB,CAAA;AAAA,IACjE,CAAC,CAAA;AACD,IAAA,IAAA,CAAK,QAAA,GAAW,UAAA;AAChB,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,CAAK,SAAA,CAAU,WAAA,CAAY,UAAU,CAAA;AAC3C,MAAA,IAAI,IAAA,CAAK,aAAa,UAAA,EAAY;AAChC,QAAA,MAAM,IAAI,wBAAA;AAAA,UACR;AAAA,SACF;AAAA,MACF;AAAA,IACF,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,IAAA,CAAK,SAAS,UAAU,CAAA;AAC9B,MAAA,MAAM,KAAA;AAAA,IACR;AACA,IAAA,IAAA,CAAK,MAAA,GAAS,IAAA;AAAA,EAChB;AAAA,EAEA,MAAM,SAAS,UAAA,EAA2C;AACxD,IAAA,IAAI,IAAA,CAAK,aAAa,UAAA,EAAY;AAChC,MAAA,IAAA,CAAK,QAAA,GAAW,MAAA;AAAA,IAClB;AACA,IAAA,IAAA,CAAK,UAAU,cAAA,EAAe;AAC9B,IAAA,MAAM,IAAA,CAAK,iBAAiB,UAAU,CAAA;AAAA,EACxC;AAAA,EAEA,WAAA,CAAY,YAA4B,MAAA,EAAsB;AAC5D,IAAA,IAAI,UAAA,KAAe,KAAK,QAAA,EAAU;AAChC,MAAA;AAAA,IACF;AACA,IAAA,IAAA,CAAK,QAAA,GAAW,MAAA;AAChB,IAAA,IAAA,CAAK,MAAA,GAAS,KAAA;AACd,IAAA,IAAA,CAAK,UAAU,MAAA,CAAO,IAAA;AAAA,MACpB,+DAA+D,MAAM,CAAA;AAAA,KACvE;AACA,IAAA,IAAA,CAAK,UAAU,cAAA,EAAe;AAC9B,IAAA,IAAA,CAAK,kBAAA,EAAmB;AAAA,EAC1B;AAAA,EAEA,kBAAA,GAA2B;AACzB,IAAA,IACE,IAAA,CAAK,SAAA,CAAU,SAAA,KAAc,MAAA,IAC7B,IAAA,CAAK,OAAA,IACL,CAAC,IAAA,CAAK,QAAA,IACN,IAAA,CAAK,aAAA,KAAkB,MAAA,EACvB;AACA,MAAA;AAAA,IACF;AACA,IAAA,MAAM,MAAA,GAAS,KAAK,SAAA,CAAU,SAAA;AAC9B,IAAA,IAAA,CAAK,gBAAgB,IAAA,CAAK,wBAAA,CAAyB,MAAM,CAAA,CAAE,QAAQ,MAAM;AACvE,MAAA,IAAA,CAAK,aAAA,GAAgB,MAAA;AAAA,IACvB,CAAC,CAAA;AAAA,EACH;AAAA,EAEA,MAAM,yBAAyB,MAAA,EAAoC;AACjE,IAAA,KAAA,IAAS,UAAU,CAAA,EAAG,CAAC,IAAA,CAAK,OAAA,EAAS,WAAW,CAAA,EAAG;AACjD,MAAA,MAAM,UAAUC,sBAAA,CAAkB,MAAA,EAAQ,OAAA,EAAS,IAAA,CAAK,UAAU,MAAM,CAAA;AACxE,MAAA,IAAA,CAAK,UAAU,MAAA,CAAO,GAAA;AAAA,QACpB,CAAA,uEAAA,EAA0E,OAAO,CAAA,SAAA,EAAY,OAAO,CAAA;AAAA,OACtG;AACA,MAAA,MAAM,cAAA,CAAe,OAAA,EAAS,IAAA,CAAK,KAAA,CAAM,MAAM,CAAA;AAC/C,MAAA,IAAI,KAAK,OAAA,EAAS;AAChB,QAAA;AAAA,MACF;AACA,MAAA,IAAI;AACF,QAAA,MAAM,KAAK,UAAA,EAAW;AACtB,QAAA,IAAA,CAAK,UAAU,MAAA,CAAO,GAAA;AAAA,UACpB,yEAAyE,OAAO,CAAA;AAAA,SAClF;AACA,QAAA;AAAA,MACF,SAAS,KAAA,EAAO;AACd,QAAA,IAAA,CAAK,UAAU,MAAA,CAAO,IAAA;AAAA,UACpB,4EAA4E,OAAO,CAAA,OAAA,EAAUD,gBAAAA,CAAY,KAAK,EAAE,OAAO,CAAA;AAAA,SACzH;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF,CAAA;AAOA,SAAS,cAAc,UAAA,EAAkC;AACvD,EAAA,MAAM,KAAA,GAAQ,UAAA;AAGd,EAAA,KAAA,CAAM,YAAY,MAAA,EAAQ,OAAA;AAAA,IACxB,IAAI,yBAAyB,8CAA8C;AAAA,GAC7E;AACF;;;AC7OO,SAAS,iBAAA,CAAkB,SAAkB,OAAA,EAAuB;AACzE,EAAA,KAAA,CAAM,OAAA,EAAS,EAAE,IAAA,EAAM,GAAA,EAAK,2BAAW,IAAI,GAAA,EAAI,EAAG,OAAA,EAAS,CAAA;AAC7D;AAEA,SAAS,MACP,KAAA,EACA;AAAA,EACE,IAAA;AAAA,EACA,SAAA;AAAA,EACA;AACF,CAAA,EACM;AACN,EAAA,QAAQ,OAAO,KAAA;AAAO,IACpB,KAAK,QAAA;AAAA,IACL,KAAK,SAAA;AACH,MAAA;AAAA,IACF,KAAK,QAAA;AACH,MAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,KAAK,CAAA,EAAG;AAC3B,QAAA,MAAM,MAAA,CAAO,SAAS,EAAE,IAAA,EAAM,QAAQ,CAAA,GAAA,EAAM,KAAK,gCAAgC,CAAA;AAAA,MACnF;AACA,MAAA;AAAA,IACF,KAAK,QAAA;AACH,MAAA,IAAI,UAAU,IAAA,EAAM;AAClB,QAAA,WAAA,CAAY,KAAA,EAAO,EAAE,IAAA,EAAM,SAAA,EAAW,SAAS,CAAA;AAAA,MACjD;AACA,MAAA;AAAA,IACF;AACE,MAAA,MAAM,MAAA,CAAO,SAAS,EAAE,IAAA,EAAM,QAAQ,CAAA,GAAA,EAAM,OAAO,KAAK,CAAA,6BAAA,CAAA,EAAiC,CAAA;AAAA;AAE/F;AAEA,SAAS,YACP,KAAA,EACA;AAAA,EACE,IAAA;AAAA,EACA,SAAA;AAAA,EACA;AACF,CAAA,EACM;AACN,EAAA,IAAI,SAAA,CAAU,GAAA,CAAI,KAAK,CAAA,EAAG;AACxB,IAAA,MAAM,OAAO,OAAA,EAAS,EAAE,IAAA,EAAM,MAAA,EAAQ,2BAA2B,CAAA;AAAA,EACnE;AACA,EAAA,SAAA,CAAU,IAAI,KAAK,CAAA;AACnB,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AACxB,IAAA,UAAA,CAAW,KAAA,EAAO,EAAE,IAAA,EAAM,SAAA,EAAW,SAAS,CAAA;AAAA,EAChD,CAAA,MAAO;AACL,IAAA,gBAAA,CAAiB,KAAA,EAAO,EAAE,IAAA,EAAM,SAAA,EAAW,SAAS,CAAA;AAAA,EACtD;AACA,EAAA,SAAA,CAAU,OAAO,KAAK,CAAA;AACxB;AASA,SAAS,WAAW,KAAA,EAAkB,EAAE,IAAA,EAAM,SAAA,EAAW,SAAQ,EAAqB;AACpF,EAAA,KAAA,IAAS,QAAQ,CAAA,EAAG,KAAA,GAAQ,KAAA,CAAM,MAAA,EAAQ,SAAS,CAAA,EAAG;AACpD,IAAA,IAAI,EAAE,SAAS,KAAA,CAAA,EAAQ;AACrB,MAAA,MAAM,OAAO,OAAA,EAAS;AAAA,QACpB,IAAA,EAAM,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,KAAK,CAAA,CAAA,CAAA;AAAA,QACtB,MAAA,EAAQ;AAAA,OACT,CAAA;AAAA,IACH;AACA,IAAA,KAAA,CAAM,KAAA,CAAM,KAAK,CAAA,EAAG,EAAE,IAAA,EAAM,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,KAAK,CAAA,CAAA,CAAA,EAAK,SAAA,EAAW,OAAA,EAAS,CAAA;AAAA,EACvE;AACF;AAEA,SAAS,iBAAiB,KAAA,EAAe,EAAE,IAAA,EAAM,SAAA,EAAW,SAAQ,EAAqB;AACvF,EAAA,MAAM,SAAA,GAAY,MAAA,CAAO,cAAA,CAAe,KAAK,CAAA;AAC7C,EAAA,IAAI,SAAA,KAAc,MAAA,CAAO,SAAA,IAAa,SAAA,KAAc,IAAA,EAAM;AACxD,IAAA,MAAM,OAAO,OAAA,EAAS;AAAA,MACpB,IAAA;AAAA,MACA,MAAA,EAAQ;AAAA,KACT,CAAA;AAAA,EACH;AACA,EAAA,IAAI,MAAA,CAAO,qBAAA,CAAsB,KAAK,CAAA,CAAE,SAAS,CAAA,EAAG;AAClD,IAAA,MAAM,OAAO,OAAA,EAAS,EAAE,IAAA,EAAM,MAAA,EAAQ,sCAAsC,CAAA;AAAA,EAC9E;AACA,EAAA,KAAA,MAAW,GAAA,IAAO,MAAA,CAAO,IAAA,CAAK,KAAK,CAAA,EAAG;AACpC,IAAA,KAAA,CAAO,KAAA,CAAkC,GAAG,CAAA,EAAG;AAAA,MAC7C,IAAA,EAAM,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,GAAG,CAAA,CAAA;AAAA,MACpB,SAAA;AAAA,MACA;AAAA,KACD,CAAA;AAAA,EACH;AACF;AAEA,SAAS,MAAA,CACP,OAAA,EACA,EAAE,IAAA,EAAM,QAAO,EACa;AAC5B,EAAA,OAAO,IAAI,0BAAA;AAAA,IACT,CAAA,MAAA,EAAS,OAAO,CAAA,iDAAA,EAAoD,IAAI,IAAI,MAAM,CAAA;AAAA,GACpF;AACF;;;ACjGA,IAAM,uBAAA,GAA0B,GAAA;AA6BhC,IAAM,gBAAA,GAAmB,cAAA;AACzB,IAAM,mBAAA,GAAsB,WAAA;AAC5B,IAAM,YAAA,GAAe,KAAA;AACrB,IAAM,iBAAA,GAAoB,kBAAA;AAC1B,IAAM,uBAAA,GAA0B,8BAAA;AAEhC,IAAM,wBAAA,GAA2B,CAAC,SAAA,EAAW,gBAAA,EAAkB,iBAAiB,aAAa,CAAA;AAC7F,IAAM,wBAAA,GAA2B,GAAA;AAE1B,IAAM,eAAA,GACX,uEAAA;AAcK,SAAS,eAAe,QAAA,EAAyC;AACtE,EAAA,iBAAA,CAAkB,QAAA,CAAS,OAAA,EAAS,QAAA,CAAS,EAAE,CAAA;AAC/C,EAAA,iBAAA,CAAkB,UAAA,EAAY,SAAS,EAAE,CAAA;AACzC,EAAA,MAAM,OAAA,GAAkC;AAAA,IACtC,CAAC,CAAA,EAAG,gBAAgB,CAAA,WAAA,CAAa,GAAG,YAAA;AAAA,IACpC,CAAC,CAAA,EAAG,gBAAgB,CAAA,EAAA,CAAI,GAAG,QAAA,CAAS,EAAA;AAAA,IACpC,CAAC,CAAA,EAAG,gBAAgB,CAAA,IAAA,CAAM,GAAG,QAAA,CAAS,IAAA;AAAA,IACtC,CAAC,CAAA,EAAG,gBAAgB,CAAA,MAAA,CAAQ,GAAG,QAAA,CAAS,MAAA;AAAA,IACxC,CAAC,CAAA,EAAG,gBAAgB,MAAM,GAAG,QAAA,CAAS,WAAW,WAAA,EAAY;AAAA,IAC7D,CAAC,CAAA,EAAG,gBAAgB,CAAA,eAAA,CAAiB,GAAG;AAAA,GAC1C;AACA,EAAA,qBAAA,CAAsB,SAAS,QAAQ,CAAA;AACvC,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,OAAO,IAAA,CAAK,IAAA,CAAK,UAAU,QAAA,CAAS,OAAO,GAAG,MAAM,CAAA;AAAA,IAC7D,OAAA,EAAS;AAAA,MACP,WAAA,EAAa,iBAAA;AAAA,MACb,UAAA,EAAY,IAAA;AAAA,MACZ,WAAW,QAAA,CAAS,EAAA;AAAA,MACpB,WAAW,IAAA,CAAK,KAAA,CAAM,SAAS,UAAA,CAAW,OAAA,KAAY,uBAAuB,CAAA;AAAA,MAC7E,GAAG,MAAA,CAAO,MAAA,EAAQ,QAAA,CAAS,IAAI,CAAA;AAAA,MAC/B,GAAG,MAAA,CAAO,OAAA,EAAS,QAAA,CAAS,MAAM,CAAA;AAAA,MAClC,GAAI,SAAS,aAAA,KAAkB,IAAA,GAAO,EAAC,GAAI,MAAA,CAAO,eAAA,EAAiB,QAAA,CAAS,aAAa,CAAA;AAAA,MACzF;AAAA;AACF,GACF;AACF;AAGA,SAAS,qBAAA,CAAsB,SAAiC,QAAA,EAA+B;AAC7F,EAAA,IAAI,QAAA,CAAS,QAAQ,IAAA,EAAM;AACzB,IAAA,OAAA,CAAQ,CAAA,EAAG,gBAAgB,CAAA,OAAA,CAAS,CAAA,GAAI,QAAA,CAAS,GAAA;AAAA,EACnD;AACA,EAAA,IAAI,QAAA,CAAS,gBAAgB,IAAA,EAAM;AACjC,IAAA,OAAA,CAAQ,CAAA,EAAG,gBAAgB,CAAA,WAAA,CAAa,CAAA,GAAI,QAAA,CAAS,WAAA;AAAA,EACvD;AACA,EAAA,IAAI,QAAA,CAAS,kBAAkB,IAAA,EAAM;AACnC,IAAA,OAAA,CAAQ,CAAA,EAAG,gBAAgB,CAAA,aAAA,CAAe,CAAA,GAAI,QAAA,CAAS,aAAA;AAAA,EACzD;AACA,EAAA,KAAA,MAAW,CAAC,MAAM,KAAK,CAAA,IAAK,OAAO,OAAA,CAAQ,QAAA,CAAS,OAAO,CAAA,EAAG;AAC5D,IAAA,iBAAA;AAAA,MACE,CAAA,aAAA,EAAgB,mBAAmB,CAAA,EAAG,IAAI,CAAA,CAAA,CAAA;AAAA,MAC1C,CAAA,EAAG,mBAAmB,CAAA,EAAG,IAAI,CAAA;AAAA,KAC/B;AACA,IAAA,OAAA,CAAQ,CAAA,EAAG,mBAAmB,CAAA,EAAG,IAAI,EAAE,CAAA,GAAI,KAAA;AAAA,EAC7C;AACF;AAYO,SAAS,yBAAyB,QAAA,EAAyC;AAChF,EAAA,iBAAA,CAAkB,QAAA,CAAS,OAAA,EAAS,QAAA,CAAS,EAAE,CAAA;AAC/C,EAAA,iBAAA,CAAkB,UAAA,EAAY,SAAS,EAAE,CAAA;AACzC,EAAA,MAAM,QAAA,GAAWE,mCAA0B,QAAA,EAAU;AAAA,IACnD,IAAA,EAAM,QAAA,CAAS,UAAA,CAAW,WAAA,EAAY;AAAA,IACtC,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,QAAA,CAAS,OAAO;AAAA,GACtC,CAAA;AACD,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,MAAA,CAAO,IAAA,CAAK,QAAA,EAAU,MAAM,CAAA;AAAA,IACrC,OAAA,EAAS;AAAA,MACP,GAAG,kBAAkB,QAAQ,CAAA;AAAA,MAC7B,WAAA,EAAa,uBAAA;AAAA,MACb,OAAA,EAAS,YAAA,CAAa,QAAA,EAAU,QAAA,CAAS,OAAO;AAAA;AAClD,GACF;AACF;AAGO,SAAS,kBACd,QAAA,EACqD;AACrD,EAAA,OAAO;AAAA,IACL,UAAA,EAAY,IAAA;AAAA,IACZ,WAAW,QAAA,CAAS,EAAA;AAAA,IACpB,WAAW,IAAA,CAAK,KAAA,CAAM,SAAS,UAAA,CAAW,OAAA,KAAY,uBAAuB,CAAA;AAAA,IAC7E,GAAG,MAAA,CAAO,MAAA,EAAQ,QAAA,CAAS,IAAI,CAAA;AAAA,IAC/B,GAAG,MAAA,CAAO,OAAA,EAAS,QAAA,CAAS,MAAM,CAAA;AAAA,IAClC,GAAI,SAAS,aAAA,KAAkB,IAAA,GAAO,EAAC,GAAI,MAAA,CAAO,eAAA,EAAiB,QAAA,CAAS,aAAa;AAAA,GAC3F;AACF;AAOO,SAAS,YAAA,CACd,UACA,OAAA,EACwB;AACxB,EAAA,KAAA,MAAW,IAAA,IAAQ,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA,EAAG;AACvC,IAAA,IAAI,wBAAA,CAAyB,KAAK,CAAC,MAAA,KAAW,KAAK,UAAA,CAAW,MAAM,CAAC,CAAA,EAAG;AACtE,MAAA,MAAM,IAAI,6BAAA;AAAA,QACR,CAAA,MAAA,EAAS,QAAA,CAAS,EAAE,CAAA,eAAA,EAAkB,IAAI,CAAA,8CAAA;AAAA,OAC5C;AAAA,IACF;AACA,IAAA,iBAAA,CAAkB,CAAA,aAAA,EAAgB,IAAI,CAAA,CAAA,CAAA,EAAK,IAAI,CAAA;AAAA,EACjD;AACA,EAAA,OAAO,MAAA,CAAO,WAAA,CAAY,MAAA,CAAO,OAAA,CAAQ,OAAO,CAAC,CAAA;AACnD;AAOO,SAAS,iBAAA,CAAkB,OAAe,KAAA,EAAqB;AACpE,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,UAAA,CAAW,KAAA,EAAO,MAAM,CAAA;AAC7C,EAAA,IAAI,QAAQ,wBAAA,EAA0B;AACpC,IAAA,MAAM,IAAI,sBAAA;AAAA,MACR,CAAA,EAAG,KAAK,CAAA,IAAA,EAAO,KAAK,mCAAmC,wBAAwB,CAAA,MAAA;AAAA,KACjF;AAAA,EACF;AACF;AAEA,SAAS,MAAA,CACP,MACA,KAAA,EAC8B;AAC9B,EAAA,OAAO,MAAA,CAAO,UAAA,CAAW,KAAA,EAAO,MAAM,CAAA,GAAI,wBAAA,GACtC,EAAC,GACA,EAAE,CAAC,IAAI,GAAG,KAAA,EAAM;AACvB;AAGO,SAAS,eAAe,OAAA,EAAqC;AAClE,EAAA,MAAM,EAAE,YAAW,GAAI,OAAA;AACvB,EAAA,MAAM,UAAA,GAAa,UAAA,CAAW,OAAA,IAAW,EAAC;AAC1C,EAAA,IAAI,UAAA,CAAW,CAAA,EAAG,gBAAgB,CAAA,WAAA,CAAa,MAAM,YAAA,EAAc;AACjE,IAAA,MAAM,IAAI,qBAAA;AAAA,MACR,CAAA,6BAAA,EAAgC,YAAY,CAAA,eAAA,EAAkB,gBAAgB,CAAA,YAAA;AAAA,KAChF;AAAA,EACF;AACA,EAAA,OAAO;AAAA,IACL,EAAA,EAAI,QAAA,CAAS,IAAA,EAAM,IAAA,CAAK,UAAA,CAAW,CAAA,EAAG,gBAAgB,CAAA,EAAA,CAAI,CAAC,CAAA,IAAK,IAAA,CAAK,UAAA,CAAW,SAAS,CAAC,CAAA;AAAA,IAC1F,IAAA,EAAM,QAAA,CAAS,MAAA,EAAQ,IAAA,CAAK,UAAA,CAAW,CAAA,EAAG,gBAAgB,CAAA,IAAA,CAAM,CAAC,CAAA,IAAK,IAAA,CAAK,UAAA,CAAW,IAAI,CAAC,CAAA;AAAA,IAC3F,MAAA,EAAQ,QAAA;AAAA,MACN,QAAA;AAAA,MACA,IAAA,CAAK,WAAW,CAAA,EAAG,gBAAgB,QAAQ,CAAC,CAAA,IAAK,IAAA,CAAK,UAAA,CAAW,KAAK;AAAA,KACxE;AAAA,IACA,KAAK,IAAA,CAAK,UAAA,CAAW,GAAG,gBAAgB,CAAA,OAAA,CAAS,CAAC,CAAA,IAAK,IAAA;AAAA,IACvD,OAAA,EAAS,YAAA,CAAa,OAAA,CAAQ,OAAO,CAAA;AAAA,IACrC,OAAA,EAAS,oBAAoB,UAAU,CAAA;AAAA,IACvC,aAAA,EACE,IAAA,CAAK,UAAA,CAAW,CAAA,EAAG,gBAAgB,CAAA,aAAA,CAAe,CAAC,CAAA,IACnD,IAAA,CAAK,UAAA,CAAW,aAAa,CAAA,IAC7B,IAAA;AAAA,IACF,aAAa,IAAA,CAAK,UAAA,CAAW,GAAG,gBAAgB,CAAA,WAAA,CAAa,CAAC,CAAA,IAAK,IAAA;AAAA,IACnE,UAAA,EAAY,UAAU,UAAA,CAAW,CAAA,EAAG,gBAAgB,CAAA,IAAA,CAAM,CAAA,EAAG,WAAW,SAAS;AAAA,GACnF;AACF;AAEA,SAAS,oBAAoB,UAAA,EAA6D;AACxF,EAAA,MAAM,UAAkC,EAAC;AACzC,EAAA,KAAA,MAAW,CAAC,IAAA,EAAM,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,UAAU,CAAA,EAAG;AACtD,IAAA,IAAI,KAAK,UAAA,CAAW,mBAAmB,CAAA,IAAK,OAAO,UAAU,QAAA,EAAU;AAErE,MAAA,MAAA,CAAO,eAAe,OAAA,EAAS,IAAA,CAAK,KAAA,CAAM,mBAAA,CAAoB,MAAM,CAAA,EAAG;AAAA,QACrE,KAAA;AAAA,QACA,UAAA,EAAY,IAAA;AAAA,QACZ,QAAA,EAAU,IAAA;AAAA,QACV,YAAA,EAAc;AAAA,OACf,CAAA;AAAA,IACH;AAAA,EACF;AACA,EAAA,OAAO,OAAA;AACT;AAEA,SAAS,aAAa,OAAA,EAA0B;AAC9C,EAAA,IAAI;AACF,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,OAAA,CAAQ,QAAA,CAAS,MAAM,CAAC,CAAA;AAAA,EAC5C,CAAA,CAAA,MAAQ;AACN,IAAA,MAAM,IAAI,sBAAsB,gCAAgC,CAAA;AAAA,EAClE;AACF;AAEA,SAAS,SAAA,CAAU,SAAkB,gBAAA,EAAiC;AACpE,EAAA,IAAI,YAAY,MAAA,EAAW;AACzB,IAAA,MAAM,QAAA,GACJ,OAAO,gBAAA,KAAqB,QAAA,GACxB,IAAI,IAAA,CAAK,gBAAA,GAAmB,uBAAuB,CAAA,GACnD,MAAA;AACN,IAAA,IAAI,aAAa,MAAA,IAAa,MAAA,CAAO,MAAM,QAAA,CAAS,OAAA,EAAS,CAAA,EAAG;AAC9D,MAAA,MAAM,IAAI,sBAAsB,qDAAqD,CAAA;AAAA,IACvF;AACA,IAAA,OAAO,QAAA;AAAA,EACT;AACA,EAAA,MAAM,UAAA,GACJ,OAAO,OAAA,KAAY,QAAA,IAAY,eAAA,CAAgB,IAAA,CAAK,OAAO,CAAA,GAAI,IAAI,IAAA,CAAK,OAAO,CAAA,GAAI,MAAA;AACrF,EAAA,IAAI,eAAe,MAAA,IAAa,MAAA,CAAO,MAAM,UAAA,CAAW,OAAA,EAAS,CAAA,EAAG;AAClE,IAAA,MAAM,IAAI,qBAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AACA,EAAA,OAAO,UAAA;AACT;AAEA,SAAS,KAAK,KAAA,EAAoC;AAChD,EAAA,OAAO,OAAO,KAAA,KAAU,QAAA,GAAW,KAAA,GAAQ,MAAA;AAC7C;AAEA,SAAS,QAAA,CAAS,WAAmB,KAAA,EAAmC;AACtE,EAAA,IAAI,KAAA,KAAU,MAAA,IAAa,KAAA,CAAM,MAAA,KAAW,CAAA,EAAG;AAC7C,IAAA,MAAM,IAAI,qBAAA;AAAA,MACR,CAAA,eAAA,EAAkB,SAAS,CAAA,SAAA,EAAY,gBAAgB,GAAG,SAAS,CAAA,CAAA;AAAA,KACrE;AAAA,EACF;AACA,EAAA,OAAO,KAAA;AACT;;;AC1QA,IAAMC,wBAAAA,GAA0B,GAAA;AAEhC,IAAM,EAAE,iBAAA,EAAmB,iBAAA,EAAmB,eAAA,EAAiB,yBAAA,EAA0B,GACvFC,gCAAA,CAAwB,CAAC,MAAA,KAAW,IAAI,qBAAA,CAAsB,MAAM,CAAC,CAAA;AAwEvE,IAAM,qBAAA,GAAwB,8BAAA;AAC9B,IAAM,aAAa,IAAI,WAAA,CAAY,SAAS,EAAE,KAAA,EAAO,MAAM,CAAA;AAC3D,IAAMC,aAAAA,GAAe,KAAA;AACrB,IAAM,mBAAA,GAAsB,yBAAA;AAE5B,IAAM,wBAAA,GAA2B,CAAC,aAAA,EAAe,gBAAA,EAAkB,eAAe,CAAA;AAElF,IAAM,qBAAA,uBAAiD,GAAA,CAAI;AAAA,EACzD,aAAA;AAAA,EACA,IAAA;AAAA,EACA,MAAA;AAAA,EACA,QAAA;AAAA,EACA,MAAA;AAAA,EACA,SAAA;AAAA,EACA,iBAAA;AAAA,EACA,YAAA;AAAA,EACA,MAAA;AAAA,EACA,aAAA;AAAA,EACA,eAAA;AAAA,EACA;AACF,CAAC,CAAA;AAiBM,SAAS,iBAAiB,OAAA,EAAqC;AACpE,EAAA,IAAIC,oBAAA,CAAY,OAAA,CAAQ,UAAA,CAAW,WAAW,MAAM,qBAAA,EAAuB;AACzE,IAAA,OAAO,eAAe,OAAO,CAAA;AAAA,EAC/B;AACA,EAAA,MAAM,IAAA,GAAO,aAAA,CAAc,OAAA,CAAQ,OAAO,CAAA;AAC1C,EAAA,IAAI,CAACC,qBAAA,CAAa,IAAI,CAAA,EAAG;AACvB,IAAA,MAAM,IAAI,sBAAsB,+CAA+C,CAAA;AAAA,EACjF;AACA,EAAA,IAAI,IAAA,CAAK,aAAa,CAAA,KAAMF,aAAAA,EAAc;AACxC,IAAA,MAAM,IAAI,qBAAA,CAAsB,CAAA,qBAAA,EAAwBA,aAAY,CAAA,CAAA,CAAG,CAAA;AAAA,EACzE;AACA,EAAA,MAAM,IAAA,GAAO,iBAAA,CAAkB,IAAA,EAAM,MAAM,CAAA;AAC3C,EAAA,eAAA,CAAgB,MAAM,MAAM,CAAA;AAC5B,EAAA,yBAAA,CAA0B,iBAAA,CAAkB,IAAA,EAAM,iBAAiB,CAAC,CAAA;AACpE,EAAA,IAAI,MAAA,CAAO,MAAA,CAAO,IAAA,EAAM,aAAa,CAAA,EAAG;AACtC,IAAA,MAAM,IAAI,qBAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AACA,EAAA,MAAM,IAAA,GAAO,iBAAA,CAAkB,IAAA,EAAM,MAAM,CAAA;AAC3C,EAAA,OAAO;AAAA,IACL,EAAA,EAAI,iBAAA,CAAkB,IAAA,EAAM,IAAI,CAAA;AAAA,IAChC,IAAA;AAAA,IACA,MAAA,EAAQ,iBAAA,CAAkB,IAAA,EAAM,QAAQ,CAAA;AAAA,IACxC,GAAA,EAAK,iBAAA,CAAkB,IAAA,EAAM,SAAS,CAAA,IAAK,IAAA;AAAA,IAC3C,OAAA,EAAS,OAAO,MAAA,CAAO,IAAA,EAAM,MAAM,CAAA,GAAI,IAAA,CAAK,MAAM,CAAA,GAAI,IAAA;AAAA,IACtD,OAAA,EAAS,EAAE,GAAG,kBAAA,CAAmB,OAAA,CAAQ,UAAU,CAAA,EAAG,GAAG,mBAAA,CAAoB,IAAI,CAAA,EAAE;AAAA,IACnF,aAAA,EAAe,iBAAA,CAAkB,IAAA,EAAM,eAAe,CAAA,IAAK,IAAA;AAAA,IAC3D,WAAA,EAAa,iBAAA,CAAkB,IAAA,EAAM,aAAa,CAAA,IAAK,IAAA;AAAA,IACvD,UAAA,EAAY,SAAS,MAAA,GAAY,iBAAA,CAAkB,QAAQ,UAAU,CAAA,GAAIG,WAAU,IAAI;AAAA,GACzF;AACF;AAyBO,SAAS,iBAAiB,OAAA,EAA0D;AACzF,EAAA,IAAI,OAAO,OAAA,CAAQ,IAAA,KAAS,QAAA,EAAU;AACpC,IAAAC,oBAAA,CAAgB,QAAQ,IAAI,CAAA;AAAA,EAC9B;AACA,EAAA,OAAO,CAAC,OAAA,KAAY;AAClB,IAAA,MAAM,EAAE,YAAW,GAAI,OAAA;AACvB,IAAA,IACE,UAAA,CAAW,UAAU,mBAAmB,CAAA,KAAM,UAC9CH,oBAAA,CAAY,UAAA,CAAW,WAAW,CAAA,KAAM,qBAAA,EACxC;AACA,MAAA,OAAO,iBAAiB,OAAO,CAAA;AAAA,IACjC;AACA,IAAA,MAAM,KAAA,GAAQ,eAAe,OAAO,CAAA;AACpC,IAAA,MAAM,IAAA,GAAO,gBAAgB,IAAA,CAAK,OAAA,CAAQ,MAAM,EAAE,KAAA,EAAO,IAAA,EAAM,MAAA,EAAQ,CAAA;AACvE,IAAA,IAAI,SAAS,MAAA,EAAW;AACtB,MAAA,MAAM,IAAI,sBAAsB,uDAAuD,CAAA;AAAA,IACzF;AACA,IAAA,eAAA,CAAgB,MAAM,gBAAgB,CAAA;AACtC,IAAA,MAAM,EAAA,GACJ,eAAA,CAAgB,IAAA,CAAK,OAAA,CAAQ,EAAA,EAAI,EAAE,KAAA,EAAO,IAAA,EAAM,IAAA,EAAM,CAAA,IAAK,YAAA,CAAa,WAAW,SAAS,CAAA;AAC9F,IAAA,IAAI,OAAO,MAAA,EAAW;AACpB,MAAA,MAAM,IAAI,qBAAA;AAAA,QACR;AAAA,OACF;AAAA,IACF;AACA,IAAA,OAAO;AAAA,MACL,EAAA;AAAA,MACA,IAAA;AAAA,MACA,MAAA,EACE,eAAA,CAAgB,IAAA,CAAK,OAAA,CAAQ,MAAA,EAAQ,EAAE,KAAA,EAAO,IAAA,EAAM,QAAA,EAAU,CAAA,IAAK,aAAA,CAAc,OAAO,CAAA;AAAA,MAC1F,GAAA,EAAK,eAAA,CAAgB,IAAA,CAAK,OAAA,CAAQ,GAAA,EAAK,EAAE,KAAA,EAAO,IAAA,EAAM,KAAA,EAAO,CAAA,IAAK,IAAA;AAAA,MAClE,SAAS,KAAA,CAAM,OAAA;AAAA,MACf,SAAS,KAAA,CAAM,OAAA;AAAA,MACf,aAAA,EAAe,IAAA;AAAA,MACf,WAAA,EAAa,IAAA;AAAA,MACb,UAAA,EAAY,iBAAA,CAAkB,OAAA,CAAQ,UAAA,EAAY,KAAK;AAAA,KACzD;AAAA,EACF,CAAA;AACF;AAGA,SAAS,eAAe,OAAA,EAAwC;AAC9D,EAAA,MAAM,EAAE,YAAW,GAAI,OAAA;AACvB,EAAA,OAAO;AAAA,IACL,UAAA,EAAY,QAAQ,MAAA,CAAO,UAAA;AAAA,IAC3B,UAAA;AAAA,IACA,OAAA,EAAS,mBAAmB,UAAU,CAAA;AAAA,IACtC,OAAA,EAAS,aAAA,CAAc,OAAA,CAAQ,OAAO;AAAA,GACxC;AACF;AAGA,IAAM,qBAAA,GAAN,cAAoCI,2BAAA,CAAkD;AAAA,EACpF,QAAQ,MAAA,EAAuB;AAC7B,IAAA,OAAO,IAAI,sBAAsB,MAAM,CAAA;AAAA,EACzC;AAAA,EAEU,cAAc,OAAA,EAA8B;AACpD,IAAA,OAAO,cAAc,OAAO,CAAA;AAAA,EAC9B;AAAA;AAAA,EAGU,UAAA,GAAmB;AAC3B,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA,EAGU,YAAY,OAAA,EAA4B;AAChD,IAAA,OAAO,iBAAA,CAAkB,QAAQ,UAAU,CAAA;AAAA,EAC7C;AACF,CAAA;AAEA,IAAM,eAAA,GAAkB,IAAI,qBAAA,EAAsB;AAM3C,SAAS,oBAAA,CAAqB,SAAkB,OAAA,EAAqC;AAC1F,EAAA,OAAO,eAAA,CAAgB,QAAA,CAAS,OAAA,EAAS,OAAO,CAAA;AAClD;AAGO,SAAS,cAAc,OAAA,EAA0B;AACtD,EAAA,IAAIC,KAAAA;AACJ,EAAA,IAAI;AACF,IAAAA,KAAAA,GAAO,UAAA,CAAW,MAAA,CAAO,OAAO,CAAA;AAAA,EAClC,CAAA,CAAA,MAAQ;AACN,IAAA,MAAM,IAAI,sBAAsB,iCAAiC,CAAA;AAAA,EACnE;AACA,EAAA,IAAI;AACF,IAAA,OAAO,IAAA,CAAK,MAAMA,KAAI,CAAA;AAAA,EACxB,CAAA,CAAA,MAAQ;AACN,IAAA,MAAM,IAAI,sBAAsB,gCAAgC,CAAA;AAAA,EAClE;AACF;AAEO,SAAS,aAAa,KAAA,EAAoC;AAC/D,EAAA,OAAO,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,CAAM,MAAA,GAAS,IAAI,KAAA,GAAQ,MAAA;AACjE;AAEA,SAAS,cAAc,OAAA,EAA8B;AACnD,EAAA,OAAO,aAAa,OAAA,CAAQ,UAAA,CAAW,KAAK,CAAA,IAAK,QAAQ,MAAA,CAAO,UAAA;AAClE;AAEA,SAASH,WAAUG,KAAAA,EAAoB;AACrC,EAAA,MAAM,IAAA,GAAO,IAAI,IAAA,CAAKA,KAAI,CAAA;AAC1B,EAAA,IAAI,CAAC,eAAA,CAAgB,IAAA,CAAKA,KAAI,CAAA,IAAK,OAAO,KAAA,CAAM,IAAA,CAAK,OAAA,EAAS,CAAA,EAAG;AAC/D,IAAA,MAAM,IAAI,qBAAA,CAAsB,CAAA,oCAAA,EAAuCA,KAAI,CAAA,CAAA,CAAG,CAAA;AAAA,EAChF;AACA,EAAA,OAAO,IAAA;AACT;AAGA,SAAS,kBAAkB,UAAA,EAAyC;AAClE,EAAA,MAAM,EAAE,WAAU,GAAI,UAAA;AACtB,EAAA,OAAO,OAAO,SAAA,KAAc,QAAA,IAAY,MAAA,CAAO,QAAA,CAAS,SAAS,CAAA,GAC7D,IAAI,IAAA,CAAK,SAAA,GAAYR,wBAAuB,CAAA,uBACxC,IAAA,EAAK;AACf;AAEA,SAAS,oBAAoB,IAAA,EAAuD;AAClF,EAAA,OAAO,MAAA,CAAO,WAAA;AAAA,IACZ,MAAA,CAAO,OAAA,CAAQ,IAAI,CAAA,CAAE,MAAA;AAAA,MACnB,CAAC,KAAA,KACC,CAAC,qBAAA,CAAsB,GAAA,CAAI,KAAA,CAAM,CAAC,CAAC,CAAA,IAAK,OAAO,KAAA,CAAM,CAAC,CAAA,KAAM;AAAA;AAChE,GACF;AACF;AAEO,SAAS,mBAAmB,UAAA,EAA2D;AAC5F,EAAA,OAAO,MAAA,CAAO,WAAA;AAAA,IACZ,OAAO,OAAA,CAAQ,UAAA,CAAW,OAAA,IAAW,EAAE,CAAA,CAAE,MAAA;AAAA,MACvC,CAAC,KAAA,KACC,OAAO,KAAA,CAAM,CAAC,MAAM,QAAA,IACpB,CAAC,wBAAA,CAAyB,IAAA,CAAK,CAAC,MAAA,KAAW,KAAA,CAAM,CAAC,CAAA,CAAE,UAAA,CAAW,MAAM,CAAC;AAAA;AAC1E,GACF;AACF;AAEA,SAAS,iBAAA,CACP,QACA,OAAA,EACM;AACN,EAAA,MAAM,KAAA,GAAiB,SAAS,OAAO,CAAA;AACvC,EAAA,IAAI,UAAU,MAAA,EAAW;AACvB,IAAA,OAAO,iBAAA,CAAkB,QAAQ,UAAU,CAAA;AAAA,EAC7C;AACA,EAAA,IAAI,EAAE,iBAAiB,IAAA,CAAA,IAAS,MAAA,CAAO,MAAM,KAAA,CAAM,OAAA,EAAS,CAAA,EAAG;AAC7D,IAAAS,yBAAA,CAAiB,KAAK,CAAA;AACtB,IAAA,MAAM,IAAI,sBAAsB,8CAA8C,CAAA;AAAA,EAChF;AACA,EAAA,OAAO,KAAA;AACT;;;AChSO,IAAM,iBAAA,GAAmC,OAAO,MAAA,CAAO;AAAA,EAC5D,MAAA,EAAQ,cAAA;AAAA,EACR,MAAA,EAAQ;AACV,CAAC;AASM,IAAM,qBAAA,GAAuC,OAAO,MAAA,CAAO;AAAA,EAChE,MAAA,EAAQ,wBAAA;AAAA,EACR,MAAA,EAAQ;AACV,CAAC;AAUD,IAAM,mBAAA,GAAsB,qBAAA;AAC5B,IAAM,oBAAA,GAAuB,kBAAA;AAuBtB,SAAS,aAAa,OAAA,EAAqD;AAChF,EAAA,MAAM,MAAA,GAASC,kCAAyB,OAAA,EAAS;AAAA,IAC/C,YAAA,EAAc,CAAC,mBAAmB,CAAA;AAAA,IAClC,QAAA,EAAU;AAAA,MACR,OAAA,EAAS,CAAC,MAAA,KAAW,IAAI,sBAAsB,MAAM,CAAA;AAAA,MACrD,WAAA,EAAa,CAAC,MAAA,KAAW,IAAI,8BAA8B,MAAM;AAAA;AACnE,GACD,CAAA;AACD,EAAA,MAAM,WAAA,GAAc,QAAQ,WAAA,IAAe,oBAAA;AAC3C,EAAA,OAAO;AAAA,IACL,MAAA,EAAQ,CAAC,QAAA,KAAa;AACpB,MAAA,iBAAA,CAAkB,QAAA,CAAS,OAAA,EAAS,QAAA,CAAS,EAAE,CAAA;AAC/C,MAAA,iBAAA,CAAkB,UAAA,EAAY,SAAS,EAAE,CAAA;AACzC,MAAA,MAAM,EAAE,IAAA,EAAM,OAAA,EAAQ,GAAI,MAAA,CAAO,MAAM,QAAQ,CAAA;AAC/C,MAAA,OAAO;AAAA,QACL,SAAS,MAAA,CAAO,IAAA,CAAK,KAAK,SAAA,CAAU,IAAI,GAAG,MAAM,CAAA;AAAA,QACjD,OAAA,EAAS;AAAA,UACP,GAAG,kBAAkB,QAAQ,CAAA;AAAA,UAC7B,WAAA;AAAA,UACA,OAAA,EAAS,YAAA,CAAa,QAAA,EAAU,OAAO;AAAA;AACzC,OACF;AAAA,IACF,CAAA;AAAA,IACA,MAAA,EAAQ,CAAC,OAAA,KAAY;AACnB,MAAA,MAAM,MAAA,GAAS,OAAO,IAAA,CAAK;AAAA,QACzB,IAAA,EAAM,aAAA,CAAc,OAAA,CAAQ,OAAO,CAAA;AAAA,QACnC,OAAA,EAAS,kBAAA,CAAmB,OAAA,CAAQ,UAAU;AAAA,OAC/C,CAAA;AACD,MAAA,OAAO,EAAE,GAAG,MAAA,EAAQ,EAAA,EAAI,OAAO,EAAA,IAAM,gBAAA,CAAiB,OAAO,CAAA,EAAE;AAAA,IACjE;AAAA,GACF;AACF;AAEA,SAAS,iBAAiB,OAAA,EAA8B;AACtD,EAAA,MAAM,EAAA,GAAK,YAAA,CAAa,OAAA,CAAQ,UAAA,CAAW,SAAS,CAAA;AACpD,EAAA,IAAI,OAAO,MAAA,EAAW;AACpB,IAAA,MAAM,IAAI,sBAAsB,sDAAsD,CAAA;AAAA,EACxF;AACA,EAAA,OAAO,EAAA;AACT;AAOO,SAAS,qBAAA,CAAsB,OAAsB,OAAA,EAAqC;AAC/F,EAAA,IAAI,UAAU,iBAAA,EAAmB;AAC/B,IAAA,OAAO,eAAe,OAAO,CAAA;AAAA,EAC/B;AACA,EAAA,OAAO,oBAAA,CAAqB,KAAA,CAAM,MAAA,CAAO,OAAO,GAAG,OAAO,CAAA;AAC5D;AC9IO,IAAM,mBAAA,GAAsB,yBAAA;AAE5B,IAAM,oBAAA,GAAuB,6BAAA;AAE7B,IAAM,yBAAA,GAA4B,+BAAA;AAElC,IAAM,6BAAA,GAAgC,mCAAA;AAEtC,IAAM,6BAAA,GAAgC,mCAAA;AAMtC,IAAM,2BAAA,GAA8B,wBAAA;AAE3C,IAAM,sBAAA,GAA4C,CAAC,mBAAA,EAAqB,oBAAoB,CAAA;AAE5F,IAAM,sBAAA,GAA4C,CAAC,kBAAA,EAAoB,kBAAkB,CAAA;AACzF,IAAM,oBAAA,GAAuB,EAAA;AAUtB,SAAS,iBAAiB,MAAA,EAAwC;AACvE,EAAA,IAAI,MAAA,CAAO,iBAAiB,CAAA,EAAG;AAC7B,IAAA,MAAM,IAAIC,wBAAmB,8CAA8C,CAAA;AAAA,EAC7E;AACA,EAAA,MAAM,QAAkB,EAAC;AACzB,EAAA,IAAI,QAAQ,MAAA,CAAO,cAAA;AACnB,EAAA,WAAS;AACP,IAAA,MAAM,IAAA,GAAO,KAAK,KAAA,CAAM,IAAA,CAAK,IAAI,KAAA,EAAO,MAAA,CAAO,UAAU,CAAC,CAAA;AAC1D,IAAA,KAAA,CAAM,KAAK,IAAI,CAAA;AACf,IAAA,IAAI,IAAA,IAAQ,MAAA,CAAO,UAAA,IAAc,MAAA,CAAO,WAAW,CAAA,EAAG;AACpD,MAAA,OAAO,KAAA;AAAA,IACT;AACA,IAAA,IAAI,KAAA,CAAM,WAAW,oBAAA,EAAsB;AACzC,MAAA,MAAM,IAAIA,uBAAA;AAAA,QACR,8BAA8B,oBAAoB,CAAA,mEAAA;AAAA,OACpD;AAAA,IACF;AACA,IAAA,KAAA,IAAS,MAAA,CAAO,MAAA;AAAA,EAClB;AACF;AAOO,SAAS,eAAA,CACd,MAAA,EACA,EAAE,OAAA,EAAS,QAAO,EACV;AACR,EAAA,MAAM,aAAa,MAAA,CAAO,SAAA,CAAU,CAAC,IAAA,KAAS,QAAQ,OAAO,CAAA;AAC7D,EAAA,IAAI,eAAe,EAAA,EAAI;AACrB,IAAA,OAAO,MAAA,CAAO,GAAG,EAAE,CAAA;AAAA,EACrB;AACA,EAAA,IAAI,eAAe,CAAA,EAAG;AACpB,IAAA,OAAO,OAAO,CAAC,CAAA;AAAA,EACjB;AACA,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,UAAA,GAAa,CAAC,CAAA;AACnC,EAAA,MAAM,KAAA,GAAQ,OAAO,UAAU,CAAA;AAC/B,EAAA,OAAO,QAAO,GAAA,CAAK,OAAA,GAAU,KAAA,KAAU,KAAA,GAAQ,SAAS,KAAA,GAAQ,KAAA;AAClE;AAGO,SAAS,iBAAA,CAAkB,SAAsB,IAAA,EAAkC;AAExF,EAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,UAAA,CAAW,OAAA,GAAU,IAAI,CAAA;AAC/C,EAAA,MAAM,MAAA,GAAS,OAAO,KAAA,KAAU,QAAA,IAAY,OAAA,CAAQ,KAAK,KAAK,CAAA,GAAI,MAAA,CAAO,KAAK,CAAA,GAAI,KAAA;AAClF,EAAA,OAAO,OAAO,WAAW,QAAA,IAAY,MAAA,CAAO,cAAc,MAAM,CAAA,IAAK,MAAA,IAAU,CAAA,GAC3E,MAAA,GACA,MAAA;AACN;AAOO,SAAS,gBAAA,CACd,SACA,aAAA,EACkD;AAClD,EAAA,MAAM,EAAE,YAAW,GAAI,OAAA;AACvB,EAAA,MAAM,OAAA,GAAmC,EAAE,GAAG,UAAA,CAAW,OAAA,EAAQ;AACjE,EAAA,KAAA,MAAW,IAAA,IAAQ;AAAA,IACjB,GAAG,sBAAA;AAAA,IACH,yBAAA;AAAA,IACA,6BAAA;AAAA,IACA,6BAAA;AAAA,IACA,GAAG;AAAA,GACL,EAAG;AACD,IAAA,OAAO,QAAQ,IAAI,CAAA;AAAA,EACrB;AACA,EAAA,MAAA,CAAO,MAAA,CAAO,SAAS,aAAa,CAAA;AACpC,EAAA,OAAO;AAAA,IACL,SAAS,OAAA,CAAQ,OAAA;AAAA,IACjB,OAAA,EAAS;AAAA,MACP,aACE,OAAO,UAAA,CAAW,WAAA,KAAgB,QAAA,GAAW,WAAW,WAAA,GAAc,kBAAA;AAAA,MACxE,UAAA,EAAY,IAAA;AAAA,MACZ,GAAI,OAAO,UAAA,CAAW,SAAA,KAAc,QAAA,GAAW,EAAE,SAAA,EAAW,UAAA,CAAW,SAAA,EAAU,GAAI,EAAC;AAAA,MACtF,GAAI,OAAO,UAAA,CAAW,IAAA,KAAS,QAAA,GAAW,EAAE,IAAA,EAAM,UAAA,CAAW,IAAA,EAAK,GAAI,EAAC;AAAA,MACvE,GAAI,OAAO,UAAA,CAAW,KAAA,KAAU,QAAA,GAAW,EAAE,KAAA,EAAO,UAAA,CAAW,KAAA,EAAM,GAAI,EAAC;AAAA,MAC1E,GAAI,OAAO,UAAA,CAAW,aAAA,KAAkB,QAAA,GACpC,EAAE,aAAA,EAAe,UAAA,CAAW,aAAA,EAAc,GAC1C,EAAC;AAAA,MACL,GAAI,OAAO,UAAA,CAAW,SAAA,KAAc,QAAA,GAAW,EAAE,SAAA,EAAW,UAAA,CAAW,SAAA,EAAU,GAAI,EAAC;AAAA,MACtF;AAAA;AACF,GACF;AACF;AAGO,SAAS,mBAAmB,OAAA,EAA8B;AAC/D,EAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,UAAA,CAAW,OAAA,GAAU,2BAA2B,CAAA;AACzE,EAAA,OAAO,OAAO,QAAA,KAAa,QAAA,GAAW,QAAA,GAAW,QAAQ,MAAA,CAAO,UAAA;AAClE;AAGO,SAAS,uBAAuB,OAAA,EAAmC;AACxE,EAAA,MAAM,UAAA,GAAa,mBAAmB,OAAO,CAAA;AAC7C,EAAA,OAAO,UAAA,KAAe,OAAA,CAAQ,MAAA,CAAO,UAAA,GACjC,UACA,EAAE,GAAG,OAAA,EAAS,MAAA,EAAQ,EAAE,GAAG,OAAA,CAAQ,MAAA,EAAQ,YAAW,EAAE;AAC9D;;;AC4DA,IAAM,gBAAA,GAAmB,EAAA;AAEzB,IAAM,sBAAA,GAAyB,EAAA;AAE/B,IAAM,qBAAA,GAAqC;AAAA,EACzC,QAAA,EAAU,CAAA;AAAA,EACV,cAAA,EAAgB,GAAA;AAAA,EAChB,MAAA,EAAQ,CAAA;AAAA,EACR,UAAA,EAAY,GAAA;AAAA,EACZ,MAAA,EAAQ,OAAA;AAAA,EACR,OAAA,EAAS;AACX,CAAA;AAEA,IAAM,kBAAA,GAAkC;AAAA,EACtC,UAAU,MAAA,CAAO,iBAAA;AAAA,EACjB,cAAA,EAAgB,GAAA;AAAA,EAChB,MAAA,EAAQ,CAAA;AAAA,EACR,UAAA,EAAY,GAAA;AAAA,EACZ,MAAA,EAAQ,OAAA;AAAA,EACR,OAAA,EAAS;AACX,CAAA;AAEA,IAAM,0BAAA,GAA6B,IAAA;AAEnC,IAAM,iBAAA,GAAiC;AAAA,EACrC,QAAA,EAAU,CAAA;AAAA,EACV,cAAA,EAAgB,GAAA;AAAA,EAChB,MAAA,EAAQ,CAAA;AAAA,EACR,UAAA,EAAY,GAAA;AAAA,EACZ,MAAA,EAAQ,OAAA;AAAA,EACR,OAAA,EAAS;AACX,CAAA;AAGO,SAAS,gBAAgB,OAAA,EAA8D;AAC5F,EAAA,MAAM,MAAA,GAAS,cAAc,OAAO,CAAA;AACpC,EAAA,OAAO;AAAA,IACL,GAAG,eAAA,CAAgB,OAAA,EAAS,MAAM,CAAA;AAAA,IAClC,GAAG,cAAA,CAAe,OAAA,EAAS,MAAM,CAAA;AAAA,IACjC,GAAG,cAAA,CAAe,OAAA,EAAS,MAAM;AAAA,GACnC;AACF;AAQA,SAAS,cAAc,OAAA,EAAkD;AACvE,EAAA,MAAM,WAAWC,qBAAA,CAAa,EAAA,CAAG,OAAA,CAAQ,QAAA,IAAY,YAAY,UAAU,CAAA;AAC3E,EAAA,MAAM,kBAAA,GAAqB,QAAQ,kBAAA,IAAsB,IAAA;AACzD,EAAA,IAAI,CAAC,kBAAA,IAAsB,OAAA,CAAQ,SAAA,KAAc,KAAA,EAAO;AACtD,IAAA,MAAM,IAAID,uBAAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AACA,EAAA,MAAM,OAAA,GAAU,QAAQ,OAAA,IAAW,KAAA;AACnC,EAAA,MAAM,WAAWE,wBAAA,CAAgB,EAAA;AAAA,IAC/B,OAAA,CAAQ,QAAA,KAAa,OAAA,GAAU,CAAA,GAAI,gBAAA,CAAA;AAAA,IACnC;AAAA,GACF;AACA,EAAA,IAAI,OAAA,IAAW,aAAa,CAAA,EAAG;AAC7B,IAAA,MAAM,IAAIF,uBAAAA,CAAmB,CAAA,+CAAA,EAAkD,QAAQ,CAAA,CAAE,CAAA;AAAA,EAC3F;AACA,EAAA,MAAM,UAAA,GAAaG,sBAAA,CAAkB,OAAA,CAAQ,UAAA,EAAY,kBAAkB,CAAA;AAC3E,EAAA,OAAO,EAAE,QAAA,EAAU,kBAAA,EAAoB,OAAA,EAAS,UAAU,UAAA,EAAW;AACvE;AAGA,SAAS,eAAA,CACP,OAAA,EACA,EAAE,QAAA,EAAU,UAAS,EAarB;AACA,EAAA,OAAO;AAAA,IACL,MAAMF,qBAAA,CAAa,EAAA,CAAG,OAAA,CAAQ,IAAA,IAAQ,YAAY,MAAM,CAAA;AAAA,IACxD,OAAA,EAAS,eAAe,OAAO,CAAA;AAAA,IAC/B,QAAA;AAAA,IACA,QAAA;AAAA,IACA,aAAaA,qBAAA,CAAa,EAAA,CAAG,OAAA,CAAQ,WAAA,IAAe,YAAY,aAAa,CAAA;AAAA,IAC7E,aAAA,EAAeA,qBAAA,CAAa,QAAA,CAAS,OAAA,CAAQ,eAAe,eAAe,CAAA;AAAA,IAC3E,KAAA,EAAOA,qBAAA,CAAa,QAAA,CAAS,OAAA,CAAQ,OAAO,OAAO,CAAA;AAAA,IACnD,oBAAoBA,qBAAA,CAAa,EAAA;AAAA,MAC/B,OAAA,CAAQ,kBAAA,IAAsB,CAAA,EAAG,QAAQ,CAAA,KAAA,CAAA;AAAA,MACzC;AAAA,KACF;AAAA,IACA,eAAA,EAAiBA,qBAAA,CAAa,QAAA,CAAS,OAAA,CAAQ,iBAAiB,iBAAiB,CAAA;AAAA,IACjF,eAAeC,wBAAA,CAAgB,EAAA;AAAA,MAC7B,QAAQ,aAAA,IAAiB,sBAAA;AAAA,MACzB;AAAA;AACF,GACF;AACF;AAGA,SAAS,cAAA,CACP,OAAA,EACA,EAAE,OAAA,EAAS,YAAW,EAItB;AACA,EAAA,OAAO;AAAA,IACL,YAAA,EAAcC,sBAAA,CAAkB,OAAA,CAAQ,YAAA,EAAc,qBAAqB,CAAA;AAAA,IAC3E,UAAA;AAAA,IACA,WAAA,EAAa,OAAA,GAAU,EAAC,GAAI,iBAAiB,UAAU,CAAA;AAAA,IACvD,oBAAoBC,qBAAA,CAAa,QAAA;AAAA,MAC/B,OAAA,CAAQ,YAAY,MAAA,IAAU,0BAAA;AAAA,MAC9B;AAAA,KACF;AAAA,IACA;AAAA,GACF;AACF;AAGA,SAAS,cAAA,CACP,OAAA,EACA,EAAE,kBAAA,EAAmB,EAYrB;AACA,EAAA,OAAO;AAAA,IACL,SAAA,EAAW,gBAAA,CAAiB,OAAA,CAAQ,SAAS,CAAA;AAAA,IAC7C,kBAAA;AAAA,IACA,eAAA,EAAiB,QAAQ,eAAA,IAAmB,KAAA;AAAA,IAC5C,kBAAkBA,qBAAA,CAAa,QAAA,CAAS,OAAA,CAAQ,cAAA,IAAkB,OAAO,gBAAgB,CAAA;AAAA,IACzF,mBAAmBA,qBAAA,CAAa,EAAA,CAAG,OAAA,CAAQ,eAAA,IAAmB,OAAO,iBAAiB,CAAA;AAAA,IACtF,GAAG,aAAa,OAAO,CAAA;AAAA,IACvB,MAAA,EAAQ,QAAQ,MAAA,IAAU,OAAA;AAAA,IAC1B,MAAA,EAAQ,OAAA,CAAQ,MAAA,IAAU,IAAA,CAAK;AAAA,GACjC;AACF;AAGO,SAAS,iBAAiB,QAAA,EAA6C;AAC5E,EAAA,IAAI,QAAA,CAAS,UAAU,MAAA,EAAW;AAChC,IAAA,OAAO,QAAA,CAAS,KAAA;AAAA,EAClB;AACA,EAAA,IAAI,QAAA,CAAS,kBAAkB,MAAA,EAAW;AACxC,IAAA,MAAM,IAAIJ,uBAAAA;AAAA,MACR,CAAA,WAAA,EAAc,SAAS,IAAI,CAAA,+CAAA;AAAA,KAC7B;AAAA,EACF;AACA,EAAA,OAAO,CAAA,EAAG,QAAA,CAAS,WAAW,CAAA,CAAA,EAAI,SAAS,aAAa,CAAA,CAAA;AAC1D;AAGA,SAAS,YAAA,CAAa;AAAA,EACpB,KAAA;AAAA,EACA;AACF,CAAA,EAAmF;AACjF,EAAA,IAAI,MAAA,KAAW,MAAA,IAAa,KAAA,KAAU,MAAA,EAAW;AAC/C,IAAA,MAAM,IAAIA,wBAAmB,mDAAmD,CAAA;AAAA,EAClF;AACA,EAAA,MAAM,MAAA,GACJ,WAAW,MAAA,GAAa,KAAA,IAAS,oBAAqB,EAAE,MAAA,EAAQ,gBAAgB,MAAA,EAAO;AACzF,EAAA,IAAI,WAAW,iBAAA,EAAmB;AAChC,IAAA,OAAO,EAAE,MAAA,EAAQ,cAAA,EAAgB,MAAA,EAAQ,cAAA,EAAe;AAAA,EAC1D;AACA,EAAA,OAAO;AAAA,IACL,QAAQ,MAAA,CAAO,MAAA;AAAA,IACf,MAAA,EAAQ,CAAC,OAAA,KAAY,qBAAA,CAAsB,QAAQ,OAAO;AAAA,GAC5D;AACF;AAEA,SAAS,eACP,OAAA,EACsD;AACtD,EAAA,MAAM,EAAE,GAAA,EAAK,OAAA,EAAQ,GAAI,OAAA;AACzB,EAAA,IAAK,GAAA,KAAQ,MAAA,MAAgB,OAAA,KAAY,MAAA,CAAA,EAAY;AACnD,IAAA,MAAM,IAAIA,wBAAmB,yCAAyC,CAAA;AAAA,EACxE;AACA,EAAA,IAAI,YAAY,MAAA,EAAW;AACzB,IAAA,OAAO,OAAA;AAAA,EACT;AACA,EAAA,OAAO,OAAO,EAAE,MAAA,EAAO,KAAM;AAC3B,IAAA,MAAM,OAAA,GAAU,MAAM,OAAO,SAAS,CAAA;AAEtC,IAAA,MAAM,aAAA,GAAgB,EAAE,MAAA,EAAO;AAC/B,IAAA,OAAO,OAAA,CAAQ,OAAA,CAAQ,GAAA,EAAM,aAAa,CAAA;AAAA,EAC5C,CAAA;AACF;AAEA,SAAS,iBACP,SAAA,EACyB;AACzB,EAAA,IAAI,cAAc,KAAA,EAAO;AACvB,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,OAAOG,uBAAkB,EAAE,GAAG,WAAW,QAAA,EAAU,CAAA,IAAK,iBAAiB,CAAA;AAC3E;;;ACrYO,SAAS,cAAA,CAAe,OAAe,OAAA,EAAyB;AACrE,EAAA,OAAO,CAAA,EAAG,KAAK,CAAA,OAAA,EAAU,OAAO,CAAA,CAAA;AAClC;AAGA,eAAsB,cAAA,CAAe,SAAsB,QAAA,EAAiC;AAC1F,EAAA,MAAM,QAAQ,cAAA,CAAe,QAAA,EAAU,SAAS,EAAE,OAAA,EAAS,MAAM,CAAA;AACnE;AAkBA,eAAsB,sBAAA,CACpB,SACA,QAAA,EACe;AACf,EAAA,MAAM,cAAA,CAAe,OAAA,EAAS,QAAA,CAAS,QAAQ,CAAA;AAC/C,EAAA,MAAM,OAAA,CAAQ,eAAe,QAAA,CAAS,kBAAA,EAAoB,UAAU,EAAE,OAAA,EAAS,MAAM,CAAA;AACrF,EAAA,MAAM,OAAA,CAAQ,WAAA,CAAY,QAAA,CAAS,eAAA,EAAiB;AAAA,IAClD,OAAA,EAAS,IAAA;AAAA,IACT,SAAA,EAAW,EAAE,cAAA,EAAgB,QAAA;AAAS,GACvC,CAAA;AACD,EAAA,MAAM,QAAQ,SAAA,CAAU,QAAA,CAAS,iBAAiB,QAAA,CAAS,kBAAA,EAAoB,SAAS,KAAK,CAAA;AAC7F,EAAA,KAAA,MAAW,OAAA,IAAW,SAAS,aAAA,EAAe;AAC5C,IAAA,MAAM,QAAQ,WAAA,CAAY,cAAA,CAAe,QAAA,CAAS,KAAA,EAAO,OAAO,CAAA,EAAG;AAAA,MACjE,OAAA,EAAS,IAAA;AAAA,MACT,SAAA,EAAW;AAAA,QACT,cAAA,EAAgB,QAAA;AAAA,QAChB,eAAA,EAAiB,OAAA;AAAA,QACjB,wBAAA,EAA0B,EAAA;AAAA,QAC1B,6BAA6B,QAAA,CAAS,KAAA;AAAA,QACtC,wBAAA,EAA0B,eAAA;AAAA,QAC1B,YAAA,EAAc;AAAA;AAChB,KACD,CAAA;AAAA,EACH;AACA,EAAA,MAAM,OAAA,CAAQ,WAAA,CAAY,QAAA,CAAS,KAAA,EAAO;AAAA,IACxC,OAAA,EAAS,IAAA;AAAA,IACT,SAAA,EAAW;AAAA,MACT,cAAA,EAAgB,QAAA;AAAA,MAChB,oBAAoB,QAAA,CAAS,aAAA;AAAA,MAC7B,0BAA0B,QAAA,CAAS,kBAAA;AAAA,MACnC,6BAA6B,QAAA,CAAS,KAAA;AAAA,MACtC,wBAAA,EAA0B,eAAA;AAAA,MAC1B,YAAA,EAAc,gBAAA;AAAA,MACd,GAAI,QAAA,CAAS,OAAA,GAAU,EAAE,0BAAA,EAA4B,IAAA,KAAS;AAAC;AACjE,GACD,CAAA;AACD,EAAA,KAAA,MAAW,WAAA,IAAe,SAAS,YAAA,EAAc;AAC/C,IAAA,MAAM,QAAQ,SAAA,CAAU,QAAA,CAAS,KAAA,EAAO,QAAA,CAAS,UAAU,WAAW,CAAA;AAAA,EACxE;AACF;;;AC5BO,IAAM,gBAAN,MAAoB;AAAA,EAChB,SAAA;AAAA,EACA,SAAA,uBAAgB,GAAA,EAAmB;AAAA,EACnC,SAAA,GAAY,IAAI,eAAA,EAAgB;AAAA,EACzC,QAAA;AAAA,EACA,YAAA;AAAA,EAEA,YAAY,QAAA,EAAiC;AAC3C,IAAA,IAAA,CAAK,SAAA,GAAY,QAAA;AAAA,EACnB;AAAA;AAAA,EAGA,QAAA,GAAoB;AAClB,IAAA,OAAO,KAAK,YAAA,KAAiB,MAAA;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,OAAO,OAAA,EAAqC;AAChD,IAAA,IAAI,iBAAA,GAAoB,KAAA;AACxB,IAAA,OAAA,CAAQ,EAAA,CAAG,OAAA,EAAS,CAAC,KAAA,KAAiB;AACpC,MAAA,IAAA,CAAK,UAAU,MAAA,CAAO,IAAA;AAAA,QACpB,iDAAiD,IAAA,CAAK,SAAA,CAAU,KAAK,CAAA,OAAA,EAAU,MAAM,OAAO,CAAA;AAAA,OAC9F;AAAA,IACF,CAAC,CAAA;AACD,IAAA,OAAA,CAAQ,EAAA,CAAG,SAAS,MAAM;AACxB,MAAA,iBAAA,GAAoB,IAAA;AACpB,MAAA,IAAI,IAAA,CAAK,aAAa,OAAA,EAAS;AAC7B,QAAA,IAAA,CAAK,QAAA,GAAW,MAAA;AAChB,QAAA,IAAA,CAAK,YAAA,GAAe,MAAA;AACpB,QAAA,IAAA,CAAK,SAAA,CAAU,eAAe,yBAAyB,CAAA;AAAA,MACzD;AAAA,IACF,CAAC,CAAA;AACD,IAAA,MAAM,OAAA,CAAQ,QAAA,CAAS,IAAA,CAAK,SAAA,CAAU,QAAQ,CAAA;AAC9C,IAAA,MAAM,EAAE,WAAA,EAAY,GAAI,MAAM,OAAA,CAAQ,OAAA;AAAA,MACpC,KAAK,SAAA,CAAU,KAAA;AAAA,MACf,CAAC,OAAA,KAAY,IAAA,CAAK,QAAA,CAAS,SAAS,OAAO,CAAA;AAAA,MAC3C,EAAE,OAAO,KAAA;AAAM,KACjB;AACA,IAAA,IAAI,iBAAA,EAAmB;AACrB,MAAA,MAAM,IAAI,wBAAA;AAAA,QACR,CAAA,4FAAA,EAA+F,IAAA,CAAK,SAAA,CAAU,KAAK,CAAA;AAAA,OACrH;AAAA,IACF;AACA,IAAA,IAAA,CAAK,QAAA,GAAW,OAAA;AAChB,IAAA,IAAA,CAAK,YAAA,GAAe,WAAA;AAAA,EACtB;AAAA;AAAA,EAGA,MAAA,GAAe;AACb,IAAA,IAAA,CAAK,QAAA,GAAW,MAAA;AAChB,IAAA,IAAA,CAAK,YAAA,GAAe,MAAA;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,IAAA,GAAsB;AAC1B,IAAA,IAAA,CAAK,UAAU,KAAA,EAAM;AACrB,IAAA,MAAM,UAAU,IAAA,CAAK,QAAA;AACrB,IAAA,MAAM,cAAc,IAAA,CAAK,YAAA;AACzB,IAAA,IAAA,CAAK,QAAA,GAAW,MAAA;AAChB,IAAA,IAAA,CAAK,YAAA,GAAe,MAAA;AACpB,IAAA,IAAI,OAAA,KAAY,MAAA,IAAa,WAAA,KAAgB,MAAA,EAAW;AACtD,MAAA,MAAM,QAAQ,MAAA,CAAO,WAAW,CAAA,CAAE,KAAA,CAAM,CAAC,KAAA,KAAmB;AAC1D,QAAA,IAAA,CAAK,UAAU,MAAA,CAAO,IAAA;AAAA,UACpB,CAAA,wDAAA,EAA2D,KAAK,SAAA,CAAU,KAAK,UAAUjB,gBAAAA,CAAY,KAAK,EAAE,OAAO,CAAA;AAAA,SACrH;AAAA,MACF,CAAC,CAAA;AAAA,IACH;AACA,IAAA,MAAM,KAAK,cAAA,EAAe;AAC1B,IAAA,MAAM,OAAA,EAAS,KAAA,EAAM,CAAE,KAAA,CAAM,MAAM,MAAS,CAAA;AAAA,EAC9C;AAAA,EAEA,MAAM,cAAA,GAAgC;AACpC,IAAA,IAAI,IAAA,CAAK,SAAA,CAAU,IAAA,KAAS,CAAA,EAAG;AAC7B,MAAA;AAAA,IACF;AACA,IAAA,MAAM,OAAA,GAAU,IAAI,eAAA,EAAgB;AACpC,IAAA,MAAM,WAAW,cAAA,CAAe,IAAA,CAAK,SAAA,CAAU,iBAAA,EAAmB,QAAQ,MAAM,CAAA;AAChF,IAAA,MAAM,OAAA,CAAQ,IAAA,CAAK,CAAC,OAAA,CAAQ,UAAA,CAAW,CAAC,GAAG,IAAA,CAAK,SAAS,CAAC,CAAA,EAAG,QAAQ,CAAC,CAAA;AACtE,IAAA,OAAA,CAAQ,KAAA,EAAM;AAAA,EAChB;AAAA,EAEA,QAAA,CAAS,SAAsB,OAAA,EAAmC;AAChE,IAAA,IAAI,YAAY,IAAA,EAAM;AACpB,MAAA,IAAA,CAAK,YAAA,GAAe,MAAA;AACpB,MAAA,IAAA,CAAK,SAAA,CAAU,eAAe,kCAAkC,CAAA;AAChE,MAAA;AAAA,IACF;AACA,IAAA,MAAM,OAAsB,IAAA,CAAK,QAAA,CAAS,SAAS,OAAO,CAAA,CAAE,QAAQ,MAAM;AACxE,MAAA,IAAA,CAAK,SAAA,CAAU,OAAO,IAAI,CAAA;AAAA,IAC5B,CAAC,CAAA;AACD,IAAA,IAAA,CAAK,SAAA,CAAU,IAAI,IAAI,CAAA;AAAA,EACzB;AAAA,EAEA,MAAM,QAAA,CAAS,OAAA,EAAsB,OAAA,EAAqC;AACxE,IAAA,MAAM,OAAA,GAAU,MAAM,IAAA,CAAK,mBAAA,CAAoB,SAAS,OAAO,CAAA;AAC/D,IAAA,IAAI,YAAY,MAAA,EAAW;AACzB,MAAA;AAAA,IACF;AACA,IAAA,MAAM,EAAE,UAAS,GAAI,OAAA;AACrB,IAAA,MAAM,QAAA,GAA6B;AAAA,MACjC,OAAA;AAAA,MACA,OAAA;AAAA,MACA,QAAA;AAAA,MACA,YAAA,EAAc,iBAAA,CAAkB,OAAA,EAAS,mBAAmB,CAAA,IAAK,CAAA;AAAA,MACjE,cAAA,EAAgB,iBAAA,CAAkB,OAAA,EAAS,oBAAoB;AAAA,KACjE;AACA,IAAA,KAAA,IAAS,OAAA,GAAU,CAAA,IAAK,OAAA,IAAW,CAAA,EAAG;AACpC,MAAA,IAAI;AACF,QAAA,MAAM,IAAA,CAAK,UAAU,SAAA,CAAU,QAAA,EAAU,EAAE,WAAA,EAAa,OAAA,CAAQ,MAAA,CAAO,UAAA,EAAY,CAAA;AACnF,QAAA,IAAA,CAAK,QAAQ,OAAA,EAAS,EAAE,OAAA,EAAS,UAAA,EAAY,OAAO,CAAA;AACpD,QAAA;AAAA,MACF,SAAS,KAAA,EAAO;AACd,QAAA,IAAK,MAAM,KAAK,aAAA,CAAc,QAAA,EAAU,EAAE,OAAA,EAAS,KAAA,EAAO,CAAA,KAAO,SAAA,EAAW;AAC1E,UAAA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,mBAAA,CACJ,OAAA,EACA,OAAA,EAC2D;AAC3D,IAAA,IAAI;AACF,MAAA,OAAO,EAAE,UAAU,IAAA,CAAK,SAAA,CAAU,OAAO,sBAAA,CAAuB,OAAO,CAAC,CAAA,EAAE;AAAA,IAC5E,SAAS,KAAA,EAAO;AACd,MAAA,IAAA,CAAK,UAAU,MAAA,CAAO,KAAA;AAAA,QACpB,CAAA,6EAAA,EAAgF,IAAA,CAAK,SAAA,CAAU,KAAK,CAAA,YAAA,EAAe,OAAA,CAAQ,MAAA,CAAO,UAAU,CAAA,CAAA,EAAI,aAAA,CAAc,KAAK,CAAC,CAAA;AAAA,OACtK;AACA,MAAA,IAAA,CAAK,SAAA,CAAU,mBAAmB,EAAE,WAAA,EAAa,QAAQ,MAAA,CAAO,UAAA,EAAY,OAAO,CAAA;AACnF,MAAA,MAAM,IAAA,CAAK,YAAY,OAAA,EAAS,EAAE,SAAS,MAAA,EAAQ,mBAAA,EAAqB,OAAO,CAAA;AAC/E,MAAA,OAAO,MAAA;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,aAAA,CACJ,QAAA,EACA,EAAE,OAAA,EAAS,OAAM,EACa;AAC9B,IAAA,MAAM,EAAE,OAAA,EAAS,OAAA,EAAS,QAAA,EAAS,GAAI,QAAA;AACvC,IAAA,MAAM,EAAE,KAAA,EAAO,YAAA,EAAa,GAAI,IAAA,CAAK,SAAA;AACrC,IAAA,MAAM,OAAA,GAAU,CAAA,MAAA,EAAS,KAAK,CAAA,SAAA,EAAY,QAAA,CAAS,EAAE,CAAA,SAAA,EAAY,OAAO,CAAA,CAAA,EAAI,aAAA,CAAc,KAAK,CAAC,CAAA,CAAA;AAChG,IAAA,IAAI,CAACmB,qBAAA,CAAiB,YAAA,EAAc,KAAK,CAAA,EAAG;AAC1C,MAAA,IAAA,CAAK,UAAU,MAAA,CAAO,KAAA;AAAA,QACpB,qFAAqF,OAAO,CAAA;AAAA,OAC9F;AACA,MAAA,MAAM,IAAA,CAAK,YAAY,OAAA,EAAS;AAAA,QAC9B,OAAA;AAAA,QACA,MAAA,EAAQ,6BAAA;AAAA,QACR;AAAA,OACD,CAAA;AACD,MAAA,OAAO,SAAA;AAAA,IACT;AACA,IAAA,IAAI,OAAA,GAAU,aAAa,QAAA,EAAU;AACnC,MAAA,MAAM,UAAUlB,sBAAAA,CAAkB,YAAA,EAAc,OAAA,EAAS,IAAA,CAAK,UAAU,MAAM,CAAA;AAC9E,MAAA,IAAA,CAAK,UAAU,MAAA,CAAO,IAAA;AAAA,QACpB,CAAA,yDAAA,EAA4D,OAAO,CAAA,SAAA,EAAY,OAAO,CAAA;AAAA,OACxF;AACA,MAAA,OAAO,IAAA,CAAK,cAAA,CAAe,QAAA,EAAU,OAAO,CAAA;AAAA,IAC9C;AACA,IAAA,OAAO,KAAK,mBAAA,CAAoB,QAAA,EAAU,EAAE,OAAA,EAAS,OAAO,CAAA;AAAA,EAC9D;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,mBAAA,CACJ,QAAA,EACA,EAAE,OAAA,EAAS,OAAM,EACa;AAC9B,IAAA,MAAM,EAAE,OAAA,EAAS,OAAA,EAAQ,GAAI,QAAA;AAC7B,IAAA,QAAA,CAAS,YAAA,IAAgB,CAAA;AACzB,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,IAAA,QAAA,CAAS,cAAA,KAAmB,GAAA;AAC5B,IAAA,MAAM,EAAE,YAAA,EAAc,cAAA,EAAe,GAAI,QAAA;AACzC,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,gBAAA,CAAiB,YAAY,CAAA;AAClD,IAAA,IAAI,GAAA,GAAM,OAAA,GAAU,cAAA,GAAiB,IAAA,CAAK,UAAU,kBAAA,EAAoB;AACtE,MAAA,IAAA,CAAK,UAAU,MAAA,CAAO,KAAA;AAAA,QACpB,CAAA,+EAAA,EAAkF,OAAO,CAAA,cAAA,EAAiB,YAAA,GAAe,CAAC,CAAA,cAAA,EAAiB,GAAA,GAAM,cAAc,CAAA,UAAA,EAAa,IAAA,CAAK,SAAA,CAAU,kBAAkB,CAAA;AAAA,OAC/M;AACA,MAAA,MAAM,IAAA,CAAK,YAAY,OAAA,EAAS;AAAA,QAC9B,OAAA;AAAA,QACA,MAAA,EAAQ,6BAAA;AAAA,QACR;AAAA,OACD,CAAA;AACD,MAAA,OAAO,SAAA;AAAA,IACT;AACA,IAAA,IAAA,CAAK,UAAU,MAAA,CAAO,IAAA;AAAA,MACpB,CAAA,6EAAA,EAAgF,OAAO,CAAA,cAAA,EAAiB,YAAY,YAAY,OAAO,CAAA;AAAA,KACzI;AACA,IAAA,IAAI,CAAC,IAAA,CAAK,SAAA,CAAU,OAAA,EAAS;AAC3B,MAAA,MAAM,IAAA,CAAK,gBAAgB,OAAA,EAAS,EAAE,SAAS,OAAA,EAAS,YAAA,EAAc,gBAAgB,CAAA;AACtF,MAAA,OAAO,SAAA;AAAA,IACT;AACA,IAAA,OAAO,IAAA,CAAK,cAAA,CAAe,QAAA,EAAU,OAAO,CAAA;AAAA,EAC9C;AAAA;AAAA,EAGA,MAAM,cAAA,CAAe,QAAA,EAA4B,OAAA,EAA+C;AAC9F,IAAA,IAAI,MAAM,IAAA,CAAK,YAAA,CAAa,OAAO,CAAA,EAAG;AACpC,MAAA,IAAA,CAAK,OAAA,CAAQ,SAAS,OAAA,EAAS,EAAE,SAAS,QAAA,CAAS,OAAA,EAAS,UAAA,EAAY,SAAA,EAAW,CAAA;AACnF,MAAA,OAAO,SAAA;AAAA,IACT;AACA,IAAA,OAAO,OAAA;AAAA,EACT;AAAA;AAAA,EAGA,iBAAiB,YAAA,EAA8B;AAC7C,IAAA,MAAM,EAAE,UAAA,EAAY,WAAA,EAAa,OAAA,EAAS,MAAA,KAAW,IAAA,CAAK,SAAA;AAC1D,IAAA,MAAM,OAAA,GAAUA,sBAAAA,CAAkB,UAAA,EAAY,YAAA,EAAc,MAAM,CAAA;AAClE,IAAA,OAAO,UAAU,OAAA,GAAU,eAAA,CAAgB,aAAa,EAAE,OAAA,EAAS,QAAQ,CAAA;AAAA,EAC7E;AAAA;AAAA,EAGA,MAAM,aAAa,OAAA,EAAmC;AACpD,IAAA,MAAM,cAAA,CAAe,OAAA,EAAS,IAAA,CAAK,SAAA,CAAU,MAAM,CAAA;AACnD,IAAA,OAAO,IAAA,CAAK,UAAU,MAAA,CAAO,OAAA;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,eAAA,CAAgB,OAAA,EAAsB,KAAA,EAA2C;AACrF,IAAA,MAAM,EAAE,OAAA,EAAS,OAAA,EAAS,YAAA,EAAc,gBAAe,GAAI,KAAA;AAC3D,IAAA,MAAM,EAAE,OAAA,EAAS,OAAA,EAAQ,GAAI,iBAAiB,OAAA,EAAS;AAAA,MACrD,CAAC,mBAAmB,GAAG,MAAA,CAAO,YAAY,CAAA;AAAA,MAC1C,CAAC,oBAAoB,GAAG,MAAA,CAAO,cAAc,CAAA;AAAA,MAC7C,CAAC,2BAA2B,GAAG,kBAAA,CAAmB,OAAO;AAAA,KAC1D,CAAA;AACD,IAAA,IAAI;AACF,MAAA,MAAM,KAAK,SAAA,CAAU,SAAA;AAAA,QACnB,EAAE,UAAU,EAAA,EAAI,UAAA,EAAY,eAAe,IAAA,CAAK,SAAA,CAAU,KAAA,EAAO,OAAO,CAAA,EAAE;AAAA,QAC1E,EAAE,SAAS,OAAA;AAAQ,OACrB;AAAA,IACF,SAAS,KAAA,EAAO;AACd,MAAA,IAAA,CAAK,UAAU,MAAA,CAAO,IAAA;AAAA,QACpB,CAAA,qGAAA,EAAwG,IAAA,CAAK,SAAA,CAAU,KAAK,CAAA,SAAA,EAAY,OAAO,CAAA,OAAA,EAAUD,gBAAAA,CAAY,KAAK,CAAA,CAAE,OAAO,CAAA;AAAA,OACrL;AACA,MAAA,MAAM,IAAA,CAAK,aAAa,OAAO,CAAA;AAC/B,MAAA,IAAA,CAAK,QAAQ,OAAA,EAAS,EAAE,OAAA,EAAS,UAAA,EAAY,WAAW,CAAA;AACxD,MAAA;AAAA,IACF;AACA,IAAA,IAAA,CAAK,QAAQ,OAAA,EAAS,EAAE,OAAA,EAAS,UAAA,EAAY,OAAO,CAAA;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,WAAA,CAAY,OAAA,EAAsB,KAAA,EAAuC;AAC7E,IAAA,MAAM,EAAE,OAAA,EAAS,MAAA,EAAQ,KAAA,EAAM,GAAI,KAAA;AACnC,IAAA,MAAM,EAAE,IAAA,EAAM,IAAA,EAAK,GAAIA,iBAAY,KAAK,CAAA;AACxC,IAAA,MAAM,EAAE,OAAA,EAAS,OAAA,EAAQ,GAAI,iBAAiB,OAAA,EAAS;AAAA,MACrD,CAAC,yBAAyB,GAAG,MAAA;AAAA,MAC7B,CAAC,6BAA6B,GAAG,IAAA;AAAA,MACjC,GAAI,SAAS,MAAA,GAAY,KAAK,EAAE,CAAC,6BAA6B,GAAG,IAAA;AAAK,KACvE,CAAA;AACD,IAAA,IAAI;AACF,MAAA,MAAM,KAAK,SAAA,CAAU,SAAA;AAAA,QACnB,EAAE,UAAU,IAAA,CAAK,SAAA,CAAU,oBAAoB,UAAA,EAAY,IAAA,CAAK,UAAU,KAAA,EAAM;AAAA,QAChF,EAAE,SAAS,OAAA;AAAQ,OACrB;AAAA,IACF,SAASoB,MAAAA,EAAO;AACd,MAAA,IAAA,CAAK,UAAU,MAAA,CAAO,IAAA;AAAA,QACpB,CAAA,4GAAA,EAA+G,KAAK,SAAA,CAAU,KAAK,UAAUpB,gBAAAA,CAAYoB,MAAK,EAAE,OAAO,CAAA;AAAA,OACzK;AACA,MAAA,IAAA,CAAK,QAAQ,OAAA,EAAS,EAAE,OAAA,EAAS,UAAA,EAAY,eAAe,CAAA;AAC5D,MAAA;AAAA,IACF;AACA,IAAA,IAAA,CAAK,QAAQ,OAAA,EAAS,EAAE,OAAA,EAAS,UAAA,EAAY,OAAO,CAAA;AAAA,EACtD;AAAA,EAEA,OAAA,CACE,OAAA,EACA,EAAE,OAAA,EAAS,YAAW,EAChB;AACN,IAAA,IAAI;AACF,MAAA,IAAI,eAAe,KAAA,EAAO;AACxB,QAAA,OAAA,CAAQ,IAAI,OAAO,CAAA;AAAA,MACrB,CAAA,MAAO;AACL,QAAA,OAAA,CAAQ,IAAA,CAAK,OAAA,EAAS,KAAA,EAAO,UAAA,KAAe,SAAS,CAAA;AAAA,MACvD;AAAA,IACF,SAAS,KAAA,EAAO;AAEd,MAAA,IAAA,CAAK,UAAU,MAAA,CAAO,IAAA;AAAA,QACpB,CAAA,kCAAA,EAAqC,UAAU,CAAA,+CAAA,EAAkD,IAAA,CAAK,SAAA,CAAU,KAAK,CAAA,OAAA,EAAUpB,gBAAAA,CAAY,KAAK,CAAA,CAAE,OAAO,CAAA;AAAA,OAC3J;AAAA,IACF;AAAA,EACF;AACF,CAAA;AAGA,SAAS,cAAc,KAAA,EAAwB;AAC7C,EAAA,MAAM,EAAE,OAAA,EAAS,IAAA,EAAM,IAAA,EAAK,GAAIA,iBAAY,KAAK,CAAA;AACjD,EAAA,OAAO,CAAA,MAAA,EAAS,OAAO,CAAA,WAAA,EAAc,IAAI,CAAA,EAAG,SAAS,MAAA,GAAY,EAAA,GAAK,CAAA,MAAA,EAAS,IAAI,CAAA,CAAE,CAAA,CAAA;AACvF;;;AC/WO,IAAM,cAAN,MAAkB;AAAA,EACvB,KAAA,GAA0B,QAAQ,OAAA,EAAQ;AAAA,EAE1C,IAAa,IAAA,EAAgD;AAC3D,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,IAAI,CAAA;AACnC,IAAA,IAAA,CAAK,KAAA,GAAQ,MAAA,CAAO,KAAA,CAAM,MAAM,MAAS,CAAA;AACzC,IAAA,OAAO,MAAA;AAAA,EACT;AACF,CAAA;;;AC6CO,IAAM,iBAAA,GAAN,cAAgCqB,6BAAA,CAAqB;AAAA,EACjD,IAAA;AAAA,EACA,MAAA,GAAS,UAAA;AAAA,EACT,SAAA;AAAA,EACA,WAAA;AAAA,EACA,WAAA;AAAA;AAAA,EAEA,aAAA,GAAgB,IAAI,WAAA,EAAY;AAAA,EACzC,KAAA;AAAA,EACA,aAAA;AAAA,EACA,QAAA;AAAA,EAEA,YAAY,OAAA,EAAmC;AAC7C,IAAA,KAAA,EAAM;AACN,IAAA,IAAA,CAAK,SAAA,GAAY,gBAAgB,OAAO,CAAA;AACxC,IAAA,IAAA,CAAK,IAAA,GAAO,KAAK,SAAA,CAAU,IAAA;AAC3B,IAAA,IAAA,CAAK,cAAc,IAAI,mBAAA,CAAoB,KAAK,IAAA,EAAM,IAAA,CAAK,UAAU,gBAAgB,CAAA;AACrF,IAAA,IAAA,CAAK,WAAA,GAAc,IAAI,oBAAA,CAAqB;AAAA,MAC1C,OAAA,EAAS,KAAK,SAAA,CAAU,OAAA;AAAA,MACxB,SAAA,EAAW,KAAK,SAAA,CAAU,SAAA;AAAA,MAC1B,WAAA,EAAa,CAAC,UAAA,KAAe,IAAA,CAAK,mBAAmB,UAAU,CAAA;AAAA,MAC/D,cAAA,EAAgB,MAAM,IAAA,CAAK,iBAAA,EAAkB;AAAA,MAC7C,MAAA,EAAQ,KAAK,SAAA,CAAU,MAAA;AAAA,MACvB,MAAA,EAAQ,KAAK,SAAA,CAAU;AAAA,KACxB,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,WAAA,GAAuB;AACrB,IAAA,OAAO,IAAA,CAAK,YAAY,WAAA,EAAY;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAA,GAAmB;AACjB,IAAA,OACE,IAAA,CAAK,WAAA,CAAY,WAAA,EAAY,IAC7B,IAAA,CAAK,KAAA,KAAU,MAAA,KACd,IAAA,CAAK,aAAA,KAAkB,MAAA,IAAa,IAAA,CAAK,aAAA,CAAc,SAAS,QAAA,EAAS,CAAA;AAAA,EAE9E;AAAA;AAAA,EAGA,MAAM,OAAA,GAAyB;AAC7B,IAAA,MAAM,IAAA,CAAK,WAAA,CAAY,KAAA,CAAM,IAAA,CAAK,UAAU,kBAAkB,CAAA;AAAA,EAChE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,OAAA,CAAQ,QAAA,EAAyB,WAAA,EAAoC;AACzE,IAAA,iBAAA,CAAkB,6BAA6B,WAAW,CAAA;AAC1D,IAAA,MAAM,EAAE,OAAA,EAAS,OAAA,KAAY,IAAA,CAAK,SAAA,CAAU,OAAO,QAAQ,CAAA;AAC3D,IAAA,MAAM,IAAA,CAAK,WAAA,CAAY,OAAA,CAAQ,IAAA,CAAK,OAAO,SAAA,EAAW;AAAA,MACpD,QAAA,EAAU,KAAK,SAAA,CAAU,QAAA;AAAA,MACzB,UAAA,EAAY,WAAA;AAAA,MACZ,OAAA;AAAA,MACA,OAAA;AAAA,MACA,SAAA,EAAW,CAAC,IAAA,CAAK,SAAA,CAAU;AAAA,KAC5B,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAgB,gBAAA,CAAiB;AAAA,IAC/B,YAAA;AAAA,IACA,SAAA;AAAA,IACA;AAAA,GACF,EAAyC;AACvC,IAAA,IAAI,IAAA,CAAK,kBAAkB,MAAA,EAAW;AACpC,MAAA,MAAM,IAAIP,uBAAAA;AAAA,QACR,CAAA,WAAA,EAAc,KAAK,IAAI,CAAA,iFAAA;AAAA,OACzB;AAAA,IACF;AACA,IAAA,IAAI,YAAA,CAAa,WAAW,CAAA,EAAG;AAC7B,MAAA,MAAM,IAAIA,uBAAAA,CAAmB,CAAA,WAAA,EAAc,IAAA,CAAK,IAAI,CAAA,gCAAA,CAAkC,CAAA;AAAA,IACxF;AACA,IAAA,MAAM,KAAA,GAAQ,gBAAA,CAAiB,IAAA,CAAK,SAAS,CAAA;AAC7C,IAAA,MAAM,YAAA,GAA6B;AAAA,MACjC,QAAA,EAAU,IAAA,CAAK,WAAA,CAAY,KAAA,EAAO,YAAY,CAAA;AAAA,MAC9C,UAAU,IAAA,CAAK,eAAA,CAAgB,OAAO,EAAE,SAAA,EAAW,OAAO;AAAA,KAC5D;AACA,IAAA,MAAM,IAAA,CAAK,aAAA,CAAc,GAAA,CAAI,YAAY;AACvC,MAAA,IAAA,CAAK,aAAA,GAAgB,YAAA;AACrB,MAAA,IAAI,IAAA,CAAK,UAAU,MAAA,EAAW;AAC5B,QAAA,MAAM,IAAA,CAAK,eAAA,CAAgB,IAAA,CAAK,KAAA,CAAM,YAAY,YAAY,CAAA;AAAA,MAChE;AAAA,IACF,CAAC,CAAA;AAAA,EACH;AAAA,EAEA,WAAA,CAAY,OAAe,YAAA,EAAmD;AAC5E,IAAA,OAAO;AAAA,MACL,QAAA,EAAU,KAAK,SAAA,CAAU,QAAA;AAAA,MACzB,KAAA;AAAA,MACA,kBAAA,EAAoB,KAAK,SAAA,CAAU,kBAAA;AAAA,MACnC,eAAA,EAAiB,IAAA,CAAK,SAAA,CAAU,eAAA,IAAmB,GAAG,KAAK,CAAA,KAAA,CAAA;AAAA,MAC3D,aAAA,EAAe,KAAK,SAAA,CAAU,aAAA;AAAA,MAC9B,OAAA,EAAS,KAAK,SAAA,CAAU,OAAA;AAAA,MACxB,aAAA,EAAe,KAAK,SAAA,CAAU,WAAA;AAAA,MAC9B;AAAA,KACF;AAAA,EACF;AAAA,EAEA,eAAA,CACE,KAAA,EACA,EAAE,SAAA,EAAW,OAAM,EACJ;AACf,IAAA,OAAO,IAAI,aAAA,CAAc;AAAA,MACvB,KAAA;AAAA,MACA,QAAA,EAAU,KAAK,SAAA,CAAU,QAAA;AAAA,MACzB,YAAA,EAAc,KAAK,SAAA,CAAU,YAAA;AAAA,MAC7B,UAAA,EAAY,KAAK,SAAA,CAAU,UAAA;AAAA,MAC3B,WAAA,EAAa,KAAK,SAAA,CAAU,WAAA;AAAA,MAC5B,kBAAA,EAAoB,KAAK,SAAA,CAAU,kBAAA;AAAA,MACnC,OAAA,EAAS,KAAK,SAAA,CAAU,OAAA;AAAA,MACxB,kBAAA,EAAoB,KAAK,SAAA,CAAU,kBAAA;AAAA,MACnC,SAAA,EAAW,CAAC,EAAE,QAAA,EAAU,YAAW,EAAG,EAAE,OAAA,EAAS,OAAA,OAC/C,IAAA,CAAK,WAAA,CAAY,OAAA,CAAQ,IAAA,CAAK,OAAO,SAAA,EAAW;AAAA,QAC9C,QAAA;AAAA,QACA,UAAA;AAAA,QACA,OAAA;AAAA,QACA,OAAA;AAAA,QACA,SAAA,EAAW;AAAA,OACZ,CAAA;AAAA,MACH,iBAAA,EAAmB,KAAK,SAAA,CAAU,iBAAA;AAAA,MAClC,SAAA;AAAA,MACA,GAAI,UAAU,MAAA,GAAY,KAAK,EAAE,gBAAA,EAAkB,MAAM,gBAAA,EAAiB;AAAA,MAC1E,MAAA,EAAQ,KAAK,SAAA,CAAU,MAAA;AAAA,MACvB,gBAAgB,CAAC,MAAA,KAAW,IAAA,CAAK,WAAA,CAAY,QAAQ,MAAM,CAAA;AAAA,MAC3D,MAAA,EAAQ,KAAK,SAAA,CAAU,MAAA;AAAA,MACvB,MAAA,EAAQ,KAAK,SAAA,CAAU;AAAA,KACxB,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,KAAA,CAAM,OAAA,GAAwB,EAAC,EAAkB;AACrD,IAAA,MAAM,EAAE,QAAO,GAAI,OAAA;AACnB,IAAA,MAAM,KAAA,GAAQ,MAAY,IAAA,CAAK,WAAA,CAAY,UAAA,EAAW;AACtD,IAAA,IAAI,MAAA,EAAQ,YAAY,IAAA,EAAM;AAC5B,MAAA,KAAA,EAAM;AAAA,IACR;AACA,IAAA,MAAA,EAAQ,iBAAiB,OAAA,EAAS,KAAA,EAAO,EAAE,IAAA,EAAM,MAAM,CAAA;AACvD,IAAA,IAAI;AAEF,MAAA,IAAA,CAAK,QAAA,KAAa,KAAK,WAAA,CAAY,KAAA;AAAA,QAAM,MACvC,IAAA,CAAK,aAAA,CAAc,GAAA,CAAI,YAAY;AACjC,UAAA,MAAM,OAAO,IAAA,CAAK,KAAA;AAClB,UAAA,IAAA,CAAK,KAAA,GAAQ,KAAA,CAAA;AACb,UAAA,MAAM,IAAA,CAAK,aAAA,EAAe,QAAA,CAAS,IAAA,EAAK;AACxC,UAAA,MAAM,MAAM,SAAA,CAAU,OAAA,CAAQ,OAAM,CAAE,KAAA,CAAM,MAAM,KAAA,CAAS,CAAA;AAAA,QAC7D,CAAC;AAAA,OACH;AACA,MAAA,MAAM,IAAA,CAAK,QAAA;AAAA,IACb,CAAA,SAAE;AACA,MAAA,MAAA,EAAQ,mBAAA,CAAoB,SAAS,KAAK,CAAA;AAAA,IAC5C;AAAA,EACF;AAAA,EAEA,MAAM,mBAAmB,UAAA,EAA2C;AAClE,IAAA,MAAM,IAAA,CAAK,aAAA,CAAc,GAAA,CAAI,YAAY;AACvC,MAAA,MAAM,OAAA,GAAU,MAAM,UAAA,CAAW,oBAAA,EAAqB;AACtD,MAAA,MAAM,SAAA,GAAuB,EAAE,OAAA,EAAS,UAAA,sBAAgB,GAAA,EAAI,EAAG,QAAQ,KAAA,EAAM;AAC7E,MAAA,OAAA,CAAQ,EAAA,CAAG,OAAA,EAAS,CAAC,KAAA,KAAiB;AACpC,QAAA,IAAA,CAAK,UAAU,MAAA,CAAO,IAAA;AAAA,UACpB,CAAA,2EAAA,EAA8E,IAAA,CAAK,IAAI,CAAA,OAAA,EAAU,MAAM,OAAO,CAAA;AAAA,SAChH;AAAA,MACF,CAAC,CAAA;AACD,MAAA,OAAA,CAAQ,EAAA,CAAG,SAAS,MAAM;AACxB,QAAA,SAAA,CAAU,MAAA,GAAS,IAAA;AACnB,QAAA,IAAI,IAAA,CAAK,KAAA,EAAO,SAAA,KAAc,SAAA,EAAW;AACvC,UAAA,IAAA,CAAK,WAAA,CAAY,QAAQ,0BAA0B,CAAA;AAAA,QACrD;AAAA,MACF,CAAC,CAAA;AACD,MAAA,OAAA,CAAQ,EAAA,CAAG,QAAA,EAAU,CAAC,OAAA,KAAyB;AAC7C,QAAA,gBAAA;AAAA,UACE,SAAA,CAAU,UAAA;AAAA,UACV,cAAc,OAAA,CAAQ,UAAA,CAAW,SAAA,EAAW,OAAA,CAAQ,OAAO,UAAU;AAAA,SACvE;AAAA,MACF,CAAC,CAAA;AACD,MAAA,MAAM,cAAA,CAAe,OAAA,EAAS,IAAA,CAAK,SAAA,CAAU,QAAQ,CAAA;AACrD,MAAA,IAAI,IAAA,CAAK,kBAAkB,MAAA,EAAW;AACpC,QAAA,MAAM,IAAA,CAAK,eAAA,CAAgB,UAAA,EAAY,IAAA,CAAK,aAAa,CAAA;AAAA,MAC3D;AACA,MAAA,IAAI,UAAU,MAAA,EAAQ;AAEpB,QAAA,MAAM,IAAI,wBAAA;AAAA,UACR,CAAA,iHAAA,EAAoH,KAAK,IAAI,CAAA;AAAA,SAC/H;AAAA,MACF;AACA,MAAA,IAAA,CAAK,KAAA,GAAQ,EAAE,UAAA,EAAY,SAAA,EAAU;AAAA,IACvC,CAAC,CAAA;AAAA,EACH;AAAA,EAEA,MAAM,eAAA,CAAgB,UAAA,EAA4B,YAAA,EAA2C;AAC3F,IAAA,MAAM,OAAA,GAAU,MAAM,UAAA,CAAW,aAAA,EAAc;AAC/C,IAAA,MAAM,sBAAA,CAAuB,OAAA,EAAS,YAAA,CAAa,QAAQ,CAAA;AAC3D,IAAA,MAAM,YAAA,CAAa,QAAA,CAAS,MAAA,CAAO,OAAO,CAAA;AAAA,EAC5C;AAAA,EAEA,iBAAA,GAA0B;AACxB,IAAA,IAAA,CAAK,KAAA,GAAQ,MAAA;AACb,IAAA,IAAA,CAAK,aAAA,EAAe,SAAS,MAAA,EAAO;AAAA,EACtC;AACF","file":"index.cjs","sourcesContent":["import { NonRetryableError, RelayBusError } from '@relaybus/core';\n\n/**\n * The broker cannot take or confirm a message right now: the transport is not\n * connected, was closed, lost its channel, or the confirm did not arrive in time.\n * Always retryable; the outbox keeps the delivery and tries again.\n */\nexport class RabbitMqUnavailableError extends RelayBusError {\n override name = 'RabbitMqUnavailableError';\n override readonly code: string = 'RELAYBUS_RABBITMQ_UNAVAILABLE';\n}\n\n/** The broker negatively acknowledged a published message. Retryable. */\nexport class RabbitMqPublishRejectedError extends RelayBusError {\n override name = 'RabbitMqPublishRejectedError';\n override readonly code: string = 'RELAYBUS_RABBITMQ_PUBLISH_REJECTED';\n}\n\n/**\n * The broker accepted the message but no queue is bound to its routing key, so\n * it would have been discarded. Retryable: it succeeds once a consumer binds.\n */\nexport class UnroutableMessageError extends RelayBusError {\n override name = 'UnroutableMessageError';\n override readonly code: string = 'RELAYBUS_RABBITMQ_UNROUTABLE_MESSAGE';\n}\n\n/** A received message is not a valid relaybus CloudEvent. It is dead-lettered. */\nexport class MalformedMessageError extends RelayBusError {\n override name = 'MalformedMessageError';\n override readonly code: string = 'RELAYBUS_RABBITMQ_MALFORMED_MESSAGE';\n}\n\n/**\n * The payload of an event cannot be represented as JSON without losing or\n * changing data (`undefined`, functions, symbols, BigInt, NaN, Infinity, Dates,\n * Maps, class instances, cycles). Never retried: the payload will not change.\n */\nexport class UnserializablePayloadError extends NonRetryableError {\n override name = 'UnserializablePayloadError';\n override readonly code: string = 'RELAYBUS_RABBITMQ_UNSERIALIZABLE_PAYLOAD';\n}\n\n/**\n * A value exceeds a protocol limit of AMQP 0-9-1, for example an event id or a\n * routing key longer than the 255 bytes of a short string. Never retried.\n */\nexport class AmqpLimitExceededError extends NonRetryableError {\n override name = 'AmqpLimitExceededError';\n override readonly code: string = 'RELAYBUS_RABBITMQ_AMQP_LIMIT_EXCEEDED';\n}\n\n/**\n * An event the configured codec cannot write: a header name the format\n * reserves, or a type a fixed-type route does not carry. Never retried.\n */\nexport class RabbitMqUnencodableEventError extends NonRetryableError {\n override name = 'RabbitMqUnencodableEventError';\n override readonly code: string = 'RELAYBUS_RABBITMQ_UNENCODABLE_EVENT';\n}\n","import { systemClock, toErrorInfo } from '@relaybus/core';\nimport { schedule, type CancelTimer } from '@relaybus/core/internal';\nimport type { AmqpConfirmChannel, AmqpPublishOptions } from './amqp-types.js';\nimport {\n RabbitMqPublishRejectedError,\n RabbitMqUnavailableError,\n UnroutableMessageError,\n} from './errors.js';\n\n/** Publisher channel plus the broker returns not yet matched with their confirm. */\nexport interface Publisher {\n readonly channel: AmqpConfirmChannel;\n readonly unroutable: Map<string, number>;\n /** Set when the channel closed, also while the transport was still being set up. */\n closed: boolean;\n}\n\n/** One message to publish and wait for the broker's confirm. */\nexport type PublishConfirmedInput = {\n readonly exchange: string;\n readonly routingKey: string;\n readonly content: Buffer;\n readonly options: AmqpPublishOptions;\n /** Ask the broker to return the message when no queue is bound to its routing key. */\n readonly mandatory: boolean;\n};\n\n/** amqplib reports a negative acknowledgement with this exact message. */\nconst NACK_MESSAGE = 'message nacked';\n\n/** The event and destination a publish error names. */\ntype PublishTarget = { readonly eventId: string; readonly destination: string };\n\n/** How one pending publish settles. */\ntype PendingConfirm = PublishTarget & {\n readonly publisher: Publisher;\n readonly returnKey: string;\n readonly cancelTimeout: CancelTimer;\n readonly resolve: () => void;\n readonly reject: (error: Error) => void;\n};\n\n/**\n * Publishes on a confirm channel and resolves only after the broker confirmed the message was\n * persisted and routed to a queue; rejects when not connected, nacked, unroutable or unconfirmed\n * within the publish timeout. It never drops a message silently.\n */\nexport class ConfirmedPublishing {\n readonly #transportName: string;\n readonly #publishTimeoutMs: number;\n\n constructor(transportName: string, publishTimeoutMs: number) {\n this.#transportName = transportName;\n this.#publishTimeoutMs = publishTimeoutMs;\n }\n\n async publish(publisher: Publisher | undefined, input: PublishConfirmedInput): Promise<void> {\n const { exchange, routingKey, content, options, mandatory } = input;\n const eventId = options.messageId ?? 'unknown';\n if (publisher === undefined) {\n throw new RabbitMqUnavailableError(\n `[RabbitMqTransport](publish) Not connected to the broker | transport=${this.#transportName} destination=${routingKey}`,\n );\n }\n const returnKey = unroutableKey(options.messageId, routingKey);\n const target = { eventId, destination: routingKey };\n await new Promise<void>((resolve, reject) => {\n const cancelTimeout = this.#startTimeout(target, reject);\n const pending = { ...target, publisher, returnKey, cancelTimeout, resolve, reject };\n try {\n publisher.channel.publish(\n exchange,\n routingKey,\n content,\n { ...options, mandatory },\n (error) => this.#confirmed(pending, error),\n );\n } catch (error) {\n cancelTimeout();\n reject(this.#toPublishError(error, target));\n }\n });\n }\n\n #startTimeout(\n { eventId, destination }: PublishTarget,\n reject: (error: Error) => void,\n ): CancelTimer {\n return schedule(systemClock, {\n run: () => {\n reject(\n new RabbitMqUnavailableError(\n `[RabbitMqTransport](publish) No broker confirm within ${this.#publishTimeoutMs}ms | transport=${this.#transportName} eventId=${eventId} destination=${destination}`,\n ),\n );\n },\n delayMs: this.#publishTimeoutMs,\n });\n }\n\n /** The broker's confirm (or nack) of one message arrived. */\n #confirmed(pending: PendingConfirm, error: Error | null | undefined): void {\n pending.cancelTimeout();\n const returned = takeUnroutable(pending.publisher.unroutable, pending.returnKey);\n if (error) {\n pending.reject(this.#toPublishError(error, pending));\n } else if (returned) {\n pending.reject(\n new UnroutableMessageError(\n `[RabbitMqTransport](publish) No queue is bound to the routing key | transport=${this.#transportName} eventId=${pending.eventId} destination=${pending.destination}`,\n ),\n );\n } else {\n pending.resolve();\n }\n }\n\n #toPublishError(error: unknown, { eventId, destination }: PublishTarget): Error {\n const { message } = toErrorInfo(error);\n const detail = `transport=${this.#transportName} eventId=${eventId} destination=${destination} error=${message}`;\n return message === NACK_MESSAGE\n ? new RabbitMqPublishRejectedError(\n `[RabbitMqTransport](publish) Broker nacked the message | ${detail}`,\n { cause: error },\n )\n : new RabbitMqUnavailableError(`[RabbitMqTransport](publish) Publish failed | ${detail}`, {\n cause: error,\n });\n }\n}\n\n/** Matches a broker return with the publish it belongs to: message id and routing key. */\nexport function unroutableKey(messageId: unknown, routingKey: string): string {\n return `${String(messageId)}\\n${routingKey}`;\n}\n\nexport function recordUnroutable(unroutable: Map<string, number>, key: string): void {\n unroutable.set(key, (unroutable.get(key) ?? 0) + 1);\n}\n\nfunction takeUnroutable(unroutable: Map<string, number>, key: string): boolean {\n const count = unroutable.get(key);\n if (count === undefined) {\n return false;\n }\n if (count === 1) {\n unroutable.delete(key);\n } else {\n unroutable.set(key, count - 1);\n }\n return true;\n}\n","import { systemClock } from '@relaybus/core';\nimport { schedule } from '@relaybus/core/internal';\n\n/** Resolves after `milliseconds`, or as soon as `signal` aborts (immediately when it already has). Never rejects. */\nexport function abortableSleep(milliseconds: number, signal: AbortSignal): Promise<void> {\n if (signal.aborted) {\n return Promise.resolve();\n }\n return new Promise((resolve) => {\n const finish = (): void => {\n cancel();\n signal.removeEventListener('abort', finish);\n resolve();\n };\n const cancel = schedule(systemClock, { run: finish, delayMs: milliseconds });\n signal.addEventListener('abort', finish, { once: true });\n });\n}\n","import {\n computeRetryDelay,\n toErrorInfo,\n type RelayBusLogger,\n type RetryPolicy,\n} from '@relaybus/core';\nimport { abortableSleep } from './abortable-sleep.js';\nimport type { AmqpConnection } from './amqp-types.js';\nimport { RabbitMqUnavailableError } from './errors.js';\nimport type { ConnectOptions } from './options.js';\n\nexport interface ConnectionSupervisorSettings {\n readonly connect: (options: ConnectOptions) => Promise<AmqpConnection>;\n /** Backoff between attempts, or undefined to never reconnect. */\n readonly reconnect: RetryPolicy | undefined;\n /** Creates channels and topology on a fresh connection. A rejection discards the connection. */\n readonly onConnected: (connection: AmqpConnection) => Promise<void>;\n /** The connection is gone or was discarded: drop everything that referenced it. */\n readonly onDisconnected: () => void;\n readonly logger: RelayBusLogger;\n readonly random: () => number;\n}\n\n/**\n * Owns the broker connection. amqplib does not reconnect, so after a connection\n * loss this class retries with capped, jittered backoff until `onConnected`\n * succeeds, and `close` stops it. It reports ready only once `onConnected` has\n * finished, so callers never use half-built channels.\n */\nexport class ConnectionSupervisor {\n readonly #settings: ConnectionSupervisorSettings;\n readonly #stop = new AbortController();\n /** Aborted by `forceClose`: destroys a socket that is still connecting. */\n readonly #force = new AbortController();\n /** Resolves on `forceClose`: closing stops waiting for the broker. */\n readonly #forcing = new Promise<void>((resolve) => {\n this.#force.signal.addEventListener('abort', () => resolve(), { once: true });\n });\n #current: AmqpConnection | undefined;\n /** Connections being closed, until their closing handshake finishes. */\n readonly #closing = new Set<AmqpConnection>();\n /** Set by `forceClose`: connections are cut instead of closed. */\n #forced = false;\n #ready = false;\n #started = false;\n #closed = false;\n #reconnecting: Promise<void> | undefined;\n\n constructor(settings: ConnectionSupervisorSettings) {\n this.#settings = settings;\n }\n\n /** True while a connection is open and `onConnected` has completed for it. */\n isConnected(): boolean {\n return this.#ready;\n }\n\n /**\n * Connects once. When that fails it rejects if `failOnError`, otherwise it\n * resolves and keeps trying in the background. Does nothing when already started.\n */\n async start(failOnError: boolean): Promise<void> {\n if (this.#started) {\n return;\n }\n if (this.#closed) {\n throw new RabbitMqUnavailableError('[ConnectionSupervisor](start) Transport is closed');\n }\n try {\n await this.#establish();\n this.#started = true;\n } catch (error) {\n if (failOnError) {\n throw error;\n }\n this.#settings.logger.warn(\n `[ConnectionSupervisor](start) Broker unreachable, retrying in the background | error=${toErrorInfo(error).message}`,\n );\n this.#started = true;\n this.#startReconnecting();\n }\n }\n\n /**\n * Drops the current connection because one of its channels failed, then\n * reconnects. Closing the channel alone would leave topology half-restored.\n */\n recover(reason: string): void {\n const connection = this.#current;\n if (connection === undefined) {\n return;\n }\n this.#handleLoss(connection, reason);\n void this.#closeConnection(connection);\n }\n\n /**\n * Stops reconnecting, runs `beforeDisconnect` while the connection is still\n * open (to drain consumers) and closes the connection.\n */\n async close(beforeDisconnect: () => Promise<void>): Promise<void> {\n this.#closed = true;\n this.#stop.abort();\n // Once forced, nothing waits for the broker: draining and the closing handshake are cut short.\n await Promise.race([this.#reconnecting, this.#forcing]);\n try {\n await Promise.race([beforeDisconnect(), this.#forcing]);\n } finally {\n const connection = this.#current;\n this.#current = undefined;\n this.#ready = false;\n if (connection !== undefined) {\n await this.#closeConnection(connection);\n }\n }\n }\n\n /**\n * Stops reconnecting and cuts every connection, open or closing, without the closing handshake. A\n * connection that finishes opening afterwards is cut at once.\n */\n forceClose(): void {\n this.#closed = true;\n this.#forced = true;\n this.#stop.abort();\n this.#force.abort();\n for (const connection of [this.#current, ...this.#closing]) {\n if (connection !== undefined) {\n destroySocket(connection);\n }\n }\n }\n\n /** Closes a connection, which `forceClose` can cut until the broker answered; cuts it once forced. */\n async #closeConnection(connection: AmqpConnection): Promise<void> {\n if (this.#forced) {\n destroySocket(connection);\n return;\n }\n this.#closing.add(connection);\n await connection.close().catch(() => undefined);\n this.#closing.delete(connection);\n }\n\n async #establish(): Promise<void> {\n const connection = await this.#settings.connect({ signal: this.#force.signal });\n // Before anything can cut it: an 'error' nobody listens to would crash the process.\n connection.on('error', (error: Error) => {\n this.#settings.logger.warn(\n `[ConnectionSupervisor](establish) Connection error | error=${error.message}`,\n );\n });\n if (this.#closed) {\n // Opened after the transport closed: nobody would use or close it.\n await this.#closeConnection(connection);\n throw new RabbitMqUnavailableError('[ConnectionSupervisor](establish) Transport is closed');\n }\n connection.on('close', (error?: Error) => {\n this.#handleLoss(connection, error?.message ?? 'closed by peer');\n });\n this.#current = connection;\n try {\n await this.#settings.onConnected(connection);\n if (this.#current !== connection) {\n throw new RabbitMqUnavailableError(\n 'Connection was lost while the topology was being set up',\n );\n }\n } catch (error) {\n await this.#discard(connection);\n throw error;\n }\n this.#ready = true;\n }\n\n async #discard(connection: AmqpConnection): Promise<void> {\n if (this.#current === connection) {\n this.#current = undefined;\n }\n this.#settings.onDisconnected();\n await this.#closeConnection(connection);\n }\n\n #handleLoss(connection: AmqpConnection, reason: string): void {\n if (connection !== this.#current) {\n return;\n }\n this.#current = undefined;\n this.#ready = false;\n this.#settings.logger.warn(\n `[ConnectionSupervisor](handleLoss) Connection lost | reason=${reason}`,\n );\n this.#settings.onDisconnected();\n this.#startReconnecting();\n }\n\n #startReconnecting(): void {\n if (\n this.#settings.reconnect === undefined ||\n this.#closed ||\n !this.#started ||\n this.#reconnecting !== undefined\n ) {\n return;\n }\n const policy = this.#settings.reconnect;\n this.#reconnecting = this.#reconnectUntilConnected(policy).finally(() => {\n this.#reconnecting = undefined;\n });\n }\n\n async #reconnectUntilConnected(policy: RetryPolicy): Promise<void> {\n for (let attempt = 1; !this.#closed; attempt += 1) {\n const delayMs = computeRetryDelay(policy, attempt, this.#settings.random);\n this.#settings.logger.log(\n `[ConnectionSupervisor](reconnectUntilConnected) Reconnecting | attempt=${attempt} delayMs=${delayMs}`,\n );\n await abortableSleep(delayMs, this.#stop.signal);\n if (this.#closed) {\n return;\n }\n try {\n await this.#establish();\n this.#settings.logger.log(\n `[ConnectionSupervisor](reconnectUntilConnected) Reconnected | attempt=${attempt}`,\n );\n return;\n } catch (error) {\n this.#settings.logger.warn(\n `[ConnectionSupervisor](reconnectUntilConnected) Attempt failed | attempt=${attempt} error=${toErrorInfo(error).message}`,\n );\n }\n }\n }\n}\n\n/**\n * Destroys the socket under an amqplib connection (the channel model keeps it in fields its types\n * omit). With an error, so amqplib sees a socket error and runs its terminal cleanup: it stops\n * heartbeating, fails pending channel operations and emits `close`.\n */\nfunction destroySocket(connection: AmqpConnection): void {\n const model = connection as {\n readonly connection?: { readonly stream?: { destroy(error: Error): void } };\n };\n model.connection?.stream?.destroy(\n new RabbitMqUnavailableError('Connection cut: the shutdown deadline passed'),\n );\n}\n","import { UnserializablePayloadError } from './errors.js';\n\n/**\n * Throws {@link UnserializablePayloadError} unless `JSON.stringify` represents\n * `payload` faithfully. Only `null`, strings, booleans, finite numbers, arrays\n * and plain objects built from those are accepted. Everything `JSON.stringify`\n * would silently drop (`undefined`, functions, symbols, symbol keys, array holes),\n * convert (NaN and Infinity to `null`, Dates to strings, Maps and Sets to `{}`,\n * class instances to their own properties) or reject late (BigInt, cycles) is\n * refused up front, naming the offending path.\n */\nexport function assertJsonPayload(payload: unknown, eventId: string): void {\n visit(payload, { path: '$', ancestors: new Set(), eventId });\n}\n\nfunction visit(\n value: unknown,\n {\n path,\n ancestors,\n eventId,\n }: { readonly path: string; readonly ancestors: Set<object>; readonly eventId: string },\n): void {\n switch (typeof value) {\n case 'string':\n case 'boolean':\n return;\n case 'number':\n if (!Number.isFinite(value)) {\n throw refuse(eventId, { path, reason: `is ${value}, which JSON turns into null` });\n }\n return;\n case 'object':\n if (value !== null) {\n visitObject(value, { path, ancestors, eventId });\n }\n return;\n default:\n throw refuse(eventId, { path, reason: `is ${typeof value}, which JSON cannot represent` });\n }\n}\n\nfunction visitObject(\n value: object,\n {\n path,\n ancestors,\n eventId,\n }: { readonly path: string; readonly ancestors: Set<object>; readonly eventId: string },\n): void {\n if (ancestors.has(value)) {\n throw refuse(eventId, { path, reason: 'is a circular reference' });\n }\n ancestors.add(value);\n if (Array.isArray(value)) {\n visitArray(value, { path, ancestors, eventId });\n } else {\n visitPlainObject(value, { path, ancestors, eventId });\n }\n ancestors.delete(value);\n}\n\n/** Where a visit is: the path so far, the objects above it and the event it belongs to. */\ntype VisitPlace = {\n readonly path: string;\n readonly ancestors: Set<object>;\n readonly eventId: string;\n};\n\nfunction visitArray(value: unknown[], { path, ancestors, eventId }: VisitPlace): void {\n for (let index = 0; index < value.length; index += 1) {\n if (!(index in value)) {\n throw refuse(eventId, {\n path: `${path}[${index}]`,\n reason: 'is an array hole, which JSON turns into null',\n });\n }\n visit(value[index], { path: `${path}[${index}]`, ancestors, eventId });\n }\n}\n\nfunction visitPlainObject(value: object, { path, ancestors, eventId }: VisitPlace): void {\n const prototype = Object.getPrototypeOf(value) as object | null;\n if (prototype !== Object.prototype && prototype !== null) {\n throw refuse(eventId, {\n path,\n reason: 'is not a plain object (class instance, Date, Map or Set)',\n });\n }\n if (Object.getOwnPropertySymbols(value).length > 0) {\n throw refuse(eventId, { path, reason: 'has a symbol key, which JSON drops' });\n }\n for (const key of Object.keys(value)) {\n visit((value as Record<string, unknown>)[key], {\n path: `${path}.${key}`,\n ancestors,\n eventId,\n });\n }\n}\n\nfunction refuse(\n eventId: string,\n { path, reason }: { readonly path: string; readonly reason: string },\n): UnserializablePayloadError {\n return new UnserializablePayloadError(\n `Event ${eventId} has a payload JSON cannot represent faithfully: ${path} ${reason}`,\n );\n}\n","import type { EventEnvelope, EventHeaders } from '@relaybus/core';\nimport { writeStructuredCloudEvent } from '@relaybus/core/internal';\nimport type { AmqpMessage, AmqpPublishOptions } from './amqp-types.js';\nimport {\n AmqpLimitExceededError,\n MalformedMessageError,\n RabbitMqUnencodableEventError,\n} from './errors.js';\nimport { assertJsonPayload } from './json-payload.js';\n\n/** AMQP `timestamp` properties count seconds. */\nconst MILLISECONDS_PER_SECOND = 1_000;\n\n/**\n * Wire format: CloudEvents 1.0 in binary content mode, following the CloudEvents\n * AMQP protocol binding adapted to RabbitMQ's AMQP 0-9-1.\n *\n * - Body: the JSON-encoded payload (`contentType` `application/json`).\n * - Headers `cloudEvents:specversion`, `cloudEvents:id`, `cloudEvents:type`,\n * `cloudEvents:source`, `cloudEvents:time` (RFC 3339, millisecond precision),\n * `cloudEvents:datacontenttype`, and when present `cloudEvents:subject` (the\n * key) and the extension attributes `cloudEvents:causationid` and\n * `cloudEvents:correlationid`.\n * - AMQP properties mirror the same values for broker tooling: `messageId`,\n * `type`, `appId` (source), `correlationId`, `timestamp` (seconds), plus\n * `deliveryMode` 2 (persistent).\n * - Event headers travel as `relaybus:<name>` message headers, so they cannot\n * collide with CloudEvents attributes or broker headers such as `x-death`.\n *\n * On receive the `cloudEvents:` headers win; the AMQP properties are the\n * fallback for events produced by other CloudEvents libraries (the AMQP\n * timestamp only when `cloudEvents:time` is absent; a present but malformed\n * time is rejected).\n *\n * AMQP 0-9-1 short strings (message properties, header names, routing keys) are\n * limited to 255 bytes. The event id, a header name or a routing key beyond\n * that is refused with {@link AmqpLimitExceededError}, because the event could\n * never be published. The `type`, `appId` and `correlationId` mirrors are\n * skipped when they do not fit; the `cloudEvents:` headers always carry them.\n */\nconst ATTRIBUTE_PREFIX = 'cloudEvents:';\nconst EVENT_HEADER_PREFIX = 'relaybus:';\nconst SPEC_VERSION = '1.0';\nconst JSON_CONTENT_TYPE = 'application/json';\nconst STRUCTURED_CONTENT_TYPE = 'application/cloudevents+json';\n/** Header name prefixes the broker or the transport own; an event header there would be lost on read. */\nconst RESERVED_HEADER_PREFIXES = ['x-death', 'x-first-death-', 'x-last-death-', 'x-relaybus-'];\nconst SHORT_STRING_LIMIT_BYTES = 255;\n/** RFC 3339 date-time, the format of the CloudEvents `time` attribute. */\nexport const RFC3339_PATTERN =\n /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:Z|[+-]\\d{2}:\\d{2})$/i;\n\n/** A serialized event, ready for `channel.publish`. */\nexport interface EncodedMessage {\n readonly content: Buffer;\n readonly options: AmqpPublishOptions;\n}\n\n/**\n * Serializes an envelope.\n *\n * @throws {UnserializablePayloadError} the payload is not representable as JSON\n * @throws {AmqpLimitExceededError} the id or a header name exceeds 255 bytes\n */\nexport function encodeEnvelope(envelope: EventEnvelope): EncodedMessage {\n assertJsonPayload(envelope.payload, envelope.id);\n assertShortString('Event id', envelope.id);\n const headers: Record<string, string> = {\n [`${ATTRIBUTE_PREFIX}specversion`]: SPEC_VERSION,\n [`${ATTRIBUTE_PREFIX}id`]: envelope.id,\n [`${ATTRIBUTE_PREFIX}type`]: envelope.type,\n [`${ATTRIBUTE_PREFIX}source`]: envelope.source,\n [`${ATTRIBUTE_PREFIX}time`]: envelope.occurredAt.toISOString(),\n [`${ATTRIBUTE_PREFIX}datacontenttype`]: JSON_CONTENT_TYPE,\n };\n addOptionalAttributes(headers, envelope);\n return {\n content: Buffer.from(JSON.stringify(envelope.payload), 'utf8'),\n options: {\n contentType: JSON_CONTENT_TYPE,\n persistent: true,\n messageId: envelope.id,\n timestamp: Math.floor(envelope.occurredAt.getTime() / MILLISECONDS_PER_SECOND),\n ...mirror('type', envelope.type),\n ...mirror('appId', envelope.source),\n ...(envelope.correlationId === null ? {} : mirror('correlationId', envelope.correlationId)),\n headers,\n },\n };\n}\n\n/** Adds the attributes an envelope may lack (subject, causation, correlation) and its event headers. */\nfunction addOptionalAttributes(headers: Record<string, string>, envelope: EventEnvelope): void {\n if (envelope.key !== null) {\n headers[`${ATTRIBUTE_PREFIX}subject`] = envelope.key;\n }\n if (envelope.causationId !== null) {\n headers[`${ATTRIBUTE_PREFIX}causationid`] = envelope.causationId;\n }\n if (envelope.correlationId !== null) {\n headers[`${ATTRIBUTE_PREFIX}correlationid`] = envelope.correlationId;\n }\n for (const [name, value] of Object.entries(envelope.headers)) {\n assertShortString(\n `Header name '${EVENT_HEADER_PREFIX}${name}'`,\n `${EVENT_HEADER_PREFIX}${name}`,\n );\n headers[`${EVENT_HEADER_PREFIX}${name}`] = value;\n }\n}\n\n/**\n * Serializes an envelope in CloudEvents structured content mode: the body is\n * one `application/cloudevents+json` document with the attributes and `data`.\n * The AMQP properties are those of binary mode; event headers travel as\n * message headers under their own names, as structured-mode readers expect.\n *\n * @throws {UnserializablePayloadError} the payload is not representable as JSON\n * @throws {AmqpLimitExceededError} the id or a header name exceeds 255 bytes\n * @throws {RabbitMqUnencodableEventError} a header name the broker or the transport reserves\n */\nexport function encodeStructuredEnvelope(envelope: EventEnvelope): EncodedMessage {\n assertJsonPayload(envelope.payload, envelope.id);\n assertShortString('Event id', envelope.id);\n const document = writeStructuredCloudEvent(envelope, {\n time: envelope.occurredAt.toISOString(),\n data: JSON.stringify(envelope.payload),\n });\n return {\n content: Buffer.from(document, 'utf8'),\n options: {\n ...messageProperties(envelope),\n contentType: STRUCTURED_CONTENT_TYPE,\n headers: plainHeaders(envelope, envelope.headers),\n },\n };\n}\n\n/** The AMQP properties every relaybus format writes; `contentType` and `headers` are the format's own. */\nexport function messageProperties(\n envelope: EventEnvelope,\n): Omit<AmqpPublishOptions, 'headers' | 'contentType'> {\n return {\n persistent: true,\n messageId: envelope.id,\n timestamp: Math.floor(envelope.occurredAt.getTime() / MILLISECONDS_PER_SECOND),\n ...mirror('type', envelope.type),\n ...mirror('appId', envelope.source),\n ...(envelope.correlationId === null ? {} : mirror('correlationId', envelope.correlationId)),\n };\n}\n\n/**\n * Message headers under their own names, for formats read by other services.\n * A name the broker or the transport reserves is refused, because the reader\n * would drop it; a name beyond 255 bytes is refused by AMQP.\n */\nexport function plainHeaders(\n envelope: EventEnvelope,\n headers: EventHeaders,\n): Record<string, string> {\n for (const name of Object.keys(headers)) {\n if (RESERVED_HEADER_PREFIXES.some((prefix) => name.startsWith(prefix))) {\n throw new RabbitMqUnencodableEventError(\n `Event ${envelope.id} has a header '${name}', a name the broker or the transport reserves`,\n );\n }\n assertShortString(`Header name '${name}'`, name);\n }\n return Object.fromEntries(Object.entries(headers));\n}\n\n/**\n * Throws {@link AmqpLimitExceededError} when `value` does not fit an AMQP short\n * string (255 bytes of UTF-8), which amqplib would otherwise reject on every\n * attempt.\n */\nexport function assertShortString(label: string, value: string): void {\n const bytes = Buffer.byteLength(value, 'utf8');\n if (bytes > SHORT_STRING_LIMIT_BYTES) {\n throw new AmqpLimitExceededError(\n `${label} is ${bytes} bytes, above the AMQP limit of ${SHORT_STRING_LIMIT_BYTES} bytes`,\n );\n }\n}\n\nfunction mirror<TName extends 'type' | 'appId' | 'correlationId'>(\n name: TName,\n value: string,\n): { [Name in TName]?: string } {\n return Buffer.byteLength(value, 'utf8') > SHORT_STRING_LIMIT_BYTES\n ? {}\n : ({ [name]: value } as { [Name in TName]?: string });\n}\n\n/** Rebuilds an envelope. Throws {@link MalformedMessageError} when the message is not a relaybus event. */\nexport function decodeEnvelope(message: AmqpMessage): EventEnvelope {\n const { properties } = message;\n const attributes = properties.headers ?? {};\n if (attributes[`${ATTRIBUTE_PREFIX}specversion`] !== SPEC_VERSION) {\n throw new MalformedMessageError(\n `Message is not a CloudEvents ${SPEC_VERSION} event (header ${ATTRIBUTE_PREFIX}specversion)`,\n );\n }\n return {\n id: required('id', text(attributes[`${ATTRIBUTE_PREFIX}id`]) ?? text(properties.messageId)),\n type: required('type', text(attributes[`${ATTRIBUTE_PREFIX}type`]) ?? text(properties.type)),\n source: required(\n 'source',\n text(attributes[`${ATTRIBUTE_PREFIX}source`]) ?? text(properties.appId),\n ),\n key: text(attributes[`${ATTRIBUTE_PREFIX}subject`]) ?? null,\n payload: parsePayload(message.content),\n headers: extractEventHeaders(attributes),\n correlationId:\n text(attributes[`${ATTRIBUTE_PREFIX}correlationid`]) ??\n text(properties.correlationId) ??\n null,\n causationId: text(attributes[`${ATTRIBUTE_PREFIX}causationid`]) ?? null,\n occurredAt: parseTime(attributes[`${ATTRIBUTE_PREFIX}time`], properties.timestamp),\n };\n}\n\nfunction extractEventHeaders(attributes: Readonly<Record<string, unknown>>): EventHeaders {\n const headers: Record<string, string> = {};\n for (const [name, value] of Object.entries(attributes)) {\n if (name.startsWith(EVENT_HEADER_PREFIX) && typeof value === 'string') {\n // defineProperty, because assigning `__proto__` would set the prototype and lose the header.\n Object.defineProperty(headers, name.slice(EVENT_HEADER_PREFIX.length), {\n value,\n enumerable: true,\n writable: true,\n configurable: true,\n });\n }\n }\n return headers;\n}\n\nfunction parsePayload(content: Buffer): unknown {\n try {\n return JSON.parse(content.toString('utf8')) as unknown;\n } catch {\n throw new MalformedMessageError('Message body is not valid JSON');\n }\n}\n\nfunction parseTime(rawTime: unknown, timestampSeconds: unknown): Date {\n if (rawTime === undefined) {\n const fallback =\n typeof timestampSeconds === 'number'\n ? new Date(timestampSeconds * MILLISECONDS_PER_SECOND)\n : undefined;\n if (fallback === undefined || Number.isNaN(fallback.getTime())) {\n throw new MalformedMessageError('Message has no valid time (header cloudEvents:time)');\n }\n return fallback;\n }\n const occurredAt =\n typeof rawTime === 'string' && RFC3339_PATTERN.test(rawTime) ? new Date(rawTime) : undefined;\n if (occurredAt === undefined || Number.isNaN(occurredAt.getTime())) {\n throw new MalformedMessageError(\n 'Message time (header cloudEvents:time) is not an RFC 3339 timestamp',\n );\n }\n return occurredAt;\n}\n\nfunction text(value: unknown): string | undefined {\n return typeof value === 'string' ? value : undefined;\n}\n\nfunction required(attribute: string, value: string | undefined): string {\n if (value === undefined || value.length === 0) {\n throw new MalformedMessageError(\n `Message has no ${attribute} (header ${ATTRIBUTE_PREFIX}${attribute})`,\n );\n }\n return value;\n}\n","import { assertEventType, type EventEnvelope, type EventHeaders } from '@relaybus/core';\nimport {\n DecodedEventReader,\n createCloudEventReaders,\n isJsonObject,\n mediaTypeOf,\n observeRejection,\n} from '@relaybus/core/internal';\nimport type { AmqpMessage, AmqpMessageProperties } from './amqp-types.js';\nimport { MalformedMessageError } from './errors.js';\nimport { RFC3339_PATTERN, decodeEnvelope } from './wire-format.js';\n\n/** AMQP `timestamp` properties count seconds. */\nconst MILLISECONDS_PER_SECOND = 1_000;\n\nconst { optionalAttribute, requiredAttribute, assertValidType, assertJsonDataContentType } =\n createCloudEventReaders((reason) => new MalformedMessageError(reason));\n\n/**\n * The event a decoder extracted from a message. `id`, `type` and `payload` are\n * required; every other field may be left out and is then filled by the\n * transport: `source` with the `appId` property (else the routing key), `key`\n * with null, `headers` with none, `correlationId` and `causationId` with null,\n * and `occurredAt` with the `timestamp` property (else the time of receipt).\n */\nexport interface DecodedEvent {\n readonly id: string;\n readonly type: string;\n readonly payload: unknown;\n readonly source?: string;\n readonly key?: string | null;\n readonly headers?: EventHeaders;\n readonly correlationId?: string | null;\n readonly causationId?: string | null;\n readonly occurredAt?: Date;\n}\n\n/**\n * Turns a consumed message into an event, for queues fed by producers that do\n * not use relaybus. Must be synchronous and free of side effects: it runs again\n * on every redelivery, so the same message must always give the same event,\n * above all the same `id`, which is what the inbox deduplicates on.\n *\n * Anything it throws marks the message as malformed: it is dead-lettered and\n * the consumer moves on. An event the bus then rejects (empty id, invalid type\n * or time) is dead-lettered the same way.\n */\nexport type RabbitMqMessageDecoder = (message: AmqpMessage) => DecodedEvent;\n\n/** A plain JSON message, decoded for the extractor options of {@link plainJsonDecoder}. */\nexport interface PlainJsonMessage {\n readonly routingKey: string;\n /** The AMQP properties as delivered (`messageId`, `type`, `appId`, `timestamp`, ...). */\n readonly properties: AmqpMessageProperties;\n /**\n * The message headers with string values, without the broker's and the\n * transport's own (`x-death`, `x-first-death-*`, `x-last-death-*`, `x-relaybus-*`).\n */\n readonly headers: EventHeaders;\n /** The body parsed as JSON. */\n readonly payload: unknown;\n}\n\n/** Options of {@link plainJsonDecoder}. Extractors returning undefined or `''` select the default. */\nexport interface PlainJsonDecoderOptions {\n /**\n * Event type handlers subscribe to: a fixed name for a queue that carries one\n * kind of event, or an extractor such as `fromHeader('event-type')`,\n * `fromPayloadField('type')` or `(message) => message.properties.type`.\n * Required; a message without a type is malformed.\n */\n readonly type: string | ((message: PlainJsonMessage) => string | undefined);\n /**\n * Event id the inbox deduplicates on. Default, and fallback when the\n * extractor finds none: the `messageId` property, which survives\n * redeliveries. A message with neither is malformed, because AMQP has no\n * other identity that is stable across redeliveries; give producers a\n * `messageId` (Spring AMQP can generate one with `setCreateMessageIds(true)`).\n */\n readonly id?: (message: PlainJsonMessage) => string | undefined;\n /** Ordering key. Default: none. */\n readonly key?: (message: PlainJsonMessage) => string | null | undefined;\n /** Logical name of the producer. Default: the `appId` property, else the routing key. */\n readonly source?: string | ((message: PlainJsonMessage) => string | undefined);\n /** When the event happened. Default: the `timestamp` property, else the time of receipt. */\n readonly occurredAt?: (message: PlainJsonMessage) => Date | undefined;\n}\n\nconst STRUCTURED_MEDIA_TYPE = 'application/cloudevents+json';\nconst strictUtf8 = new TextDecoder('utf-8', { fatal: true });\nconst SPEC_VERSION = '1.0';\nconst SPEC_VERSION_HEADER = 'cloudEvents:specversion';\n/** Headers the broker or this transport add on their own; never event headers. */\nconst INTERNAL_HEADER_PREFIXES = ['x-relaybus-', 'x-first-death-', 'x-last-death-'];\n/** Attributes of a structured event that map to envelope fields rather than headers. */\nconst STRUCTURED_ATTRIBUTES: ReadonlySet<string> = new Set([\n 'specversion',\n 'id',\n 'type',\n 'source',\n 'time',\n 'subject',\n 'datacontenttype',\n 'dataschema',\n 'data',\n 'data_base64',\n 'correlationid',\n 'causationid',\n]);\n\n/**\n * Decodes a CloudEvents 1.0 message in either content mode:\n * - structured (`contentType` property `application/cloudevents+json`): the\n * body is a JSON object with `specversion`, `id`, `type`, `source` and\n * optionally `time` (else the `timestamp` property, else the time of\n * receipt), `subject` (the key), `data` (the payload, null when absent) and\n * a JSON `datacontenttype`. `data_base64` is refused, because relaybus\n * payloads are JSON. Extension attributes with string values (`traceparent`,\n * ...) become event headers, as do the string message headers;\n * `correlationid` and `causationid` fill their envelope fields.\n * - binary (anything else): exactly the default decoder, `cloudEvents:*`\n * headers with the AMQP properties as fallback.\n *\n * @throws MalformedMessageError for a message that is neither.\n */\nexport function decodeCloudEvent(message: AmqpMessage): EventEnvelope {\n if (mediaTypeOf(message.properties.contentType) !== STRUCTURED_MEDIA_TYPE) {\n return decodeEnvelope(message);\n }\n const body = parseJsonBody(message.content);\n if (!isJsonObject(body)) {\n throw new MalformedMessageError('A structured CloudEvent must be a JSON object');\n }\n if (body['specversion'] !== SPEC_VERSION) {\n throw new MalformedMessageError(`specversion must be '${SPEC_VERSION}'`);\n }\n const type = requiredAttribute(body, 'type');\n assertValidType(type, 'type');\n assertJsonDataContentType(optionalAttribute(body, 'datacontenttype'));\n if (Object.hasOwn(body, 'data_base64')) {\n throw new MalformedMessageError(\n 'data_base64 is not supported: relaybus payloads are JSON, send them as data',\n );\n }\n const time = optionalAttribute(body, 'time');\n return {\n id: requiredAttribute(body, 'id'),\n type,\n source: requiredAttribute(body, 'source'),\n key: optionalAttribute(body, 'subject') ?? null,\n payload: Object.hasOwn(body, 'data') ? body['data'] : null,\n headers: { ...readForeignHeaders(message.properties), ...extensionAttributes(body) },\n correlationId: optionalAttribute(body, 'correlationid') ?? null,\n causationId: optionalAttribute(body, 'causationid') ?? null,\n occurredAt: time === undefined ? propertyTimeOrNow(message.properties) : parseTime(time),\n };\n}\n\n/**\n * Creates a decoder for messages whose body is plain JSON, as published by a\n * service that does not use relaybus (plain amqplib, Spring AMQP's\n * `Jackson2JsonMessageConverter`, a Go or Python service): the body becomes the\n * payload, the string headers become event headers, and the options say where\n * the event type and id come from.\n *\n * A message that is a CloudEvent anyway (a `cloudEvents:specversion` header,\n * or a structured `application/cloudevents+json` body) is decoded with\n * {@link decodeCloudEvent} instead, so relaybus and foreign producers can feed\n * one queue. A body that is not JSON, a missing or invalid type, a missing id\n * and an extractor returning anything but a string are malformed.\n *\n * ```ts\n * new RabbitMqTransport({\n * url,\n * consumerGroup: 'billing',\n * decode: plainJsonDecoder({ type: (message) => message.properties.type as string }),\n * });\n * ```\n *\n * @throws ConfigurationError when a fixed `type` is not a valid event type.\n */\nexport function plainJsonDecoder(options: PlainJsonDecoderOptions): RabbitMqMessageDecoder {\n if (typeof options.type === 'string') {\n assertEventType(options.type);\n }\n return (message) => {\n const { properties } = message;\n if (\n properties.headers?.[SPEC_VERSION_HEADER] !== undefined ||\n mediaTypeOf(properties.contentType) === STRUCTURED_MEDIA_TYPE\n ) {\n return decodeCloudEvent(message);\n }\n const plain = plainMessageOf(message);\n const type = RABBITMQ_EVENTS.text(options.type, { plain, name: 'type' });\n if (type === undefined) {\n throw new MalformedMessageError('Message has no event type: the type option found none');\n }\n assertValidType(type, 'The event type');\n const id =\n RABBITMQ_EVENTS.text(options.id, { plain, name: 'id' }) ?? nonEmptyText(properties.messageId);\n if (id === undefined) {\n throw new MalformedMessageError(\n 'Message has no id: set the messageId property on the producer or configure the id option',\n );\n }\n return {\n id,\n type,\n source:\n RABBITMQ_EVENTS.text(options.source, { plain, name: 'source' }) ?? defaultSource(message),\n key: RABBITMQ_EVENTS.text(options.key, { plain, name: 'key' }) ?? null,\n payload: plain.payload,\n headers: plain.headers,\n correlationId: null,\n causationId: null,\n occurredAt: resolveOccurredAt(options.occurredAt, plain),\n };\n };\n}\n\n/** A message as the extractor options of {@link plainJsonDecoder} see it. */\nfunction plainMessageOf(message: AmqpMessage): PlainJsonMessage {\n const { properties } = message;\n return {\n routingKey: message.fields.routingKey,\n properties,\n headers: readForeignHeaders(properties),\n payload: parseJsonBody(message.content),\n };\n}\n\n/** The inbound plumbing of AMQP messages: malformed messages and the message's own defaults. */\nclass RabbitMqDecodedEvents extends DecodedEventReader<AmqpMessage, PlainJsonMessage> {\n invalid(reason: string): Error {\n return new MalformedMessageError(reason);\n }\n\n protected defaultSource(message: AmqpMessage): string {\n return defaultSource(message);\n }\n\n /** None: AMQP messages carry no ordering key. */\n protected defaultKey(): null {\n return null;\n }\n\n /** The `timestamp` property, else the time of receipt. */\n protected defaultTime(message: AmqpMessage): Date {\n return propertyTimeOrNow(message.properties);\n }\n}\n\nconst RABBITMQ_EVENTS = new RabbitMqDecodedEvents();\n\n/**\n * Fills the fields a decoder left out (see {@link DecodedEvent}) and guards\n * against a decoder that returned no object.\n */\nexport function completeDecodedEvent(decoded: unknown, message: AmqpMessage): EventEnvelope {\n return RABBITMQ_EVENTS.complete(decoded, message);\n}\n\n/** Parses the body as UTF-8 JSON, refusing invalid UTF-8 instead of replacing it. */\nexport function parseJsonBody(content: Buffer): unknown {\n let text: string;\n try {\n text = strictUtf8.decode(content);\n } catch {\n throw new MalformedMessageError('Message body is not valid UTF-8');\n }\n try {\n return JSON.parse(text) as unknown;\n } catch {\n throw new MalformedMessageError('Message body is not valid JSON');\n }\n}\n\nexport function nonEmptyText(value: unknown): string | undefined {\n return typeof value === 'string' && value.length > 0 ? value : undefined;\n}\n\nfunction defaultSource(message: AmqpMessage): string {\n return nonEmptyText(message.properties.appId) ?? message.fields.routingKey;\n}\n\nfunction parseTime(text: string): Date {\n const time = new Date(text);\n if (!RFC3339_PATTERN.test(text) || Number.isNaN(time.getTime())) {\n throw new MalformedMessageError(`time is not an RFC 3339 timestamp: '${text}'`);\n }\n return time;\n}\n\n/** The `timestamp` property (seconds), else the time of receipt. */\nfunction propertyTimeOrNow(properties: AmqpMessageProperties): Date {\n const { timestamp } = properties;\n return typeof timestamp === 'number' && Number.isFinite(timestamp)\n ? new Date(timestamp * MILLISECONDS_PER_SECOND)\n : new Date();\n}\n\nfunction extensionAttributes(body: Record<string, unknown>): Record<string, string> {\n return Object.fromEntries(\n Object.entries(body).filter(\n (entry): entry is [string, string] =>\n !STRUCTURED_ATTRIBUTES.has(entry[0]) && typeof entry[1] === 'string',\n ),\n );\n}\n\nexport function readForeignHeaders(properties: AmqpMessageProperties): Record<string, string> {\n return Object.fromEntries(\n Object.entries(properties.headers ?? {}).filter(\n (entry): entry is [string, string] =>\n typeof entry[1] === 'string' &&\n !INTERNAL_HEADER_PREFIXES.some((prefix) => entry[0].startsWith(prefix)),\n ),\n );\n}\n\nfunction resolveOccurredAt(\n option: PlainJsonDecoderOptions['occurredAt'],\n message: PlainJsonMessage,\n): Date {\n const value: unknown = option?.(message);\n if (value === undefined) {\n return propertyTimeOrNow(message.properties);\n }\n if (!(value instanceof Date) || Number.isNaN(value.getTime())) {\n observeRejection(value);\n throw new MalformedMessageError('The occurredAt option returned no valid Date');\n }\n return value;\n}\n","import type { EventEnvelope } from '@relaybus/core';\nimport { createJsonEnvelopeFormat, type JsonEnvelopeMapping } from '@relaybus/core/internal';\nimport type { AmqpMessage } from './amqp-types.js';\nimport { MalformedMessageError, RabbitMqUnencodableEventError } from './errors.js';\nimport {\n completeDecodedEvent,\n decodeCloudEvent,\n nonEmptyText,\n parseJsonBody,\n readForeignHeaders,\n type RabbitMqMessageDecoder,\n} from './inbound-decoders.js';\nimport { assertJsonPayload } from './json-payload.js';\nimport {\n assertShortString,\n decodeEnvelope,\n encodeEnvelope,\n encodeStructuredEnvelope,\n messageProperties,\n plainHeaders,\n type EncodedMessage,\n} from './wire-format.js';\n\n/**\n * The wire format of a {@link RabbitMqTransport}: how an event becomes a\n * message (`encode`, on publish) and a consumed message becomes an event\n * (`decode`).\n *\n * Both must be synchronous and free of side effects. What `encode` throws\n * fails the publish: the outbox retries it, unless it is a `NonRetryableError`\n * such as {@link RabbitMqUnencodableEventError}. Give every message a\n * `messageId`: the transport matches broker returns of unroutable messages by\n * it. What `decode` throws marks the message as malformed: it is\n * dead-lettered and the consumer moves on. See {@link RabbitMqMessageDecoder}\n * for the decode contract.\n */\nexport interface RabbitMqCodec {\n readonly encode: (envelope: EventEnvelope) => EncodedMessage;\n readonly decode: RabbitMqMessageDecoder;\n}\n\n/**\n * CloudEvents 1.0 binary content mode, the default: the body is the JSON\n * payload, the attributes travel as `cloudEvents:*` headers mirrored in the\n * AMQP properties. Decoding is strict: any other message is malformed.\n */\nexport const cloudEventsBinary: RabbitMqCodec = Object.freeze({\n encode: encodeEnvelope,\n decode: decodeEnvelope,\n});\n\n/**\n * CloudEvents 1.0 structured content mode: the body is one\n * `application/cloudevents+json` document with the attributes and `data`.\n * Decoding accepts structured and binary mode ({@link decodeCloudEvent}).\n * Event headers travel under their own names; names starting with `x-death`,\n * `x-first-death-`, `x-last-death-` or `x-relaybus-` are refused.\n */\nexport const cloudEventsStructured: RabbitMqCodec = Object.freeze({\n encode: encodeStructuredEnvelope,\n decode: decodeCloudEvent,\n});\n\n/**\n * Where each value of a JSON message lives, for {@link jsonEnvelope}. Besides\n * `{ body }` and `{ header }`, the id may be `'message-id-property'`: the\n * AMQP `messageId` property, which the codec always writes and which survives\n * redeliveries; a message without one is malformed.\n */\nexport type RabbitMqJsonEnvelopeMapping = JsonEnvelopeMapping<'message-id-property'>;\n\nconst MESSAGE_ID_PROPERTY = 'message-id-property';\nconst DEFAULT_CONTENT_TYPE = 'application/json';\n\n/**\n * A JSON wire format declared by a mapping, in both directions: for queues\n * shared with services that wrap events in their own envelope\n * (`{ \"eventName\": ..., \"data\": {...} }`, MassTransit) or send the bare\n * payload. Every message also gets the AMQP properties of binary mode:\n * `messageId` (the event id), `type`, `appId` (the source), `correlationId`,\n * `timestamp` (seconds) and `persistent`. Event\n * headers that are message headers are written as they are, so a name the\n * mapping uses for another field, or one the broker reserves, is refused\n * with {@link RabbitMqUnencodableEventError}.\n *\n * ```ts\n * codec: jsonEnvelope({\n * type: { body: 'eventName' },\n * id: 'message-id-property',\n * payload: { body: 'data' },\n * })\n * ```\n *\n * @throws ConfigurationError for an incomplete or self-overlapping mapping.\n */\nexport function jsonEnvelope(mapping: RabbitMqJsonEnvelopeMapping): RabbitMqCodec {\n const format = createJsonEnvelopeFormat(mapping, {\n transportIds: [MESSAGE_ID_PROPERTY],\n failures: {\n invalid: (reason) => new MalformedMessageError(reason),\n unencodable: (reason) => new RabbitMqUnencodableEventError(reason),\n },\n });\n const contentType = mapping.contentType ?? DEFAULT_CONTENT_TYPE;\n return {\n encode: (envelope) => {\n assertJsonPayload(envelope.payload, envelope.id);\n assertShortString('Event id', envelope.id);\n const { body, headers } = format.write(envelope);\n return {\n content: Buffer.from(JSON.stringify(body), 'utf8'),\n options: {\n ...messageProperties(envelope),\n contentType,\n headers: plainHeaders(envelope, headers),\n },\n };\n },\n decode: (message) => {\n const fields = format.read({\n body: parseJsonBody(message.content),\n headers: readForeignHeaders(message.properties),\n });\n return { ...fields, id: fields.id ?? requireMessageId(message) };\n },\n };\n}\n\nfunction requireMessageId(message: AmqpMessage): string {\n const id = nonEmptyText(message.properties.messageId);\n if (id === undefined) {\n throw new MalformedMessageError('Message has no id: the messageId property is missing');\n }\n return id;\n}\n\n/**\n * The event a {@link RabbitMqTransport} with `codec` hands to the bus for `message`: the codec's\n * `decode`, with what it leaves out filled in (see `DecodedEvent`). Throws for a malformed\n * message. For codec contract tests (`rabbitMqCodecContract` of `@relaybus/testing`).\n */\nexport function decodeRabbitMqMessage(codec: RabbitMqCodec, message: AmqpMessage): EventEnvelope {\n if (codec === cloudEventsBinary) {\n return decodeEnvelope(message);\n }\n return completeDecodedEvent(codec.decode(message), message);\n}\n","import { ConfigurationError, type RetryPolicy } from '@relaybus/core';\nimport type { AmqpMessage, AmqpPublishOptions } from './amqp-types.js';\n\n/** Number of delayed redeliveries a message went through. Set on every retry copy. */\nexport const REDELIVERIES_HEADER = 'x-relaybus-redeliveries';\n/** Epoch milliseconds of the first failure that needed a delayed redelivery. */\nexport const FIRST_FAILURE_HEADER = 'x-relaybus-first-failure-at';\n/** Why a message was moved to the dead-letter queue by the consumer. */\nexport const DEAD_LETTER_REASON_HEADER = 'x-relaybus-dead-letter-reason';\n/** Class name of the error that dead-lettered a message, such as `MalformedMessageError`. */\nexport const DEAD_LETTER_ERROR_NAME_HEADER = 'x-relaybus-dead-letter-error-name';\n/** Stable code of that error, such as `RELAYBUS_RABBITMQ_MALFORMED_MESSAGE`; absent for non-relaybus errors. */\nexport const DEAD_LETTER_ERROR_CODE_HEADER = 'x-relaybus-dead-letter-error-code';\n/**\n * The routing key a message was originally published with. Set on retry copies,\n * which travel through the default exchange and return with the queue name as\n * routing key, so decoders still see the original one.\n */\nexport const ORIGINAL_ROUTING_KEY_HEADER = 'x-relaybus-routing-key';\n\nconst RELAYBUS_STATE_HEADERS: readonly string[] = [REDELIVERIES_HEADER, FIRST_FAILURE_HEADER];\n/** Counters the broker stamps on its own redeliveries; they must not travel in a copy. */\nconst BROKER_COUNTER_HEADERS: readonly string[] = ['x-delivery-count', 'x-acquired-count'];\nconst MAXIMUM_LADDER_TIERS = 16;\n\n/**\n * The fixed delays of the retry queues, ascending: the policy's delay grown by\n * its factor until the cap. Each tier is its own queue with a queue-level TTL,\n * so messages in one queue always expire in arrival order; one queue with\n * mixed per-message TTLs would let a long delay hold back shorter ones.\n *\n * @throws {ConfigurationError} the policy has no usable delays or too many tiers\n */\nexport function buildRetryLadder(policy: RetryPolicy): readonly number[] {\n if (policy.initialDelayMs < 1) {\n throw new ConfigurationError('redelivery.initialDelay must be at least 1ms');\n }\n const tiers: number[] = [];\n let delay = policy.initialDelayMs;\n for (;;) {\n const tier = Math.round(Math.min(delay, policy.maxDelayMs));\n tiers.push(tier);\n if (tier >= policy.maxDelayMs || policy.factor === 1) {\n return tiers;\n }\n if (tiers.length === MAXIMUM_LADDER_TIERS) {\n throw new ConfigurationError(\n `redelivery needs more than ${MAXIMUM_LADDER_TIERS} retry queues; raise redelivery.factor or lower redelivery.maxDelay`,\n );\n }\n delay *= policy.factor;\n }\n}\n\n/**\n * Maps a jittered delay onto the ladder. A delay between two tiers goes to the\n * upper one with the probability that keeps the expected delay equal to\n * `delayMs`, so jitter still spreads a cohort of failures across tiers.\n */\nexport function chooseRetryTier(\n ladder: readonly number[],\n { delayMs, random }: { readonly delayMs: number; readonly random: () => number },\n): number {\n const upperIndex = ladder.findIndex((tier) => tier >= delayMs);\n if (upperIndex === -1) {\n return ladder.at(-1)!;\n }\n if (upperIndex === 0) {\n return ladder[0]!;\n }\n const lower = ladder[upperIndex - 1]!;\n const upper = ladder[upperIndex]!;\n return random() < (delayMs - lower) / (upper - lower) ? upper : lower;\n}\n\n/** Reads a non-negative integer that a copy carries as a header (string or number). */\nexport function readCounterHeader(message: AmqpMessage, name: string): number | undefined {\n // A message decoded by a custom decoder (plain JSON, structured mode) may have no headers.\n const value = message.properties.headers?.[name];\n const parsed = typeof value === 'string' && /^\\d+$/.test(value) ? Number(value) : value;\n return typeof parsed === 'number' && Number.isSafeInteger(parsed) && parsed >= 0\n ? parsed\n : undefined;\n}\n\n/**\n * A byte-faithful copy of a received message for publishing to another queue:\n * same body and properties, headers carried over except the broker's delivery\n * counters and relaybus' own redelivery state, then `headerChanges` applied.\n */\nexport function copyForRepublish(\n message: AmqpMessage,\n headerChanges: Readonly<Record<string, string>>,\n): { content: Buffer; options: AmqpPublishOptions } {\n const { properties } = message;\n const headers: Record<string, unknown> = { ...properties.headers };\n for (const name of [\n ...RELAYBUS_STATE_HEADERS,\n DEAD_LETTER_REASON_HEADER,\n DEAD_LETTER_ERROR_NAME_HEADER,\n DEAD_LETTER_ERROR_CODE_HEADER,\n ...BROKER_COUNTER_HEADERS,\n ]) {\n delete headers[name];\n }\n Object.assign(headers, headerChanges);\n return {\n content: message.content,\n options: {\n contentType:\n typeof properties.contentType === 'string' ? properties.contentType : 'application/json',\n persistent: true,\n ...(typeof properties.messageId === 'string' ? { messageId: properties.messageId } : {}),\n ...(typeof properties.type === 'string' ? { type: properties.type } : {}),\n ...(typeof properties.appId === 'string' ? { appId: properties.appId } : {}),\n ...(typeof properties.correlationId === 'string'\n ? { correlationId: properties.correlationId }\n : {}),\n ...(typeof properties.timestamp === 'number' ? { timestamp: properties.timestamp } : {}),\n headers,\n },\n };\n}\n\n/** The routing key the message was published with: the original one for a retry copy. */\nexport function originalRoutingKey(message: AmqpMessage): string {\n const original = message.properties.headers?.[ORIGINAL_ROUTING_KEY_HEADER];\n return typeof original === 'string' ? original : message.fields.routingKey;\n}\n\n/** The message as first published: a retry copy gets its original routing key back. */\nexport function withOriginalRoutingKey(message: AmqpMessage): AmqpMessage {\n const routingKey = originalRoutingKey(message);\n return routingKey === message.fields.routingKey\n ? message\n : { ...message, fields: { ...message.fields, routingKey } };\n}\n","import {\n ConfigurationError,\n createRetryPolicy,\n type Duration,\n type EventEnvelope,\n type RelayBusLogger,\n type RetryPolicy,\n type RetryPolicyOptions,\n} from '@relaybus/core';\nimport { Milliseconds, NonEmptyText, PositiveInteger } from '@relaybus/core/internal';\nimport type { AmqpConnection, AmqpMessage } from './amqp-types.js';\nimport { cloudEventsBinary, decodeRabbitMqMessage, type RabbitMqCodec } from './codecs.js';\nimport type { RabbitMqMessageDecoder } from './inbound-decoders.js';\nimport { buildRetryLadder } from './redelivery.js';\nimport { decodeEnvelope, encodeEnvelope, type EncodedMessage } from './wire-format.js';\n\n/** Connection settings accepted by `amqplib.connect`, given as an object instead of a URL. */\nexport interface BrokerConnectionSettings {\n readonly protocol?: string;\n readonly hostname?: string;\n readonly port?: number;\n readonly username?: string;\n readonly password?: string;\n readonly vhost?: string;\n /** Seconds. See \"Operational notes\" in the README for the heartbeat defaults of each amqplib version. */\n readonly heartbeat?: number;\n}\n\n/** Backoff between reconnect attempts. Attempts are unlimited. */\nexport type ReconnectOptions = Pick<\n RetryPolicyOptions,\n 'initialDelay' | 'factor' | 'maxDelay' | 'jitter'\n>;\n\n/**\n * Delayed redelivery of messages whose handler keeps failing. Each failed\n * delivery goes to a retry queue and returns to the main queue after a growing\n * delay, so an outage of the handler's dependency is waited out instead of\n * burning through delivery attempts.\n */\nexport type RedeliveryOptions = Pick<\n RetryPolicyOptions,\n 'initialDelay' | 'factor' | 'maxDelay' | 'jitter'\n> & {\n /**\n * How long a message may keep failing, counted from its first delayed\n * redelivery, before it is dead-lettered. Default `'1h'`.\n */\n readonly maxAge?: Duration;\n};\n\nexport interface RabbitMqTransportOptions {\n /** Name referenced by routes and subscriptions. Default `'rabbitmq'`. */\n readonly name?: string;\n /**\n * Broker location, for example `amqp://user:pass@host:5672/vhost?heartbeat=30`.\n * Give exactly one of `url` and `connect`.\n */\n readonly url?: string | BrokerConnectionSettings;\n /**\n * Opens one connection. Called again after every connection loss. Use it for\n * TLS options, custom credentials or an alternative amqplib instance. `signal` aborts when a\n * shutdown runs past its deadline: pass it on (`amqplib.connect(url, { signal })`) so a broker\n * that never answers the handshake cannot hold the socket open.\n */\n readonly connect?: (options: ConnectOptions) => Promise<AmqpConnection>;\n /** Topic exchange events are published to. Durable, created when missing. Default `'relaybus'`. */\n readonly exchange?: string;\n /**\n * Unacknowledged messages the consumer holds, which is also its concurrency.\n * Default 50, or 1 when `ordered`.\n */\n readonly prefetch?: number;\n /** Prefix of derived queue names. Default `'relaybus'`. */\n readonly queuePrefix?: string;\n /**\n * Consumer group: services sharing it share one queue and split the messages,\n * services with different groups each receive every message. The queue is\n * `<queuePrefix>.<consumerGroup>`. Required when subscribing, unless `queue` is set.\n */\n readonly consumerGroup?: string;\n /** Explicit queue name. Overrides `queuePrefix` and `consumerGroup`. */\n readonly queue?: string;\n /** Exchange poison messages are dead-lettered to. Default `'<exchange>.dead'`. */\n readonly deadLetterExchange?: string;\n /** Queue that keeps dead-lettered messages for inspection. Default `'<queue>.dead'`. */\n readonly deadLetterQueue?: string;\n /**\n * Quorum queue `x-delivery-limit`: deliveries after which the broker itself\n * dead-letters a message. Failing handlers do not consume it (they use\n * `redelivery`); it only stops a message that crashes the consumer or its\n * channel again and again. Default 10.\n */\n readonly deliveryLimit?: number;\n /**\n * Handler attempts on the same delivery, with backoff, before the message is\n * scheduled for delayed redelivery. Absorbs short blips without a broker round\n * trip. Default: 3 attempts, 200 ms initial delay, factor 2, 5 s cap, equal jitter.\n */\n readonly handlerRetry?: RetryPolicyOptions;\n /**\n * Delayed redelivery after `handlerRetry` is spent. Default: 2 s initial\n * delay, factor 2, 5 min cap, equal jitter, dead-lettered after 1 h of\n * failing (about 18 redeliveries). Delays are quantized to the retry queues,\n * one per step of the exponential ladder (9 queues with the defaults).\n * Ignored when `ordered`, where the same delays are waited in place.\n */\n readonly redelivery?: RedeliveryOptions;\n /**\n * Consume the queue strictly in order: a single active consumer across all\n * replicas, one message at a time, a failing message is retried in place\n * (blocking the queue) instead of being delayed. Needed when\n * `EventEnvelope.key` order matters; costs throughput, because one handler\n * runs at a time. Default false: handlers run concurrently and a delayed\n * redelivery overtakes later messages, so order is not preserved.\n */\n readonly ordered?: boolean;\n /** Reconnect backoff, or `false` to never reconnect. Default: 500 ms initial, factor 2, 30 s cap, equal jitter. */\n readonly reconnect?: ReconnectOptions | false;\n /**\n * When true (default) `connect()` rejects if the broker is unreachable, which\n * fails startup. When false it resolves and keeps trying in the background.\n */\n readonly failOnConnectError?: boolean;\n /**\n * When false (default) a message that no queue is bound to makes `publish`\n * reject. When true it resolves and the broker silently discards the message.\n */\n readonly allowUnroutable?: boolean;\n /** How long `publish` waits for the broker confirm. Default `'30s'`. */\n readonly publishTimeout?: Duration;\n /** How long `close` waits for running handlers. Default `'30s'`. */\n readonly shutdownTimeout?: Duration;\n /**\n * The wire format, both ways: how events become messages and consumed\n * messages become events. Default {@link cloudEventsBinary}: CloudEvents\n * binary mode (`cloudEvents:*` headers, AMQP properties as fallback), any\n * other message is malformed and dead-lettered. {@link cloudEventsStructured}\n * writes structured mode and reads both, {@link jsonEnvelope} maps a JSON\n * format of your own (an envelope with the payload inside, or the bare\n * payload), and an object with `encode` and `decode` can do anything else.\n * Whatever `decode` throws marks the message as malformed: it is\n * dead-lettered, the consumer keeps running.\n */\n readonly codec?: RabbitMqCodec;\n /**\n * How consumed messages become events; events are still written in\n * CloudEvents binary mode.\n *\n * @deprecated Use `codec`: `decode: fn` is `codec: { encode: encodeEnvelope, decode: fn }`.\n * Giving both `decode` and `codec` is a configuration error.\n */\n readonly decode?: RabbitMqMessageDecoder;\n /** Default: `console`. */\n readonly logger?: RelayBusLogger;\n /** Random source for jitter. Default `Math.random`. Intended for tests. */\n readonly random?: () => number;\n}\n\n/** What `connect` gets for each connection it opens. */\nexport interface ConnectOptions {\n /** Aborted when a shutdown runs past its deadline; destroys a socket still connecting. */\n readonly signal: AbortSignal;\n}\n\nexport interface ResolvedTransportSettings {\n readonly name: string;\n readonly connect: (options: ConnectOptions) => Promise<AmqpConnection>;\n readonly exchange: string;\n readonly prefetch: number;\n readonly queuePrefix: string;\n readonly consumerGroup: string | undefined;\n readonly queue: string | undefined;\n readonly deadLetterExchange: string;\n readonly deadLetterQueue: string | undefined;\n readonly deliveryLimit: number;\n readonly handlerRetry: RetryPolicy;\n readonly redelivery: RetryPolicy;\n /** Fixed delays of the retry queues; empty when `ordered`. */\n readonly retryLadder: readonly number[];\n readonly redeliveryMaxAgeMs: number;\n readonly ordered: boolean;\n readonly reconnect: RetryPolicy | undefined;\n readonly failOnConnectError: boolean;\n readonly allowUnroutable: boolean;\n readonly publishTimeoutMs: number;\n readonly shutdownTimeoutMs: number;\n /** Turns an event into the message to publish. */\n readonly encode: (envelope: EventEnvelope) => EncodedMessage;\n /** Turns a consumed message into a complete envelope; throws for a malformed one. */\n readonly decode: (message: AmqpMessage) => EventEnvelope;\n readonly logger: RelayBusLogger;\n readonly random: () => number;\n}\n\n/** Default `prefetch` when not ordered. */\nconst DEFAULT_PREFETCH = 50;\n/** Default `deliveryLimit`. */\nconst DEFAULT_DELIVERY_LIMIT = 10;\n\nconst DEFAULT_HANDLER_RETRY: RetryPolicy = {\n attempts: 3,\n initialDelayMs: 200,\n factor: 2,\n maxDelayMs: 5_000,\n jitter: 'equal',\n retryIf: undefined,\n};\n\nconst DEFAULT_REDELIVERY: RetryPolicy = {\n attempts: Number.POSITIVE_INFINITY,\n initialDelayMs: 2_000,\n factor: 2,\n maxDelayMs: 300_000,\n jitter: 'equal',\n retryIf: undefined,\n};\n\nconst DEFAULT_REDELIVERY_MAX_AGE = '1h';\n\nconst DEFAULT_RECONNECT: RetryPolicy = {\n attempts: 1,\n initialDelayMs: 500,\n factor: 2,\n maxDelayMs: 30_000,\n jitter: 'equal',\n retryIf: undefined,\n};\n\n/** Validates the options and applies defaults. Throws `ConfigurationError`. */\nexport function resolveSettings(options: RabbitMqTransportOptions): ResolvedTransportSettings {\n const basics = resolveBasics(options);\n return {\n ...resolveTopology(options, basics),\n ...resolveRetries(options, basics),\n ...resolveRuntime(options, basics),\n };\n}\n\n/** The settings the others depend on, checked first: exchange, connect behaviour, ordering, prefetch, redelivery. */\ntype BasicSettings = Pick<\n ResolvedTransportSettings,\n 'exchange' | 'failOnConnectError' | 'ordered' | 'prefetch' | 'redelivery'\n>;\n\nfunction resolveBasics(options: RabbitMqTransportOptions): BasicSettings {\n const exchange = NonEmptyText.of(options.exchange ?? 'relaybus', 'exchange');\n const failOnConnectError = options.failOnConnectError ?? true;\n if (!failOnConnectError && options.reconnect === false) {\n throw new ConfigurationError(\n 'failOnConnectError=false needs reconnect enabled, otherwise the transport would never connect',\n );\n }\n const ordered = options.ordered ?? false;\n const prefetch = PositiveInteger.of(\n options.prefetch ?? (ordered ? 1 : DEFAULT_PREFETCH),\n 'prefetch',\n );\n if (ordered && prefetch !== 1) {\n throw new ConfigurationError(`ordered consumption needs prefetch 1, received ${prefetch}`);\n }\n const redelivery = createRetryPolicy(options.redelivery, DEFAULT_REDELIVERY);\n return { exchange, failOnConnectError, ordered, prefetch, redelivery };\n}\n\n/** Names, connection, exchanges and queues. */\nfunction resolveTopology(\n options: RabbitMqTransportOptions,\n { exchange, prefetch }: BasicSettings,\n): Pick<\n ResolvedTransportSettings,\n | 'name'\n | 'connect'\n | 'exchange'\n | 'prefetch'\n | 'queuePrefix'\n | 'consumerGroup'\n | 'queue'\n | 'deadLetterExchange'\n | 'deadLetterQueue'\n | 'deliveryLimit'\n> {\n return {\n name: NonEmptyText.of(options.name ?? 'rabbitmq', 'name'),\n connect: resolveConnect(options),\n exchange,\n prefetch,\n queuePrefix: NonEmptyText.of(options.queuePrefix ?? 'relaybus', 'queuePrefix'),\n consumerGroup: NonEmptyText.optional(options.consumerGroup, 'consumerGroup'),\n queue: NonEmptyText.optional(options.queue, 'queue'),\n deadLetterExchange: NonEmptyText.of(\n options.deadLetterExchange ?? `${exchange}.dead`,\n 'deadLetterExchange',\n ),\n deadLetterQueue: NonEmptyText.optional(options.deadLetterQueue, 'deadLetterQueue'),\n deliveryLimit: PositiveInteger.of(\n options.deliveryLimit ?? DEFAULT_DELIVERY_LIMIT,\n 'deliveryLimit',\n ),\n };\n}\n\n/** Handler retries, delayed redelivery and its retry queues. */\nfunction resolveRetries(\n options: RabbitMqTransportOptions,\n { ordered, redelivery }: BasicSettings,\n): Pick<\n ResolvedTransportSettings,\n 'handlerRetry' | 'redelivery' | 'retryLadder' | 'redeliveryMaxAgeMs' | 'ordered'\n> {\n return {\n handlerRetry: createRetryPolicy(options.handlerRetry, DEFAULT_HANDLER_RETRY),\n redelivery,\n retryLadder: ordered ? [] : buildRetryLadder(redelivery),\n redeliveryMaxAgeMs: Milliseconds.positive(\n options.redelivery?.maxAge ?? DEFAULT_REDELIVERY_MAX_AGE,\n 'redelivery.maxAge',\n ),\n ordered,\n };\n}\n\n/** Reconnection, timeouts, the codec and the injected logger and randomness. */\nfunction resolveRuntime(\n options: RabbitMqTransportOptions,\n { failOnConnectError }: BasicSettings,\n): Pick<\n ResolvedTransportSettings,\n | 'reconnect'\n | 'failOnConnectError'\n | 'allowUnroutable'\n | 'publishTimeoutMs'\n | 'shutdownTimeoutMs'\n | 'encode'\n | 'decode'\n | 'logger'\n | 'random'\n> {\n return {\n reconnect: resolveReconnect(options.reconnect),\n failOnConnectError,\n allowUnroutable: options.allowUnroutable ?? false,\n publishTimeoutMs: Milliseconds.positive(options.publishTimeout ?? '30s', 'publishTimeout'),\n shutdownTimeoutMs: Milliseconds.of(options.shutdownTimeout ?? '30s', 'shutdownTimeout'),\n ...resolveCodec(options),\n logger: options.logger ?? console,\n random: options.random ?? Math.random,\n };\n}\n\n/** `<queuePrefix>.<consumerGroup>`, or the explicit queue name. */\nexport function resolveQueueName(settings: ResolvedTransportSettings): string {\n if (settings.queue !== undefined) {\n return settings.queue;\n }\n if (settings.consumerGroup === undefined) {\n throw new ConfigurationError(\n `Transport '${settings.name}' needs 'consumerGroup' or 'queue' to subscribe`,\n );\n }\n return `${settings.queuePrefix}.${settings.consumerGroup}`;\n}\n\n/** The codec of the options; the deprecated `decode` pairs with the default encoding. */\nfunction resolveCodec({\n codec,\n decode,\n}: RabbitMqTransportOptions): Pick<ResolvedTransportSettings, 'encode' | 'decode'> {\n if (decode !== undefined && codec !== undefined) {\n throw new ConfigurationError(\"Give 'codec' or the deprecated 'decode', not both\");\n }\n const chosen =\n decode === undefined ? (codec ?? cloudEventsBinary) : { encode: encodeEnvelope, decode };\n if (chosen === cloudEventsBinary) {\n return { encode: encodeEnvelope, decode: decodeEnvelope };\n }\n return {\n encode: chosen.encode,\n decode: (message) => decodeRabbitMqMessage(chosen, message),\n };\n}\n\nfunction resolveConnect(\n options: RabbitMqTransportOptions,\n): (options: ConnectOptions) => Promise<AmqpConnection> {\n const { url, connect } = options;\n if ((url === undefined) === (connect === undefined)) {\n throw new ConfigurationError(\"Give exactly one of 'url' and 'connect'\");\n }\n if (connect !== undefined) {\n return connect;\n }\n return async ({ signal }) => {\n const amqplib = await import('amqplib');\n // amqplib hands its socket options to net.connect / tls.connect, which take a signal; its types omit it.\n const socketOptions = { signal } as unknown as Parameters<typeof amqplib.connect>[1];\n return amqplib.connect(url!, socketOptions);\n };\n}\n\nfunction resolveReconnect(\n reconnect: ReconnectOptions | false | undefined,\n): RetryPolicy | undefined {\n if (reconnect === false) {\n return undefined;\n }\n return createRetryPolicy({ ...reconnect, attempts: 1 }, DEFAULT_RECONNECT);\n}\n","import type { AmqpChannel } from './amqp-types.js';\n\n/** Names of the broker objects a subscribing transport owns. */\nexport interface ConsumerTopology {\n readonly exchange: string;\n readonly queue: string;\n readonly deadLetterExchange: string;\n readonly deadLetterQueue: string;\n readonly deliveryLimit: number;\n /** Single active consumer, so the queue is consumed strictly in order. */\n readonly ordered: boolean;\n /** TTLs of the retry queues, ascending; empty when ordered. */\n readonly retryDelaysMs: readonly number[];\n /** Routing-key patterns the queue is bound with. */\n readonly destinations: readonly string[];\n}\n\n/** Name of the retry queue that holds messages for `delayMs` before returning them to `queue`. */\nexport function retryQueueName(queue: string, delayMs: number): string {\n return `${queue}.retry.${delayMs}`;\n}\n\n/** Declares the durable topic exchange events are published to. Idempotent. */\nexport async function assertExchange(channel: AmqpChannel, exchange: string): Promise<void> {\n await channel.assertExchange(exchange, 'topic', { durable: true });\n}\n\n/**\n * Declares the consumer side, all durable quorum queues and idempotent:\n *\n * - the main queue with a dead-letter exchange, `x-dead-letter-strategy`\n * `at-least-once` (which requires `x-overflow` `reject-publish`),\n * `x-delivery-limit` as a backstop for crash loops, and optionally\n * `x-single-active-consumer`; bound to the topic exchange once per destination;\n * - one retry queue per delay tier: a queue-level `x-message-ttl`, expired\n * messages dead-lettered through the default exchange back to the main queue;\n * - a direct dead-letter exchange and the dead-letter queue, bound with the main\n * queue's name as routing key.\n *\n * Declaring an existing queue with different arguments makes the broker close\n * the channel (`PRECONDITION_FAILED`); see the README for migrating a queue\n * created by an older version or with other options.\n */\nexport async function assertConsumerTopology(\n channel: AmqpChannel,\n topology: ConsumerTopology,\n): Promise<void> {\n await assertExchange(channel, topology.exchange);\n await channel.assertExchange(topology.deadLetterExchange, 'direct', { durable: true });\n await channel.assertQueue(topology.deadLetterQueue, {\n durable: true,\n arguments: { 'x-queue-type': 'quorum' },\n });\n await channel.bindQueue(topology.deadLetterQueue, topology.deadLetterExchange, topology.queue);\n for (const delayMs of topology.retryDelaysMs) {\n await channel.assertQueue(retryQueueName(topology.queue, delayMs), {\n durable: true,\n arguments: {\n 'x-queue-type': 'quorum',\n 'x-message-ttl': delayMs,\n 'x-dead-letter-exchange': '',\n 'x-dead-letter-routing-key': topology.queue,\n 'x-dead-letter-strategy': 'at-least-once',\n 'x-overflow': 'reject-publish',\n },\n });\n }\n await channel.assertQueue(topology.queue, {\n durable: true,\n arguments: {\n 'x-queue-type': 'quorum',\n 'x-delivery-limit': topology.deliveryLimit,\n 'x-dead-letter-exchange': topology.deadLetterExchange,\n 'x-dead-letter-routing-key': topology.queue,\n 'x-dead-letter-strategy': 'at-least-once',\n 'x-overflow': 'reject-publish',\n ...(topology.ordered ? { 'x-single-active-consumer': true } : {}),\n },\n });\n for (const destination of topology.destinations) {\n await channel.bindQueue(topology.queue, topology.exchange, destination);\n }\n}\n","import {\n computeRetryDelay,\n isRetryableError,\n toErrorInfo,\n type EventEnvelope,\n} from '@relaybus/core';\nimport { abortableSleep } from './abortable-sleep.js';\nimport type { AmqpChannel, AmqpMessage } from './amqp-types.js';\nimport { RabbitMqUnavailableError } from './errors.js';\nimport {\n DEAD_LETTER_ERROR_CODE_HEADER,\n DEAD_LETTER_ERROR_NAME_HEADER,\n DEAD_LETTER_REASON_HEADER,\n FIRST_FAILURE_HEADER,\n ORIGINAL_ROUTING_KEY_HEADER,\n REDELIVERIES_HEADER,\n chooseRetryTier,\n copyForRepublish,\n originalRoutingKey,\n readCounterHeader,\n withOriginalRoutingKey,\n} from './redelivery.js';\nimport type {\n DeadLetterInput,\n ProcessedMessage,\n QueueConsumerSettings,\n RedeliverLaterInput,\n} from './queue-consumer-types.js';\nimport { retryQueueName } from './topology.js';\n\nexport type { ConfirmedRepublish, QueueConsumerSettings } from './queue-consumer-types.js';\n\ntype Settlement = 'ack' | 'requeue' | 'dead-letter';\n\n/**\n * Consumes one queue with manual acknowledgements.\n *\n * A message is acknowledged only after the handler resolved. When the handler\n * fails it is first retried on the same delivery with short backoff\n * (`handlerRetry`). If that does not help, a copy goes to the retry queue whose\n * TTL matches the next backoff step, and the original is acknowledged only\n * after the broker confirmed the copy; the copy returns to the main queue when\n * its TTL expires. This waits out a long outage of the handler's dependency.\n *\n * Malformed messages, non-retryable errors and messages that kept failing for\n * `redeliveryMaxAgeMs` go to the dead-letter exchange through a confirmed copy\n * (carrying the reason, without retry state, so a replay starts fresh) and the\n * original is acknowledged afterwards. If a copy cannot be confirmed the\n * original is requeued or rejected without requeue, which makes the broker\n * dead-letter it; it is never acknowledged unprocessed, so nothing is lost.\n *\n * In ordered mode nothing is moved: the failing message is retried in place with\n * the same backoff, holding the queue.\n */\nexport class QueueConsumer {\n readonly #settings: QueueConsumerSettings;\n readonly #inFlight = new Set<Promise<void>>();\n readonly #stopping = new AbortController();\n #channel: AmqpChannel | undefined;\n #consumerTag: string | undefined;\n\n constructor(settings: QueueConsumerSettings) {\n this.#settings = settings;\n }\n\n /** True while a consumer is registered on a live channel. */\n isActive(): boolean {\n return this.#consumerTag !== undefined;\n }\n\n /**\n * Starts consuming on a channel whose topology is already declared.\n *\n * @throws {RabbitMqUnavailableError} the channel closed while it was being set up\n */\n async attach(channel: AmqpChannel): Promise<void> {\n let closedDuringSetup = false;\n channel.on('error', (error: Error) => {\n this.#settings.logger.warn(\n `[QueueConsumer](attach) Channel error | queue=${this.#settings.queue} error=${error.message}`,\n );\n });\n channel.on('close', () => {\n closedDuringSetup = true;\n if (this.#channel === channel) {\n this.#channel = undefined;\n this.#consumerTag = undefined;\n this.#settings.onConsumerLost('consumer channel closed');\n }\n });\n await channel.prefetch(this.#settings.prefetch);\n const { consumerTag } = await channel.consume(\n this.#settings.queue,\n (message) => this.#receive(channel, message),\n { noAck: false },\n );\n if (closedDuringSetup) {\n throw new RabbitMqUnavailableError(\n `[QueueConsumer](attach) Consumer channel closed while the consumer was being set up | queue=${this.#settings.queue}`,\n );\n }\n this.#channel = channel;\n this.#consumerTag = consumerTag;\n }\n\n /** Forgets the channel without closing it, because its connection is gone. */\n detach(): void {\n this.#channel = undefined;\n this.#consumerTag = undefined;\n }\n\n /**\n * Stops taking messages, aborts pending handler backoff (those messages are\n * requeued), waits up to the shutdown timeout for running handlers, then\n * closes the channel. Unacknowledged messages return to the queue.\n */\n async stop(): Promise<void> {\n this.#stopping.abort();\n const channel = this.#channel;\n const consumerTag = this.#consumerTag;\n this.#channel = undefined;\n this.#consumerTag = undefined;\n if (channel !== undefined && consumerTag !== undefined) {\n await channel.cancel(consumerTag).catch((error: unknown) => {\n this.#settings.logger.warn(\n `[QueueConsumer](stop) Could not cancel consumer | queue=${this.#settings.queue} error=${toErrorInfo(error).message}`,\n );\n });\n }\n await this.#awaitInFlight();\n await channel?.close().catch(() => undefined);\n }\n\n async #awaitInFlight(): Promise<void> {\n if (this.#inFlight.size === 0) {\n return;\n }\n const timeout = new AbortController();\n const timedOut = abortableSleep(this.#settings.shutdownTimeoutMs, timeout.signal);\n await Promise.race([Promise.allSettled([...this.#inFlight]), timedOut]);\n timeout.abort();\n }\n\n #receive(channel: AmqpChannel, message: AmqpMessage | null): void {\n if (message === null) {\n this.#consumerTag = undefined;\n this.#settings.onConsumerLost('consumer cancelled by the broker');\n return;\n }\n const task: Promise<void> = this.#process(channel, message).finally(() => {\n this.#inFlight.delete(task);\n });\n this.#inFlight.add(task);\n }\n\n async #process(channel: AmqpChannel, message: AmqpMessage): Promise<void> {\n const decoded = await this.#decodeOrDeadLetter(channel, message);\n if (decoded === undefined) {\n return;\n }\n const { envelope } = decoded;\n const delivery: ProcessedMessage = {\n channel,\n message,\n envelope,\n redeliveries: readCounterHeader(message, REDELIVERIES_HEADER) ?? 0,\n firstFailureAt: readCounterHeader(message, FIRST_FAILURE_HEADER),\n };\n for (let attempt = 1; ; attempt += 1) {\n try {\n await this.#settings.onMessage(envelope, { destination: message.fields.routingKey });\n this.#settle(channel, { message, settlement: 'ack' });\n return;\n } catch (error) {\n if ((await this.#afterFailure(delivery, { attempt, error })) === 'settled') {\n return;\n }\n }\n }\n }\n\n /** The event of `message`, or undefined after dead-lettering a message that is not one. */\n async #decodeOrDeadLetter(\n channel: AmqpChannel,\n message: AmqpMessage,\n ): Promise<{ readonly envelope: EventEnvelope } | undefined> {\n try {\n return { envelope: this.#settings.decode(withOriginalRoutingKey(message)) };\n } catch (error) {\n this.#settings.logger.error(\n `[QueueConsumer](decodeOrDeadLetter) Dead-lettering malformed message | queue=${this.#settings.queue} routingKey=${message.fields.routingKey} ${describeError(error)}`,\n );\n this.#settings.onInvalidMessage?.({ destination: message.fields.routingKey, error });\n await this.#deadLetter(channel, { message, reason: 'malformed message', error });\n return undefined;\n }\n }\n\n /**\n * Decides what follows a failed attempt: dead-letter a non-retryable error, retry on the same\n * delivery while local attempts remain, else redeliver later. `retry` runs the handler again.\n */\n async #afterFailure(\n delivery: ProcessedMessage,\n { attempt, error }: { readonly attempt: number; readonly error: unknown },\n ): Promise<'retry' | 'settled'> {\n const { channel, message, envelope } = delivery;\n const { queue, handlerRetry } = this.#settings;\n const failure = `queue=${queue} eventId=${envelope.id} attempt=${attempt} ${describeError(error)}`;\n if (!isRetryableError(handlerRetry, error)) {\n this.#settings.logger.error(\n `[QueueConsumer](afterFailure) Dead-lettering message the handler cannot process | ${failure}`,\n );\n await this.#deadLetter(channel, {\n message,\n reason: 'non-retryable handler error',\n error,\n });\n return 'settled';\n }\n if (attempt < handlerRetry.attempts) {\n const delayMs = computeRetryDelay(handlerRetry, attempt, this.#settings.random);\n this.#settings.logger.warn(\n `[QueueConsumer](afterFailure) Handler failed, retrying | ${failure} delayMs=${delayMs}`,\n );\n return this.#waitOrRequeue(delivery, delayMs);\n }\n return this.#afterSpentAttempts(delivery, { failure, error });\n }\n\n /**\n * The local attempts are spent: dead-letter a message that kept failing past `redeliveryMaxAgeMs`,\n * else park it in a retry queue, or, when ordered, wait and retry it in place.\n */\n async #afterSpentAttempts(\n delivery: ProcessedMessage,\n { failure, error }: { readonly failure: string; readonly error: unknown },\n ): Promise<'retry' | 'settled'> {\n const { channel, message } = delivery;\n delivery.redeliveries += 1;\n const now = Date.now();\n delivery.firstFailureAt ??= now;\n const { redeliveries, firstFailureAt } = delivery;\n const delayMs = this.#redeliveryDelay(redeliveries);\n if (now + delayMs - firstFailureAt > this.#settings.redeliveryMaxAgeMs) {\n this.#settings.logger.error(\n `[QueueConsumer](afterSpentAttempts) Dead-lettering message that kept failing | ${failure} redeliveries=${redeliveries - 1} failingForMs=${now - firstFailureAt} maxAgeMs=${this.#settings.redeliveryMaxAgeMs}`,\n );\n await this.#deadLetter(channel, {\n message,\n reason: 'redelivery window exhausted',\n error,\n });\n return 'settled';\n }\n this.#settings.logger.warn(\n `[QueueConsumer](afterSpentAttempts) Handler attempts spent, retrying later | ${failure} redeliveries=${redeliveries} delayMs=${delayMs}`,\n );\n if (!this.#settings.ordered) {\n await this.#redeliverLater(channel, { message, delayMs, redeliveries, firstFailureAt });\n return 'settled';\n }\n return this.#waitOrRequeue(delivery, delayMs);\n }\n\n /** Waits `delayMs` before the next attempt; requeues instead when the consumer stops meanwhile. */\n async #waitOrRequeue(delivery: ProcessedMessage, delayMs: number): Promise<'retry' | 'settled'> {\n if (await this.#interrupted(delayMs)) {\n this.#settle(delivery.channel, { message: delivery.message, settlement: 'requeue' });\n return 'settled';\n }\n return 'retry';\n }\n\n /** The backoff before the next delayed redelivery: a retry queue's TTL, or an exact wait when ordered. */\n #redeliveryDelay(redeliveries: number): number {\n const { redelivery, retryLadder, ordered, random } = this.#settings;\n const delayMs = computeRetryDelay(redelivery, redeliveries, random);\n return ordered ? delayMs : chooseRetryTier(retryLadder, { delayMs, random });\n }\n\n /** Sleeps; true when the consumer is stopping, so the caller must give the message back. */\n async #interrupted(delayMs: number): Promise<boolean> {\n await abortableSleep(delayMs, this.#stopping.signal);\n return this.#stopping.signal.aborted;\n }\n\n /**\n * Parks a copy in the retry queue of `delayMs` and acknowledges the original\n * only once the broker confirmed the copy. When the copy cannot be confirmed\n * the original is requeued after the same delay, so it is neither lost nor\n * hot-looped.\n */\n async #redeliverLater(channel: AmqpChannel, input: RedeliverLaterInput): Promise<void> {\n const { message, delayMs, redeliveries, firstFailureAt } = input;\n const { content, options } = copyForRepublish(message, {\n [REDELIVERIES_HEADER]: String(redeliveries),\n [FIRST_FAILURE_HEADER]: String(firstFailureAt),\n [ORIGINAL_ROUTING_KEY_HEADER]: originalRoutingKey(message),\n });\n try {\n await this.#settings.republish(\n { exchange: '', routingKey: retryQueueName(this.#settings.queue, delayMs) },\n { content, options },\n );\n } catch (error) {\n this.#settings.logger.warn(\n `[QueueConsumer](redeliverLater) Could not park the message in the retry queue, requeueing it | queue=${this.#settings.queue} delayMs=${delayMs} error=${toErrorInfo(error).message}`,\n );\n await this.#interrupted(delayMs);\n this.#settle(channel, { message, settlement: 'requeue' });\n return;\n }\n this.#settle(channel, { message, settlement: 'ack' });\n }\n\n /**\n * Moves the message to the dead-letter queue through a confirmed copy that\n * carries the reason and no retry state. If the copy cannot be confirmed the\n * message is rejected without requeue, which makes the broker dead-letter it\n * (at-least-once), so it still ends up in the dead-letter queue.\n */\n async #deadLetter(channel: AmqpChannel, input: DeadLetterInput): Promise<void> {\n const { message, reason, error } = input;\n const { name, code } = toErrorInfo(error);\n const { content, options } = copyForRepublish(message, {\n [DEAD_LETTER_REASON_HEADER]: reason,\n [DEAD_LETTER_ERROR_NAME_HEADER]: name,\n ...(code === undefined ? {} : { [DEAD_LETTER_ERROR_CODE_HEADER]: code }),\n });\n try {\n await this.#settings.republish(\n { exchange: this.#settings.deadLetterExchange, routingKey: this.#settings.queue },\n { content, options },\n );\n } catch (error) {\n this.#settings.logger.warn(\n `[QueueConsumer](deadLetter) Could not publish to the dead-letter exchange, leaving it to the broker | queue=${this.#settings.queue} error=${toErrorInfo(error).message}`,\n );\n this.#settle(channel, { message, settlement: 'dead-letter' });\n return;\n }\n this.#settle(channel, { message, settlement: 'ack' });\n }\n\n #settle(\n channel: AmqpChannel,\n { message, settlement }: { readonly message: AmqpMessage; readonly settlement: Settlement },\n ): void {\n try {\n if (settlement === 'ack') {\n channel.ack(message);\n } else {\n channel.nack(message, false, settlement === 'requeue');\n }\n } catch (error) {\n // The channel is gone; the broker redelivers the message and the inbox drops the duplicate.\n this.#settings.logger.warn(\n `[QueueConsumer](settle) Could not ${settlement} message, the broker will redeliver it | queue=${this.#settings.queue} error=${toErrorInfo(error).message}`,\n );\n }\n }\n}\n\n/** Log fields of an error: its message, class name and, for relaybus errors, its code. */\nfunction describeError(error: unknown): string {\n const { message, name, code } = toErrorInfo(error);\n return `error=${message} errorName=${name}${code === undefined ? '' : ` code=${code}`}`;\n}\n","/** Runs async tasks one after another, in submission order, even when one fails. */\nexport class SerialQueue {\n #tail: Promise<unknown> = Promise.resolve();\n\n run<TResult>(task: () => Promise<TResult>): Promise<TResult> {\n const result = this.#tail.then(task);\n this.#tail = result.catch(() => undefined);\n return result;\n }\n}\n","import { ConfigurationError, type CloseOptions, type EventEnvelope } from '@relaybus/core';\nimport { SubscribingTransport, type TransportSubscription } from '@relaybus/core/internal';\nimport type { AmqpConnection, AmqpMessage } from './amqp-types.js';\nimport {\n ConfirmedPublishing,\n recordUnroutable,\n unroutableKey,\n type Publisher,\n} from './confirmed-publishing.js';\nimport { ConnectionSupervisor } from './connection-supervisor.js';\nimport { RabbitMqUnavailableError } from './errors.js';\nimport {\n resolveQueueName,\n resolveSettings,\n type RabbitMqTransportOptions,\n type ResolvedTransportSettings,\n} from './options.js';\nimport { QueueConsumer } from './queue-consumer.js';\nimport { SerialQueue } from './serial-queue.js';\nimport { assertConsumerTopology, assertExchange, type ConsumerTopology } from './topology.js';\nimport { assertShortString } from './wire-format.js';\n\ninterface LiveConnection {\n readonly connection: AmqpConnection;\n readonly publisher: Publisher;\n}\n\ninterface Subscription {\n readonly topology: ConsumerTopology;\n readonly consumer: QueueConsumer;\n}\n\n/**\n * RabbitMQ {@link Transport} built on amqplib.\n *\n * Publishing: each event goes to a durable topic exchange as a persistent,\n * mandatory message with the destination as routing key. `publish` resolves\n * only after the broker confirmed it was persisted and routed to a queue, and\n * rejects when the transport is disconnected, the broker nacks, the message is\n * unroutable or no confirm arrives in time. It never drops a message silently,\n * so the outbox retries the delivery.\n *\n * Subscribing: one durable quorum queue per consumer group, bound to the\n * destinations (routing-key patterns such as `orders.*`). A message is\n * acknowledged only after the handler resolved. A failing handler is retried\n * on the same delivery, then through retry queues with growing delays (see\n * `redelivery`), and finally dead-lettered after the retry window; poison\n * messages are dead-lettered at once. Nothing is lost on the way.\n *\n * Reconnection: after a connection or channel loss the transport reconnects\n * with capped, jittered backoff and restores channels, topology and the\n * consumer. Events published meanwhile are rejected, and therefore retried by\n * the outbox, rather than buffered in memory.\n */\nexport class RabbitMqTransport extends SubscribingTransport {\n readonly name: string;\n readonly system = 'rabbitmq';\n readonly #settings: ResolvedTransportSettings;\n readonly #supervisor: ConnectionSupervisor;\n readonly #publishing: ConfirmedPublishing;\n /** Serializes topology work so a subscription never races a reconnect. */\n readonly #topologyWork = new SerialQueue();\n #live: LiveConnection | undefined;\n #subscription: Subscription | undefined;\n #closing: Promise<void> | undefined;\n\n constructor(options: RabbitMqTransportOptions) {\n super();\n this.#settings = resolveSettings(options);\n this.name = this.#settings.name;\n this.#publishing = new ConfirmedPublishing(this.name, this.#settings.publishTimeoutMs);\n this.#supervisor = new ConnectionSupervisor({\n connect: this.#settings.connect,\n reconnect: this.#settings.reconnect,\n onConnected: (connection) => this.#establishChannels(connection),\n onDisconnected: () => this.#forgetConnection(),\n logger: this.#settings.logger,\n random: this.#settings.random,\n });\n }\n\n /**\n * True while the connection is open and publishing and consuming are set up.\n * Use it for readiness probes.\n */\n isConnected(): boolean {\n return this.#supervisor.isConnected();\n }\n\n /**\n * True when the transport can publish and, once subscribed, is consuming: the\n * connection is up, its channels are open and the consumer is registered. False while reconnecting and after a cancelled consumer.\n */\n isReady(): boolean {\n return (\n this.#supervisor.isConnected() &&\n this.#live !== undefined &&\n (this.#subscription === undefined || this.#subscription.consumer.isActive())\n );\n }\n\n /** Connects to the broker. Rejects when it is unreachable unless `failOnConnectError` is false. */\n async connect(): Promise<void> {\n await this.#supervisor.start(this.#settings.failOnConnectError);\n }\n\n /**\n * Publishes to the exchange with `destination` as routing key and resolves\n * after the broker confirmed the message.\n *\n * @throws {UnserializablePayloadError} the payload is not representable as JSON (never retried)\n * @throws {AmqpLimitExceededError} the event id, a header name or `destination` exceeds 255 bytes (never retried)\n * @throws {RabbitMqUnavailableError} not connected, channel lost, or confirm timed out\n * @throws {RabbitMqPublishRejectedError} the broker nacked the message\n * @throws {UnroutableMessageError} no queue is bound to `destination` (unless `allowUnroutable`)\n * @throws whatever the `codec`'s `encode` throws, such as {@link RabbitMqUnencodableEventError}\n */\n async publish(envelope: EventEnvelope, destination: string): Promise<void> {\n assertShortString('Destination (routing key)', destination);\n const { content, options } = this.#settings.encode(envelope);\n await this.#publishing.publish(this.#live?.publisher, {\n exchange: this.#settings.exchange,\n routingKey: destination,\n content,\n options,\n mandatory: !this.#settings.allowUnroutable,\n });\n }\n\n /**\n * Binds one durable quorum queue to `destinations` and delivers its messages\n * to `onMessage`. Call it once per transport; give each subscription its own\n * transport instance, with its own `name` and `consumerGroup`.\n */\n protected async openSubscription({\n destinations,\n onMessage,\n hooks,\n }: TransportSubscription): Promise<void> {\n if (this.#subscription !== undefined) {\n throw new ConfigurationError(\n `Transport '${this.name}' already has a subscription; create another transport for another consumer group`,\n );\n }\n if (destinations.length === 0) {\n throw new ConfigurationError(`Transport '${this.name}' needs at least one destination`);\n }\n const queue = resolveQueueName(this.#settings);\n const subscription: Subscription = {\n topology: this.#topologyOf(queue, destinations),\n consumer: this.#createConsumer(queue, { onMessage, hooks }),\n };\n await this.#topologyWork.run(async () => {\n this.#subscription = subscription;\n if (this.#live !== undefined) {\n await this.#startConsuming(this.#live.connection, subscription);\n }\n });\n }\n\n #topologyOf(queue: string, destinations: readonly string[]): ConsumerTopology {\n return {\n exchange: this.#settings.exchange,\n queue,\n deadLetterExchange: this.#settings.deadLetterExchange,\n deadLetterQueue: this.#settings.deadLetterQueue ?? `${queue}.dead`,\n deliveryLimit: this.#settings.deliveryLimit,\n ordered: this.#settings.ordered,\n retryDelaysMs: this.#settings.retryLadder,\n destinations,\n };\n }\n\n #createConsumer(\n queue: string,\n { onMessage, hooks }: Pick<TransportSubscription, 'onMessage' | 'hooks'>,\n ): QueueConsumer {\n return new QueueConsumer({\n queue,\n prefetch: this.#settings.prefetch,\n handlerRetry: this.#settings.handlerRetry,\n redelivery: this.#settings.redelivery,\n retryLadder: this.#settings.retryLadder,\n redeliveryMaxAgeMs: this.#settings.redeliveryMaxAgeMs,\n ordered: this.#settings.ordered,\n deadLetterExchange: this.#settings.deadLetterExchange,\n republish: ({ exchange, routingKey }, { content, options }) =>\n this.#publishing.publish(this.#live?.publisher, {\n exchange,\n routingKey,\n content,\n options,\n mandatory: true,\n }),\n shutdownTimeoutMs: this.#settings.shutdownTimeoutMs,\n onMessage,\n ...(hooks === undefined ? {} : { onInvalidMessage: hooks.onInvalidMessage }),\n decode: this.#settings.decode,\n onConsumerLost: (reason) => this.#supervisor.recover(reason),\n logger: this.#settings.logger,\n random: this.#settings.random,\n });\n }\n\n /**\n * Stops consuming, waits up to `shutdownTimeout` for running handlers\n * (messages still being retried go back to the queue), then closes the\n * channels and the connection. Once `options.signal` aborts (the bus shutdown deadline passed),\n * the connection's socket is destroyed instead of waiting for the broker.\n */\n async close(options: CloseOptions = {}): Promise<void> {\n const { signal } = options;\n const force = (): void => this.#supervisor.forceClose();\n if (signal?.aborted === true) {\n force();\n }\n signal?.addEventListener('abort', force, { once: true });\n try {\n // A second call shares the work of the first, and its signal can still cut the connection.\n this.#closing ??= this.#supervisor.close(() =>\n this.#topologyWork.run(async () => {\n const live = this.#live;\n this.#live = undefined;\n await this.#subscription?.consumer.stop();\n await live?.publisher.channel.close().catch(() => undefined);\n }),\n );\n await this.#closing;\n } finally {\n signal?.removeEventListener('abort', force);\n }\n }\n\n async #establishChannels(connection: AmqpConnection): Promise<void> {\n await this.#topologyWork.run(async () => {\n const channel = await connection.createConfirmChannel();\n const publisher: Publisher = { channel, unroutable: new Map(), closed: false };\n channel.on('error', (error: Error) => {\n this.#settings.logger.warn(\n `[RabbitMqTransport](establishChannels) Publisher channel error | transport=${this.name} error=${error.message}`,\n );\n });\n channel.on('close', () => {\n publisher.closed = true;\n if (this.#live?.publisher === publisher) {\n this.#supervisor.recover('publisher channel closed');\n }\n });\n channel.on('return', (message: AmqpMessage) => {\n recordUnroutable(\n publisher.unroutable,\n unroutableKey(message.properties.messageId, message.fields.routingKey),\n );\n });\n await assertExchange(channel, this.#settings.exchange);\n if (this.#subscription !== undefined) {\n await this.#startConsuming(connection, this.#subscription);\n }\n if (publisher.closed) {\n // The close came before `live` was set, so nothing reacted to it.\n throw new RabbitMqUnavailableError(\n `[RabbitMqTransport](establishChannels) Publisher channel closed while the transport was being set up | transport=${this.name}`,\n );\n }\n this.#live = { connection, publisher };\n });\n }\n\n async #startConsuming(connection: AmqpConnection, subscription: Subscription): Promise<void> {\n const channel = await connection.createChannel();\n await assertConsumerTopology(channel, subscription.topology);\n await subscription.consumer.attach(channel);\n }\n\n #forgetConnection(): void {\n this.#live = undefined;\n this.#subscription?.consumer.detach();\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/errors.ts","../src/confirmed-publishing.ts","../src/abortable-sleep.ts","../src/connection-supervisor.ts","../src/json-payload.ts","../src/wire-format.ts","../src/inbound-decoders.ts","../src/codecs.ts","../src/redelivery.ts","../src/options.ts","../src/topology.ts","../src/queue-consumer.ts","../src/serial-queue.ts","../src/rabbitmq-transport.ts"],"names":["RelayBusError","NonRetryableError","schedule","systemClock","toErrorInfo","computeRetryDelay","writeStructuredCloudEvent","MILLISECONDS_PER_SECOND","createCloudEventReaders","SPEC_VERSION","mediaTypeOf","isJsonObject","parseTime","assertEventType","DecodedEventReader","text","observeRejection","createJsonEnvelopeFormat","mergeWireTypes","ConfigurationError","NonEmptyText","PositiveInteger","createRetryPolicy","Milliseconds","isRetryableError","error","SubscribingTransport","WireTypesUnsupportedError","withDeclaredWireTypes"],"mappings":"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","file":"index.cjs","sourcesContent":["import { NonRetryableError, RelayBusError } from '@relaybus/core';\n\n/**\n * The broker cannot take or confirm a message right now: the transport is not\n * connected, was closed, lost its channel, or the confirm did not arrive in time.\n * Always retryable; the outbox keeps the delivery and tries again.\n */\nexport class RabbitMqUnavailableError extends RelayBusError {\n override name = 'RabbitMqUnavailableError';\n override readonly code: string = 'RELAYBUS_RABBITMQ_UNAVAILABLE';\n}\n\n/** The broker negatively acknowledged a published message. Retryable. */\nexport class RabbitMqPublishRejectedError extends RelayBusError {\n override name = 'RabbitMqPublishRejectedError';\n override readonly code: string = 'RELAYBUS_RABBITMQ_PUBLISH_REJECTED';\n}\n\n/**\n * The broker accepted the message but no queue is bound to its routing key, so\n * it would have been discarded. Retryable: it succeeds once a consumer binds.\n */\nexport class UnroutableMessageError extends RelayBusError {\n override name = 'UnroutableMessageError';\n override readonly code: string = 'RELAYBUS_RABBITMQ_UNROUTABLE_MESSAGE';\n}\n\n/** A received message is not a valid relaybus CloudEvent. It is dead-lettered. */\nexport class MalformedMessageError extends RelayBusError {\n override name = 'MalformedMessageError';\n override readonly code: string = 'RELAYBUS_RABBITMQ_MALFORMED_MESSAGE';\n}\n\n/**\n * The payload of an event cannot be represented as JSON without losing or\n * changing data (`undefined`, functions, symbols, BigInt, NaN, Infinity, Dates,\n * Maps, class instances, cycles). Never retried: the payload will not change.\n */\nexport class UnserializablePayloadError extends NonRetryableError {\n override name = 'UnserializablePayloadError';\n override readonly code: string = 'RELAYBUS_RABBITMQ_UNSERIALIZABLE_PAYLOAD';\n}\n\n/**\n * A value exceeds a protocol limit of AMQP 0-9-1, for example an event id or a\n * routing key longer than the 255 bytes of a short string. Never retried.\n */\nexport class AmqpLimitExceededError extends NonRetryableError {\n override name = 'AmqpLimitExceededError';\n override readonly code: string = 'RELAYBUS_RABBITMQ_AMQP_LIMIT_EXCEEDED';\n}\n\n/**\n * An event the configured codec cannot write: a header name the format\n * reserves, or a type a fixed-type route does not carry. Never retried.\n */\nexport class RabbitMqUnencodableEventError extends NonRetryableError {\n override name = 'RabbitMqUnencodableEventError';\n override readonly code: string = 'RELAYBUS_RABBITMQ_UNENCODABLE_EVENT';\n}\n","import { systemClock, toErrorInfo } from '@relaybus/core';\nimport { schedule, type CancelTimer } from '@relaybus/core/internal';\nimport type { AmqpConfirmChannel, AmqpPublishOptions } from './amqp-types.js';\nimport {\n RabbitMqPublishRejectedError,\n RabbitMqUnavailableError,\n UnroutableMessageError,\n} from './errors.js';\n\n/** Publisher channel plus the broker returns not yet matched with their confirm. */\nexport interface Publisher {\n readonly channel: AmqpConfirmChannel;\n readonly unroutable: Map<string, number>;\n /** Set when the channel closed, also while the transport was still being set up. */\n closed: boolean;\n}\n\n/** One message to publish and wait for the broker's confirm. */\nexport type PublishConfirmedInput = {\n readonly exchange: string;\n readonly routingKey: string;\n readonly content: Buffer;\n readonly options: AmqpPublishOptions;\n /** Ask the broker to return the message when no queue is bound to its routing key. */\n readonly mandatory: boolean;\n};\n\n/** amqplib reports a negative acknowledgement with this exact message. */\nconst NACK_MESSAGE = 'message nacked';\n\n/** The event and destination a publish error names. */\ntype PublishTarget = { readonly eventId: string; readonly destination: string };\n\n/** How one pending publish settles. */\ntype PendingConfirm = PublishTarget & {\n readonly publisher: Publisher;\n readonly returnKey: string;\n readonly cancelTimeout: CancelTimer;\n readonly resolve: () => void;\n readonly reject: (error: Error) => void;\n};\n\n/**\n * Publishes on a confirm channel and resolves only after the broker confirmed the message was\n * persisted and routed to a queue; rejects when not connected, nacked, unroutable or unconfirmed\n * within the publish timeout. It never drops a message silently.\n */\nexport class ConfirmedPublishing {\n readonly #transportName: string;\n readonly #publishTimeoutMs: number;\n\n constructor(transportName: string, publishTimeoutMs: number) {\n this.#transportName = transportName;\n this.#publishTimeoutMs = publishTimeoutMs;\n }\n\n async publish(publisher: Publisher | undefined, input: PublishConfirmedInput): Promise<void> {\n const { exchange, routingKey, content, options, mandatory } = input;\n const eventId = options.messageId ?? 'unknown';\n if (publisher === undefined) {\n throw new RabbitMqUnavailableError(\n `[RabbitMqTransport](publish) Not connected to the broker | transport=${this.#transportName} destination=${routingKey}`,\n );\n }\n const returnKey = unroutableKey(options.messageId, routingKey);\n const target = { eventId, destination: routingKey };\n await new Promise<void>((resolve, reject) => {\n const cancelTimeout = this.#startTimeout(target, reject);\n const pending = { ...target, publisher, returnKey, cancelTimeout, resolve, reject };\n try {\n publisher.channel.publish(\n exchange,\n routingKey,\n content,\n { ...options, mandatory },\n (error) => this.#confirmed(pending, error),\n );\n } catch (error) {\n cancelTimeout();\n reject(this.#toPublishError(error, target));\n }\n });\n }\n\n #startTimeout(\n { eventId, destination }: PublishTarget,\n reject: (error: Error) => void,\n ): CancelTimer {\n return schedule(systemClock, {\n run: () => {\n reject(\n new RabbitMqUnavailableError(\n `[RabbitMqTransport](publish) No broker confirm within ${this.#publishTimeoutMs}ms | transport=${this.#transportName} eventId=${eventId} destination=${destination}`,\n ),\n );\n },\n delayMs: this.#publishTimeoutMs,\n });\n }\n\n /** The broker's confirm (or nack) of one message arrived. */\n #confirmed(pending: PendingConfirm, error: Error | null | undefined): void {\n pending.cancelTimeout();\n const returned = takeUnroutable(pending.publisher.unroutable, pending.returnKey);\n if (error) {\n pending.reject(this.#toPublishError(error, pending));\n } else if (returned) {\n pending.reject(\n new UnroutableMessageError(\n `[RabbitMqTransport](publish) No queue is bound to the routing key | transport=${this.#transportName} eventId=${pending.eventId} destination=${pending.destination}`,\n ),\n );\n } else {\n pending.resolve();\n }\n }\n\n #toPublishError(error: unknown, { eventId, destination }: PublishTarget): Error {\n const { message } = toErrorInfo(error);\n const detail = `transport=${this.#transportName} eventId=${eventId} destination=${destination} error=${message}`;\n return message === NACK_MESSAGE\n ? new RabbitMqPublishRejectedError(\n `[RabbitMqTransport](publish) Broker nacked the message | ${detail}`,\n { cause: error },\n )\n : new RabbitMqUnavailableError(`[RabbitMqTransport](publish) Publish failed | ${detail}`, {\n cause: error,\n });\n }\n}\n\n/** Matches a broker return with the publish it belongs to: message id and routing key. */\nexport function unroutableKey(messageId: unknown, routingKey: string): string {\n return `${String(messageId)}\\n${routingKey}`;\n}\n\nexport function recordUnroutable(unroutable: Map<string, number>, key: string): void {\n unroutable.set(key, (unroutable.get(key) ?? 0) + 1);\n}\n\nfunction takeUnroutable(unroutable: Map<string, number>, key: string): boolean {\n const count = unroutable.get(key);\n if (count === undefined) {\n return false;\n }\n if (count === 1) {\n unroutable.delete(key);\n } else {\n unroutable.set(key, count - 1);\n }\n return true;\n}\n","import { systemClock } from '@relaybus/core';\nimport { schedule } from '@relaybus/core/internal';\n\n/** Resolves after `milliseconds`, or as soon as `signal` aborts (immediately when it already has). Never rejects. */\nexport function abortableSleep(milliseconds: number, signal: AbortSignal): Promise<void> {\n if (signal.aborted) {\n return Promise.resolve();\n }\n return new Promise((resolve) => {\n const finish = (): void => {\n cancel();\n signal.removeEventListener('abort', finish);\n resolve();\n };\n const cancel = schedule(systemClock, { run: finish, delayMs: milliseconds });\n signal.addEventListener('abort', finish, { once: true });\n });\n}\n","import {\n computeRetryDelay,\n toErrorInfo,\n type RelayBusLogger,\n type RetryPolicy,\n} from '@relaybus/core';\nimport { abortableSleep } from './abortable-sleep.js';\nimport type { AmqpConnection } from './amqp-types.js';\nimport { RabbitMqUnavailableError } from './errors.js';\nimport type { ConnectOptions } from './options.js';\n\nexport interface ConnectionSupervisorSettings {\n readonly connect: (options: ConnectOptions) => Promise<AmqpConnection>;\n /** Backoff between attempts, or undefined to never reconnect. */\n readonly reconnect: RetryPolicy | undefined;\n /** Creates channels and topology on a fresh connection. A rejection discards the connection. */\n readonly onConnected: (connection: AmqpConnection) => Promise<void>;\n /** The connection is gone or was discarded: drop everything that referenced it. */\n readonly onDisconnected: () => void;\n readonly logger: RelayBusLogger;\n readonly random: () => number;\n}\n\n/**\n * Owns the broker connection. amqplib does not reconnect, so after a connection\n * loss this class retries with capped, jittered backoff until `onConnected`\n * succeeds, and `close` stops it. It reports ready only once `onConnected` has\n * finished, so callers never use half-built channels.\n */\nexport class ConnectionSupervisor {\n readonly #settings: ConnectionSupervisorSettings;\n readonly #stop = new AbortController();\n /** Aborted by `forceClose`: destroys a socket that is still connecting. */\n readonly #force = new AbortController();\n /** Resolves on `forceClose`: closing stops waiting for the broker. */\n readonly #forcing = new Promise<void>((resolve) => {\n this.#force.signal.addEventListener('abort', () => resolve(), { once: true });\n });\n #current: AmqpConnection | undefined;\n /** Connections being closed, until their closing handshake finishes. */\n readonly #closing = new Set<AmqpConnection>();\n /** Set by `forceClose`: connections are cut instead of closed. */\n #forced = false;\n #ready = false;\n #started = false;\n #closed = false;\n #reconnecting: Promise<void> | undefined;\n\n constructor(settings: ConnectionSupervisorSettings) {\n this.#settings = settings;\n }\n\n /** True while a connection is open and `onConnected` has completed for it. */\n isConnected(): boolean {\n return this.#ready;\n }\n\n /**\n * Connects once. When that fails it rejects if `failOnError`, otherwise it\n * resolves and keeps trying in the background. Does nothing when already started.\n */\n async start(failOnError: boolean): Promise<void> {\n if (this.#started) {\n return;\n }\n if (this.#closed) {\n throw new RabbitMqUnavailableError('[ConnectionSupervisor](start) Transport is closed');\n }\n try {\n await this.#establish();\n this.#started = true;\n } catch (error) {\n if (failOnError) {\n throw error;\n }\n this.#settings.logger.warn(\n `[ConnectionSupervisor](start) Broker unreachable, retrying in the background | error=${toErrorInfo(error).message}`,\n );\n this.#started = true;\n this.#startReconnecting();\n }\n }\n\n /**\n * Drops the current connection because one of its channels failed, then\n * reconnects. Closing the channel alone would leave topology half-restored.\n */\n recover(reason: string): void {\n const connection = this.#current;\n if (connection === undefined) {\n return;\n }\n this.#handleLoss(connection, reason);\n void this.#closeConnection(connection);\n }\n\n /**\n * Stops reconnecting, runs `beforeDisconnect` while the connection is still\n * open (to drain consumers) and closes the connection.\n */\n async close(beforeDisconnect: () => Promise<void>): Promise<void> {\n this.#closed = true;\n this.#stop.abort();\n // Once forced, nothing waits for the broker: draining and the closing handshake are cut short.\n await Promise.race([this.#reconnecting, this.#forcing]);\n try {\n await Promise.race([beforeDisconnect(), this.#forcing]);\n } finally {\n const connection = this.#current;\n this.#current = undefined;\n this.#ready = false;\n if (connection !== undefined) {\n await this.#closeConnection(connection);\n }\n }\n }\n\n /**\n * Stops reconnecting and cuts every connection, open or closing, without the closing handshake. A\n * connection that finishes opening afterwards is cut at once.\n */\n forceClose(): void {\n this.#closed = true;\n this.#forced = true;\n this.#stop.abort();\n this.#force.abort();\n for (const connection of [this.#current, ...this.#closing]) {\n if (connection !== undefined) {\n destroySocket(connection);\n }\n }\n }\n\n /** Closes a connection, which `forceClose` can cut until the broker answered; cuts it once forced. */\n async #closeConnection(connection: AmqpConnection): Promise<void> {\n if (this.#forced) {\n destroySocket(connection);\n return;\n }\n this.#closing.add(connection);\n await connection.close().catch(() => undefined);\n this.#closing.delete(connection);\n }\n\n async #establish(): Promise<void> {\n const connection = await this.#settings.connect({ signal: this.#force.signal });\n // Before anything can cut it: an 'error' nobody listens to would crash the process.\n connection.on('error', (error: Error) => {\n this.#settings.logger.warn(\n `[ConnectionSupervisor](establish) Connection error | error=${error.message}`,\n );\n });\n if (this.#closed) {\n // Opened after the transport closed: nobody would use or close it.\n await this.#closeConnection(connection);\n throw new RabbitMqUnavailableError('[ConnectionSupervisor](establish) Transport is closed');\n }\n connection.on('close', (error?: Error) => {\n this.#handleLoss(connection, error?.message ?? 'closed by peer');\n });\n this.#current = connection;\n try {\n await this.#settings.onConnected(connection);\n if (this.#current !== connection) {\n throw new RabbitMqUnavailableError(\n 'Connection was lost while the topology was being set up',\n );\n }\n } catch (error) {\n await this.#discard(connection);\n throw error;\n }\n this.#ready = true;\n }\n\n async #discard(connection: AmqpConnection): Promise<void> {\n if (this.#current === connection) {\n this.#current = undefined;\n }\n this.#settings.onDisconnected();\n await this.#closeConnection(connection);\n }\n\n #handleLoss(connection: AmqpConnection, reason: string): void {\n if (connection !== this.#current) {\n return;\n }\n this.#current = undefined;\n this.#ready = false;\n this.#settings.logger.warn(\n `[ConnectionSupervisor](handleLoss) Connection lost | reason=${reason}`,\n );\n this.#settings.onDisconnected();\n this.#startReconnecting();\n }\n\n #startReconnecting(): void {\n if (\n this.#settings.reconnect === undefined ||\n this.#closed ||\n !this.#started ||\n this.#reconnecting !== undefined\n ) {\n return;\n }\n const policy = this.#settings.reconnect;\n this.#reconnecting = this.#reconnectUntilConnected(policy).finally(() => {\n this.#reconnecting = undefined;\n });\n }\n\n async #reconnectUntilConnected(policy: RetryPolicy): Promise<void> {\n for (let attempt = 1; !this.#closed; attempt += 1) {\n const delayMs = computeRetryDelay(policy, attempt, this.#settings.random);\n this.#settings.logger.log(\n `[ConnectionSupervisor](reconnectUntilConnected) Reconnecting | attempt=${attempt} delayMs=${delayMs}`,\n );\n await abortableSleep(delayMs, this.#stop.signal);\n if (this.#closed) {\n return;\n }\n try {\n await this.#establish();\n this.#settings.logger.log(\n `[ConnectionSupervisor](reconnectUntilConnected) Reconnected | attempt=${attempt}`,\n );\n return;\n } catch (error) {\n this.#settings.logger.warn(\n `[ConnectionSupervisor](reconnectUntilConnected) Attempt failed | attempt=${attempt} error=${toErrorInfo(error).message}`,\n );\n }\n }\n }\n}\n\n/**\n * Destroys the socket under an amqplib connection (the channel model keeps it in fields its types\n * omit). With an error, so amqplib sees a socket error and runs its terminal cleanup: it stops\n * heartbeating, fails pending channel operations and emits `close`.\n */\nfunction destroySocket(connection: AmqpConnection): void {\n const model = connection as {\n readonly connection?: { readonly stream?: { destroy(error: Error): void } };\n };\n model.connection?.stream?.destroy(\n new RabbitMqUnavailableError('Connection cut: the shutdown deadline passed'),\n );\n}\n","import { UnserializablePayloadError } from './errors.js';\n\n/**\n * Throws {@link UnserializablePayloadError} unless `JSON.stringify` represents\n * `payload` faithfully. Only `null`, strings, booleans, finite numbers, arrays\n * and plain objects built from those are accepted. Everything `JSON.stringify`\n * would silently drop (`undefined`, functions, symbols, symbol keys, array holes),\n * convert (NaN and Infinity to `null`, Dates to strings, Maps and Sets to `{}`,\n * class instances to their own properties) or reject late (BigInt, cycles) is\n * refused up front, naming the offending path.\n */\nexport function assertJsonPayload(payload: unknown, eventId: string): void {\n visit(payload, { path: '$', ancestors: new Set(), eventId });\n}\n\nfunction visit(\n value: unknown,\n {\n path,\n ancestors,\n eventId,\n }: { readonly path: string; readonly ancestors: Set<object>; readonly eventId: string },\n): void {\n switch (typeof value) {\n case 'string':\n case 'boolean':\n return;\n case 'number':\n if (!Number.isFinite(value)) {\n throw refuse(eventId, { path, reason: `is ${value}, which JSON turns into null` });\n }\n return;\n case 'object':\n if (value !== null) {\n visitObject(value, { path, ancestors, eventId });\n }\n return;\n default:\n throw refuse(eventId, { path, reason: `is ${typeof value}, which JSON cannot represent` });\n }\n}\n\nfunction visitObject(\n value: object,\n {\n path,\n ancestors,\n eventId,\n }: { readonly path: string; readonly ancestors: Set<object>; readonly eventId: string },\n): void {\n if (ancestors.has(value)) {\n throw refuse(eventId, { path, reason: 'is a circular reference' });\n }\n ancestors.add(value);\n if (Array.isArray(value)) {\n visitArray(value, { path, ancestors, eventId });\n } else {\n visitPlainObject(value, { path, ancestors, eventId });\n }\n ancestors.delete(value);\n}\n\n/** Where a visit is: the path so far, the objects above it and the event it belongs to. */\ntype VisitPlace = {\n readonly path: string;\n readonly ancestors: Set<object>;\n readonly eventId: string;\n};\n\nfunction visitArray(value: unknown[], { path, ancestors, eventId }: VisitPlace): void {\n for (let index = 0; index < value.length; index += 1) {\n if (!(index in value)) {\n throw refuse(eventId, {\n path: `${path}[${index}]`,\n reason: 'is an array hole, which JSON turns into null',\n });\n }\n visit(value[index], { path: `${path}[${index}]`, ancestors, eventId });\n }\n}\n\nfunction visitPlainObject(value: object, { path, ancestors, eventId }: VisitPlace): void {\n const prototype = Object.getPrototypeOf(value) as object | null;\n if (prototype !== Object.prototype && prototype !== null) {\n throw refuse(eventId, {\n path,\n reason: 'is not a plain object (class instance, Date, Map or Set)',\n });\n }\n if (Object.getOwnPropertySymbols(value).length > 0) {\n throw refuse(eventId, { path, reason: 'has a symbol key, which JSON drops' });\n }\n for (const key of Object.keys(value)) {\n visit((value as Record<string, unknown>)[key], {\n path: `${path}.${key}`,\n ancestors,\n eventId,\n });\n }\n}\n\nfunction refuse(\n eventId: string,\n { path, reason }: { readonly path: string; readonly reason: string },\n): UnserializablePayloadError {\n return new UnserializablePayloadError(\n `Event ${eventId} has a payload JSON cannot represent faithfully: ${path} ${reason}`,\n );\n}\n","import type { EventEnvelope, EventHeaders } from '@relaybus/core';\nimport { writeStructuredCloudEvent } from '@relaybus/core/internal';\nimport type { AmqpMessage, AmqpPublishOptions } from './amqp-types.js';\nimport {\n AmqpLimitExceededError,\n MalformedMessageError,\n RabbitMqUnencodableEventError,\n} from './errors.js';\nimport { assertJsonPayload } from './json-payload.js';\n\n/** AMQP `timestamp` properties count seconds. */\nconst MILLISECONDS_PER_SECOND = 1_000;\n\n/**\n * Wire format: CloudEvents 1.0 in binary content mode, following the CloudEvents\n * AMQP protocol binding adapted to RabbitMQ's AMQP 0-9-1.\n *\n * - Body: the JSON-encoded payload (`contentType` `application/json`).\n * - Headers `cloudEvents:specversion`, `cloudEvents:id`, `cloudEvents:type`,\n * `cloudEvents:source`, `cloudEvents:time` (RFC 3339, millisecond precision),\n * `cloudEvents:datacontenttype`, and when present `cloudEvents:subject` (the\n * key) and the extension attributes `cloudEvents:causationid` and\n * `cloudEvents:correlationid`.\n * - AMQP properties mirror the same values for broker tooling: `messageId`,\n * `type`, `appId` (source), `correlationId`, `timestamp` (seconds), plus\n * `deliveryMode` 2 (persistent).\n * - Event headers travel as `relaybus:<name>` message headers, so they cannot\n * collide with CloudEvents attributes or broker headers such as `x-death`.\n *\n * On receive the `cloudEvents:` headers win; the AMQP properties are the\n * fallback for events produced by other CloudEvents libraries (the AMQP\n * timestamp only when `cloudEvents:time` is absent; a present but malformed\n * time is rejected).\n *\n * AMQP 0-9-1 short strings (message properties, header names, routing keys) are\n * limited to 255 bytes. The event id, a header name or a routing key beyond\n * that is refused with {@link AmqpLimitExceededError}, because the event could\n * never be published. The `type`, `appId` and `correlationId` mirrors are\n * skipped when they do not fit; the `cloudEvents:` headers always carry them.\n */\nconst ATTRIBUTE_PREFIX = 'cloudEvents:';\nconst EVENT_HEADER_PREFIX = 'relaybus:';\nconst SPEC_VERSION = '1.0';\nconst JSON_CONTENT_TYPE = 'application/json';\nconst STRUCTURED_CONTENT_TYPE = 'application/cloudevents+json';\n/** Header name prefixes the broker or the transport own; an event header there would be lost on read. */\nconst RESERVED_HEADER_PREFIXES = ['x-death', 'x-first-death-', 'x-last-death-', 'x-relaybus-'];\nconst SHORT_STRING_LIMIT_BYTES = 255;\n/** RFC 3339 date-time, the format of the CloudEvents `time` attribute. */\nexport const RFC3339_PATTERN =\n /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:Z|[+-]\\d{2}:\\d{2})$/i;\n\n/** A serialized event, ready for `channel.publish`. */\nexport interface EncodedMessage {\n readonly content: Buffer;\n readonly options: AmqpPublishOptions;\n}\n\n/**\n * Serializes an envelope.\n *\n * @throws {UnserializablePayloadError} the payload is not representable as JSON\n * @throws {AmqpLimitExceededError} the id or a header name exceeds 255 bytes\n */\nexport function encodeEnvelope(envelope: EventEnvelope): EncodedMessage {\n assertJsonPayload(envelope.payload, envelope.id);\n assertShortString('Event id', envelope.id);\n const headers: Record<string, string> = {\n [`${ATTRIBUTE_PREFIX}specversion`]: SPEC_VERSION,\n [`${ATTRIBUTE_PREFIX}id`]: envelope.id,\n [`${ATTRIBUTE_PREFIX}type`]: envelope.type,\n [`${ATTRIBUTE_PREFIX}source`]: envelope.source,\n [`${ATTRIBUTE_PREFIX}time`]: envelope.occurredAt.toISOString(),\n [`${ATTRIBUTE_PREFIX}datacontenttype`]: JSON_CONTENT_TYPE,\n };\n addOptionalAttributes(headers, envelope);\n return {\n content: Buffer.from(JSON.stringify(envelope.payload), 'utf8'),\n options: {\n contentType: JSON_CONTENT_TYPE,\n persistent: true,\n messageId: envelope.id,\n timestamp: Math.floor(envelope.occurredAt.getTime() / MILLISECONDS_PER_SECOND),\n ...mirror('type', envelope.type),\n ...mirror('appId', envelope.source),\n ...(envelope.correlationId === null ? {} : mirror('correlationId', envelope.correlationId)),\n headers,\n },\n };\n}\n\n/** Adds the attributes an envelope may lack (subject, causation, correlation) and its event headers. */\nfunction addOptionalAttributes(headers: Record<string, string>, envelope: EventEnvelope): void {\n if (envelope.key !== null) {\n headers[`${ATTRIBUTE_PREFIX}subject`] = envelope.key;\n }\n if (envelope.causationId !== null) {\n headers[`${ATTRIBUTE_PREFIX}causationid`] = envelope.causationId;\n }\n if (envelope.correlationId !== null) {\n headers[`${ATTRIBUTE_PREFIX}correlationid`] = envelope.correlationId;\n }\n for (const [name, value] of Object.entries(envelope.headers)) {\n assertShortString(\n `Header name '${EVENT_HEADER_PREFIX}${name}'`,\n `${EVENT_HEADER_PREFIX}${name}`,\n );\n headers[`${EVENT_HEADER_PREFIX}${name}`] = value;\n }\n}\n\n/**\n * Serializes an envelope in CloudEvents structured content mode: the body is\n * one `application/cloudevents+json` document with the attributes and `data`.\n * The AMQP properties are those of binary mode; event headers travel as\n * message headers under their own names, as structured-mode readers expect.\n *\n * @throws {UnserializablePayloadError} the payload is not representable as JSON\n * @throws {AmqpLimitExceededError} the id or a header name exceeds 255 bytes\n * @throws {RabbitMqUnencodableEventError} a header name the broker or the transport reserves\n */\nexport function encodeStructuredEnvelope(envelope: EventEnvelope): EncodedMessage {\n assertJsonPayload(envelope.payload, envelope.id);\n assertShortString('Event id', envelope.id);\n const document = writeStructuredCloudEvent(envelope, {\n time: envelope.occurredAt.toISOString(),\n data: JSON.stringify(envelope.payload),\n });\n return {\n content: Buffer.from(document, 'utf8'),\n options: {\n ...messageProperties(envelope),\n contentType: STRUCTURED_CONTENT_TYPE,\n headers: plainHeaders(envelope, envelope.headers),\n },\n };\n}\n\n/** The AMQP properties every relaybus format writes; `contentType` and `headers` are the format's own. */\nexport function messageProperties(\n envelope: EventEnvelope,\n): Omit<AmqpPublishOptions, 'headers' | 'contentType'> {\n return {\n persistent: true,\n messageId: envelope.id,\n timestamp: Math.floor(envelope.occurredAt.getTime() / MILLISECONDS_PER_SECOND),\n ...mirror('type', envelope.type),\n ...mirror('appId', envelope.source),\n ...(envelope.correlationId === null ? {} : mirror('correlationId', envelope.correlationId)),\n };\n}\n\n/**\n * Message headers under their own names, for formats read by other services.\n * A name the broker or the transport reserves is refused, because the reader\n * would drop it; a name beyond 255 bytes is refused by AMQP.\n */\nexport function plainHeaders(\n envelope: EventEnvelope,\n headers: EventHeaders,\n): Record<string, string> {\n for (const name of Object.keys(headers)) {\n if (RESERVED_HEADER_PREFIXES.some((prefix) => name.startsWith(prefix))) {\n throw new RabbitMqUnencodableEventError(\n `Event ${envelope.id} has a header '${name}', a name the broker or the transport reserves`,\n );\n }\n assertShortString(`Header name '${name}'`, name);\n }\n return Object.fromEntries(Object.entries(headers));\n}\n\n/**\n * Throws {@link AmqpLimitExceededError} when `value` does not fit an AMQP short\n * string (255 bytes of UTF-8), which amqplib would otherwise reject on every\n * attempt.\n */\nexport function assertShortString(label: string, value: string): void {\n const bytes = Buffer.byteLength(value, 'utf8');\n if (bytes > SHORT_STRING_LIMIT_BYTES) {\n throw new AmqpLimitExceededError(\n `${label} is ${bytes} bytes, above the AMQP limit of ${SHORT_STRING_LIMIT_BYTES} bytes`,\n );\n }\n}\n\nfunction mirror<TName extends 'type' | 'appId' | 'correlationId'>(\n name: TName,\n value: string,\n): { [Name in TName]?: string } {\n return Buffer.byteLength(value, 'utf8') > SHORT_STRING_LIMIT_BYTES\n ? {}\n : ({ [name]: value } as { [Name in TName]?: string });\n}\n\n/** Rebuilds an envelope. Throws {@link MalformedMessageError} when the message is not a relaybus event. */\nexport function decodeEnvelope(message: AmqpMessage): EventEnvelope {\n const { properties } = message;\n const attributes = properties.headers ?? {};\n if (attributes[`${ATTRIBUTE_PREFIX}specversion`] !== SPEC_VERSION) {\n throw new MalformedMessageError(\n `Message is not a CloudEvents ${SPEC_VERSION} event (header ${ATTRIBUTE_PREFIX}specversion)`,\n );\n }\n return {\n id: required('id', text(attributes[`${ATTRIBUTE_PREFIX}id`]) ?? text(properties.messageId)),\n type: required('type', text(attributes[`${ATTRIBUTE_PREFIX}type`]) ?? text(properties.type)),\n source: required(\n 'source',\n text(attributes[`${ATTRIBUTE_PREFIX}source`]) ?? text(properties.appId),\n ),\n key: text(attributes[`${ATTRIBUTE_PREFIX}subject`]) ?? null,\n payload: parsePayload(message.content),\n headers: extractEventHeaders(attributes),\n correlationId:\n text(attributes[`${ATTRIBUTE_PREFIX}correlationid`]) ??\n text(properties.correlationId) ??\n null,\n causationId: text(attributes[`${ATTRIBUTE_PREFIX}causationid`]) ?? null,\n occurredAt: parseTime(attributes[`${ATTRIBUTE_PREFIX}time`], properties.timestamp),\n };\n}\n\nfunction extractEventHeaders(attributes: Readonly<Record<string, unknown>>): EventHeaders {\n const headers: Record<string, string> = {};\n for (const [name, value] of Object.entries(attributes)) {\n if (name.startsWith(EVENT_HEADER_PREFIX) && typeof value === 'string') {\n // defineProperty, because assigning `__proto__` would set the prototype and lose the header.\n Object.defineProperty(headers, name.slice(EVENT_HEADER_PREFIX.length), {\n value,\n enumerable: true,\n writable: true,\n configurable: true,\n });\n }\n }\n return headers;\n}\n\nfunction parsePayload(content: Buffer): unknown {\n try {\n return JSON.parse(content.toString('utf8')) as unknown;\n } catch {\n throw new MalformedMessageError('Message body is not valid JSON');\n }\n}\n\nfunction parseTime(rawTime: unknown, timestampSeconds: unknown): Date {\n if (rawTime === undefined) {\n const fallback =\n typeof timestampSeconds === 'number'\n ? new Date(timestampSeconds * MILLISECONDS_PER_SECOND)\n : undefined;\n if (fallback === undefined || Number.isNaN(fallback.getTime())) {\n throw new MalformedMessageError('Message has no valid time (header cloudEvents:time)');\n }\n return fallback;\n }\n const occurredAt =\n typeof rawTime === 'string' && RFC3339_PATTERN.test(rawTime) ? new Date(rawTime) : undefined;\n if (occurredAt === undefined || Number.isNaN(occurredAt.getTime())) {\n throw new MalformedMessageError(\n 'Message time (header cloudEvents:time) is not an RFC 3339 timestamp',\n );\n }\n return occurredAt;\n}\n\nfunction text(value: unknown): string | undefined {\n return typeof value === 'string' ? value : undefined;\n}\n\nfunction required(attribute: string, value: string | undefined): string {\n if (value === undefined || value.length === 0) {\n throw new MalformedMessageError(\n `Message has no ${attribute} (header ${ATTRIBUTE_PREFIX}${attribute})`,\n );\n }\n return value;\n}\n","import { assertEventType, type EventEnvelope, type EventHeaders } from '@relaybus/core';\nimport {\n DecodedEventReader,\n createCloudEventReaders,\n isJsonObject,\n mediaTypeOf,\n observeRejection,\n} from '@relaybus/core/internal';\nimport type { AmqpMessage, AmqpMessageProperties } from './amqp-types.js';\nimport { MalformedMessageError } from './errors.js';\nimport { RFC3339_PATTERN, decodeEnvelope } from './wire-format.js';\n\n/** AMQP `timestamp` properties count seconds. */\nconst MILLISECONDS_PER_SECOND = 1_000;\n\nconst { optionalAttribute, requiredAttribute, assertValidType, assertJsonDataContentType } =\n createCloudEventReaders((reason) => new MalformedMessageError(reason));\n\n/**\n * The event a decoder extracted from a message. `id`, `type` and `payload` are\n * required; every other field may be left out and is then filled by the\n * transport: `source` with the `appId` property (else the routing key), `key`\n * with null, `headers` with none, `correlationId` and `causationId` with null,\n * and `occurredAt` with the `timestamp` property (else the time of receipt).\n */\nexport interface DecodedEvent {\n readonly id: string;\n readonly type: string;\n readonly payload: unknown;\n readonly source?: string;\n readonly key?: string | null;\n readonly headers?: EventHeaders;\n readonly correlationId?: string | null;\n readonly causationId?: string | null;\n readonly occurredAt?: Date;\n}\n\n/**\n * Turns a consumed message into an event, for queues fed by producers that do\n * not use relaybus. Must be synchronous and free of side effects: it runs again\n * on every redelivery, so the same message must always give the same event,\n * above all the same `id`, which is what the inbox deduplicates on.\n *\n * Anything it throws marks the message as malformed: it is dead-lettered and\n * the consumer moves on. An event the bus then rejects (empty id, invalid type\n * or time) is dead-lettered the same way.\n */\nexport type RabbitMqMessageDecoder = (message: AmqpMessage) => DecodedEvent;\n\n/** A plain JSON message, decoded for the extractor options of {@link plainJsonDecoder}. */\nexport interface PlainJsonMessage {\n readonly routingKey: string;\n /** The AMQP properties as delivered (`messageId`, `type`, `appId`, `timestamp`, ...). */\n readonly properties: AmqpMessageProperties;\n /**\n * The message headers with string values, without the broker's and the\n * transport's own (`x-death`, `x-first-death-*`, `x-last-death-*`, `x-relaybus-*`).\n */\n readonly headers: EventHeaders;\n /** The body parsed as JSON. */\n readonly payload: unknown;\n}\n\n/** Options of {@link plainJsonDecoder}. Extractors returning undefined or `''` select the default. */\nexport interface PlainJsonDecoderOptions {\n /**\n * Event type handlers subscribe to: a fixed name for a queue that carries one\n * kind of event, or an extractor such as `fromHeader('event-type')`,\n * `fromPayloadField('type')` or `(message) => message.properties.type`.\n * Required; a message without a type is malformed.\n */\n readonly type: string | ((message: PlainJsonMessage) => string | undefined);\n /**\n * Event id the inbox deduplicates on. Default, and fallback when the\n * extractor finds none: the `messageId` property, which survives\n * redeliveries. A message with neither is malformed, because AMQP has no\n * other identity that is stable across redeliveries; give producers a\n * `messageId` (Spring AMQP can generate one with `setCreateMessageIds(true)`).\n */\n readonly id?: (message: PlainJsonMessage) => string | undefined;\n /** Ordering key. Default: none. */\n readonly key?: (message: PlainJsonMessage) => string | null | undefined;\n /** Logical name of the producer. Default: the `appId` property, else the routing key. */\n readonly source?: string | ((message: PlainJsonMessage) => string | undefined);\n /** When the event happened. Default: the `timestamp` property, else the time of receipt. */\n readonly occurredAt?: (message: PlainJsonMessage) => Date | undefined;\n}\n\nconst STRUCTURED_MEDIA_TYPE = 'application/cloudevents+json';\nconst strictUtf8 = new TextDecoder('utf-8', { fatal: true });\nconst SPEC_VERSION = '1.0';\nconst SPEC_VERSION_HEADER = 'cloudEvents:specversion';\n/** Headers the broker or this transport add on their own; never event headers. */\nconst INTERNAL_HEADER_PREFIXES = ['x-relaybus-', 'x-first-death-', 'x-last-death-'];\n/** Attributes of a structured event that map to envelope fields rather than headers. */\nconst STRUCTURED_ATTRIBUTES: ReadonlySet<string> = new Set([\n 'specversion',\n 'id',\n 'type',\n 'source',\n 'time',\n 'subject',\n 'datacontenttype',\n 'dataschema',\n 'data',\n 'data_base64',\n 'correlationid',\n 'causationid',\n]);\n\n/**\n * Decodes a CloudEvents 1.0 message in either content mode:\n * - structured (`contentType` property `application/cloudevents+json`): the\n * body is a JSON object with `specversion`, `id`, `type`, `source` and\n * optionally `time` (else the `timestamp` property, else the time of\n * receipt), `subject` (the key), `data` (the payload, null when absent) and\n * a JSON `datacontenttype`. `data_base64` is refused, because relaybus\n * payloads are JSON. Extension attributes with string values (`traceparent`,\n * ...) become event headers, as do the string message headers;\n * `correlationid` and `causationid` fill their envelope fields.\n * - binary (anything else): exactly the default decoder, `cloudEvents:*`\n * headers with the AMQP properties as fallback.\n *\n * @throws MalformedMessageError for a message that is neither.\n */\nexport function decodeCloudEvent(message: AmqpMessage): EventEnvelope {\n if (mediaTypeOf(message.properties.contentType) !== STRUCTURED_MEDIA_TYPE) {\n return decodeEnvelope(message);\n }\n const body = parseJsonBody(message.content);\n if (!isJsonObject(body)) {\n throw new MalformedMessageError('A structured CloudEvent must be a JSON object');\n }\n if (body['specversion'] !== SPEC_VERSION) {\n throw new MalformedMessageError(`specversion must be '${SPEC_VERSION}'`);\n }\n const type = requiredAttribute(body, 'type');\n assertValidType(type, 'type');\n assertJsonDataContentType(optionalAttribute(body, 'datacontenttype'));\n if (Object.hasOwn(body, 'data_base64')) {\n throw new MalformedMessageError(\n 'data_base64 is not supported: relaybus payloads are JSON, send them as data',\n );\n }\n const time = optionalAttribute(body, 'time');\n return {\n id: requiredAttribute(body, 'id'),\n type,\n source: requiredAttribute(body, 'source'),\n key: optionalAttribute(body, 'subject') ?? null,\n payload: Object.hasOwn(body, 'data') ? body['data'] : null,\n headers: { ...readForeignHeaders(message.properties), ...extensionAttributes(body) },\n correlationId: optionalAttribute(body, 'correlationid') ?? null,\n causationId: optionalAttribute(body, 'causationid') ?? null,\n occurredAt: time === undefined ? propertyTimeOrNow(message.properties) : parseTime(time),\n };\n}\n\n/**\n * Creates a decoder for messages whose body is plain JSON, as published by a\n * service that does not use relaybus (plain amqplib, Spring AMQP's\n * `Jackson2JsonMessageConverter`, a Go or Python service): the body becomes the\n * payload, the string headers become event headers, and the options say where\n * the event type and id come from.\n *\n * A message that is a CloudEvent anyway (a `cloudEvents:specversion` header,\n * or a structured `application/cloudevents+json` body) is decoded with\n * {@link decodeCloudEvent} instead, so relaybus and foreign producers can feed\n * one queue. A body that is not JSON, a missing or invalid type, a missing id\n * and an extractor returning anything but a string are malformed.\n *\n * ```ts\n * new RabbitMqTransport({\n * url,\n * consumerGroup: 'billing',\n * decode: plainJsonDecoder({ type: (message) => message.properties.type as string }),\n * });\n * ```\n *\n * @throws ConfigurationError when a fixed `type` is not a valid event type.\n */\nexport function plainJsonDecoder(options: PlainJsonDecoderOptions): RabbitMqMessageDecoder {\n if (typeof options.type === 'string') {\n assertEventType(options.type);\n }\n return (message) => {\n const { properties } = message;\n if (\n properties.headers?.[SPEC_VERSION_HEADER] !== undefined ||\n mediaTypeOf(properties.contentType) === STRUCTURED_MEDIA_TYPE\n ) {\n return decodeCloudEvent(message);\n }\n const plain = plainMessageOf(message);\n const type = RABBITMQ_EVENTS.text(options.type, { plain, name: 'type' });\n if (type === undefined) {\n throw new MalformedMessageError('Message has no event type: the type option found none');\n }\n assertValidType(type, 'The event type');\n const id =\n RABBITMQ_EVENTS.text(options.id, { plain, name: 'id' }) ?? nonEmptyText(properties.messageId);\n if (id === undefined) {\n throw new MalformedMessageError(\n 'Message has no id: set the messageId property on the producer or configure the id option',\n );\n }\n return {\n id,\n type,\n source:\n RABBITMQ_EVENTS.text(options.source, { plain, name: 'source' }) ?? defaultSource(message),\n key: RABBITMQ_EVENTS.text(options.key, { plain, name: 'key' }) ?? null,\n payload: plain.payload,\n headers: plain.headers,\n correlationId: null,\n causationId: null,\n occurredAt: resolveOccurredAt(options.occurredAt, plain),\n };\n };\n}\n\n/** A message as the extractor options of {@link plainJsonDecoder} see it. */\nfunction plainMessageOf(message: AmqpMessage): PlainJsonMessage {\n const { properties } = message;\n return {\n routingKey: message.fields.routingKey,\n properties,\n headers: readForeignHeaders(properties),\n payload: parseJsonBody(message.content),\n };\n}\n\n/** The inbound plumbing of AMQP messages: malformed messages and the message's own defaults. */\nclass RabbitMqDecodedEvents extends DecodedEventReader<AmqpMessage, PlainJsonMessage> {\n invalid(reason: string): Error {\n return new MalformedMessageError(reason);\n }\n\n protected defaultSource(message: AmqpMessage): string {\n return defaultSource(message);\n }\n\n /** None: AMQP messages carry no ordering key. */\n protected defaultKey(): null {\n return null;\n }\n\n /** The `timestamp` property, else the time of receipt. */\n protected defaultTime(message: AmqpMessage): Date {\n return propertyTimeOrNow(message.properties);\n }\n}\n\nconst RABBITMQ_EVENTS = new RabbitMqDecodedEvents();\n\n/**\n * Fills the fields a decoder left out (see {@link DecodedEvent}) and guards\n * against a decoder that returned no object.\n */\nexport function completeDecodedEvent(decoded: unknown, message: AmqpMessage): EventEnvelope {\n return RABBITMQ_EVENTS.complete(decoded, message);\n}\n\n/** Parses the body as UTF-8 JSON, refusing invalid UTF-8 instead of replacing it. */\nexport function parseJsonBody(content: Buffer): unknown {\n let text: string;\n try {\n text = strictUtf8.decode(content);\n } catch {\n throw new MalformedMessageError('Message body is not valid UTF-8');\n }\n try {\n return JSON.parse(text) as unknown;\n } catch {\n throw new MalformedMessageError('Message body is not valid JSON');\n }\n}\n\nexport function nonEmptyText(value: unknown): string | undefined {\n return typeof value === 'string' && value.length > 0 ? value : undefined;\n}\n\nfunction defaultSource(message: AmqpMessage): string {\n return nonEmptyText(message.properties.appId) ?? message.fields.routingKey;\n}\n\nfunction parseTime(text: string): Date {\n const time = new Date(text);\n if (!RFC3339_PATTERN.test(text) || Number.isNaN(time.getTime())) {\n throw new MalformedMessageError(`time is not an RFC 3339 timestamp: '${text}'`);\n }\n return time;\n}\n\n/** The `timestamp` property (seconds), else the time of receipt. */\nfunction propertyTimeOrNow(properties: AmqpMessageProperties): Date {\n const { timestamp } = properties;\n return typeof timestamp === 'number' && Number.isFinite(timestamp)\n ? new Date(timestamp * MILLISECONDS_PER_SECOND)\n : new Date();\n}\n\nfunction extensionAttributes(body: Record<string, unknown>): Record<string, string> {\n return Object.fromEntries(\n Object.entries(body).filter(\n (entry): entry is [string, string] =>\n !STRUCTURED_ATTRIBUTES.has(entry[0]) && typeof entry[1] === 'string',\n ),\n );\n}\n\nexport function readForeignHeaders(properties: AmqpMessageProperties): Record<string, string> {\n return Object.fromEntries(\n Object.entries(properties.headers ?? {}).filter(\n (entry): entry is [string, string] =>\n typeof entry[1] === 'string' &&\n !INTERNAL_HEADER_PREFIXES.some((prefix) => entry[0].startsWith(prefix)),\n ),\n );\n}\n\nfunction resolveOccurredAt(\n option: PlainJsonDecoderOptions['occurredAt'],\n message: PlainJsonMessage,\n): Date {\n const value: unknown = option?.(message);\n if (value === undefined) {\n return propertyTimeOrNow(message.properties);\n }\n if (!(value instanceof Date) || Number.isNaN(value.getTime())) {\n observeRejection(value);\n throw new MalformedMessageError('The occurredAt option returned no valid Date');\n }\n return value;\n}\n","import type { EventEnvelope } from '@relaybus/core';\nimport {\n createJsonEnvelopeFormat,\n mergeWireTypes,\n type JsonEnvelopeMapping,\n} from '@relaybus/core/internal';\nimport type { AmqpMessage } from './amqp-types.js';\nimport { MalformedMessageError, RabbitMqUnencodableEventError } from './errors.js';\nimport {\n completeDecodedEvent,\n decodeCloudEvent,\n nonEmptyText,\n parseJsonBody,\n readForeignHeaders,\n type RabbitMqMessageDecoder,\n} from './inbound-decoders.js';\nimport { assertJsonPayload } from './json-payload.js';\nimport {\n assertShortString,\n decodeEnvelope,\n encodeEnvelope,\n encodeStructuredEnvelope,\n messageProperties,\n plainHeaders,\n type EncodedMessage,\n} from './wire-format.js';\n\n/**\n * The wire format of a {@link RabbitMqTransport}: how an event becomes a\n * message (`encode`, on publish) and a consumed message becomes an event\n * (`decode`).\n *\n * Both must be synchronous and free of side effects. What `encode` throws\n * fails the publish: the outbox retries it, unless it is a `NonRetryableError`\n * such as {@link RabbitMqUnencodableEventError}. Give every message a\n * `messageId`: the transport matches broker returns of unroutable messages by\n * it. What `decode` throws marks the message as malformed: it is\n * dead-lettered and the consumer moves on. See {@link RabbitMqMessageDecoder}\n * for the decode contract.\n */\nexport interface RabbitMqCodec {\n readonly encode: (envelope: EventEnvelope) => EncodedMessage;\n readonly decode: RabbitMqMessageDecoder;\n /**\n * Returns this codec with more wire names for event types, which a route or catalog declares\n * (`wireTypes` of `route(...)` or `defineCatalog`). Only a codec that maps type names has it\n * ({@link jsonEnvelope}); declaring wire names for a transport whose codec lacks it fails at boot.\n */\n readonly withWireTypes?: (wireTypes: Readonly<Record<string, string>>) => RabbitMqCodec;\n}\n\n/**\n * CloudEvents 1.0 binary content mode, the default: the body is the JSON\n * payload, the attributes travel as `cloudEvents:*` headers mirrored in the\n * AMQP properties. Decoding is strict: any other message is malformed.\n */\nexport const cloudEventsBinary: RabbitMqCodec = Object.freeze({\n encode: encodeEnvelope,\n decode: decodeEnvelope,\n});\n\n/**\n * CloudEvents 1.0 structured content mode: the body is one\n * `application/cloudevents+json` document with the attributes and `data`.\n * Decoding accepts structured and binary mode ({@link decodeCloudEvent}).\n * Event headers travel under their own names; names starting with `x-death`,\n * `x-first-death-`, `x-last-death-` or `x-relaybus-` are refused.\n */\nexport const cloudEventsStructured: RabbitMqCodec = Object.freeze({\n encode: encodeStructuredEnvelope,\n decode: decodeCloudEvent,\n});\n\n/**\n * Where each value of a JSON message lives, for {@link jsonEnvelope}. Besides\n * `{ body }` and `{ header }`, the id may be `'message-id-property'`: the\n * AMQP `messageId` property, which the codec always writes and which survives\n * redeliveries; a message without one is malformed.\n */\nexport type RabbitMqJsonEnvelopeMapping = JsonEnvelopeMapping<'message-id-property'>;\n\nconst MESSAGE_ID_PROPERTY = 'message-id-property';\nconst DEFAULT_CONTENT_TYPE = 'application/json';\n\n/**\n * A JSON wire format declared by a mapping, in both directions: for queues\n * shared with services that wrap events in their own envelope\n * (`{ \"eventName\": ..., \"data\": {...} }`, MassTransit) or send the bare\n * payload. Every message also gets the AMQP properties of binary mode:\n * `messageId` (the event id), `type`, `appId` (the source), `correlationId`,\n * `timestamp` (seconds) and `persistent`. Event\n * headers that are message headers are written as they are, so a name the\n * mapping uses for another field, or one the broker reserves, is refused\n * with {@link RabbitMqUnencodableEventError}.\n *\n * ```ts\n * codec: jsonEnvelope({\n * type: { body: 'eventName' },\n * id: 'message-id-property',\n * payload: { body: 'data' },\n * })\n * ```\n *\n * @throws ConfigurationError for an incomplete or self-overlapping mapping.\n */\nexport function jsonEnvelope(mapping: RabbitMqJsonEnvelopeMapping): RabbitMqCodec {\n const format = createJsonEnvelopeFormat(mapping, {\n transportIds: [MESSAGE_ID_PROPERTY],\n failures: {\n invalid: (reason) => new MalformedMessageError(reason),\n unencodable: (reason) => new RabbitMqUnencodableEventError(reason),\n },\n });\n const contentType = mapping.contentType ?? DEFAULT_CONTENT_TYPE;\n return {\n withWireTypes: (declared) =>\n jsonEnvelope({ ...mapping, wireTypes: mergeWireTypes(mapping, declared) }),\n encode: (envelope) => {\n assertJsonPayload(envelope.payload, envelope.id);\n assertShortString('Event id', envelope.id);\n const { body, headers } = format.write(envelope);\n return {\n content: Buffer.from(JSON.stringify(body), 'utf8'),\n options: {\n ...messageProperties(envelope),\n contentType,\n headers: plainHeaders(envelope, headers),\n },\n };\n },\n decode: (message) => {\n const fields = format.read({\n body: parseJsonBody(message.content),\n headers: readForeignHeaders(message.properties),\n });\n return { ...fields, id: fields.id ?? requireMessageId(message) };\n },\n };\n}\n\nfunction requireMessageId(message: AmqpMessage): string {\n const id = nonEmptyText(message.properties.messageId);\n if (id === undefined) {\n throw new MalformedMessageError('Message has no id: the messageId property is missing');\n }\n return id;\n}\n\n/**\n * The event a {@link RabbitMqTransport} with `codec` hands to the bus for `message`: the codec's\n * `decode`, with what it leaves out filled in (see `DecodedEvent`). Throws for a malformed\n * message. For codec contract tests (`rabbitMqCodecContract` of `@relaybus/testing`).\n */\nexport function decodeRabbitMqMessage(codec: RabbitMqCodec, message: AmqpMessage): EventEnvelope {\n if (codec === cloudEventsBinary) {\n return decodeEnvelope(message);\n }\n return completeDecodedEvent(codec.decode(message), message);\n}\n","import { ConfigurationError, type RetryPolicy } from '@relaybus/core';\nimport type { AmqpMessage, AmqpPublishOptions } from './amqp-types.js';\n\n/** Number of delayed redeliveries a message went through. Set on every retry copy. */\nexport const REDELIVERIES_HEADER = 'x-relaybus-redeliveries';\n/** Epoch milliseconds of the first failure that needed a delayed redelivery. */\nexport const FIRST_FAILURE_HEADER = 'x-relaybus-first-failure-at';\n/** Why a message was moved to the dead-letter queue by the consumer. */\nexport const DEAD_LETTER_REASON_HEADER = 'x-relaybus-dead-letter-reason';\n/** Class name of the error that dead-lettered a message, such as `MalformedMessageError`. */\nexport const DEAD_LETTER_ERROR_NAME_HEADER = 'x-relaybus-dead-letter-error-name';\n/** Stable code of that error, such as `RELAYBUS_RABBITMQ_MALFORMED_MESSAGE`; absent for non-relaybus errors. */\nexport const DEAD_LETTER_ERROR_CODE_HEADER = 'x-relaybus-dead-letter-error-code';\n/**\n * The routing key a message was originally published with. Set on retry copies,\n * which travel through the default exchange and return with the queue name as\n * routing key, so decoders still see the original one.\n */\nexport const ORIGINAL_ROUTING_KEY_HEADER = 'x-relaybus-routing-key';\n\nconst RELAYBUS_STATE_HEADERS: readonly string[] = [REDELIVERIES_HEADER, FIRST_FAILURE_HEADER];\n/** Counters the broker stamps on its own redeliveries; they must not travel in a copy. */\nconst BROKER_COUNTER_HEADERS: readonly string[] = ['x-delivery-count', 'x-acquired-count'];\nconst MAXIMUM_LADDER_TIERS = 16;\n\n/**\n * The fixed delays of the retry queues, ascending: the policy's delay grown by\n * its factor until the cap. Each tier is its own queue with a queue-level TTL,\n * so messages in one queue always expire in arrival order; one queue with\n * mixed per-message TTLs would let a long delay hold back shorter ones.\n *\n * @throws {ConfigurationError} the policy has no usable delays or too many tiers\n */\nexport function buildRetryLadder(policy: RetryPolicy): readonly number[] {\n if (policy.initialDelayMs < 1) {\n throw new ConfigurationError('redelivery.initialDelay must be at least 1ms');\n }\n const tiers: number[] = [];\n let delay = policy.initialDelayMs;\n for (;;) {\n const tier = Math.round(Math.min(delay, policy.maxDelayMs));\n tiers.push(tier);\n if (tier >= policy.maxDelayMs || policy.factor === 1) {\n return tiers;\n }\n if (tiers.length === MAXIMUM_LADDER_TIERS) {\n throw new ConfigurationError(\n `redelivery needs more than ${MAXIMUM_LADDER_TIERS} retry queues; raise redelivery.factor or lower redelivery.maxDelay`,\n );\n }\n delay *= policy.factor;\n }\n}\n\n/**\n * Maps a jittered delay onto the ladder. A delay between two tiers goes to the\n * upper one with the probability that keeps the expected delay equal to\n * `delayMs`, so jitter still spreads a cohort of failures across tiers.\n */\nexport function chooseRetryTier(\n ladder: readonly number[],\n { delayMs, random }: { readonly delayMs: number; readonly random: () => number },\n): number {\n const upperIndex = ladder.findIndex((tier) => tier >= delayMs);\n if (upperIndex === -1) {\n return ladder.at(-1)!;\n }\n if (upperIndex === 0) {\n return ladder[0]!;\n }\n const lower = ladder[upperIndex - 1]!;\n const upper = ladder[upperIndex]!;\n return random() < (delayMs - lower) / (upper - lower) ? upper : lower;\n}\n\n/** Reads a non-negative integer that a copy carries as a header (string or number). */\nexport function readCounterHeader(message: AmqpMessage, name: string): number | undefined {\n // A message decoded by a custom decoder (plain JSON, structured mode) may have no headers.\n const value = message.properties.headers?.[name];\n const parsed = typeof value === 'string' && /^\\d+$/.test(value) ? Number(value) : value;\n return typeof parsed === 'number' && Number.isSafeInteger(parsed) && parsed >= 0\n ? parsed\n : undefined;\n}\n\n/**\n * A byte-faithful copy of a received message for publishing to another queue:\n * same body and properties, headers carried over except the broker's delivery\n * counters and relaybus' own redelivery state, then `headerChanges` applied.\n */\nexport function copyForRepublish(\n message: AmqpMessage,\n headerChanges: Readonly<Record<string, string>>,\n): { content: Buffer; options: AmqpPublishOptions } {\n const { properties } = message;\n const headers: Record<string, unknown> = { ...properties.headers };\n for (const name of [\n ...RELAYBUS_STATE_HEADERS,\n DEAD_LETTER_REASON_HEADER,\n DEAD_LETTER_ERROR_NAME_HEADER,\n DEAD_LETTER_ERROR_CODE_HEADER,\n ...BROKER_COUNTER_HEADERS,\n ]) {\n delete headers[name];\n }\n Object.assign(headers, headerChanges);\n return {\n content: message.content,\n options: {\n contentType:\n typeof properties.contentType === 'string' ? properties.contentType : 'application/json',\n persistent: true,\n ...(typeof properties.messageId === 'string' ? { messageId: properties.messageId } : {}),\n ...(typeof properties.type === 'string' ? { type: properties.type } : {}),\n ...(typeof properties.appId === 'string' ? { appId: properties.appId } : {}),\n ...(typeof properties.correlationId === 'string'\n ? { correlationId: properties.correlationId }\n : {}),\n ...(typeof properties.timestamp === 'number' ? { timestamp: properties.timestamp } : {}),\n headers,\n },\n };\n}\n\n/** The routing key the message was published with: the original one for a retry copy. */\nexport function originalRoutingKey(message: AmqpMessage): string {\n const original = message.properties.headers?.[ORIGINAL_ROUTING_KEY_HEADER];\n return typeof original === 'string' ? original : message.fields.routingKey;\n}\n\n/** The message as first published: a retry copy gets its original routing key back. */\nexport function withOriginalRoutingKey(message: AmqpMessage): AmqpMessage {\n const routingKey = originalRoutingKey(message);\n return routingKey === message.fields.routingKey\n ? message\n : { ...message, fields: { ...message.fields, routingKey } };\n}\n","import {\n ConfigurationError,\n createRetryPolicy,\n type Duration,\n type EventEnvelope,\n type RelayBusLogger,\n type RetryPolicy,\n type RetryPolicyOptions,\n} from '@relaybus/core';\nimport { Milliseconds, NonEmptyText, PositiveInteger } from '@relaybus/core/internal';\nimport type { AmqpConnection, AmqpMessage } from './amqp-types.js';\nimport { cloudEventsBinary, decodeRabbitMqMessage, type RabbitMqCodec } from './codecs.js';\nimport type { RabbitMqMessageDecoder } from './inbound-decoders.js';\nimport { buildRetryLadder } from './redelivery.js';\nimport { decodeEnvelope, encodeEnvelope, type EncodedMessage } from './wire-format.js';\n\n/** Connection settings accepted by `amqplib.connect`, given as an object instead of a URL. */\nexport interface BrokerConnectionSettings {\n readonly protocol?: string;\n readonly hostname?: string;\n readonly port?: number;\n readonly username?: string;\n readonly password?: string;\n readonly vhost?: string;\n /** Seconds. See \"Operational notes\" in the README for the heartbeat defaults of each amqplib version. */\n readonly heartbeat?: number;\n}\n\n/** Backoff between reconnect attempts. Attempts are unlimited. */\nexport type ReconnectOptions = Pick<\n RetryPolicyOptions,\n 'initialDelay' | 'factor' | 'maxDelay' | 'jitter'\n>;\n\n/**\n * Delayed redelivery of messages whose handler keeps failing. Each failed\n * delivery goes to a retry queue and returns to the main queue after a growing\n * delay, so an outage of the handler's dependency is waited out instead of\n * burning through delivery attempts.\n */\nexport type RedeliveryOptions = Pick<\n RetryPolicyOptions,\n 'initialDelay' | 'factor' | 'maxDelay' | 'jitter'\n> & {\n /**\n * How long a message may keep failing, counted from its first delayed\n * redelivery, before it is dead-lettered. Default `'1h'`.\n */\n readonly maxAge?: Duration;\n};\n\nexport interface RabbitMqTransportOptions {\n /** Name referenced by routes and subscriptions. Default `'rabbitmq'`. */\n readonly name?: string;\n /**\n * Broker location, for example `amqp://user:pass@host:5672/vhost?heartbeat=30`.\n * Give exactly one of `url` and `connect`.\n */\n readonly url?: string | BrokerConnectionSettings;\n /**\n * Opens one connection. Called again after every connection loss. Use it for\n * TLS options, custom credentials or an alternative amqplib instance. `signal` aborts when a\n * shutdown runs past its deadline: pass it on (`amqplib.connect(url, { signal })`) so a broker\n * that never answers the handshake cannot hold the socket open.\n */\n readonly connect?: (options: ConnectOptions) => Promise<AmqpConnection>;\n /** Topic exchange events are published to. Durable, created when missing. Default `'relaybus'`. */\n readonly exchange?: string;\n /**\n * Unacknowledged messages the consumer holds, which is also its concurrency.\n * Default 50, or 1 when `ordered`.\n */\n readonly prefetch?: number;\n /** Prefix of derived queue names. Default `'relaybus'`. */\n readonly queuePrefix?: string;\n /**\n * Consumer group: services sharing it share one queue and split the messages,\n * services with different groups each receive every message. The queue is\n * `<queuePrefix>.<consumerGroup>`. Required when subscribing, unless `queue` is set.\n */\n readonly consumerGroup?: string;\n /** Explicit queue name. Overrides `queuePrefix` and `consumerGroup`. */\n readonly queue?: string;\n /** Exchange poison messages are dead-lettered to. Default `'<exchange>.dead'`. */\n readonly deadLetterExchange?: string;\n /** Queue that keeps dead-lettered messages for inspection. Default `'<queue>.dead'`. */\n readonly deadLetterQueue?: string;\n /**\n * Quorum queue `x-delivery-limit`: deliveries after which the broker itself\n * dead-letters a message. Failing handlers do not consume it (they use\n * `redelivery`); it only stops a message that crashes the consumer or its\n * channel again and again. Default 10.\n */\n readonly deliveryLimit?: number;\n /**\n * Handler attempts on the same delivery, with backoff, before the message is\n * scheduled for delayed redelivery. Absorbs short blips without a broker round\n * trip. Default: 3 attempts, 200 ms initial delay, factor 2, 5 s cap, equal jitter.\n */\n readonly handlerRetry?: RetryPolicyOptions;\n /**\n * Delayed redelivery after `handlerRetry` is spent. Default: 2 s initial\n * delay, factor 2, 5 min cap, equal jitter, dead-lettered after 1 h of\n * failing (about 18 redeliveries). Delays are quantized to the retry queues,\n * one per step of the exponential ladder (9 queues with the defaults).\n * Ignored when `ordered`, where the same delays are waited in place.\n */\n readonly redelivery?: RedeliveryOptions;\n /**\n * Consume the queue strictly in order: a single active consumer across all\n * replicas, one message at a time, a failing message is retried in place\n * (blocking the queue) instead of being delayed. Needed when\n * `EventEnvelope.key` order matters; costs throughput, because one handler\n * runs at a time. Default false: handlers run concurrently and a delayed\n * redelivery overtakes later messages, so order is not preserved.\n */\n readonly ordered?: boolean;\n /** Reconnect backoff, or `false` to never reconnect. Default: 500 ms initial, factor 2, 30 s cap, equal jitter. */\n readonly reconnect?: ReconnectOptions | false;\n /**\n * When true (default) `connect()` rejects if the broker is unreachable, which\n * fails startup. When false it resolves and keeps trying in the background.\n */\n readonly failOnConnectError?: boolean;\n /**\n * When false (default) a message that no queue is bound to makes `publish`\n * reject. When true it resolves and the broker silently discards the message.\n */\n readonly allowUnroutable?: boolean;\n /** How long `publish` waits for the broker confirm. Default `'30s'`. */\n readonly publishTimeout?: Duration;\n /** How long `close` waits for running handlers. Default `'30s'`. */\n readonly shutdownTimeout?: Duration;\n /**\n * The wire format, both ways: how events become messages and consumed\n * messages become events. Default {@link cloudEventsBinary}: CloudEvents\n * binary mode (`cloudEvents:*` headers, AMQP properties as fallback), any\n * other message is malformed and dead-lettered. {@link cloudEventsStructured}\n * writes structured mode and reads both, {@link jsonEnvelope} maps a JSON\n * format of your own (an envelope with the payload inside, or the bare\n * payload), and an object with `encode` and `decode` can do anything else.\n * Whatever `decode` throws marks the message as malformed: it is\n * dead-lettered, the consumer keeps running.\n */\n readonly codec?: RabbitMqCodec;\n /**\n * How consumed messages become events; events are still written in\n * CloudEvents binary mode.\n *\n * @deprecated Use `codec`: `decode: fn` is `codec: { encode: encodeEnvelope, decode: fn }`.\n * Giving both `decode` and `codec` is a configuration error.\n */\n readonly decode?: RabbitMqMessageDecoder;\n /** Default: `console`. */\n readonly logger?: RelayBusLogger;\n /** Random source for jitter. Default `Math.random`. Intended for tests. */\n readonly random?: () => number;\n}\n\n/** What `connect` gets for each connection it opens. */\nexport interface ConnectOptions {\n /** Aborted when a shutdown runs past its deadline; destroys a socket still connecting. */\n readonly signal: AbortSignal;\n}\n\nexport interface ResolvedTransportSettings {\n readonly name: string;\n readonly connect: (options: ConnectOptions) => Promise<AmqpConnection>;\n readonly exchange: string;\n readonly prefetch: number;\n readonly queuePrefix: string;\n readonly consumerGroup: string | undefined;\n readonly queue: string | undefined;\n readonly deadLetterExchange: string;\n readonly deadLetterQueue: string | undefined;\n readonly deliveryLimit: number;\n readonly handlerRetry: RetryPolicy;\n readonly redelivery: RetryPolicy;\n /** Fixed delays of the retry queues; empty when `ordered`. */\n readonly retryLadder: readonly number[];\n readonly redeliveryMaxAgeMs: number;\n readonly ordered: boolean;\n readonly reconnect: RetryPolicy | undefined;\n readonly failOnConnectError: boolean;\n readonly allowUnroutable: boolean;\n readonly publishTimeoutMs: number;\n readonly shutdownTimeoutMs: number;\n /** The wire format the `encode` and `decode` below come from. */\n readonly codec: RabbitMqCodec;\n /** Turns an event into the message to publish. */\n readonly encode: (envelope: EventEnvelope) => EncodedMessage;\n /** Turns a consumed message into a complete envelope; throws for a malformed one. */\n readonly decode: (message: AmqpMessage) => EventEnvelope;\n readonly logger: RelayBusLogger;\n readonly random: () => number;\n}\n\n/** Default `prefetch` when not ordered. */\nconst DEFAULT_PREFETCH = 50;\n/** Default `deliveryLimit`. */\nconst DEFAULT_DELIVERY_LIMIT = 10;\n\nconst DEFAULT_HANDLER_RETRY: RetryPolicy = {\n attempts: 3,\n initialDelayMs: 200,\n factor: 2,\n maxDelayMs: 5_000,\n jitter: 'equal',\n retryIf: undefined,\n};\n\nconst DEFAULT_REDELIVERY: RetryPolicy = {\n attempts: Number.POSITIVE_INFINITY,\n initialDelayMs: 2_000,\n factor: 2,\n maxDelayMs: 300_000,\n jitter: 'equal',\n retryIf: undefined,\n};\n\nconst DEFAULT_REDELIVERY_MAX_AGE = '1h';\n\nconst DEFAULT_RECONNECT: RetryPolicy = {\n attempts: 1,\n initialDelayMs: 500,\n factor: 2,\n maxDelayMs: 30_000,\n jitter: 'equal',\n retryIf: undefined,\n};\n\n/** Validates the options and applies defaults. Throws `ConfigurationError`. */\nexport function resolveSettings(options: RabbitMqTransportOptions): ResolvedTransportSettings {\n const basics = resolveBasics(options);\n return {\n ...resolveTopology(options, basics),\n ...resolveRetries(options, basics),\n ...resolveRuntime(options, basics),\n };\n}\n\n/** The settings the others depend on, checked first: exchange, connect behaviour, ordering, prefetch, redelivery. */\ntype BasicSettings = Pick<\n ResolvedTransportSettings,\n 'exchange' | 'failOnConnectError' | 'ordered' | 'prefetch' | 'redelivery'\n>;\n\nfunction resolveBasics(options: RabbitMqTransportOptions): BasicSettings {\n const exchange = NonEmptyText.of(options.exchange ?? 'relaybus', 'exchange');\n const failOnConnectError = options.failOnConnectError ?? true;\n if (!failOnConnectError && options.reconnect === false) {\n throw new ConfigurationError(\n 'failOnConnectError=false needs reconnect enabled, otherwise the transport would never connect',\n );\n }\n const ordered = options.ordered ?? false;\n const prefetch = PositiveInteger.of(\n options.prefetch ?? (ordered ? 1 : DEFAULT_PREFETCH),\n 'prefetch',\n );\n if (ordered && prefetch !== 1) {\n throw new ConfigurationError(`ordered consumption needs prefetch 1, received ${prefetch}`);\n }\n const redelivery = createRetryPolicy(options.redelivery, DEFAULT_REDELIVERY);\n return { exchange, failOnConnectError, ordered, prefetch, redelivery };\n}\n\n/** Names, connection, exchanges and queues. */\nfunction resolveTopology(\n options: RabbitMqTransportOptions,\n { exchange, prefetch }: BasicSettings,\n): Pick<\n ResolvedTransportSettings,\n | 'name'\n | 'connect'\n | 'exchange'\n | 'prefetch'\n | 'queuePrefix'\n | 'consumerGroup'\n | 'queue'\n | 'deadLetterExchange'\n | 'deadLetterQueue'\n | 'deliveryLimit'\n> {\n return {\n name: NonEmptyText.of(options.name ?? 'rabbitmq', 'name'),\n connect: resolveConnect(options),\n exchange,\n prefetch,\n queuePrefix: NonEmptyText.of(options.queuePrefix ?? 'relaybus', 'queuePrefix'),\n consumerGroup: NonEmptyText.optional(options.consumerGroup, 'consumerGroup'),\n queue: NonEmptyText.optional(options.queue, 'queue'),\n deadLetterExchange: NonEmptyText.of(\n options.deadLetterExchange ?? `${exchange}.dead`,\n 'deadLetterExchange',\n ),\n deadLetterQueue: NonEmptyText.optional(options.deadLetterQueue, 'deadLetterQueue'),\n deliveryLimit: PositiveInteger.of(\n options.deliveryLimit ?? DEFAULT_DELIVERY_LIMIT,\n 'deliveryLimit',\n ),\n };\n}\n\n/** Handler retries, delayed redelivery and its retry queues. */\nfunction resolveRetries(\n options: RabbitMqTransportOptions,\n { ordered, redelivery }: BasicSettings,\n): Pick<\n ResolvedTransportSettings,\n 'handlerRetry' | 'redelivery' | 'retryLadder' | 'redeliveryMaxAgeMs' | 'ordered'\n> {\n return {\n handlerRetry: createRetryPolicy(options.handlerRetry, DEFAULT_HANDLER_RETRY),\n redelivery,\n retryLadder: ordered ? [] : buildRetryLadder(redelivery),\n redeliveryMaxAgeMs: Milliseconds.positive(\n options.redelivery?.maxAge ?? DEFAULT_REDELIVERY_MAX_AGE,\n 'redelivery.maxAge',\n ),\n ordered,\n };\n}\n\n/** Reconnection, timeouts, the codec and the injected logger and randomness. */\nfunction resolveRuntime(\n options: RabbitMqTransportOptions,\n { failOnConnectError }: BasicSettings,\n): Pick<\n ResolvedTransportSettings,\n | 'reconnect'\n | 'failOnConnectError'\n | 'allowUnroutable'\n | 'publishTimeoutMs'\n | 'shutdownTimeoutMs'\n | 'codec'\n | 'encode'\n | 'decode'\n | 'logger'\n | 'random'\n> {\n return {\n reconnect: resolveReconnect(options.reconnect),\n failOnConnectError,\n allowUnroutable: options.allowUnroutable ?? false,\n publishTimeoutMs: Milliseconds.positive(options.publishTimeout ?? '30s', 'publishTimeout'),\n shutdownTimeoutMs: Milliseconds.of(options.shutdownTimeout ?? '30s', 'shutdownTimeout'),\n ...resolveCodec(options),\n logger: options.logger ?? console,\n random: options.random ?? Math.random,\n };\n}\n\n/** `<queuePrefix>.<consumerGroup>`, or the explicit queue name. */\nexport function resolveQueueName(settings: ResolvedTransportSettings): string {\n if (settings.queue !== undefined) {\n return settings.queue;\n }\n if (settings.consumerGroup === undefined) {\n throw new ConfigurationError(\n `Transport '${settings.name}' needs 'consumerGroup' or 'queue' to subscribe`,\n );\n }\n return `${settings.queuePrefix}.${settings.consumerGroup}`;\n}\n\n/** The codec of the options; the deprecated `decode` pairs with the default encoding. */\nfunction resolveCodec({\n codec,\n decode,\n}: RabbitMqTransportOptions): Pick<ResolvedTransportSettings, 'codec' | 'encode' | 'decode'> {\n if (decode !== undefined && codec !== undefined) {\n throw new ConfigurationError(\"Give 'codec' or the deprecated 'decode', not both\");\n }\n return codecSettings(\n decode === undefined ? (codec ?? cloudEventsBinary) : { encode: encodeEnvelope, decode },\n );\n}\n\n/** The settings that follow from a codec: the codec itself and its `encode` and `decode`. */\nexport function codecSettings(\n chosen: RabbitMqCodec,\n): Pick<ResolvedTransportSettings, 'codec' | 'encode' | 'decode'> {\n if (chosen === cloudEventsBinary) {\n return { codec: chosen, encode: encodeEnvelope, decode: decodeEnvelope };\n }\n return {\n codec: chosen,\n encode: chosen.encode,\n decode: (message) => decodeRabbitMqMessage(chosen, message),\n };\n}\n\nfunction resolveConnect(\n options: RabbitMqTransportOptions,\n): (options: ConnectOptions) => Promise<AmqpConnection> {\n const { url, connect } = options;\n if ((url === undefined) === (connect === undefined)) {\n throw new ConfigurationError(\"Give exactly one of 'url' and 'connect'\");\n }\n if (connect !== undefined) {\n return connect;\n }\n return async ({ signal }) => {\n const amqplib = await import('amqplib');\n // amqplib hands its socket options to net.connect / tls.connect, which take a signal; its types omit it.\n const socketOptions = { signal } as unknown as Parameters<typeof amqplib.connect>[1];\n return amqplib.connect(url!, socketOptions);\n };\n}\n\nfunction resolveReconnect(\n reconnect: ReconnectOptions | false | undefined,\n): RetryPolicy | undefined {\n if (reconnect === false) {\n return undefined;\n }\n return createRetryPolicy({ ...reconnect, attempts: 1 }, DEFAULT_RECONNECT);\n}\n","import type { AmqpChannel } from './amqp-types.js';\n\n/** Names of the broker objects a subscribing transport owns. */\nexport interface ConsumerTopology {\n readonly exchange: string;\n readonly queue: string;\n readonly deadLetterExchange: string;\n readonly deadLetterQueue: string;\n readonly deliveryLimit: number;\n /** Single active consumer, so the queue is consumed strictly in order. */\n readonly ordered: boolean;\n /** TTLs of the retry queues, ascending; empty when ordered. */\n readonly retryDelaysMs: readonly number[];\n /** Routing-key patterns the queue is bound with. */\n readonly destinations: readonly string[];\n}\n\n/** Name of the retry queue that holds messages for `delayMs` before returning them to `queue`. */\nexport function retryQueueName(queue: string, delayMs: number): string {\n return `${queue}.retry.${delayMs}`;\n}\n\n/** Declares the durable topic exchange events are published to. Idempotent. */\nexport async function assertExchange(channel: AmqpChannel, exchange: string): Promise<void> {\n await channel.assertExchange(exchange, 'topic', { durable: true });\n}\n\n/**\n * Declares the consumer side, all durable quorum queues and idempotent:\n *\n * - the main queue with a dead-letter exchange, `x-dead-letter-strategy`\n * `at-least-once` (which requires `x-overflow` `reject-publish`),\n * `x-delivery-limit` as a backstop for crash loops, and optionally\n * `x-single-active-consumer`; bound to the topic exchange once per destination;\n * - one retry queue per delay tier: a queue-level `x-message-ttl`, expired\n * messages dead-lettered through the default exchange back to the main queue;\n * - a direct dead-letter exchange and the dead-letter queue, bound with the main\n * queue's name as routing key.\n *\n * Declaring an existing queue with different arguments makes the broker close\n * the channel (`PRECONDITION_FAILED`); see the README for migrating a queue\n * created by an older version or with other options.\n */\nexport async function assertConsumerTopology(\n channel: AmqpChannel,\n topology: ConsumerTopology,\n): Promise<void> {\n await assertExchange(channel, topology.exchange);\n await channel.assertExchange(topology.deadLetterExchange, 'direct', { durable: true });\n await channel.assertQueue(topology.deadLetterQueue, {\n durable: true,\n arguments: { 'x-queue-type': 'quorum' },\n });\n await channel.bindQueue(topology.deadLetterQueue, topology.deadLetterExchange, topology.queue);\n for (const delayMs of topology.retryDelaysMs) {\n await channel.assertQueue(retryQueueName(topology.queue, delayMs), {\n durable: true,\n arguments: {\n 'x-queue-type': 'quorum',\n 'x-message-ttl': delayMs,\n 'x-dead-letter-exchange': '',\n 'x-dead-letter-routing-key': topology.queue,\n 'x-dead-letter-strategy': 'at-least-once',\n 'x-overflow': 'reject-publish',\n },\n });\n }\n await channel.assertQueue(topology.queue, {\n durable: true,\n arguments: {\n 'x-queue-type': 'quorum',\n 'x-delivery-limit': topology.deliveryLimit,\n 'x-dead-letter-exchange': topology.deadLetterExchange,\n 'x-dead-letter-routing-key': topology.queue,\n 'x-dead-letter-strategy': 'at-least-once',\n 'x-overflow': 'reject-publish',\n ...(topology.ordered ? { 'x-single-active-consumer': true } : {}),\n },\n });\n for (const destination of topology.destinations) {\n await channel.bindQueue(topology.queue, topology.exchange, destination);\n }\n}\n","import {\n computeRetryDelay,\n isRetryableError,\n toErrorInfo,\n type EventEnvelope,\n} from '@relaybus/core';\nimport { abortableSleep } from './abortable-sleep.js';\nimport type { AmqpChannel, AmqpMessage } from './amqp-types.js';\nimport { RabbitMqUnavailableError } from './errors.js';\nimport {\n DEAD_LETTER_ERROR_CODE_HEADER,\n DEAD_LETTER_ERROR_NAME_HEADER,\n DEAD_LETTER_REASON_HEADER,\n FIRST_FAILURE_HEADER,\n ORIGINAL_ROUTING_KEY_HEADER,\n REDELIVERIES_HEADER,\n chooseRetryTier,\n copyForRepublish,\n originalRoutingKey,\n readCounterHeader,\n withOriginalRoutingKey,\n} from './redelivery.js';\nimport type {\n DeadLetterInput,\n ProcessedMessage,\n QueueConsumerSettings,\n RedeliverLaterInput,\n} from './queue-consumer-types.js';\nimport { retryQueueName } from './topology.js';\n\nexport type { ConfirmedRepublish, QueueConsumerSettings } from './queue-consumer-types.js';\n\ntype Settlement = 'ack' | 'requeue' | 'dead-letter';\n\n/**\n * Consumes one queue with manual acknowledgements.\n *\n * A message is acknowledged only after the handler resolved. When the handler\n * fails it is first retried on the same delivery with short backoff\n * (`handlerRetry`). If that does not help, a copy goes to the retry queue whose\n * TTL matches the next backoff step, and the original is acknowledged only\n * after the broker confirmed the copy; the copy returns to the main queue when\n * its TTL expires. This waits out a long outage of the handler's dependency.\n *\n * Malformed messages, non-retryable errors and messages that kept failing for\n * `redeliveryMaxAgeMs` go to the dead-letter exchange through a confirmed copy\n * (carrying the reason, without retry state, so a replay starts fresh) and the\n * original is acknowledged afterwards. If a copy cannot be confirmed the\n * original is requeued or rejected without requeue, which makes the broker\n * dead-letter it; it is never acknowledged unprocessed, so nothing is lost.\n *\n * In ordered mode nothing is moved: the failing message is retried in place with\n * the same backoff, holding the queue.\n */\nexport class QueueConsumer {\n readonly #settings: QueueConsumerSettings;\n readonly #inFlight = new Set<Promise<void>>();\n readonly #stopping = new AbortController();\n #channel: AmqpChannel | undefined;\n #consumerTag: string | undefined;\n\n constructor(settings: QueueConsumerSettings) {\n this.#settings = settings;\n }\n\n /** True while a consumer is registered on a live channel. */\n isActive(): boolean {\n return this.#consumerTag !== undefined;\n }\n\n /**\n * Starts consuming on a channel whose topology is already declared.\n *\n * @throws {RabbitMqUnavailableError} the channel closed while it was being set up\n */\n async attach(channel: AmqpChannel): Promise<void> {\n let closedDuringSetup = false;\n channel.on('error', (error: Error) => {\n this.#settings.logger.warn(\n `[QueueConsumer](attach) Channel error | queue=${this.#settings.queue} error=${error.message}`,\n );\n });\n channel.on('close', () => {\n closedDuringSetup = true;\n if (this.#channel === channel) {\n this.#channel = undefined;\n this.#consumerTag = undefined;\n this.#settings.onConsumerLost('consumer channel closed');\n }\n });\n await channel.prefetch(this.#settings.prefetch);\n const { consumerTag } = await channel.consume(\n this.#settings.queue,\n (message) => this.#receive(channel, message),\n { noAck: false },\n );\n if (closedDuringSetup) {\n throw new RabbitMqUnavailableError(\n `[QueueConsumer](attach) Consumer channel closed while the consumer was being set up | queue=${this.#settings.queue}`,\n );\n }\n this.#channel = channel;\n this.#consumerTag = consumerTag;\n }\n\n /** Forgets the channel without closing it, because its connection is gone. */\n detach(): void {\n this.#channel = undefined;\n this.#consumerTag = undefined;\n }\n\n /**\n * Stops taking messages, aborts pending handler backoff (those messages are\n * requeued), waits up to the shutdown timeout for running handlers, then\n * closes the channel. Unacknowledged messages return to the queue.\n */\n async stop(): Promise<void> {\n this.#stopping.abort();\n const channel = this.#channel;\n const consumerTag = this.#consumerTag;\n this.#channel = undefined;\n this.#consumerTag = undefined;\n if (channel !== undefined && consumerTag !== undefined) {\n await channel.cancel(consumerTag).catch((error: unknown) => {\n this.#settings.logger.warn(\n `[QueueConsumer](stop) Could not cancel consumer | queue=${this.#settings.queue} error=${toErrorInfo(error).message}`,\n );\n });\n }\n await this.#awaitInFlight();\n await channel?.close().catch(() => undefined);\n }\n\n async #awaitInFlight(): Promise<void> {\n if (this.#inFlight.size === 0) {\n return;\n }\n const timeout = new AbortController();\n const timedOut = abortableSleep(this.#settings.shutdownTimeoutMs, timeout.signal);\n await Promise.race([Promise.allSettled([...this.#inFlight]), timedOut]);\n timeout.abort();\n }\n\n #receive(channel: AmqpChannel, message: AmqpMessage | null): void {\n if (message === null) {\n this.#consumerTag = undefined;\n this.#settings.onConsumerLost('consumer cancelled by the broker');\n return;\n }\n const task: Promise<void> = this.#process(channel, message).finally(() => {\n this.#inFlight.delete(task);\n });\n this.#inFlight.add(task);\n }\n\n async #process(channel: AmqpChannel, message: AmqpMessage): Promise<void> {\n const decoded = await this.#decodeOrDeadLetter(channel, message);\n if (decoded === undefined) {\n return;\n }\n const { envelope } = decoded;\n const delivery: ProcessedMessage = {\n channel,\n message,\n envelope,\n redeliveries: readCounterHeader(message, REDELIVERIES_HEADER) ?? 0,\n firstFailureAt: readCounterHeader(message, FIRST_FAILURE_HEADER),\n };\n for (let attempt = 1; ; attempt += 1) {\n try {\n await this.#settings.onMessage(envelope, { destination: message.fields.routingKey });\n this.#settle(channel, { message, settlement: 'ack' });\n return;\n } catch (error) {\n if ((await this.#afterFailure(delivery, { attempt, error })) === 'settled') {\n return;\n }\n }\n }\n }\n\n /** The event of `message`, or undefined after dead-lettering a message that is not one. */\n async #decodeOrDeadLetter(\n channel: AmqpChannel,\n message: AmqpMessage,\n ): Promise<{ readonly envelope: EventEnvelope } | undefined> {\n try {\n return { envelope: this.#settings.decode(withOriginalRoutingKey(message)) };\n } catch (error) {\n this.#settings.logger.error(\n `[QueueConsumer](decodeOrDeadLetter) Dead-lettering malformed message | queue=${this.#settings.queue} routingKey=${message.fields.routingKey} ${describeError(error)}`,\n );\n this.#settings.onInvalidMessage?.({ destination: message.fields.routingKey, error });\n await this.#deadLetter(channel, { message, reason: 'malformed message', error });\n return undefined;\n }\n }\n\n /**\n * Decides what follows a failed attempt: dead-letter a non-retryable error, retry on the same\n * delivery while local attempts remain, else redeliver later. `retry` runs the handler again.\n */\n async #afterFailure(\n delivery: ProcessedMessage,\n { attempt, error }: { readonly attempt: number; readonly error: unknown },\n ): Promise<'retry' | 'settled'> {\n const { channel, message, envelope } = delivery;\n const { queue, handlerRetry } = this.#settings;\n const failure = `queue=${queue} eventId=${envelope.id} attempt=${attempt} ${describeError(error)}`;\n if (!isRetryableError(handlerRetry, error)) {\n this.#settings.logger.error(\n `[QueueConsumer](afterFailure) Dead-lettering message the handler cannot process | ${failure}`,\n );\n await this.#deadLetter(channel, {\n message,\n reason: 'non-retryable handler error',\n error,\n });\n return 'settled';\n }\n if (attempt < handlerRetry.attempts) {\n const delayMs = computeRetryDelay(handlerRetry, attempt, this.#settings.random);\n this.#settings.logger.warn(\n `[QueueConsumer](afterFailure) Handler failed, retrying | ${failure} delayMs=${delayMs}`,\n );\n return this.#waitOrRequeue(delivery, delayMs);\n }\n return this.#afterSpentAttempts(delivery, { failure, error });\n }\n\n /**\n * The local attempts are spent: dead-letter a message that kept failing past `redeliveryMaxAgeMs`,\n * else park it in a retry queue, or, when ordered, wait and retry it in place.\n */\n async #afterSpentAttempts(\n delivery: ProcessedMessage,\n { failure, error }: { readonly failure: string; readonly error: unknown },\n ): Promise<'retry' | 'settled'> {\n const { channel, message } = delivery;\n delivery.redeliveries += 1;\n const now = Date.now();\n delivery.firstFailureAt ??= now;\n const { redeliveries, firstFailureAt } = delivery;\n const delayMs = this.#redeliveryDelay(redeliveries);\n if (now + delayMs - firstFailureAt > this.#settings.redeliveryMaxAgeMs) {\n this.#settings.logger.error(\n `[QueueConsumer](afterSpentAttempts) Dead-lettering message that kept failing | ${failure} redeliveries=${redeliveries - 1} failingForMs=${now - firstFailureAt} maxAgeMs=${this.#settings.redeliveryMaxAgeMs}`,\n );\n await this.#deadLetter(channel, {\n message,\n reason: 'redelivery window exhausted',\n error,\n });\n return 'settled';\n }\n this.#settings.logger.warn(\n `[QueueConsumer](afterSpentAttempts) Handler attempts spent, retrying later | ${failure} redeliveries=${redeliveries} delayMs=${delayMs}`,\n );\n if (!this.#settings.ordered) {\n await this.#redeliverLater(channel, { message, delayMs, redeliveries, firstFailureAt });\n return 'settled';\n }\n return this.#waitOrRequeue(delivery, delayMs);\n }\n\n /** Waits `delayMs` before the next attempt; requeues instead when the consumer stops meanwhile. */\n async #waitOrRequeue(delivery: ProcessedMessage, delayMs: number): Promise<'retry' | 'settled'> {\n if (await this.#interrupted(delayMs)) {\n this.#settle(delivery.channel, { message: delivery.message, settlement: 'requeue' });\n return 'settled';\n }\n return 'retry';\n }\n\n /** The backoff before the next delayed redelivery: a retry queue's TTL, or an exact wait when ordered. */\n #redeliveryDelay(redeliveries: number): number {\n const { redelivery, retryLadder, ordered, random } = this.#settings;\n const delayMs = computeRetryDelay(redelivery, redeliveries, random);\n return ordered ? delayMs : chooseRetryTier(retryLadder, { delayMs, random });\n }\n\n /** Sleeps; true when the consumer is stopping, so the caller must give the message back. */\n async #interrupted(delayMs: number): Promise<boolean> {\n await abortableSleep(delayMs, this.#stopping.signal);\n return this.#stopping.signal.aborted;\n }\n\n /**\n * Parks a copy in the retry queue of `delayMs` and acknowledges the original\n * only once the broker confirmed the copy. When the copy cannot be confirmed\n * the original is requeued after the same delay, so it is neither lost nor\n * hot-looped.\n */\n async #redeliverLater(channel: AmqpChannel, input: RedeliverLaterInput): Promise<void> {\n const { message, delayMs, redeliveries, firstFailureAt } = input;\n const { content, options } = copyForRepublish(message, {\n [REDELIVERIES_HEADER]: String(redeliveries),\n [FIRST_FAILURE_HEADER]: String(firstFailureAt),\n [ORIGINAL_ROUTING_KEY_HEADER]: originalRoutingKey(message),\n });\n try {\n await this.#settings.republish(\n { exchange: '', routingKey: retryQueueName(this.#settings.queue, delayMs) },\n { content, options },\n );\n } catch (error) {\n this.#settings.logger.warn(\n `[QueueConsumer](redeliverLater) Could not park the message in the retry queue, requeueing it | queue=${this.#settings.queue} delayMs=${delayMs} error=${toErrorInfo(error).message}`,\n );\n await this.#interrupted(delayMs);\n this.#settle(channel, { message, settlement: 'requeue' });\n return;\n }\n this.#settle(channel, { message, settlement: 'ack' });\n }\n\n /**\n * Moves the message to the dead-letter queue through a confirmed copy that\n * carries the reason and no retry state. If the copy cannot be confirmed the\n * message is rejected without requeue, which makes the broker dead-letter it\n * (at-least-once), so it still ends up in the dead-letter queue.\n */\n async #deadLetter(channel: AmqpChannel, input: DeadLetterInput): Promise<void> {\n const { message, reason, error } = input;\n const { name, code } = toErrorInfo(error);\n const { content, options } = copyForRepublish(message, {\n [DEAD_LETTER_REASON_HEADER]: reason,\n [DEAD_LETTER_ERROR_NAME_HEADER]: name,\n ...(code === undefined ? {} : { [DEAD_LETTER_ERROR_CODE_HEADER]: code }),\n });\n try {\n await this.#settings.republish(\n { exchange: this.#settings.deadLetterExchange, routingKey: this.#settings.queue },\n { content, options },\n );\n } catch (error) {\n this.#settings.logger.warn(\n `[QueueConsumer](deadLetter) Could not publish to the dead-letter exchange, leaving it to the broker | queue=${this.#settings.queue} error=${toErrorInfo(error).message}`,\n );\n this.#settle(channel, { message, settlement: 'dead-letter' });\n return;\n }\n this.#settle(channel, { message, settlement: 'ack' });\n }\n\n #settle(\n channel: AmqpChannel,\n { message, settlement }: { readonly message: AmqpMessage; readonly settlement: Settlement },\n ): void {\n try {\n if (settlement === 'ack') {\n channel.ack(message);\n } else {\n channel.nack(message, false, settlement === 'requeue');\n }\n } catch (error) {\n // The channel is gone; the broker redelivers the message and the inbox drops the duplicate.\n this.#settings.logger.warn(\n `[QueueConsumer](settle) Could not ${settlement} message, the broker will redeliver it | queue=${this.#settings.queue} error=${toErrorInfo(error).message}`,\n );\n }\n }\n}\n\n/** Log fields of an error: its message, class name and, for relaybus errors, its code. */\nfunction describeError(error: unknown): string {\n const { message, name, code } = toErrorInfo(error);\n return `error=${message} errorName=${name}${code === undefined ? '' : ` code=${code}`}`;\n}\n","/** Runs async tasks one after another, in submission order, even when one fails. */\nexport class SerialQueue {\n #tail: Promise<unknown> = Promise.resolve();\n\n run<TResult>(task: () => Promise<TResult>): Promise<TResult> {\n const result = this.#tail.then(task);\n this.#tail = result.catch(() => undefined);\n return result;\n }\n}\n","import {\n ConfigurationError,\n WireTypesUnsupportedError,\n type CloseOptions,\n type EventEnvelope,\n} from '@relaybus/core';\nimport {\n SubscribingTransport,\n withDeclaredWireTypes,\n type TransportSubscription,\n} from '@relaybus/core/internal';\nimport type { AmqpConnection, AmqpMessage } from './amqp-types.js';\nimport {\n ConfirmedPublishing,\n recordUnroutable,\n unroutableKey,\n type Publisher,\n} from './confirmed-publishing.js';\nimport { ConnectionSupervisor } from './connection-supervisor.js';\nimport { RabbitMqUnavailableError } from './errors.js';\nimport {\n codecSettings,\n resolveQueueName,\n resolveSettings,\n type RabbitMqTransportOptions,\n type ResolvedTransportSettings,\n} from './options.js';\nimport { QueueConsumer } from './queue-consumer.js';\nimport { SerialQueue } from './serial-queue.js';\nimport { assertConsumerTopology, assertExchange, type ConsumerTopology } from './topology.js';\nimport { assertShortString } from './wire-format.js';\n\ninterface LiveConnection {\n readonly connection: AmqpConnection;\n readonly publisher: Publisher;\n}\n\ninterface Subscription {\n readonly topology: ConsumerTopology;\n readonly consumer: QueueConsumer;\n}\n\n/**\n * RabbitMQ {@link Transport} built on amqplib.\n *\n * Publishing: each event goes to a durable topic exchange as a persistent,\n * mandatory message with the destination as routing key. `publish` resolves\n * only after the broker confirmed it was persisted and routed to a queue, and\n * rejects when the transport is disconnected, the broker nacks, the message is\n * unroutable or no confirm arrives in time. It never drops a message silently,\n * so the outbox retries the delivery.\n *\n * Subscribing: one durable quorum queue per consumer group, bound to the\n * destinations (routing-key patterns such as `orders.*`). A message is\n * acknowledged only after the handler resolved. A failing handler is retried\n * on the same delivery, then through retry queues with growing delays (see\n * `redelivery`), and finally dead-lettered after the retry window; poison\n * messages are dead-lettered at once. Nothing is lost on the way.\n *\n * Reconnection: after a connection or channel loss the transport reconnects\n * with capped, jittered backoff and restores channels, topology and the\n * consumer. Events published meanwhile are rejected, and therefore retried by\n * the outbox, rather than buffered in memory.\n */\nexport class RabbitMqTransport extends SubscribingTransport {\n readonly name: string;\n readonly system = 'rabbitmq';\n #settings: ResolvedTransportSettings;\n readonly #supervisor: ConnectionSupervisor;\n readonly #publishing: ConfirmedPublishing;\n /** Serializes topology work so a subscription never races a reconnect. */\n readonly #topologyWork = new SerialQueue();\n #live: LiveConnection | undefined;\n #subscription: Subscription | undefined;\n #closing: Promise<void> | undefined;\n /** Set when the transport first connects, publishes or subscribes: its wire format is fixed from then on. */\n #used = false;\n\n constructor(options: RabbitMqTransportOptions) {\n super();\n this.#settings = resolveSettings(options);\n this.name = this.#settings.name;\n this.#publishing = new ConfirmedPublishing(this.name, this.#settings.publishTimeoutMs);\n this.#supervisor = new ConnectionSupervisor({\n connect: this.#settings.connect,\n reconnect: this.#settings.reconnect,\n onConnected: (connection) => this.#establishChannels(connection),\n onDisconnected: () => this.#forgetConnection(),\n logger: this.#settings.logger,\n random: this.#settings.random,\n });\n }\n\n /**\n * True while the connection is open and publishing and consuming are set up.\n * Use it for readiness probes.\n */\n isConnected(): boolean {\n return this.#supervisor.isConnected();\n }\n\n /**\n * True when the transport can publish and, once subscribed, is consuming: the\n * connection is up, its channels are open and the consumer is registered. False while reconnecting and after a cancelled consumer.\n */\n isReady(): boolean {\n return (\n this.#supervisor.isConnected() &&\n this.#live !== undefined &&\n (this.#subscription === undefined || this.#subscription.consumer.isActive())\n );\n }\n\n /** Connects to the broker. Rejects when it is unreachable unless `failOnConnectError` is false. */\n async connect(): Promise<void> {\n this.#used = true;\n await this.#supervisor.start(this.#settings.failOnConnectError);\n }\n\n /**\n * Publishes to the exchange with `destination` as routing key and resolves\n * after the broker confirmed the message.\n *\n * @throws {UnserializablePayloadError} the payload is not representable as JSON (never retried)\n * @throws {AmqpLimitExceededError} the event id, a header name or `destination` exceeds 255 bytes (never retried)\n * @throws {RabbitMqUnavailableError} not connected, channel lost, or confirm timed out\n * @throws {RabbitMqPublishRejectedError} the broker nacked the message\n * @throws {UnroutableMessageError} no queue is bound to `destination` (unless `allowUnroutable`)\n * @throws whatever the `codec`'s `encode` throws, such as {@link RabbitMqUnencodableEventError}\n */\n /**\n * Checks the wire names a route or catalog declares and returns the function that makes the codec\n * write and read events under them. The bus calls it when it is created, before the transport\n * connects.\n *\n * @throws WireTypesUnsupportedError when the codec does not map type names (use `jsonEnvelope`),\n * WireTypeCollisionError when a name clashes with one of the codec's own `wireTypes`.\n */\n declareWireTypes(wireTypes: Readonly<Record<string, string>>): () => void {\n if (this.#used) {\n throw new WireTypesUnsupportedError(\n `Transport '${this.name}' already started; declare wire names before it connects or subscribes`,\n );\n }\n const codec = withDeclaredWireTypes(this.#settings.codec, { wireTypes, transport: this.name });\n return () => {\n this.#settings = { ...this.#settings, ...codecSettings(codec) };\n };\n }\n\n async publish(envelope: EventEnvelope, destination: string): Promise<void> {\n this.#used = true;\n assertShortString('Destination (routing key)', destination);\n const { content, options } = this.#settings.encode(envelope);\n await this.#publishing.publish(this.#live?.publisher, {\n exchange: this.#settings.exchange,\n routingKey: destination,\n content,\n options,\n mandatory: !this.#settings.allowUnroutable,\n });\n }\n\n /**\n * Binds one durable quorum queue to `destinations` and delivers its messages\n * to `onMessage`. Call it once per transport; give each subscription its own\n * transport instance, with its own `name` and `consumerGroup`.\n */\n protected async openSubscription({\n destinations,\n onMessage,\n hooks,\n }: TransportSubscription): Promise<void> {\n this.#used = true;\n if (this.#subscription !== undefined) {\n throw new ConfigurationError(\n `Transport '${this.name}' already has a subscription; create another transport for another consumer group`,\n );\n }\n if (destinations.length === 0) {\n throw new ConfigurationError(`Transport '${this.name}' needs at least one destination`);\n }\n const queue = resolveQueueName(this.#settings);\n const subscription: Subscription = {\n topology: this.#topologyOf(queue, destinations),\n consumer: this.#createConsumer(queue, { onMessage, hooks }),\n };\n await this.#topologyWork.run(async () => {\n this.#subscription = subscription;\n if (this.#live !== undefined) {\n await this.#startConsuming(this.#live.connection, subscription);\n }\n });\n }\n\n #topologyOf(queue: string, destinations: readonly string[]): ConsumerTopology {\n return {\n exchange: this.#settings.exchange,\n queue,\n deadLetterExchange: this.#settings.deadLetterExchange,\n deadLetterQueue: this.#settings.deadLetterQueue ?? `${queue}.dead`,\n deliveryLimit: this.#settings.deliveryLimit,\n ordered: this.#settings.ordered,\n retryDelaysMs: this.#settings.retryLadder,\n destinations,\n };\n }\n\n #createConsumer(\n queue: string,\n { onMessage, hooks }: Pick<TransportSubscription, 'onMessage' | 'hooks'>,\n ): QueueConsumer {\n return new QueueConsumer({\n queue,\n prefetch: this.#settings.prefetch,\n handlerRetry: this.#settings.handlerRetry,\n redelivery: this.#settings.redelivery,\n retryLadder: this.#settings.retryLadder,\n redeliveryMaxAgeMs: this.#settings.redeliveryMaxAgeMs,\n ordered: this.#settings.ordered,\n deadLetterExchange: this.#settings.deadLetterExchange,\n republish: ({ exchange, routingKey }, { content, options }) =>\n this.#publishing.publish(this.#live?.publisher, {\n exchange,\n routingKey,\n content,\n options,\n mandatory: true,\n }),\n shutdownTimeoutMs: this.#settings.shutdownTimeoutMs,\n onMessage,\n ...(hooks === undefined ? {} : { onInvalidMessage: hooks.onInvalidMessage }),\n decode: this.#settings.decode,\n onConsumerLost: (reason) => this.#supervisor.recover(reason),\n logger: this.#settings.logger,\n random: this.#settings.random,\n });\n }\n\n /**\n * Stops consuming, waits up to `shutdownTimeout` for running handlers\n * (messages still being retried go back to the queue), then closes the\n * channels and the connection. Once `options.signal` aborts (the bus shutdown deadline passed),\n * the connection's socket is destroyed instead of waiting for the broker.\n */\n async close(options: CloseOptions = {}): Promise<void> {\n this.#used = true;\n const { signal } = options;\n const force = (): void => this.#supervisor.forceClose();\n if (signal?.aborted === true) {\n force();\n }\n signal?.addEventListener('abort', force, { once: true });\n try {\n // A second call shares the work of the first, and its signal can still cut the connection.\n this.#closing ??= this.#supervisor.close(() =>\n this.#topologyWork.run(async () => {\n const live = this.#live;\n this.#live = undefined;\n await this.#subscription?.consumer.stop();\n await live?.publisher.channel.close().catch(() => undefined);\n }),\n );\n await this.#closing;\n } finally {\n signal?.removeEventListener('abort', force);\n }\n }\n\n async #establishChannels(connection: AmqpConnection): Promise<void> {\n await this.#topologyWork.run(async () => {\n const channel = await connection.createConfirmChannel();\n const publisher: Publisher = { channel, unroutable: new Map(), closed: false };\n channel.on('error', (error: Error) => {\n this.#settings.logger.warn(\n `[RabbitMqTransport](establishChannels) Publisher channel error | transport=${this.name} error=${error.message}`,\n );\n });\n channel.on('close', () => {\n publisher.closed = true;\n if (this.#live?.publisher === publisher) {\n this.#supervisor.recover('publisher channel closed');\n }\n });\n channel.on('return', (message: AmqpMessage) => {\n recordUnroutable(\n publisher.unroutable,\n unroutableKey(message.properties.messageId, message.fields.routingKey),\n );\n });\n await assertExchange(channel, this.#settings.exchange);\n if (this.#subscription !== undefined) {\n await this.#startConsuming(connection, this.#subscription);\n }\n if (publisher.closed) {\n // The close came before `live` was set, so nothing reacted to it.\n throw new RabbitMqUnavailableError(\n `[RabbitMqTransport](establishChannels) Publisher channel closed while the transport was being set up | transport=${this.name}`,\n );\n }\n this.#live = { connection, publisher };\n });\n }\n\n async #startConsuming(connection: AmqpConnection, subscription: Subscription): Promise<void> {\n const channel = await connection.createChannel();\n await assertConsumerTopology(channel, subscription.topology);\n await subscription.consumer.attach(channel);\n }\n\n #forgetConnection(): void {\n this.#live = undefined;\n this.#subscription?.consumer.detach();\n }\n}\n"]}