itd-api 0.0.5 → 0.0.6

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/builders/base.ts","../src/core/errors.ts","../src/builders/comment.ts","../src/builders/poll.ts","../src/builders/post.ts","../src/types/enums.ts","../src/builders/report.ts","../node_modules/set-cookie-parser/lib/set-cookie.js","../src/core/cookies.ts","../src/core/emitter.ts","../src/core/runtime.ts","../src/core/auth.ts","../src/core/storage.ts","../src/core/url.ts","../src/core/config.ts","../src/core/redact.ts","../src/core/unwrap.ts","../src/core/error-factory.ts","../src/core/http.ts","../src/core/plugins.ts","../src/core/rate-limit.ts","../src/core/retry.ts","../src/notifications/type-map.ts","../src/notifications/normalize.ts","../src/realtime/transport.ts","../src/realtime/poll.ts","../src/realtime/reconnect.ts","../node_modules/eventsource-parser/src/errors.ts","../node_modules/eventsource-parser/src/parse.ts","../src/realtime/sse.ts","../src/realtime/stream.ts","../src/core/pagination.ts","../src/resources/base.ts","../src/resources/auth.ts","../src/resources/comments.ts","../src/core/mime.ts","../src/resources/files.ts","../src/resources/misc.ts","../src/resources/notifications.ts","../src/resources/posts.ts","../src/resources/users.ts","../src/client.ts","../src/notifications/text.ts","../src/notifications/url.ts","../src/types/models.ts"],"names":["value","cookies","start","text","duration","trailing","line"],"mappings":";AACO,IAAM,OAAA,mBAAU,MAAA,CAAO,GAAA,CAAI,aAAa,CAAA;AAkCxC,SAAS,UAAa,KAAA,EAAwC;AACnE,EAAA,OAAO,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,KAAU,QAAQ,OAAA,IAAW,KAAA;AACnE;AAYO,SAAS,YAAA,CACd,KAAA,EACA,OAAA,EACA,QAAA,EACG;AACH,EAAA,IAAI,OAAO,UAAU,UAAA,EAAY;AAC/B,IAAA,MAAM,MAAA,GAAU,KAAA,CAAgC,OAAA,EAAS,CAAA;AACzD,IAAA,OAAO,UAAa,MAAM,CAAA,GAAI,OAAO,KAAA,EAAM,GAAI,SAAS,MAAW,CAAA;AAAA,EACrE;AAEA,EAAA,IAAI,SAAA,CAAa,KAAK,CAAA,EAAG,OAAO,MAAM,KAAA,EAAM;AAE5C,EAAA,OAAO,SAAS,KAAU,CAAA;AAC5B;;;AC3DA,IAAM,SAAA,mBAAY,MAAA,CAAO,GAAA,CAAI,WAAW,CAAA;AAOjC,IAAM,YAAA,GAAe,OAAO,MAAA,CAAO;AAAA;AAAA,EAExC,GAAA,EAAK,KAAA;AAAA;AAAA,EAEL,OAAA,EAAS,SAAA;AAAA;AAAA,EAET,OAAA,EAAS,SAAA;AAAA;AAAA,EAET,KAAA,EAAO,OAAA;AAAA;AAAA,EAEP,MAAA,EAAQ;AACV,CAAU;AAUH,IAAM,eAAA,GAAkB,OAAO,MAAA,CAAO;AAAA;AAAA,EAE3C,OAAA,EAAS,SAAA;AAAA,EACT,UAAA,EAAY,YAAA;AAAA,EACZ,IAAA,EAAM,MAAA;AAAA,EACN,SAAA,EAAW,WAAA;AAAA,EACX,QAAA,EAAU,WAAA;AAAA,EACV,QAAA,EAAU,UAAA;AAAA,EACV,SAAA,EAAW,YAAA;AAAA,EACX,iBAAA,EAAmB,oBAAA;AAAA,EACnB,MAAA,EAAQ;AACV,CAAU;AAsBH,IAAM,QAAA,GAAN,cAAuB,KAAA,CAAM;AAAA;AAAA,EAElC,CAAU,SAAS,IAAI,IAAA;AAAA;AAAA,EAGd,IAAA;AAAA,EAET,WAAA,CAAY,IAAA,EAAoB,OAAA,EAAiB,OAAA,EAA+B;AAC9E,IAAA,KAAA,CAAM,SAAS,OAAO,CAAA;AACtB,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AACZ,IAAA,IAAA,CAAK,IAAA,GAAO,UAAA;AAAA,EACd;AACF;AAmDO,IAAM,WAAA,GAAN,cAA0B,QAAA,CAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO/B,OAAA;AAAA;AAAA,EAEA,MAAA;AAAA;AAAA,EAEA,IAAA;AAAA;AAAA,EAEA,MAAA;AAAA;AAAA,EAEA,KAAA;AAAA;AAAA,EAEA,WAAA;AAAA;AAAA,EAEA,SAAA;AAAA;AAAA,EAEA,MAAA;AAAA;AAAA,EAEA,IAAA;AAAA;AAAA,EAEA,GAAA;AAAA;AAAA,EAEA,QAAA;AAAA;AAAA,EAEA,UAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,SAAA;AAAA;AAAA,EAEA,kBAAA;AAAA;AAAA;AAAA;AAAA,EAKT,WAAA,CAAY,IAAA,EAAuB,OAAA,GAA2B,eAAA,CAAgB,OAAA,EAAS;AACrF,IAAA,KAAA,CAAM,YAAA,CAAa,GAAA,EAAK,IAAA,CAAK,OAAO,CAAA;AACpC,IAAA,IAAA,CAAK,IAAA,GAAO,aAAA;AACZ,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA;AACf,IAAA,IAAA,CAAK,SAAS,IAAA,CAAK,MAAA;AACnB,IAAA,IAAA,CAAK,OAAO,IAAA,CAAK,IAAA;AACjB,IAAA,IAAA,CAAK,SAAS,IAAA,CAAK,MAAA;AACnB,IAAA,IAAA,CAAK,QAAQ,IAAA,CAAK,KAAA;AAClB,IAAA,IAAA,CAAK,WAAA,GAAc,IAAA,CAAK,WAAA,IAAe,EAAC;AACxC,IAAA,IAAA,CAAK,YAAY,IAAA,CAAK,SAAA;AACtB,IAAA,IAAA,CAAK,SAAS,IAAA,CAAK,MAAA;AACnB,IAAA,IAAA,CAAK,OAAO,IAAA,CAAK,IAAA;AACjB,IAAA,IAAA,CAAK,MAAM,IAAA,CAAK,GAAA;AAChB,IAAA,IAAA,CAAK,WAAW,IAAA,CAAK,QAAA;AACrB,IAAA,IAAA,CAAK,aAAa,IAAA,CAAK,UAAA;AACvB,IAAA,IAAA,CAAK,YAAY,IAAA,CAAK,SAAA;AACtB,IAAA,IAAA,CAAK,qBAAqB,IAAA,CAAK,kBAAA;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,WAAW,KAAA,EAAgC;AACzC,IAAA,OAAO,KAAA,CAAM,QAAA,CAAS,IAAA,CAAK,IAAI,CAAA;AAAA,EACjC;AAAA;AAAA,EAGA,IAAI,WAAA,GAAuB;AACzB,IAAA,OAAO,IAAA,CAAK,MAAA,KAAW,GAAA,IAAO,IAAA,CAAK,MAAA,IAAU,GAAA;AAAA,EAC/C;AACF;AAGO,IAAM,kBAAA,GAAN,cAAiC,WAAA,CAAY;AAAA,EAClD,YAAY,IAAA,EAAuB;AACjC,IAAA,KAAA,CAAM,IAAA,EAAM,gBAAgB,UAAU,CAAA;AACtC,IAAA,IAAA,CAAK,IAAA,GAAO,oBAAA;AAAA,EACd;AACF;AAGO,IAAM,YAAA,GAAN,cAA2B,WAAA,CAAY;AAAA,EAC5C,YAAY,IAAA,EAAuB;AACjC,IAAA,KAAA,CAAM,IAAA,EAAM,gBAAgB,IAAI,CAAA;AAChC,IAAA,IAAA,CAAK,IAAA,GAAO,cAAA;AAAA,EACd;AACF;AAGO,IAAM,iBAAA,GAAN,cAAgC,WAAA,CAAY;AAAA,EACjD,YAAY,IAAA,EAAuB;AACjC,IAAA,KAAA,CAAM,IAAA,EAAM,gBAAgB,SAAS,CAAA;AACrC,IAAA,IAAA,CAAK,IAAA,GAAO,mBAAA;AAAA,EACd;AACF;AAGO,IAAM,gBAAA,GAAN,cAA+B,WAAA,CAAY;AAAA,EAChD,YAAY,IAAA,EAAuB;AACjC,IAAA,KAAA,CAAM,IAAA,EAAM,gBAAgB,QAAQ,CAAA;AACpC,IAAA,IAAA,CAAK,IAAA,GAAO,kBAAA;AAAA,EACd;AACF;AAGO,IAAM,gBAAA,GAAN,cAA+B,WAAA,CAAY;AAAA,EAChD,YAAY,IAAA,EAAuB;AACjC,IAAA,KAAA,CAAM,IAAA,EAAM,gBAAgB,QAAQ,CAAA;AACpC,IAAA,IAAA,CAAK,IAAA,GAAO,kBAAA;AAAA,EACd;AACF;AAQO,IAAM,iBAAA,GAAN,cAAgC,WAAA,CAAY;AAAA,EACjD,YAAY,IAAA,EAAuB;AACjC,IAAA,KAAA,CAAM,IAAA,EAAM,gBAAgB,SAAS,CAAA;AACrC,IAAA,IAAA,CAAK,IAAA,GAAO,mBAAA;AAAA,EACd;AACF;AAOO,IAAM,yBAAA,GAAN,cAAwC,WAAA,CAAY;AAAA;AAAA,EAEhD,eAAA;AAAA,EAET,YAAY,IAAA,EAAyD;AACnE,IAAA,KAAA,CAAM,IAAA,EAAM,gBAAgB,iBAAiB,CAAA;AAC7C,IAAA,IAAA,CAAK,IAAA,GAAO,2BAAA;AACZ,IAAA,IAAA,CAAK,eAAA,GAAkB,KAAK,MAAA,GACxB,CAAA,wCAAA,EAA2C,mBAAmB,IAAA,CAAK,MAAM,CAAC,CAAA,CAAA,GAC1E,MAAA;AAAA,EACN;AACF;AAGO,IAAM,cAAA,GAAN,cAA6B,WAAA,CAAY;AAAA,EAC9C,YAAY,IAAA,EAAuB;AACjC,IAAA,KAAA,CAAM,IAAA,EAAM,gBAAgB,MAAM,CAAA;AAClC,IAAA,IAAA,CAAK,IAAA,GAAO,gBAAA;AAAA,EACd;AACF;AAGO,IAAM,eAAA,GAAN,cAA8B,QAAA,CAAS;AAAA;AAAA,EAEnC,MAAA;AAAA;AAAA,EAEA,IAAA;AAAA,EAET,WAAA,CAAY,SAAiB,IAAA,EAAyD;AACpF,IAAA,KAAA,CAAM,aAAa,OAAA,EAAS,OAAA,EAAS,EAAE,KAAA,EAAO,IAAA,CAAK,OAAO,CAAA;AAC1D,IAAA,IAAA,CAAK,IAAA,GAAO,iBAAA;AACZ,IAAA,IAAA,CAAK,SAAS,IAAA,CAAK,MAAA;AACnB,IAAA,IAAA,CAAK,OAAO,IAAA,CAAK,IAAA;AAAA,EACnB;AACF;AAGO,IAAM,eAAA,GAAN,cAA8B,QAAA,CAAS;AAAA;AAAA,EAEnC,OAAA;AAAA;AAAA,EAEA,MAAA;AAAA;AAAA,EAEA,IAAA;AAAA,EAET,YAAY,IAAA,EAAyD;AACnE,IAAA,KAAA;AAAA,MACE,YAAA,CAAa,OAAA;AAAA,MACb,CAAA,qCAAA,EAAU,KAAK,MAAM,CAAA,CAAA,EAAI,KAAK,IAAI,CAAA,6FAAA,EAAqB,KAAK,OAAO,CAAA,aAAA;AAAA,KACrE;AACA,IAAA,IAAA,CAAK,IAAA,GAAO,iBAAA;AACZ,IAAA,IAAA,CAAK,UAAU,IAAA,CAAK,OAAA;AACpB,IAAA,IAAA,CAAK,SAAS,IAAA,CAAK,MAAA;AACnB,IAAA,IAAA,CAAK,OAAO,IAAA,CAAK,IAAA;AAAA,EACnB;AACF;AAGO,IAAM,aAAA,GAAN,cAA4B,QAAA,CAAS;AAAA,EAC1C,WAAA,CAAY,UAAU,iFAAA,EAAkB;AACtC,IAAA,KAAA,CAAM,YAAA,CAAa,OAAO,OAAO,CAAA;AACjC,IAAA,IAAA,CAAK,IAAA,GAAO,eAAA;AAAA,EACd;AACF;AAQO,IAAM,cAAA,GAAN,cAA6B,QAAA,CAAS;AAAA,EAC3C,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,YAAA,CAAa,QAAQ,OAAO,CAAA;AAClC,IAAA,IAAA,CAAK,IAAA,GAAO,gBAAA;AAAA,EACd;AACF;AAGO,SAAS,WAAW,KAAA,EAAmC;AAC5D,EAAA,OAAO,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,KAAU,QAAQ,SAAA,IAAa,KAAA;AACrE;AAGO,SAAS,cAAc,KAAA,EAAsC;AAClE,EAAA,OAAO,UAAA,CAAW,KAAK,CAAA,IAAK,KAAA,CAAM,SAAS,YAAA,CAAa,GAAA;AAC1D;AASA,SAAS,UAAA,CAAW,OAAgB,IAAA,EAAgC;AAClE,EAAA,OAAO,aAAA,CAAc,KAAK,CAAA,IAAK,KAAA,CAAM,OAAA,KAAY,IAAA;AACnD;AAGO,SAAS,qBAAqB,KAAA,EAA6C;AAChF,EAAA,OAAO,UAAA,CAAW,KAAA,EAAO,eAAA,CAAgB,UAAU,CAAA;AACrD;AAGO,SAAS,eAAe,KAAA,EAAuC;AACpE,EAAA,OAAO,UAAA,CAAW,KAAA,EAAO,eAAA,CAAgB,IAAI,CAAA;AAC/C;AAGO,SAAS,oBAAoB,KAAA,EAA4C;AAC9E,EAAA,OAAO,UAAA,CAAW,KAAA,EAAO,eAAA,CAAgB,SAAS,CAAA;AACpD;AAGO,SAAS,mBAAmB,KAAA,EAA2C;AAC5E,EAAA,OAAO,UAAA,CAAW,KAAA,EAAO,eAAA,CAAgB,QAAQ,CAAA;AACnD;AAGO,SAAS,mBAAmB,KAAA,EAA2C;AAC5E,EAAA,OAAO,UAAA,CAAW,KAAA,EAAO,eAAA,CAAgB,QAAQ,CAAA;AACnD;AAGO,SAAS,oBAAoB,KAAA,EAA4C;AAC9E,EAAA,OAAO,UAAA,CAAW,KAAA,EAAO,eAAA,CAAgB,SAAS,CAAA;AACpD;AAGO,SAAS,4BAA4B,KAAA,EAAoD;AAC9F,EAAA,OAAO,UAAA,CAAW,KAAA,EAAO,eAAA,CAAgB,iBAAiB,CAAA;AAC5D;AAGO,SAAS,iBAAiB,KAAA,EAAyC;AACxE,EAAA,OAAO,UAAA,CAAW,KAAA,EAAO,eAAA,CAAgB,MAAM,CAAA;AACjD;;;AC9XO,SAAS,gBAAgB,KAAA,EAA+C;AAC7E,EAAA,MAAM,UAAU,OAAO,KAAA,EAAO,OAAA,KAAY,QAAA,GAAW,MAAM,OAAA,GAAU,EAAA;AACrE,EAAA,MAAM,aAAA,GAAgB,KAAA,EAAO,aAAA,IAAiB,EAAC;AAC/C,EAAA,MAAM,KAAA,GAAQ,KAAA,EAAO,KAAA,IAAS,EAAC;AAE/B,EAAA,MAAM,UAAA,GAAa,OAAA,CAAQ,IAAA,EAAK,KAAM,EAAA;AACtC,EAAA,MAAM,cAAA,GAAiB,aAAA,CAAc,MAAA,GAAS,CAAA,IAAK,MAAM,MAAA,GAAS,CAAA;AAElE,EAAA,IAAI,CAAC,UAAA,IAAc,CAAC,cAAA,EAAgB;AAClC,IAAA,MAAM,IAAI,eAAe,gOAA4C,CAAA;AAAA,EACvE;AAEA,EAAA,OAAO,KAAA;AACT;AAGA,SAAS,cAAc,KAAA,EAA2B;AAChD,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,IAAA,EAAK,KAAM,EAAA,EAAI;AAC/B,IAAA,MAAM,IAAI,cAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AAEA,EAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,KAAA,CAAM,MAAA,GAAS,MAAM,aAAA,CAAc,MAAA;AACvD,EAAA,IAAI,UAAU,CAAA,EAAG;AACf,IAAA,MAAM,IAAI,cAAA;AAAA,MACR,kWAAqE,KAAK,CAAA;AAAA,KAC5E;AAAA,EACF;AACF;AAOO,IAAM,cAAA,GAAN,MAAM,eAAA,CAAyD;AAAA;AAAA,EAEpE,CAAU,OAAO,IAAI,IAAA;AAAA,EAEZ,MAAA;AAAA;AAAA,EAGT,YAAY,KAAA,EAAqB;AAC/B,IAAA,IAAA,CAAK,MAAA,GAAS,KAAA;AAAA,EAChB;AAAA;AAAA,EAGA,QAAQ,IAAA,EAA8B;AACpC,IAAA,OAAO,IAAI,gBAAe,EAAE,GAAG,KAAK,MAAA,EAAQ,OAAA,EAAS,MAAM,CAAA;AAAA,EAC7D;AAAA;AAAA,EAGA,OAAO,IAAA,EAAiC;AACtC,IAAA,OAAO,IAAI,eAAA,CAAe,EAAE,GAAG,KAAK,MAAA,EAAQ,KAAA,EAAO,CAAC,GAAG,IAAA,CAAK,MAAA,CAAO,KAAA,EAAO,IAAI,GAAG,CAAA;AAAA,EACnF;AAAA;AAAA,EAGA,SAAS,YAAA,EAAsC;AAC7C,IAAA,OAAO,IAAI,eAAA,CAAe;AAAA,MACxB,GAAG,IAAA,CAAK,MAAA;AAAA,MACR,eAAe,CAAC,GAAG,IAAA,CAAK,MAAA,CAAO,eAAe,YAAY;AAAA,KAC3D,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,KAAA,EAAkC;AACtC,IAAA,OAAO,IAAI,eAAA,CAAe,EAAE,GAAG,IAAA,CAAK,MAAA,EAAQ,KAAA,EAAO,CAAC,KAAK,CAAA,EAAG,KAAA,EAAO,IAAA,EAAM,CAAA;AAAA,EAC3E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,QAAQ,MAAA,EAAgC;AACtC,IAAA,OAAO,IAAI,gBAAe,EAAE,GAAG,KAAK,MAAA,EAAQ,aAAA,EAAe,QAAQ,CAAA;AAAA,EACrE;AAAA,EAEA,KAAA,GAA4B;AAC1B,IAAA,MAAM,EAAE,SAAS,aAAA,EAAe,KAAA,EAAO,OAAO,GAAG,IAAA,KAAS,IAAA,CAAK,MAAA;AAE/D,IAAA,IAAI,KAAA,EAAO,aAAA,CAAc,IAAA,CAAK,MAAM,CAAA;AAEpC,IAAA,OAAO,eAAA,CAAgB;AAAA,MACrB,GAAG,IAAA;AAAA,MACH,OAAA;AAAA,MACA,GAAI,aAAA,CAAc,MAAA,GAAS,IAAI,EAAE,aAAA,KAAkB,EAAC;AAAA,MACpD,GAAI,KAAA,CAAM,MAAA,GAAS,IAAI,EAAE,KAAA,KAAU;AAAC,KACrC,CAAA;AAAA,EACH;AAAA,EAEA,MAAA,GAA6B;AAC3B,IAAA,OAAO,KAAK,KAAA,EAAM;AAAA,EACpB;AACF,CAAA;AAcO,SAAS,OAAA,CAAQ,UAAU,EAAA,EAAoB;AACpD,EAAA,OAAO,IAAI,cAAA,CAAe,EAAE,OAAA,EAAS,aAAA,EAAe,EAAC,EAAG,KAAA,EAAO,EAAC,EAAG,KAAA,EAAO,KAAA,EAAO,CAAA;AACnF;AAUO,SAAS,cAAA,CAAe,KAAA,EAAqB,YAAA,GAAe,KAAA,EAA2B;AAC5F,EAAA,MAAM,WAAW,YAAA,CAAa,KAAA,EAAO,MAAM,OAAA,IAAW,eAAe,CAAA;AAErE,EAAA,IAAI,CAAC,YAAA,IAAgB,QAAA,CAAS,aAAA,KAAkB,MAAA,EAAW;AACzD,IAAA,MAAM,IAAI,cAAA;AAAA,MACR;AAAA,KAEF;AAAA,EACF;AAEA,EAAA,OAAO,QAAA;AACT;;;AC7JA,IAAM,WAAA,GAAc,CAAA;AAGpB,IAAM,WAAA,GAAc,EAAA;AACpB,IAAM,mBAAA,GAAsB,GAAA;AAC5B,IAAM,iBAAA,GAAoB,GAAA;AASnB,SAAS,aAAa,KAAA,EAAyC;AACpE,EAAA,MAAM,WAAW,KAAA,EAAO,QAAA;AAExB,EAAA,IAAI,OAAO,QAAA,KAAa,QAAA,IAAY,QAAA,CAAS,IAAA,OAAW,EAAA,EAAI;AAC1D,IAAA,MAAM,IAAI,eAAe,6KAAiC,CAAA;AAAA,EAC5D;AAEA,EAAA,IAAI,QAAA,CAAS,IAAA,EAAK,CAAE,MAAA,GAAS,mBAAA,EAAqB;AAChD,IAAA,MAAM,IAAI,cAAA;AAAA,MACR,mFAAkB,mBAAmB,CAAA,oGAAA,EAAuB,QAAA,CAAS,IAAA,GAAO,MAAM,CAAA,CAAA;AAAA,KACpF;AAAA,EACF;AAEA,EAAA,MAAM,OAAA,GAAU,MAAM,OAAA,CAAQ,KAAA,CAAM,OAAO,CAAA,GAAI,KAAA,CAAM,UAAU,EAAC;AAEhE,EAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,GAAA,CAAI,CAAC,QAAQ,KAAA,KAAU;AAC3C,IAAA,MAAM,IAAA,GAAO,OAAO,MAAA,EAAQ,IAAA,KAAS,WAAW,MAAA,CAAO,IAAA,CAAK,MAAK,GAAI,EAAA;AACrE,IAAA,IAAI,SAAS,EAAA,EAAI;AACf,MAAA,MAAM,IAAI,cAAA,CAAe,CAAA,sFAAA,EAAmB,KAAA,GAAQ,CAAC,CAAA,+KAAA,CAAqC,CAAA;AAAA,IAC5F;AACA,IAAA,IAAI,IAAA,CAAK,SAAS,iBAAA,EAAmB;AACnC,MAAA,MAAM,IAAI,cAAA;AAAA,QACR,yFAAmB,KAAA,GAAQ,CAAC,+CAAY,iBAAiB,CAAA,oGAAA,EAAuB,KAAK,MAAM,CAAA,CAAA;AAAA,OAC7F;AAAA,IACF;AACA,IAAA,OAAO,IAAA;AAAA,EACT,CAAC,CAAA;AAED,EAAA,IAAI,KAAA,CAAM,SAAS,WAAA,EAAa;AAC9B,IAAA,MAAM,IAAI,cAAA;AAAA,MACR,CAAA,qHAAA,EAAyB,WAAW,CAAA,qGAAA,EAAwB,KAAA,CAAM,MAAM,CAAA;AAAA,KAC1E;AAAA,EACF;AAEA,EAAA,IAAI,KAAA,CAAM,SAAS,WAAA,EAAa;AAC9B,IAAA,MAAM,IAAI,cAAA;AAAA,MACR,CAAA,wIAAA,EAA6B,WAAW,CAAA,2GAAA,EAAyB,KAAA,CAAM,MAAM,CAAA;AAAA,KAC/E;AAAA,EACF;AAEA,EAAA,MAAM,IAAA,uBAAW,GAAA,EAAY;AAC7B,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,IAAI,IAAA,CAAK,GAAA,CAAI,IAAI,CAAA,EAAG;AAClB,MAAA,MAAM,IAAI,cAAA,CAAe,CAAA,+CAAA,EAAY,IAAI,CAAA,uOAAA,CAA6C,CAAA;AAAA,IACxF;AACA,IAAA,IAAA,CAAK,IAAI,IAAI,CAAA;AAAA,EACf;AAEA,EAAA,OAAO;AAAA,IACL,QAAA,EAAU,SAAS,IAAA,EAAK;AAAA,IACxB,SAAS,KAAA,CAAM,GAAA,CAAI,CAAC,IAAA,MAAU,EAAE,MAAK,CAAE,CAAA;AAAA;AAAA;AAAA,IAGvC,cAAA,EAAgB,MAAM,cAAA,IAAkB;AAAA,GAC1C;AACF;AAQO,IAAM,WAAA,GAAN,MAAM,YAAA,CAAmD;AAAA;AAAA,EAE9D,CAAU,OAAO,IAAI,IAAA;AAAA,EAEZ,MAAA;AAAA;AAAA,EAGT,YAAY,KAAA,EAAwB;AAClC,IAAA,IAAA,CAAK,MAAA,GAAS,KAAA;AAAA,EAChB;AAAA;AAAA,EAGA,SAAS,IAAA,EAA2B;AAClC,IAAA,OAAO,IAAI,aAAY,EAAE,GAAG,KAAK,MAAA,EAAQ,QAAA,EAAU,MAAM,CAAA;AAAA,EAC3D;AAAA;AAAA,EAGA,OAAO,IAAA,EAA2B;AAChC,IAAA,OAAO,IAAI,YAAA,CAAY,EAAE,GAAG,IAAA,CAAK,QAAQ,OAAA,EAAS,CAAC,GAAG,IAAA,CAAK,OAAO,OAAA,EAAS,EAAE,IAAA,EAAM,GAAG,CAAA;AAAA,EACxF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,WAAW,KAAA,EAA8B;AACvC,IAAA,OAAO,IAAI,YAAA,CAAY;AAAA,MACrB,GAAG,IAAA,CAAK,MAAA;AAAA,MACR,OAAA,EAAS,CAAC,GAAG,IAAA,CAAK,OAAO,OAAA,EAAS,GAAG,KAAA,CAAM,GAAA,CAAI,CAAC,IAAA,MAAU,EAAE,IAAA,GAAO,CAAC;AAAA,KACrE,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,cAAA,CAAe,UAAU,IAAA,EAAmB;AAC1C,IAAA,OAAO,IAAI,aAAY,EAAE,GAAG,KAAK,MAAA,EAAQ,cAAA,EAAgB,SAAS,CAAA;AAAA,EACpE;AAAA,EAEA,KAAA,GAAyB;AACvB,IAAA,OAAO,YAAA,CAAa,KAAK,MAAM,CAAA;AAAA,EACjC;AAAA,EAEA,MAAA,GAA0B;AACxB,IAAA,OAAO,KAAK,KAAA,EAAM;AAAA,EACpB;AACF,CAAA;AAkBO,SAAS,IAAA,CAAK,WAAW,EAAA,EAAiB;AAC/C,EAAA,OAAO,IAAI,WAAA,CAAY,EAAE,UAAU,OAAA,EAAS,IAAI,CAAA;AAClD;AAMO,SAAS,YAAY,KAAA,EAAmC;AAC7D,EAAA,OAAO,YAAA,CAAa,KAAA,EAAO,MAAM,IAAA,IAAQ,YAAY,CAAA;AACvD;;;ACvJA,IAAM,YAAA,GAAe,iEAAA;AAWd,SAAS,aAAa,KAAA,EAAyC;AACpE,EAAA,MAAM,UAAU,OAAO,KAAA,EAAO,OAAA,KAAY,QAAA,GAAW,MAAM,OAAA,GAAU,EAAA;AACrE,EAAA,MAAM,aAAA,GAAgB,KAAA,EAAO,aAAA,IAAiB,EAAC;AAC/C,EAAA,MAAM,KAAA,GAAQ,KAAA,EAAO,KAAA,IAAS,EAAC;AAE/B,EAAA,MAAM,UAAA,GAAa,OAAA,CAAQ,IAAA,EAAK,KAAM,EAAA;AACtC,EAAA,MAAM,cAAA,GAAiB,aAAA,CAAc,MAAA,GAAS,CAAA,IAAK,MAAM,MAAA,GAAS,CAAA;AAClE,EAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,KAAA,EAAO,IAAI,CAAA;AAEnC,EAAA,IAAI,CAAC,UAAA,IAAc,CAAC,cAAA,IAAkB,CAAC,OAAA,EAAS;AAC9C,IAAA,MAAM,IAAI,eAAe,sNAA4C,CAAA;AAAA,EACvE;AAEA,EAAA,MAAM,kBAAkB,KAAA,CAAM,eAAA;AAC9B,EAAA,IAAI,eAAA,KAAoB,MAAA,IAAa,eAAA,KAAoB,IAAA,EAAM;AAC7D,IAAA,IAAI,CAAC,YAAA,CAAa,IAAA,CAAK,eAAe,CAAA,EAAG;AACvC,MAAA,MAAM,IAAI,cAAA;AAAA,QACR,gRAA0E,eAAe,CAAA,+OAAA;AAAA,OAE3F;AAAA,IACF;AAAA,EACF;AAIA,EAAA,OAAO,KAAA,CAAM,IAAA,KAAS,MAAA,GAAY,KAAA,GAAQ,EAAE,GAAG,KAAA,EAAO,IAAA,EAAM,WAAA,CAAY,KAAA,CAAM,IAAI,CAAA,EAAE;AACtF;AAuBO,IAAM,WAAA,GAAN,MAAM,YAAA,CAAmD;AAAA;AAAA,EAE9D,CAAU,OAAO,IAAI,IAAA;AAAA,EAEZ,MAAA;AAAA;AAAA,EAGT,YAAY,KAAA,EAAkB;AAC5B,IAAA,IAAA,CAAK,MAAA,GAAS,KAAA;AAAA,EAChB;AAAA;AAAA,EAGA,QAAQ,IAAA,EAA2B;AACjC,IAAA,OAAO,IAAI,aAAY,EAAE,GAAG,KAAK,MAAA,EAAQ,OAAA,EAAS,MAAM,CAAA;AAAA,EAC1D;AAAA;AAAA,EAGA,OAAO,IAAA,EAA2B;AAChC,IAAA,MAAM,SAAA,GAAY,IAAA,CAAK,MAAA,CAAO,OAAA,KAAY,KAAK,EAAA,GAAK,IAAA;AACpD,IAAA,OAAO,IAAI,YAAA,CAAY,EAAE,GAAG,IAAA,CAAK,MAAA,EAAQ,OAAA,EAAS,IAAA,CAAK,MAAA,CAAO,OAAA,GAAU,SAAA,GAAY,IAAA,EAAM,CAAA;AAAA,EAC5F;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,KAAA,EAA4B;AAChC,IAAA,OAAO,IAAI,YAAA,CAAY,EAAE,GAAG,IAAA,CAAK,MAAA,EAAQ,OAAO,CAAA;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,MAAA,EAA6B;AAClC,IAAA,OAAO,IAAI,aAAY,EAAE,GAAG,KAAK,MAAA,EAAQ,eAAA,EAAiB,QAAQ,CAAA;AAAA,EACpE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,IAAA,EAA8B;AACnC,IAAA,OAAO,IAAI,YAAA,CAAY,EAAE,GAAG,KAAK,MAAA,EAAQ,KAAA,EAAO,CAAC,GAAG,IAAA,CAAK,MAAA,CAAO,KAAA,EAAO,IAAI,GAAG,CAAA;AAAA,EAChF;AAAA;AAAA,EAGA,SAAS,YAAA,EAAmC;AAC1C,IAAA,OAAO,IAAI,YAAA,CAAY;AAAA,MACrB,GAAG,IAAA,CAAK,MAAA;AAAA,MACR,eAAe,CAAC,GAAG,IAAA,CAAK,MAAA,CAAO,eAAe,YAAY;AAAA,KAC3D,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,KAAK,KAAA,EAA+B;AAClC,IAAA,OAAO,IAAI,YAAA,CAAY,EAAE,GAAG,IAAA,CAAK,QAAQ,IAAA,EAAM,WAAA,CAAY,KAAK,CAAA,EAAG,CAAA;AAAA,EACrE;AAAA,EAEA,KAAA,GAAyB;AACvB,IAAA,MAAM,EAAE,OAAA,EAAS,aAAA,EAAe,OAAO,GAAG,IAAA,KAAS,IAAA,CAAK,MAAA;AAExD,IAAA,OAAO,YAAA,CAAa;AAAA,MAClB,GAAG,IAAA;AAAA,MACH,GAAI,OAAA,KAAY,EAAA,GAAK,EAAE,OAAA,KAAY,EAAC;AAAA,MACpC,GAAI,aAAA,CAAc,MAAA,GAAS,IAAI,EAAE,aAAA,KAAkB,EAAC;AAAA,MACpD,GAAI,KAAA,CAAM,MAAA,GAAS,IAAI,EAAE,KAAA,KAAU;AAAC,KACrC,CAAA;AAAA,EACH;AAAA,EAEA,MAAA,GAA0B;AACxB,IAAA,OAAO,KAAK,KAAA,EAAM;AAAA,EACpB;AACF,CAAA;AAkBO,SAAS,IAAA,CAAK,UAAU,EAAA,EAAiB;AAC9C,EAAA,OAAO,IAAI,WAAA,CAAY,EAAE,OAAA,EAAS,aAAA,EAAe,EAAC,EAAG,KAAA,EAAO,EAAC,EAAG,CAAA;AAClE;AAMO,SAAS,YAAY,KAAA,EAAmC;AAC7D,EAAA,OAAO,YAAA,CAAa,KAAA,EAAO,MAAM,IAAA,IAAQ,YAAY,CAAA;AACvD;;;AC7IO,IAAM,OAAA,GAAU,OAAO,MAAA,CAAO;AAAA;AAAA,EAEnC,OAAA,EAAS,SAAA;AAAA;AAAA,EAET,SAAA,EAAW,WAAA;AAAA;AAAA,EAEX,IAAA,EAAM;AACR,CAAU;AAIH,IAAM,WAAA,GAAc,OAAO,MAAA,CAAO;AAAA;AAAA,EAEvC,MAAA,EAAQ,QAAA;AAAA;AAAA,EAER,MAAA,EAAQ,QAAA;AAAA;AAAA,EAER,OAAA,EAAS;AACX,CAAU;AAIH,IAAM,cAAA,GAAiB,OAAO,MAAA,CAAO;AAAA,EAC1C,KAAA,EAAO,OAAA;AAAA,EACP,KAAA,EAAO,OAAA;AAAA;AAAA,EAEP,KAAA,EAAO;AACT,CAAU;AAiBH,IAAM,QAAA,GAAW,OAAO,MAAA,CAAO;AAAA;AAAA,EAEpC,OAAA,EAAS,SAAA;AAAA;AAAA,EAET,OAAA,EAAS,SAAA;AAAA;AAAA,EAET,IAAA,EAAM,MAAA;AAAA,EACN,IAAA,EAAM,MAAA;AAAA,EACN,MAAA,EAAQ,QAAA;AAAA,EACR,SAAA,EAAW,WAAA;AAAA;AAAA,EAEX,MAAA,EAAQ,QAAA;AAAA;AAAA,EAER,OAAA,EAAS,SAAA;AAAA;AAAA,EAET,SAAA,EAAW,WAAA;AAAA,EACX,KAAA,EAAO;AACT,CAAU;AAIH,IAAM,gBAAA,GAAmB,OAAO,MAAA,CAAO;AAAA,EAC5C,IAAA,EAAM,MAAA;AAAA,EACN,OAAA,EAAS,SAAA;AAAA,EACT,IAAA,EAAM;AACR,CAAU;AAIH,IAAM,YAAA,GAAe,OAAO,MAAA,CAAO;AAAA,EACxC,IAAA,EAAM,MAAA;AAAA,EACN,QAAA,EAAU,UAAA;AAAA,EACV,IAAA,EAAM,MAAA;AAAA,EACN,KAAA,EAAO,OAAA;AAAA,EACP,KAAA,EAAO,OAAA;AAAA,EACP,KAAA,EAAO;AACT,CAAU;AAIH,IAAM,cAAA,GAAiB,OAAO,MAAA,CAAO;AAAA,EAC1C,UAAA,EAAY,YAAA;AAAA,EACZ,SAAA,EAAW,WAAA;AAAA,EACX,KAAA,EAAO,OAAA;AAAA,EACP,YAAA,EAAc;AAChB,CAAU;AASH,IAAM,UAAA,GAAa,OAAO,MAAA,CAAO;AAAA,EACtC,QAAA,EAAU;AACZ,CAAU;AAIH,IAAM,eAAA,GAAkB,OAAO,MAAA,CAAO;AAAA,EAC3C,QAAA,EAAU,UAAA;AAAA;AAAA,EAEV,MAAA,EAAQ;AACV,CAAU;AAUH,IAAM,gBAAA,GAAmB,OAAO,MAAA,CAAO;AAAA;AAAA,EAE5C,YAAA,EAAc,eAAA;AAAA;AAAA,EAEd,WAAA,EAAa,cAAA;AAAA;AAAA,EAEb,YAAA,EAAc,eAAA;AAAA;AAAA,EAEd,UAAA,EAAY,aAAA;AAAA;AAAA,EAEZ,WAAA,EAAa,cAAA;AAAA;AAAA,EAEb,eAAA,EAAiB,kBAAA;AAAA;AAAA,EAEjB,cAAA,EAAgB,iBAAA;AAAA;AAAA,EAEhB,QAAA,EAAU,WAAA;AAAA;AAAA,EAEV,MAAA,EAAQ,QAAA;AAAA;AAAA,EAER,aAAA,EAAe,gBAAA;AAAA;AAAA,EAEf,cAAA,EAAgB,iBAAA;AAAA;AAAA,EAEhB,oBAAA,EAAsB,uBAAA;AAAA;AAAA,EAEtB,oBAAA,EAAsB;AACxB,CAAU;AAgBH,IAAM,YAAA,GAAe,OAAO,MAAA,CAAO;AAAA,EACxC,WAAA,EAAa,aAAA;AAAA,EACb,YAAA,EAAc,cAAA;AAAA,EACd,aAAA,EAAe,eAAA;AAAA,EACf,gBAAA,EAAkB,kBAAA;AAAA,EAClB,qBAAA,EAAuB,uBAAA;AAAA,EACvB,gBAAA,EAAkB,kBAAA;AAAA,EAClB,uBAAA,EAAyB,yBAAA;AAAA,EACzB,mBAAA,EAAqB,qBAAA;AAAA,EACrB,aAAA,EAAe,eAAA;AAAA;AAAA,EAEf,SAAA,EAAW,WAAA;AAAA;AAAA,EAEX,cAAA,EAAgB,gBAAA;AAAA;AAAA,EAEhB,6BAAA,EAA+B,+BAAA;AAAA,EAC/B,WAAA,EAAa,aAAA;AAAA;AAAA,EAEb,kBAAA,EAAoB,oBAAA;AAAA,EACpB,mBAAA,EAAqB,qBAAA;AAAA,EACrB,gCAAA,EAAkC,kCAAA;AAAA,EAClC,2BAAA,EAA6B,6BAAA;AAAA,EAC7B,0BAAA,EAA4B,4BAAA;AAAA,EAC5B,kCAAA,EAAoC,oCAAA;AAAA,EACpC,eAAA,EAAiB,iBAAA;AAAA,EACjB,eAAA,EAAiB,iBAAA;AAAA,EACjB,6BAAA,EAA+B,+BAAA;AAAA;AAAA,EAE/B,qBAAA,EAAuB,uBAAA;AAAA;AAAA,EAEvB,iBAAA,EAAmB,mBAAA;AAAA,EACnB,kBAAA,EAAoB,oBAAA;AAAA,EACpB,sBAAA,EAAwB,wBAAA;AAAA,EACxB,0BAAA,EAA4B,4BAAA;AAAA,EAC5B,+BAAA,EAAiC,iCAAA;AAAA,EACjC,yBAAA,EAA2B,2BAAA;AAAA,EAC3B,cAAA,EAAgB,gBAAA;AAAA,EAChB,qBAAA,EAAuB,uBAAA;AAAA,EACvB,aAAA,EAAe,eAAA;AAAA,EACf,2BAAA,EAA6B,6BAAA;AAAA,EAC7B,2BAAA,EAA6B,6BAAA;AAAA,EAC7B,uBAAA,EAAyB;AAC3B,CAAU;;;AC9OV,IAAM,UAAU,IAAI,GAAA,CAAY,MAAA,CAAO,MAAA,CAAO,YAAY,CAAC,CAAA;AAC3D,IAAM,eAAe,IAAI,GAAA,CAAY,MAAA,CAAO,MAAA,CAAO,gBAAgB,CAAC,CAAA;AAO7D,SAAS,eAAe,KAAA,EAA6C;AAC1E,EAAA,IAAI,CAAC,KAAA,EAAO,QAAA,IAAY,OAAO,KAAA,CAAM,aAAa,QAAA,EAAU;AAC1D,IAAA,MAAM,IAAI,eAAe,sNAAiD,CAAA;AAAA,EAC5E;AAEA,EAAA,IAAI,CAAC,YAAA,CAAa,GAAA,CAAI,KAAA,CAAM,UAAU,CAAA,EAAG;AACvC,IAAA,MAAM,IAAI,cAAA;AAAA,MACR,CAAA,qHAAA,EAAmC,CAAC,GAAG,YAAY,CAAA,CAAE,IAAA,CAAK,IAAI,CAAC,CAAA,oDAAA,EAChD,MAAA,CAAO,KAAA,CAAM,UAAU,CAAC,CAAA;AAAA,KACzC;AAAA,EACF;AAEA,EAAA,IAAI,CAAC,OAAA,CAAQ,GAAA,CAAI,KAAA,CAAM,MAAM,CAAA,EAAG;AAC9B,IAAA,MAAM,IAAI,cAAA;AAAA,MACR,CAAA,uJAAA,EAA+B,MAAA,CAAO,KAAA,CAAM,MAAM,CAAC,CAAA,oEAAA,EAAkB,CAAC,GAAG,OAAO,CAAA,CAAE,IAAA,CAAK,IAAI,CAAC,CAAA;AAAA,KAC9F;AAAA,EACF;AAEA,EAAA,OAAO,KAAA;AACT;AAQO,IAAM,aAAA,GAAN,MAAM,cAAA,CAAuD;AAAA;AAAA,EAElE,CAAU,OAAO,IAAI,IAAA;AAAA,EAEZ,MAAA;AAAA;AAAA,EAGT,YAAY,KAAA,EAAmC;AAC7C,IAAA,IAAA,CAAK,MAAA,GAAS,KAAA;AAAA,EAChB;AAAA;AAAA,EAGA,OAAO,MAAA,EAAqC;AAC1C,IAAA,OAAO,IAAI,cAAA,CAAc,EAAE,GAAG,IAAA,CAAK,MAAA,EAAQ,QAAQ,CAAA;AAAA,EACrD;AAAA;AAAA,EAGA,YAAY,IAAA,EAA6B;AACvC,IAAA,OAAO,IAAI,eAAc,EAAE,GAAG,KAAK,MAAA,EAAQ,WAAA,EAAa,MAAM,CAAA;AAAA,EAChE;AAAA,EAEA,KAAA,GAA2B;AACzB,IAAA,OAAO,cAAA,CAAe,KAAK,MAA2B,CAAA;AAAA,EACxD;AAAA,EAEA,MAAA,GAA4B;AAC1B,IAAA,OAAO,KAAK,KAAA,EAAM;AAAA,EACpB;AACF,CAAA;AAEA,SAAS,KAAA,CAAM,YAA8B,QAAA,EAAiC;AAC5E,EAAA,OAAO,IAAI,aAAA,CAAc,EAAE,UAAA,EAAY,UAAU,CAAA;AACnD;AAgBO,IAAM,MAAA,GAAS,OAAO,MAAA,CAAO;AAAA;AAAA,EAElC,MAAM,CAAC,MAAA,KAAmB,KAAA,CAAM,gBAAA,CAAiB,MAAM,MAAM,CAAA;AAAA;AAAA,EAE7D,SAAS,CAAC,SAAA,KAAsB,KAAA,CAAM,gBAAA,CAAiB,SAAS,SAAS,CAAA;AAAA;AAAA,EAEzE,MAAM,CAAC,MAAA,KAAmB,KAAA,CAAM,gBAAA,CAAiB,MAAM,MAAM;AAC/D,CAAC;AAMM,SAAS,cAAc,KAAA,EAAuC;AACnE,EAAA,OAAO,YAAA,CAAa,OAAO,MAAM,IAAI,cAAc,EAAE,GAAG,cAAc,CAAA;AACxE;;;ACvGA,IAAI,mBAAA,GAAsB;AAAA,EACxB,YAAA,EAAc,IAAA;AAAA,EACd,GAAA,EAAK,KAAA;AAAA,EACL,MAAA,EAAQ,KAAA;AAAA,EACR,KAAA,EAAO;AAAA;AACT,CAAA;AAEA,SAAS,eAAe,GAAA,EAAK;AAC3B,EAAA,OAAO,OAAO,GAAA,KAAQ,QAAA,IAAY,GAAA,IAAO,EAAC;AAC5C;AAEA,SAAS,aAAA,GAAgB;AACvB,EAAA,uBAAO,MAAA,CAAO,OAAO,IAAI,CAAA;AAC3B;AAEA,SAAS,iBAAiB,GAAA,EAAK;AAC7B,EAAA,OAAO,OAAO,GAAA,KAAQ,QAAA,IAAY,CAAC,CAAC,IAAI,IAAA,EAAK;AAC/C;AAEA,SAAS,WAAA,CAAY,gBAAgB,OAAA,EAAS;AAC5C,EAAA,IAAI,QAAQ,cAAA,CAAe,KAAA,CAAM,GAAG,CAAA,CAAE,OAAO,gBAAgB,CAAA;AAE7D,EAAA,IAAI,gBAAA,GAAmB,MAAM,KAAA,EAAM;AACnC,EAAA,IAAI,CAAC,gBAAA,EAAkB;AACrB,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,IAAI,MAAA,GAAS,mBAAmB,gBAAgB,CAAA;AAChD,EAAA,IAAI,OAAO,MAAA,CAAO,IAAA;AAClB,EAAA,IAAI,QAAQ,MAAA,CAAO,KAAA;AAEnB,EAAA,OAAA,GAAU,UACN,MAAA,CAAO,MAAA,CAAO,EAAC,EAAG,mBAAA,EAAqB,OAAO,CAAA,GAC9C,mBAAA;AAEJ,EAAA,IAAI,cAAA,CAAe,IAAI,CAAA,EAAG;AACxB,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,IAAI;AACF,IAAA,KAAA,GAAQ,OAAA,CAAQ,YAAA,GAAe,kBAAA,CAAmB,KAAK,CAAA,GAAI,KAAA;AAAA,EAC7D,SAAS,CAAA,EAAG;AACV,IAAA,OAAA,CAAQ,KAAA;AAAA,MACN,uGAAA;AAAA,MACA;AAAA,KACF;AAAA,EACF;AAEA,EAAA,IAAI,SAAS,aAAA,EAAc;AAC3B,EAAA,MAAA,CAAO,IAAA,GAAO,IAAA;AACd,EAAA,MAAA,CAAO,KAAA,GAAQ,KAAA;AAEf,EAAA,KAAA,CAAM,OAAA,CAAQ,SAAU,IAAA,EAAM;AAC5B,IAAA,IAAI,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA;AAC1B,IAAA,IAAI,MAAM,KAAA,CAAM,KAAA,EAAM,CAAE,IAAA,GAAO,WAAA,EAAY;AAC3C,IAAA,IAAI,cAAA,CAAe,GAAG,CAAA,EAAG;AACvB,MAAA;AAAA,IACF;AACA,IAAA,IAAIA,MAAAA,GAAQ,KAAA,CAAM,IAAA,CAAK,GAAG,EAAE,IAAA,EAAK;AACjC,IAAA,IAAI,QAAQ,SAAA,EAAW;AACrB,MAAA,MAAA,CAAO,OAAA,GAAU,IAAI,IAAA,CAAKA,MAAK,CAAA;AAAA,IACjC,CAAA,MAAA,IAAW,QAAQ,SAAA,EAAW;AAC5B,MAAA,IAAI,CAAA,GAAI,QAAA,CAASA,MAAAA,EAAO,EAAE,CAAA;AAC1B,MAAA,IAAI,CAAC,MAAA,CAAO,KAAA,CAAM,CAAC,CAAA,SAAU,MAAA,GAAS,CAAA;AAAA,IACxC,CAAA,MAAA,IAAW,QAAQ,QAAA,EAAU;AAC3B,MAAA,MAAA,CAAO,MAAA,GAAS,IAAA;AAAA,IAClB,CAAA,MAAA,IAAW,QAAQ,UAAA,EAAY;AAC7B,MAAA,MAAA,CAAO,QAAA,GAAW,IAAA;AAAA,IACpB,CAAA,MAAA,IAAW,QAAQ,UAAA,EAAY;AAC7B,MAAA,MAAA,CAAO,QAAA,GAAWA,MAAAA;AAAA,IACpB,CAAA,MAAA,IAAW,QAAQ,aAAA,EAAe;AAChC,MAAA,MAAA,CAAO,WAAA,GAAc,IAAA;AAAA,IACvB,WAAW,GAAA,EAAK;AACd,MAAA,MAAA,CAAO,GAAG,CAAA,GAAIA,MAAAA;AAAA,IAChB;AAAA,EACF,CAAC,CAAA;AAED,EAAA,OAAO,MAAA;AACT;AAEA,SAAS,mBAAmB,gBAAA,EAAkB;AAG5C,EAAA,IAAI,IAAA,GAAO,EAAA;AACX,EAAA,IAAI,KAAA,GAAQ,EAAA;AACZ,EAAA,IAAI,YAAA,GAAe,gBAAA,CAAiB,KAAA,CAAM,GAAG,CAAA;AAC7C,EAAA,IAAI,YAAA,CAAa,SAAS,CAAA,EAAG;AAC3B,IAAA,IAAA,GAAO,aAAa,KAAA,EAAM;AAC1B,IAAA,KAAA,GAAQ,YAAA,CAAa,KAAK,GAAG,CAAA;AAAA,EAC/B,CAAA,MAAO;AACL,IAAA,KAAA,GAAQ,gBAAA;AAAA,EACV;AAEA,EAAA,OAAO,EAAE,MAAY,KAAA,EAAa;AACpC;AAEA,SAAS,cAAA,CAAe,OAAO,OAAA,EAAS;AACtC,EAAA,OAAA,GAAU,UACN,MAAA,CAAO,MAAA,CAAO,EAAC,EAAG,mBAAA,EAAqB,OAAO,CAAA,GAC9C,mBAAA;AAEJ,EAAA,IAAI,CAAC,KAAA,EAAO;AACV,IAAA,IAAI,CAAC,QAAQ,GAAA,EAAK;AAChB,MAAA,OAAO,EAAC;AAAA,IACV,CAAA,MAAO;AACL,MAAA,OAAO,aAAA,EAAc;AAAA,IACvB;AAAA,EACF;AAEA,EAAA,IAAI,MAAM,OAAA,EAAS;AACjB,IAAA,IAAI,OAAO,KAAA,CAAM,OAAA,CAAQ,YAAA,KAAiB,UAAA,EAAY;AAGpD,MAAA,KAAA,GAAQ,KAAA,CAAM,QAAQ,YAAA,EAAa;AAAA,IACrC,CAAA,MAAA,IAAW,KAAA,CAAM,OAAA,CAAQ,YAAY,CAAA,EAAG;AAEtC,MAAA,KAAA,GAAQ,KAAA,CAAM,QAAQ,YAAY,CAAA;AAAA,IACpC,CAAA,MAAO;AAEL,MAAA,IAAI,GAAA,GACF,KAAA,CAAM,OAAA,CACJ,MAAA,CAAO,IAAA,CAAK,MAAM,OAAO,CAAA,CAAE,IAAA,CAAK,SAAU,GAAA,EAAK;AAC7C,QAAA,OAAO,GAAA,CAAI,aAAY,KAAM,YAAA;AAAA,MAC/B,CAAC,CACH,CAAA;AAEF,MAAA,IAAI,CAAC,GAAA,IAAO,KAAA,CAAM,QAAQ,MAAA,IAAU,CAAC,QAAQ,MAAA,EAAQ;AACnD,QAAA,OAAA,CAAQ,IAAA;AAAA,UACN;AAAA,SACF;AAAA,MACF;AACA,MAAA,KAAA,GAAQ,GAAA;AAAA,IACV;AAAA,EACF;AAEA,EAAA,IAAI,QAAQ,OAAA,CAAQ,KAAA;AACpB,EAAA,IAAI,OAAA,GAAU,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA;AAEjC,EAAA,IAAI,UAAU,MAAA,EAAQ;AACpB,IAAA,KAAA,GAAQ,CAAC,OAAA;AAAA,EACX;AAEA,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,KAAA,GAAQ,CAAC,KAAK,CAAA;AAAA,EAChB;AAEA,EAAA,KAAA,GAAQ,KAAA,CAAM,OAAO,gBAAgB,CAAA;AAErC,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,KAAA,GAAQ,KAAA,CAAM,GAAA,CAAI,kBAAkB,CAAA,CAAE,IAAA,EAAK;AAAA,EAC7C;AAEA,EAAA,IAAI,CAAC,QAAQ,GAAA,EAAK;AAChB,IAAA,OAAO,KAAA,CACJ,GAAA,CAAI,SAAU,GAAA,EAAK;AAClB,MAAA,OAAO,WAAA,CAAY,KAAK,OAAO,CAAA;AAAA,IACjC,CAAC,CAAA,CACA,MAAA,CAAO,OAAO,CAAA;AAAA,EACnB,CAAA,MAAO;AACL,IAAA,IAAI,UAAU,aAAA,EAAc;AAC5B,IAAA,OAAO,KAAA,CAAM,MAAA,CAAO,SAAUC,QAAAA,EAAS,GAAA,EAAK;AAC1C,MAAA,IAAI,MAAA,GAAS,WAAA,CAAY,GAAA,EAAK,OAAO,CAAA;AACrC,MAAA,IAAI,MAAA,IAAU,CAAC,cAAA,CAAe,MAAA,CAAO,IAAI,CAAA,EAAG;AAC1C,QAAAA,QAAAA,CAAQ,MAAA,CAAO,IAAI,CAAA,GAAI,MAAA;AAAA,MACzB;AACA,MAAA,OAAOA,QAAAA;AAAA,IACT,GAAG,OAAO,CAAA;AAAA,EACZ;AACF;AAaA,SAAS,mBAAmB,aAAA,EAAe;AACzC,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,aAAa,CAAA,EAAG;AAChC,IAAA,OAAO,aAAA;AAAA,EACT;AACA,EAAA,IAAI,OAAO,kBAAkB,QAAA,EAAU;AACrC,IAAA,OAAO,EAAC;AAAA,EACV;AAEA,EAAA,IAAI,iBAAiB,EAAC;AACtB,EAAA,IAAI,GAAA,GAAM,CAAA;AACV,EAAA,IAAIC,MAAAA;AACJ,EAAA,IAAI,EAAA;AACJ,EAAA,IAAI,SAAA;AACJ,EAAA,IAAI,SAAA;AACJ,EAAA,IAAI,qBAAA;AAEJ,EAAA,SAAS,cAAA,GAAiB;AACxB,IAAA,OAAO,GAAA,GAAM,cAAc,MAAA,IAAU,IAAA,CAAK,KAAK,aAAA,CAAc,MAAA,CAAO,GAAG,CAAC,CAAA,EAAG;AACzE,MAAA,GAAA,IAAO,CAAA;AAAA,IACT;AACA,IAAA,OAAO,MAAM,aAAA,CAAc,MAAA;AAAA,EAC7B;AAEA,EAAA,SAAS,cAAA,GAAiB;AACxB,IAAA,EAAA,GAAK,aAAA,CAAc,OAAO,GAAG,CAAA;AAE7B,IAAA,OAAO,EAAA,KAAO,GAAA,IAAO,EAAA,KAAO,GAAA,IAAO,EAAA,KAAO,GAAA;AAAA,EAC5C;AAEA,EAAA,OAAO,GAAA,GAAM,cAAc,MAAA,EAAQ;AACjC,IAAAA,MAAAA,GAAQ,GAAA;AACR,IAAA,qBAAA,GAAwB,KAAA;AAExB,IAAA,OAAO,gBAAe,EAAG;AACvB,MAAA,EAAA,GAAK,aAAA,CAAc,OAAO,GAAG,CAAA;AAC7B,MAAA,IAAI,OAAO,GAAA,EAAK;AAEd,QAAA,SAAA,GAAY,GAAA;AACZ,QAAA,GAAA,IAAO,CAAA;AAEP,QAAA,cAAA,EAAe;AACf,QAAA,SAAA,GAAY,GAAA;AAEZ,QAAA,OAAO,GAAA,GAAM,aAAA,CAAc,MAAA,IAAU,cAAA,EAAe,EAAG;AACrD,UAAA,GAAA,IAAO,CAAA;AAAA,QACT;AAGA,QAAA,IAAI,MAAM,aAAA,CAAc,MAAA,IAAU,cAAc,MAAA,CAAO,GAAG,MAAM,GAAA,EAAK;AAEnE,UAAA,qBAAA,GAAwB,IAAA;AAExB,UAAA,GAAA,GAAM,SAAA;AACN,UAAA,cAAA,CAAe,IAAA,CAAK,aAAA,CAAc,SAAA,CAAUA,MAAAA,EAAO,SAAS,CAAC,CAAA;AAC7D,UAAAA,MAAAA,GAAQ,GAAA;AAAA,QACV,CAAA,MAAO;AAGL,UAAA,GAAA,GAAM,SAAA,GAAY,CAAA;AAAA,QACpB;AAAA,MACF,CAAA,MAAO;AACL,QAAA,GAAA,IAAO,CAAA;AAAA,MACT;AAAA,IACF;AAEA,IAAA,IAAI,CAAC,qBAAA,IAAyB,GAAA,IAAO,aAAA,CAAc,MAAA,EAAQ;AACzD,MAAA,cAAA,CAAe,KAAK,aAAA,CAAc,SAAA,CAAUA,MAAAA,EAAO,aAAA,CAAc,MAAM,CAAC,CAAA;AAAA,IAC1E;AAAA,EACF;AAEA,EAAA,OAAO,cAAA;AACT;AAGA,cAAA,CAAe,cAAA,GAAiB,cAAA;AAEhC,cAAA,CAAe,KAAA,GAAQ,cAAA;AACvB,cAAA,CAAe,WAAA,GAAc,WAAA;AAC7B,cAAA,CAAe,kBAAA,GAAqB,kBAAA;;;ACrP7B,IAAM,gBAAA,GAAmB;AASzB,IAAM,cAAA,GAAiB;AAGvB,IAAM,mBAAA,GAAsB;AAGnC,IAAM,oBAAA,GAAuB,GAAA;AAE7B,SAAS,SAAS,GAAA,EAAqB;AACrC,EAAA,IAAI;AACF,IAAA,OAAO,IAAI,GAAA,CAAI,GAAG,CAAA,CAAE,MAAA;AAAA,EACtB,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAA;AAAA,EACT;AACF;AAGA,SAAS,YAAY,IAAA,EAA4C;AAC/D,EAAA,IAAI,CAAC,MAAM,OAAO,MAAA;AAClB,EAAA,MAAM,IAAA,GAAO,KAAK,OAAA,EAAQ;AAC1B,EAAA,OAAO,MAAA,CAAO,QAAA,CAAS,IAAI,CAAA,GAAI,IAAA,GAAO,MAAA;AACxC;AAEA,SAAS,OAAO,GAAA,EAAqB;AACnC,EAAA,IAAI;AACF,IAAA,OAAO,IAAI,GAAA,CAAI,GAAG,CAAA,CAAE,QAAA,IAAY,GAAA;AAAA,EAClC,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,GAAA;AAAA,EACT;AACF;AAQA,SAAS,WAAA,CAAY,YAAoB,WAAA,EAA8B;AACrE,EAAA,IAAI,UAAA,KAAe,GAAA,IAAO,UAAA,KAAe,WAAA,EAAa,OAAO,IAAA;AAC7D,EAAA,IAAI,CAAC,WAAA,CAAY,UAAA,CAAW,UAAU,GAAG,OAAO,KAAA;AAChD,EAAA,OAAO,WAAW,QAAA,CAAS,GAAG,KAAK,WAAA,CAAY,UAAA,CAAW,MAAM,CAAA,KAAM,GAAA;AACxE;AAYO,IAAM,YAAN,MAAgB;AAAA,EACZ,SAAA,uBAAgB,GAAA,EAAuC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAShE,eAAA,CAAgB,KAAa,QAAA,EAA0B;AACrD,IAAA,MAAM,UAAU,QAAA,CAAS,OAAA;AAEzB,IAAA,MAAM,GAAA,GACJ,OAAO,OAAA,CAAQ,YAAA,KAAiB,UAAA,GAC5B,OAAA,CAAQ,YAAA,EAAa,GACrB,kBAAA,CAAmB,OAAA,CAAQ,GAAA,CAAI,YAAY,KAAK,EAAE,CAAA;AAExD,IAAA,IAAI,IAAI,MAAA,GAAS,CAAA,EAAG,IAAA,CAAK,cAAA,CAAe,KAAK,GAAG,CAAA;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,GAAA,CAAI,GAAA,EAAa,IAAA,EAAc,KAAA,EAAe,OAAO,GAAA,EAAW;AAC9D,IAAA,IAAA,CAAK,cAAA,CAAe,GAAA,EAAK,CAAC,CAAA,EAAG,IAAI,IAAI,KAAK,CAAA,OAAA,EAAU,IAAI,CAAA,CAAE,CAAC,CAAA;AAAA,EAC7D;AAAA;AAAA,EAGA,cAAA,CAAe,KAAa,gBAAA,EAAkC;AAC5D,IAAA,MAAM,MAAA,GAAS,SAAS,GAAG,CAAA;AAC3B,IAAA,IAAI,CAAC,MAAA,EAAQ;AAEb,IAAA,MAAM,MAAM,IAAA,CAAK,SAAA,CAAU,IAAI,MAAM,CAAA,wBAAS,GAAA,EAA0B;AAExE,IAAA,KAAA,MAAW,MAAA,IAAU,cAAA,CAAe,gBAAgB,CAAA,EAAG;AAIrD,MAAA,MAAM,OAAA,GAAU,WAAA,CAAY,MAAA,CAAO,OAAO,CAAA;AAC1C,MAAA,MAAM,aAAA,GACJ,OAAO,MAAA,CAAO,MAAA,KAAW,YAAY,MAAA,CAAO,QAAA,CAAS,MAAA,CAAO,MAAM,IAC9D,IAAA,CAAK,GAAA,EAAI,GAAI,MAAA,CAAO,SAAS,GAAA,GAC7B,MAAA;AAGN,MAAA,MAAM,YAAY,aAAA,IAAiB,OAAA;AAGnC,MAAA,IAAI,SAAA,KAAc,MAAA,IAAa,SAAA,IAAa,IAAA,CAAK,KAAI,EAAG;AACtD,QAAA,GAAA,CAAI,MAAA,CAAO,OAAO,IAAI,CAAA;AACtB,QAAA;AAAA,MACF;AAEA,MAAA,GAAA,CAAI,GAAA,CAAI,OAAO,IAAA,EAAM;AAAA,QACnB,MAAM,MAAA,CAAO,IAAA;AAAA,QACb,OAAO,MAAA,CAAO,KAAA;AAAA,QACd,IAAA,EAAM,OAAO,IAAA,IAAQ,GAAA;AAAA,QACrB,OAAA,EAAS,SAAA;AAAA,QACT,MAAA,EAAQ,OAAO,MAAA,IAAU;AAAA,OAC1B,CAAA;AAAA,IACH;AAEA,IAAA,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,MAAA,EAAQ,GAAG,CAAA;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,UAAU,GAAA,EAAiC;AACzC,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,SAAA,CAAU,GAAG,CAAA;AAClC,IAAA,IAAI,OAAA,CAAQ,MAAA,KAAW,CAAA,EAAG,OAAO,MAAA;AACjC,IAAA,OAAO,OAAA,CAAQ,GAAA,CAAI,CAAC,MAAA,KAAW,CAAA,EAAG,MAAA,CAAO,IAAI,CAAA,CAAA,EAAI,MAAA,CAAO,KAAK,CAAA,CAAE,CAAA,CAAE,KAAK,IAAI,CAAA;AAAA,EAC5E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,QAAA,CAAS,MAAc,GAAA,EAAkC;AACvD,IAAA,IAAI,GAAA,EAAK,OAAO,IAAA,CAAK,SAAA,CAAU,GAAG,CAAA,CAAE,IAAA,CAAK,CAAC,MAAA,KAAW,MAAA,CAAO,IAAA,KAAS,IAAI,CAAA,EAAG,KAAA;AAE5E,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,IAAA,KAAA,MAAW,GAAA,IAAO,IAAA,CAAK,SAAA,CAAU,MAAA,EAAO,EAAG;AACzC,MAAA,MAAM,MAAA,GAAS,GAAA,CAAI,GAAA,CAAI,IAAI,CAAA;AAC3B,MAAA,IAAI,MAAA,KAAW,OAAO,OAAA,KAAY,MAAA,IAAa,OAAO,OAAA,GAAU,GAAA,CAAA,SAAa,MAAA,CAAO,KAAA;AAAA,IACtF;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,GAAA,CAAI,MAAc,GAAA,EAAuB;AACvC,IAAA,IAAI,GAAA,EAAK,OAAO,IAAA,CAAK,SAAA,CAAU,GAAG,CAAA,CAAE,IAAA,CAAK,CAAC,MAAA,KAAW,MAAA,CAAO,IAAA,KAAS,IAAI,CAAA;AAEzE,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,IAAA,KAAA,MAAW,GAAA,IAAO,IAAA,CAAK,SAAA,CAAU,MAAA,EAAO,EAAG;AACzC,MAAA,MAAM,MAAA,GAAS,GAAA,CAAI,GAAA,CAAI,IAAI,CAAA;AAC3B,MAAA,IAAI,WAAW,MAAA,CAAO,OAAA,KAAY,UAAa,MAAA,CAAO,OAAA,GAAU,MAAM,OAAO,IAAA;AAAA,IAC/E;AACA,IAAA,OAAO,KAAA;AAAA,EACT;AAAA;AAAA,EAGA,SAAA,GAAsB;AACpB,IAAA,MAAM,SAAmB,EAAC;AAC1B,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AAErB,IAAA,KAAA,MAAW,CAAC,MAAA,EAAQ,GAAG,CAAA,IAAK,KAAK,SAAA,EAAW;AAC1C,MAAA,KAAA,MAAW,MAAA,IAAU,GAAA,CAAI,MAAA,EAAO,EAAG;AACjC,QAAA,IAAI,MAAA,CAAO,OAAA,KAAY,MAAA,IAAa,MAAA,CAAO,WAAW,GAAA,EAAK;AAE3D,QAAA,MAAM,KAAA,GAAQ,CAAC,CAAA,EAAG,MAAA,CAAO,IAAI,CAAA,CAAA,EAAI,MAAA,CAAO,KAAK,CAAA,CAAA,EAAI,CAAA,KAAA,EAAQ,MAAA,CAAO,IAAI,CAAA,CAAE,CAAA;AACtE,QAAA,IAAI,MAAA,CAAO,YAAY,MAAA,EAAW;AAChC,UAAA,KAAA,CAAM,IAAA,CAAK,WAAW,IAAI,IAAA,CAAK,OAAO,OAAO,CAAA,CAAE,WAAA,EAAa,CAAA,CAAE,CAAA;AAAA,QAChE;AACA,QAAA,IAAI,MAAA,CAAO,MAAA,EAAQ,KAAA,CAAM,IAAA,CAAK,QAAQ,CAAA;AAEtC,QAAA,MAAA,CAAO,IAAA,CAAK,CAAA,EAAG,MAAM,CAAA,EAAG,oBAAoB,GAAG,KAAA,CAAM,IAAA,CAAK,IAAI,CAAC,CAAA,CAAE,CAAA;AAAA,MACnE;AAAA,IACF;AAEA,IAAA,OAAO,MAAA;AAAA,EACT;AAAA;AAAA,EAGA,YAAY,OAAA,EAA8C;AACxD,IAAA,IAAI,CAAC,OAAA,EAAS;AAEd,IAAA,KAAA,MAAW,SAAS,OAAA,EAAS;AAC3B,MAAA,MAAM,WAAA,GAAc,KAAA,CAAM,OAAA,CAAQ,oBAAoB,CAAA;AACtD,MAAA,IAAI,eAAe,CAAA,EAAG;AAEtB,MAAA,MAAM,MAAA,GAAS,KAAA,CAAM,KAAA,CAAM,CAAA,EAAG,WAAW,CAAA;AACzC,MAAA,MAAM,SAAA,GAAY,KAAA,CAAM,KAAA,CAAM,WAAA,GAAc,CAAC,CAAA;AAC7C,MAAA,IAAI,CAAC,QAAA,CAAS,MAAM,CAAA,EAAG;AAEvB,MAAA,IAAA,CAAK,cAAA,CAAe,MAAA,EAAQ,CAAC,SAAS,CAAC,CAAA;AAAA,IACzC;AAAA,EACF;AAAA;AAAA,EAGA,KAAA,GAAc;AACZ,IAAA,IAAA,CAAK,UAAU,KAAA,EAAM;AAAA,EACvB;AAAA;AAAA,EAGA,UAAU,GAAA,EAA6B;AACrC,IAAA,MAAM,MAAA,GAAS,SAAS,GAAG,CAAA;AAC3B,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,MAAM,CAAA;AACrC,IAAA,IAAI,CAAC,GAAA,EAAK,OAAO,EAAC;AAElB,IAAA,MAAM,eAAA,GAAkB,MAAA,CAAO,UAAA,CAAW,QAAQ,CAAA;AAClD,IAAA,MAAM,WAAA,GAAc,OAAO,GAAG,CAAA;AAC9B,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,IAAA,MAAM,SAAyB,EAAC;AAEhC,IAAA,KAAA,MAAW,MAAA,IAAU,GAAA,CAAI,MAAA,EAAO,EAAG;AACjC,MAAA,IAAI,MAAA,CAAO,OAAA,KAAY,MAAA,IAAa,MAAA,CAAO,WAAW,GAAA,EAAK;AACzD,QAAA,GAAA,CAAI,MAAA,CAAO,OAAO,IAAI,CAAA;AACtB,QAAA;AAAA,MACF;AACA,MAAA,IAAI,MAAA,CAAO,MAAA,IAAU,CAAC,eAAA,EAAiB;AACvC,MAAA,IAAI,CAAC,WAAA,CAAY,MAAA,CAAO,IAAA,EAAM,WAAW,CAAA,EAAG;AAE5C,MAAA,MAAA,CAAO,KAAK,MAAM,CAAA;AAAA,IACpB;AAEA,IAAA,OAAO,MAAA;AAAA,EACT;AACF,CAAA;;;ACjPO,IAAM,UAAN,MAAsB;AAAA,EAClB,UAAA,uBAAiB,GAAA,EAAwC;AAAA,EACzD,QAAA;AAAA,EAET,YAAY,eAAA,EAA4C;AACtD,IAAA,IAAA,CAAK,QAAA,GAAW,eAAA;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,EAAA,CAA2B,OAAU,QAAA,EAA4C;AAC/E,IAAA,MAAM,MAAM,IAAA,CAAK,UAAA,CAAW,IAAI,KAAK,CAAA,wBAAS,GAAA,EAAI;AAClD,IAAA,GAAA,CAAI,IAAI,QAA2B,CAAA;AACnC,IAAA,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,KAAA,EAAO,GAAG,CAAA;AAE9B,IAAA,OAAO,MAAM,IAAA,CAAK,GAAA,CAAI,KAAA,EAAO,QAAQ,CAAA;AAAA,EACvC;AAAA;AAAA,EAGA,IAAA,CAA6B,OAAU,QAAA,EAA4C;AACjF,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,EAAA,CAAG,KAAA,EAAO,CAAC,OAAA,KAAY;AACtC,MAAA,GAAA,EAAI;AACJ,MAAA,QAAA,CAAS,OAAO,CAAA;AAAA,IAClB,CAAC,CAAA;AACD,IAAA,OAAO,GAAA;AAAA,EACT;AAAA;AAAA,EAGA,GAAA,CAA4B,OAAU,QAAA,EAAqC;AACzE,IAAA,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,KAAK,CAAA,EAAG,OAAO,QAA2B,CAAA;AAAA,EAChE;AAAA;AAAA,EAGA,IAAA,CAA6B,OAAU,OAAA,EAA0B;AAC/D,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,KAAK,CAAA;AACrC,IAAA,IAAI,CAAC,GAAA,EAAK;AAGV,IAAA,KAAA,MAAW,QAAA,IAAY,CAAC,GAAG,GAAG,CAAA,EAAG;AAC/B,MAAA,IAAI;AACF,QAAC,SAAiC,OAAO,CAAA;AAAA,MAC3C,SAAS,KAAA,EAAO;AACd,QAAA,IAAA,CAAK,WAAW,KAAK,CAAA;AAAA,MACvB;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,cAAc,KAAA,EAA6B;AACzC,IAAA,OAAO,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,KAAK,GAAG,IAAA,IAAQ,CAAA;AAAA,EAC7C;AAAA;AAAA,EAGA,kBAAA,GAA2B;AACzB,IAAA,IAAA,CAAK,WAAW,KAAA,EAAM;AAAA,EACxB;AACF,CAAA;;;ACzEO,IAAM,WAAA,GAAc,OAAO,MAAA,CAAO;AAAA;AAAA,EAEvC,IAAA,EAAM,MAAA;AAAA;AAAA,EAEN,OAAA,EAAS,SAAA;AAAA;AAAA,EAET,MAAA,EAAQ;AACV,CAAU;AAIH,IAAM,eAAA,GAAkB,OAAO,MAAA,CAAO;AAAA,EAC3C,OAAA,EAAS,SAAA;AAAA;AAAA,EAET,WAAA,EAAa,cAAA;AAAA,EACb,MAAA,EAAQ;AACV,CAAU;AAUH,SAAS,aAAA,GAAiC;AAC/C,EAAA,MAAM,MAAO,UAAA,CAAoD,SAAA;AACjE,EAAA,IAAI,GAAA,EAAK,OAAA,KAAY,aAAA,EAAe,OAAO,eAAA,CAAgB,WAAA;AAE3D,EAAA,IAAI,OAAO,QAAA,KAAa,WAAA,EAAa,OAAO,eAAA,CAAgB,OAAA;AAE5D,EAAA,OAAO,eAAA,CAAgB,MAAA;AACzB;AAQO,SAAS,mBAAmB,IAAA,EAA4B;AAC7D,EAAA,IAAI,IAAA,KAAS,WAAA,CAAY,OAAA,EAAS,OAAO,KAAA;AACzC,EAAA,IAAI,IAAA,KAAS,WAAA,CAAY,MAAA,EAAQ,OAAO,IAAA;AACxC,EAAA,OAAO,aAAA,OAAoB,eAAA,CAAgB,MAAA;AAC7C;AAQO,SAAS,sBAAsB,IAAA,EAA4B;AAChE,EAAA,IAAI,IAAA,KAAS,WAAA,CAAY,OAAA,EAAS,OAAO,IAAA;AACzC,EAAA,IAAI,IAAA,KAAS,WAAA,CAAY,MAAA,EAAQ,OAAO,KAAA;AACxC,EAAA,OAAO,aAAA,OAAoB,eAAA,CAAgB,OAAA;AAC7C;AAQO,SAAS,aAAa,MAAA,EAAqC;AAChE,EAAA,IAAI,QAAQ,OAAO,MAAA;AAEnB,EAAA,IAAI,OAAO,UAAA,CAAW,KAAA,KAAU,UAAA,EAAY;AAG1C,IAAA,OAAO,UAAA,CAAW,KAAA,CAAM,IAAA,CAAK,UAAU,CAAA;AAAA,EACzC;AAEA,EAAA,MAAM,IAAI,cAAA;AAAA,IACR;AAAA,GAEF;AACF;AAUO,SAAS,OAAO,KAAA,EAA+B;AACpD,EAAA,OAAO,OAAO,IAAA,KAAS,WAAA,IAAe,KAAA,YAAiB,IAAA;AACzD;AAGO,SAAS,OAAO,KAAA,EAA+B;AACpD,EAAA,OAAO,OAAO,IAAA,KAAS,WAAA,IAAe,KAAA,YAAiB,IAAA;AACzD;AAGO,SAAS,qBAAA,GAAiC;AAC/C,EAAA,OAAO,OAAO,cAAA,KAAmB,WAAA,IAAe,OAAO,WAAA,KAAgB,WAAA;AACzE;AAQO,SAAS,cAAA,GAAyB;AACvC,EAAA,MAAM,YAAa,UAAA,CAAmC,MAAA;AAEtD,EAAA,IAAI,OAAO,SAAA,EAAW,UAAA,KAAe,UAAA,EAAY,OAAO,UAAU,UAAA,EAAW;AAG7E,EAAA,MAAM,KAAA,GAAQ,IAAI,UAAA,CAAW,EAAE,CAAA;AAC/B,EAAA,IAAI,OAAO,SAAA,EAAW,eAAA,KAAoB,UAAA,EAAY,SAAA,CAAU,gBAAgB,KAAK,CAAA;AAAA,OAChF,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,MAAM,MAAA,EAAQ,CAAA,EAAA,EAAK,KAAA,CAAM,CAAC,IAAI,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,MAAA,KAAW,GAAG,CAAA;AAGrF,EAAA,KAAA,CAAM,CAAC,CAAA,GAAK,KAAA,CAAM,CAAC,IAAK,EAAA,GAAQ,EAAA;AAEhC,EAAA,KAAA,CAAM,CAAC,CAAA,GAAK,KAAA,CAAM,CAAC,IAAK,EAAA,GAAQ,GAAA;AAEhC,EAAA,MAAM,MAAM,KAAA,CAAM,IAAA,CAAK,KAAA,EAAO,CAAC,SAAS,IAAA,CAAK,QAAA,CAAS,EAAE,CAAA,CAAE,SAAS,CAAA,EAAG,GAAG,CAAC,CAAA,CAAE,KAAK,EAAE,CAAA;AAEnF,EAAA,OAAO;AAAA,IACL,GAAA,CAAI,KAAA,CAAM,CAAA,EAAG,CAAC,CAAA;AAAA,IACd,GAAA,CAAI,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAAA,IACf,GAAA,CAAI,KAAA,CAAM,EAAA,EAAI,EAAE,CAAA;AAAA,IAChB,GAAA,CAAI,KAAA,CAAM,EAAA,EAAI,EAAE,CAAA;AAAA,IAChB,GAAA,CAAI,KAAA,CAAM,EAAA,EAAI,EAAE;AAAA,GAClB,CAAE,KAAK,GAAG,CAAA;AACZ;AAGO,SAAS,eAAA,GAA2B;AACzC,EAAA,IAAI;AACF,IAAA,OAAO,OAAO,UAAA,CAAW,YAAA,KAAiB,WAAA,IAAe,WAAW,YAAA,KAAiB,IAAA;AAAA,EACvF,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;;;ACvIO,IAAM,UAAA,GAAa;AAAA,EACxB,MAAA,EAAQ,sBAAA;AAAA,EACR,OAAA,EAAS;AACX;AAgBO,IAAM,kBAAA,GAAqB;AAG3B,IAAM,gBAAA,GAAmB;AAmBhC,SAAS,gBAAgB,OAAA,EAAsC;AAC7D,EAAA,IAAI,OAAO,OAAA,KAAY,QAAA,IAAY,OAAA,KAAY,MAAM,OAAO,MAAA;AAC5D,EAAA,MAAM,QAAS,OAAA,CAA0B,WAAA;AACzC,EAAA,OAAO,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,CAAM,MAAA,GAAS,IAAI,KAAA,GAAQ,MAAA;AACjE;AAUO,IAAM,cAAN,MAAkB;AAAA,EACd,OAAA;AAAA,EACA,KAAA;AAAA,EACA,IAAA;AAAA,EACA,QAAA,GAAW,IAAI,OAAA,EAAoB;AAAA;AAAA,EAG5C,QAAA;AAAA;AAAA,EAEA,WAAA,GAA6C,IAAA;AAAA;AAAA,EAE7C,UAAA,GAAqC,IAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOrC,SAAA;AAAA,EAEA,WAAA,CAAY,MAAA,EAAwB,IAAA,EAAkB,GAAA,EAAgB;AACpE,IAAA,IAAA,CAAK,OAAA,GAAU,MAAA;AACf,IAAA,IAAA,CAAK,KAAA,GAAQ,IAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,GAAA;AAAA,EACd;AAAA;AAAA,EAGA,IAAI,EAAA,GAAgC;AAClC,IAAA,OAAO,IAAA,CAAK,QAAA,CAAS,EAAA,CAAG,IAAA,CAAK,KAAK,QAAQ,CAAA;AAAA,EAC5C;AAAA;AAAA,EAGA,IAAI,IAAA,GAAoC;AACtC,IAAA,OAAO,IAAA,CAAK,QAAA,CAAS,IAAA,CAAK,IAAA,CAAK,KAAK,QAAQ,CAAA;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,iBAAA,GAAsC;AAC1C,IAAA,MAAM,KAAK,YAAA,EAAa;AACxB,IAAA,OAAO,KAAK,kBAAA,EAAmB;AAAA,EACjC;AAAA;AAAA,EAGA,kBAAA,GAA8B;AAC5B,IAAA,IAAI,CAAC,IAAA,CAAK,OAAA,CAAQ,YAAA,EAAc,OAAO,IAAA;AACvC,IAAA,IAAI,IAAA,CAAK,IAAA,CAAK,GAAA,CAAI,gBAAgB,GAAG,OAAO,IAAA;AAG5C,IAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,QAAA,EAAU,YAAY,CAAA;AAAA,EAC5C;AAAA;AAAA,EAGA,MAAM,cAAA,GAAkD;AACtD,IAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,cAAA,EAAe;AACxC,IAAA,OAAO,QAAQ,EAAE,aAAA,EAAe,UAAU,KAAK,CAAA,CAAA,KAAO,EAAC;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,WAAA,GAA+B;AACnC,IAAA,IAAI,IAAA,CAAK,SAAA,EAAW,OAAO,IAAA,CAAK,SAAA;AAEhC,IAAA,MAAM,OAAA,GAAU,MAAM,IAAA,CAAK,YAAA,EAAa;AACxC,IAAA,MAAM,WAAW,IAAA,CAAK,OAAA,CAAQ,QAAA,IAAY,OAAA,EAAS,YAAY,cAAA,EAAe;AAE9E,IAAA,IAAA,CAAK,SAAA,GAAY,QAAA;AAIjB,IAAA,IAAI,OAAA,EAAS,aAAa,QAAA,EAAU;AAClC,MAAA,MAAM,IAAA,CAAK,aAAa,EAAE,GAAI,WAAW,EAAC,EAAI,UAAU,CAAA;AAAA,IAC1D;AAEA,IAAA,OAAO,QAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,cAAA,GAAyC;AAC7C,IAAA,MAAM,OAAA,GAAU,MAAM,IAAA,CAAK,YAAA,EAAa;AACxC,IAAA,IAAI,OAAA,EAAS,WAAA,EAAa,OAAO,OAAA,CAAQ,WAAA;AAEzC,IAAA,MAAM,IAAA,GAAO,KAAK,OAAA,CAAQ,IAAA;AAC1B,IAAA,IAAI,CAAC,MAAM,OAAO,IAAA;AAGlB,IAAA,IAAI,OAAO,IAAA,KAAS,QAAA,IAAY,UAAA,IAAc,IAAA,EAAM;AAClD,MAAA,OAAQ,MAAM,IAAA,CAAK,QAAA,EAAS,IAAM,IAAA;AAAA,IACpC;AAEA,IAAA,IAAI,OAAO,IAAA,KAAS,QAAA,IAAY,OAAA,IAAW,IAAA,EAAM;AAC/C,MAAA,OAAO,IAAA,CAAK,uBAAuB,IAAI,CAAA;AAAA,IACzC;AAEA,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,cAAA,GAAmC;AACvC,IAAA,IAAI;AACF,MAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,oBAAA,EAAqB;AAC9C,MAAA,IAAI,KAAA,KAAU,MAAM,OAAO,IAAA;AAG3B,MAAA,IAAA,CAAK,QAAA,CAAS,KAAK,WAAA,EAAa,EAAE,OAAO,IAAA,CAAK,sBAAA,IAA0B,CAAA;AACxE,MAAA,OAAO,KAAA;AAAA,IACT,SAAS,KAAA,EAAO;AACd,MAAA,IAAA,CAAK,QAAA,CAAS,IAAA,CAAK,WAAA,EAAa,EAAE,OAAO,CAAA;AACzC,MAAA,OAAO,KAAA;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,sBAAA,GAAuC;AACrC,IAAA,OAAO,IAAI,YAAA,CAAa;AAAA,MACtB,MAAA,EAAQ,GAAA;AAAA,MACR,IAAA,EAAM,iBAAA;AAAA,MACN,OAAA,EACE,qbAAA;AAAA,MAEF,MAAA,EAAQ,MAAA;AAAA,MACR,MAAM,UAAA,CAAW,OAAA;AAAA,MACjB,GAAA,EAAK;AAAA,KACN,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,OAAA,GAA2B;AAC/B,IAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,oBAAA,EAAqB;AAC9C,IAAA,IAAI,KAAA,KAAU,IAAA,EAAM,MAAM,IAAA,CAAK,sBAAA,EAAuB;AACtD,IAAA,OAAO,KAAA;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,eAAe,WAAA,EAAoC;AACvD,IAAA,MAAM,IAAA,CAAK,YAAA,CAAa,EAAE,GAAI,IAAA,CAAK,QAAA,IAAY,EAAC,EAAI,WAAA,EAAa,UAAA,EAAY,IAAA,CAAK,GAAA,IAAO,CAAA;AACzF,IAAA,IAAA,CAAK,QAAA,CAAS,IAAA,CAAK,QAAA,EAAU,EAAE,aAAa,CAAA;AAAA,EAC9C;AAAA;AAAA,EAGA,MAAM,UAAA,GAAyC;AAC7C,IAAA,OAAO,KAAK,YAAA,EAAa;AAAA,EAC3B;AAAA;AAAA,EAGA,MAAM,WAAW,OAAA,EAAoC;AACnD,IAAA,IAAA,CAAK,IAAA,CAAK,WAAA,CAAY,OAAA,CAAQ,OAAO,CAAA;AACrC,IAAA,IAAA,CAAK,cAAc,OAAA,CAAQ,QAAA;AAC3B,IAAA,MAAM,IAAA,CAAK,aAAa,OAAO,CAAA;AAC/B,IAAA,IAAA,CAAK,kBAAA,EAAmB;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,KAAA,GAAuB;AAC3B,IAAA,IAAA,CAAK,QAAA,GAAW,IAAA;AAChB,IAAA,IAAA,CAAK,KAAK,KAAA,EAAM;AAChB,IAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,OAAA,CAAQ,KAAA,EAAM;AAEjC,IAAA,IAAI,IAAA,CAAK,WAAW,MAAM,IAAA,CAAK,aAAa,EAAE,QAAA,EAAU,IAAA,CAAK,SAAA,EAAW,CAAA;AAExE,IAAA,IAAA,CAAK,QAAA,CAAS,IAAA,CAAK,SAAA,EAAW,MAAS,CAAA;AAAA,EACzC;AAAA,EAEA,MAAM,YAAA,GAA2C;AAC/C,IAAA,IAAI,IAAA,CAAK,QAAA,KAAa,MAAA,EAAW,OAAO,IAAA,CAAK,QAAA;AAE7C,IAAA,MAAM,SAAU,MAAM,IAAA,CAAK,OAAA,CAAQ,OAAA,CAAQ,KAAI,IAAM,IAAA;AAGrD,IAAA,IAAI,QAAQ,OAAA,EAAS,IAAA,CAAK,IAAA,CAAK,WAAA,CAAY,OAAO,OAAO,CAAA;AAEzD,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,kBAAA,CAAmB,IAAA,CAAK,QAAQ,IAAI,CAAA;AAK5D,IAAA,IAAA,CAAK,QAAA,GACH,UAAU,UAAA,GACN;AAAA,MACE,GAAG,MAAA;AAAA,MACH,WAAA,EAAa,MAAA,CAAO,WAAA,IAAe,UAAA,CAAW,WAAA;AAAA,MAC9C,YAAA,EAAc,MAAA,CAAO,YAAA,IAAgB,UAAA,CAAW;AAAA,QAEjD,MAAA,IAAU,UAAA;AAEjB,IAAA,IAAA,CAAK,kBAAA,EAAmB;AAExB,IAAA,OAAO,IAAA,CAAK,QAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,kBAAA,GAA2B;AACzB,IAAA,IAAI,CAAC,IAAA,CAAK,OAAA,CAAQ,YAAA,EAAc;AAEhC,IAAA,MAAM,YAAA,GAAe,KAAK,QAAA,EAAU,YAAA;AACpC,IAAA,IAAI,CAAC,YAAA,EAAc;AACnB,IAAA,IAAI,IAAA,CAAK,IAAA,CAAK,GAAA,CAAI,cAAc,CAAA,EAAG;AAEnC,IAAA,IAAA,CAAK,KAAK,GAAA,CAAI,IAAA,CAAK,QAAQ,OAAA,EAAS,cAAA,EAAgB,cAAc,mBAAmB,CAAA;AAAA,EACvF;AAAA,EAEA,mBAAmB,IAAA,EAAgD;AACjE,IAAA,IAAI,CAAC,MAAM,OAAO,IAAA;AAClB,IAAA,IAAI,OAAO,IAAA,KAAS,QAAA,EAAU,OAAO,EAAE,aAAa,IAAA,EAAM,UAAA,EAAY,IAAA,CAAK,GAAA,EAAI,EAAE;AAEjF,IAAA,IAAI,iBAAiB,IAAA,EAAM;AACzB,MAAA,OAAO;AAAA,QACL,aAAa,IAAA,CAAK,WAAA;AAAA,QAClB,cAAc,IAAA,CAAK,YAAA;AAAA,QACnB,UAAA,EAAY,KAAK,GAAA;AAAI,OACvB;AAAA,IACF;AAEA,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EAEA,MAAM,aAAa,OAAA,EAAoC;AACrD,IAAA,MAAM,UAAU,IAAA,CAAK,OAAA,CAAQ,eAAe,IAAA,CAAK,IAAA,CAAK,WAAU,GAAI,MAAA;AACpE,IAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,QAAA,IAAY,IAAA,CAAK,SAAA;AAE1C,IAAA,MAAM,IAAA,GAAmB;AAAA,MACvB,GAAG,OAAA;AAAA,MACH,GAAI,OAAA,EAAS,MAAA,GAAS,EAAE,OAAA,KAAY,EAAC;AAAA,MACrC,GAAI,QAAA,GAAW,EAAE,QAAA,KAAa;AAAC,KACjC;AAEA,IAAA,IAAA,CAAK,QAAA,GAAW,IAAA;AAChB,IAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,OAAA,CAAQ,GAAA,CAAI,IAAI,CAAA;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,oBAAA,GAA+C;AAC7C,IAAA,IAAI,IAAA,CAAK,WAAA,EAAa,OAAO,IAAA,CAAK,WAAA;AAElC,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,eAAA,EAAgB,CAAE,QAAQ,MAAM;AACnD,MAAA,IAAA,CAAK,WAAA,GAAc,IAAA;AAAA,IACrB,CAAC,CAAA;AAED,IAAA,IAAA,CAAK,WAAA,GAAc,OAAA;AACnB,IAAA,OAAO,OAAA;AAAA,EACT;AAAA,EAEA,MAAM,eAAA,GAA0C;AAC9C,IAAA,MAAM,KAAK,YAAA,EAAa;AAExB,IAAA,IAAI,CAAC,IAAA,CAAK,kBAAA,EAAmB,EAAG;AAG9B,MAAA,OAAO,KAAK,cAAA,EAAe;AAAA,IAC7B;AAEA,IAAA,IAAI;AACF,MAAA,MAAM,OAAA,GAAU,MAAM,IAAA,CAAK,KAAA,CAAM,OAAA,CAAiB;AAAA,QAChD,MAAA,EAAQ,MAAA;AAAA,QACR,MAAM,UAAA,CAAW,OAAA;AAAA;AAAA;AAAA,QAGjB,QAAA,EAAU,IAAA;AAAA;AAAA,QAEV,eAAA,EAAiB,IAAA;AAAA;AAAA;AAAA,QAGjB,SAAA,EAAW;AAAA,OACZ,CAAA;AAED,MAAA,MAAM,WAAA,GAAc,gBAAgB,OAAO,CAAA;AAC3C,MAAA,IAAI,CAAC,WAAA,EAAa,OAAO,IAAA,CAAK,cAAA,EAAe;AAK7C,MAAA,MAAM,OAAA,GAAU,KAAK,IAAA,CAAK,QAAA;AAAA,QACxB,cAAA;AAAA,QACA,IAAA,CAAK,QAAQ,OAAA,GAAU;AAAA,OACzB;AAEA,MAAA,MAAM,KAAK,YAAA,CAAa;AAAA,QACtB,GAAI,IAAA,CAAK,QAAA,IAAY,EAAC;AAAA,QACtB,WAAA;AAAA,QACA,GAAI,OAAA,GAAU,EAAE,YAAA,EAAc,OAAA,KAAY,EAAC;AAAA,QAC3C,UAAA,EAAY,KAAK,GAAA;AAAI,OACtB,CAAA;AAED,MAAA,IAAA,CAAK,QAAA,CAAS,IAAA,CAAK,QAAA,EAAU,EAAE,aAAa,CAAA;AAC5C,MAAA,OAAO,WAAA;AAAA,IACT,SAAS,KAAA,EAAO;AACd,MAAA,IAAI,iBAAiB,WAAA,EAAa;AAEhC,QAAA,IAAA,CAAK,QAAA,GAAW,IAAA;AAChB,QAAA,IAAA,CAAK,KAAK,KAAA,EAAM;AAChB,QAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,OAAA,CAAQ,KAAA,EAAM;AAEjC,QAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,cAAA,EAAe;AAC3C,QAAA,IAAI,QAAA,KAAa,MAAM,OAAO,QAAA;AAI9B,QAAA,MAAM,KAAA;AAAA,MACR;AACA,MAAA,MAAM,KAAA;AAAA,IACR;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,cAAA,GAAyC;AAC7C,IAAA,MAAM,IAAA,GAAO,KAAK,OAAA,CAAQ,IAAA;AAE1B,IAAA,IACE,CAAC,IAAA,CAAK,OAAA,CAAQ,uBAAA,IACd,CAAC,IAAA,IACD,OAAO,IAAA,KAAS,QAAA,IAChB,EAAE,OAAA,IAAW,IAAA,CAAA,EACb;AACA,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,IAAI;AACF,MAAA,OAAO,MAAM,IAAA,CAAK,sBAAA,CAAuB,IAAI,CAAA;AAAA,IAC/C,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,IAAA;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,uBAAuB,WAAA,EAA+C;AACpE,IAAA,IAAI,IAAA,CAAK,UAAA,EAAY,OAAO,IAAA,CAAK,UAAA;AAEjC,IAAA,MAAM,UAAU,IAAA,CAAK,cAAA,CAAe,WAAW,CAAA,CAAE,QAAQ,MAAM;AAC7D,MAAA,IAAA,CAAK,UAAA,GAAa,IAAA;AAAA,IACpB,CAAC,CAAA;AAED,IAAA,IAAA,CAAK,UAAA,GAAa,OAAA;AAClB,IAAA,OAAO,OAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,uBAAuB,WAAA,EAA+C;AAC1E,IAAA,IAAI,YAAY,iBAAA,EAAmB;AACjC,MAAA,MAAM,KAAA,GAAQ,MAAM,WAAA,CAAY,iBAAA,EAAkB;AAClD,MAAA,IAAI,OAAO,OAAO,KAAA;AAAA,IACpB;AAEA,IAAA,IAAI,WAAA,CAAY,cAAA,EAAgB,OAAO,WAAA,CAAY,cAAA;AAEnD,IAAA,MAAM,IAAI,cAAA;AAAA,MACR;AAAA,KAKF;AAAA,EACF;AAAA,EAEA,MAAM,eAAe,WAAA,EAA+C;AAClE,IAAA,MAAM,cAAA,GAAiB,MAAM,IAAA,CAAK,sBAAA,CAAuB,WAAW,CAAA;AAEpE,IAAA,MAAM,OAAA,GAAU,MAAM,IAAA,CAAK,KAAA,CAAM,OAAA,CAAiB;AAAA,MAChD,MAAA,EAAQ,MAAA;AAAA,MACR,MAAM,UAAA,CAAW,MAAA;AAAA,MACjB,IAAA,EAAM,EAAE,KAAA,EAAO,WAAA,CAAY,OAAO,QAAA,EAAU,WAAA,CAAY,UAAU,cAAA,EAAe;AAAA,MACjF,QAAA,EAAU,IAAA;AAAA,MACV,eAAA,EAAiB,IAAA;AAAA;AAAA;AAAA,MAGjB,SAAA,EAAW;AAAA,KACZ,CAAA;AAED,IAAA,MAAM,WAAA,GAAc,gBAAgB,OAAO,CAAA;AAE3C,IAAA,IAAI,CAAC,WAAA,EAAa;AAEhB,MAAA,MAAM,IAAI,cAAA;AAAA,QACR;AAAA,OAGF;AAAA,IACF;AAIA,IAAA,MAAM,IAAA,CAAK,aAAa,EAAE,WAAA,EAAa,YAAY,IAAA,CAAK,GAAA,IAAO,CAAA;AAC/D,IAAA,IAAA,CAAK,QAAA,CAAS,IAAA,CAAK,QAAA,EAAU,EAAE,aAAa,CAAA;AAC5C,IAAA,IAAA,CAAK,QAAA,CAAS,IAAA,CAAK,QAAA,EAAU,EAAE,aAAa,CAAA;AAE5C,IAAA,OAAO,WAAA;AAAA,EACT;AACF,CAAA;;;ACtcO,IAAM,qBAAN,MAAiD;AAAA,EACtD,QAAA,GAA8B,IAAA;AAAA,EAE9B,YAAY,OAAA,EAA6B;AACvC,IAAA,IAAA,CAAK,WAAW,OAAA,IAAW,IAAA;AAAA,EAC7B;AAAA,EAEA,GAAA,GAAyB;AACvB,IAAA,OAAO,IAAA,CAAK,QAAA;AAAA,EACd;AAAA,EAEA,IAAI,OAAA,EAA2B;AAC7B,IAAA,IAAA,CAAK,QAAA,GAAW,OAAA;AAAA,EAClB;AAAA,EAEA,KAAA,GAAc;AACZ,IAAA,IAAA,CAAK,QAAA,GAAW,IAAA;AAAA,EAClB;AACF;AAWO,IAAM,2BAAN,MAAuD;AAAA,EACnD,IAAA;AAAA,EACA,SAAA,GAAY,IAAI,kBAAA,EAAmB;AAAA,EACnC,UAAA;AAAA;AAAA,EAGT,WAAA,CAAY,MAAM,iBAAA,EAAmB;AACnC,IAAA,IAAA,CAAK,IAAA,GAAO,GAAA;AACZ,IAAA,IAAA,CAAK,aAAa,eAAA,EAAgB;AAAA,EACpC;AAAA,EAEA,GAAA,GAAyB;AACvB,IAAA,IAAI,CAAC,IAAA,CAAK,UAAA,EAAY,OAAO,IAAA,CAAK,UAAU,GAAA,EAAI;AAEhD,IAAA,IAAI;AACF,MAAA,MAAM,GAAA,GAAM,UAAA,CAAW,YAAA,CAAa,OAAA,CAAQ,KAAK,IAAI,CAAA;AACrD,MAAA,IAAI,CAAC,KAAK,OAAO,IAAA;AACjB,MAAA,MAAM,MAAA,GAAkB,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA;AACtC,MAAA,OAAO,OAAO,MAAA,KAAW,QAAA,IAAY,MAAA,KAAW,OAAQ,MAAA,GAAwB,IAAA;AAAA,IAClF,CAAA,CAAA,MAAQ;AAEN,MAAA,OAAO,IAAA;AAAA,IACT;AAAA,EACF;AAAA,EAEA,IAAI,OAAA,EAA2B;AAC7B,IAAA,IAAI,CAAC,KAAK,UAAA,EAAY;AACpB,MAAA,IAAA,CAAK,SAAA,CAAU,IAAI,OAAO,CAAA;AAC1B,MAAA;AAAA,IACF;AAEA,IAAA,IAAI;AACF,MAAA,UAAA,CAAW,aAAa,OAAA,CAAQ,IAAA,CAAK,MAAM,IAAA,CAAK,SAAA,CAAU,OAAO,CAAC,CAAA;AAAA,IACpE,CAAA,CAAA,MAAQ;AAEN,MAAA,IAAA,CAAK,SAAA,CAAU,IAAI,OAAO,CAAA;AAAA,IAC5B;AAAA,EACF;AAAA,EAEA,KAAA,GAAc;AACZ,IAAA,IAAI,CAAC,KAAK,UAAA,EAAY;AACpB,MAAA,IAAA,CAAK,UAAU,KAAA,EAAM;AACrB,MAAA;AAAA,IACF;AAEA,IAAA,IAAI;AACF,MAAA,UAAA,CAAW,YAAA,CAAa,UAAA,CAAW,IAAA,CAAK,IAAI,CAAA;AAAA,IAC9C,CAAA,CAAA,MAAQ;AACN,MAAA,IAAA,CAAK,UAAU,KAAA,EAAM;AAAA,IACvB;AAAA,EACF;AACF;AAcO,SAAS,mBAAmB,QAAA,EAAsC;AACvE,EAAA,OAAO,QAAA;AACT;;;AChIO,SAAS,WAAW,MAAA,EAA8B;AACvD,EAAA,IAAI,CAAC,QAAQ,OAAO,EAAA;AAEpB,EAAA,MAAM,MAAA,GAAS,IAAI,eAAA,EAAgB;AAEnC,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA,EAAG;AACjD,IAAA,IAAI,KAAA,KAAU,MAAA,IAAa,KAAA,KAAU,IAAA,EAAM;AAE3C,IAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AACxB,MAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,QAAA,IAAI,IAAA,KAAS,MAAA,IAAa,IAAA,KAAS,IAAA,EAAM;AACzC,QAAA,MAAA,CAAO,MAAA,CAAO,GAAA,EAAK,MAAA,CAAO,IAAI,CAAC,CAAA;AAAA,MACjC;AACA,MAAA;AAAA,IACF;AAEA,IAAA,MAAA,CAAO,MAAA,CAAO,GAAA,EAAK,MAAA,CAAO,KAAK,CAAC,CAAA;AAAA,EAClC;AAEA,EAAA,MAAM,KAAA,GAAQ,OAAO,QAAA,EAAS;AAC9B,EAAA,OAAO,KAAA,GAAQ,CAAA,CAAA,EAAI,KAAK,CAAA,CAAA,GAAK,EAAA;AAC/B;AAUO,SAAS,iBAAA,CAAkB,KAAA,EAAe,IAAA,GAAO,2EAAA,EAAyB;AAC/E,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,CAAM,IAAA,OAAW,EAAA,EAAI;AACpD,IAAA,MAAM,IAAI,cAAA;AAAA,MACR,GAAG,IAAI,CAAA,8MAAA,EAA4C,IAAA,CAAK,SAAA,CAAU,KAAK,CAAC,CAAA;AAAA,KAC1E;AAAA,EACF;AACA,EAAA,OAAO,mBAAmB,KAAK,CAAA;AACjC;AAcO,SAAS,OAAA,CAAQ,SAAiB,IAAA,EAAsB;AAC7D,EAAA,MAAM,IAAA,GAAO,QAAQ,QAAA,CAAS,GAAG,IAAI,OAAA,CAAQ,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA,GAAI,OAAA;AAC5D,EAAA,MAAM,SAAS,IAAA,CAAK,UAAA,CAAW,GAAG,CAAA,GAAI,IAAA,GAAO,IAAI,IAAI,CAAA,CAAA;AACrD,EAAA,OAAO,CAAA,EAAG,IAAI,CAAA,EAAG,MAAM,CAAA,CAAA;AACzB;AAGO,SAAS,iBAAiB,OAAA,EAAyB;AACxD,EAAA,IAAI,MAAA;AACJ,EAAA,IAAI;AACF,IAAA,MAAA,GAAS,IAAI,IAAI,OAAO,CAAA;AAAA,EAC1B,CAAA,CAAA,MAAQ;AACN,IAAA,MAAM,IAAI,cAAA;AAAA,MACR,CAAA,0LAAA,EAAiD,IAAA,CAAK,SAAA,CAAU,OAAO,CAAC,CAAA;AAAA,KAC1E;AAAA,EACF;AAEA,EAAA,IAAI,MAAA,CAAO,QAAA,KAAa,OAAA,IAAW,MAAA,CAAO,aAAa,QAAA,EAAU;AAC/D,IAAA,MAAM,IAAI,cAAA;AAAA,MACR,CAAA,uMAAA,EAAyD,OAAO,QAAQ,CAAA;AAAA,KAC1E;AAAA,EACF;AAEA,EAAA,OAAO,MAAA,CAAO,MAAA,IAAU,MAAA,CAAO,QAAA,KAAa,GAAA,GAAM,KAAK,MAAA,CAAO,QAAA,CAAS,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAA,CAAA;AAC1F;;;ACnGO,IAAM,gBAAA,GAAmB;AAGzB,IAAM,eAAA,GAAkB;AAKxB,IAAM,eAAA,GAAkB;AAYxB,IAAM,kBAAA,GAAqB,oCAAoC,eAAe,CAAA,sCAAA;AAwB9E,IAAM,yBAAA,GAA4B,OAAO,MAAA,CAAO,CAAC,KAAM,GAAA,EAAM,GAAA,EAAQ,GAAA,EAAQ,GAAM,CAAC,CAAA;AAmC3F,SAAS,eAAA,CAAgB,OAAe,IAAA,EAAsB;AAC5D,EAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,KAAK,CAAA,IAAK,QAAQ,CAAA,EAAG;AACxC,IAAA,MAAM,IAAI,cAAA,CAAe,CAAA,EAAG,IAAI,CAAA,kPAAA,EAAkD,KAAK,CAAA,CAAE,CAAA;AAAA,EAC3F;AACA,EAAA,OAAO,KAAA;AACT;AAGA,SAAS,aAAA,GAAwB;AAC/B,EAAA,OAAO;AAAA,IACL,KAAA,EAAO,CAAC,OAAA,EAAA,GAAY,IAAA,KAAS,OAAA,CAAQ,MAAM,CAAA,UAAA,EAAa,OAAO,CAAA,CAAA,EAAI,GAAG,IAAI,CAAA;AAAA,IAC1E,IAAA,EAAM,CAAC,OAAA,EAAA,GAAY,IAAA,KAAS,OAAA,CAAQ,KAAK,CAAA,UAAA,EAAa,OAAO,CAAA,CAAA,EAAI,GAAG,IAAI,CAAA;AAAA,IACxE,IAAA,EAAM,CAAC,OAAA,EAAA,GAAY,IAAA,KAAS,OAAA,CAAQ,KAAK,CAAA,UAAA,EAAa,OAAO,CAAA,CAAA,EAAI,GAAG,IAAI,CAAA;AAAA,IACxE,KAAA,EAAO,CAAC,OAAA,EAAA,GAAY,IAAA,KAAS,OAAA,CAAQ,MAAM,CAAA,UAAA,EAAa,OAAO,CAAA,CAAA,EAAI,GAAG,IAAI;AAAA,GAC5E;AACF;AAEA,SAAS,aAAa,KAAA,EAAoE;AACxF,EAAA,IAAI,KAAA,KAAU,OAAO,OAAO,MAAA;AAE5B,EAAA,MAAM,OAAA,GAAU,SAAS,EAAC;AAC1B,EAAA,MAAM,QAAA,GAAW,QAAQ,QAAA,IAAY,CAAA;AAErC,EAAA,IAAI,CAAC,MAAA,CAAO,SAAA,CAAU,QAAQ,CAAA,IAAK,WAAW,CAAA,EAAG;AAC/C,IAAA,MAAM,IAAI,cAAA,CAAe,CAAA,mNAAA,EAA2D,QAAQ,CAAA,CAAE,CAAA;AAAA,EAChG;AAEA,EAAA,MAAM,MAAA,GAAS,QAAQ,MAAA,IAAU,GAAA;AACjC,EAAA,IAAI,MAAA,GAAS,CAAA,IAAK,MAAA,GAAS,CAAA,EAAG;AAC5B,IAAA,MAAM,IAAI,cAAA,CAAe,CAAA,qMAAA,EAAuD,MAAM,CAAA,CAAE,CAAA;AAAA,EAC1F;AAGA,EAAA,IAAI,QAAA,KAAa,GAAG,OAAO,MAAA;AAE3B,EAAA,OAAO;AAAA,IACL,QAAA;AAAA,IACA,SAAA,EAAW,eAAA,CAAgB,OAAA,CAAQ,SAAA,IAAa,KAAK,iBAAiB,CAAA;AAAA,IACtE,QAAA,EAAU,eAAA,CAAgB,OAAA,CAAQ,QAAA,IAAY,KAAQ,gBAAgB,CAAA;AAAA,IACtE,MAAA;AAAA,IACA,WAAA,EAAa,QAAQ,WAAA,IAAe,KAAA;AAAA,IACpC,aAAa,OAAA,CAAQ;AAAA,GACvB;AACF;AAEA,SAAS,iBACP,SAAA,EACsC;AACtC,EAAA,IAAI,SAAA,KAAc,OAAO,OAAO,MAAA;AAEhC,EAAA,MAAM,QAAA,GAAW;AAAA,IACf,WAAA,EAAa,CAAA;AAAA,IACb,GAAA,EAAK,MAAA;AAAA,IACL,WAAA,EAAa,yBAAA;AAAA,IACb,cAAA,EAAgB;AAAA,GAClB;AACA,EAAA,IAAI,CAAC,WAAW,OAAO,QAAA;AAEvB,EAAA,MAAM,WAAA,GAAc,UAAU,WAAA,IAAe,CAAA;AAC7C,EAAA,IAAI,CAAC,MAAA,CAAO,SAAA,CAAU,WAAW,CAAA,IAAK,cAAc,CAAA,EAAG;AACrD,IAAA,MAAM,IAAI,cAAA;AAAA,MACR,6NAAkE,WAAW,CAAA;AAAA,KAC/E;AAAA,EACF;AAEA,EAAA,IAAI,SAAA,CAAU,GAAA,KAAQ,MAAA,KAAc,CAAC,MAAA,CAAO,QAAA,CAAS,SAAA,CAAU,GAAG,CAAA,IAAK,SAAA,CAAU,GAAA,IAAO,CAAA,CAAA,EAAI;AAC1F,IAAA,MAAM,IAAI,cAAA;AAAA,MACR,CAAA,mPAAA,EAA6D,UAAU,GAAG,CAAA;AAAA,KAC5E;AAAA,EACF;AAEA,EAAA,MAAM,WAAA,GAAc,SAAA,CAAU,WAAA,IAAe,QAAA,CAAS,WAAA;AACtD,EAAA,KAAA,MAAW,KAAA,IAAS,WAAA,EAAa,eAAA,CAAgB,KAAA,EAAO,uBAAuB,CAAA;AAE/E,EAAA,OAAO;AAAA,IACL,WAAA;AAAA,IACA,KAAK,SAAA,CAAU,GAAA;AAAA,IACf,WAAA;AAAA,IACA,cAAA,EAAgB,UAAU,cAAA,IAAkB;AAAA,GAC9C;AACF;AAQA,SAAS,aAAa,IAAA,EAAoD;AACxE,EAAA,IAAI,IAAA,KAAS,QAAW,OAAO,MAAA;AAE/B,EAAA,IAAI,OAAO,SAAS,QAAA,EAAU;AAC5B,IAAA,IAAI,IAAA,CAAK,IAAA,EAAK,KAAM,EAAA,EAAI;AACtB,MAAA,MAAM,IAAI,eAAe,mLAAiD,CAAA;AAAA,IAC5E;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,IAAI,OAAO,IAAA,KAAS,QAAA,IAAY,IAAA,KAAS,IAAA,EAAM;AAC7C,IAAA,MAAM,IAAI,cAAA;AAAA,MACR,CAAA,uRAAA,EAA8D,OAAO,IAAI,CAAA;AAAA,KAC3E;AAAA,EACF;AAEA,EAAA,IAAI,cAAc,IAAA,EAAM;AACtB,IAAA,IAAI,OAAO,IAAA,CAAK,QAAA,KAAa,UAAA,EAAY;AACvC,MAAA,MAAM,IAAI,eAAe,8HAAoC,CAAA;AAAA,IAC/D;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,IAAI,iBAAiB,IAAA,EAAM;AACzB,IAAA,IAAI,OAAO,KAAK,WAAA,KAAgB,QAAA,IAAY,KAAK,WAAA,CAAY,IAAA,OAAW,EAAA,EAAI;AAC1E,MAAA,MAAM,IAAI,eAAe,4KAA+C,CAAA;AAAA,IAC1E;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,IAAI,OAAA,IAAW,IAAA,IAAQ,UAAA,IAAc,IAAA,EAAM;AACzC,IAAA,MAAM,EAAE,KAAA,EAAO,QAAA,EAAU,cAAA,EAAgB,mBAAkB,GAAI,IAAA;AAM/D,IAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,CAAM,IAAA,OAAW,EAAA,EAAI;AACpD,MAAA,MAAM,IAAI,eAAe,sKAAyC,CAAA;AAAA,IACpE;AACA,IAAA,IAAI,OAAO,QAAA,KAAa,QAAA,IAAY,QAAA,KAAa,EAAA,EAAI;AACnD,MAAA,MAAM,IAAI,eAAe,yKAA4C,CAAA;AAAA,IACvE;AACA,IAAA,IAAI,iBAAA,KAAsB,MAAA,IAAa,OAAO,iBAAA,KAAsB,UAAA,EAAY;AAC9E,MAAA,MAAM,IAAI,eAAe,uIAA6C,CAAA;AAAA,IACxE;AACA,IAAA,IACE,cAAA,KAAmB,WAClB,OAAO,cAAA,KAAmB,YAAY,cAAA,CAAe,IAAA,OAAW,EAAA,CAAA,EACjE;AACA,MAAA,MAAM,IAAI,eAAe,+KAAkD,CAAA;AAAA,IAC7E;AAKA,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,MAAM,IAAI,cAAA;AAAA,IACR;AAAA,GAEF;AACF;AAUO,SAAS,aAAA,CAAc,OAAA,GAA4B,EAAC,EAAmB;AAC5E,EAAA,MAAM,IAAA,GAAoB,OAAA,CAAQ,IAAA,IAAQ,WAAA,CAAY,IAAA;AAEtD,EAAA,IAAI,CAAC,MAAA,CAAO,MAAA,CAAO,WAAW,CAAA,CAAE,QAAA,CAAS,IAAI,CAAA,EAAG;AAC9C,IAAA,MAAM,IAAI,cAAA;AAAA,MACR,CAAA,+GAAA,EAA6B,OAAO,MAAA,CAAO,WAAW,EAAE,IAAA,CAAK,IAAI,CAAC,CAAA,oDAAA,EAAe,IAAI,CAAA;AAAA,KACvF;AAAA,EACF;AAEA,EAAA,MAAM,OAAA,GAAU,eAAA,CAAgB,OAAA,CAAQ,OAAA,IAAW,iBAAiB,SAAS,CAAA;AAE7E,EAAA,IACE,OAAA,CAAQ,QAAA,KAAa,MAAA,KACpB,OAAO,OAAA,CAAQ,QAAA,KAAa,QAAA,IAAY,OAAA,CAAQ,QAAA,CAAS,IAAA,EAAK,KAAM,EAAA,CAAA,EACrE;AACA,IAAA,MAAM,IAAI,eAAe,oKAAuC,CAAA;AAAA,EAClE;AAEA,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,gBAAA,CAAiB,OAAA,CAAQ,OAAA,IAAW,gBAAgB,CAAA;AAAA,IAC7D,IAAA,EAAM,YAAA,CAAa,OAAA,CAAQ,IAAI,CAAA;AAAA,IAC/B,OAAA,EAAS,OAAA,CAAQ,OAAA,IAAW,IAAI,kBAAA,EAAmB;AAAA,IACnD,WAAA,EAAa,QAAQ,WAAA,IAAe,IAAA;AAAA,IACpC,uBAAA,EAAyB,QAAQ,uBAAA,IAA2B,IAAA;AAAA,IAC5D,KAAA,EAAO,YAAA,CAAa,OAAA,CAAQ,KAAK,CAAA;AAAA,IACjC,OAAA;AAAA,IACA,KAAA,EAAO,YAAA,CAAa,OAAA,CAAQ,KAAK,CAAA;AAAA,IACjC,SAAA,EAAW,gBAAA,CAAiB,OAAA,CAAQ,SAAS,CAAA;AAAA,IAC7C,KAAA,EAAO,OAAA,CAAQ,KAAA,IAAS,EAAC;AAAA,IACzB,QAAQ,OAAA,CAAQ,MAAA,KAAW,OAAO,aAAA,EAAc,GAAI,QAAQ,MAAA,IAAU,MAAA;AAAA,IACtE,OAAA,EAAS,EAAE,GAAG,OAAA,CAAQ,OAAA,EAAQ;AAAA,IAC9B,UAAU,OAAA,CAAQ,QAAA;AAAA;AAAA,IAElB,WAAW,OAAA,CAAQ,SAAA,KAAc,KAAA,GAAQ,MAAA,GAAa,QAAQ,SAAA,IAAa,kBAAA;AAAA,IAC3E,IAAA;AAAA,IACA,YAAA,EAAc,mBAAmB,IAAI,CAAA;AAAA,IACrC,eAAA,EAAiB,sBAAsB,IAAI;AAAA,GAC7C;AACF;;;AC1RA,IAAM,cAAA,uBAAqB,GAAA,CAAI,CAAC,iBAAiB,QAAA,EAAU,YAAA,EAAc,WAAW,CAAC,CAAA;AAGrF,IAAM,aAAA,uBAAoB,GAAA,CAAI;AAAA,EAC5B,UAAA;AAAA,EACA,aAAA;AAAA,EACA,aAAA;AAAA,EACA,aAAA;AAAA,EACA,cAAA;AAAA,EACA,iBAAA;AAAA,EACA,WAAA;AAAA,EACA,OAAA;AAAA,EACA,gBAAA;AAAA,EACA;AACF,CAAC,CAAA;AAUM,SAAS,WAAW,KAAA,EAAuB;AAChD,EAAA,IAAI,KAAA,CAAM,MAAA,IAAU,CAAA,EAAG,OAAO,QAAA;AAC9B,EAAA,OAAO,CAAA,EAAG,KAAA,CAAM,KAAA,CAAM,CAAA,EAAG,CAAC,CAAC,CAAA,OAAA,EAAK,KAAA,CAAM,MAAM,CAAA,OAAA,EAAK,KAAA,CAAM,KAAA,CAAM,EAAE,CAAC,CAAA,CAAA;AAClE;AAQO,SAAS,cAAc,OAAA,EAA0C;AACtE,EAAA,MAAM,SAAiC,EAAC;AAExC,EAAA,OAAA,CAAQ,OAAA,CAAQ,CAAC,KAAA,EAAO,IAAA,KAAS;AAC/B,IAAA,IAAI,cAAA,CAAe,GAAA,CAAI,IAAA,CAAK,WAAA,EAAa,CAAA,EAAG;AAE1C,MAAA,MAAM,OAAA,GAAU,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAA;AACjC,MAAA,MAAA,CAAO,IAAI,IACT,OAAA,GAAU,CAAA,GACN,GAAG,KAAA,CAAM,KAAA,CAAM,GAAG,OAAO,CAAC,IAAI,UAAA,CAAW,KAAA,CAAM,MAAM,OAAA,GAAU,CAAC,CAAC,CAAC,CAAA,CAAA,GAClE,WAAW,KAAK,CAAA;AACtB,MAAA;AAAA,IACF;AACA,IAAA,MAAA,CAAO,IAAI,CAAA,GAAI,KAAA;AAAA,EACjB,CAAC,CAAA;AAED,EAAA,OAAO,MAAA;AACT;AAOO,SAAS,WAAW,IAAA,EAAwB;AACjD,EAAA,IAAI,IAAA,KAAS,IAAA,IAAQ,IAAA,KAAS,MAAA,EAAW,OAAO,IAAA;AAEhD,EAAA,IAAI,OAAO,QAAA,KAAa,WAAA,IAAe,IAAA,YAAgB,UAAU,OAAO,YAAA;AACxE,EAAA,IAAI,MAAA,CAAO,IAAI,CAAA,EAAG,OAAO,QAAA;AACzB,EAAA,IAAI,gBAAgB,WAAA,IAAe,WAAA,CAAY,MAAA,CAAO,IAAI,GAAG,OAAO,UAAA;AAEpE,EAAA,IAAI,MAAM,OAAA,CAAQ,IAAI,GAAG,OAAO,IAAA,CAAK,IAAI,UAAU,CAAA;AAEnD,EAAA,IAAI,OAAO,SAAS,QAAA,EAAU;AAC5B,IAAA,MAAM,SAAkC,EAAC;AACzC,IAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,IAAI,CAAA,EAAG;AAC/C,MAAA,MAAA,CAAO,GAAG,CAAA,GAAI,aAAA,CAAc,GAAA,CAAI,GAAA,CAAI,aAAa,CAAA,GAAI,wCAAA,GAAa,UAAA,CAAW,KAAK,CAAA;AAAA,IACpF;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,OAAO,IAAA;AACT;;;AC7DO,SAAS,WAAW,IAAA,EAAwB;AACjD,EAAA,IAAI,OAAO,SAAS,QAAA,IAAY,IAAA,KAAS,QAAQ,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA,EAAG,OAAO,IAAA;AAE7E,EAAA,MAAM,IAAA,GAAO,MAAA,CAAO,IAAA,CAAK,IAAI,CAAA;AAC7B,EAAA,IAAI,KAAK,MAAA,KAAW,CAAA,IAAK,KAAK,CAAC,CAAA,KAAM,QAAQ,OAAO,IAAA;AAEpD,EAAA,OAAQ,IAAA,CAA2B,IAAA;AACrC;AAQO,SAAS,SAAS,KAAA,EAAkD;AACzE,EAAA,OAAO,OAAO,UAAU,QAAA,IAAY,KAAA,KAAU,QAAQ,CAAC,KAAA,CAAM,QAAQ,KAAK,CAAA;AAC5E;AAGO,SAAS,SAAS,KAAA,EAAoC;AAC3D,EAAA,OAAO,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,CAAM,MAAA,GAAS,IAAI,KAAA,GAAQ,MAAA;AACjE;AAQO,SAAS,SAAA,CAAa,QAAiB,KAAA,EAAoB;AAChE,EAAA,IAAI,OAAO,MAAA,KAAW,QAAA,IAAY,MAAA,KAAW,IAAA,SAAa,EAAC;AAC3D,EAAA,MAAM,KAAA,GAAS,OAAmC,KAAK,CAAA;AACvD,EAAA,OAAO,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,GAAK,QAAgB,EAAC;AAClD;AAGO,SAAS,UAAA,CAAW,QAAiB,KAAA,EAAoD;AAC9F,EAAA,IAAI,OAAO,MAAA,KAAW,QAAA,IAAY,MAAA,KAAW,MAAM,OAAO,MAAA;AAC1D,EAAA,MAAM,KAAA,GAAS,OAAmC,KAAK,CAAA;AACvD,EAAA,IAAI,OAAO,UAAU,QAAA,IAAY,KAAA,KAAU,QAAQ,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG,OAAO,MAAA;AAChF,EAAA,OAAO,KAAA;AACT;AAGO,SAAS,WAAA,CAAY,MAAA,EAAiB,KAAA,EAAe,QAAA,GAAW,KAAA,EAAgB;AACrF,EAAA,IAAI,OAAO,MAAA,KAAW,QAAA,IAAY,MAAA,KAAW,MAAM,OAAO,QAAA;AAC1D,EAAA,MAAM,KAAA,GAAS,OAAmC,KAAK,CAAA;AACvD,EAAA,OAAO,OAAO,KAAA,KAAU,SAAA,GAAY,KAAA,GAAQ,QAAA;AAC9C;AAGO,SAAS,UAAA,CAAW,MAAA,EAAiB,KAAA,EAAe,QAAA,EAA0B;AACnF,EAAA,IAAI,OAAO,MAAA,KAAW,QAAA,IAAY,MAAA,KAAW,MAAM,OAAO,QAAA;AAC1D,EAAA,MAAM,KAAA,GAAS,OAAmC,KAAK,CAAA;AACvD,EAAA,OAAO,OAAO,KAAA,KAAU,QAAA,IAAY,OAAO,QAAA,CAAS,KAAK,IAAI,KAAA,GAAQ,QAAA;AACvE;AAGO,SAAS,UAAA,CAAW,QAAiB,KAAA,EAAmC;AAC7E,EAAA,IAAI,OAAO,MAAA,KAAW,QAAA,IAAY,MAAA,KAAW,MAAM,OAAO,MAAA;AAC1D,EAAA,MAAM,KAAA,GAAS,OAAmC,KAAK,CAAA;AACvD,EAAA,OAAO,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,CAAM,MAAA,GAAS,IAAI,KAAA,GAAQ,MAAA;AACjE;;;AC/CA,SAAS,mBAAmB,MAAA,EAAiD;AAC3E,EAAA,MAAM,SAAyB,EAAC;AAEhC,EAAA,MAAM,SAAS,MAAA,CAAO,MAAA;AACtB,EAAA,IAAI,QAAA,CAAS,MAAM,CAAA,EAAG;AACpB,IAAA,KAAA,MAAW,CAAC,KAAA,EAAO,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA,EAAG;AACnD,MAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AACxB,QAAA,MAAM,WAAW,KAAA,CAAM,MAAA,CAAO,CAAC,IAAA,KAAyB,OAAO,SAAS,QAAQ,CAAA;AAChF,QAAA,IAAI,QAAA,CAAS,MAAA,GAAS,CAAA,EAAG,MAAA,CAAO,KAAK,CAAA,GAAI,QAAA;AAAA,MAC3C,CAAA,MAAA,IAAW,OAAO,KAAA,KAAU,QAAA,EAAU;AACpC,QAAA,MAAA,CAAO,KAAK,CAAA,GAAI,CAAC,KAAK,CAAA;AAAA,MACxB;AAAA,IACF;AAAA,EACF;AAEA,EAAA,MAAM,aAAa,MAAA,CAAO,UAAA;AAC1B,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,UAAU,CAAA,EAAG;AAC7B,IAAA,KAAA,MAAW,aAAa,UAAA,EAAY;AAClC,MAAA,IAAI,CAAC,QAAA,CAAS,SAAS,CAAA,EAAG;AAC1B,MAAA,MAAM,QAAQ,QAAA,CAAS,SAAA,CAAU,KAAK,CAAA,IAAK,QAAA,CAAS,UAAU,QAAQ,CAAA;AACtE,MAAA,MAAM,OAAA,GAAU,QAAA,CAAS,SAAA,CAAU,OAAO,CAAA;AAC1C,MAAA,IAAI,CAAC,KAAA,IAAS,CAAC,OAAA,EAAS;AACxB,MAAA,MAAM,QAAA,GAAW,OAAO,KAAK,CAAA;AAC7B,MAAA,IAAI,QAAA,EAAU,QAAA,CAAS,IAAA,CAAK,OAAO,CAAA;AAAA,WAC9B,MAAA,CAAO,KAAK,CAAA,GAAI,CAAC,OAAO,CAAA;AAAA,IAC/B;AAAA,EACF;AAEA,EAAA,OAAO,MAAA;AACT;AAYO,SAAS,cAAA,CAAe,IAAA,EAAe,MAAA,EAAgB,UAAA,GAAa,EAAA,EAAqB;AAC9F,EAAA,MAAM,eAAA,GAAkB,aAAa,CAAA,KAAA,EAAQ,MAAM,IAAI,UAAU,CAAA,CAAA,GAAK,QAAQ,MAAM,CAAA,CAAA;AAGpF,EAAA,IAAI,OAAO,SAAS,QAAA,EAAU;AAC5B,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,eAAA;AAAA,MACN,OAAA,EAAS,QAAA,CAAS,IAAA,CAAK,IAAA,EAAM,CAAA,IAAK,eAAA;AAAA,MAClC,MAAA,EAAQ,MAAA;AAAA,MACR,KAAA,EAAO,MAAA;AAAA,MACP,aAAa,EAAC;AAAA,MACd,MAAA,EAAQ;AAAA,KACV;AAAA,EACF;AAEA,EAAA,IAAI,CAAC,QAAA,CAAS,IAAI,CAAA,EAAG;AACnB,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,eAAA;AAAA,MACN,OAAA,EAAS,eAAA;AAAA,MACT,MAAA,EAAQ,MAAA;AAAA,MACR,KAAA,EAAO,MAAA;AAAA,MACP,aAAa,EAAC;AAAA,MACd,MAAA,EAAQ;AAAA,KACV;AAAA,EACF;AAIA,EAAA,IAAI,IAAA,CAAK,SAAS,YAAA,EAAc;AAC9B,IAAA,MAAM,MAAA,GAAS,QAAA,CAAS,IAAA,CAAK,EAAE,CAAA;AAE/B,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,kBAAA;AAAA,MACN,OAAA,EAAS,MAAA,GACL,CAAA,yOAAA,EAAgD,MAAM,CAAA,IAAA,CAAA,GACtD,gMAAA;AAAA,MACJ,MAAA,EAAQ,MAAA;AAAA,MACR,KAAA,EAAO,MAAA;AAAA,MACP,aAAa,EAAC;AAAA,MACd,MAAA,EAAQ;AAAA,KACV;AAAA,EACF;AAIA,EAAA,MAAM,QAAQ,QAAA,CAAS,IAAA,CAAK,KAAK,CAAA,GAAI,KAAK,KAAA,GAAQ,IAAA;AAElD,EAAA,MAAM,OAAA,GACJ,QAAA,CAAS,KAAA,CAAM,OAAO,CAAA,IACtB,QAAA,CAAS,KAAA,CAAM,MAAM,CAAA,IACrB,QAAA,CAAS,KAAA,CAAM,KAAK,CAAA;AAAA,EAEpB,QAAA,CAAS,IAAA,CAAK,KAAK,CAAA,IACnB,eAAA;AAEF,EAAA,OAAO;AAAA,IACL,IAAA,EAAO,SAAS,KAAA,CAAM,IAAI,KAAK,QAAA,CAAS,IAAA,CAAK,IAAI,CAAA,IAAK,eAAA;AAAA,IACtD,OAAA;AAAA,IACA,MAAA,EAAQ,QAAA,CAAS,KAAA,CAAM,MAAM,CAAA;AAAA,IAC7B,KAAA,EAAO,QAAA,CAAS,KAAA,CAAM,KAAK,CAAA;AAAA,IAC3B,WAAA,EAAa,EAAE,GAAG,kBAAA,CAAmB,IAAI,CAAA,EAAG,GAAG,kBAAA,CAAmB,KAAK,CAAA,EAAE;AAAA,IACzE,QAAQ,QAAA,CAAS,KAAA,CAAM,MAAM,CAAA,IAAK,QAAA,CAAS,KAAK,MAAM;AAAA,GACxD;AACF;AAQO,SAAS,eAAA,CACd,MAAA,EACA,GAAA,GAAM,IAAA,CAAK,KAAI,EACK;AACpB,EAAA,IAAI,CAAC,QAAQ,OAAO,MAAA;AAEpB,EAAA,MAAM,OAAA,GAAU,OAAO,MAAM,CAAA;AAC7B,EAAA,IAAI,MAAA,CAAO,SAAS,OAAO,CAAA,SAAU,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,OAAA,GAAU,GAAI,CAAA;AAE/D,EAAA,MAAM,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,MAAM,CAAA;AAC9B,EAAA,IAAI,MAAA,CAAO,SAAS,IAAI,CAAA,SAAU,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,GAAO,GAAG,CAAA;AAExD,EAAA,OAAO,MAAA;AACT;AAGA,SAAS,aAAA,CAAc,SAA8B,IAAA,EAAkC;AACrF,EAAA,MAAM,GAAA,GAAM,OAAA,EAAS,GAAA,CAAI,IAAI,CAAA;AAC7B,EAAA,IAAI,GAAA,KAAQ,IAAA,IAAQ,GAAA,KAAQ,MAAA,EAAW,OAAO,MAAA;AAE9C,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,QAAA,CAAS,GAAA,EAAK,EAAE,CAAA;AACrC,EAAA,OAAO,MAAA,CAAO,QAAA,CAAS,KAAK,CAAA,GAAI,KAAA,GAAQ,MAAA;AAC1C;AAQO,SAAS,cAAc,OAAA,EAG5B;AACA,EAAA,OAAO;AAAA,IACL,KAAA,EAAO,aAAA,CAAc,OAAA,EAAS,mBAAmB,CAAA;AAAA,IACjD,SAAA,EAAW,aAAA,CAAc,OAAA,EAAS,uBAAuB;AAAA,GAC3D;AACF;AAEA,IAAM,kBAAA,GAAqB,CAAC,cAAA,EAAgB,aAAA,EAAe,cAAc,kBAAkB,CAAA;AAGpF,SAAS,aAAa,OAAA,EAAkD;AAC7E,EAAA,IAAI,CAAC,SAAS,OAAO,MAAA;AACrB,EAAA,KAAA,MAAW,QAAQ,kBAAA,EAAoB;AACrC,IAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,GAAA,CAAI,IAAI,CAAA;AAC9B,IAAA,IAAI,OAAO,OAAO,KAAA;AAAA,EACpB;AACA,EAAA,OAAO,MAAA;AACT;AAGA,IAAM,aAAA,GAAkE;AAAA,EACtE,gBAAA,EAAkB,kBAAA;AAAA,EAClB,mBAAA,EAAqB,iBAAA;AAAA,EACrB,YAAA,EAAc,YAAA;AAAA,EACd,eAAA,EAAiB,YAAA;AAAA,EACjB,eAAA,EAAiB,YAAA;AAAA,EACjB,6BAAA,EAA+B,YAAA;AAAA;AAAA;AAAA,EAG/B,qBAAA,EAAuB,YAAA;AAAA,EACvB,iBAAA,EAAmB,YAAA;AAAA,EACnB,2BAAA,EAA6B,YAAA;AAAA,EAC7B,aAAA,EAAe,iBAAA;AAAA,EACf,gBAAA,EAAkB,gBAAA;AAAA;AAAA,EAElB,SAAA,EAAW,gBAAA;AAAA,EACX,qBAAA,EAAuB;AACzB,CAAA;AAGA,SAAS,cAAc,MAAA,EAAkD;AACvE,EAAA,IAAI,MAAA,KAAW,KAAK,OAAO,YAAA;AAC3B,EAAA,IAAI,MAAA,KAAW,KAAK,OAAO,iBAAA;AAC3B,EAAA,IAAI,MAAA,KAAW,KAAK,OAAO,gBAAA;AAC3B,EAAA,IAAI,MAAA,KAAW,KAAK,OAAO,gBAAA;AAC3B,EAAA,IAAI,MAAA,KAAW,KAAK,OAAO,kBAAA;AAC3B,EAAA,IAAI,MAAA,KAAW,KAAK,OAAO,iBAAA;AAC3B,EAAA,IAAI,MAAA,IAAU,KAAK,OAAO,cAAA;AAC1B,EAAA,OAAO,WAAA;AACT;AAUA,SAAS,YAAY,IAAA,EAAwB;AAC3C,EAAA,IAAI,CAAC,QAAA,CAAS,IAAI,CAAA,IAAK,IAAA,CAAK,IAAA,KAAS,YAAA,IAAgB,CAAC,QAAA,CAAS,IAAA,CAAK,KAAK,CAAA,EAAG,OAAO,IAAA;AAEnF,EAAA,OAAO,EAAE,GAAG,IAAA,EAAM,OAAO,UAAA,CAAW,IAAA,CAAK,KAAK,CAAA,EAAE;AAClD;AAoBO,SAAS,eAAe,OAAA,EAAoC;AACjE,EAAA,MAAM,SAAS,cAAA,CAAe,OAAA,CAAQ,MAAM,OAAA,CAAQ,MAAA,EAAQ,QAAQ,UAAU,CAAA;AAC9E,EAAA,MAAM,SAAA,GAAY,aAAA,CAAc,OAAA,CAAQ,OAAO,CAAA;AAE/C,EAAA,MAAM,IAAA,GAAO;AAAA,IACX,WAAW,SAAA,CAAU,KAAA;AAAA,IACrB,oBAAoB,SAAA,CAAU,SAAA;AAAA,IAC9B,QAAQ,OAAA,CAAQ,MAAA;AAAA,IAChB,MAAM,MAAA,CAAO,IAAA;AAAA,IACb,SAAS,MAAA,CAAO,OAAA;AAAA,IAChB,QAAQ,MAAA,CAAO,MAAA;AAAA,IACf,OAAO,MAAA,CAAO,KAAA;AAAA,IACd,aAAa,MAAA,CAAO,WAAA;AAAA,IACpB,SAAA,EAAW,YAAA,CAAa,OAAA,CAAQ,OAAO,CAAA;AAAA,IACvC,QAAQ,OAAA,CAAQ,MAAA;AAAA,IAChB,MAAM,OAAA,CAAQ,IAAA;AAAA,IACd,GAAA,EAAK,WAAA,CAAY,OAAA,CAAQ,IAAI,CAAA;AAAA,IAC7B,UAAU,OAAA,CAAQ,QAAA;AAAA,IAClB,YAAY,eAAA,CAAgB,OAAA,CAAQ,OAAA,EAAS,GAAA,CAAI,aAAa,CAAC;AAAA,GACjE;AAEA,EAAA,IAAI,MAAA,CAAO,SAAS,6BAAA,EAA+B;AACjD,IAAA,OAAO,IAAI,0BAA0B,EAAE,GAAG,MAAM,MAAA,EAAQ,MAAA,CAAO,QAAQ,CAAA;AAAA,EACzE;AAEA,EAAA,MAAM,OAAO,aAAA,CAAc,MAAA,CAAO,IAAI,CAAA,IAAK,aAAA,CAAc,QAAQ,MAAM,CAAA;AACvE,EAAA,OAAO,IAAI,KAAK,IAAa,CAAA;AAC/B;;;AC3OA,SAAS,MAAM,EAAA,EAA2B;AACxC,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,YAAY,UAAA,CAAW,OAAA,EAAS,EAAE,CAAC,CAAA;AACzD;AAGA,IAAM,UAAA,uBAAsC,GAAA,EAAY;AASxD,SAAS,SAAA,CAAU,OAAA,EAAkB,IAAA,EAAc,KAAA,EAAqB;AACtE,EAAA,IAAI;AACF,IAAA,OAAA,CAAQ,GAAA,CAAI,MAAM,KAAK,CAAA;AAAA,EACzB,CAAA,CAAA,MAAQ;AACN,IAAA,MAAM,IAAI,cAAA;AAAA,MACR,2GAAsB,IAAI,CAAA,6iBAAA;AAAA,KAE5B;AAAA,EACF;AACF;AAGA,SAAS,UAAU,IAAA,EAAiC;AAClD,EAAA,IAAI,OAAO,IAAA,KAAS,QAAA,IAAY,SAAS,IAAA,EAAM,OAAO,OAAO,IAAA,KAAS,QAAA;AACtE,EAAA,OACG,OAAO,aAAa,WAAA,IAAe,IAAA,YAAgB,YACpD,MAAA,CAAO,IAAI,CAAA,IACV,OAAO,eAAA,KAAoB,WAAA,IAAe,gBAAgB,eAAA,IAC1D,OAAO,mBAAmB,WAAA,IAAe,IAAA,YAAgB,kBAC1D,IAAA,YAAgB,WAAA,IAChB,WAAA,CAAY,MAAA,CAAO,IAAI,CAAA;AAE3B;AAQA,eAAe,SAAS,QAAA,EAAsC;AAC5D,EAAA,IAAI,SAAS,MAAA,KAAW,GAAA,IAAO,QAAA,CAAS,MAAA,KAAW,KAAK,OAAO,MAAA;AAC/D,EAAA,IAAI,SAAS,OAAA,CAAQ,GAAA,CAAI,gBAAgB,CAAA,KAAM,KAAK,OAAO,MAAA;AAE3D,EAAA,MAAM,WAAA,GAAc,QAAA,CAAS,OAAA,CAAQ,GAAA,CAAI,cAAc,CAAA,IAAK,EAAA;AAE5D,EAAA,IAAI,WAAA,CAAY,QAAA,CAAS,MAAM,CAAA,EAAG;AAChC,IAAA,MAAMC,KAAAA,GAAO,MAAM,QAAA,CAAS,IAAA,EAAK;AACjC,IAAA,IAAIA,KAAAA,KAAS,IAAI,OAAO,MAAA;AACxB,IAAA,IAAI;AACF,MAAA,OAAO,IAAA,CAAK,MAAMA,KAAI,CAAA;AAAA,IACxB,CAAA,CAAA,MAAQ;AAGN,MAAA,OAAOA,KAAAA;AAAA,IACT;AAAA,EACF;AAEA,EAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,IAAA,EAAK;AACjC,EAAA,OAAO,IAAA,KAAS,KAAK,MAAA,GAAY,IAAA;AACnC;AAgBA,SAAS,iBAAA,CAAkB,YAAqC,OAAA,EAA8B;AAC5F,EAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,EAAA,IAAI,QAAA,GAAW,KAAA;AAEf,EAAA,MAAM,WAAA,GAAc,MAAM,UAAA,CAAW,KAAA,CAAM,YAAY,MAAM,CAAA;AAE7D,EAAA,IAAI,UAAA,EAAY;AACd,IAAA,IAAI,UAAA,CAAW,OAAA,EAAS,UAAA,CAAW,KAAA,CAAM,WAAW,MAAM,CAAA;AAAA,oBAC1C,gBAAA,CAAiB,OAAA,EAAS,aAAa,EAAE,IAAA,EAAM,MAAM,CAAA;AAAA,EACvE;AAEA,EAAA,MAAM,KAAA,GACJ,OAAA,GAAU,CAAA,GACN,UAAA,CAAW,MAAM;AACf,IAAA,QAAA,GAAW,IAAA;AACX,IAAA,UAAA,CAAW,KAAA,EAAM;AAAA,EACnB,CAAA,EAAG,OAAO,CAAA,GACV,MAAA;AAEN,EAAA,OAAO;AAAA,IACL,QAAQ,UAAA,CAAW,MAAA;AAAA,IACnB,UAAU,MAAM,QAAA;AAAA,IAChB,SAAS,MAAM;AACb,MAAA,IAAI,KAAA,KAAU,MAAA,EAAW,YAAA,CAAa,KAAK,CAAA;AAC3C,MAAA,UAAA,EAAY,mBAAA,CAAoB,SAAS,WAAW,CAAA;AAAA,IACtD;AAAA,GACF;AACF;AASO,IAAM,aAAN,MAAiB;AAAA,EACb,OAAA;AAAA,EACT,cAAA;AAAA,EACA,QAAA;AAAA,EAEA,WAAA,CAAY,MAAA,EAAwB,aAAA,GAAmC,EAAC,EAAG;AACzE,IAAA,IAAA,CAAK,OAAA,GAAU,MAAA;AACf,IAAA,IAAA,CAAK,cAAA,GAAiB,aAAA;AAAA,EACxB;AAAA;AAAA,EAGA,IAAI,OAAA,GAAkB;AACpB,IAAA,OAAO,KAAK,OAAA,CAAQ,OAAA;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,IAAI,gBAAA,GAAwC;AAC1C,IAAA,OAAO,IAAA,CAAK,UAAU,UAAA,IAAc,UAAA;AAAA,EACtC;AAAA;AAAA,EAGA,WAAW,OAAA,EAA+B;AACxC,IAAA,IAAA,CAAK,QAAA,GAAW,OAAA;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,iBAAiB,aAAA,EAAwC;AACvD,IAAA,IAAA,CAAK,iBAAiB,EAAE,GAAG,IAAA,CAAK,cAAA,EAAgB,GAAG,aAAA,EAAc;AAAA,EACnE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,QAAqB,OAAA,EAAwC;AACjE,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,YAAA,CAAgB,OAAO,CAAA;AAK/C,IAAA,IAAI,CAAC,IAAA,CAAK,cAAA,CAAe,YAAY,OAAA,CAAQ,SAAA,SAAkB,IAAA,EAAK;AAEpE,IAAA,OAAO,IAAA,CAAK,cAAA,CAAe,QAAA,CAAS,IAAI,CAAA;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,aAAgB,OAAA,EAAwC;AACtD,IAAA,MAAM,UAAU,IAAA,CAAK,QAAA;AACrB,IAAA,IAAI,CAAC,WAAW,OAAA,CAAQ,IAAA,KAAS,GAAG,OAAO,IAAA,CAAK,aAAgB,OAAO,CAAA;AAEvE,IAAA,OAAO,OAAA,CAAQ,IAAI,OAAA,EAAS,CAAC,YAAY,IAAA,CAAK,YAAA,CAAgB,OAAO,CAAC,CAAA;AAAA,EACxE;AAAA,EAEA,MAAM,aAAgB,OAAA,EAAwC;AAC5D,IAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,MAAA,CAAO,WAAA,EAAY;AAE1C,IAAA,KAAA,IAAS,OAAA,GAAU,KAAK,OAAA,EAAA,EAAW;AACjC,MAAA,IAAI;AACF,QAAA,OAAO,MAAM,IAAA,CAAK,QAAA,CAAY,OAAA,EAAS,OAAO,CAAA;AAAA,MAChD,SAAS,KAAA,EAAO;AACd,QAAA,MAAM,QAAQ,IAAA,CAAK,cAAA,CAAe,cAAA,GAAiB,KAAA,EAAO,SAAS,MAAM,CAAA;AACzE,QAAA,IAAI,KAAA,KAAU,QAAW,MAAM,KAAA;AAE/B,QAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,KAAA,CAAM,OAAA,GAAU;AAAA,UACjC,MAAA;AAAA,UACA,MAAM,OAAA,CAAQ,IAAA;AAAA,UACd,GAAA,EAAK,IAAA,CAAK,SAAA,CAAU,OAAO,CAAA;AAAA,UAC3B,OAAA,EAAS,IAAI,OAAA,EAAQ;AAAA,UACrB,OAAA;AAAA,UACA,KAAA;AAAA,UACA;AAAA,SACD,CAAA;AAED,QAAA,IAAA,CAAK,QAAQ,MAAA,EAAQ,KAAA;AAAA,UACnB,CAAA,qCAAA,EAAU,MAAM,CAAA,CAAA,EAAI,OAAA,CAAQ,IAAI,CAAA,6CAAA,EAAa,OAAA,GAAU,CAAC,CAAA,gCAAA,EAAU,KAAK,CAAA,aAAA;AAAA,SACzE;AAEA,QAAA,MAAM,MAAM,KAAK,CAAA;AAAA,MACnB;AAAA,IACF;AAAA,EACF;AAAA,EAEA,UAAU,OAAA,EAAoC;AAC5C,IAAA,OAAO,OAAA,CAAQ,KAAK,OAAA,CAAQ,OAAA,EAAS,QAAQ,IAAI,CAAA,GAAI,UAAA,CAAW,OAAA,CAAQ,KAAK,CAAA;AAAA,EAC/E;AAAA,EAEA,MAAM,aAAA,CAAc,OAAA,EAA4B,GAAA,EAA+B;AAC7E,IAAA,MAAM,OAAA,GAAU,IAAI,OAAA,EAAQ;AAE5B,IAAA,OAAA,CAAQ,GAAA,CAAI,UAAU,kBAAkB,CAAA;AAGxC,IAAA,OAAA,CAAQ,GAAA,CAAI,oBAAoB,gBAAgB,CAAA;AAGhD,IAAA,IAAI,IAAA,CAAK,QAAQ,SAAA,EAAW,SAAA,CAAU,SAAS,YAAA,EAAc,IAAA,CAAK,QAAQ,SAAS,CAAA;AAEnF,IAAA,IAAI,IAAA,CAAK,eAAe,WAAA,EAAa;AACnC,MAAA,SAAA,CAAU,SAAS,aAAA,EAAe,MAAM,IAAA,CAAK,cAAA,CAAe,aAAa,CAAA;AAAA,IAC3E;AAGA,IAAA,KAAA,MAAW,CAAC,MAAM,KAAK,CAAA,IAAK,OAAO,OAAA,CAAQ,IAAA,CAAK,QAAQ,OAAO,CAAA;AAC7D,MAAA,SAAA,CAAU,OAAA,EAAS,MAAM,KAAK,CAAA;AAEhC,IAAA,IAAI,CAAC,OAAA,CAAQ,QAAA,IAAY,IAAA,CAAK,eAAe,cAAA,EAAgB;AAC3D,MAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,cAAA,CAAe,cAAA,EAAe;AACtD,MAAA,KAAA,MAAW,CAAC,IAAA,EAAM,KAAK,CAAA,IAAK,MAAA,CAAO,OAAA,CAAQ,IAAI,CAAA,EAAG,SAAA,CAAU,OAAA,EAAS,IAAA,EAAM,KAAK,CAAA;AAAA,IAClF;AAEA,IAAA,IAAI,IAAA,CAAK,OAAA,CAAQ,YAAA,IAAgB,IAAA,CAAK,eAAe,eAAA,EAAiB;AACpE,MAAA,MAAM,MAAA,GAAS,IAAA,CAAK,cAAA,CAAe,eAAA,CAAgB,GAAG,CAAA;AACtD,MAAA,IAAI,MAAA,EAAQ,SAAA,CAAU,OAAA,EAAS,QAAA,EAAU,MAAM,CAAA;AAAA,IACjD;AAEA,IAAA,KAAA,MAAW,CAAC,IAAA,EAAM,KAAK,CAAA,IAAK,MAAA,CAAO,QAAQ,OAAA,CAAQ,OAAA,IAAW,EAAE,CAAA,EAAG;AACjE,MAAA,SAAA,CAAU,OAAA,EAAS,MAAM,KAAK,CAAA;AAAA,IAChC;AAEA,IAAA,OAAO,OAAA;AAAA,EACT;AAAA,EAEA,MAAM,QAAA,CAAY,OAAA,EAA4B,OAAA,EAA6B;AACzE,IAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,MAAA,CAAO,WAAA,EAAY;AAC1C,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,SAAA,CAAU,OAAO,CAAA;AAClC,IAAA,MAAM,OAAA,GAAU,MAAM,IAAA,CAAK,aAAA,CAAc,SAAS,GAAG,CAAA;AAErD,IAAA,IAAI,IAAA;AACJ,IAAA,IAAI,OAAA,CAAQ,IAAA,KAAS,MAAA,IAAa,OAAA,CAAQ,SAAS,IAAA,EAAM;AACvD,MAAA,IAAI,SAAA,CAAU,OAAA,CAAQ,IAAI,CAAA,EAAG;AAE3B,QAAA,IAAA,GAAO,OAAA,CAAQ,IAAA;AAAA,MACjB,CAAA,MAAO;AACL,QAAA,IAAA,GAAO,IAAA,CAAK,SAAA,CAAU,OAAA,CAAQ,IAAI,CAAA;AAClC,QAAA,IAAI,CAAC,QAAQ,GAAA,CAAI,cAAc,GAAG,OAAA,CAAQ,GAAA,CAAI,gBAAgB,kBAAkB,CAAA;AAAA,MAClF;AAAA,IACF;AAEA,IAAA,MAAM,OAAA,GAAU,EAAE,MAAA,EAAQ,IAAA,EAAM,QAAQ,IAAA,EAAM,GAAA,EAAK,SAAS,OAAA,EAAQ;AACpE,IAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,KAAA,CAAM,SAAA,GAAY,OAAO,CAAA;AAE5C,IAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,OAAA,IAAW,IAAA,CAAK,OAAA,CAAQ,OAAA;AAChD,IAAA,MAAM,KAAA,GAAQ,iBAAA,CAAkB,OAAA,CAAQ,MAAA,EAAQ,OAAO,CAAA;AACvD,IAAA,MAAM,SAAA,GAAY,KAAK,GAAA,EAAI;AAE3B,IAAA,IAAA,CAAK,OAAA,CAAQ,QAAQ,KAAA,CAAM,CAAA,OAAA,EAAK,MAAM,CAAA,CAAA,EAAI,OAAA,CAAQ,IAAI,CAAA,CAAA,EAAI;AAAA,MACxD,OAAA,EAAS,cAAc,OAAO,CAAA;AAAA,MAC9B,IAAA,EAAM,UAAA,CAAW,OAAA,CAAQ,IAAI;AAAA,KAC9B,CAAA;AAED,IAAA,IAAI,QAAA;AACJ,IAAA,IAAI;AACF,MAAA,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,KAAA,CAAM,GAAA,EAAK;AAAA,QACvC,MAAA;AAAA,QACA,OAAA;AAAA,QACA,QAAQ,KAAA,CAAM,MAAA;AAAA,QACd,GAAI,IAAA,KAAS,KAAA,CAAA,GAAY,EAAE,IAAA,KAAS,EAAC;AAAA,QACrC,GAAI,KAAK,OAAA,CAAQ,eAAA,GAAkB,EAAE,WAAA,EAAa,SAAA,KAAuB;AAAC,OAC3E,CAAA;AAAA,IACH,SAAS,KAAA,EAAO;AACd,MAAA,MAAMC,SAAAA,GAAW,IAAA,CAAK,GAAA,EAAI,GAAI,SAAA;AAC9B,MAAA,MAAM,UAAU,IAAA,CAAK,iBAAA,CAAkB,OAAO,KAAA,EAAO,OAAA,EAAS,QAAQ,OAAO,CAAA;AAE7E,MAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,KAAA,CAAM,OAAA,GAAU,EAAE,GAAG,OAAA,EAAS,QAAA,EAAAA,SAAAA,EAAU,KAAA,EAAO,OAAA,EAAS,CAAA;AAC3E,MAAA,IAAA,CAAK,OAAA,CAAQ,MAAA,EAAQ,IAAA,CAAK,CAAA,KAAA,EAAK,MAAM,CAAA,CAAA,EAAI,OAAA,CAAQ,IAAI,CAAA,EAAA,EAAKA,SAAQ,CAAA,gBAAA,EAAS,OAAA,CAAQ,OAAO,CAAA,CAAE,CAAA;AAE5F,MAAA,MAAM,OAAA;AAAA,IACR,CAAA,SAAE;AACA,MAAA,KAAA,CAAM,OAAA,EAAQ;AAAA,IAChB;AAEA,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,GAAA,EAAI,GAAI,SAAA;AAE9B,IAAA,IAAI,IAAA,CAAK,eAAe,WAAA,EAAa;AACnC,MAAA,MAAM,EAAE,KAAA,EAAO,SAAA,EAAU,GAAI,aAAA,CAAc,SAAS,OAAO,CAAA;AAC3D,MAAA,IAAA,CAAK,cAAA,CAAe,WAAA,CAAY,KAAA,EAAO,SAAS,CAAA;AAAA,IAClD;AAEA,IAAA,IAAI,KAAK,OAAA,CAAQ,YAAA,OAAmB,cAAA,CAAe,WAAA,GAAc,KAAK,QAAQ,CAAA;AAE9E,IAAA,MAAM,OAAA,GAAU,MAAM,QAAA,CAAS,QAAQ,CAAA;AAEvC,IAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAGhB,MAAA,IACE,QAAA,CAAS,MAAA,KAAW,GAAA,IACpB,CAAC,OAAA,CAAQ,eAAA,IACT,IAAA,CAAK,OAAA,CAAQ,WAAA,IACb,IAAA,CAAK,cAAA,CAAe,cAAA,EACpB;AACA,QAAA,MAAM,SAAA,GAAY,MAAM,IAAA,CAAK,cAAA,CAAe,cAAA,EAAe;AAC3D,QAAA,IAAI,SAAA,EAAW;AACb,UAAA,IAAA,CAAK,OAAA,CAAQ,QAAQ,KAAA,CAAM,CAAA,kIAAA,EAA4B,MAAM,CAAA,CAAA,EAAI,OAAA,CAAQ,IAAI,CAAA,CAAE,CAAA;AAC/E,UAAA,OAAO,IAAA,CAAK,SAAY,EAAE,GAAG,SAAS,eAAA,EAAiB,IAAA,IAAQ,OAAO,CAAA;AAAA,QACxE;AAAA,MACF;AAEA,MAAA,MAAM,QAAQ,cAAA,CAAe;AAAA,QAC3B,MAAA;AAAA,QACA,MAAM,OAAA,CAAQ,IAAA;AAAA,QACd,QAAQ,QAAA,CAAS,MAAA;AAAA,QACjB,YAAY,QAAA,CAAS,UAAA;AAAA,QACrB,SAAS,QAAA,CAAS,OAAA;AAAA,QAClB,QAAA;AAAA,QACA,IAAA,EAAM;AAAA,OACP,CAAA;AAED,MAAA,MAAM,IAAA,CAAK,QAAQ,KAAA,CAAM,OAAA,GAAU,EAAE,GAAG,OAAA,EAAS,QAAA,EAAU,KAAA,EAAO,CAAA;AAClE,MAAA,IAAA,CAAK,QAAQ,MAAA,EAAQ,IAAA;AAAA,QACnB,CAAA,OAAA,EAAK,QAAA,CAAS,MAAM,CAAA,CAAA,EAAI,MAAM,CAAA,CAAA,EAAI,OAAA,CAAQ,IAAI,CAAA,EAAA,EAAK,QAAQ,CAAA,gBAAA,EAAS,KAAA,CAAM,OAAO,CAAA;AAAA,OACnF;AAEA,MAAA,MAAM,KAAA;AAAA,IACR;AAEA,IAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,KAAA,CAAM,UAAA,GAAa;AAAA,MACpC,GAAG,OAAA;AAAA,MACH,QAAQ,QAAA,CAAS,MAAA;AAAA,MACjB,QAAA;AAAA,MACA;AAAA,KACD,CAAA;AAED,IAAA,IAAA,CAAK,OAAA,CAAQ,MAAA,EAAQ,KAAA,CAAM,CAAA,OAAA,EAAK,QAAA,CAAS,MAAM,CAAA,CAAA,EAAI,MAAM,CAAA,CAAA,EAAI,OAAA,CAAQ,IAAI,CAAA,EAAA,EAAK,QAAQ,CAAA,cAAA,CAAM,CAAA;AAE5F,IAAA,OAAQ,OAAA,CAAQ,GAAA,GAAM,OAAA,GAAU,UAAA,CAAW,OAAO,CAAA;AAAA,EACpD;AAAA;AAAA,EAGA,iBAAA,CACE,KAAA,EACA,KAAA,EACA,OAAA,EACA,QACA,OAAA,EACmD;AACnD,IAAA,MAAM,OAAA,GAAU,KAAA,YAAiB,KAAA,IAAS,KAAA,CAAM,IAAA,KAAS,YAAA;AAEzD,IAAA,IAAI,OAAA,IAAW,KAAA,CAAM,QAAA,EAAS,EAAG;AAC/B,MAAA,OAAO,IAAI,gBAAgB,EAAE,OAAA,EAAS,QAAQ,IAAA,EAAM,OAAA,CAAQ,MAAM,CAAA;AAAA,IACpE;AAEA,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,OAAO,IAAI,aAAA,CAAc,CAAA,qCAAA,EAAU,MAAM,CAAA,CAAA,EAAI,OAAA,CAAQ,IAAI,CAAA,2CAAA,CAAU,CAAA;AAAA,IACrE;AAEA,IAAA,OAAO,IAAI,eAAA;AAAA,MACT,CAAA,+GAAA,EAAwB,MAAM,CAAA,CAAA,EAAI,OAAA,CAAQ,IAAI,CAAA,EAAA,EAAK,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,MAAA,CAAO,KAAK,CAAC,CAAA,CAAA;AAAA,MACzG,EAAE,MAAA,EAAQ,IAAA,EAAM,OAAA,CAAQ,IAAA,EAAM,OAAO,KAAA;AAAM,KAC7C;AAAA,EACF;AACF,CAAA;;;ACzWA,IAAM,OAAA,uBAAmC,GAAA,EAAY;AAQrD,IAAM,oBAAA,uBAAgD,GAAA,CAAI;AAAA,EACxD,QAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA;AAAA,EACA,MAAA;AAAA,EACA,OAAA;AAAA,EACA,MAAA;AAAA,EACA,UAAA;AAAA,EACA,iBAAA;AAAA,EACA,WAAA;AAAA,EACA;AACF,CAAC,CAAA;AAQM,IAAM,iBAAN,MAAqB;AAAA,EACjB,gBAA+B,EAAC;AAAA,EAChC,WAAA,uBAAkB,GAAA,EAAY;AAAA,EAC9B,MAAA,uBAAa,GAAA,EAAY;AAAA;AAAA,EAGlC,IAAI,IAAA,GAAe;AACjB,IAAA,OAAO,KAAK,aAAA,CAAc,MAAA;AAAA,EAC5B;AAAA;AAAA,EAGA,IAAI,UAAA,GAAkC;AACpC,IAAA,OAAO,IAAA,CAAK,WAAA,CAAY,IAAA,KAAS,CAAA,GAAI,UAAU,IAAA,CAAK,WAAA;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,GAAA,CAAI,QAAmB,OAAA,EAA2C;AAChE,IAAA,IAAI,OAAO,MAAA,EAAQ,OAAA,KAAY,UAAA,EAAY;AACzC,MAAA,MAAM,IAAI,eAAe,iNAAiD,CAAA;AAAA,IAC5E;AAEA,IAAA,MAAM,OAAO,MAAA,CAAO,IAAA;AACpB,IAAA,IAAI,OAAO,IAAA,KAAS,QAAA,IAAY,IAAA,CAAK,IAAA,OAAW,EAAA,EAAI;AAClD,MAAA,MAAM,IAAI,eAAe,qLAAoC,CAAA;AAAA,IAC/D;AAIA,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,IAAI,CAAA,EAAG;AACzB,MAAA,MAAM,IAAI,cAAA,CAAe,CAAA,yCAAA,EAAW,IAAI,CAAA,8EAAA,CAAiB,CAAA;AAAA,IAC3D;AAEA,IAAA,MAAM,IAAA,GAAO,MAAA,CAAO,UAAA,IAAc,EAAC;AACnC,IAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,MAAA,IAAI,OAAO,GAAA,KAAQ,QAAA,IAAY,GAAA,CAAI,IAAA,OAAW,EAAA,EAAI;AAChD,QAAA,MAAM,IAAI,cAAA,CAAe,CAAA,yCAAA,EAAW,IAAI,CAAA,gIAAA,CAA2B,CAAA;AAAA,MACrE;AACA,MAAA,IAAI,oBAAA,CAAqB,GAAA,CAAI,GAAG,CAAA,EAAG;AACjC,QAAA,MAAM,IAAI,cAAA;AAAA,UACR,CAAA,yCAAA,EAAW,IAAI,CAAA,6EAAA,EAAmB,GAAG,CAAA,kOAAA,EACjB,CAAC,GAAG,oBAAoB,CAAA,CAAE,IAAA,CAAK,IAAI,CAAC,CAAA;AAAA,SAC1D;AAAA,MACF;AAAA,IACF;AAIA,IAAA,MAAM,MAAA,GAAS,KAAK,aAAA,CAAc,MAAA;AAClC,IAAA,IAAI;AACF,MAAA,MAAA,CAAO,OAAA,CAAQ;AAAA,QACb,GAAG,OAAA;AAAA,QACH,GAAA,EAAK,CAAC,WAAA,KAAgB;AACpB,UAAA,IAAI,OAAO,gBAAgB,UAAA,EAAY;AACrC,YAAA,MAAM,IAAI,cAAA,CAAe,CAAA,yCAAA,EAAW,IAAI,CAAA,oHAAA,CAA8B,CAAA;AAAA,UACxE;AACA,UAAA,IAAA,CAAK,aAAA,CAAc,KAAK,WAAW,CAAA;AAAA,QACrC;AAAA,OACD,CAAA;AAAA,IACH,SAAS,KAAA,EAAO;AACd,MAAA,IAAA,CAAK,cAAc,MAAA,GAAS,MAAA;AAC5B,MAAA,MAAM,KAAA;AAAA,IACR;AAEA,IAAA,IAAA,CAAK,MAAA,CAAO,IAAI,IAAI,CAAA;AACpB,IAAA,KAAA,MAAW,GAAA,IAAO,IAAA,EAAM,IAAA,CAAK,WAAA,CAAY,IAAI,GAAG,CAAA;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,GAAA,CACE,SACA,OAAA,EACkB;AAClB,IAAA,MAAM,KAAA,GAAQ,KAAK,aAAA,CAAc,WAAA;AAAA,MAC/B,CAAC,IAAA,EAAM,WAAA,KAAgB,CAAC,OAAA,KAAY,WAAA,CAAY,SAAS,IAAI,CAAA;AAAA,MAC7D;AAAA,KACF;AAEA,IAAA,OAAO,MAAM,OAAO,CAAA;AAAA,EACtB;AACF,CAAA;;;ACpLO,IAAM,eAAN,MAAmB;AAAA,EACf,YAAA;AAAA;AAAA,EAEA,OAAA;AAAA,EAEA,WAAyB,EAAC;AAAA,EACnC,OAAA,GAAU,CAAA;AAAA;AAAA,EAEV,SAAA,GAAY,CAAA;AAAA,EACZ,MAAA;AAAA,EAEA,YAAY,OAAA,EAAmC;AAC7C,IAAA,IAAA,CAAK,eAAe,OAAA,CAAQ,WAAA;AAC5B,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA,CAAQ,GAAA,GAAM,GAAA,GAAO,QAAQ,GAAA,GAAM,CAAA;AAAA,EACpD;AAAA;AAAA,EAGA,IAAI,MAAA,GAAiB;AACnB,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,EACd;AAAA;AAAA,EAGA,IAAI,OAAA,GAAkB;AACpB,IAAA,OAAO,KAAK,QAAA,CAAS,MAAA;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,SAAY,IAAA,EAAoC;AAC9C,IAAA,OAAO,IAAI,OAAA,CAAW,CAAC,OAAA,EAAS,MAAA,KAAW;AACzC,MAAA,MAAM,MAAM,MAAM;AAChB,QAAA,IAAA,CAAK,OAAA,IAAW,CAAA;AAEhB,QAAA,IAAA,GACG,IAAA,CAAK,OAAA,EAAS,MAAM,CAAA,CACpB,QAAQ,MAAM;AACb,UAAA,IAAA,CAAK,OAAA,IAAW,CAAA;AAChB,UAAA,IAAA,CAAK,MAAA,EAAO;AAAA,QACd,CAAC,CAAA;AAAA,MACL,CAAA;AAEA,MAAA,IAAA,CAAK,QAAA,CAAS,IAAA,CAAK,EAAE,GAAA,EAAK,CAAA;AAC1B,MAAA,IAAA,CAAK,MAAA,EAAO;AAAA,IACd,CAAC,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,EAAA,EAAkB;AACtB,IAAA,IAAI,MAAM,CAAA,EAAG;AACb,IAAA,IAAA,CAAK,SAAA,GAAY,KAAK,GAAA,CAAI,IAAA,CAAK,WAAW,IAAA,CAAK,GAAA,KAAQ,EAAE,CAAA;AAAA,EAC3D;AAAA;AAAA,EAGA,MAAA,GAAe;AACb,IAAA,IAAI,IAAA,CAAK,QAAA,CAAS,MAAA,KAAW,CAAA,EAAG;AAChC,IAAA,IAAI,IAAA,CAAK,OAAA,IAAW,IAAA,CAAK,YAAA,EAAc;AAEvC,IAAA,IAAI,IAAA,CAAK,WAAW,MAAA,EAAW;AAE/B,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AAErB,IAAA,IAAI,IAAA,CAAK,YAAY,GAAA,EAAK;AACxB,MAAA,IAAA,CAAK,MAAA,GAAS,WAAW,MAAM;AAC7B,QAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,QAAA,IAAA,CAAK,MAAA,EAAO;AAAA,MACd,CAAA,EAAG,IAAA,CAAK,SAAA,GAAY,GAAG,CAAA;AACvB,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,QAAA,CAAS,KAAA,EAAM;AACjC,IAAA,IAAI,CAAC,IAAA,EAAM;AAEX,IAAA,IAAI,KAAK,OAAA,GAAU,CAAA,EAAG,IAAA,CAAK,SAAA,GAAY,MAAM,IAAA,CAAK,OAAA;AAElD,IAAA,IAAA,CAAK,GAAA,EAAI;AAGT,IAAA,IAAA,CAAK,MAAA,EAAO;AAAA,EACd;AACF,CAAA;;;ACzFA,IAAM,qCAAqB,IAAI,GAAA,CAAI,CAAC,KAAA,EAAO,MAAA,EAAQ,SAAS,CAAC,CAAA;AAS7D,SAAS,WAAA,CAAY,KAAA,EAAgB,MAAA,EAAgB,WAAA,EAA+B;AAElF,EAAA,IAAI,KAAA,YAAiB,eAAe,OAAO,KAAA;AAE3C,EAAA,MAAM,YAAA,GAAe,WAAA,IAAe,kBAAA,CAAmB,GAAA,CAAI,MAAM,CAAA;AAEjE,EAAA,IAAI,iBAAiB,WAAA,EAAa;AAChC,IAAA,IAAI,KAAA,CAAM,MAAA,KAAW,GAAA,EAAK,OAAO,IAAA;AACjC,IAAA,IAAI,KAAA,CAAM,MAAA,IAAU,GAAA,EAAK,OAAO,YAAA;AAChC,IAAA,OAAO,KAAA;AAAA,EACT;AAEA,EAAA,IAAI,KAAA,YAAiB,eAAA,IAAmB,KAAA,YAAiB,eAAA,EAAiB,OAAO,YAAA;AAEjF,EAAA,OAAO,KAAA;AACT;AAGA,SAAS,YAAA,CACP,OAAA,EACA,OAAA,EACA,MAAA,EACQ;AACR,EAAA,MAAM,WAAA,GAAc,OAAA,CAAQ,SAAA,GAAY,CAAA,KAAM,OAAA,GAAU,CAAA,CAAA;AACxD,EAAA,MAAM,MAAA,GAAS,IAAA,CAAK,GAAA,CAAI,WAAA,EAAa,QAAQ,QAAQ,CAAA;AACrD,EAAA,MAAM,SAAS,MAAA,GAAS,OAAA,CAAQ,MAAA,IAAU,MAAA,KAAW,CAAA,GAAI,CAAA,CAAA;AAEzD,EAAA,OAAO,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,KAAA,CAAM,MAAA,GAAS,MAAM,CAAC,CAAA;AAChD;AAmBO,SAAS,oBAAA,CACd,OAAA,EACA,MAAA,GAAuB,IAAA,CAAK,MAAA,EACZ;AAChB,EAAA,OAAO,CAAC,KAAA,EAAO,OAAA,EAAS,MAAA,KAAW;AACjC,IAAA,IAAI,OAAA,IAAW,OAAA,CAAQ,QAAA,EAAU,OAAO,MAAA;AAExC,IAAA,IAAI,QAAQ,WAAA,EAAa;AACvB,MAAA,OAAO,OAAA,CAAQ,YAAY,KAAA,EAAO,OAAO,IACrC,YAAA,CAAa,OAAA,EAAS,OAAA,EAAS,MAAM,CAAA,GACrC,MAAA;AAAA,IACN;AAEA,IAAA,IAAI,CAAC,WAAA,CAAY,KAAA,EAAO,QAAQ,OAAA,CAAQ,WAAW,GAAG,OAAO,MAAA;AAE7D,IAAA,IAAI,KAAA,YAAiB,WAAA,IAAe,KAAA,CAAM,UAAA,KAAe,MAAA,EAAW;AAClE,MAAA,OAAO,KAAA,CAAM,UAAA,GAAa,OAAA,CAAQ,QAAA,GAAW,SAAY,KAAA,CAAM,UAAA;AAAA,IACjE;AAEA,IAAA,OAAO,YAAA,CAAa,OAAA,EAAS,OAAA,EAAS,MAAM,CAAA;AAAA,EAC9C,CAAA;AACF;;;ACrFO,IAAM,yBAAA,GAAwE,OAAO,MAAA,CAAO;AAAA,EACjG,MAAM,gBAAA,CAAiB,YAAA;AAAA,EACvB,SAAS,gBAAA,CAAiB,WAAA;AAAA,EAC1B,cAAc,gBAAA,CAAiB,eAAA;AAAA,EAC/B,OAAO,gBAAA,CAAiB,YAAA;AAAA,EACxB,QAAQ,gBAAA,CAAiB,UAAA;AAAA,EACzB,SAAS,gBAAA,CAAiB;AAC5B,CAAC;AAED,IAAM,cAAc,IAAI,GAAA,CAAY,MAAA,CAAO,MAAA,CAAO,gBAAgB,CAAC,CAAA;AAgB5D,SAAS,0BAA0B,OAAA,EAAmC;AAC3E,EAAA,OAAO,yBAAA,CAA0B,OAAO,CAAA,IAAK,OAAA;AAC/C;AAOO,SAAS,wBAAwB,IAAA,EAAuB;AAC7D,EAAA,OAAO,WAAA,CAAY,GAAA,CAAI,yBAAA,CAA0B,IAAI,CAAC,CAAA;AACxD;;;AC9BA,SAAS,QAAQ,KAAA,EAAmC;AAClD,EAAA,IAAI,CAAC,QAAA,CAAS,KAAK,CAAA,EAAG,OAAO,MAAA;AAC7B,EAAA,MAAM,EAAA,GAAK,QAAA,CAAS,KAAA,CAAM,EAAE,CAAA;AAC5B,EAAA,IAAI,CAAC,IAAI,OAAO,MAAA;AAEhB,EAAA,OAAO;AAAA,IACL,EAAA;AAAA,IACA,QAAA,EAAU,QAAA,CAAS,KAAA,CAAM,QAAQ,CAAA,IAAK,EAAA;AAAA,IACtC,WAAA,EAAa,QAAA,CAAS,KAAA,CAAM,WAAW,CAAA,IAAK,EAAA;AAAA,IAC5C,MAAA,EAAQ,QAAA,CAAS,KAAA,CAAM,MAAM,CAAA,IAAK,EAAA;AAAA,IAClC,GAAI,OAAO,KAAA,CAAM,WAAA,KAAgB,SAAA,GAAY,EAAE,WAAA,EAAa,KAAA,CAAM,WAAA,EAAY,GAAI,EAAC;AAAA,IACnF,GAAI,OAAO,KAAA,CAAM,YAAA,KAAiB,SAAA,GAAY,EAAE,YAAA,EAAc,KAAA,CAAM,YAAA,EAAa,GAAI;AAAC,GACxF;AACF;AAGA,SAAS,WAAW,MAAA,EAA0C;AAC5D,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,MAAA,CAAO,MAAM,CAAA,EAAG;AAChC,IAAA,OAAO,MAAA,CAAO,OAAO,GAAA,CAAI,OAAO,EAAE,MAAA,CAAO,CAAC,KAAA,KAA0B,KAAA,KAAU,MAAS,CAAA;AAAA,EACzF;AAEA,EAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,MAAA,CAAO,KAAK,CAAA;AACnC,EAAA,OAAO,MAAA,GAAS,CAAC,MAAM,CAAA,GAAI,EAAC;AAC9B;AAuBO,SAAS,sBAAsB,KAAA,EAA8B;AAClE,EAAA,MAAM,MAAA,GAAS,QAAA,CAAS,KAAK,CAAA,GAAI,QAAQ,EAAC;AAG1C,EAAA,MAAM,UAAU,QAAA,CAAS,MAAA,CAAO,OAAO,CAAA,GAAI,OAAO,OAAA,GAAU,MAAA;AAE5D,EAAA,MAAM,OAAA,GAAU,SAAS,OAAA,CAAQ,IAAI,KAAK,QAAA,CAAS,MAAA,CAAO,IAAI,CAAA,IAAK,EAAA;AACnE,EAAA,MAAM,SAAA,GAAY,SAAS,OAAA,CAAQ,SAAS,KAAK,QAAA,CAAS,MAAA,CAAO,SAAS,CAAA,IAAK,EAAA;AAC/E,EAAA,MAAM,SAAS,QAAA,CAAS,OAAA,CAAQ,MAAM,CAAA,IAAK,QAAA,CAAS,OAAO,MAAM,CAAA;AAEjE,EAAA,MAAM,MAAA,GACJ,OAAO,OAAA,CAAQ,MAAA,KAAW,YACtB,OAAA,CAAQ,MAAA,GACR,OAAO,OAAA,CAAQ,IAAA,KAAS,SAAA,GACtB,OAAA,CAAQ,IAAA,GACR,QAAQ,MAAM,CAAA;AAUtB,EAAA,MAAM,SAAA,GAAY,QAAA,CAAS,OAAA,CAAQ,SAAS,CAAA;AAC5C,EAAA,MAAM,QAAA,GAAW,QAAA,CAAS,OAAA,CAAQ,QAAQ,CAAA;AAC1C,EAAA,MAAM,gBAAA,GAAmB,QAAQ,WAAA,KAAgB,SAAA;AACjD,EAAA,MAAM,QAAA,GAAW,QAAA,CAAS,OAAA,CAAQ,QAAQ,CAAA;AAE1C,EAAA,OAAO;AAAA,IACL,EAAA,EAAI,SAAS,OAAA,CAAQ,EAAE,KAAK,QAAA,CAAS,MAAA,CAAO,EAAE,CAAA,IAAK,EAAA;AAAA,IACnD,IAAA,EAAM,0BAA0B,OAAO,CAAA;AAAA,IACvC,OAAA;AAAA,IACA,QAAA,EACE,SAAS,OAAA,CAAQ,QAAQ,MAAM,gBAAA,GAAoB,SAAA,IAAa,WAAY,QAAA,CAAA,IAAa,IAAA;AAAA,IAC3F,gBACE,QAAA,CAAS,OAAA,CAAQ,cAAc,CAAA,KAAM,gBAAA,GAAoB,YAAY,IAAA,GAAQ,IAAA,CAAA;AAAA,IAC/E,MAAA;AAAA,IACA,MAAA,EAAQ,WAAW,OAAO,CAAA;AAAA,IAC1B,KAAA,EAAO,OAAO,OAAA,CAAQ,KAAA,KAAU,YAAY,OAAA,CAAQ,KAAA,GAAQ,CAAA,GAAI,OAAA,CAAQ,KAAA,GAAQ,CAAA;AAAA,IAChF,OAAA,EAAS,SAAS,OAAA,CAAQ,aAAa,KAAK,QAAA,CAAS,OAAA,CAAQ,OAAO,CAAA,IAAK,IAAA;AAAA,IACzE,GAAI,QAAA,GAAW,EAAE,QAAA,KAAa,EAAC;AAAA,IAC/B,SAAA;AAAA,IACA,SAAA,EAAW,QAAA,CAAS,OAAA,CAAQ,SAAS,KAAK,MAAA,IAAU,SAAA;AAAA,IACpD,GAAA,EAAK;AAAA,GACP;AACF;AAQO,SAAS,sBAAsB,IAAA,EAAkC;AACtE,EAAA,MAAM,MAAA,GAAS,QAAA,CAAS,IAAI,CAAA,GAAI,OAAO,EAAC;AAExC,EAAA,OAAO;AAAA,IACL,YAAA,EAAc,sBAAsB,IAAI,CAAA;AAAA,IACxC,aAAa,OAAO,MAAA,CAAO,WAAA,KAAgB,QAAA,GAAW,OAAO,WAAA,GAAc,MAAA;AAAA,IAC3E,KAAA,EAAO,OAAO,KAAA,KAAU;AAAA,GAC1B;AACF;AASO,SAAS,qBAAqB,IAAA,EAAmC;AACtE,EAAA,IAAI,CAAC,QAAA,CAAS,IAAI,CAAA,EAAG,OAAO,MAAA;AAE5B,EAAA,MAAM,UAAU,QAAA,CAAS,IAAA,CAAK,OAAO,CAAA,GAAI,KAAK,OAAA,GAAU,MAAA;AACxD,EAAA,IAAI,CAAC,SAAS,OAAO,MAAA;AAErB,EAAA,OAAO,OAAO,OAAA,CAAQ,KAAA,KAAU,QAAA,GAAW,QAAQ,KAAA,GAAQ,MAAA;AAC7D;;;AC9FO,IAAM,uBAAA,GAAN,cAAsC,KAAA,CAAM;AAAA,EACjD,WAAA,GAAc;AACZ,IAAA,KAAA,CAAM,kNAAwC,CAAA;AAC9C,IAAA,IAAA,CAAK,IAAA,GAAO,yBAAA;AAAA,EACd;AACF;;;AC/BO,IAAM,gBAAN,MAAiD;AAAA,EAC7C,IAAA,GAAO,MAAA;AAAA,EAEP,SAAA;AAAA,EACA,MAAA;AAAA,EAET,WAAA,CAAY,OAAA,GAAgC,EAAC,EAAG;AAC9C,IAAA,IAAA,CAAK,SAAA,GAAY,QAAQ,QAAA,IAAY,IAAA;AACrC,IAAA,IAAA,CAAK,MAAA,GAAS,QAAQ,KAAA,IAAS,EAAA;AAAA,EACjC;AAAA,EAEA,MAAM,QAAQ,OAAA,EAA0C;AACtD,IAAA,MAAM,IAAA,uBAAW,GAAA,EAAY;AAC7B,IAAA,IAAI,QAAA,GAAW,IAAA;AACf,IAAA,IAAI,eAAA;AAEJ,IAAA,OAAA,CAAQ,MAAA,EAAO;AAEf,IAAA,OAAO,CAAC,OAAA,CAAQ,MAAA,CAAO,OAAA,EAAS;AAC9B,MAAA,MAAM,KAAA,GAAQ,MAAM,OAAA,CAAQ,QAAA,EAAS;AACrC,MAAA,IAAI,CAAC,KAAA,EAAO,MAAM,IAAI,uBAAA,EAAwB;AAE9C,MAAA,MAAM,OAAA,GAAU,IAAI,OAAA,CAAQ;AAAA,QAC1B,MAAA,EAAQ,kBAAA;AAAA,QACR,aAAA,EAAe,UAAU,KAAK,CAAA;AAAA,OAC/B,CAAA;AAED,MAAA,MAAM,QAAA,GAAW,MAAM,OAAA,CAAQ,KAAA;AAAA,QAC7B,CAAA,EAAG,QAAQ,OAAA,CAAQ,OAAA,EAAS,qBAAqB,CAAC,CAAA,OAAA,EAAU,KAAK,MAAM,CAAA,SAAA,CAAA;AAAA,QACvE,EAAE,MAAA,EAAQ,KAAA,EAAO,OAAA,EAAS,MAAA,EAAQ,QAAQ,MAAA;AAAO,OACnD;AAEA,MAAA,IAAI,QAAA,CAAS,MAAA,KAAW,GAAA,EAAK,MAAM,IAAI,uBAAA,EAAwB;AAC/D,MAAA,IAAI,CAAC,SAAS,EAAA,EAAI,MAAM,IAAI,KAAA,CAAM,CAAA,4KAAA,EAAmC,QAAA,CAAS,MAAM,CAAA,CAAE,CAAA;AAEtF,MAAA,MAAM,IAAA,GAAgB,MAAM,QAAA,CAAS,IAAA,EAAK;AAC1C,MAAA,MAAM,OAAA,GACJ,OAAO,IAAA,KAAS,QAAA,IAAY,SAAS,IAAA,IAAQ,MAAA,IAAU,IAAA,GAClD,IAAA,CAA2B,IAAA,GAC5B,IAAA;AAEN,MAAA,MAAM,KAAA,GAAQ,SAAA,CAAmC,OAAA,EAAS,eAAe,CAAA;AAEzE,MAAA,KAAA,MAAW,QAAQ,CAAC,GAAG,KAAK,CAAA,CAAE,SAAQ,EAAG;AACvC,QAAA,MAAM,KAAK,OAAO,IAAA,CAAK,EAAA,KAAO,QAAA,GAAW,KAAK,EAAA,GAAK,MAAA;AACnD,QAAA,IAAI,CAAC,EAAA,IAAM,IAAA,CAAK,GAAA,CAAI,EAAE,CAAA,EAAG;AAEzB,QAAA,IAAA,CAAK,IAAI,EAAE,CAAA;AAGX,QAAA,IAAI,CAAC,QAAA,EAAU,OAAA,CAAQ,OAAA,CAAQ,EAAE,IAAA,EAAM,cAAA,EAAgB,IAAA,EAAM,EAAE,OAAA,EAAS,IAAA,EAAK,EAAG,CAAA;AAAA,MAClF;AAGA,MAAA,IAAI,IAAA,CAAK,IAAA,GAAO,IAAA,CAAK,MAAA,GAAS,CAAA,EAAG;AAC/B,QAAA,MAAM,MAAA,GAAS,CAAC,GAAG,IAAI,CAAA,CAAE,KAAA,CAAM,CAAA,EAAG,IAAA,CAAK,IAAA,GAAO,IAAA,CAAK,MAAA,GAAS,CAAC,CAAA;AAC7D,QAAA,KAAA,MAAW,EAAA,IAAM,MAAA,EAAQ,IAAA,CAAK,MAAA,CAAO,EAAE,CAAA;AAAA,MACzC;AAEA,MAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,UAAA,CAAW,SAAS,OAAO,CAAA;AACpD,MAAA,IAAI,KAAA,KAAU,MAAA,IAAa,KAAA,KAAU,eAAA,EAAiB;AACpD,QAAA,eAAA,GAAkB,KAAA;AAClB,QAAA,OAAA,CAAQ,OAAA,CAAQ,EAAE,IAAA,EAAM,cAAA,EAAgB,IAAA,EAAM,EAAE,OAAA,EAAS,EAAE,KAAA,EAAM,EAAE,EAAG,CAAA;AAAA,MACxE;AAEA,MAAA,QAAA,GAAW,KAAA;AACX,MAAA,MAAM,IAAA,CAAK,KAAA,CAAM,OAAA,CAAQ,MAAM,CAAA;AAAA,IACjC;AAAA,EACF;AAAA,EAEA,MAAM,UAAA,CAAW,OAAA,EAA2B,OAAA,EAA+C;AACzF,IAAA,IAAI;AACF,MAAA,MAAM,QAAA,GAAW,MAAM,OAAA,CAAQ,KAAA,CAAM,QAAQ,OAAA,CAAQ,OAAA,EAAS,0BAA0B,CAAA,EAAG;AAAA,QACzF,MAAA,EAAQ,KAAA;AAAA,QACR,OAAA;AAAA,QACA,QAAQ,OAAA,CAAQ;AAAA,OACjB,CAAA;AAED,MAAA,IAAI,CAAC,QAAA,CAAS,EAAA,EAAI,OAAO,KAAA,CAAA;AAEzB,MAAA,MAAM,IAAA,GAAgB,MAAM,QAAA,CAAS,IAAA,EAAK;AAC1C,MAAA,MAAM,OAAA,GACJ,OAAO,IAAA,KAAS,QAAA,IAAY,SAAS,IAAA,IAAQ,MAAA,IAAU,IAAA,GAClD,IAAA,CAA2B,IAAA,GAC5B,IAAA;AAEN,MAAA,OAAO,UAAA,CAAW,OAAA,EAAS,OAAA,EAAS,CAAC,CAAA;AAAA,IACvC,CAAA,CAAA,MAAQ;AAEN,MAAA,OAAO,MAAA;AAAA,IACT;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,MAAA,EAAoC;AAGxC,IAAA,IAAI,MAAA,CAAO,OAAA,EAAS,OAAO,OAAA,CAAQ,OAAA,EAAQ;AAE3C,IAAA,OAAO,IAAI,OAAA,CAAc,CAAC,OAAA,KAAY;AACpC,MAAA,MAAM,KAAA,GAAQ,UAAA,CAAW,MAAA,EAAQ,IAAA,CAAK,SAAS,CAAA;AAE/C,MAAA,SAAS,MAAA,GAAS;AAChB,QAAA,YAAA,CAAa,KAAK,CAAA;AAClB,QAAA,MAAA,CAAO,mBAAA,CAAoB,SAAS,MAAM,CAAA;AAC1C,QAAA,OAAA,EAAQ;AAAA,MACV;AAEA,MAAA,MAAA,CAAO,iBAAiB,OAAA,EAAS,MAAA,EAAQ,EAAE,IAAA,EAAM,MAAM,CAAA;AAAA,IACzD,CAAC,CAAA;AAAA,EACH;AACF,CAAA;;;AChIO,IAAM,iBAAA,GAAoB,MAAA,CAAO,MAAA,CAAO,CAAC,GAAA,EAAM,KAAM,GAAA,EAAM,GAAA,EAAM,IAAA,EAAO,GAAK,CAAC;AAG9E,IAAM,gBAAA,GAAmB;AAOzB,IAAM,sBAAA,GAAyB;AAqB/B,SAAS,eACd,OAAA,EACA,OAAA,GAA4B,EAAC,EAC7B,MAAA,GAAuB,KAAK,MAAA,EACpB;AACR,EAAA,MAAM,OAAA,GAAU,QAAQ,OAAA,IAAW,iBAAA;AACnC,EAAA,MAAM,MAAA,GAAS,QAAQ,MAAA,IAAU,gBAAA;AAEjC,EAAA,MAAM,IAAA,GAAO,QAAQ,IAAA,CAAK,GAAA,CAAI,SAAS,OAAA,CAAQ,MAAA,GAAS,CAAC,CAAC,CAAA,IAAK,GAAA;AAC/D,EAAA,MAAM,MAAA,GAAS,IAAA,GAAO,MAAA,IAAU,MAAA,KAAW,CAAA,GAAI,CAAA,CAAA;AAE/C,EAAA,OAAO,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,KAAA,CAAM,IAAA,GAAO,MAAM,CAAC,CAAA;AAC9C;;;ACtCO,IAAM,UAAA,GAAN,cAAyB,KAAA,CAAM;AAqBpC,EAAA,WAAA,CACE,SACA,OAAA,EACA;AACA,IAAA,KAAA,CAAM,OAAO,CAAA,EACb,IAAA,CAAK,OAAO,YAAA,EACZ,IAAA,CAAK,OAAO,OAAA,CAAQ,IAAA,EACpB,KAAK,KAAA,GAAQ,OAAA,CAAQ,OACrB,IAAA,CAAK,KAAA,GAAQ,QAAQ,KAAA,EACrB,IAAA,CAAK,OAAO,OAAA,CAAQ,IAAA;AACtB,EAAA;AACF,CAAA;ACnCA,IAAM,EAAA,GAAK,EAAA;AAAX,IACM,EAAA,GAAK,EAAA;AADX,IAEM,KAAA,GAAQ,EAAA;AAGd,SAAS,KAAK,IAAA,EAAe;AAE7B;AAWO,SAAS,aAAa,MAAA,EAAyC;AACpE,EAAA,IAAI,OAAO,MAAA,IAAW,UAAA;AACpB,IAAA,MAAM,IAAI,SAAA;AACR,MAAA;AAAA,KAAA;AAIJ,EAAA,MAAM,EAAC,OAAA,GAAU,IAAA,EAAM,OAAA,GAAU,IAAA,EAAM,OAAA,GAAU,IAAA,EAAM,SAAA,EAAW,aAAA,EAAA,GAAiB,MAAA,EAQ7E,gBAAA,GAA6B,EAAA;AAInC,EAAA,IAAI,sBAAA,GAAyB,CAAA,EAEzB,YAAA,GAAe,IAAA,EACf,EAAA,EACA,OAAO,EAAA,EACP,SAAA,GAAY,CAAA,EACZ,SAAA,EAIA,UAAA,GAAa,KAAA;AAajB,EAAA,SAAS,KAAK,KAAA,EAAe;AAC3B,IAAA,IAAI,UAAA;AACF,MAAA,MAAM,IAAI,KAAA;AACR,QAAA;AAAA,OAAA;AAoBJ,IAAA,IAhBI,YAAA,KACF,YAAA,GAAe,KAAA,EAIb,KAAA,CAAM,UAAA,CAAW,CAAC,CAAA,KAAM,GAAA,IACxB,KAAA,CAAM,UAAA,CAAW,CAAC,CAAA,KAAM,OACxB,KAAA,CAAM,UAAA,CAAW,CAAC,CAAA,KAAM,GAAA,KAExB,KAAA,GAAQ,KAAA,CAAM,KAAA,CAAM,CAAC,CAAA,CAAA,CAAA,EAOrB,gBAAA,CAAiB,MAAA,KAAW,CAAA,EAAG;AACjC,MAAA,MAAMC,SAAAA,GAAW,aAAa,KAAK,CAAA;AAC/BA,MAAAA,SAAAA,KAAa,EAAA,KACf,iBAAiB,IAAA,CAAKA,SAAQ,GAC9B,sBAAA,GAAyBA,SAAAA,CAAS,SAEpC,eAAA,EAAA;AACA,MAAA;AACF,IAAA;AAKA,IAAA,IAAI,MAAM,OAAA,CAAQ;AAAI,CAAA,CAAA,KAAM,EAAA,IAAM,KAAA,CAAM,OAAA,CAAQ,IAAI,MAAM,EAAA,EAAI;AAC5D,MAAA,gBAAA,CAAiB,KAAK,KAAK,CAAA,EAC3B,sBAAA,IAA0B,KAAA,CAAM,QAChC,eAAA,EAAA;AACA,MAAA;AACF,IAAA;AAIA,IAAA,gBAAA,CAAiB,KAAK,KAAK,CAAA;AAC3B,IAAA,MAAM,KAAA,GAAQ,gBAAA,CAAiB,IAAA,CAAK,EAAE,CAAA;AACtC,IAAA,gBAAA,CAAiB,MAAA,GAAS,GAC1B,sBAAA,GAAyB,CAAA;AACzB,IAAA,MAAM,QAAA,GAAW,aAAa,KAAK,CAAA;AAC/B,IAAA,QAAA,KAAa,EAAA,KACf,iBAAiB,IAAA,CAAK,QAAQ,GAC9B,sBAAA,GAAyB,QAAA,CAAS,SAEpC,eAAA,EAAA;AACF,EAAA;AAEA,EAAA,SAAS,eAAA,GAAkB;AACrB,IAAA,aAAA,KAAkB,WAClB,sBAAA,GAAyB,IAAA,CAAK,UAAU,aAAA,KAE5C,UAAA,GAAa,MACb,gBAAA,CAAiB,MAAA,GAAS,GAC1B,sBAAA,GAAyB,CAAA,EACzB,KAAK,MAAA,EACL,IAAA,GAAO,IACP,SAAA,GAAY,CAAA,EACZ,YAAY,MAAA,EACZ,OAAA;MACE,IAAI,UAAA,CAAW,CAAA,0CAAA,EAA6C,aAAa,CAAA,WAAA,CAAA,EAAe;QACtF,IAAA,EAAM;OACP;AAAA,KAAA,CAAA,CAAA;AAEL,EAAA;AAWA,EAAA,SAAS,aAAa,KAAA,EAAuB;AAC3C,IAAA,IAAI,WAAA,GAAc,CAAA;AAMlB,IAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA,KAAM,EAAA,EAAI;AAC9B,MAAA,IAAI,OAAA,GAAU,MAAM,OAAA,CAAQ;GAAM,WAAW,CAAA;AAC7C,MAAA,OAAO,YAAY,EAAA,IAAI;AAIrB,QAAA,IAAI,gBAAgB,OAAA,EAAS;AACvB,UAAA,SAAA,GAAY,CAAA,IACd,QAAQ,EAAC,EAAA,EAAI,OAAO,SAAA,EAAW,IAAA,EAAK,CAAA,EAEtC,EAAA,GAAK,MAAA,EACL,OAAO,EAAA,EACP,SAAA,GAAY,GACZ,SAAA,GAAY,MAAA,EACZ,cAAc,OAAA,GAAU,CAAA,EACxB,OAAA,GAAU,KAAA,CAAM,OAAA,CAAQ;GAAM,WAAW,CAAA;AACzC,UAAA;AACF,QAAA;AACA,QAAA,MAAM,aAAA,GAAgB,KAAA,CAAM,UAAA,CAAW,WAAW,CAAA;AAClD,QAAA,IAAI,YAAA,CAAa,KAAA,EAAO,WAAA,EAAa,aAAa,CAAA,EAAG;AAGnD,UAAA,MAAM,UAAA,GACJ,KAAA,CAAM,UAAA,CAAW,WAAA,GAAc,CAAC,CAAA,KAAM,KAAA,GAAQ,WAAA,GAAc,CAAA,GAAI,cAAc,CAAA,EAC1E,KAAA,GAAQ,KAAA,CAAM,KAAA,CAAM,YAAY,OAAO,CAAA;AAM7C,UAAA,IAAI,cAAc,CAAA,IAAK,KAAA,CAAM,WAAW,OAAA,GAAU,CAAC,MAAM,EAAA,EAAI;AAC3D,YAAA,OAAA,CAAQ,EAAC,EAAA,EAAI,KAAA,EAAO,WAAW,IAAA,EAAM,KAAA,EAAM,CAAA,EAC3C,EAAA,GAAK,QACL,IAAA,GAAO,EAAA,EACP,YAAY,MAAA,EACZ,WAAA,GAAc,UAAU,CAAA,EACxB,OAAA,GAAU,MAAM,OAAA,CAAQ;GAAM,WAAW,CAAA;AACzC,YAAA;AACF,UAAA;AAEA,UAAA,IAAA,GAAO,SAAA,KAAc,CAAA,GAAI,KAAA,GAAQ,CAAA,EAAG,IAAI;AAAK,EAAA,KAAK,CAAA,CAAA,EAClD,SAAA,EAAA;AACF,QAAA,CAAA,oBAAyB,KAAA,EAAO,WAAA,EAAa,aAAa,CAAA,GAIxD,YACE,KAAA,CAAM,KAAA;AACJ,UAAA,KAAA,CAAM,WAAW,WAAA,GAAc,CAAC,MAAM,KAAA,GAAQ,WAAA,GAAc,IAAI,WAAA,GAAc,CAAA;AAC9E,UAAA;AAAA,SAAA,IACG,MAAA,GAKP,SAAA,CAAU,KAAA,EAAO,WAAA,EAAa,OAAO,CAAA;AAEvC,QAAA,WAAA,GAAc,OAAA,GAAU,CAAA,EACxB,OAAA,GAAU,KAAA,CAAM,OAAA,CAAQ;GAAM,WAAW,CAAA;AAC3C,MAAA;AACA,MAAA,OAAO,KAAA,CAAM,MAAM,WAAW,CAAA;AAChC,IAAA;AAKA,IAAA,OAAO,WAAA,GAAc,MAAM,MAAA,IAAQ;AACjC,MAAA,MAAM,OAAA,GAAU,MAAM,OAAA,CAAQ,IAAA,EAAM,WAAW,CAAA,EACzC,OAAA,GAAU,MAAM,OAAA,CAAQ;GAAM,WAAW,CAAA;AAE/C,MAAA,IAAI,OAAA,GAAU,EAAA;AAgBd,MAAA,IAfI,OAAA,KAAY,MAAM,OAAA,KAAY,EAAA,GAChC,UAAU,OAAA,GAAU,OAAA,GAAU,OAAA,GAAU,OAAA,GAC/B,OAAA,KAAY,EAAA,GAIjB,YAAY,KAAA,CAAM,MAAA,GAAS,CAAA,GAC7B,OAAA,GAAU,EAAA,GAEV,OAAA,GAAU,UAEH,OAAA,KAAY,EAAA,KACrB,OAAA,GAAU,OAAA,CAAA,EAGR,OAAA,KAAY,EAAA;AACd,QAAA;AAGF,MAAA,SAAA,CAAU,OAAO,WAAA,EAAa,OAAO,CAAA,EACrC,WAAA,GAAc,UAAU,CAAA,EAGpB,KAAA,CAAM,UAAA,CAAW,WAAA,GAAc,CAAC,CAAA,KAAM,EAAA,IAAM,MAAM,UAAA,CAAW,WAAW,MAAM,EAAA,IAChF,WAAA,EAAA;AAEJ,IAAA;AAEA,IAAA,OAAO,KAAA,CAAM,MAAM,WAAW,CAAA;AAChC,EAAA;AAEA,EAAA,SAAS,SAAA,CAAU,KAAA,EAAeH,MAAAA,EAAe,GAAA,EAAa;AAC5D,IAAA,IAAIA,WAAU,GAAA,EAAK;AACjB,MAAA,aAAA,EAAA;AACA,MAAA;AACF,IAAA;AAEA,IAAA,MAAM,aAAA,GAAgB,KAAA,CAAM,UAAA,CAAWA,MAAK,CAAA;AAE5C,IAAA,IAAI,YAAA,CAAa,KAAA,EAAOA,MAAAA,EAAO,aAAa,CAAA,EAAG;AAE7C,MAAA,MAAM,UAAA,GAAa,KAAA,CAAM,UAAA,CAAWA,MAAAA,GAAQ,CAAC,CAAA,KAAM,KAAA,GAAQA,MAAAA,GAAQ,CAAA,GAAIA,SAAQ,CAAA,EACzEF,MAAAA,GAAQ,KAAA,CAAM,KAAA,CAAM,YAAY,GAAG,CAAA;AACzC,MAAA,IAAA,GAAO,SAAA,KAAc,CAAA,GAAIA,MAAAA,GAAQ,CAAA,EAAG,IAAI;AAAKA,EAAAA,MAAK,CAAA,CAAA,EAClD,SAAA,EAAA;AACA,MAAA;AACF,IAAA;AAEA,IAAA,IAAI,aAAA,CAAc,KAAA,EAAOE,MAAAA,EAAO,aAAa,CAAA,EAAG;AAE9C,MAAA,SAAA,GACE,KAAA,CAAM,KAAA,CAAM,KAAA,CAAM,UAAA,CAAWA,MAAAA,GAAQ,CAAC,CAAA,KAAM,KAAA,GAAQA,MAAAA,GAAQ,CAAA,GAAIA,MAAAA,GAAQ,CAAA,EAAG,GAAG,CAAA,IAAK,MAAA;AACrF,MAAA;AACF,IAAA;AAGA,IAAA,IACE,aAAA,KAAkB,GAAA,IAClB,KAAA,CAAM,UAAA,CAAWA,MAAAA,GAAQ,CAAC,CAAA,KAAM,GAAA,IAChC,KAAA,CAAM,UAAA,CAAWA,MAAAA,GAAQ,CAAC,MAAM,EAAA,EAChC;AAEA,MAAA,MAAMF,MAAAA,GAAQ,KAAA,CAAM,KAAA,CAAM,KAAA,CAAM,UAAA,CAAWE,MAAAA,GAAQ,CAAC,CAAA,KAAM,KAAA,GAAQA,MAAAA,GAAQ,CAAA,GAAIA,MAAAA,GAAQ,GAAG,GAAG,CAAA;AAC5F,MAAA,EAAA,GAAKF,MAAAA,CAAM,QAAA,CAAS,IAAI,CAAA,GAAI,MAAA,GAAYA,MAAAA;AACxC,MAAA;AACF,IAAA;AAGA,IAAA,IAAI,kBAAkB,EAAA,EAAI;AACxB,MAAA,IAAI,SAAA,EAAW;AACb,QAAA,MAAMM,KAAAA,GAAO,KAAA,CAAM,KAAA,CAAMJ,MAAAA,EAAO,GAAG,CAAA;AAEnC,QAAA,SAAA,CAAUI,KAAAA,CAAK,KAAA,CAAM,KAAA,CAAM,UAAA,CAAWJ,MAAAA,GAAQ,CAAC,CAAA,KAAM,KAAA,GAAQ,CAAA,GAAI,CAAC,CAAC,CAAA;AACrE,MAAA;AACA,MAAA;AACF,IAAA;AAEA,IAAA,MAAM,IAAA,GAAO,MAAM,KAAA,CAAMA,MAAAA,EAAO,GAAG,CAAA,EAC7B,mBAAA,GAAsB,IAAA,CAAK,OAAA,CAAQ,GAAG,CAAA;AAC5C,IAAA,IAAI,wBAAwB,EAAA,EAAI;AAC9B,MAAA,YAAA,CAAa,IAAA,EAAM,IAAI,IAAI,CAAA;AAC3B,MAAA;AACF,IAAA;AAEA,IAAA,MAAM,QAAQ,IAAA,CAAK,KAAA,CAAM,GAAG,mBAAmB,CAAA,EAEzC,SAAS,IAAA,CAAK,UAAA,CAAW,sBAAsB,CAAC,CAAA,KAAM,QAAQ,CAAA,GAAI,CAAA,EAClE,QAAQ,IAAA,CAAK,KAAA,CAAM,sBAAsB,MAAM,CAAA;AACrD,IAAA,YAAA,CAAa,KAAA,EAAO,OAAO,IAAI,CAAA;AACjC,EAAA;AAEA,EAAA,SAAS,YAAA,CAAa,KAAA,EAAe,KAAA,EAAe,IAAA,EAAc;AAEhE,IAAA,QAAQ,KAAA;MACN,KAAK,OAAA;AAEH,QAAA,SAAA,GAAY,KAAA,IAAS,MAAA;AACrB,QAAA;MACF,KAAK,MAAA;AACH,QAAA,IAAA,GAAO,SAAA,KAAc,CAAA,GAAI,KAAA,GAAQ,CAAA,EAAG,IAAI;AAAK,EAAA,KAAK,CAAA,CAAA,EAClD,SAAA,EAAA;AACA,QAAA;MACF,KAAK,IAAA;AAGH,QAAA,EAAA,GAAK,KAAA,CAAM,QAAA,CAAS,IAAI,CAAA,GAAI,MAAA,GAAY,KAAA;AACxC,QAAA;MACF,KAAK,OAAA;AAIC,QAAA,OAAA,CAAQ,IAAA,CAAK,KAAK,CAAA,GACpB,OAAA,CAAQ,SAAS,KAAA,EAAO,EAAE,CAAC,CAAA,GAE3B,OAAA;UACE,IAAI,UAAA,CAAW,CAAA,0BAAA,EAA6B,KAAK,CAAA,CAAA,CAAA,EAAK;YACpD,IAAA,EAAM,eAAA;AACN,YAAA,KAAA;AACA,YAAA;WACD;AAAA,SAAA;AAGL,QAAA;AACF,MAAA;AAEE,QAAA,OAAA;UACE,IAAI,UAAA;YACF,CAAA,eAAA,EAAkB,KAAA,CAAM,MAAA,GAAS,EAAA,GAAK,CAAA,EAAG,KAAA,CAAM,MAAM,CAAA,EAAG,EAAE,CAAC,CAAA,MAAA,CAAA,GAAM,KAAK,CAAA,CAAA,CAAA;AACtE,YAAA,EAAC,IAAA,EAAM,eAAA,EAAiB,KAAA,EAAO,KAAA,EAAO,IAAA;AAAI;AAC5C,SAAA;AAEF,QAAA;AAAA;AAEN,EAAA;AAEA,EAAA,SAAS,aAAA,GAAgB;AACnB,IAAA,SAAA,GAAY,KACd,OAAA,CAAQ;AACN,MAAA,EAAA;MACA,KAAA,EAAO,SAAA;AACP,MAAA;AAAA,KACD,GAGH,EAAA,GAAK,MAAA,EACL,OAAO,EAAA,EACP,SAAA,GAAY,GACZ,SAAA,GAAY,MAAA;AACd,EAAA;AAEA,EAAA,SAAS,KAAA,CAAM,OAAA,GAA+B,EAAA,EAAI;AAChD,IAAA,IAAI,OAAA,CAAQ,OAAA,IAAW,gBAAA,CAAiB,MAAA,GAAS,CAAA,EAAG;AAClD,MAAA,MAAM,cAAA,GAAiB,gBAAA,CAAiB,IAAA,CAAK,EAAE,CAAA;AAC/C,MAAA,SAAA,CAAU,cAAA,EAAgB,CAAA,EAAG,cAAA,CAAe,MAAM,CAAA;AACpD,IAAA;AAEA,IAAA,YAAA,GAAe,IAAA,EACf,EAAA,GAAK,MAAA,EACL,IAAA,GAAO,IACP,SAAA,GAAY,CAAA,EACZ,SAAA,GAAY,MAAA,EACZ,gBAAA,CAAiB,MAAA,GAAS,CAAA,EAC1B,sBAAA,GAAyB,GACzB,UAAA,GAAa,KAAA;AACf,EAAA;AAEA,EAAA,OAAO,EAAC,MAAM,KAAA,EAAA;AAChB;AAYA,SAAS,YAAA,CAAa,KAAA,EAAe,CAAA,EAAW,aAAA,EAAgC;AAC9E,EAAA,OACE,aAAA,KAAkB,GAAA,IAClB,KAAA,CAAM,UAAA,CAAW,CAAA,GAAI,CAAC,CAAA,KAAM,EAAA,IAC5B,KAAA,CAAM,UAAA,CAAW,CAAA,GAAI,CAAC,MAAM,GAAA,IAC5B,KAAA,CAAM,UAAA,CAAW,CAAA,GAAI,CAAC,CAAA,KAAM,MAC5B,KAAA,CAAM,UAAA,CAAW,CAAA,GAAI,CAAC,CAAA,KAAM,EAAA;AAEhC;AAUA,SAAS,aAAA,CAAc,KAAA,EAAe,CAAA,EAAW,aAAA,EAAgC;AAC/E,EAAA,OACE,aAAA,KAAkB,GAAA,IAClB,KAAA,CAAM,UAAA,CAAW,CAAA,GAAI,CAAC,CAAA,KAAM,GAAA,IAC5B,KAAA,CAAM,UAAA,CAAW,CAAA,GAAI,CAAC,MAAM,GAAA,IAC5B,KAAA,CAAM,UAAA,CAAW,CAAA,GAAI,CAAC,CAAA,KAAM,GAAA,IAC5B,KAAA,CAAM,UAAA,CAAW,CAAA,GAAI,CAAC,CAAA,KAAM,GAAA,IAC5B,KAAA,CAAM,UAAA,CAAW,CAAA,GAAI,CAAC,CAAA,KAAM,EAAA;AAEhC;;;AC3aO,IAAM,WAAA,GAAc;AAyBpB,IAAM,eAAN,MAAgD;AAAA,EAC5C,IAAA,GAAO,KAAA;AAAA,EAEP,YAAA;AAAA;AAAA,EAET,YAAA;AAAA,EAEA,WAAA,CAAY,OAAA,GAA+B,EAAC,EAAG;AAC7C,IAAA,IAAA,CAAK,YAAA,GAAe,QAAQ,WAAA,IAAe,GAAA;AAAA,EAC7C;AAAA,EAEA,MAAM,QAAQ,OAAA,EAA0C;AACtD,IAAA,MAAM,KAAA,GAAQ,MAAM,OAAA,CAAQ,QAAA,EAAS;AACrC,IAAA,IAAI,CAAC,KAAA,EAAO,MAAM,IAAI,uBAAA,EAAwB;AAE9C,IAAA,MAAM,OAAA,GAAU,IAAI,OAAA,CAAQ;AAAA,MAC1B,MAAA,EAAQ,mBAAA;AAAA,MACR,aAAA,EAAe,UAAU,KAAK,CAAA,CAAA;AAAA,MAC9B,eAAA,EAAiB;AAAA,KAClB,CAAA;AAGD,IAAA,IAAI,KAAK,YAAA,EAAc,OAAA,CAAQ,GAAA,CAAI,eAAA,EAAiB,KAAK,YAAY,CAAA;AAErE,IAAA,MAAM,QAAA,GAAW,MAAM,OAAA,CAAQ,KAAA,CAAM,QAAQ,OAAA,CAAQ,OAAA,EAAS,WAAW,CAAA,EAAG;AAAA,MAC1E,MAAA,EAAQ,KAAA;AAAA,MACR,OAAA;AAAA,MACA,QAAQ,OAAA,CAAQ;AAAA,KACjB,CAAA;AAED,IAAA,IAAI,QAAA,CAAS,MAAA,KAAW,GAAA,EAAK,MAAM,IAAI,uBAAA,EAAwB;AAC/D,IAAA,IAAI,CAAC,SAAS,EAAA,EAAI,MAAM,IAAI,KAAA,CAAM,CAAA,4KAAA,EAAmC,QAAA,CAAS,MAAM,CAAA,CAAE,CAAA;AACtF,IAAA,IAAI,CAAC,QAAA,CAAS,IAAA,EAAM,MAAM,IAAI,MAAM,iKAA+B,CAAA;AAEnE,IAAA,OAAA,CAAQ,MAAA,EAAO;AAEf,IAAA,MAAM,IAAA,CAAK,KAAA,CAAM,QAAA,CAAS,IAAA,EAAM,OAAO,CAAA;AAAA,EACzC;AAAA,EAEA,MAAM,KAAA,CAAM,IAAA,EAAkC,OAAA,EAA0C;AACtF,IAAA,MAAM,MAAA,GAAS,KAAK,SAAA,EAAU;AAC9B,IAAA,MAAM,OAAA,GAAU,IAAI,WAAA,EAAY;AAEhC,IAAA,MAAM,SAAS,YAAA,CAAa;AAAA,MAC1B,OAAA,EAAS,CAAC,OAAA,KAAY;AACpB,QAAA,IAAI,OAAA,CAAQ,EAAA,EAAI,IAAA,CAAK,YAAA,GAAe,OAAA,CAAQ,EAAA;AAE5C,QAAA,IAAI,IAAA;AACJ,QAAA,IAAI;AACF,UAAA,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA;AAAA,QAChC,SAAS,KAAA,EAAO;AAEd,UAAA,OAAA,CAAQ,YAAA,CAAa,KAAA,EAAO,OAAA,CAAQ,IAAI,CAAA;AACxC,UAAA;AAAA,QACF;AAGA,QAAA,MAAM,IAAA,GACJ,OAAA,CAAQ,KAAA,KACP,OAAO,IAAA,KAAS,QAAA,IAAY,IAAA,KAAS,IAAA,IAAQ,MAAA,IAAU,IAAA,GACpD,MAAA,CAAQ,IAAA,CAA2B,IAAI,CAAA,GACvC,SAAA,CAAA;AAEN,QAAA,OAAA,CAAQ,OAAA,CAAQ,EAAE,IAAA,EAAM,IAAA,EAAM,CAAA;AAAA,MAChC;AAAA,KACD,CAAA;AAED,IAAA,IAAI,SAAA;AAEJ,IAAA,MAAM,eAAe,MAAM;AACzB,MAAA,IAAI,IAAA,CAAK,gBAAgB,CAAA,EAAG;AAC5B,MAAA,IAAI,SAAA,KAAc,MAAA,EAAW,YAAA,CAAa,SAAS,CAAA;AAEnD,MAAA,SAAA,GAAY,WAAW,MAAM;AAE3B,QAAA,KAAK,MAAA,CAAO,OAAO,IAAI,KAAA,CAAM,6KAAiC,CAAC,CAAA,CAAE,MAAM,MAAM;AAAA,QAAC,CAAC,CAAA;AAAA,MACjF,CAAA,EAAG,KAAK,YAAY,CAAA;AAAA,IACtB,CAAA;AAEA,IAAA,YAAA,EAAa;AAEb,IAAA,IAAI;AACF,MAAA,WAAS;AACP,QAAA,MAAM,EAAE,IAAA,EAAM,KAAA,EAAM,GAAI,MAAM,OAAO,IAAA,EAAK;AAC1C,QAAA,IAAI,IAAA,EAAM;AAEV,QAAA,YAAA,EAAa;AACb,QAAA,MAAA,CAAO,IAAA,CAAK,QAAQ,MAAA,CAAO,KAAA,EAAO,EAAE,MAAA,EAAQ,IAAA,EAAM,CAAC,CAAA;AAAA,MACrD;AAAA,IACF,CAAA,SAAE;AACA,MAAA,IAAI,SAAA,KAAc,MAAA,EAAW,YAAA,CAAa,SAAS,CAAA;AACnD,MAAA,MAAA,CAAO,WAAA,IAAc;AAAA,IACvB;AAAA,EACF;AACF,CAAA;;;AChFO,IAAM,qBAAA,GAAwB,OAAO,MAAA,CAAO;AAAA;AAAA,EAEjD,IAAA,EAAM,MAAA;AAAA;AAAA,EAEN,GAAA,EAAK,KAAA;AAAA;AAAA,EAEL,IAAA,EAAM;AACR,CAAU;AAyEH,IAAM,cAAN,MAAkB;AAAA,EACd,KAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA,GAAW,IAAI,OAAA,EAAwB;AAAA,EACvC,UAAA;AAAA,EACA,YAAA;AAAA,EAET,WAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OAAA,GAAU,KAAA;AAAA,EACV,UAA0B,cAAA,CAAe,YAAA;AAAA,EACzC,QAAA,GAAW,CAAA;AAAA,EACX,MAAA;AAAA,EACA,kBAAA;AAAA,EAEA,WAAA,CAAY,IAAA,EAAoB,OAAA,GAA2B,EAAC,EAAG;AAC7D,IAAA,IAAA,CAAK,KAAA,GAAQ,IAAA;AACb,IAAA,IAAA,CAAK,QAAA,GAAW,OAAA;AAChB,IAAA,IAAA,CAAK,YAAA,GAAe,QAAQ,WAAA,IAAe,sBAAA;AAC3C,IAAA,IAAA,CAAK,UAAA,GAAa,KAAK,gBAAA,EAAiB;AAAA,EAC1C;AAAA;AAAA,EAGA,IAAI,MAAA,GAAyB;AAC3B,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,EACd;AAAA;AAAA,EAGA,IAAI,SAAA,GAAoB;AACtB,IAAA,OAAO,KAAK,UAAA,CAAW,IAAA;AAAA,EACzB;AAAA;AAAA,EAGA,EAAA,CAAmC,OAAU,QAAA,EAAoD;AAC/F,IAAA,OAAO,IAAA,CAAK,QAAA,CAAS,EAAA,CAAG,KAAA,EAAO,QAAQ,CAAA;AAAA,EACzC;AAAA;AAAA,EAGA,IAAA,CACE,OACA,QAAA,EACa;AACb,IAAA,OAAO,IAAA,CAAK,QAAA,CAAS,IAAA,CAAK,KAAA,EAAO,QAAQ,CAAA;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,OAAA,GAAyB;AAC7B,IAAA,IAAI,KAAK,OAAA,EAAS;AAClB,IAAA,IAAA,CAAK,OAAA,GAAU,IAAA;AAEf,IAAA,IAAA,CAAK,2BAAA,EAA4B;AAEjC,IAAA,IAAI,IAAA,CAAK,QAAA,CAAS,SAAA,KAAc,KAAA,EAAO;AACrC,MAAA,IAAI;AACF,QAAA,IAAA,CAAK,SAAS,IAAA,CAAK,aAAA,EAAe,MAAM,IAAA,CAAK,KAAA,CAAM,kBAAkB,CAAA;AAAA,MACvE,SAAS,KAAA,EAAO;AAEd,QAAA,IAAA,CAAK,KAAA,CAAM,MAAA,EAAQ,KAAA,CAAM,wNAAA,EAA2C,KAAK,CAAA;AAAA,MAC3E;AAAA,IACF;AAGA,IAAA,IAAI,IAAA,CAAK,OAAA,EAAS,IAAA,CAAK,IAAA,EAAK;AAAA,EAC9B;AAAA;AAAA,EAGA,UAAA,GAAmB;AACjB,IAAA,IAAA,CAAK,OAAA,GAAU,KAAA;AAEf,IAAA,IAAI,IAAA,CAAK,WAAW,MAAA,EAAW;AAC7B,MAAA,YAAA,CAAa,KAAK,MAAM,CAAA;AACxB,MAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AAAA,IAChB;AAEA,IAAA,IAAA,CAAK,kBAAA,IAAqB;AAC1B,IAAA,IAAA,CAAK,kBAAA,GAAqB,MAAA;AAE1B,IAAA,IAAA,CAAK,aAAa,KAAA,EAAM;AACxB,IAAA,IAAA,CAAK,WAAA,GAAc,MAAA;AACnB,IAAA,IAAA,CAAK,QAAA,GAAW,CAAA;AAEhB,IAAA,IAAA,CAAK,UAAA,CAAW,eAAe,YAAY,CAAA;AAAA,EAC7C;AAAA;AAAA,EAGA,kBAAA,GAA2B;AACzB,IAAA,IAAA,CAAK,SAAS,kBAAA,EAAmB;AAAA,EACnC;AAAA,EAEA,gBAAA,GAAsC;AACpC,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,QAAA,CAAS,SAAA,IAAa,qBAAA,CAAsB,IAAA;AAE9D,IAAA,IAAI,OAAO,IAAA,KAAS,QAAA,EAAU,OAAO,IAAA;AAErC,IAAA,IACE,IAAA,KAAS,sBAAsB,IAAA,IAC9B,IAAA,KAAS,sBAAsB,IAAA,IAAQ,CAAC,uBAAsB,EAC/D;AACA,MAAA,OAAO,IAAI,aAAA,CAAc;AAAA,QACvB,GAAI,IAAA,CAAK,QAAA,CAAS,YAAA,KAAiB,MAAA,GAC/B,EAAE,QAAA,EAAU,IAAA,CAAK,QAAA,CAAS,YAAA,EAAa,GACvC;AAAC,OACN,CAAA;AAAA,IACH;AAEA,IAAA,OAAO,IAAI,YAAA,CAAa;AAAA,MACtB,GAAI,IAAA,CAAK,QAAA,CAAS,WAAA,KAAgB,MAAA,GAC9B,EAAE,WAAA,EAAa,IAAA,CAAK,QAAA,CAAS,WAAA,EAAY,GACzC;AAAC,KACN,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,IAAA,GAAa;AAGX,IAAA,IAAA,CAAK,aAAa,KAAA,EAAM;AAExB,IAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,IAAA,IAAA,CAAK,WAAA,GAAc,UAAA;AACnB,IAAA,IAAA,CAAK,UAAA,CAAW,eAAe,UAAU,CAAA;AAEzC,IAAA,KAAK,IAAA,CAAK,WACP,OAAA,CAAQ;AAAA,MACP,OAAA,EAAS,KAAK,KAAA,CAAM,OAAA;AAAA,MACpB,KAAA,EAAO,KAAK,KAAA,CAAM,KAAA;AAAA,MAClB,QAAA,EAAU,KAAK,KAAA,CAAM,QAAA;AAAA,MACrB,QAAQ,UAAA,CAAW,MAAA;AAAA,MACnB,QAAQ,MAAM;AACZ,QAAA,IAAA,CAAK,QAAA,GAAW,CAAA;AAChB,QAAA,IAAA,CAAK,UAAA,CAAW,eAAe,SAAS,CAAA;AAAA,MAC1C,CAAA;AAAA,MACA,OAAA,EAAS,CAAC,KAAA,KAAU,IAAA,CAAK,aAAa,KAAA,CAAM,IAAA,EAAM,MAAM,IAAI,CAAA;AAAA,MAC5D,YAAA,EAAc,CAAC,KAAA,EAAO,GAAA,KAAQ,IAAA,CAAK,QAAA,CAAS,IAAA,CAAK,YAAA,EAAc,EAAE,KAAA,EAAO,GAAA,EAAK;AAAA,KAC9E,CAAA,CACA,IAAA;AAAA,MACC,MAAM;AAEJ,QAAA,IAAI,CAAC,UAAA,CAAW,MAAA,CAAO,OAAA,EAAS;AAC9B,UAAA,IAAA,CAAK,cAAA,CAAe,IAAI,KAAA,CAAM,8NAA0C,CAAC,CAAA;AAAA,QAC3E;AAAA,MACF,CAAA;AAAA,MACA,CAAC,KAAA,KAAmB;AAClB,QAAA,IAAI,UAAA,CAAW,OAAO,OAAA,EAAS;AAC/B,QAAA,IAAA,CAAK,eAAe,KAAK,CAAA;AAAA,MAC3B;AAAA,KACF;AAAA,EACJ;AAAA,EAEA,YAAA,CAAa,MAAc,IAAA,EAAqB;AAC9C,IAAA,IAAA,CAAK,SAAS,IAAA,CAAK,SAAA,EAAW,EAAE,IAAA,EAAM,MAAM,CAAA;AAE5C,IAAA,IAAI,SAAS,WAAA,EAAa;AAExB,MAAA,IAAA,CAAK,QAAA,CAAS,KAAK,OAAA,EAAS,EAAE,QAAQ,UAAA,CAAW,IAAA,EAAM,QAAQ,CAAA,EAAG,CAAA;AAClE,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,SAAS,cAAA,EAAgB;AAC3B,MAAA,MAAM,KAAA,GAAQ,sBAAsB,IAAI,CAAA;AACxC,MAAA,IAAA,CAAK,QAAA,CAAS,IAAA,CAAK,cAAA,EAAgB,KAAK,CAAA;AAGxC,MAAA,IAAI,KAAA,CAAM,gBAAgB,MAAA,EAAW,IAAA,CAAK,SAAS,IAAA,CAAK,aAAA,EAAe,MAAM,WAAW,CAAA;AACxF,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,SAAS,cAAA,EAAgB;AAC3B,MAAA,MAAM,KAAA,GAAQ,qBAAqB,IAAI,CAAA;AAGvC,MAAA,IAAI,UAAU,MAAA,EAAW,IAAA,CAAK,QAAA,CAAS,IAAA,CAAK,eAAe,KAAK,CAAA;AAAA,IAClE;AAAA,EACF;AAAA,EAEA,eAAe,KAAA,EAAsB;AACnC,IAAA,IAAA,CAAK,WAAA,GAAc,MAAA;AAEnB,IAAA,IAAI,iBAAiB,uBAAA,EAAyB;AAC5C,MAAA,KAAK,IAAA,CAAK,qBAAqB,KAAK,CAAA;AACpC,MAAA;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,UAAA,CAAW,eAAe,KAAK,CAAA;AACpC,IAAA,IAAA,CAAK,mBAAmB,KAAK,CAAA;AAAA,EAC/B;AAAA;AAAA,EAGA,MAAM,qBAAqB,KAAA,EAA+B;AACxD,IAAA,IAAA,CAAK,UAAA,CAAW,eAAe,KAAK,CAAA;AAEpC,IAAA,MAAM,SAAA,GAAY,MAAM,IAAA,CAAK,KAAA,CAAM,SAAQ,CAAE,KAAA,CAAM,MAAM,KAAK,CAAA;AAE9D,IAAA,IAAI,CAAC,SAAA,EAAW;AACd,MAAA,IAAA,CAAK,SAAS,IAAA,CAAK,OAAA,EAAS,EAAE,KAAA,EAAO,aAAA,EAAe,OAAO,CAAA;AAC3D,MAAA,IAAA,CAAK,QAAA,CAAS,IAAA,CAAK,QAAA,EAAU,MAAS,CAAA;AACtC,MAAA;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,mBAAmB,KAAK,CAAA;AAAA,EAC/B;AAAA,EAEA,mBAAmB,KAAA,EAAsB;AACvC,IAAA,IAAI,IAAA,CAAK,QAAA,IAAY,IAAA,CAAK,YAAA,EAAc;AACtC,MAAA,IAAA,CAAK,SAAS,IAAA,CAAK,OAAA,EAAS,EAAE,KAAA,EAAO,aAAA,EAAe,OAAO,CAAA;AAC3D,MAAA,IAAA,CAAK,QAAA,CAAS,IAAA,CAAK,QAAA,EAAU,MAAS,CAAA;AACtC,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,KAAA,GAAQ,cAAA,CAAe,IAAA,CAAK,QAAA,EAAU,KAAK,QAAQ,CAAA;AACzD,IAAA,IAAA,CAAK,QAAA,IAAY,CAAA;AAEjB,IAAA,IAAA,CAAK,SAAS,IAAA,CAAK,OAAA,EAAS,EAAE,KAAA,EAAO,aAAA,EAAe,MAAM,CAAA;AAC1D,IAAA,IAAA,CAAK,QAAA,CAAS,KAAK,WAAA,EAAa,EAAE,SAAS,IAAA,CAAK,QAAA,EAAU,OAAO,CAAA;AAEjE,IAAA,IAAA,CAAK,MAAA,GAAS,WAAW,MAAM;AAC7B,MAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,MAAA,IAAA,CAAK,IAAA,EAAK;AAAA,IACZ,GAAG,KAAK,CAAA;AAAA,EACV;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,2BAAA,GAAoC;AAClC,IAAA,IAAI,KAAK,kBAAA,EAAoB;AAE7B,IAAA,MAAM,MAAA,GAAS,UAAA;AAMf,IAAA,IAAI,OAAO,MAAA,CAAO,gBAAA,KAAqB,UAAA,EAAY;AAEnD,IAAA,MAAM,OAAO,MAAM;AAEjB,MAAA,IAAI,IAAA,CAAK,WAAA,IAAe,IAAA,CAAK,MAAA,KAAW,MAAA,EAAW;AACnD,MAAA,IAAI,IAAA,CAAK,OAAA,KAAY,cAAA,CAAe,YAAA,EAAc;AAElD,MAAA,IAAA,CAAK,QAAA,GAAW,CAAA;AAChB,MAAA,IAAA,CAAK,IAAA,EAAK;AAAA,IACZ,CAAA;AAEA,IAAA,MAAM,eAAe,MAAM;AACzB,MAAA,IAAI,MAAA,CAAO,QAAA,EAAU,eAAA,KAAoB,SAAA,EAAW,IAAA,EAAK;AAAA,IAC3D,CAAA;AAEA,IAAA,MAAM,YAAoC,EAAC;AAE3C,IAAA,IAAI,IAAA,CAAK,QAAA,CAAS,kBAAA,KAAuB,KAAA,IAAS,OAAO,QAAA,EAAU;AACjE,MAAA,SAAA,CAAU,IAAA,CAAK,CAAC,kBAAA,EAAoB,YAAY,CAAC,CAAA;AAAA,IACnD;AACA,IAAA,IAAI,IAAA,CAAK,QAAA,CAAS,iBAAA,KAAsB,KAAA,EAAO;AAC7C,MAAA,SAAA,CAAU,IAAA,CAAK,CAAC,QAAA,EAAU,IAAI,CAAC,CAAA;AAAA,IACjC;AAEA,IAAA,KAAA,MAAW,CAAC,MAAM,QAAQ,CAAA,IAAK,WAAW,MAAA,CAAO,gBAAA,CAAiB,MAAM,QAAQ,CAAA;AAEhF,IAAA,IAAA,CAAK,qBAAqB,MAAM;AAC9B,MAAA,KAAA,MAAW,CAAC,MAAM,QAAQ,CAAA,IAAK,WAAW,MAAA,CAAO,mBAAA,GAAsB,MAAM,QAAQ,CAAA;AAAA,IACvF,CAAA;AAAA,EACF;AAAA,EAEA,WAAW,MAAA,EAA8B;AACvC,IAAA,IAAI,IAAA,CAAK,YAAY,MAAA,EAAQ;AAC7B,IAAA,IAAA,CAAK,OAAA,GAAU,MAAA;AACf,IAAA,IAAA,CAAK,QAAA,CAAS,IAAA,CAAK,QAAA,EAAU,MAAM,CAAA;AAAA,EACrC;AACF;;;AC5XO,IAAM,cAAA,GAAiB,OAAO,MAAA,CAAO;AAAA;AAAA,EAE1C,MAAA,EAAQ,QAAA;AAAA;AAAA,EAER,IAAA,EAAM,MAAA;AAAA;AAAA,EAEN,MAAA,EAAQ;AACV,CAAU;AA+CV,SAAS,SAAA,CAAa,MAAe,MAAA,EAAgC;AACnE,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA,EAAG,OAAO,IAAA;AAEhC,EAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,IAAA,MAAM,KAAA,GAAQ,SAAA,CAAa,IAAA,EAAM,KAAK,CAAA;AACtC,IAAA,IAAI,KAAA,CAAM,MAAA,GAAS,CAAA,EAAG,OAAO,KAAA;AAAA,EAC/B;AAGA,EAAA,MAAM,OAAA,GAAU,OAAO,CAAC,CAAA;AACxB,EAAA,OAAO,YAAY,MAAA,GAAY,EAAC,GAAI,SAAA,CAAa,MAAM,OAAO,CAAA;AAChE;AAQA,SAAS,WAAW,IAAA,EAA8B;AAChD,EAAA,MAAM,UAAA,GAAa,UAAA,CAAW,IAAA,EAAM,YAAY,CAAA;AAChD,EAAA,MAAM,IAAA,GAAO,UAAA,CAAW,IAAA,EAAM,MAAM,CAAA;AACpC,EAAA,MAAM,UAAA,GAAa,UAAA,CAAW,IAAA,EAAM,QAAQ,CAAA;AAE5C,EAAA,OACE,UAAA,CAAW,UAAA,EAAY,YAAY,CAAA,IACnC,WAAW,IAAA,EAAM,YAAY,CAAA,IAC7B,UAAA,CAAW,MAAM,QAAQ,CAAA,IACzB,UAAA,CAAW,UAAA,EAAY,MAAM,CAAA,IAC7B,IAAA;AAEJ;AASO,SAAS,cAAA,CAAkB,SAAkB,MAAA,EAA2B;AAC7E,EAAA,MAAM,UAAA,GAAa,UAAA,CAAW,IAAA,EAAM,YAAY,CAAA;AAChD,EAAA,MAAM,KAAA,GAAQ,SAAA,CAAa,IAAA,EAAM,MAAM,CAAA;AACvC,EAAA,MAAM,UAAA,GAAa,WAAW,IAAI,CAAA;AAElC,EAAA,OAAO;AAAA,IACL,KAAA;AAAA;AAAA,IAEA,OAAA,EAAS,YAAY,UAAA,EAAY,SAAA,EAAW,YAAY,IAAA,EAAM,SAAA,EAAW,UAAA,KAAe,IAAI,CAAC,CAAA;AAAA,IAC7F,UAAA;AAAA,IACA,KAAA,EAAO,UAAA,CAAW,UAAA,EAAY,OAAA,EAAS,CAAC,CAAA,IAAK,MAAA;AAAA,IAC7C,GAAA,EAAK;AAAA,GACP;AACF;AAQO,SAAS,kBAAA,CAAsB,SAAkB,MAAA,EAA2B;AACjF,EAAA,MAAM,KAAA,GAAQ,SAAA,CAAa,IAAA,EAAM,MAAM,CAAA;AACvC,EAAA,MAAM,UAAA,GAAa,WAAW,IAAI,CAAA;AAClC,EAAA,MAAM,KAAA,GAAQ,UAAA,CAAW,IAAA,EAAM,OAAA,EAAS,EAAE,CAAA;AAE1C,EAAA,OAAO;AAAA,IACL,KAAA;AAAA,IACA,OAAA,EAAS,WAAA,CAAY,IAAA,EAAM,SAAA,EAAW,eAAe,IAAI,CAAA;AAAA,IACzD,UAAA;AAAA,IACA,GAAI,KAAA,IAAS,CAAA,GAAI,EAAE,KAAA,KAAU,EAAC;AAAA,IAC9B,GAAA,EAAK;AAAA,GACP;AACF;AAQO,SAAS,aAAA,CAAiB,SAAkB,MAAA,EAA2B;AAC5E,EAAA,MAAM,UAAA,GAAa,UAAA,CAAW,IAAA,EAAM,YAAY,CAAA;AAChD,EAAA,MAAM,KAAA,GAAQ,SAAA,CAAa,IAAA,EAAM,MAAM,CAAA;AACvC,EAAA,MAAM,UAAA,GAAa,WAAW,IAAI,CAAA;AAElC,EAAA,OAAO;AAAA,IACL,KAAA;AAAA,IACA,OAAA,EAAS,YAAY,UAAA,EAAY,SAAA,EAAW,YAAY,IAAA,EAAM,SAAA,EAAW,UAAA,KAAe,IAAI,CAAC,CAAA;AAAA,IAC7F,IAAA,EAAM,UAAA,CAAW,UAAA,EAAY,MAAA,EAAQ,CAAC,CAAA;AAAA,IACtC,KAAA,EAAO,UAAA,CAAW,UAAA,EAAY,OAAA,EAAS,CAAC,CAAA,IAAK,MAAA;AAAA,IAC7C,KAAA,EAAO,UAAA,CAAW,UAAA,EAAY,OAAA,EAAS,CAAC,CAAA;AAAA,IACxC,GAAI,UAAA,KAAe,IAAA,GAAO,EAAE,UAAA,KAAe,EAAC;AAAA,IAC5C,GAAA,EAAK;AAAA,GACP;AACF;AAQO,SAAS,cAAA,CAAkB,IAAA,EAAe,KAAA,EAAe,MAAA,EAAyB;AACvF,EAAA,MAAM,KAAA,GAAQ,SAAA,CAAa,IAAA,EAAM,KAAK,CAAA;AAEtC,EAAA,OAAO;AAAA,IACL,KAAA;AAAA,IACA,OAAA,EAAS,WAAA,CAAY,IAAA,EAAM,SAAS,CAAA;AAAA,IACpC,UAAA,EAAY,SAAS,KAAA,CAAM,MAAA;AAAA,IAC3B,GAAA,EAAK;AAAA,GACP;AACF;AA+BO,IAAM,YAAN,MAA+C;AAAA,EAC3C,QAAA;AAAA,EACA,SAAA;AAAA,EAET,MAAA;AAAA,EACA,SAAA,GAAY,KAAA;AAAA,EACZ,YAAA,GAAe,CAAA;AAAA,EAEf,YAAY,OAAA,EAA8B;AACxC,IAAA,IAAA,CAAK,QAAA,GAAW,OAAA;AAChB,IAAA,IAAA,CAAK,SAAA,GAAY,QAAQ,QAAA,IAAY,GAAA;AACrC,IAAA,IAAA,CAAK,MAAA,GAAS,OAAA,CAAQ,KAAA,IAAS,EAAC;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,IAAA,GAAgC;AACpC,IAAA,IAAI,IAAA,CAAK,WAAW,OAAO,IAAA;AAC3B,IAAA,IAAI,IAAA,CAAK,QAAA,CAAS,MAAA,EAAQ,OAAA,EAAS,OAAO,IAAA;AAE1C,IAAA,IAAI,IAAA,CAAK,YAAA,IAAgB,IAAA,CAAK,SAAA,EAAW;AACvC,MAAA,IAAA,CAAK,SAAA,GAAY,IAAA;AACjB,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,MAAM,WAAW,IAAA,CAAK,MAAA;AACtB,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,QAAA,CAAS,KAAK,QAAQ,CAAA;AAC9C,IAAA,IAAA,CAAK,YAAA,IAAgB,CAAA;AAErB,IAAA,IAAA,CAAK,MAAA,GAAS,IAAA,CAAK,QAAA,CAAS,QAAA,EAAU,IAAI,CAAA;AAC1C,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,KAAA,GAAkD;AACvD,IAAA,WAAS;AACP,MAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,EAAK;AAC7B,MAAA,IAAI,CAAC,IAAA,EAAM;AACX,MAAA,MAAM,IAAA;AAAA,IACR;AAAA,EACF;AAAA;AAAA,EAGA,QAAQ,MAAA,CAAO,aAAa,CAAA,GAAwC;AAClE,IAAA,WAAA,MAAiB,IAAA,IAAQ,IAAA,CAAK,KAAA,EAAM,EAAG;AACrC,MAAA,KAAA,MAAW,IAAA,IAAQ,KAAK,KAAA,EAAO;AAC7B,QAAA,IAAI,IAAA,CAAK,QAAA,CAAS,MAAA,EAAQ,OAAA,EAAS;AACnC,QAAA,MAAM,IAAA;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,QAAQ,GAAA,EAA4B;AACxC,IAAA,MAAM,SAAc,EAAC;AAErB,IAAA,WAAA,MAAiB,QAAQ,IAAA,EAAM;AAC7B,MAAA,MAAA,CAAO,KAAK,IAAI,CAAA;AAChB,MAAA,IAAI,GAAA,KAAQ,MAAA,IAAa,MAAA,CAAO,MAAA,IAAU,GAAA,EAAK;AAAA,IACjD;AAEA,IAAA,OAAO,MAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,QAAA,CAAS,UAAqB,IAAA,EAA0B;AACtD,IAAA,IAAI,CAAC,IAAA,CAAK,OAAA,IAAW,IAAA,CAAK,KAAA,CAAM,WAAW,CAAA,EAAG;AAC5C,MAAA,IAAA,CAAK,SAAA,GAAY,IAAA;AACjB,MAAA,OAAO,QAAA;AAAA,IACT;AAEA,IAAA,IAAI,IAAA,CAAK,QAAA,CAAS,IAAA,KAAS,cAAA,CAAe,MAAA,EAAQ;AAChD,MAAA,MAAM,MAAA,GAAS,KAAK,UAAA,IAAc,MAAA;AAElC,MAAA,IAAI,CAAC,MAAA,IAAU,MAAA,KAAW,QAAA,CAAS,MAAA,EAAQ;AACzC,QAAA,IAAA,CAAK,SAAA,GAAY,IAAA;AACjB,QAAA,OAAO,QAAA;AAAA,MACT;AAEA,MAAA,OAAO,EAAE,MAAA,EAAO;AAAA,IAClB;AAEA,IAAA,IAAI,IAAA,CAAK,QAAA,CAAS,IAAA,KAAS,cAAA,CAAe,IAAA,EAAM;AAC9C,MAAA,OAAO,EAAE,IAAA,EAAA,CAAO,QAAA,CAAS,IAAA,IAAQ,KAAK,CAAA,EAAE;AAAA,IAC1C;AAEA,IAAA,OAAO,EAAE,QAAQ,IAAA,CAAK,UAAA,IAAA,CAAe,SAAS,MAAA,IAAU,CAAA,IAAK,IAAA,CAAK,KAAA,CAAM,MAAA,EAAO;AAAA,EACjF;AACF;;;ACzUO,IAAM,eAAN,MAAmB;AAAA;AAAA,EAEL,IAAA;AAAA,EAEnB,YAAY,IAAA,EAAkB;AAC5B,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUU,eAAe,OAAA,EAA8D;AACrF,IAAA,IAAI,CAAC,OAAA,EAAS,OAAO,EAAC;AAEtB,IAAA,MAAM,MAAA,GAAkC;AAAA,MACtC,GAAI,QAAQ,MAAA,KAAW,MAAA,GAAY,EAAE,MAAA,EAAQ,OAAA,CAAQ,MAAA,EAAO,GAAI,EAAC;AAAA,MACjE,GAAI,QAAQ,OAAA,KAAY,MAAA,GAAY,EAAE,OAAA,EAAS,OAAA,CAAQ,OAAA,EAAQ,GAAI,EAAC;AAAA,MACpE,GAAI,QAAQ,OAAA,KAAY,MAAA,GAAY,EAAE,OAAA,EAAS,OAAA,CAAQ,OAAA,EAAQ,GAAI,EAAC;AAAA,MACpE,GAAI,QAAQ,KAAA,KAAU,MAAA,GAAY,EAAE,KAAA,EAAO,OAAA,CAAQ,KAAA,EAAM,GAAI;AAAC,KAChE;AAEA,IAAA,MAAM,UAAA,GAAa,KAAK,IAAA,CAAK,gBAAA;AAC7B,IAAA,IAAI,UAAA,CAAW,IAAA,KAAS,CAAA,EAAG,OAAO,MAAA;AAElC,IAAA,MAAM,MAAA,GAAS,OAAA;AACf,IAAA,MAAM,MAAA,GAAS,MAAA;AACf,IAAA,KAAA,MAAW,OAAO,UAAA,EAAY;AAC5B,MAAA,MAAM,KAAA,GAAQ,OAAO,GAAG,CAAA;AACxB,MAAA,IAAI,KAAA,KAAU,MAAA,EAAW,MAAA,CAAO,GAAG,CAAA,GAAI,KAAA;AAAA,IACzC;AAEA,IAAA,OAAO,MAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASU,QAAA,CACR,IAAA,EACA,IAAA,EACA,OAAA,EACc;AACd,IAAA,OAAO,IAAI,SAAA,CAAa;AAAA,MACtB,IAAA;AAAA,MACA,IAAA;AAAA,MACA,GAAI,SAAS,QAAA,KAAa,MAAA,GAAY,EAAE,QAAA,EAAU,OAAA,CAAQ,QAAA,EAAS,GAAI,EAAC;AAAA,MACxE,GAAI,SAAS,MAAA,KAAW,MAAA,GAAY,EAAE,MAAA,EAAQ,OAAA,CAAQ,MAAA,EAAO,GAAI,EAAC;AAAA,MAClE,GAAI,SAAS,KAAA,KAAU,MAAA,GAAY,EAAE,KAAA,EAAO,OAAA,CAAQ,KAAA,EAAM,GAAI;AAAC,KAChE,CAAA;AAAA,EACH;AACF,CAAA;AAGO,SAAS,aAAA,CAAc,OAAoB,KAAA,EAA+B;AAC/E,EAAA,OAAO;AAAA,IACL,GAAG,KAAA;AAAA,IACH,GAAI,MAAM,MAAA,KAAW,MAAA,GAAY,EAAE,MAAA,EAAQ,KAAA,CAAM,MAAA,EAAO,GAAI,EAAC;AAAA,IAC7D,GAAI,MAAM,IAAA,KAAS,MAAA,GAAY,EAAE,IAAA,EAAM,KAAA,CAAM,IAAA,EAAK,GAAI,EAAC;AAAA,IACvD,GAAI,MAAM,MAAA,KAAW,MAAA,GAAY,EAAE,MAAA,EAAQ,KAAA,CAAM,MAAA,EAAO,GAAI;AAAC,GAC/D;AACF;;;AC9BO,IAAM,aAAA,GAAgB,OAAO,MAAA,CAAO;AAAA,EACzC,MAAA,EAAQ,QAAA;AAAA,EACR,MAAA,EAAQ;AACV,CAAU;AAIH,IAAM,YAAA,GAAe,OAAO,MAAA,CAAO;AAAA,EACxC,aAAA,EAAe,eAAA;AAAA,EACf,WAAA,EAAa;AACf,CAAU;AAkBH,IAAM,YAAA,GAAN,cAA2B,YAAA,CAAa;AAAA,EACpC,KAAA;AAAA,EAET,WAAA,CAAY,MAAkB,IAAA,EAA6B;AACzD,IAAA,KAAA,CAAM,IAAI,CAAA;AACV,IAAA,IAAA,CAAK,QAAQ,IAAA,CAAK,IAAA;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,MAAA,CAAO,WAAA,EAAiC,OAAA,GAA0B,EAAC,EAAoB;AAC3F,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ;AAAA,MACnC,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,sBAAA;AAAA,MACN,IAAA,EAAM,WAAA;AAAA,MACN,QAAA,EAAU,IAAA;AAAA,MACV,eAAA,EAAiB,IAAA;AAAA,MACjB,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAED,IAAA,MAAM,SAAA,GAAY,UAAA,CAAW,IAAA,EAAM,WAAW,CAAA;AAC9C,IAAA,IAAI,CAAC,SAAA,EAAW;AACd,MAAA,MAAM,IAAI,eAAe,wLAA4C,CAAA;AAAA,IACvE;AAEA,IAAA,OAAO,SAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,MAAA,CACJ,WAAA,EACA,OAAA,GAA0B,EAAC,EACJ;AACvB,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ;AAAA,MACnC,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,sBAAA;AAAA,MACN,IAAA,EAAM,WAAA;AAAA,MACN,QAAA,EAAU,IAAA;AAAA,MACV,eAAA,EAAiB,IAAA;AAAA,MACjB,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAED,IAAA,MAAM,WAAA,GAAc,UAAA,CAAW,IAAA,EAAM,aAAa,CAAA;AAElD,IAAA,IAAI,WAAA,EAAa;AACf,MAAA,MAAM,IAAA,CAAK,KAAA,CAAM,cAAA,CAAe,WAAW,CAAA;AAC3C,MAAA,OAAO,EAAE,MAAA,EAAQ,YAAA,CAAa,aAAA,EAAe,WAAA,EAAY;AAAA,IAC3D;AAEA,IAAA,OAAO,EAAE,QAAQ,YAAA,CAAa,WAAA,EAAa,WAAW,UAAA,CAAW,IAAA,EAAM,WAAW,CAAA,EAAE;AAAA,EACtF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,SAAA,CACJ,KAAA,EACA,OAAA,GAA0B,EAAC,EACV;AACjB,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ;AAAA,MACnC,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,yBAAA;AAAA,MACN,IAAA,EAAM,KAAA;AAAA,MACN,QAAA,EAAU,IAAA;AAAA,MACV,eAAA,EAAiB,IAAA;AAAA,MACjB,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAED,IAAA,MAAM,WAAA,GAAc,UAAA,CAAW,IAAA,EAAM,aAAa,CAAA;AAClD,IAAA,IAAI,CAAC,WAAA,EAAa;AAChB,MAAA,MAAM,IAAI,eAAe,2OAAuD,CAAA;AAAA,IAClF;AAEA,IAAA,MAAM,IAAA,CAAK,KAAA,CAAM,cAAA,CAAe,WAAW,CAAA;AAC3C,IAAA,OAAO,WAAA;AAAA,EACT;AAAA;AAAA,EAGA,SAAA,CACE,KAAA,EACA,OAAA,GAA0B,EAAC,EACZ;AACf,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAc;AAAA,MAC7B,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,yBAAA;AAAA,MACN,IAAA,EAAM,KAAA;AAAA,MACN,QAAA,EAAU,IAAA;AAAA,MACV,eAAA,EAAiB,IAAA;AAAA,MACjB,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoBA,MAAM,aAAA,CACJ,KAAA,EACA,OAAA,GAA0B,EAAC,EACV;AACjB,IAAA,MAAM,EAAE,MAAA,EAAQ,GAAG,WAAA,EAAY,GAAI,KAAA;AACnC,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,MAAA,CAAO,aAAa,OAAO,CAAA;AAErD,IAAA,IAAI,MAAA,CAAO,MAAA,KAAW,YAAA,CAAa,aAAA,SAAsB,MAAA,CAAO,WAAA;AAEhE,IAAA,IAAI,CAAC,OAAO,SAAA,EAAW;AACrB,MAAA,MAAM,IAAI,cAAA;AAAA,QACR;AAAA,OACF;AAAA,IACF;AAEA,IAAA,MAAM,GAAA,GAAM,MAAM,MAAA,EAAO;AAIzB,IAAA,OAAO,IAAA,CAAK,SAAA;AAAA,MACV;AAAA,QACE,OAAO,WAAA,CAAY,KAAA;AAAA,QACnB,UAAU,WAAA,CAAY,QAAA;AAAA,QACtB,GAAA;AAAA,QACA,WAAW,MAAA,CAAO;AAAA,OACpB;AAAA,MACA;AAAA,KACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAA,GAA2B;AACzB,IAAA,OAAO,IAAA,CAAK,MAAM,OAAA,EAAQ;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBA,iBAAA,GAAsC;AACpC,IAAA,OAAO,IAAA,CAAK,MAAM,iBAAA,EAAkB;AAAA,EACtC;AAAA;AAAA,EAGA,MAAM,MAAA,CAAO,OAAA,GAA0B,EAAC,EAAkB;AACxD,IAAA,MAAM,IAAA,CAAK,KAAK,OAAA,CAAc;AAAA,MAC5B,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,qBAAA;AAAA,MACN,eAAA,EAAiB,IAAA;AAAA,MACjB,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAED,IAAA,MAAM,IAAA,CAAK,MAAM,KAAA,EAAM;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,SAAA,CAAU,OAAA,GAA0B,EAAC,EAAkB;AAC3D,IAAA,MAAM,IAAA,CAAK,oBAAoB,OAAO,CAAA;AACtC,IAAA,MAAM,IAAA,CAAK,OAAO,OAAO,CAAA;AAAA,EAC3B;AAAA;AAAA,EAGA,OAAA,GAAyB;AACvB,IAAA,OAAO,IAAA,CAAK,MAAM,KAAA,EAAM;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,cAAA,CAAe,KAAA,EAA4B,OAAA,GAA0B,EAAC,EAAoB;AAC9F,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ;AAAA,MACnC,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,8BAAA;AAAA,MACN,IAAA,EAAM,KAAA;AAAA,MACN,QAAA,EAAU,IAAA;AAAA,MACV,eAAA,EAAiB,IAAA;AAAA,MACjB,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAED,IAAA,MAAM,SAAA,GAAY,UAAA,CAAW,IAAA,EAAM,WAAW,CAAA;AAC9C,IAAA,IAAI,CAAC,SAAA,EAAW;AACd,MAAA,MAAM,IAAI,eAAe,0OAAsD,CAAA;AAAA,IACjF;AAEA,IAAA,OAAO,SAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,aAAA,CAAc,KAAA,EAA2B,OAAA,GAA0B,EAAC,EAAkB;AACpF,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAc;AAAA,MAC7B,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,6BAAA;AAAA,MACN,IAAA,EAAM,KAAA;AAAA,MACN,QAAA,EAAU,IAAA;AAAA,MACV,eAAA,EAAiB,IAAA;AAAA,MACjB,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBA,MAAM,oBAAA,CACJ,KAAA,EAIA,OAAA,GAA0B,EAAC,EACZ;AACf,IAAA,MAAM,SAAA,GAAY,MAAM,IAAA,CAAK,cAAA;AAAA,MAC3B,EAAE,KAAA,EAAO,KAAA,CAAM,KAAA,EAAO,cAAA,EAAgB,MAAM,cAAA,EAAe;AAAA,MAC3D;AAAA,KACF;AAEA,IAAA,MAAM,GAAA,GAAM,MAAM,KAAA,CAAM,MAAA,EAAO;AAE/B,IAAA,MAAM,IAAA,CAAK,aAAA;AAAA,MACT,EAAE,OAAO,KAAA,CAAM,KAAA,EAAO,KAAK,SAAA,EAAW,WAAA,EAAa,MAAM,WAAA,EAAY;AAAA,MACrE;AAAA,KACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,cAAA,CACE,KAAA,EACA,OAAA,GAA0B,EAAC,EACZ;AACf,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAc;AAAA,MAC7B,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,8BAAA;AAAA;AAAA;AAAA,MAGN,MAAM,EAAE,GAAG,KAAA,EAAO,eAAA,EAAiB,MAAM,WAAA,EAAY;AAAA,MACrD,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,SAAS,QAAA,EAAiC;AACxC,IAAA,OAAO,QAAQ,IAAA,CAAK,IAAA,CAAK,OAAA,EAAS,CAAA,mBAAA,EAAsB,QAAQ,CAAA,CAAE,CAAA;AAAA,EACpE;AAAA;AAAA,EAGA,MAAM,QAAA,CAAS,OAAA,GAA0B,EAAC,EAAuB;AAC/D,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ;AAAA,MACnC,MAAA,EAAQ,KAAA;AAAA,MACR,IAAA,EAAM,uBAAA;AAAA,MACN,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAED,IAAA,OAAO,SAAA,CAAmB,MAAM,UAAU,CAAA;AAAA,EAC5C;AAAA;AAAA,EAGA,aAAA,CAAc,SAAA,EAAmB,OAAA,GAA0B,EAAC,EAAkB;AAC5E,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAc;AAAA,MAC7B,MAAA,EAAQ,QAAA;AAAA,MACR,IAAA,EAAM,CAAA,sBAAA,EAAyB,kBAAA,CAAmB,SAAS,CAAC,CAAA,CAAA;AAAA,MAC5D,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,mBAAA,CAAoB,OAAA,GAA0B,EAAC,EAAkB;AAC/D,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAc;AAAA,MAC7B,MAAA,EAAQ,QAAA;AAAA,MACR,IAAA,EAAM,uBAAA;AAAA,MACN,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AACF,CAAA;;;ACpZO,IAAM,gBAAA,GAAN,cAA+B,YAAA,CAAa;AAAA,EACxC,YAAA;AAAA,EAET,WAAA,CACE,MACA,IAAA,EACA;AACA,IAAA,KAAA,CAAM,IAAI,CAAA;AACV,IAAA,IAAA,CAAK,eAAe,IAAA,CAAK,WAAA;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,OAAA,CAAQ,SAAA,EAAmB,MAAA,GAAwB,EAAC,EAA2B;AACnF,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ;AAAA,MACnC,MAAA,EAAQ,KAAA;AAAA,MACR,IAAA,EAAM,CAAA,cAAA,EAAiB,iBAAA,CAAkB,SAAA,EAAW,WAAW,CAAC,CAAA,QAAA,CAAA;AAAA,MAChE,OAAO,EAAE,KAAA,EAAO,OAAO,KAAA,EAAO,IAAA,EAAM,OAAO,IAAA,EAAK;AAAA,MAChD,GAAG,IAAA,CAAK,cAAA,CAAe,MAAM;AAAA,KAC9B,CAAA;AAED,IAAA,OAAO,aAAA,CAAuB,MAAM,SAAS,CAAA;AAAA,EAC/C;AAAA;AAAA,EAGA,cAAA,CAAe,SAAA,EAAmB,MAAA,GAAwB,EAAC,EAAuB;AAChF,IAAA,MAAM,IAAA,GAAO,CAAA,cAAA,EAAiB,iBAAA,CAAkB,SAAA,EAAW,WAAW,CAAC,CAAA,QAAA,CAAA;AAEvE,IAAA,OAAO,IAAA,CAAK,QAAA;AAAA,MACV,cAAA,CAAe,IAAA;AAAA,MACf,OAAO,KAAA,KAAU;AACf,QAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ;AAAA,UACnC,MAAA,EAAQ,KAAA;AAAA,UACR,IAAA;AAAA,UACA,OAAO,aAAA,CAAc,EAAE,OAAO,MAAA,CAAO,KAAA,IAAS,KAAK,CAAA;AAAA,UACnD,GAAG,IAAA,CAAK,cAAA,CAAe,MAAM;AAAA,SAC9B,CAAA;AACD,QAAA,OAAO,aAAA,CAAuB,MAAM,SAAS,CAAA;AAAA,MAC/C,CAAA;AAAA,MACA,EAAE,GAAG,MAAA,EAAQ,GAAI,MAAA,CAAO,SAAS,MAAA,GAAY,EAAE,KAAA,EAAO,EAAE,MAAM,MAAA,CAAO,IAAA,EAAK,EAAE,GAAI,EAAC;AAAG,KACtF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,KAAA,CACJ,SAAA,EACA,KAAA,EACA,OAAA,GAA0B,EAAC,EACT;AAClB,IAAA,MAAM,IAAA,GAAO,cAAA,CAAe,OAAO,KAAA,KAAU,QAAA,GAAW,EAAE,OAAA,EAAS,KAAA,EAAM,GAAI,KAAA,EAAO,IAAI,CAAA;AAExF,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,aAAA,IAAiB,EAAC;AACxC,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,IAAS,EAAC;AAC7B,IAAA,MAAM,aAAA,GACJ,KAAA,CAAM,MAAA,GAAS,CAAA,GAAI,CAAC,GAAG,QAAA,EAAU,GAAI,MAAM,IAAA,CAAK,YAAA,CAAa,KAAA,EAAO,OAAO,CAAE,CAAA,GAAI,QAAA;AAEnF,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAiB;AAAA,MAChC,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,CAAA,cAAA,EAAiB,iBAAA,CAAkB,SAAA,EAAW,WAAW,CAAC,CAAA,QAAA,CAAA;AAAA,MAChE,IAAA,EAAM;AAAA,QACJ,OAAA,EAAS,KAAK,OAAA,IAAW,EAAA;AAAA,QACzB,aAAA;AAAA,QACA,GAAI,KAAK,aAAA,GAAgB,EAAE,eAAe,IAAA,CAAK,aAAA,KAAkB;AAAC,OACpE;AAAA,MACA,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,MAAA,CAAO,SAAA,EAAmB,OAAA,EAAiB,OAAA,GAA0B,EAAC,EAAqB;AACzF,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAiB;AAAA,MAChC,MAAA,EAAQ,OAAA;AAAA,MACR,IAAA,EAAM,CAAA,cAAA,EAAiB,iBAAA,CAAkB,SAAA,EAAW,WAAW,CAAC,CAAA,CAAA;AAAA,MAChE,IAAA,EAAM,EAAE,OAAA,EAAQ;AAAA,MAChB,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,MAAA,CAAO,SAAA,EAAmB,OAAA,GAA0B,EAAC,EAAkB;AACrE,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAc;AAAA,MAC7B,MAAA,EAAQ,QAAA;AAAA,MACR,IAAA,EAAM,CAAA,cAAA,EAAiB,iBAAA,CAAkB,SAAA,EAAW,WAAW,CAAC,CAAA,CAAA;AAAA,MAChE,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,OAAA,CAAQ,SAAA,EAAmB,OAAA,GAA0B,EAAC,EAAqB;AACzE,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAiB;AAAA,MAChC,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,CAAA,cAAA,EAAiB,iBAAA,CAAkB,SAAA,EAAW,WAAW,CAAC,CAAA,QAAA,CAAA;AAAA,MAChE,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,IAAA,CAAK,SAAA,EAAmB,OAAA,GAA0B,EAAC,EAAwB;AACzE,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAoB;AAAA,MACnC,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,CAAA,cAAA,EAAiB,iBAAA,CAAkB,SAAA,EAAW,WAAW,CAAC,CAAA,KAAA,CAAA;AAAA,MAChE,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,MAAA,CAAO,SAAA,EAAmB,OAAA,GAA0B,EAAC,EAAwB;AAC3E,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAoB;AAAA,MACnC,MAAA,EAAQ,QAAA;AAAA,MACR,IAAA,EAAM,CAAA,cAAA,EAAiB,iBAAA,CAAkB,SAAA,EAAW,WAAW,CAAC,CAAA,KAAA,CAAA;AAAA,MAChE,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AACF,CAAA;;;AC/IO,IAAM,gBAAA,GAAmB,OAAO,MAAA,CAAO;AAAA,EAC5C,YAAA;AAAA,EACA,WAAA;AAAA,EACA,WAAA;AAAA,EACA,YAAA;AAAA,EACA,YAAA;AAAA,EACA,YAAA;AAAA,EACA;AACF,CAAU;AAIH,IAAM,gBAAA,GAAmB,OAAO,MAAA,CAAO;AAAA,EAC5C,WAAA;AAAA,EACA,YAAA;AAAA,EACA;AACF,CAAU;AAIH,IAAM,gBAAA,GAAmB,MAAA,CAAO,MAAA,CAAO,CAAC,WAAW,CAAU;AAI7D,IAAM,kBAAA,GAAqB,OAAO,MAAA,CAAO;AAAA,EAC9C,GAAG,gBAAA;AAAA,EACH,GAAG,gBAAA;AAAA,EACH,GAAG;AACL,CAAU;AASV,IAAM,iBAAA,GAAsD,OAAO,MAAA,CAAO;AAAA,EACxE,GAAA,EAAK,YAAA;AAAA,EACL,IAAA,EAAM,YAAA;AAAA,EACN,IAAA,EAAM,YAAA;AAAA,EACN,GAAA,EAAK,WAAA;AAAA,EACL,GAAA,EAAK,WAAA;AAAA,EACL,IAAA,EAAM,YAAA;AAAA,EACN,IAAA,EAAM,YAAA;AAAA,EACN,IAAA,EAAM,YAAA;AAAA,EACN,IAAA,EAAM,YAAA;AAAA,EACN,GAAA,EAAK,WAAA;AAAA,EACL,GAAA,EAAK,WAAA;AAAA,EACL,IAAA,EAAM,YAAA;AAAA,EACN,GAAA,EAAK,iBAAA;AAAA,EACL,EAAA,EAAI,iBAAA;AAAA,EACJ,GAAA,EAAK,WAAA;AAAA,EACL,GAAA,EAAK,WAAA;AAAA,EACL,IAAA,EAAM;AACR,CAAC,CAAA;AAGM,SAAS,iBAAiB,QAAA,EAAsC;AACrE,EAAA,MAAM,GAAA,GAAM,QAAA,CAAS,WAAA,CAAY,GAAG,CAAA;AACpC,EAAA,IAAI,GAAA,GAAM,GAAG,OAAO,MAAA;AAEpB,EAAA,OAAO,kBAAkB,QAAA,CAAS,KAAA,CAAM,MAAM,CAAC,CAAA,CAAE,aAAa,CAAA;AAChE;AAGO,SAAS,cAAc,QAAA,EAA+C;AAC3E,EAAA,OAAQ,kBAAA,CAAyC,QAAA,CAAS,QAAA,CAAS,WAAA,EAAa,CAAA;AAClF;AAUO,SAAS,iBAAA,CAAkB,UAA8B,QAAA,EAAyB;AACvF,EAAA,IAAI,CAAC,QAAA,EAAU;AACb,IAAA,MAAM,IAAI,cAAA;AAAA,MACR,CAAA,sKAAA,EAAkC,QAAA,GAAW,CAAA,KAAA,EAAK,QAAQ,SAAM,EAAE,CAAA,0HAAA;AAAA,KAEpE;AAAA,EACF;AAEA,EAAA,IAAI,CAAC,aAAA,CAAc,QAAQ,CAAA,EAAG;AAC5B,IAAA,MAAM,IAAI,cAAA;AAAA,MACR,0BAAQ,QAAQ,CAAA,6NAAA,EAA8C,kBAAA,CAAmB,IAAA,CAAK,IAAI,CAAC,CAAA,CAAA;AAAA,KAC7F;AAAA,EACF;AACF;;;ACzDO,IAAM,sBAAA,GAAyB,GAAA;AAiB/B,IAAM,aAAA,GAAN,cAA4B,YAAA,CAAa;AAAA,EAC9C,SAAA;AAAA,EAEA,WAAA,CAAY,IAAA,EAAkB,IAAA,GAAkC,EAAC,EAAG;AAClE,IAAA,KAAA,CAAM,IAAI,CAAA;AACV,IAAA,IAAA,CAAK,YAAY,IAAA,CAAK,QAAA;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,cAAc,QAAA,EAA4B;AACxC,IAAA,IAAA,CAAK,SAAA,GAAY,QAAA;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,MAAM,MAAA,CAAO,KAAA,EAAkB,OAAA,GAAyB,EAAC,EAA0B;AACjF,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,QAAA,CAAS,OAAO,OAAO,CAAA;AAEnD,IAAA,MAAM,IAAA,GAAO,IAAI,QAAA,EAAS;AAC1B,IAAA,IAAA,CAAK,GAAA,CAAI,MAAA,EAAQ,QAAA,CAAS,IAAA,EAAM,SAAS,QAAQ,CAAA;AAEjD,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAsB;AAAA,MACrC,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,mBAAA;AAAA,MACN,IAAA,EAAM,IAAA;AAAA,MACN,OAAA,EAAS,QAAQ,OAAA,IAAW,sBAAA;AAAA,MAC5B,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,UAAA,CAAW,KAAA,EAAoB,OAAA,GAAyB,EAAC,EAAsB;AACnF,IAAA,MAAM,MAAgB,EAAC;AAEvB,IAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,MAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,MAAA,CAAO,MAAM,OAAO,CAAA;AAChD,MAAA,GAAA,CAAI,IAAA,CAAK,SAAS,EAAE,CAAA;AAAA,IACtB;AAEA,IAAA,OAAO,GAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,GAAA,CAAI,MAAA,EAAgB,OAAA,GAA0B,EAAC,EAAqB;AAClE,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAQ;AAAA,MACvB,MAAA,EAAQ,KAAA;AAAA,MACR,IAAA,EAAM,CAAA,WAAA,EAAc,iBAAA,CAAkB,MAAA,EAAQ,QAAQ,CAAC,CAAA,CAAA;AAAA,MACvD,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,MAAA,CAAO,MAAA,EAAgB,OAAA,GAA0B,EAAC,EAAkB;AAClE,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAc;AAAA,MAC7B,MAAA,EAAQ,QAAA;AAAA,MACR,IAAA,EAAM,CAAA,WAAA,EAAc,iBAAA,CAAkB,MAAA,EAAQ,QAAQ,CAAC,CAAA,CAAA;AAAA,MACvD,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,MAAM,QAAA,CAAS,KAAA,EAAkB,OAAA,EAA+C;AAC9E,IAAA,MAAM,EAAE,MAAM,QAAA,EAAU,WAAA,KAAgB,MAAM,IAAA,CAAK,UAAA,CAAW,KAAA,EAAO,OAAO,CAAA;AAE5E,IAAA,MAAM,IAAA,GACJ,iBAAiB,MAAA,CAAO,IAAI,IAAI,IAAA,CAAK,IAAA,GAAO,MAAA,KAAc,gBAAA,CAAiB,QAAQ,CAAA,CAAA;AAErF,IAAA,IAAI,QAAQ,YAAA,KAAiB,KAAA,EAAO,iBAAA,CAAkB,IAAA,IAAQ,QAAW,QAAQ,CAAA;AAEjF,IAAA,MAAM,OACJ,MAAA,CAAO,IAAI,MAAM,CAAC,IAAA,IAAQ,KAAK,IAAA,KAAS,IAAA,CAAA,GACpC,OACA,IAAI,IAAA,CAAK,CAAC,IAAgB,CAAA,EAAG,EAAE,IAAA,EAAM,IAAA,IAAQ,IAAI,CAAA;AAEvD,IAAA,OAAO,EAAE,MAAM,QAAA,EAAS;AAAA,EAC1B;AAAA,EAEA,MAAM,UAAA,CACJ,KAAA,EACA,OAAA,EAC4F;AAC5F,IAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,MAAA,IAAI,CAAC,KAAK,SAAA,EAAW;AACnB,QAAA,MAAM,IAAI,cAAA;AAAA,UACR,8FAAqB,KAAK,CAAA,gXAAA;AAAA,SAE5B;AAAA,MACF;AAEA,MAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,SAAA,CAAU,KAAK,CAAA;AACvC,MAAA,OAAO;AAAA,QACL,MAAM,IAAA,CAAK,IAAA;AAAA,QACX,QAAA,EAAU,OAAA,CAAQ,QAAA,IAAY,IAAA,CAAK,QAAA;AAAA,QACnC,GAAI,QAAQ,WAAA,GAAc,EAAE,aAAa,OAAA,CAAQ,WAAA,KAAgB;AAAC,OACpE;AAAA,IACF;AAEA,IAAA,IAAI,KAAA,YAAiB,eAAe,WAAA,CAAY,MAAA,CAAO,KAAK,CAAA,IAAK,MAAA,CAAO,KAAK,CAAA,EAAG;AAC9E,MAAA,MAAM,YAAA,GAAe,MAAA,CAAO,KAAK,CAAA,GAC7B,KAAA,CAAM,IAAA,GACL,OAAA,CAAQ,QAAA,IAAY,IAAA,CAAK,aAAA,CAAc,OAAA,CAAQ,WAAW,CAAA;AAE/D,MAAA,OAAO;AAAA,QACL,IAAA,EAAM,KAAA;AAAA,QACN,QAAA,EAAU,QAAQ,QAAA,IAAY,YAAA;AAAA,QAC9B,GAAI,QAAQ,WAAA,GAAc,EAAE,aAAa,OAAA,CAAQ,WAAA,KAAgB;AAAC,OACpE;AAAA,IACF;AAEA,IAAA,MAAM,WAAA,GAAc,KAAA,CAAM,WAAA,IAAe,OAAA,CAAQ,WAAA;AAEjD,IAAA,OAAO;AAAA,MACL,MAAM,KAAA,CAAM,IAAA;AAAA,MACZ,UAAU,KAAA,CAAM,QAAA,IAAY,QAAQ,QAAA,IAAY,IAAA,CAAK,cAAc,WAAW,CAAA;AAAA,MAC9E,GAAI,WAAA,GAAc,EAAE,WAAA,KAAgB;AAAC,KACvC;AAAA,EACF;AAAA;AAAA,EAGA,cAAc,WAAA,EAAyC;AACrD,IAAA,MAAM,SAAA,GAAY,WAAA,EAAa,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,CAAA,EAAG,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,CAAA;AAC1D,IAAA,OAAO,SAAA,GAAY,CAAA,KAAA,EAAQ,SAAS,CAAA,CAAA,GAAK,MAAA;AAAA,EAC3C;AACF,CAAA;;;AC3KO,IAAM,gBAAA,GAAN,cAA+B,YAAA,CAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMjD,MAAM,MAAA,CACJ,KAAA,EACA,MAAA,GAA8C,EAAC,EAC3B;AACpB,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ;AAAA,MACnC,MAAA,EAAQ,KAAA;AAAA,MACR,IAAA,EAAM,eAAA;AAAA,MACN,OAAO,EAAE,CAAA,EAAG,KAAA,EAAO,KAAA,EAAO,OAAO,KAAA,EAAM;AAAA,MACvC,GAAG,IAAA,CAAK,cAAA,CAAe,MAAM;AAAA,KAC9B,CAAA;AAED,IAAA,OAAO,SAAA,CAAmB,MAAM,UAAU,CAAA;AAAA,EAC5C;AAAA;AAAA,EAGA,MAAM,QAAA,CAAS,MAAA,GAA8C,EAAC,EAAuB;AACnF,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ;AAAA,MACnC,MAAA,EAAQ,KAAA;AAAA,MACR,IAAA,EAAM,wBAAA;AAAA,MACN,KAAA,EAAO,EAAE,KAAA,EAAO,MAAA,CAAO,KAAA,EAAM;AAAA,MAC7B,GAAG,IAAA,CAAK,cAAA,CAAe,MAAM;AAAA,KAC9B,CAAA;AAED,IAAA,OAAO,SAAA,CAAmB,MAAM,UAAU,CAAA;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,KAAA,CAAM,GAAA,EAAa,MAAA,GAA6B,EAAC,EAAwB;AAC7E,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ;AAAA,MACnC,MAAA,EAAQ,KAAA;AAAA,MACR,IAAA,EAAM,CAAA,cAAA,EAAiB,iBAAA,CAAkB,GAAA,EAAK,KAAK,CAAC,CAAA,MAAA,CAAA;AAAA,MACpD,OAAO,EAAE,KAAA,EAAO,OAAO,KAAA,EAAO,MAAA,EAAQ,OAAO,MAAA,EAAO;AAAA,MACpD,GAAG,IAAA,CAAK,cAAA,CAAe,MAAM;AAAA,KAC9B,CAAA;AAED,IAAA,OAAO,cAAA,CAAqB,MAAM,OAAO,CAAA;AAAA,EAC3C;AAAA;AAAA,EAGA,YAAA,CAAa,GAAA,EAAa,MAAA,GAA6B,EAAC,EAAoB;AAC1E,IAAA,MAAM,IAAA,GAAO,CAAA,cAAA,EAAiB,iBAAA,CAAkB,GAAA,EAAK,KAAK,CAAC,CAAA,MAAA,CAAA;AAE3D,IAAA,OAAO,IAAA,CAAK,QAAA;AAAA,MACV,cAAA,CAAe,MAAA;AAAA,MACf,OAAO,KAAA,KAAU;AACf,QAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ;AAAA,UACnC,MAAA,EAAQ,KAAA;AAAA,UACR,IAAA;AAAA,UACA,OAAO,aAAA,CAAc,EAAE,OAAO,MAAA,CAAO,KAAA,IAAS,KAAK,CAAA;AAAA,UACnD,GAAG,IAAA,CAAK,cAAA,CAAe,MAAM;AAAA,SAC9B,CAAA;AACD,QAAA,OAAO,cAAA,CAAqB,MAAM,OAAO,CAAA;AAAA,MAC3C,CAAA;AAAA,MACA,EAAE,GAAG,MAAA,EAAQ,GAAI,OAAO,MAAA,GAAS,EAAE,KAAA,EAAO,EAAE,QAAQ,MAAA,CAAO,MAAA,EAAO,EAAE,GAAI,EAAC;AAAG,KAC9E;AAAA,EACF;AACF,CAAA;AAOO,IAAM,cAAA,GAAN,cAA6B,YAAA,CAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAS/C,MAAM,GAAA,CAAI,KAAA,EAAe,OAAA,GAA0B,EAAC,EAA0B;AAC5E,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ;AAAA,MACnC,MAAA,EAAQ,KAAA;AAAA,MACR,IAAA,EAAM,aAAA;AAAA,MACN,KAAA,EAAO,EAAE,CAAA,EAAG,KAAA,EAAM;AAAA,MAClB,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAED,IAAA,OAAO;AAAA,MACL,KAAA,EAAO,SAAA,CAAuB,IAAA,EAAM,OAAO,CAAA;AAAA,MAC3C,QAAA,EAAU,SAAA,CAAmB,IAAA,EAAM,UAAU;AAAA,KAC/C;AAAA,EACF;AACF,CAAA;AAOO,IAAM,eAAA,GAAN,cAA8B,YAAA,CAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAahD,MAAA,CAAO,KAAA,EAAoB,OAAA,GAA0B,EAAC,EAAoB;AACxE,IAAA,MAAM,IAAA,GAAO,cAAc,KAAK,CAAA;AAEhC,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAgB;AAAA,MAC/B,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,cAAA;AAAA,MACN,IAAA,EAAM,IAAA;AAAA,MACN,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AACF,CAAA;AAOO,IAAM,oBAAA,GAAN,cAAmC,YAAA,CAAa;AAAA;AAAA,EAErD,MAAA,CAAO,OAAA,GAA0B,EAAC,EAAgC;AAChE,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAA4B;AAAA,MAC3C,MAAA,EAAQ,KAAA;AAAA,MACR,IAAA,EAAM,0BAAA;AAAA,MACN,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,MAAA,CAAO,QAAA,EAAkB,OAAA,GAA0B,EAAC,EAAqB;AACvE,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAQ;AAAA,MACvB,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,0BAAA;AAAA,MACN,IAAA,EAAM,EAAE,QAAA,EAAS;AAAA,MACjB,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AACF,CAAA;AAOO,IAAM,oBAAA,GAAN,cAAmC,YAAA,CAAa;AAAA;AAAA,EAErD,MAAA,CAAO,OAAA,GAA0B,EAAC,EAA0B;AAC1D,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAsB;AAAA,MACrC,MAAA,EAAQ,KAAA;AAAA;AAAA,MAER,IAAA,EAAM,uBAAA;AAAA,MACN,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,GAAA,CAAI,OAAA,GAA0B,EAAC,EAAqB;AAClD,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAQ;AAAA,MACvB,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,0BAAA;AAAA,MACN,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,cAAA,CAAe,OAAA,EAAkB,OAAA,GAA0B,EAAC,EAAqB;AAC/E,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAQ;AAAA,MACvB,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,mCAAA;AAAA,MACN,IAAA,EAAM,EAAE,OAAA,EAAQ;AAAA,MAChB,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,QAAA,CAAS,OAAA,GAA0B,EAAC,EAAqB;AACvD,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAQ;AAAA,MACvB,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,gCAAA;AAAA,MACN,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,MAAM,OAAA,CAAQ,OAAA,GAA0B,EAAC,EAA6B;AACpE,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ;AAAA,MACnC,MAAA,EAAQ,KAAA;AAAA,MACR,IAAA,EAAM,8BAAA;AAAA,MACN,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAED,IAAA,OAAO,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA,GAAK,OAA2B,EAAC;AAAA,EAC5D;AAAA;AAAA,EAGA,gBAAA,CAAiB,QAAA,EAAkB,OAAA,GAA0B,EAAC,EAAqB;AACjF,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAQ;AAAA,MACvB,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,CAAA,6BAAA,EAAgC,iBAAA,CAAkB,QAAA,EAAU,UAAU,CAAC,CAAA,QAAA,CAAA;AAAA,MAC7E,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,YAAA,CAAa,QAAA,EAAkB,OAAA,GAA0B,EAAC,EAAkB;AAC1E,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAc;AAAA,MAC7B,MAAA,EAAQ,QAAA;AAAA,MACR,IAAA,EAAM,CAAA,6BAAA,EAAgC,iBAAA,CAAkB,QAAA,EAAU,UAAU,CAAC,CAAA,CAAA;AAAA,MAC7E,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AACF,CAAA;AAOO,IAAM,gBAAA,GAAN,cAA+B,YAAA,CAAa;AAAA;AAAA,EAEjD,MAAM,SAAA,CAAU,OAAA,GAA0B,EAAC,EAA8B;AACvE,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ;AAAA,MACnC,MAAA,EAAQ,KAAA;AAAA,MACR,IAAA,EAAM,yBAAA;AAAA,MACN,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAED,IAAA,OAAO,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA,GAAK,OAA4B,EAAC;AAAA,EAC7D;AAAA;AAAA,EAGA,MAAM,aAAA,CAAc,OAAA,GAA0B,EAAC,EAA4B;AACzE,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ;AAAA,MACnC,MAAA,EAAQ,KAAA;AAAA,MACR,IAAA,EAAM,6BAAA;AAAA,MACN,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAED,IAAA,OAAO,SAAA,CAAwB,MAAM,eAAe,CAAA;AAAA,EACtD;AAAA;AAAA,EAGA,MAAA,CAAO,OAAA,GAA0B,EAAC,EAAoB;AACpD,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAgB;AAAA,MAC/B,MAAA,EAAQ,KAAA;AAAA,MACR,IAAA,EAAM,gBAAA;AAAA,MACN,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AACF,CAAA;AAqCO,IAAM,iBAAA,GAAN,cAAgC,YAAA,CAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOlD,KAAA,CAAM,OAAA,EAAuB,OAAA,GAA0B,EAAC,EAAqB;AAC3E,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAQ;AAAA,MACvB,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,WAAA;AAAA,MACN,IAAA,EAAM;AAAA,QACJ,KAAA,EAAO,OAAA,CAAQ,GAAA,CAAI,CAAC,KAAA,MAAW;AAAA,UAC7B,IAAI,KAAA,CAAM,MAAA;AAAA,UACV,GAAG,KAAA,CAAM,QAAA;AAAA,UACT,GAAI,MAAM,EAAA,GAAK,EAAE,GAAG,KAAA,CAAM,EAAA,KAAO;AAAC,SACpC,CAAE;AAAA,OACJ;AAAA,MACA,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,WAAA,CAAY,OAAA,EAA6B,OAAA,GAA0B,EAAC,EAAqB;AACvF,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAQ;AAAA,MACvB,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,WAAA;AAAA,MACN,IAAA,EAAM;AAAA,QACJ,KAAA,EAAO,OAAA,CAAQ,GAAA,CAAI,CAAC,KAAA,MAAW;AAAA,UAC7B,GAAG,KAAA,CAAM,IAAA;AAAA,UACT,GAAI,MAAM,KAAA,KAAU,MAAA,GAAY,EAAE,CAAA,EAAG,KAAA,CAAM,KAAA,EAAM,GAAI,EAAC;AAAA,UACtD,GAAI,MAAM,MAAA,GAAS,EAAE,IAAI,KAAA,CAAM,MAAA,KAAW,EAAC;AAAA,UAC3C,GAAI,MAAM,YAAA,GAAe,EAAE,IAAI,KAAA,CAAM,YAAA,KAAiB,EAAC;AAAA,UACvD,GAAI,MAAM,EAAA,GAAK,EAAE,GAAG,KAAA,CAAM,EAAA,KAAO;AAAC,SACpC,CAAE;AAAA,OACJ;AAAA,MACA,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AACF,CAAA;;;ACpXA,IAAM,eAAA,GAAkB,EAAA;AAoBxB,SAAS,aAAa,IAAA,EAAqC;AACzD,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,WAAA,CAAY,IAAA,EAAM,SAAA,EAAW,IAAI,CAAA;AAAA,IAC1C,KAAA,EAAO,WAAA,CAAY,IAAA,EAAM,OAAA,EAAS,IAAI,CAAA;AAAA,IACtC,OAAA,EAAS,WAAA,CAAY,IAAA,EAAM,SAAA,EAAW,IAAI,CAAA;AAAA,IAC1C,SAAA,EAAW,WAAA,CAAY,IAAA,EAAM,WAAA,EAAa,IAAI,CAAA;AAAA,IAC9C,KAAA,EAAO,WAAA,CAAY,IAAA,EAAM,OAAA,EAAS,IAAI,CAAA;AAAA,IACtC,QAAA,EAAU,WAAA,CAAY,IAAA,EAAM,UAAA,EAAY,IAAI,CAAA;AAAA,IAC5C,QAAA,EAAU,WAAA,CAAY,IAAA,EAAM,UAAA,EAAY,IAAI;AAAA,GAC9C;AACF;AAQO,IAAM,qBAAA,GAAN,cAAoC,YAAA,CAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAatD,IAAA,CAAK,MAAA,GAAiC,EAAC,EAAgC;AACrE,IAAA,OAAO,IAAA,CAAK,SAAA,CAAU,MAAA,EAAQ,MAAA,CAAO,UAAU,CAAC,CAAA;AAAA,EAClD;AAAA;AAAA,EAGA,MAAM,SAAA,CAAU,MAAA,EAAgC,MAAA,EAA6C;AAC3F,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ;AAAA,MACnC,MAAA,EAAQ,KAAA;AAAA;AAAA,MAER,IAAA,EAAM,qBAAA;AAAA,MACN,KAAA,EAAO,EAAE,KAAA,EAAO,MAAA,CAAO,OAAO,MAAA,EAAO;AAAA,MACrC,GAAG,IAAA,CAAK,cAAA,CAAe,MAAM;AAAA,KAC9B,CAAA;AAED,IAAA,MAAM,IAAA,GAAO,cAAA,CAAwB,IAAA,EAAM,eAAA,EAAiB,MAAM,CAAA;AAElE,IAAA,OAAO,EAAE,GAAG,IAAA,EAAM,KAAA,EAAO,KAAK,KAAA,CAAM,GAAA,CAAI,qBAAqB,CAAA,EAAE;AAAA,EACjE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,OAAA,CAAQ,MAAA,GAAiC,EAAC,EAA4B;AACpE,IAAA,OAAO,IAAA,CAAK,QAAA;AAAA,MACV,cAAA,CAAe,MAAA;AAAA,MACf,CAAC,KAAA,KAAU,IAAA,CAAK,UAAU,MAAA,EAAQ,KAAA,CAAM,UAAU,CAAC,CAAA;AAAA,MACnD,EAAE,GAAG,MAAA,EAAQ,GAAI,MAAA,CAAO,WAAW,MAAA,GAAY,EAAE,KAAA,EAAO,EAAE,QAAQ,MAAA,CAAO,MAAA,EAAO,EAAE,GAAI,EAAC;AAAG,KAC5F;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,KAAA,CAAM,OAAA,GAA0B,EAAC,EAAoB;AACzD,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ;AAAA,MACnC,MAAA,EAAQ,KAAA;AAAA,MACR,IAAA,EAAM,0BAAA;AAAA,MACN,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAED,IAAA,OAAO,UAAA,CAAW,IAAA,EAAM,OAAA,EAAS,CAAC,CAAA;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,QAAA,CAAS,cAAA,EAAwB,OAAA,GAA0B,EAAC,EAAoB;AACpF,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ;AAAA,MACnC,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,CAAA,mBAAA,EAAsB,iBAAA,CAAkB,cAAA,EAAgB,gBAAgB,CAAC,CAAA,KAAA,CAAA;AAAA,MAC/E,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAED,IAAA,OAAO,UAAA,CAAW,IAAA,EAAM,aAAA,EAAe,CAAC,CAAA;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,aAAA,CAAc,GAAA,EAAe,OAAA,GAA0B,EAAC,EAAoB;AAChF,IAAA,IAAI,MAAA,GAAS,CAAA;AAEb,IAAA,KAAA,IAAS,QAAQ,CAAA,EAAG,KAAA,GAAQ,GAAA,CAAI,MAAA,EAAQ,SAAS,eAAA,EAAiB;AAChE,MAAA,MAAM,KAAA,GAAQ,GAAA,CAAI,KAAA,CAAM,KAAA,EAAO,QAAQ,eAAe,CAAA;AAEtD,MAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ;AAAA,QACnC,MAAA,EAAQ,MAAA;AAAA,QACR,IAAA,EAAM,+BAAA;AAAA,QACN,IAAA,EAAM,EAAE,GAAA,EAAK,KAAA,EAAM;AAAA,QACnB,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,OAC/B,CAAA;AAED,MAAA,MAAA,IAAU,UAAA,CAAW,IAAA,EAAM,aAAA,EAAe,CAAC,CAAA;AAAA,IAC7C;AAEA,IAAA,OAAO,MAAA;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,WAAA,CAAY,OAAA,GAA0B,EAAC,EAAoB;AAC/D,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ;AAAA,MACnC,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,6BAAA;AAAA,MACN,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAED,IAAA,OAAO,UAAA,CAAW,IAAA,EAAM,aAAA,EAAe,CAAC,CAAA;AAAA,EAC1C;AAAA;AAAA,EAGA,MAAM,WAAA,CAAY,OAAA,GAA0B,EAAC,EAAkC;AAC7E,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ;AAAA,MACnC,MAAA,EAAQ,KAAA;AAAA,MACR,IAAA,EAAM,6BAAA;AAAA,MACN,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAED,IAAA,OAAO,aAAa,IAAI,CAAA;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,cAAA,CACJ,KAAA,EACA,OAAA,GAA0B,EAAC,EACI;AAC/B,IAAA,MAAM,UAAmC,EAAC;AAE1C,IAAA,KAAA,MAAW,GAAA,IAAO;AAAA,MAChB,SAAA;AAAA,MACA,OAAA;AAAA,MACA,SAAA;AAAA,MACA,WAAA;AAAA,MACA,OAAA;AAAA,MACA,UAAA;AAAA,MACA;AAAA,KACF,EAAY;AACV,MAAA,MAAM,KAAA,GAAQ,MAAM,GAAG,CAAA;AACvB,MAAA,IAAI,KAAA,KAAU,MAAA,EAAW,OAAA,CAAQ,GAAG,CAAA,GAAI,KAAA;AAAA,IAC1C;AAEA,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ;AAAA,MACnC,MAAA,EAAQ,KAAA;AAAA,MACR,IAAA,EAAM,6BAAA;AAAA,MACN,IAAA,EAAM,OAAA;AAAA,MACN,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAED,IAAA,OAAO,aAAa,IAAI,CAAA;AAAA,EAC1B;AACF,CAAA;;;AC1IO,IAAM,aAAA,GAAN,cAA4B,YAAA,CAAa;AAAA,EACrC,YAAA;AAAA,EAET,WAAA,CACE,MACA,IAAA,EACA;AACA,IAAA,KAAA,CAAM,IAAI,CAAA;AACV,IAAA,IAAA,CAAK,eAAe,IAAA,CAAK,WAAA;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,IAAA,CAAK,MAAA,GAAqB,EAAC,EAAwB;AACvD,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ;AAAA,MACnC,MAAA,EAAQ,KAAA;AAAA,MACR,IAAA,EAAM,YAAA;AAAA,MACN,KAAA,EAAO,EAAE,GAAA,EAAK,MAAA,CAAO,GAAA,EAAK,OAAO,MAAA,CAAO,KAAA,EAAO,MAAA,EAAQ,MAAA,CAAO,MAAA,EAAO;AAAA,MACrE,GAAG,IAAA,CAAK,cAAA,CAAe,MAAM;AAAA,KAC9B,CAAA;AAED,IAAA,OAAO,cAAA,CAAqB,MAAM,OAAO,CAAA;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,OAAA,CAAQ,MAAA,GAAqB,EAAC,EAAoB;AAChD,IAAA,OAAO,IAAA,CAAK,QAAA;AAAA,MACV,cAAA,CAAe,MAAA;AAAA,MACf,OAAO,KAAA,KAAqB;AAC1B,QAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ;AAAA,UACnC,MAAA,EAAQ,KAAA;AAAA,UACR,IAAA,EAAM,YAAA;AAAA,UACN,KAAA,EAAO,aAAA,CAAc,EAAE,GAAA,EAAK,MAAA,CAAO,KAAK,KAAA,EAAO,MAAA,CAAO,KAAA,EAAM,EAAG,KAAK,CAAA;AAAA,UACpE,GAAG,IAAA,CAAK,cAAA,CAAe,MAAM;AAAA,SAC9B,CAAA;AACD,QAAA,OAAO,cAAA,CAAqB,MAAM,OAAO,CAAA;AAAA,MAC3C,CAAA;AAAA,MACA,EAAE,GAAG,MAAA,EAAQ,GAAI,OAAO,MAAA,GAAS,EAAE,KAAA,EAAO,EAAE,QAAQ,MAAA,CAAO,MAAA,EAAO,EAAE,GAAI,EAAC;AAAG,KAC9E;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,MAAA,CAAO,KAAA,EAAkB,OAAA,GAA0B,EAAC,EAAkB;AAC1E,IAAA,MAAM,IAAA,GAAO,YAAY,KAAK,CAAA;AAC9B,IAAA,MAAM,aAAA,GAAgB,MAAM,IAAA,CAAK,mBAAA,CAAoB,MAAM,OAAO,CAAA;AAElE,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAc;AAAA,MAC7B,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,YAAA;AAAA,MACN,IAAA,EAAM;AAAA,QACJ,OAAA,EAAS,KAAK,OAAA,IAAW,EAAA;AAAA,QACzB,GAAI,KAAK,KAAA,GAAQ,EAAE,OAAO,IAAA,CAAK,KAAA,KAAU,EAAC;AAAA,QAC1C,GAAI,KAAK,eAAA,GAAkB,EAAE,iBAAiB,IAAA,CAAK,eAAA,KAAoB,EAAC;AAAA,QACxE,GAAI,aAAA,CAAc,MAAA,GAAS,IAAI,EAAE,aAAA,KAAkB,EAAC;AAAA,QACpD,GAAI,KAAK,IAAA,GAAO,EAAE,MAAM,IAAA,CAAK,IAAA,KAAS;AAAC,OACzC;AAAA,MACA,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,GAAA,CAAI,MAAA,EAAgB,OAAA,GAA0B,EAAC,EAAkB;AAC/D,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAc;AAAA,MAC7B,MAAA,EAAQ,KAAA;AAAA,MACR,IAAA,EAAM,CAAA,WAAA,EAAc,iBAAA,CAAkB,MAAA,EAAQ,QAAQ,CAAC,CAAA,CAAA;AAAA,MACvD,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,MAAA,CACE,MAAA,EACA,KAAA,EACA,OAAA,GAA0B,EAAC,EACZ;AACf,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAc;AAAA,MAC7B,MAAA,EAAQ,KAAA;AAAA,MACR,IAAA,EAAM,CAAA,WAAA,EAAc,iBAAA,CAAkB,MAAA,EAAQ,QAAQ,CAAC,CAAA,CAAA;AAAA,MACvD,IAAA,EAAM,EAAE,OAAA,EAAS,KAAA,CAAM,WAAW,EAAA,EAAI,GAAI,KAAA,CAAM,KAAA,GAAQ,EAAE,KAAA,EAAO,KAAA,CAAM,KAAA,EAAM,GAAI,EAAC,EAAG;AAAA,MACrF,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,MAAA,CAAO,MAAA,EAAgB,OAAA,GAA0B,EAAC,EAAkB;AAClE,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAc;AAAA,MAC7B,MAAA,EAAQ,QAAA;AAAA,MACR,IAAA,EAAM,CAAA,WAAA,EAAc,iBAAA,CAAkB,MAAA,EAAQ,QAAQ,CAAC,CAAA,CAAA;AAAA,MACvD,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,OAAA,CAAQ,MAAA,EAAgB,OAAA,GAA0B,EAAC,EAAkB;AACnE,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAc;AAAA,MAC7B,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,CAAA,WAAA,EAAc,iBAAA,CAAkB,MAAA,EAAQ,QAAQ,CAAC,CAAA,QAAA,CAAA;AAAA,MACvD,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,IAAA,CAAK,MAAA,EAAgB,OAAA,GAA0B,EAAC,EAAwB;AACtE,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAoB;AAAA,MACnC,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,CAAA,WAAA,EAAc,iBAAA,CAAkB,MAAA,EAAQ,QAAQ,CAAC,CAAA,KAAA,CAAA;AAAA,MACvD,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,MAAA,CAAO,MAAA,EAAgB,OAAA,GAA0B,EAAC,EAAwB;AACxE,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAoB;AAAA,MACnC,MAAA,EAAQ,QAAA;AAAA,MACR,IAAA,EAAM,CAAA,WAAA,EAAc,iBAAA,CAAkB,MAAA,EAAQ,QAAQ,CAAC,CAAA,KAAA,CAAA;AAAA,MACvD,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,MAAA,EAAgB,OAAA,GAAU,EAAA,EAAI,OAAA,GAA0B,EAAC,EAAkB;AAChF,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAc;AAAA,MAC7B,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,CAAA,WAAA,EAAc,iBAAA,CAAkB,MAAA,EAAQ,QAAQ,CAAC,CAAA,OAAA,CAAA;AAAA,MACvD,IAAA,EAAM,EAAE,OAAA,EAAQ;AAAA,MAChB,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,QAAA,CAAS,MAAA,EAAgB,OAAA,GAA0B,EAAC,EAAkB;AACpE,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAc;AAAA,MAC7B,MAAA,EAAQ,QAAA;AAAA,MACR,IAAA,EAAM,CAAA,WAAA,EAAc,iBAAA,CAAkB,MAAA,EAAQ,QAAQ,CAAC,CAAA,OAAA,CAAA;AAAA,MACvD,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,GAAA,CAAI,MAAA,EAAgB,OAAA,GAA0B,EAAC,EAA2B;AACxE,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAuB;AAAA,MACtC,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,CAAA,WAAA,EAAc,iBAAA,CAAkB,MAAA,EAAQ,QAAQ,CAAC,CAAA,IAAA,CAAA;AAAA,MACvD,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,KAAA,CAAM,MAAA,EAAgB,OAAA,GAA0B,EAAC,EAA2B;AAC1E,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAuB;AAAA,MACtC,MAAA,EAAQ,QAAA;AAAA,MACR,IAAA,EAAM,CAAA,WAAA,EAAc,iBAAA,CAAkB,MAAA,EAAQ,QAAQ,CAAC,CAAA,IAAA,CAAA;AAAA,MACvD,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAA,CAAK,MAAA,EAAgB,SAAA,EAAqB,OAAA,GAA0B,EAAC,EAAkB;AACrF,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAc;AAAA,MAC7B,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,CAAA,WAAA,EAAc,iBAAA,CAAkB,MAAA,EAAQ,QAAQ,CAAC,CAAA,UAAA,CAAA;AAAA,MACvD,IAAA,EAAM,EAAE,SAAA,EAAU;AAAA,MAClB,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,MAAM,KAAA,CAAM,GAAA,EAAe,OAAA,GAA0B,EAAC,EAAyB;AAC7E,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ;AAAA,MACnC,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,kBAAA;AAAA,MACN,IAAA,EAAM,EAAE,GAAA,EAAI;AAAA,MACZ,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAED,IAAA,OAAO,SAAA,CAAqB,MAAM,OAAO,CAAA;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,MAAA,CAAO,IAAA,EAAe,MAAA,GAA0B,EAAC,EAAwB;AAC7E,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ;AAAA,MACnC,MAAA,EAAQ,KAAA;AAAA,MACR,IAAA,EAAM,CAAA,gBAAA,EAAmB,iBAAA,CAAkB,IAAA,EAAM,MAAM,CAAC,CAAA,CAAA;AAAA,MACxD,KAAA,EAAO;AAAA,QACL,OAAO,MAAA,CAAO,KAAA;AAAA,QACd,QAAQ,MAAA,CAAO,MAAA;AAAA,QACf,MAAM,MAAA,CAAO,IAAA;AAAA,QACb,cAAc,MAAA,CAAO;AAAA,OACvB;AAAA,MACA,GAAG,IAAA,CAAK,cAAA,CAAe,MAAM;AAAA,KAC9B,CAAA;AAED,IAAA,OAAO,cAAA,CAAqB,MAAM,OAAO,CAAA;AAAA,EAC3C;AAAA;AAAA,EAGA,aAAA,CAAc,IAAA,EAAe,MAAA,GAA0B,EAAC,EAAoB;AAC1E,IAAA,MAAM,IAAA,GAAO,CAAA,gBAAA,EAAmB,iBAAA,CAAkB,IAAA,EAAM,MAAM,CAAC,CAAA,CAAA;AAE/D,IAAA,OAAO,IAAA,CAAK,QAAA;AAAA,MACV,cAAA,CAAe,MAAA;AAAA,MACf,OAAO,KAAA,KAAU;AACf,QAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ;AAAA,UACnC,MAAA,EAAQ,KAAA;AAAA,UACR,IAAA;AAAA,UACA,KAAA,EAAO,aAAA;AAAA,YACL,EAAE,OAAO,MAAA,CAAO,KAAA,EAAO,MAAM,MAAA,CAAO,IAAA,EAAM,YAAA,EAAc,MAAA,CAAO,YAAA,EAAa;AAAA,YAC5E;AAAA,WACF;AAAA,UACA,GAAG,IAAA,CAAK,cAAA,CAAe,MAAM;AAAA,SAC9B,CAAA;AACD,QAAA,OAAO,cAAA,CAAqB,MAAM,OAAO,CAAA;AAAA,MAC3C,CAAA;AAAA,MACA,EAAE,GAAG,MAAA,EAAQ,GAAI,OAAO,MAAA,GAAS,EAAE,KAAA,EAAO,EAAE,QAAQ,MAAA,CAAO,MAAA,EAAO,EAAE,GAAI,EAAC;AAAG,KAC9E;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,WAAA,CAAY,IAAA,EAAe,MAAA,GAA0B,EAAC,EAAwB;AAClF,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ;AAAA,MACnC,MAAA,EAAQ,KAAA;AAAA,MACR,IAAA,EAAM,CAAA,gBAAA,EAAmB,iBAAA,CAAkB,IAAA,EAAM,MAAM,CAAC,CAAA,MAAA,CAAA;AAAA,MACxD,OAAO,EAAE,KAAA,EAAO,OAAO,KAAA,EAAO,MAAA,EAAQ,OAAO,MAAA,EAAO;AAAA,MACpD,GAAG,IAAA,CAAK,cAAA,CAAe,MAAM;AAAA,KAC9B,CAAA;AAED,IAAA,OAAO,cAAA,CAAqB,MAAM,OAAO,CAAA;AAAA,EAC3C;AAAA;AAAA,EAGA,kBAAA,CAAmB,IAAA,EAAe,MAAA,GAA0B,EAAC,EAAoB;AAC/E,IAAA,MAAM,IAAA,GAAO,CAAA,gBAAA,EAAmB,iBAAA,CAAkB,IAAA,EAAM,MAAM,CAAC,CAAA,MAAA,CAAA;AAE/D,IAAA,OAAO,IAAA,CAAK,QAAA;AAAA,MACV,cAAA,CAAe,MAAA;AAAA,MACf,OAAO,KAAA,KAAU;AACf,QAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ;AAAA,UACnC,MAAA,EAAQ,KAAA;AAAA,UACR,IAAA;AAAA,UACA,OAAO,aAAA,CAAc,EAAE,OAAO,MAAA,CAAO,KAAA,IAAS,KAAK,CAAA;AAAA,UACnD,GAAG,IAAA,CAAK,cAAA,CAAe,MAAM;AAAA,SAC9B,CAAA;AACD,QAAA,OAAO,cAAA,CAAqB,MAAM,OAAO,CAAA;AAAA,MAC3C,CAAA;AAAA,MACA,EAAE,GAAG,MAAA,EAAQ,GAAI,OAAO,MAAA,GAAS,EAAE,KAAA,EAAO,EAAE,QAAQ,MAAA,CAAO,MAAA,EAAO,EAAE,GAAI,EAAC;AAAG,KAC9E;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,QAAA,CAAS,MAAA,EAAgB,MAAA,GAAyB,EAAC,EAA2B;AAClF,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ;AAAA,MACnC,MAAA,EAAQ,KAAA;AAAA,MACR,IAAA,EAAM,CAAA,WAAA,EAAc,iBAAA,CAAkB,MAAA,EAAQ,QAAQ,CAAC,CAAA,SAAA,CAAA;AAAA,MACvD,KAAA,EAAO,EAAE,KAAA,EAAO,MAAA,CAAO,KAAA,EAAO,QAAQ,MAAA,CAAO,MAAA,EAAQ,IAAA,EAAM,MAAA,CAAO,IAAA,EAAK;AAAA,MACvE,GAAG,IAAA,CAAK,cAAA,CAAe,MAAM;AAAA,KAC9B,CAAA;AAED,IAAA,OAAO,kBAAA,CAA4B,MAAM,UAAU,CAAA;AAAA,EACrD;AAAA;AAAA,EAGA,eAAA,CAAgB,MAAA,EAAgB,MAAA,GAAyB,EAAC,EAAuB;AAC/E,IAAA,MAAM,IAAA,GAAO,CAAA,WAAA,EAAc,iBAAA,CAAkB,MAAA,EAAQ,QAAQ,CAAC,CAAA,SAAA,CAAA;AAE9D,IAAA,OAAO,IAAA,CAAK,QAAA;AAAA,MACV,cAAA,CAAe,MAAA;AAAA,MACf,OAAO,KAAA,KAAU;AACf,QAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ;AAAA,UACnC,MAAA,EAAQ,KAAA;AAAA,UACR,IAAA;AAAA,UACA,KAAA,EAAO,aAAA,CAAc,EAAE,KAAA,EAAO,MAAA,CAAO,OAAO,IAAA,EAAM,MAAA,CAAO,IAAA,EAAK,EAAG,KAAK,CAAA;AAAA,UACtE,GAAG,IAAA,CAAK,cAAA,CAAe,MAAM;AAAA,SAC9B,CAAA;AACD,QAAA,OAAO,kBAAA,CAA4B,MAAM,UAAU,CAAA;AAAA,MACrD,CAAA;AAAA,MACA,EAAE,GAAG,MAAA,EAAQ,GAAI,OAAO,MAAA,GAAS,EAAE,KAAA,EAAO,EAAE,QAAQ,MAAA,CAAO,MAAA,EAAO,EAAE,GAAI,EAAC;AAAG,KAC9E;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,OAAA,CACJ,MAAA,EACA,KAAA,EACA,OAAA,GAA0B,EAAC,EACT;AAClB,IAAA,MAAM,IAAA,GAAO,eAAe,OAAO,KAAA,KAAU,WAAW,EAAE,OAAA,EAAS,KAAA,EAAM,GAAI,KAAK,CAAA;AAClF,IAAA,MAAM,aAAA,GAAgB,MAAM,IAAA,CAAK,mBAAA,CAAoB,MAAM,OAAO,CAAA;AAElE,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAiB;AAAA,MAChC,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,CAAA,WAAA,EAAc,iBAAA,CAAkB,MAAA,EAAQ,QAAQ,CAAC,CAAA,SAAA,CAAA;AAAA,MACvD,MAAM,EAAE,OAAA,EAAS,IAAA,CAAK,OAAA,IAAW,IAAI,aAAA,EAAc;AAAA,MACnD,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,YAAA,CAAa,MAAA,EAAgB,KAAA,EAAkB,OAAA,GAA0B,EAAC,EAAqB;AAC7F,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,MAAA,EAAQ,EAAE,OAAA,EAAS,EAAA,EAAI,KAAA,EAAO,CAAC,KAAK,CAAA,EAAE,EAAG,OAAO,CAAA;AAAA,EACtE;AAAA;AAAA,EAGA,MAAM,mBAAA,CACJ,IAAA,EACA,OAAA,EACmB;AACnB,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,aAAA,IAAiB,EAAC;AACxC,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,IAAS,EAAC;AAE7B,IAAA,IAAI,KAAA,CAAM,MAAA,KAAW,CAAA,EAAG,OAAO,QAAA;AAE/B,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,YAAA,CAAa,OAAO,OAAO,CAAA;AACvD,IAAA,OAAO,CAAC,GAAG,QAAA,EAAU,GAAG,QAAQ,CAAA;AAAA,EAClC;AACF,CAAA;;;AClZO,IAAM,aAAA,GAAN,cAA4B,YAAA,CAAa;AAAA;AAAA,EAE9C,EAAA,CAAG,OAAA,GAA0B,EAAC,EAAuB;AACnD,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAmB;AAAA,MAClC,MAAA,EAAQ,KAAA;AAAA,MACR,IAAA,EAAM,eAAA;AAAA,MACN,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,QAAA,CAAS,KAAA,EAA2B,OAAA,GAA0B,EAAC,EAAuB;AACpF,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAmB;AAAA,MAClC,MAAA,EAAQ,KAAA;AAAA,MACR,IAAA,EAAM,eAAA;AAAA,MACN,IAAA,EAAM,KAAA;AAAA,MACN,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,UAAA,CAAW,OAAA,GAA0B,EAAC,EAAkB;AACtD,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAc;AAAA,MAC7B,MAAA,EAAQ,QAAA;AAAA,MACR,IAAA,EAAM,eAAA;AAAA,MACN,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,OAAA,CAAQ,OAAA,GAA0B,EAAC,EAAkB;AACnD,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAc;AAAA,MAC7B,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,uBAAA;AAAA,MACN,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,aAAA,CACE,KAAA,EACA,OAAA,GAA0B,EAAC,EACP;AACpB,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAmB;AAAA,MAClC,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,oBAAA;AAAA,MACN,IAAA,EAAM,KAAA;AAAA,MACN,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,GAAA,CAAI,IAAA,EAAe,OAAA,GAA0B,EAAC,EAA2B;AACvE,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAuB;AAAA,MACtC,MAAA,EAAQ,KAAA;AAAA,MACR,IAAA,EAAM,CAAA,WAAA,EAAc,iBAAA,CAAkB,IAAA,EAAM,MAAM,CAAC,CAAA,CAAA;AAAA,MACnD,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,MAAM,aAAA,CAAc,QAAA,EAAkB,OAAA,GAA0B,EAAC,EAAqB;AACpF,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ;AAAA,MACnC,MAAA,EAAQ,KAAA;AAAA,MACR,IAAA,EAAM,2BAAA;AAAA,MACN,KAAA,EAAO,EAAE,QAAA,EAAS;AAAA,MAClB,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAED,IAAA,OAAO,WAAA,CAAY,MAAM,WAAW,CAAA;AAAA,EACtC;AAAA;AAAA,EAGA,MAAM,MAAA,CACJ,KAAA,EACA,MAAA,GAA8C,EAAC,EACvB;AACxB,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ;AAAA,MACnC,MAAA,EAAQ,KAAA;AAAA,MACR,IAAA,EAAM,mBAAA;AAAA,MACN,OAAO,EAAE,CAAA,EAAG,KAAA,EAAO,KAAA,EAAO,OAAO,KAAA,EAAM;AAAA,MACvC,GAAG,IAAA,CAAK,cAAA,CAAe,MAAM;AAAA,KAC9B,CAAA;AAED,IAAA,OAAO,SAAA,CAAuB,MAAM,OAAO,CAAA;AAAA,EAC7C;AAAA;AAAA,EAGA,MAAM,WAAA,CAAY,OAAA,GAA0B,EAAC,EAA2B;AACtE,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ;AAAA,MACnC,MAAA,EAAQ,KAAA;AAAA,MACR,IAAA,EAAM,sCAAA;AAAA,MACN,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAED,IAAA,OAAO,SAAA,CAAuB,MAAM,OAAO,CAAA;AAAA,EAC7C;AAAA;AAAA,EAGA,MAAM,QAAA,CAAS,OAAA,GAA0B,EAAC,EAAoB;AAC5D,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ;AAAA,MACnC,MAAA,EAAQ,KAAA;AAAA,MACR,IAAA,EAAM,4BAAA;AAAA,MACN,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAED,IAAA,OAAO,SAAA,CAAgB,MAAM,OAAO,CAAA;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAA,CAAO,IAAA,EAAe,OAAA,GAA0B,EAAC,EAA0B;AACzE,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAsB;AAAA,MACrC,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,CAAA,WAAA,EAAc,iBAAA,CAAkB,IAAA,EAAM,MAAM,CAAC,CAAA,OAAA,CAAA;AAAA,MACnD,MAAM,EAAC;AAAA,MACP,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,QAAA,CAAS,IAAA,EAAe,OAAA,GAA0B,EAAC,EAAkB;AACnE,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAc;AAAA,MAC7B,MAAA,EAAQ,QAAA;AAAA,MACR,IAAA,EAAM,CAAA,WAAA,EAAc,iBAAA,CAAkB,IAAA,EAAM,MAAM,CAAC,CAAA,OAAA,CAAA;AAAA,MACnD,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,SAAA,CAAU,IAAA,EAAe,MAAA,GAAyB,EAAC,EAA+B;AAChF,IAAA,OAAO,IAAA,CAAK,UAAU,CAAA,WAAA,EAAc,iBAAA,CAAkB,MAAM,MAAM,CAAC,cAAc,MAAM,CAAA;AAAA,EACzF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,gBAAA,CAAiB,IAAA,EAAe,MAAA,GAAyB,EAAC,EAA2B;AACnF,IAAA,OAAO,IAAA,CAAK,eAAe,CAAA,WAAA,EAAc,iBAAA,CAAkB,MAAM,MAAM,CAAC,cAAc,MAAM,CAAA;AAAA,EAC9F;AAAA;AAAA,EAGA,SAAA,CAAU,IAAA,EAAe,MAAA,GAAyB,EAAC,EAA+B;AAChF,IAAA,OAAO,IAAA,CAAK,UAAU,CAAA,WAAA,EAAc,iBAAA,CAAkB,MAAM,MAAM,CAAC,cAAc,MAAM,CAAA;AAAA,EACzF;AAAA;AAAA,EAGA,gBAAA,CAAiB,IAAA,EAAe,MAAA,GAAyB,EAAC,EAA2B;AACnF,IAAA,OAAO,IAAA,CAAK,eAAe,CAAA,WAAA,EAAc,iBAAA,CAAkB,MAAM,MAAM,CAAC,cAAc,MAAM,CAAA;AAAA,EAC9F;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,YAAA,CAAa,OAAA,EAAmB,OAAA,GAA0B,EAAC,EAAqC;AAC9F,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAiC;AAAA,MAChD,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,0BAAA;AAAA,MACN,IAAA,EAAM,EAAE,OAAA,EAAQ;AAAA,MAChB,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,KAAA,CAAM,IAAA,EAAe,OAAA,GAA0B,EAAC,EAAkB;AAChE,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAc;AAAA,MAC7B,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,CAAA,WAAA,EAAc,iBAAA,CAAkB,IAAA,EAAM,MAAM,CAAC,CAAA,MAAA,CAAA;AAAA,MACnD,MAAM,EAAC;AAAA,MACP,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,OAAA,CAAQ,IAAA,EAAe,OAAA,GAA0B,EAAC,EAAkB;AAClE,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAc;AAAA,MAC7B,MAAA,EAAQ,QAAA;AAAA,MACR,IAAA,EAAM,CAAA,WAAA,EAAc,iBAAA,CAAkB,IAAA,EAAM,MAAM,CAAC,CAAA,MAAA,CAAA;AAAA,MACnD,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,OAAA,CAAQ,MAAA,GAAyB,EAAC,EAA+B;AAC/D,IAAA,OAAO,IAAA,CAAK,SAAA,CAAU,uBAAA,EAAyB,MAAM,CAAA;AAAA,EACvD;AAAA;AAAA,EAGA,cAAA,CAAe,MAAA,GAAyB,EAAC,EAA2B;AAClE,IAAA,OAAO,IAAA,CAAK,cAAA,CAAe,uBAAA,EAAyB,MAAM,CAAA;AAAA,EAC5D;AAAA;AAAA,EAGA,UAAA,CAAW,OAAA,GAA0B,EAAC,EAA6B;AACjE,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAyB;AAAA,MACxC,MAAA,EAAQ,KAAA;AAAA,MACR,IAAA,EAAM,uBAAA;AAAA,MACN,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,aAAA,CAAc,KAAA,EAA2B,OAAA,GAA0B,EAAC,EAA6B;AAC/F,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAyB;AAAA,MACxC,MAAA,EAAQ,KAAA;AAAA,MACR,IAAA,EAAM,uBAAA;AAAA,MACN,IAAA,EAAM,KAAA;AAAA,MACN,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,IAAA,CAAK,OAAA,GAA0B,EAAC,EAAwB;AAC5D,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ;AAAA,MACnC,MAAA,EAAQ,KAAA;AAAA,MACR,IAAA,EAAM,oBAAA;AAAA,MACN,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAED,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,SAAA,CAAU,IAAA,EAAM,MAAM,CAAA;AAAA;AAAA,MAE5B,SAAA,EAAW,UAAA,CAAW,IAAA,EAAM,WAAW,CAAA,IAAK;AAAA,KAC9C;AAAA,EACF;AAAA;AAAA,EAGA,MAAA,CAAO,IAAA,EAAc,OAAA,GAA0B,EAAC,EAAkB;AAChE,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAc;AAAA,MAC7B,MAAA,EAAQ,KAAA;AAAA,MACR,IAAA,EAAM,mBAAA;AAAA,MACN,IAAA,EAAM,EAAE,IAAA,EAAK;AAAA,MACb,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,SAAA,CAAU,OAAA,GAA0B,EAAC,EAAkB;AACrD,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAc;AAAA,MAC7B,MAAA,EAAQ,QAAA;AAAA,MACR,IAAA,EAAM,mBAAA;AAAA,MACN,GAAG,IAAA,CAAK,cAAA,CAAe,OAAO;AAAA,KAC/B,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,aAAA,CACJ,IAAA,EACA,MAAA,EACA,KAAA,EAC4B;AAC5B,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ;AAAA,MACnC,MAAA,EAAQ,KAAA;AAAA,MACR,IAAA;AAAA,MACA,OAAO,aAAA,CAAc,EAAE,OAAO,MAAA,CAAO,KAAA,IAAS,KAAK,CAAA;AAAA,MACnD,GAAG,IAAA,CAAK,cAAA,CAAe,MAAM;AAAA,KAC9B,CAAA;AAED,IAAA,OAAO,aAAA,CAA2B,IAAA,EAAM,OAAA,EAAS,WAAA,EAAa,aAAa,SAAS,CAAA;AAAA,EACtF;AAAA,EAEA,SAAA,CAAU,MAAc,MAAA,EAAoD;AAC1E,IAAA,OAAO,IAAA,CAAK,aAAA,CAAc,IAAA,EAAM,MAAA,EAAQ;AAAA,MACtC,GAAI,OAAO,IAAA,KAAS,MAAA,GAAY,EAAE,IAAA,EAAM,MAAA,CAAO,IAAA,EAAK,GAAI;AAAC,KAC1D,CAAA;AAAA,EACH;AAAA,EAEA,cAAA,CAAe,MAAc,MAAA,EAAgD;AAC3E,IAAA,OAAO,IAAA,CAAK,QAAA;AAAA,MACV,cAAA,CAAe,IAAA;AAAA,MACf,CAAC,KAAA,KAAU,IAAA,CAAK,aAAA,CAAc,IAAA,EAAM,QAAQ,KAAK,CAAA;AAAA;AAAA,MAEjD,EAAE,GAAG,MAAA,EAAQ,GAAI,MAAA,CAAO,SAAS,MAAA,GAAY,EAAE,KAAA,EAAO,EAAE,MAAM,MAAA,CAAO,IAAA,EAAK,EAAE,GAAI,EAAC;AAAG,KACtF;AAAA,EACF;AACF,CAAA;;;AC9TO,IAAM,YAAN,MAAgB;AAAA,EACZ,OAAA;AAAA,EACA,KAAA;AAAA,EACA,YAAA;AAAA,EACA,IAAA;AAAA,EACA,MAAA;AAAA,EACA,QAAA,GAAW,IAAI,cAAA,EAAe;AAAA;AAAA,EAG9B,IAAA;AAAA;AAAA,EAEA,KAAA;AAAA;AAAA,EAEA,KAAA;AAAA;AAAA,EAEA,QAAA;AAAA;AAAA,EAEA,KAAA;AAAA;AAAA,EAEA,aAAA;AAAA;AAAA,EAEA,QAAA;AAAA;AAAA,EAEA,MAAA;AAAA;AAAA,EAEA,OAAA;AAAA;AAAA,EAEA,YAAA;AAAA;AAAA,EAEA,YAAA;AAAA;AAAA,EAEA,QAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,SAAA;AAAA,EAET,WAAA,CAAY,OAAA,GAA4B,EAAC,EAAG;AAC1C,IAAA,IAAA,CAAK,OAAA,GAAU,cAAc,OAAO,CAAA;AACpC,IAAA,IAAA,CAAK,IAAA,GAAO,IAAI,SAAA,EAAU;AAC1B,IAAA,IAAA,CAAK,KAAA,GAAQ,IAAI,UAAA,CAAW,IAAA,CAAK,OAAO,CAAA;AACxC,IAAA,IAAA,CAAK,YAAA,GAAe,IAAI,WAAA,CAAY,IAAA,CAAK,SAAS,IAAA,CAAK,KAAA,EAAO,KAAK,IAAI,CAAA;AAEvE,IAAA,IAAA,CAAK,MAAA,GAAS,KAAK,OAAA,CAAQ,SAAA,GAAY,IAAI,YAAA,CAAa,IAAA,CAAK,OAAA,CAAQ,SAAS,CAAA,GAAI,MAAA;AAIlF,IAAA,IAAA,CAAK,KAAA,CAAM,UAAA,CAAW,IAAA,CAAK,QAAQ,CAAA;AAEnC,IAAA,IAAA,CAAK,MAAM,gBAAA,CAAiB;AAAA,MAC1B,cAAA,EAAgB,MAAM,IAAA,CAAK,YAAA,CAAa,cAAA,EAAe;AAAA,MACvD,WAAA,EAAa,MAAM,IAAA,CAAK,YAAA,CAAa,WAAA,EAAY;AAAA,MACjD,cAAA,EAAgB,MAAM,IAAA,CAAK,YAAA,CAAa,cAAA,EAAe;AAAA,MACvD,iBAAiB,CAAC,GAAA,KAAQ,IAAA,CAAK,IAAA,CAAK,UAAU,GAAG,CAAA;AAAA,MACjD,WAAA,EAAa,CAAC,GAAA,EAAK,QAAA,KAAa,KAAK,IAAA,CAAK,eAAA,CAAgB,KAAK,QAAQ,CAAA;AAAA,MACvE,GAAI,IAAA,CAAK,MAAA,GAAS,EAAE,QAAA,EAAU,IAAA,CAAK,MAAA,CAAO,QAAA,CAAS,IAAA,CAAK,IAAA,CAAK,MAAM,CAAA,KAAM,EAAC;AAAA;AAAA;AAAA,MAG1E,GAAI,IAAA,CAAK,OAAA,CAAQ,KAAA,IAAS,IAAA,CAAK,OAAA,CAAQ,SAAA,GACnC,EAAE,cAAA,EAAgB,IAAA,CAAK,qBAAA,EAAsB,KAC7C,EAAC;AAAA,MACL,GAAI,IAAA,CAAK,MAAA,IAAU,IAAA,CAAK,QAAQ,SAAA,EAAW,cAAA,GACvC,EAAE,WAAA,EAAa,KAAK,kBAAA,CAAmB,IAAA,CAAK,IAAI,CAAA,KAChD;AAAC,KACN,CAAA;AAED,IAAA,IAAA,CAAK,KAAA,GAAQ,IAAI,aAAA,CAAc,IAAA,CAAK,KAAK,CAAA;AAEzC,IAAA,MAAM,WAAA,GAAc,CAAC,KAAA,EAAoB,cAAA,KACvC,IAAA,CAAK,MAAM,UAAA,CAAW,KAAA,EAAO,cAAA,IAAkB,EAAE,CAAA;AAEnD,IAAA,IAAA,CAAK,IAAA,GAAO,IAAI,YAAA,CAAa,IAAA,CAAK,OAAO,EAAE,IAAA,EAAM,IAAA,CAAK,YAAA,EAAc,CAAA;AACpE,IAAA,IAAA,CAAK,KAAA,GAAQ,IAAI,aAAA,CAAc,IAAA,CAAK,KAAK,CAAA;AACzC,IAAA,IAAA,CAAK,QAAQ,IAAI,aAAA,CAAc,KAAK,KAAA,EAAO,EAAE,aAAa,CAAA;AAC1D,IAAA,IAAA,CAAK,WAAW,IAAI,gBAAA,CAAiB,KAAK,KAAA,EAAO,EAAE,aAAa,CAAA;AAChE,IAAA,IAAA,CAAK,aAAA,GAAgB,IAAI,qBAAA,CAAsB,IAAA,CAAK,KAAK,CAAA;AACzD,IAAA,IAAA,CAAK,QAAA,GAAW,IAAI,gBAAA,CAAiB,IAAA,CAAK,KAAK,CAAA;AAC/C,IAAA,IAAA,CAAK,MAAA,GAAS,IAAI,cAAA,CAAe,IAAA,CAAK,KAAK,CAAA;AAC3C,IAAA,IAAA,CAAK,OAAA,GAAU,IAAI,eAAA,CAAgB,IAAA,CAAK,KAAK,CAAA;AAC7C,IAAA,IAAA,CAAK,YAAA,GAAe,IAAI,oBAAA,CAAqB,IAAA,CAAK,KAAK,CAAA;AACvD,IAAA,IAAA,CAAK,YAAA,GAAe,IAAI,oBAAA,CAAqB,IAAA,CAAK,KAAK,CAAA;AACvD,IAAA,IAAA,CAAK,QAAA,GAAW,IAAI,gBAAA,CAAiB,IAAA,CAAK,KAAK,CAAA;AAC/C,IAAA,IAAA,CAAK,SAAA,GAAY,IAAI,iBAAA,CAAkB,IAAA,CAAK,KAAK,CAAA;AAAA,EACnD;AAAA;AAAA,EAGA,IAAI,OAAA,GAAkB;AACpB,IAAA,OAAO,KAAK,OAAA,CAAQ,OAAA;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,QAAqB,OAAA,EAAwC;AAC3D,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,OAAA,CAAW,OAAO,CAAA;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBA,IAAI,MAAA,EAAyB;AAC3B,IAAA,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,MAAA,EAAQ,EAAE,OAAA,EAAS,IAAA,CAAK,OAAA,CAAQ,OAAA,EAAS,MAAA,EAAQ,IAAA,CAAK,OAAA,CAAQ,MAAA,EAAQ,CAAA;AACxF,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,EAAA,CAA+B,OAAU,QAAA,EAAgD;AACvF,IAAA,OAAO,IAAA,CAAK,YAAA,CAAa,EAAA,CAAG,KAAA,EAAO,QAAQ,CAAA;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoBA,QAAA,CAAS,OAAA,GAA2B,EAAC,EAAgB;AACnD,IAAA,OAAO,IAAI,WAAA;AAAA,MACT;AAAA,QACE,OAAA,EAAS,KAAK,OAAA,CAAQ,OAAA;AAAA,QACtB,KAAA,EAAO,KAAK,OAAA,CAAQ,KAAA;AAAA,QACpB,QAAA,EAAU,MAAM,IAAA,CAAK,YAAA,CAAa,cAAA,EAAe;AAAA,QACjD,OAAA,EAAS,MAAM,IAAA,CAAK,YAAA,CAAa,cAAA,EAAe;AAAA,QAChD,gBAAA,EAAkB,MAAM,IAAA,CAAK,aAAA,CAAc,KAAA,EAAM;AAAA,QACjD,MAAA,EAAQ,KAAK,OAAA,CAAQ;AAAA,OACvB;AAAA,MACA;AAAA,KACF;AAAA,EACF;AAAA;AAAA,EAGA,UAAA,GAAyC;AACvC,IAAA,OAAO,IAAA,CAAK,aAAa,UAAA,EAAW;AAAA,EACtC;AAAA;AAAA,EAGA,WAAW,OAAA,EAAoC;AAC7C,IAAA,OAAO,IAAA,CAAK,YAAA,CAAa,UAAA,CAAW,OAAO,CAAA;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,cAAc,QAAA,EAA4B;AACxC,IAAA,IAAA,CAAK,KAAA,CAAM,cAAc,QAAQ,CAAA;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,kBAAA,CAAmB,OAA2B,SAAA,EAAqC;AACjF,IAAA,IAAI,SAAA,KAAc,MAAA,IAAa,SAAA,GAAY,CAAA,EAAG;AAE9C,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,OAAA,CAAQ,SAAA,EAAW,YAAY,CAAC,CAAA;AACnD,IAAA,IAAI,UAAU,MAAA,EAAW;AAEzB,IAAA,IAAA,CAAK,MAAA,EAAQ,MAAM,KAAK,CAAA;AACxB,IAAA,IAAA,CAAK,QAAQ,MAAA,EAAQ,KAAA;AAAA,MACnB,+HAA2B,SAAS,CAAA,cAAA,EAAO,KAAA,IAAS,GAAG,0EAAmB,KAAK,CAAA,aAAA;AAAA,KACjF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,qBAAA,GAAwB;AACtB,IAAA,MAAM,KAAA,GAAQ,KAAK,OAAA,CAAQ,KAAA;AAC3B,IAAA,MAAM,SAAA,GAAY,KAAA,GAAQ,oBAAA,CAAqB,KAAK,CAAA,GAAI,MAAA;AACxD,IAAA,MAAM,QAAQ,IAAA,CAAK,MAAA;AACnB,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,OAAA,CAAQ,SAAA,EAAW,eAAe,EAAC;AAEvD,IAAA,OAAO,CAAC,KAAA,EAAgB,OAAA,EAAiB,MAAA,KAAuC;AAC9E,MAAA,IAAI,mBAAA,CAAoB,KAAK,CAAA,EAAG;AAE9B,QAAA,MAAM,IAAA,GAAO,KAAA,CAAM,UAAA,IAAc,MAAA,CAAO,UAAU,CAAC,CAAA;AAGnD,QAAA,IAAI,IAAA,KAAS,QAAW,OAAO,MAAA;AAE/B,QAAA,KAAA,EAAO,MAAM,IAAI,CAAA;AACjB,QAAA,IAAA,CAAK,OAAA,CAAQ,QAAQ,KAAA,CAAM,CAAA,sHAAA,EAA0B,UAAU,CAAC,CAAA,gCAAA,EAAU,IAAI,CAAA,aAAA,CAAK,CAAA;AAEnF,QAAA,OAAO,IAAA;AAAA,MACT;AAEA,MAAA,OAAO,SAAA,GAAY,KAAA,EAAO,OAAA,EAAS,MAAM,CAAA;AAAA,IAC3C,CAAA;AAAA,EACF;AACF;AAYO,SAAS,YAAA,CAAa,OAAA,GAA4B,EAAC,EAAc;AACtE,EAAA,OAAO,IAAI,UAAU,OAAO,CAAA;AAC9B;;;ACxUA,IAAM,aAAA,GAAgB,0EAAA;AAGtB,IAAM,aAAA,GAAgB,mGAAA;AAQtB,IAAM,SAAA,GAEF,OAAO,MAAA,CAAO;AAAA,EAChB,CAAC,gBAAA,CAAiB,MAAM,GAAG;AAAA,IACzB,GAAA,EAAK,CAAC,IAAA,KAAS,CAAA,EAAG,IAAI,CAAA,kHAAA,CAAA;AAAA,IACtB,MAAM,CAAC,IAAA,EAAM,WAAW,CAAA,EAAG,IAAI,8BAAU,MAAM,CAAA,mGAAA;AAAA,GACjD;AAAA,EACA,CAAC,gBAAA,CAAiB,aAAa,GAAG;AAAA,IAChC,GAAA,EAAK,CAAC,IAAA,KAAS,CAAA,EAAG,IAAI,CAAA,kIAAA,CAAA;AAAA,IACtB,MAAM,CAAC,IAAA,EAAM,WAAW,CAAA,EAAG,IAAI,8BAAU,MAAM,CAAA,kIAAA;AAAA,GACjD;AAAA,EACA,CAAC,gBAAA,CAAiB,cAAc,GAAG;AAAA,IACjC,GAAA,EAAK,CAAC,IAAA,KAAS,CAAA,EAAG,IAAI,CAAA,2GAAA,CAAA;AAAA,IACtB,MAAM,CAAC,IAAA,EAAM,WAAW,CAAA,EAAG,IAAI,8BAAU,MAAM,CAAA,yGAAA;AAAA,GACjD;AAAA,EACA,CAAC,gBAAA,CAAiB,YAAY,GAAG;AAAA,IAC/B,GAAA,EAAK,CAAC,IAAA,KAAS,CAAA,EAAG,IAAI,CAAA,yFAAA,CAAA;AAAA,IACtB,MAAM,CAAC,IAAA,EAAM,WAAW,CAAA,EAAG,IAAI,8BAAU,MAAM,CAAA,uFAAA;AAAA,GACjD;AAAA,EACA,CAAC,gBAAA,CAAiB,WAAW,GAAG;AAAA,IAC9B,GAAA,EAAK,CAAC,IAAA,KAAS,CAAA,EAAG,IAAI,CAAA,qJAAA,CAAA;AAAA,IACtB,MAAM,CAAC,IAAA,EAAM,WAAW,CAAA,EAAG,IAAI,8BAAU,MAAM,CAAA,mJAAA;AAAA,GACjD;AAAA,EACA,CAAC,gBAAA,CAAiB,UAAU,GAAG;AAAA,IAC7B,GAAA,EAAK,CAAC,IAAA,KAAS,CAAA,EAAG,IAAI,CAAA,kFAAA,CAAA;AAAA,IACtB,MAAM,CAAC,IAAA,EAAM,WAAW,CAAA,EAAG,IAAI,8BAAU,MAAM,CAAA,gFAAA;AAAA,GACjD;AAAA,EACA,CAAC,gBAAA,CAAiB,eAAe,GAAG;AAAA,IAClC,GAAA,EAAK,CAAC,IAAA,KAAS,CAAA,EAAG,IAAI,CAAA,mIAAA,CAAA;AAAA,IACtB,MAAM,CAAC,IAAA,EAAM,WAAW,CAAA,EAAG,IAAI,8BAAU,MAAM,CAAA,iIAAA;AAAA,GACjD;AAAA,EACA,CAAC,gBAAA,CAAiB,YAAY,GAAG;AAAA,IAC/B,GAAA,EAAK,CAAC,IAAA,KAAS,CAAA,EAAG,IAAI,CAAA,sJAAA,CAAA;AAAA,IACtB,MAAM,CAAC,IAAA,EAAM,WAAW,CAAA,EAAG,IAAI,8BAAU,MAAM,CAAA,oJAAA;AAAA,GACjD;AAAA,EACA,CAAC,gBAAA,CAAiB,WAAW,GAAG;AAAA,IAC9B,GAAA,EAAK,CAAC,IAAA,KAAS,CAAA,EAAG,IAAI,CAAA,kHAAA,CAAA;AAAA,IACtB,MAAM,CAAC,IAAA,EAAM,WAAW,CAAA,EAAG,IAAI,8BAAU,MAAM,CAAA,gHAAA;AAAA,GACjD;AAAA,EACA,CAAC,gBAAA,CAAiB,cAAc,GAAG;AAAA,IACjC,GAAA,EAAK,CAAC,IAAA,KAAS,CAAA,EAAG,IAAI,CAAA,sJAAA,CAAA;AAAA,IACtB,MAAM,CAAC,IAAA,EAAM,WAAW,CAAA,EAAG,IAAI,8BAAU,MAAM,CAAA,oJAAA;AAAA,GACjD;AAAA,EACA,CAAC,gBAAA,CAAiB,QAAQ,GAAG;AAAA,IAC3B,GAAA,EAAK,CAAC,IAAA,KAAS,CAAA,EAAG,IAAI,CAAA,8HAAA,CAAA;AAAA,IACtB,MAAM,CAAC,IAAA,EAAM,WAAW,CAAA,EAAG,IAAI,8BAAU,MAAM,CAAA,4HAAA;AAAA,GACjD;AAAA,EACA,CAAC,gBAAA,CAAiB,oBAAoB,GAAG;AAAA,IACvC,KAAK,MAAM,gMAAA;AAAA,IACX,MAAM,MAAM;AAAA,GACd;AAAA,EACA,CAAC,gBAAA,CAAiB,oBAAoB,GAAG;AAAA,IACvC,KAAK,MAAM,sMAAA;AAAA,IACX,MAAM,MAAM;AAAA;AAEhB,CAAC,CAAA;AAcM,SAAS,uBAAuB,YAAA,EAAoC;AACzE,EAAA,MAAM,QAAA,GAAW,SAAA,CAAU,YAAA,CAAa,IAAI,CAAA;AAC5C,EAAA,IAAI,CAAC,UAAU,OAAO,aAAA;AAEtB,EAAA,MAAM,KAAA,GAAQ,YAAA,CAAa,MAAA,CAAO,CAAC,CAAA;AACnC,EAAA,MAAM,IAAA,GAAO,KAAA,EAAO,WAAA,IAAe,KAAA,EAAO,QAAA,IAAY,aAAA;AAEtD,EAAA,MAAM,MAAA,GAAS,aAAa,KAAA,GAAQ,CAAA;AACpC,EAAA,OAAO,MAAA,GAAS,IAAI,QAAA,CAAS,IAAA,CAAK,MAAM,MAAM,CAAA,GAAI,QAAA,CAAS,GAAA,CAAI,IAAI,CAAA;AACrE;;;ACzFA,IAAM,UAAA,uBAAiB,GAAA,CAAY;AAAA,EACjC,gBAAA,CAAiB,YAAA;AAAA,EACjB,gBAAA,CAAiB,UAAA;AAAA,EACjB,gBAAA,CAAiB,WAAA;AAAA,EACjB,gBAAA,CAAiB;AACnB,CAAC,CAAA;AAGD,IAAM,aAAA,uBAAoB,GAAA,CAAY;AAAA,EACpC,gBAAA,CAAiB,WAAA;AAAA,EACjB,gBAAA,CAAiB,eAAA;AAAA,EACjB,gBAAA,CAAiB,YAAA;AAAA,EACjB,gBAAA,CAAiB;AACnB,CAAC,CAAA;AAGD,IAAM,YAAA,uBAAmB,GAAA,CAAY;AAAA,EACnC,gBAAA,CAAiB,MAAA;AAAA,EACjB,gBAAA,CAAiB,aAAA;AAAA,EACjB,gBAAA,CAAiB;AACnB,CAAC,CAAA;AAeM,SAAS,uBAAuB,YAAA,EAAoC;AACzE,EAAA,MAAM,EAAE,IAAA,EAAM,QAAA,EAAU,cAAA,EAAgB,UAAS,GAAI,YAAA;AACrD,EAAA,MAAM,QAAA,GAAW,YAAA,CAAa,MAAA,CAAO,CAAC,CAAA,EAAG,QAAA;AAEzC,EAAA,IAAI,YAAY,QAAA,EAAU;AACxB,IAAA,IAAI,UAAA,CAAW,IAAI,IAAI,CAAA,SAAU,CAAA,EAAA,EAAK,QAAQ,SAAS,QAAQ,CAAA,CAAA;AAE/D,IAAA,IAAI,aAAA,CAAc,GAAA,CAAI,IAAI,CAAA,EAAG;AAC3B,MAAA,OAAO,cAAA,GACH,CAAA,EAAA,EAAK,QAAQ,CAAA,MAAA,EAAS,cAAc,CAAA,SAAA,EAAY,QAAQ,CAAA,CAAA,GACxD,CAAA,EAAA,EAAK,QAAQ,CAAA,MAAA,EAAS,QAAQ,CAAA,CAAA;AAAA,IACpC;AAAA,EACF;AAEA,EAAA,IAAI,YAAY,YAAA,CAAa,GAAA,CAAI,IAAI,CAAA,EAAG,OAAO,KAAK,QAAQ,CAAA,CAAA;AAE5D,EAAA,OAAO,QAAA,IAAY,gBAAA;AACrB;;;ACyJO,SAAS,YAAY,OAAA,EAAwC;AAClE,EAAA,OAAO,cAAA,IAAkB,OAAA;AAC3B;AAiWO,SAAS,OAAO,KAAA,EAAgD;AACrE,EAAA,IAAI,CAAC,OAAO,OAAO,IAAA;AACnB,EAAA,MAAM,IAAA,GAAO,IAAI,IAAA,CAAK,KAAK,CAAA;AAC3B,EAAA,OAAO,OAAO,QAAA,CAAS,IAAA,CAAK,OAAA,EAAS,IAAI,IAAA,GAAO,IAAA;AAClD","file":"chunk-CCRQI3ON.js","sourcesContent":["/** Метка билдера. Через `Symbol.for` — чтобы распознавание переживало смешивание ESM и CJS. */\nexport const BUILDER = Symbol.for('itd.builder');\n\n/**\n * Билдер входных данных.\n *\n * Билдеры необязательны: любой метод, принимающий билдер, принимает и обычный объект.\n * Проверки одинаковы в обоих случаях.\n */\nexport interface ItdBuilder<T> {\n /** @internal */\n readonly [BUILDER]: true;\n /**\n * Собирает и проверяет результат.\n *\n * @throws {ItdConfigError} если нарушены требования к данным\n */\n build(): T;\n /** Чтобы билдер корректно вёл себя внутри `JSON.stringify`. */\n toJSON(): T;\n}\n\n/**\n * Три равноправные формы входа: обычный объект, готовый билдер или функция-настройщик.\n *\n * @example\n * ```ts\n * itd.posts.create({ content: 'привет' }); // объект\n * itd.posts.create(post().content('привет')); // билдер\n * itd.posts.create((p) => p.content('привет')); // функция\n * ```\n */\nexport type BuilderInput<T, B extends ItdBuilder<T>> = T | B | ((builder: B) => B | T);\n\n/** Является ли значение билдером. */\nexport function isBuilder<T>(value: unknown): value is ItdBuilder<T> {\n return typeof value === 'object' && value !== null && BUILDER in value;\n}\n\n/**\n * Приводит любую из трёх форм входа к готовому объекту.\n *\n * Проверка выполняется всегда, независимо от формы: обычный объект проходит ровно те же\n * правила, что и результат билдера.\n *\n * @param input то, что передал пользователь\n * @param factory создаёт пустой билдер для формы с функцией\n * @param validate проверяет собранный объект\n */\nexport function resolveInput<T, B extends ItdBuilder<T>>(\n input: BuilderInput<T, B>,\n factory: () => B,\n validate: (value: T) => T,\n): T {\n if (typeof input === 'function') {\n const result = (input as (builder: B) => B | T)(factory());\n return isBuilder<T>(result) ? result.build() : validate(result as T);\n }\n\n if (isBuilder<T>(input)) return input.build();\n\n return validate(input as T);\n}\n","import type { ItdErrorCode } from '../types/enums.js';\n\n/** Бренд, по которому ошибки библиотеки распознаются надёжнее, чем через `instanceof`. */\nconst ITD_ERROR = Symbol.for('itd.error');\n\n/**\n * Категория ошибки. Определяет, какие поля у неё есть.\n *\n * Значение, а не только тип: категорию нужно с чем-то сравнивать в рантайме.\n */\nexport const ItdErrorKind = Object.freeze({\n /** Сервер ответил статусом ≥ 400. */\n Api: 'api',\n /** Запрос не дошёл до сервера. */\n Network: 'network',\n /** Истёк таймаут запроса. */\n Timeout: 'timeout',\n /** Запрос отменён через `AbortSignal`. */\n Abort: 'abort',\n /** Некорректная конфигурация или аргументы — обнаружено до обращения к сети. */\n Config: 'config',\n} as const);\nexport type ItdErrorKind = (typeof ItdErrorKind)[keyof typeof ItdErrorKind];\n\n/**\n * Разновидность ошибки API — то же, что класс ошибки, но в виде данных.\n *\n * Существует потому, что `instanceof` подводит, когда в дереве зависимостей оказались\n * две копии пакета или смешаны сборки ESM и CJS: классы тогда разные, хотя ошибка та же.\n * Проверки {@link isItdValidationError} и соседние опираются на это поле, а не на класс.\n */\nexport const ItdApiErrorKind = Object.freeze({\n /** Ни одна из специализаций не подошла. */\n Generic: 'generic',\n Validation: 'validation',\n Auth: 'auth',\n Forbidden: 'forbidden',\n NotFound: 'not_found',\n Conflict: 'conflict',\n RateLimit: 'rate_limit',\n PhoneVerification: 'phone_verification',\n Server: 'server',\n} as const);\nexport type ItdApiErrorKind = (typeof ItdApiErrorKind)[keyof typeof ItdApiErrorKind];\n\n/** Ошибки по полям формы: `{ email: ['уже занят'] }`. */\nexport type ItdFieldErrors = Record<string, string[]>;\n\n/**\n * Базовый класс всех ошибок библиотеки.\n *\n * Ловить его имеет смысл, чтобы отделить проблемы обращения к итд.com от прочих исключений.\n * Для разбора конкретной причины используйте {@link isItdApiError} и поле {@link ItdApiError.code}.\n *\n * @example\n * ```ts\n * try {\n * await itd.posts.like(id);\n * } catch (e) {\n * if (isItdError(e)) console.error('итд.com:', e.message);\n * else throw e;\n * }\n * ```\n */\nexport class ItdError extends Error {\n /** @internal */\n readonly [ITD_ERROR] = true as const;\n\n /** Категория ошибки. */\n readonly kind: ItdErrorKind;\n\n constructor(kind: ItdErrorKind, message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.kind = kind;\n this.name = 'ItdError';\n }\n}\n\n/** Параметры конструктора {@link ItdApiError}. */\nexport interface ItdApiErrorInit {\n /** HTTP-статус ответа. */\n status: number;\n /** Строковый код ошибки из тела ответа. */\n code: ItdErrorCode;\n /** Человекочитаемое сообщение. */\n message: string;\n /** Расширенное описание, если сервер его прислал. */\n detail?: string | undefined;\n /** Заголовок ошибки, если сервер его прислал. */\n title?: string | undefined;\n /** Ошибки по конкретным полям (сведены из `errors` и `violations`). */\n fieldErrors?: ItdFieldErrors | undefined;\n /** Идентификатор запроса из заголовков ответа, если есть. */\n requestId?: string | undefined;\n /** HTTP-метод запроса. */\n method: string;\n /** Путь запроса без базового URL. */\n path: string;\n /** Тело ответа как оно пришло — на случай, если документация разошлась с реальностью. */\n raw: unknown;\n /** Сам объект ответа. Тело уже прочитано. */\n response?: Response | undefined;\n /** Значение `Retry-After` в миллисекундах, если заголовок был. */\n retryAfter?: number | undefined;\n /** Сколько запросов разрешено в окне (`x-ratelimit-limit`). */\n rateLimit?: number | undefined;\n /** Сколько запросов осталось в окне (`x-ratelimit-remaining`). */\n rateLimitRemaining?: number | undefined;\n}\n\n/**\n * Ошибка, возвращённая сервером итд.com (HTTP-статус ≥ 400).\n *\n * API отдаёт ошибки в двух разных формах — `{ error: { … } }` и `{ code, message, violations }`.\n * Библиотека сводит обе к этому классу, поэтому разбирать форму ответа вручную не нужно.\n *\n * @example\n * ```ts\n * try {\n * await itd.users.updateMe({ username: 'занятое_имя' });\n * } catch (e) {\n * if (e instanceof ItdValidationError) {\n * console.log(e.fieldErrors.username); // ['Имя уже занято']\n * }\n * }\n * ```\n */\nexport class ItdApiError extends ItdError {\n /**\n * Разновидность ошибки: та же информация, что и класс, но пригодная для сравнения.\n *\n * Позволяет разбирать ошибку через `switch`, а проверкам вроде {@link isItdAuthError} —\n * работать даже когда в проекте оказались две копии библиотеки.\n */\n readonly apiKind: ItdApiErrorKind;\n /** HTTP-статус ответа. */\n readonly status: number;\n /** Строковый код ошибки, например `VALIDATION_ERROR`. */\n readonly code: ItdErrorCode;\n /** Расширенное описание, если сервер его прислал. */\n readonly detail: string | undefined;\n /** Заголовок ошибки, если сервер его прислал. */\n readonly title: string | undefined;\n /** Ошибки по полям. Пустой объект, если сервер их не прислал. */\n readonly fieldErrors: ItdFieldErrors;\n /** Идентификатор запроса из заголовков ответа. */\n readonly requestId: string | undefined;\n /** HTTP-метод запроса. */\n readonly method: string;\n /** Путь запроса без базового URL. */\n readonly path: string;\n /** Тело ответа как оно пришло. */\n readonly raw: unknown;\n /** Объект ответа. Тело уже прочитано и повторно прочитано быть не может. */\n readonly response: Response | undefined;\n /** Пауза из заголовка `Retry-After` в миллисекундах. Сервер итд.com его не присылает. */\n readonly retryAfter: number | undefined;\n /**\n * Сколько запросов разрешено в окне — заголовок `x-ratelimit-limit`.\n *\n * Времени сброса окна сервер не сообщает, поэтому точный момент повтора неизвестен.\n */\n readonly rateLimit: number | undefined;\n /** Сколько запросов осталось в окне — заголовок `x-ratelimit-remaining`. */\n readonly rateLimitRemaining: number | undefined;\n\n /**\n * @param apiKind разновидность; подставляется подклассами, снаружи задавать не нужно\n */\n constructor(init: ItdApiErrorInit, apiKind: ItdApiErrorKind = ItdApiErrorKind.Generic) {\n super(ItdErrorKind.Api, init.message);\n this.name = 'ItdApiError';\n this.apiKind = apiKind;\n this.status = init.status;\n this.code = init.code;\n this.detail = init.detail;\n this.title = init.title;\n this.fieldErrors = init.fieldErrors ?? {};\n this.requestId = init.requestId;\n this.method = init.method;\n this.path = init.path;\n this.raw = init.raw;\n this.response = init.response;\n this.retryAfter = init.retryAfter;\n this.rateLimit = init.rateLimit;\n this.rateLimitRemaining = init.rateLimitRemaining;\n }\n\n /**\n * Проверяет код ошибки. Удобнее, чем сравнивать строки вручную.\n *\n * @example\n * ```ts\n * if (err.hasCode('OTP_INVALID', 'MISSING_FLOW_TOKEN')) await restartOtpFlow();\n * ```\n */\n hasCode(...codes: ItdErrorCode[]): boolean {\n return codes.includes(this.code);\n }\n\n /** Имеет ли смысл повторить запрос: `429` и серверные ошибки `5xx`. */\n get isRetryable(): boolean {\n return this.status === 429 || this.status >= 500;\n }\n}\n\n/** `400` / `422` — данные не прошли валидацию. Подробности в {@link ItdApiError.fieldErrors}. */\nexport class ItdValidationError extends ItdApiError {\n constructor(init: ItdApiErrorInit) {\n super(init, ItdApiErrorKind.Validation);\n this.name = 'ItdValidationError';\n }\n}\n\n/** `401` — токен отсутствует, истёк или отозван. */\nexport class ItdAuthError extends ItdApiError {\n constructor(init: ItdApiErrorInit) {\n super(init, ItdApiErrorKind.Auth);\n this.name = 'ItdAuthError';\n }\n}\n\n/** `403` — доступ запрещён либо действие ограничено настройками приватности. */\nexport class ItdForbiddenError extends ItdApiError {\n constructor(init: ItdApiErrorInit) {\n super(init, ItdApiErrorKind.Forbidden);\n this.name = 'ItdForbiddenError';\n }\n}\n\n/** `404` — сущность не найдена. */\nexport class ItdNotFoundError extends ItdApiError {\n constructor(init: ItdApiErrorInit) {\n super(init, ItdApiErrorKind.NotFound);\n this.name = 'ItdNotFoundError';\n }\n}\n\n/** `409` — сущность уже существует. */\nexport class ItdConflictError extends ItdApiError {\n constructor(init: ItdApiErrorInit) {\n super(init, ItdApiErrorKind.Conflict);\n this.name = 'ItdConflictError';\n }\n}\n\n/**\n * `429` — превышен лимит запросов.\n *\n * Если сервер прислал `Retry-After`, пауза доступна в {@link ItdApiError.retryAfter}\n * (в миллисекундах). При включённых ретраях библиотека выдерживает её автоматически.\n */\nexport class ItdRateLimitError extends ItdApiError {\n constructor(init: ItdApiErrorInit) {\n super(init, ItdApiErrorKind.RateLimit);\n this.name = 'ItdRateLimitError';\n }\n}\n\n/**\n * Действие требует подтверждённого телефона (`PHONE_VERIFICATION_REQUIRED`).\n *\n * Подтверждение проходит через Telegram-бота: ссылка лежит в {@link verificationUrl}.\n */\nexport class ItdPhoneVerificationError extends ItdApiError {\n /** Ссылка на бота подтверждения, если удалось определить идентификатор пользователя. */\n readonly verificationUrl: string | undefined;\n\n constructor(init: ItdApiErrorInit & { userId?: string | undefined }) {\n super(init, ItdApiErrorKind.PhoneVerification);\n this.name = 'ItdPhoneVerificationError';\n this.verificationUrl = init.userId\n ? `https://t.me/itd_verification_bot?start=${encodeURIComponent(init.userId)}`\n : undefined;\n }\n}\n\n/** `5xx` — ошибка на стороне сервера. */\nexport class ItdServerError extends ItdApiError {\n constructor(init: ItdApiErrorInit) {\n super(init, ItdApiErrorKind.Server);\n this.name = 'ItdServerError';\n }\n}\n\n/** Запрос не дошёл до сервера: DNS, обрыв соединения, отсутствие сети. */\nexport class ItdNetworkError extends ItdError {\n /** HTTP-метод запроса. */\n readonly method: string;\n /** Путь запроса без базового URL. */\n readonly path: string;\n\n constructor(message: string, init: { method: string; path: string; cause?: unknown }) {\n super(ItdErrorKind.Network, message, { cause: init.cause });\n this.name = 'ItdNetworkError';\n this.method = init.method;\n this.path = init.path;\n }\n}\n\n/** Истёк таймаут запроса, заданный опцией `timeout`. */\nexport class ItdTimeoutError extends ItdError {\n /** Значение таймаута в миллисекундах. */\n readonly timeout: number;\n /** HTTP-метод запроса. */\n readonly method: string;\n /** Путь запроса без базового URL. */\n readonly path: string;\n\n constructor(init: { timeout: number; method: string; path: string }) {\n super(\n ItdErrorKind.Timeout,\n `Запрос ${init.method} ${init.path} превысил таймаут ${init.timeout} мс`,\n );\n this.name = 'ItdTimeoutError';\n this.timeout = init.timeout;\n this.method = init.method;\n this.path = init.path;\n }\n}\n\n/** Запрос отменён через переданный `AbortSignal`. */\nexport class ItdAbortError extends ItdError {\n constructor(message = 'Запрос отменён') {\n super(ItdErrorKind.Abort, message);\n this.name = 'ItdAbortError';\n }\n}\n\n/**\n * Некорректная конфигурация или аргументы — обнаружено до обращения к сети.\n *\n * Этим же классом сообщают о нарушенных инвариантах билдеры: например, опрос\n * с одним вариантом ответа.\n */\nexport class ItdConfigError extends ItdError {\n constructor(message: string) {\n super(ItdErrorKind.Config, message);\n this.name = 'ItdConfigError';\n }\n}\n\n/** Любая ошибка, порождённая этой библиотекой. */\nexport function isItdError(value: unknown): value is ItdError {\n return typeof value === 'object' && value !== null && ITD_ERROR in value;\n}\n\n/** Ошибка, пришедшая от сервера итд.com (статус ≥ 400). */\nexport function isItdApiError(value: unknown): value is ItdApiError {\n return isItdError(value) && value.kind === ItdErrorKind.Api;\n}\n\n/**\n * Проверяет разновидность ошибки API.\n *\n * Намеренно не `instanceof`: две копии пакета в дереве зависимостей или смешение сборок\n * ESM и CJS дают разные классы для одной и той же ошибки, и проверка по классу молча\n * перестаёт срабатывать. Поле {@link ItdApiError.apiKind} от этого не зависит.\n */\nfunction hasApiKind(value: unknown, kind: ItdApiErrorKind): boolean {\n return isItdApiError(value) && value.apiKind === kind;\n}\n\n/** Ошибка валидации: `VALIDATION_ERROR` либо статус `400`/`422`. */\nexport function isItdValidationError(value: unknown): value is ItdValidationError {\n return hasApiKind(value, ItdApiErrorKind.Validation);\n}\n\n/** Ошибка авторизации: истёкший или отозванный токен. */\nexport function isItdAuthError(value: unknown): value is ItdAuthError {\n return hasApiKind(value, ItdApiErrorKind.Auth);\n}\n\n/** Доступ запрещён либо действие ограничено настройками приватности. */\nexport function isItdForbiddenError(value: unknown): value is ItdForbiddenError {\n return hasApiKind(value, ItdApiErrorKind.Forbidden);\n}\n\n/** Сущность не найдена. */\nexport function isItdNotFoundError(value: unknown): value is ItdNotFoundError {\n return hasApiKind(value, ItdApiErrorKind.NotFound);\n}\n\n/** Сущность уже существует. */\nexport function isItdConflictError(value: unknown): value is ItdConflictError {\n return hasApiKind(value, ItdApiErrorKind.Conflict);\n}\n\n/** Превышен лимит запросов. */\nexport function isItdRateLimitError(value: unknown): value is ItdRateLimitError {\n return hasApiKind(value, ItdApiErrorKind.RateLimit);\n}\n\n/** Действие требует подтверждённого телефона. Ссылка — в `verificationUrl`. */\nexport function isItdPhoneVerificationError(value: unknown): value is ItdPhoneVerificationError {\n return hasApiKind(value, ItdApiErrorKind.PhoneVerification);\n}\n\n/** Ошибка на стороне сервера (`5xx`). */\nexport function isItdServerError(value: unknown): value is ItdServerError {\n return hasApiKind(value, ItdApiErrorKind.Server);\n}\n","import { ItdConfigError } from '../core/errors.js';\nimport type { UserId } from '../types/models.js';\nimport type { CreateCommentInput, FileInput } from '../types/params.js';\nimport { BUILDER, type BuilderInput, type ItdBuilder, resolveInput } from './base.js';\n\n/** Внутреннее состояние {@link CommentBuilder}. */\ninterface CommentState extends CreateCommentInput {\n content: string;\n attachmentIds: string[];\n files: FileInput[];\n /** Голосовой комментарий: текста быть не должно, вложение ровно одно. */\n voice: boolean;\n}\n\n/**\n * Проверяет данные комментария.\n *\n * @throws {ItdConfigError} если комментарий пуст или голосовой собран неверно\n */\nexport function validateComment(input: CreateCommentInput): CreateCommentInput {\n const content = typeof input?.content === 'string' ? input.content : '';\n const attachmentIds = input?.attachmentIds ?? [];\n const files = input?.files ?? [];\n\n const hasContent = content.trim() !== '';\n const hasAttachments = attachmentIds.length > 0 || files.length > 0;\n\n if (!hasContent && !hasAttachments) {\n throw new ItdConfigError('Комментарий пуст: нужен текст или вложение');\n }\n\n return input;\n}\n\n/** Дополнительная проверка голосового комментария. */\nfunction validateVoice(state: CommentState): void {\n if (state.content.trim() !== '') {\n throw new ItdConfigError(\n 'У голосового комментария не может быть текста: API принимает либо текст, либо аудио',\n );\n }\n\n const total = state.files.length + state.attachmentIds.length;\n if (total !== 1) {\n throw new ItdConfigError(\n `Голосовой комментарий требует ровно одно аудиовложение, передано: ${total}`,\n );\n }\n}\n\n/**\n * Билдер комментария и ответа на комментарий.\n *\n * Неизменяемый: каждый вызов возвращает новый экземпляр. Создаётся функцией {@link comment}.\n */\nexport class CommentBuilder implements ItdBuilder<CreateCommentInput> {\n /** @internal */\n readonly [BUILDER] = true as const;\n\n readonly #state: CommentState;\n\n /** @internal Создавайте билдер функцией {@link comment}. */\n constructor(state: CommentState) {\n this.#state = state;\n }\n\n /** Задаёт текст комментария. */\n content(text: string): CommentBuilder {\n return new CommentBuilder({ ...this.#state, content: text });\n }\n\n /** Прикладывает файл — он будет загружен перед отправкой. */\n attach(file: FileInput): CommentBuilder {\n return new CommentBuilder({ ...this.#state, files: [...this.#state.files, file] });\n }\n\n /** Прикладывает уже загруженное вложение. */\n attachId(attachmentId: string): CommentBuilder {\n return new CommentBuilder({\n ...this.#state,\n attachmentIds: [...this.#state.attachmentIds, attachmentId],\n });\n }\n\n /**\n * Делает комментарий голосовым.\n *\n * Текста у такого комментария быть не должно, а вложение ровно одно — аудио в формате\n * `audio/ogg`. Так его принимает API.\n *\n * @example\n * ```ts\n * await itd.posts.comment(postId, (c) => c.voice('./answer.ogg'));\n * ```\n */\n voice(audio: FileInput): CommentBuilder {\n return new CommentBuilder({ ...this.#state, files: [audio], voice: true });\n }\n\n /**\n * Кому адресован ответ.\n *\n * Имеет смысл только в `itd.comments.reply()`; при отправке комментария к посту\n * это поле вызовет ошибку.\n */\n replyTo(userId: UserId): CommentBuilder {\n return new CommentBuilder({ ...this.#state, replyToUserId: userId });\n }\n\n build(): CreateCommentInput {\n const { content, attachmentIds, files, voice, ...rest } = this.#state;\n\n if (voice) validateVoice(this.#state);\n\n return validateComment({\n ...rest,\n content,\n ...(attachmentIds.length > 0 ? { attachmentIds } : {}),\n ...(files.length > 0 ? { files } : {}),\n });\n }\n\n toJSON(): CreateCommentInput {\n return this.build();\n }\n}\n\n/**\n * Начинает сборку комментария.\n *\n * @param content текст; можно задать позже методом {@link CommentBuilder.content}\n *\n * @example\n * ```ts\n * import { comment } from 'itd-api';\n *\n * await itd.posts.comment(postId, comment('согласен').attach('./meme.png'));\n * ```\n */\nexport function comment(content = ''): CommentBuilder {\n return new CommentBuilder({ content, attachmentIds: [], files: [], voice: false });\n}\n\n/** Что принимает параметр комментария: объект, билдер или функция-настройщик. */\nexport type CommentInput = BuilderInput<CreateCommentInput, CommentBuilder>;\n\n/**\n * Приводит любую форму входа к готовым данным комментария.\n *\n * @param allowReplyTo разрешено ли поле `replyToUserId`; в комментарии к посту — нет\n */\nexport function resolveComment(input: CommentInput, allowReplyTo = false): CreateCommentInput {\n const resolved = resolveInput(input, () => comment(), validateComment);\n\n if (!allowReplyTo && resolved.replyToUserId !== undefined) {\n throw new ItdConfigError(\n 'replyTo применим только к ответу на комментарий (itd.comments.reply). ' +\n 'В комментарии к посту адресат не указывается.',\n );\n }\n\n return resolved;\n}\n","import { ItdConfigError } from '../core/errors.js';\nimport type { CreatePollInput } from '../types/params.js';\nimport { BUILDER, type BuilderInput, type ItdBuilder, resolveInput } from './base.js';\n\n/** Минимальное число вариантов ответа. */\nconst MIN_OPTIONS = 2;\n\n/** Ограничения опроса — те же, что действуют в интерфейсе итд.com. */\nconst MAX_OPTIONS = 10;\nconst MAX_QUESTION_LENGTH = 200;\nconst MAX_OPTION_LENGTH = 100;\n\n/**\n * Проверяет данные опроса.\n *\n * Применяется и к билдеру, и к обычному объекту — правила одни и те же.\n *\n * @throws {ItdConfigError} если вопрос пуст, вариантов меньше двух или есть дубли\n */\nexport function validatePoll(input: CreatePollInput): CreatePollInput {\n const question = input?.question;\n\n if (typeof question !== 'string' || question.trim() === '') {\n throw new ItdConfigError('Опрос требует непустого вопроса');\n }\n\n if (question.trim().length > MAX_QUESTION_LENGTH) {\n throw new ItdConfigError(\n `Вопрос длиннее ${MAX_QUESTION_LENGTH} символов (передано ${question.trim().length})`,\n );\n }\n\n const options = Array.isArray(input.options) ? input.options : [];\n\n const texts = options.map((option, index) => {\n const text = typeof option?.text === 'string' ? option.text.trim() : '';\n if (text === '') {\n throw new ItdConfigError(`Вариант ответа №${index + 1} пуст — у каждого должен быть текст`);\n }\n if (text.length > MAX_OPTION_LENGTH) {\n throw new ItdConfigError(\n `Вариант ответа №${index + 1} длиннее ${MAX_OPTION_LENGTH} символов (передано ${text.length})`,\n );\n }\n return text;\n });\n\n if (texts.length < MIN_OPTIONS) {\n throw new ItdConfigError(\n `Опрос требует минимум ${MIN_OPTIONS} варианта, передано: ${texts.length}`,\n );\n }\n\n if (texts.length > MAX_OPTIONS) {\n throw new ItdConfigError(\n `Опрос допускает не больше ${MAX_OPTIONS} вариантов, передано: ${texts.length}`,\n );\n }\n\n const seen = new Set<string>();\n for (const text of texts) {\n if (seen.has(text)) {\n throw new ItdConfigError(`Вариант «${text}» повторяется — варианты должны различаться`);\n }\n seen.add(text);\n }\n\n return {\n question: question.trim(),\n options: texts.map((text) => ({ text })),\n // Поле обязательно: без него сервер отвергает создание поста с опросом,\n // даже когда выбор одиночный.\n multipleChoice: input.multipleChoice ?? false,\n };\n}\n\n/**\n * Билдер опроса.\n *\n * Неизменяемый: каждый вызов возвращает новый экземпляр, поэтому заготовку можно\n * переиспользовать, не боясь её испортить. Создаётся функцией {@link poll}.\n */\nexport class PollBuilder implements ItdBuilder<CreatePollInput> {\n /** @internal */\n readonly [BUILDER] = true as const;\n\n readonly #state: CreatePollInput;\n\n /** @internal Создавайте билдер функцией {@link poll}. */\n constructor(state: CreatePollInput) {\n this.#state = state;\n }\n\n /** Задаёт вопрос. */\n question(text: string): PollBuilder {\n return new PollBuilder({ ...this.#state, question: text });\n }\n\n /** Добавляет один вариант ответа. */\n option(text: string): PollBuilder {\n return new PollBuilder({ ...this.#state, options: [...this.#state.options, { text }] });\n }\n\n /**\n * Добавляет несколько вариантов сразу.\n *\n * @example\n * ```ts\n * poll('ну как?').options('да', 'нет', 'не знаю');\n * ```\n */\n options(...texts: string[]): PollBuilder {\n return new PollBuilder({\n ...this.#state,\n options: [...this.#state.options, ...texts.map((text) => ({ text }))],\n });\n }\n\n /** Разрешает выбор нескольких вариантов. */\n multipleChoice(enabled = true): PollBuilder {\n return new PollBuilder({ ...this.#state, multipleChoice: enabled });\n }\n\n build(): CreatePollInput {\n return validatePoll(this.#state);\n }\n\n toJSON(): CreatePollInput {\n return this.build();\n }\n}\n\n/**\n * Начинает сборку опроса.\n *\n * @param question вопрос; можно задать позже методом {@link PollBuilder.question}\n *\n * @example\n * ```ts\n * import { poll } from 'itd-api';\n *\n * const q = poll('Какой язык лучше?')\n * .options('TypeScript', 'JavaScript')\n * .multipleChoice();\n *\n * await itd.posts.create({ content: 'голосуем', poll: q });\n * ```\n */\nexport function poll(question = ''): PollBuilder {\n return new PollBuilder({ question, options: [] });\n}\n\n/** Что принимает параметр опроса: объект, билдер или функция-настройщик. */\nexport type PollInput = BuilderInput<CreatePollInput, PollBuilder>;\n\n/** Приводит любую форму входа к готовым данным опроса. */\nexport function resolvePoll(input: PollInput): CreatePollInput {\n return resolveInput(input, () => poll(), validatePoll);\n}\n","import { ItdConfigError } from '../core/errors.js';\nimport type { Span, UserId } from '../types/models.js';\nimport type { CreatePostInput, FileInput } from '../types/params.js';\nimport { BUILDER, type BuilderInput, type ItdBuilder, resolveInput } from './base.js';\nimport { type PollInput, resolvePoll } from './poll.js';\n\n/** UUID любой версии. */\nconst UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\n/**\n * Проверяет данные поста.\n *\n * Отдельного внимания заслуживает `wallRecipientId`: API принимает там **только UUID**,\n * а имя пользователя молча приводит к ошибке на сервере. Проверка здесь превращает\n * это в понятное сообщение до отправки запроса.\n *\n * @throws {ItdConfigError} если пост пуст или получатель стены задан именем пользователя\n */\nexport function validatePost(input: CreatePostInput): CreatePostInput {\n const content = typeof input?.content === 'string' ? input.content : '';\n const attachmentIds = input?.attachmentIds ?? [];\n const files = input?.files ?? [];\n\n const hasContent = content.trim() !== '';\n const hasAttachments = attachmentIds.length > 0 || files.length > 0;\n const hasPoll = Boolean(input?.poll);\n\n if (!hasContent && !hasAttachments && !hasPoll) {\n throw new ItdConfigError('Пост пуст: нужен текст, вложение или опрос');\n }\n\n const wallRecipientId = input.wallRecipientId;\n if (wallRecipientId !== undefined && wallRecipientId !== null) {\n if (!UUID_PATTERN.test(wallRecipientId)) {\n throw new ItdConfigError(\n `wallRecipientId должен быть UUID, а не именем пользователя (получено: «${wallRecipientId}»). ` +\n 'Идентификатор можно взять из профиля: (await itd.users.get(username)).id',\n );\n }\n }\n\n // Опрос внутри обычного объекта тоже может быть билдером или функцией — приводим его\n // здесь, чтобы форма записи не влияла на результат и на проверки.\n return input.poll === undefined ? input : { ...input, poll: resolvePoll(input.poll) };\n}\n\n/** Внутреннее состояние {@link PostBuilder}. */\ninterface PostState extends CreatePostInput {\n content: string;\n attachmentIds: string[];\n files: FileInput[];\n}\n\n/**\n * Билдер поста.\n *\n * Неизменяемый: каждый вызов возвращает новый экземпляр, поэтому заготовку можно\n * переиспользовать. Создаётся функцией {@link post}.\n *\n * @example Заготовка для нескольких постов\n * ```ts\n * const onWall = post().onWall(userId);\n *\n * await itd.posts.create(onWall.content('первый'));\n * await itd.posts.create(onWall.content('второй')); // заготовка не испорчена\n * ```\n */\nexport class PostBuilder implements ItdBuilder<CreatePostInput> {\n /** @internal */\n readonly [BUILDER] = true as const;\n\n readonly #state: PostState;\n\n /** @internal Создавайте билдер функцией {@link post}. */\n constructor(state: PostState) {\n this.#state = state;\n }\n\n /** Задаёт текст поста, заменяя прежний. */\n content(text: string): PostBuilder {\n return new PostBuilder({ ...this.#state, content: text });\n }\n\n /** Дописывает текст к уже заданному. */\n append(text: string): PostBuilder {\n const separator = this.#state.content === '' ? '' : '\\n';\n return new PostBuilder({ ...this.#state, content: this.#state.content + separator + text });\n }\n\n /**\n * Задаёт разметку текста.\n *\n * Библиотека разметку не генерирует: хэштеги и упоминания нужно размечать самостоятельно\n * либо не размечать вовсе.\n */\n spans(spans: Span[]): PostBuilder {\n return new PostBuilder({ ...this.#state, spans });\n }\n\n /**\n * Публикует пост на стене другого пользователя.\n *\n * @param userId **UUID** пользователя; имя пользователя не подойдёт\n */\n onWall(userId: UserId): PostBuilder {\n return new PostBuilder({ ...this.#state, wallRecipientId: userId });\n }\n\n /**\n * Прикладывает файл — он будет загружен перед публикацией.\n *\n * Порядок вызовов сохраняется в порядке вложений.\n */\n attach(file: FileInput): PostBuilder {\n return new PostBuilder({ ...this.#state, files: [...this.#state.files, file] });\n }\n\n /** Прикладывает уже загруженное вложение по его идентификатору. */\n attachId(attachmentId: string): PostBuilder {\n return new PostBuilder({\n ...this.#state,\n attachmentIds: [...this.#state.attachmentIds, attachmentId],\n });\n }\n\n /**\n * Добавляет опрос.\n *\n * Принимает объект, {@link PollBuilder} или функцию-настройщик.\n *\n * @example\n * ```ts\n * post('голосуем').poll((q) => q.question('ну как?').options('да', 'нет'));\n * ```\n */\n poll(input: PollInput): PostBuilder {\n return new PostBuilder({ ...this.#state, poll: resolvePoll(input) });\n }\n\n build(): CreatePostInput {\n const { content, attachmentIds, files, ...rest } = this.#state;\n\n return validatePost({\n ...rest,\n ...(content !== '' ? { content } : {}),\n ...(attachmentIds.length > 0 ? { attachmentIds } : {}),\n ...(files.length > 0 ? { files } : {}),\n });\n }\n\n toJSON(): CreatePostInput {\n return this.build();\n }\n}\n\n/**\n * Начинает сборку поста.\n *\n * @param content текст; можно задать позже методом {@link PostBuilder.content}\n *\n * @example\n * ```ts\n * import { post } from 'itd-api';\n *\n * await itd.posts.create(\n * post('смотрите что нашёл')\n * .attach('./photo.jpg')\n * .poll((q) => q.question('нравится?').options('да', 'нет')),\n * );\n * ```\n */\nexport function post(content = ''): PostBuilder {\n return new PostBuilder({ content, attachmentIds: [], files: [] });\n}\n\n/** Что принимает параметр поста: объект, билдер или функция-настройщик. */\nexport type PostInput = BuilderInput<CreatePostInput, PostBuilder>;\n\n/** Приводит любую форму входа к готовым данным поста. */\nexport function resolvePost(input: PostInput): CreatePostInput {\n return resolveInput(input, () => post(), validatePost);\n}\n","/**\n * Перечисления API итд.com.\n *\n * Здесь намеренно не используется `enum` из TypeScript. Вместо него — пара «замороженный\n * объект + одноимённый тип». Такой приём даёт всё, ради чего берут `enum`\n * (`FeedTab.Popular`, перебор значений в рантайме), и при этом:\n *\n * - **стирается без остатка** — `enum` порождает рантайм-код и отвергается средами,\n * которые просто срезают типы (`node --experimental-strip-types`);\n * - **не запрещает обычные строки** — `itd.posts.list({ tab: 'popular' })` остаётся валидным,\n * тогда как строковый `enum` считает это ошибкой типа и вынуждает всех импортировать себя;\n * - **позволяет открытые множества** — там, где документация перечисляет значения не полностью,\n * тип расширяется через {@link Loose}, а объект остаётся справочником известных значений.\n *\n * @example\n * ```ts\n * import { FeedTab } from 'itd-api';\n *\n * await itd.posts.list({ tab: FeedTab.Popular }); // без магических строк\n * await itd.posts.list({ tab: 'popular' }); // и так тоже можно\n *\n * Object.values(FeedTab); // ['popular', 'following', 'clan']\n * ```\n *\n * @packageDocumentation\n */\n\n/**\n * Открытое строковое перечисление.\n *\n * Даёт автодополнение известных значений, но не ломается, если сервер пришлёт новое.\n * Используется там, где документация API перечисляет значения не полностью («`everyone` и др.»).\n */\nexport type Loose<T extends string> = T | (string & {});\n\n/**\n * Вкладка ленты `GET /api/posts`.\n *\n * Множество закрытое: неизвестное значение сервер отвергнет.\n */\nexport const FeedTab = Object.freeze({\n /** Популярное. Курсор здесь — номер страницы в виде строки (`\"2\"`, `\"6\"`…). */\n Popular: 'popular',\n /** Записи тех, на кого вы подписаны. Курсор — отметка времени последнего поста. */\n Following: 'following',\n /** Лента клана. Курсор, как и в подписках, — отметка времени. */\n Clan: 'clan',\n} as const);\nexport type FeedTab = (typeof FeedTab)[keyof typeof FeedTab];\n\n/** Порядок комментариев к посту. */\nexport const CommentSort = Object.freeze({\n /** Сначала новые. */\n Newest: 'newest',\n /** Сначала старые. */\n Oldest: 'oldest',\n /** Сначала популярные. */\n Popular: 'popular',\n} as const);\nexport type CommentSort = (typeof CommentSort)[keyof typeof CommentSort];\n\n/** Тип вложения. */\nexport const AttachmentType = Object.freeze({\n Image: 'image',\n Video: 'video',\n /** Голосовые комментарии: `audio/ogg`, с полем `duration`. */\n Audio: 'audio',\n} as const);\nexport type AttachmentType = (typeof AttachmentType)[keyof typeof AttachmentType];\n\n/**\n * Тип фрагмента разметки в тексте поста или комментария.\n *\n * Первые два сервер расставляет сам при разборе текста, остальные приходят от редактора.\n * Тип открытый: набор может пополниться.\n *\n * @example\n * ```ts\n * await itd.posts.update(postId, {\n * content: 'жирное слово',\n * spans: [{ type: SpanType.Bold, offset: 0, length: 6 }],\n * });\n * ```\n */\nexport const SpanType = Object.freeze({\n /** Хэштег. Название без решётки лежит в `tag`. */\n Hashtag: 'hashtag',\n /** Упоминание. Имя пользователя лежит в `tag`. */\n Mention: 'mention',\n /** Ссылка. Адрес лежит в `url`, а не в `tag`. */\n Link: 'link',\n Bold: 'bold',\n Italic: 'italic',\n Underline: 'underline',\n /** Зачёркнутый. */\n Strike: 'strike',\n /** Спойлер: текст скрыт до нажатия. */\n Spoiler: 'spoiler',\n /** Моноширинный. */\n Monospace: 'monospace',\n Quote: 'quote',\n} as const);\nexport type SpanType = Loose<(typeof SpanType)[keyof typeof SpanType]>;\n\n/** На что подаётся жалоба. */\nexport const ReportTargetType = Object.freeze({\n Post: 'post',\n Comment: 'comment',\n User: 'user',\n} as const);\nexport type ReportTargetType = (typeof ReportTargetType)[keyof typeof ReportTargetType];\n\n/** Причина жалобы. Множество закрытое. */\nexport const ReportReason = Object.freeze({\n Spam: 'spam',\n Violence: 'violence',\n Hate: 'hate',\n Adult: 'adult',\n Fraud: 'fraud',\n Other: 'other',\n} as const);\nexport type ReportReason = (typeof ReportReason)[keyof typeof ReportReason];\n\n/** Состояние realtime-соединения. */\nexport const RealtimeStatus = Object.freeze({\n Connecting: 'connecting',\n Connected: 'connected',\n Error: 'error',\n Disconnected: 'disconnected',\n} as const);\nexport type RealtimeStatus = (typeof RealtimeStatus)[keyof typeof RealtimeStatus];\n\n/**\n * Кто может писать на стену профиля.\n *\n * Документация перечисляет значения не полностью, поэтому тип открытый: объект ниже —\n * справочник известных значений, но сервер может прислать и другое.\n */\nexport const WallAccess = Object.freeze({\n Everyone: 'everyone',\n} as const);\nexport type WallAccess = Loose<(typeof WallAccess)[keyof typeof WallAccess]>;\n\n/** Кто видит реакции пользователя. Список в документации неполный. */\nexport const LikesVisibility = Object.freeze({\n Everyone: 'everyone',\n /** Только взаимные подписки. */\n Mutual: 'mutual',\n} as const);\nexport type LikesVisibility = Loose<(typeof LikesVisibility)[keyof typeof LikesVisibility]>;\n\n/**\n * Канонический тип уведомления (новое поколение имён).\n *\n * REST-эндпоинт `/api/notifications/` отдаёт старые имена (`like`, `comment`, `reply`,\n * `repost`, `mention`), SSE-поток — новые. Библиотека приводит их к этому набору,\n * сохраняя исходное значение в поле `rawType`.\n */\nexport const NotificationType = Object.freeze({\n /** Реакция на пост. Старое имя — `like`. */\n PostReaction: 'post_reaction',\n /** Комментарий к посту. Старое имя — `comment`. */\n PostComment: 'post_comment',\n /** Ответ на комментарий. Старое имя — `reply`. */\n CommentReply: 'comment_reply',\n /** Репост. Старое имя — `repost`. */\n PostRepost: 'post_repost',\n /** Упоминание в посте. Старое имя — `mention`. */\n PostMention: 'post_mention',\n /** Реакция на комментарий. */\n CommentReaction: 'comment_reaction',\n /** Упоминание в комментарии. */\n CommentMention: 'comment_mention',\n /** Запись на вашей стене. */\n WallPost: 'wall_post',\n /** На вас подписались. */\n Follow: 'follow',\n /** Заявка на подписку (закрытый профиль). */\n FollowRequest: 'follow_request',\n /** Заявка на подписку принята. */\n FollowAccepted: 'follow_accepted',\n /** Верификация одобрена. Приходит только по REST. */\n VerificationApproved: 'verification_approved',\n /** Верификация отклонена. Приходит только по REST. */\n VerificationRejected: 'verification_rejected',\n} as const);\nexport type NotificationType = Loose<(typeof NotificationType)[keyof typeof NotificationType]>;\n\n/**\n * Строковые коды ошибок из поля `code`.\n *\n * Ключи намеренно повторяют написание сервера: код из ответа API можно найти здесь\n * поиском один в один, без мысленного перевода регистра.\n *\n * Список открыт — сервер может добавить новый код, и это не должно ломать типизацию.\n *\n * @example\n * ```ts\n * if (err.hasCode(ItdErrorCode.OTP_INVALID)) await restartOtpFlow();\n * ```\n */\nexport const ItdErrorCode = Object.freeze({\n BAD_REQUEST: 'BAD_REQUEST',\n UNAUTHORIZED: 'UNAUTHORIZED',\n ACCESS_DENIED: 'ACCESS_DENIED',\n ENTITY_NOT_FOUND: 'ENTITY_NOT_FOUND',\n ENTITY_ALREADY_EXISTS: 'ENTITY_ALREADY_EXISTS',\n VALIDATION_ERROR: 'VALIDATION_ERROR',\n BUSINESS_RULE_VIOLATION: 'BUSINESS_RULE_VIOLATION',\n RATE_LIMIT_EXCEEDED: 'RATE_LIMIT_EXCEEDED',\n UNKNOWN_ERROR: 'UNKNOWN_ERROR',\n /** Сервер отвечает так на `404`, `ENTITY_NOT_FOUND` в этом случае не приходит. */\n NOT_FOUND: 'NOT_FOUND',\n /** На практике не приходит: вместо него сервер шлёт `TURNSTILE_VERIFICATION_FAILED`. */\n CAPTCHA_FAILED: 'CAPTCHA_FAILED',\n /** Капча не пройдена: токен Turnstile недействителен, просрочен или уже использован. */\n TURNSTILE_VERIFICATION_FAILED: 'TURNSTILE_VERIFICATION_FAILED',\n OTP_INVALID: 'OTP_INVALID',\n /** `flowToken` неизвестен или просрочен — поток подтверждения нужно начинать заново. */\n INVALID_FLOW_TOKEN: 'INVALID_FLOW_TOKEN',\n ACCOUNT_DEACTIVATED: 'ACCOUNT_DEACTIVATED',\n ACCOUNT_EMAIL_DOMAIN_NOT_ALLOWED: 'ACCOUNT_EMAIL_DOMAIN_NOT_ALLOWED',\n ACCOUNT_INVALID_CREDENTIALS: 'ACCOUNT_INVALID_CREDENTIALS',\n ACCOUNT_TEMPORARILY_LOCKED: 'ACCOUNT_TEMPORARILY_LOCKED',\n ACCOUNT_CURRENT_PASSWORD_INCORRECT: 'ACCOUNT_CURRENT_PASSWORD_INCORRECT',\n SESSION_EXPIRED: 'SESSION_EXPIRED',\n SESSION_REVOKED: 'SESSION_REVOKED',\n SESSION_INVALID_REFRESH_TOKEN: 'SESSION_INVALID_REFRESH_TOKEN',\n /** Запрос обновления пришёл без cookie `refresh_token` — продлевать нечего. */\n REFRESH_TOKEN_MISSING: 'REFRESH_TOKEN_MISSING',\n /** Cookie `refresh_token` есть, но сессии за ней уже нет: отозвана или истекла. */\n SESSION_NOT_FOUND: 'SESSION_NOT_FOUND',\n MISSING_FLOW_TOKEN: 'MISSING_FLOW_TOKEN',\n PROFILE_USERNAME_TAKEN: 'PROFILE_USERNAME_TAKEN',\n PROFILE_RESTRICTION_ACTIVE: 'PROFILE_RESTRICTION_ACTIVE',\n PROFILE_MODIFICATION_RESTRICTED: 'PROFILE_MODIFICATION_RESTRICTED',\n CONTENT_MODERATION_FAILED: 'CONTENT_MODERATION_FAILED',\n FILE_TOO_LARGE: 'FILE_TOO_LARGE',\n UNSUPPORTED_FILE_TYPE: 'UNSUPPORTED_FILE_TYPE',\n UPLOAD_FAILED: 'UPLOAD_FAILED',\n VIDEO_REQUIRES_VERIFICATION: 'VIDEO_REQUIRES_VERIFICATION',\n PHONE_VERIFICATION_REQUIRED: 'PHONE_VERIFICATION_REQUIRED',\n WRITE_ACCESS_RESTRICTED: 'WRITE_ACCESS_RESTRICTED',\n} as const);\nexport type ItdErrorCode = Loose<(typeof ItdErrorCode)[keyof typeof ItdErrorCode]>;\n","import { ItdConfigError } from '../core/errors.js';\nimport { ReportReason, ReportTargetType } from '../types/enums.js';\nimport type { CreateReportInput } from '../types/params.js';\nimport { BUILDER, type BuilderInput, type ItdBuilder, resolveInput } from './base.js';\n\nconst REASONS = new Set<string>(Object.values(ReportReason));\nconst TARGET_TYPES = new Set<string>(Object.values(ReportTargetType));\n\n/**\n * Проверяет данные жалобы.\n *\n * @throws {ItdConfigError} если объект жалобы или причина заданы неверно\n */\nexport function validateReport(input: CreateReportInput): CreateReportInput {\n if (!input?.targetId || typeof input.targetId !== 'string') {\n throw new ItdConfigError('Жалоба требует идентификатор объекта (targetId)');\n }\n\n if (!TARGET_TYPES.has(input.targetType)) {\n throw new ItdConfigError(\n `targetType должен быть одним из ${[...TARGET_TYPES].join(', ')}, ` +\n `получено: ${String(input.targetType)}`,\n );\n }\n\n if (!REASONS.has(input.reason)) {\n throw new ItdConfigError(\n `Неизвестная причина жалобы «${String(input.reason)}». Допустимые: ${[...REASONS].join(', ')}`,\n );\n }\n\n return input;\n}\n\n/**\n * Билдер жалобы.\n *\n * Точка входа задаёт объект жалобы и его тип одновременно, поэтому рассогласовать\n * `targetType` и `targetId` невозможно. Создаётся объектом {@link report}.\n */\nexport class ReportBuilder implements ItdBuilder<CreateReportInput> {\n /** @internal */\n readonly [BUILDER] = true as const;\n\n readonly #state: Partial<CreateReportInput>;\n\n /** @internal Создавайте билдер через {@link report}. */\n constructor(state: Partial<CreateReportInput>) {\n this.#state = state;\n }\n\n /** Указывает причину жалобы. */\n reason(reason: ReportReason): ReportBuilder {\n return new ReportBuilder({ ...this.#state, reason });\n }\n\n /** Добавляет пояснение в свободной форме. */\n description(text: string): ReportBuilder {\n return new ReportBuilder({ ...this.#state, description: text });\n }\n\n build(): CreateReportInput {\n return validateReport(this.#state as CreateReportInput);\n }\n\n toJSON(): CreateReportInput {\n return this.build();\n }\n}\n\nfunction start(targetType: ReportTargetType, targetId: string): ReportBuilder {\n return new ReportBuilder({ targetType, targetId });\n}\n\n/**\n * Начинает сборку жалобы.\n *\n * Тип объекта выбирается точкой входа, так что указать идентификатор комментария\n * с типом «пост» нельзя в принципе.\n *\n * @example\n * ```ts\n * import { report, ReportReason } from 'itd-api';\n *\n * await itd.reports.create(report.post(postId).reason(ReportReason.Spam));\n * await itd.reports.create(report.user(userId).reason('fraud').description('пишет в личку'));\n * ```\n */\nexport const report = Object.freeze({\n /** Жалоба на пост. */\n post: (postId: string) => start(ReportTargetType.Post, postId),\n /** Жалоба на комментарий. */\n comment: (commentId: string) => start(ReportTargetType.Comment, commentId),\n /** Жалоба на пользователя. */\n user: (userId: string) => start(ReportTargetType.User, userId),\n});\n\n/** Что принимает параметр жалобы: объект, билдер или функция-настройщик. */\nexport type ReportInput = BuilderInput<CreateReportInput, ReportBuilder>;\n\n/** Приводит любую форму входа к готовым данным жалобы. */\nexport function resolveReport(input: ReportInput): CreateReportInput {\n return resolveInput(input, () => new ReportBuilder({}), validateReport);\n}\n","var defaultParseOptions = {\n decodeValues: true,\n map: false,\n silent: false,\n split: \"auto\", // auto = split strings but not arrays\n};\n\nfunction isForbiddenKey(key) {\n return typeof key !== \"string\" || key in {};\n}\n\nfunction createNullObj() {\n return Object.create(null);\n}\n\nfunction isNonEmptyString(str) {\n return typeof str === \"string\" && !!str.trim();\n}\n\nfunction parseString(setCookieValue, options) {\n var parts = setCookieValue.split(\";\").filter(isNonEmptyString);\n\n var nameValuePairStr = parts.shift();\n if (!nameValuePairStr) {\n return null;\n }\n var parsed = parseNameValuePair(nameValuePairStr);\n var name = parsed.name;\n var value = parsed.value;\n\n options = options\n ? Object.assign({}, defaultParseOptions, options)\n : defaultParseOptions;\n\n if (isForbiddenKey(name)) {\n return null;\n }\n\n try {\n value = options.decodeValues ? decodeURIComponent(value) : value; // decode cookie value\n } catch (e) {\n console.error(\n \"set-cookie-parser: failed to decode cookie value. Set options.decodeValues=false to disable decoding.\",\n e\n );\n }\n\n var cookie = createNullObj();\n cookie.name = name;\n cookie.value = value;\n\n parts.forEach(function (part) {\n var sides = part.split(\"=\");\n var key = sides.shift().trim().toLowerCase();\n if (isForbiddenKey(key)) {\n return;\n }\n var value = sides.join(\"=\").trim();\n if (key === \"expires\") {\n cookie.expires = new Date(value);\n } else if (key === \"max-age\") {\n var n = parseInt(value, 10);\n if (!Number.isNaN(n)) cookie.maxAge = n;\n } else if (key === \"secure\") {\n cookie.secure = true;\n } else if (key === \"httponly\") {\n cookie.httpOnly = true;\n } else if (key === \"samesite\") {\n cookie.sameSite = value;\n } else if (key === \"partitioned\") {\n cookie.partitioned = true;\n } else if (key) {\n cookie[key] = value;\n }\n });\n\n return cookie;\n}\n\nfunction parseNameValuePair(nameValuePairStr) {\n // Parses name-value-pair according to rfc6265bis draft\n\n var name = \"\";\n var value = \"\";\n var nameValueArr = nameValuePairStr.split(\"=\");\n if (nameValueArr.length > 1) {\n name = nameValueArr.shift();\n value = nameValueArr.join(\"=\"); // everything after the first =, joined by a \"=\" if there was more than one part\n } else {\n value = nameValuePairStr;\n }\n\n return { name: name, value: value };\n}\n\nfunction parseSetCookie(input, options) {\n options = options\n ? Object.assign({}, defaultParseOptions, options)\n : defaultParseOptions;\n\n if (!input) {\n if (!options.map) {\n return [];\n } else {\n return createNullObj();\n }\n }\n\n if (input.headers) {\n if (typeof input.headers.getSetCookie === \"function\") {\n // for fetch responses - they combine headers of the same type in the headers array,\n // but getSetCookie returns an uncombined array\n input = input.headers.getSetCookie();\n } else if (input.headers[\"set-cookie\"]) {\n // fast-path for node.js (which automatically normalizes header names to lower-case)\n input = input.headers[\"set-cookie\"];\n } else {\n // slow-path for other environments - see #25\n var sch =\n input.headers[\n Object.keys(input.headers).find(function (key) {\n return key.toLowerCase() === \"set-cookie\";\n })\n ];\n // warn if called on a request-like object with a cookie header rather than a set-cookie header - see #34, 36\n if (!sch && input.headers.cookie && !options.silent) {\n console.warn(\n \"Warning: set-cookie-parser appears to have been called on a request object. It is designed to parse Set-Cookie headers from responses, not Cookie headers from requests. Set the option {silent: true} to suppress this warning.\"\n );\n }\n input = sch;\n }\n }\n\n var split = options.split;\n var isArray = Array.isArray(input);\n\n if (split === \"auto\") {\n split = !isArray;\n }\n\n if (!isArray) {\n input = [input];\n }\n\n input = input.filter(isNonEmptyString);\n\n if (split) {\n input = input.map(splitCookiesString).flat();\n }\n\n if (!options.map) {\n return input\n .map(function (str) {\n return parseString(str, options);\n })\n .filter(Boolean);\n } else {\n var cookies = createNullObj();\n return input.reduce(function (cookies, str) {\n var cookie = parseString(str, options);\n if (cookie && !isForbiddenKey(cookie.name)) {\n cookies[cookie.name] = cookie;\n }\n return cookies;\n }, cookies);\n }\n}\n\n/*\n Set-Cookie header field-values are sometimes comma joined in one string. This splits them without choking on commas\n that are within a single set-cookie field-value, such as in the Expires portion.\n\n This is uncommon, but explicitly allowed - see https://tools.ietf.org/html/rfc2616#section-4.2\n Node.js does this for every header *except* set-cookie - see https://github.com/nodejs/node/blob/d5e363b77ebaf1caf67cd7528224b651c86815c1/lib/_http_incoming.js#L128\n React Native's fetch does this for *every* header, including set-cookie.\n\n Based on: https://github.com/google/j2objc/commit/16820fdbc8f76ca0c33472810ce0cb03d20efe25\n Credits to: https://github.com/tomball for original and https://github.com/chrusart for JavaScript implementation\n*/\nfunction splitCookiesString(cookiesString) {\n if (Array.isArray(cookiesString)) {\n return cookiesString;\n }\n if (typeof cookiesString !== \"string\") {\n return [];\n }\n\n var cookiesStrings = [];\n var pos = 0;\n var start;\n var ch;\n var lastComma;\n var nextStart;\n var cookiesSeparatorFound;\n\n function skipWhitespace() {\n while (pos < cookiesString.length && /\\s/.test(cookiesString.charAt(pos))) {\n pos += 1;\n }\n return pos < cookiesString.length;\n }\n\n function notSpecialChar() {\n ch = cookiesString.charAt(pos);\n\n return ch !== \"=\" && ch !== \";\" && ch !== \",\";\n }\n\n while (pos < cookiesString.length) {\n start = pos;\n cookiesSeparatorFound = false;\n\n while (skipWhitespace()) {\n ch = cookiesString.charAt(pos);\n if (ch === \",\") {\n // ',' is a cookie separator if we have later first '=', not ';' or ','\n lastComma = pos;\n pos += 1;\n\n skipWhitespace();\n nextStart = pos;\n\n while (pos < cookiesString.length && notSpecialChar()) {\n pos += 1;\n }\n\n // currently special character\n if (pos < cookiesString.length && cookiesString.charAt(pos) === \"=\") {\n // we found cookies separator\n cookiesSeparatorFound = true;\n // pos is inside the next cookie, so back up and return it.\n pos = nextStart;\n cookiesStrings.push(cookiesString.substring(start, lastComma));\n start = pos;\n } else {\n // in param ',' or param separator ';',\n // we continue from that comma\n pos = lastComma + 1;\n }\n } else {\n pos += 1;\n }\n }\n\n if (!cookiesSeparatorFound || pos >= cookiesString.length) {\n cookiesStrings.push(cookiesString.substring(start, cookiesString.length));\n }\n }\n\n return cookiesStrings;\n}\n\n// named export for CJS\nparseSetCookie.parseSetCookie = parseSetCookie;\n// for backwards compatibility\nparseSetCookie.parse = parseSetCookie;\nparseSetCookie.parseString = parseString;\nparseSetCookie.splitCookiesString = splitCookiesString;\n\n// EXPORTS\n// (this section is replaced by build-cjs.js)\n\n// named export for ESM\nexport { parseSetCookie };\n// for backwards compatibility\nexport default parseSetCookie;\nexport { parseSetCookie as parse, parseString, splitCookiesString };\n","import { parse as parseSetCookie, splitCookiesString } from 'set-cookie-parser';\n\n/** Cookie, сохранённая в jar. */\ninterface StoredCookie {\n name: string;\n value: string;\n path: string;\n /** Момент истечения, мс с начала эпохи. `undefined` — сессионная cookie. */\n expires: number | undefined;\n secure: boolean;\n}\n\n/** Имя cookie-флага «есть refresh-сессия». Ставится сайтом итд.com рядом с refresh-токеном. */\nexport const AUTH_FLAG_COOKIE = 'is_auth';\n\n/**\n * Имя cookie с refresh-токеном.\n *\n * `POST /api/v1/auth/refresh` читает токен **только отсюда** — тело запроса сервер игнорирует.\n * Cookie помечена `HttpOnly`, поэтому в браузере её не прочитать и не выставить; вне браузера\n * она проходит через jar, и туда же кладётся токен, переданный строкой.\n */\nexport const REFRESH_COOKIE = 'refresh_token';\n\n/** Путь, которым сервер ограничивает {@link REFRESH_COOKIE}. */\nexport const REFRESH_COOKIE_PATH = '/api/v1/auth';\n\n/** Разделитель origin и содержимого cookie при сериализации. В origin пробелов не бывает. */\nconst SERIALIZED_SEPARATOR = ' ';\n\nfunction originOf(url: string): string {\n try {\n return new URL(url).origin;\n } catch {\n return '';\n }\n}\n\n/** Дата в миллисекунды. Некорректная дата считается отсутствующей, а не `NaN`. */\nfunction toTimestamp(date: Date | undefined): number | undefined {\n if (!date) return undefined;\n const time = date.getTime();\n return Number.isFinite(time) ? time : undefined;\n}\n\nfunction pathOf(url: string): string {\n try {\n return new URL(url).pathname || '/';\n } catch {\n return '/';\n }\n}\n\n/**\n * Подходит ли путь cookie запросу.\n *\n * Правило из RFC 6265: путь cookie должен быть префиксом пути запроса, причём граница\n * должна проходить по сегменту — `/api` не подходит запросу `/apiary`.\n */\nfunction pathMatches(cookiePath: string, requestPath: string): boolean {\n if (cookiePath === '/' || cookiePath === requestPath) return true;\n if (!requestPath.startsWith(cookiePath)) return false;\n return cookiePath.endsWith('/') || requestPath[cookiePath.length] === '/';\n}\n\n/**\n * Минимальное хранилище cookie для сред без своего.\n *\n * Refresh-токен итд.com приходит в `Set-Cookie`, а `fetch` вне браузера cookie не хранит —\n * без jar сессию не продлить. В браузере и React Native не используется: там cookie ведёт\n * сама среда.\n *\n * Реализована практическая часть RFC 6265: origin, путь, срок жизни, флаг `Secure`.\n * Доменные cookie для поддоменов намеренно не поддерживаются — API работает с одного хоста.\n */\nexport class CookieJar {\n readonly #byOrigin = new Map<string, Map<string, StoredCookie>>();\n\n /**\n * Забирает `Set-Cookie` из ответа.\n *\n * Использует `Headers.getSetCookie()`, где он есть (Node 20+, undici). В остальных средах\n * заголовки склеены в одну строку, и её нельзя резать по запятой напрямую: запятая есть\n * внутри `Expires=Wed, 09 Jun 2027 …`. Разделением занимается `set-cookie-parser`.\n */\n setFromResponse(url: string, response: Response): void {\n const headers = response.headers as Headers & { getSetCookie?: () => string[] };\n\n const raw =\n typeof headers.getSetCookie === 'function'\n ? headers.getSetCookie()\n : splitCookiesString(headers.get('set-cookie') ?? '');\n\n if (raw.length > 0) this.setFromStrings(url, raw);\n }\n\n /**\n * Кладёт cookie напрямую, минуя `Set-Cookie`.\n *\n * Нужно ровно в одном случае: пользователь передал refresh-токен строкой, а сервер читает\n * его только из cookie. Значение не кодируется — оно уходит в заголовок как есть.\n */\n set(url: string, name: string, value: string, path = '/'): void {\n this.setFromStrings(url, [`${name}=${value}; Path=${path}`]);\n }\n\n /** Сохраняет cookie из готовых строк `Set-Cookie`. */\n setFromStrings(url: string, setCookieStrings: string[]): void {\n const origin = originOf(url);\n if (!origin) return;\n\n const jar = this.#byOrigin.get(origin) ?? new Map<string, StoredCookie>();\n\n for (const parsed of parseSetCookie(setCookieStrings)) {\n // Битую дату (её легко получить, если заголовки склеены неправильно) считаем\n // отсутствующей: сессионная cookie лучше, чем cookie со сроком NaN, которая\n // не истекает и одновременно нигде не находится.\n const expires = toTimestamp(parsed.expires);\n const maxAgeExpires =\n typeof parsed.maxAge === 'number' && Number.isFinite(parsed.maxAge)\n ? Date.now() + parsed.maxAge * 1000\n : undefined;\n\n // Max-Age приоритетнее Expires — так требует RFC 6265.\n const expiresAt = maxAgeExpires ?? expires;\n\n // Удаление cookie сервером: срок в прошлом либо Max-Age=0.\n if (expiresAt !== undefined && expiresAt <= Date.now()) {\n jar.delete(parsed.name);\n continue;\n }\n\n jar.set(parsed.name, {\n name: parsed.name,\n value: parsed.value,\n path: parsed.path ?? '/',\n expires: expiresAt,\n secure: parsed.secure ?? false,\n });\n }\n\n this.#byOrigin.set(origin, jar);\n }\n\n /**\n * Собирает значение заголовка `Cookie` для запроса.\n *\n * @returns строка вида `a=1; b=2` либо `undefined`, если подходящих cookie нет\n */\n getHeader(url: string): string | undefined {\n const cookies = this.#matching(url);\n if (cookies.length === 0) return undefined;\n return cookies.map((cookie) => `${cookie.name}=${cookie.value}`).join('; ');\n }\n\n /**\n * Значение действующей cookie.\n *\n * Нужно, чтобы забрать обновлённый refresh-токен: сервер ротирует его при каждом\n * продлении сессии, и сохранять надо именно новое значение.\n *\n * @param url если указан, учитываются origin, путь и флаг `Secure`\n */\n getValue(name: string, url?: string): string | undefined {\n if (url) return this.#matching(url).find((cookie) => cookie.name === name)?.value;\n\n const now = Date.now();\n for (const jar of this.#byOrigin.values()) {\n const cookie = jar.get(name);\n if (cookie && (cookie.expires === undefined || cookie.expires > now)) return cookie.value;\n }\n return undefined;\n }\n\n /**\n * Есть ли действующая cookie с таким именем.\n *\n * Используется для проверки флага {@link AUTH_FLAG_COOKIE} перед запросом обновления\n * токена: у анонима refresh-сессии нет, и дёргать API незачем.\n */\n has(name: string, url?: string): boolean {\n if (url) return this.#matching(url).some((cookie) => cookie.name === name);\n\n const now = Date.now();\n for (const jar of this.#byOrigin.values()) {\n const cookie = jar.get(name);\n if (cookie && (cookie.expires === undefined || cookie.expires > now)) return true;\n }\n return false;\n }\n\n /** Сохраняет содержимое jar для записи в {@link TokenStorage}. */\n serialize(): string[] {\n const result: string[] = [];\n const now = Date.now();\n\n for (const [origin, jar] of this.#byOrigin) {\n for (const cookie of jar.values()) {\n if (cookie.expires !== undefined && cookie.expires <= now) continue;\n\n const parts = [`${cookie.name}=${cookie.value}`, `Path=${cookie.path}`];\n if (cookie.expires !== undefined) {\n parts.push(`Expires=${new Date(cookie.expires).toUTCString()}`);\n }\n if (cookie.secure) parts.push('Secure');\n\n result.push(`${origin}${SERIALIZED_SEPARATOR}${parts.join('; ')}`);\n }\n }\n\n return result;\n }\n\n /** Восстанавливает jar из результата {@link serialize}. Некорректные записи молча пропускаются. */\n deserialize(entries: readonly string[] | undefined): void {\n if (!entries) return;\n\n for (const entry of entries) {\n const separatorAt = entry.indexOf(SERIALIZED_SEPARATOR);\n if (separatorAt <= 0) continue;\n\n const origin = entry.slice(0, separatorAt);\n const setCookie = entry.slice(separatorAt + 1);\n if (!originOf(origin)) continue;\n\n this.setFromStrings(origin, [setCookie]);\n }\n }\n\n /** Удаляет все cookie. */\n clear(): void {\n this.#byOrigin.clear();\n }\n\n /** Действующие cookie, подходящие запросу: тот же origin, подходящий путь, не истёкшие. */\n #matching(url: string): StoredCookie[] {\n const origin = originOf(url);\n const jar = this.#byOrigin.get(origin);\n if (!jar) return [];\n\n const isSecureRequest = origin.startsWith('https:');\n const requestPath = pathOf(url);\n const now = Date.now();\n const result: StoredCookie[] = [];\n\n for (const cookie of jar.values()) {\n if (cookie.expires !== undefined && cookie.expires <= now) {\n jar.delete(cookie.name);\n continue;\n }\n if (cookie.secure && !isSecureRequest) continue;\n if (!pathMatches(cookie.path, requestPath)) continue;\n\n result.push(cookie);\n }\n\n return result;\n }\n}\n","/** Обработчик события. */\nexport type Listener<T> = (payload: T) => void;\n\n/** Функция отписки, которую возвращает {@link Emitter.on}. */\nexport type Unsubscribe = () => void;\n\n/**\n * Минимальный типизированный источник событий.\n *\n * Своя реализация вместо `EventTarget` и `EventEmitter`: первый есть не везде и требует\n * обёрток `CustomEvent`, второй существует только в Node. Нужны ровно подписка и рассылка.\n *\n * Исключение в обработчике не прерывает рассылку остальным и не роняет библиотеку.\n *\n * @typeParam Events карта «имя события → тип полезной нагрузки». Задаётся интерфейсом,\n * поэтому ограничение на индексную сигнатуру намеренно не накладывается.\n */\nexport class Emitter<Events> {\n readonly #listeners = new Map<keyof Events, Set<Listener<never>>>();\n readonly #onError: ((error: unknown) => void) | undefined;\n\n constructor(onListenerError?: (error: unknown) => void) {\n this.#onError = onListenerError;\n }\n\n /**\n * Подписывается на событие.\n *\n * @returns функция отписки\n *\n * @example\n * ```ts\n * const off = realtime.on('notification', (event) => console.log(event));\n * off();\n * ```\n */\n on<K extends keyof Events>(event: K, listener: Listener<Events[K]>): Unsubscribe {\n const set = this.#listeners.get(event) ?? new Set();\n set.add(listener as Listener<never>);\n this.#listeners.set(event, set);\n\n return () => this.off(event, listener);\n }\n\n /** Подписывается на одно срабатывание. */\n once<K extends keyof Events>(event: K, listener: Listener<Events[K]>): Unsubscribe {\n const off = this.on(event, (payload) => {\n off();\n listener(payload);\n });\n return off;\n }\n\n /** Отписывается от события. */\n off<K extends keyof Events>(event: K, listener: Listener<Events[K]>): void {\n this.#listeners.get(event)?.delete(listener as Listener<never>);\n }\n\n /** Рассылает событие подписчикам. */\n emit<K extends keyof Events>(event: K, payload: Events[K]): void {\n const set = this.#listeners.get(event);\n if (!set) return;\n\n // Копия нужна: обработчик вправе отписаться прямо во время рассылки.\n for (const listener of [...set]) {\n try {\n (listener as Listener<Events[K]>)(payload);\n } catch (error) {\n this.#onError?.(error);\n }\n }\n }\n\n /** Сколько подписчиков у события. */\n listenerCount(event: keyof Events): number {\n return this.#listeners.get(event)?.size ?? 0;\n }\n\n /** Снимает все подписки. */\n removeAllListeners(): void {\n this.#listeners.clear();\n }\n}\n","import { ItdConfigError } from './errors.js';\n\n/**\n * Как библиотека обращается с cookie.\n *\n * - `browser` — cookie ведёт браузер, запросы уходят с `credentials: 'include'`;\n * - `server` — cookie ведёт встроенный jar, заголовок `Cookie` подставляется вручную;\n * - `auto` — определяется по среде исполнения (значение по умолчанию).\n */\nexport const RuntimeMode = Object.freeze({\n /** Определяется по среде исполнения. Значение по умолчанию. */\n Auto: 'auto',\n /** Cookie ведёт браузер, запросы уходят с `credentials: 'include'`. */\n Browser: 'browser',\n /** Cookie ведёт встроенный jar, заголовок `Cookie` подставляется вручную. */\n Server: 'server',\n} as const);\nexport type RuntimeMode = (typeof RuntimeMode)[keyof typeof RuntimeMode];\n\n/** Распознанная среда исполнения. */\nexport const DetectedRuntime = Object.freeze({\n Browser: 'browser',\n /** Есть `window`, но нет `document`; cookie ведёт нативный сетевой слой. */\n ReactNative: 'react-native',\n Server: 'server',\n} as const);\nexport type DetectedRuntime = (typeof DetectedRuntime)[keyof typeof DetectedRuntime];\n\n/**\n * Определяет среду исполнения.\n *\n * React Native выделен отдельно намеренно: там есть `window`, но нет `document`, а cookie\n * хранит нативный сетевой слой (`NSHTTPCookieStorage` / `OkHttp`). Свой jar в этой среде\n * привёл бы к отправке cookie дважды.\n */\nexport function detectRuntime(): DetectedRuntime {\n const nav = (globalThis as { navigator?: { product?: string } }).navigator;\n if (nav?.product === 'ReactNative') return DetectedRuntime.ReactNative;\n\n if (typeof document !== 'undefined') return DetectedRuntime.Browser;\n\n return DetectedRuntime.Server;\n}\n\n/**\n * Нужно ли вести собственный cookie-jar.\n *\n * Только в серверных средах: в браузере `Set-Cookie` из JS не читается и не нужен,\n * в React Native cookie ведёт нативный слой.\n */\nexport function shouldUseCookieJar(mode: RuntimeMode): boolean {\n if (mode === RuntimeMode.Browser) return false;\n if (mode === RuntimeMode.Server) return true;\n return detectRuntime() === DetectedRuntime.Server;\n}\n\n/**\n * Нужно ли отправлять запросы с `credentials: 'include'`.\n *\n * Только в браузере: именно так refresh-cookie попадает в запрос `POST /api/v1/auth/refresh`.\n * Требует настроенного CORS на стороне итд.com — если его нет, укажите свой прокси в `baseUrl`.\n */\nexport function shouldSendCredentials(mode: RuntimeMode): boolean {\n if (mode === RuntimeMode.Browser) return true;\n if (mode === RuntimeMode.Server) return false;\n return detectRuntime() === DetectedRuntime.Browser;\n}\n\n/**\n * Возвращает реализацию `fetch`.\n *\n * @param custom реализация из конфигурации клиента, если пользователь её передал\n * @throws {ItdConfigError} если `fetch` недоступен — например, на Node ниже 18\n */\nexport function resolveFetch(custom?: typeof fetch): typeof fetch {\n if (custom) return custom;\n\n if (typeof globalThis.fetch === 'function') {\n // Привязка к globalThis обязательна: в некоторых средах несвязанный fetch бросает\n // «Illegal invocation».\n return globalThis.fetch.bind(globalThis);\n }\n\n throw new ItdConfigError(\n 'В этой среде нет глобального fetch. Обновитесь до Node 18+ либо передайте свою ' +\n 'реализацию через опцию fetch.',\n );\n}\n\n/**\n * Проверки бинарных типов, безопасные в любой среде.\n *\n * Обычный `instanceof` здесь недостаточен: конструктора может не быть вовсе, и тогда\n * проверка падает с `ReferenceError`, а не возвращает `false`. `Blob` есть в Node с 18.0,\n * но `File` стал глобальным только в Node 20 — при заявленной поддержке Node 18 голый\n * `instanceof File` ронял бы любую загрузку.\n */\nexport function isBlob(value: unknown): value is Blob {\n return typeof Blob !== 'undefined' && value instanceof Blob;\n}\n\n/** @see {@link isBlob} */\nexport function isFile(value: unknown): value is File {\n return typeof File !== 'undefined' && value instanceof File;\n}\n\n/** Доступно ли потоковое чтение тела ответа — от этого зависит, сработает ли SSE. */\nexport function supportsStreamingBody(): boolean {\n return typeof ReadableStream !== 'undefined' && typeof TextDecoder !== 'undefined';\n}\n\n/**\n * Создаёт идентификатор устройства для заголовка `X-Device-Id` — UUID v4.\n *\n * `crypto.randomUUID` есть в Node 19+, браузерах и Deno, но отсутствует в Node 18 вне\n * защищённого контекста, поэтому предусмотрен запасной путь.\n */\nexport function createDeviceId(): string {\n const webCrypto = (globalThis as { crypto?: Crypto }).crypto;\n\n if (typeof webCrypto?.randomUUID === 'function') return webCrypto.randomUUID();\n\n // Форма UUID v4 собирается вручную: серверу важна стабильность значения, а не его энтропия.\n const bytes = new Uint8Array(16);\n if (typeof webCrypto?.getRandomValues === 'function') webCrypto.getRandomValues(bytes);\n else for (let i = 0; i < bytes.length; i++) bytes[i] = Math.floor(Math.random() * 256);\n\n // biome-ignore lint/style/noNonNullAssertion: длина массива фиксирована выше\n bytes[6] = (bytes[6]! & 0x0f) | 0x40;\n // biome-ignore lint/style/noNonNullAssertion: длина массива фиксирована выше\n bytes[8] = (bytes[8]! & 0x3f) | 0x80;\n\n const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, '0')).join('');\n\n return [\n hex.slice(0, 8),\n hex.slice(8, 12),\n hex.slice(12, 16),\n hex.slice(16, 20),\n hex.slice(20, 32),\n ].join('-');\n}\n\n/** Есть ли в среде `localStorage`. Проверка безопасна: доступ к нему может бросать. */\nexport function hasLocalStorage(): boolean {\n try {\n return typeof globalThis.localStorage !== 'undefined' && globalThis.localStorage !== null;\n } catch {\n return false;\n }\n}\n","import type { AuthInput, CredentialsAuth } from '../types/options.js';\nimport type { ResolvedConfig } from './config.js';\nimport {\n AUTH_FLAG_COOKIE,\n type CookieJar,\n REFRESH_COOKIE,\n REFRESH_COOKIE_PATH,\n} from './cookies.js';\nimport { Emitter } from './emitter.js';\nimport { ItdApiError, ItdAuthError, ItdConfigError } from './errors.js';\nimport type { HttpClient } from './http.js';\nimport { createDeviceId } from './runtime.js';\nimport type { ItdSession } from './storage.js';\n\n/** Пути авторизации. Вынесены, чтобы не расходиться между модулями. */\nexport const AUTH_PATHS = {\n signIn: '/api/v1/auth/sign-in',\n refresh: '/api/v1/auth/refresh',\n} as const;\n\n/**\n * Публичный ключ Cloudflare Turnstile платформы итд.com.\n *\n * Нужен, чтобы отрисовать виджет капчи и получить токен для `signIn`, `signUp`\n * и `forgotPassword`.\n *\n * @example\n * ```ts\n * turnstile.render('#captcha', {\n * sitekey: TURNSTILE_SITE_KEY,\n * callback: (turnstileToken) => itd.auth.signIn({ email, password, turnstileToken }),\n * });\n * ```\n */\nexport const TURNSTILE_SITE_KEY = '0x4AAAAAACHhxczw6fJGwPBg';\n\n/** Заголовок с идентификатором устройства. Сервер связывает с ним запись в списке сессий. */\nexport const DEVICE_ID_HEADER = 'X-Device-Id';\n\n/** События слоя авторизации. */\nexport interface AuthEvents {\n /** Токен получен или обновлён. */\n tokens: { accessToken: string };\n /** Выполнен вход. */\n signIn: { accessToken: string };\n /** Сессия очищена — вручную или из-за неудачного обновления. */\n signOut: undefined;\n /** Обновить сессию не удалось; дальнейшие запросы будут падать с 401. */\n authError: { error: unknown };\n}\n\n/** Ответ эндпоинтов, выдающих токен. */\ninterface TokenResponse {\n accessToken?: unknown;\n}\n\nfunction readAccessToken(payload: unknown): string | undefined {\n if (typeof payload !== 'object' || payload === null) return undefined;\n const token = (payload as TokenResponse).accessToken;\n return typeof token === 'string' && token.length > 0 ? token : undefined;\n}\n\n/**\n * Хранит сессию и продлевает её.\n *\n * Главное здесь — **дедупликация обновления**. Когда десять параллельных запросов\n * одновременно получают `401`, обновление должно произойти один раз, а остальные обязаны\n * дождаться его результата. Иначе сервер увидит десять параллельных `refresh`, и все,\n * кроме первого, скорее всего получат отказ по уже использованному токену.\n */\nexport class AuthManager {\n readonly #config: ResolvedConfig;\n readonly #http: HttpClient;\n readonly #jar: CookieJar;\n readonly #emitter = new Emitter<AuthEvents>();\n\n /** `undefined` — сессия ещё не читалась из хранилища. */\n #session: ItdSession | null | undefined;\n /** Общий промис обновления: к нему присоединяются все, кто получил 401. */\n #refreshing: Promise<string | null> | null = null;\n /** Общий промис входа по логину и паролю. */\n #signingIn: Promise<string> | null = null;\n /**\n * Идентификатор устройства.\n *\n * Держится отдельно от сессии намеренно: выход из аккаунта не меняет устройство,\n * поэтому `clear()` его не трогает.\n */\n #deviceId: string | undefined;\n\n constructor(config: ResolvedConfig, http: HttpClient, jar: CookieJar) {\n this.#config = config;\n this.#http = http;\n this.#jar = jar;\n }\n\n /** Подписка на события авторизации. */\n get on(): Emitter<AuthEvents>['on'] {\n return this.#emitter.on.bind(this.#emitter);\n }\n\n /** Подписка на одно срабатывание. */\n get once(): Emitter<AuthEvents>['once'] {\n return this.#emitter.once.bind(this.#emitter);\n }\n\n /**\n * Есть ли признак живой refresh-сессии.\n *\n * Рядом с refresh-токеном сервер ставит незакрытую cookie `is_auth` — по ней видно,\n * что продлевать сессию вообще есть смысл, и API не дёргается у анонимов.\n * В браузере cookie ведёт сама среда, поэтому там ответ всегда `true`.\n *\n * Асинхронный, потому что признак может лежать в {@link TokenStorage}: до чтения оттуда\n * ответ был бы `false` даже при полностью рабочей сохранённой сессии.\n */\n async hasRefreshSession(): Promise<boolean> {\n await this.#loadSession();\n return this.#hasRefreshSession();\n }\n\n /** То же самое, но без чтения хранилища — для вызовов, где сессия уже загружена. */\n #hasRefreshSession(): boolean {\n if (!this.#config.useCookieJar) return true;\n if (this.#jar.has(AUTH_FLAG_COOKIE)) return true;\n\n // Явно переданный refresh-токен — тоже основание пробовать.\n return Boolean(this.#session?.refreshToken);\n }\n\n /** Заголовки авторизации для очередного запроса. Пустой объект, если токена нет. */\n async getAuthHeaders(): Promise<Record<string, string>> {\n const token = await this.getAccessToken();\n return token ? { Authorization: `Bearer ${token}` } : {};\n }\n\n /**\n * Идентификатор устройства для заголовка `X-Device-Id`.\n *\n * Заводится один раз и сохраняется в сессии, чтобы пережить перезапуск процесса:\n * сервер связывает с ним запись в списке сессий, и плавающее значение плодило бы\n * по новой сессии на каждый старт.\n */\n async getDeviceId(): Promise<string> {\n if (this.#deviceId) return this.#deviceId;\n\n const session = await this.#loadSession();\n const deviceId = this.#config.deviceId ?? session?.deviceId ?? createDeviceId();\n\n this.#deviceId = deviceId;\n\n // Записываем, только если значение действительно новое, — иначе каждый первый запрос\n // дёргал бы хранилище без всякой пользы.\n if (session?.deviceId !== deviceId) {\n await this.#saveSession({ ...(session ?? {}), deviceId });\n }\n\n return deviceId;\n }\n\n /**\n * Текущий токен доступа.\n *\n * При необходимости выполняет отложенный вход: если в конфигурации переданы логин\n * и пароль, первый же запрос сам заведёт сессию.\n */\n async getAccessToken(): Promise<string | null> {\n const session = await this.#loadSession();\n if (session?.accessToken) return session.accessToken;\n\n const auth = this.#config.auth;\n if (!auth) return null;\n\n // Внешний источник токена спрашиваем каждый раз: он сам решает, когда обновлять.\n if (typeof auth === 'object' && 'getToken' in auth) {\n return (await auth.getToken()) ?? null;\n }\n\n if (typeof auth === 'object' && 'email' in auth) {\n return this.#signInWithCredentials(auth);\n }\n\n return null;\n }\n\n /**\n * Реакция транспорта на ответ `401`.\n *\n * @returns `true`, если токен обновлён и запрос имеет смысл повторить\n */\n async onUnauthorized(): Promise<boolean> {\n try {\n const token = await this.#refreshDeduplicated();\n if (token !== null) return true;\n\n // Обновлять нечем — это тоже отказ авторизации, и подписчик должен о нём узнать.\n this.#emitter.emit('authError', { error: this.#noRefreshSessionError() });\n return false;\n } catch (error) {\n this.#emitter.emit('authError', { error });\n return false;\n }\n }\n\n /**\n * Ошибка «сессию продлить нечем».\n *\n * Возникает, только когда обновление даже не начиналось: нет ни cookie `is_auth`,\n * ни refresh-токена. Если сервер ответил отказом, наружу уходит **его** ошибка —\n * подменять её этой значило бы прятать причину (`REFRESH_TOKEN_MISSING`,\n * `SESSION_NOT_FOUND`, `SESSION_REVOKED` — разные поводы и разные действия).\n */\n #noRefreshSessionError(): ItdAuthError {\n return new ItdAuthError({\n status: 401,\n code: 'SESSION_EXPIRED',\n message:\n 'Не удалось обновить сессию: нет ни cookie is_auth, ни refresh-токена. ' +\n 'Войдите заново либо передайте refreshToken в auth.',\n method: 'POST',\n path: AUTH_PATHS.refresh,\n raw: undefined,\n });\n }\n\n /**\n * Обновляет токен доступа.\n *\n * Параллельные вызовы объединяются в один сетевой запрос.\n *\n * @throws {ItdAuthError} если обновить сессию не удалось\n */\n async refresh(): Promise<string> {\n const token = await this.#refreshDeduplicated();\n if (token === null) throw this.#noRefreshSessionError();\n return token;\n }\n\n /** Сохраняет токен, полученный извне, — например после подтверждения OTP. */\n async setAccessToken(accessToken: string): Promise<void> {\n await this.#saveSession({ ...(this.#session ?? {}), accessToken, obtainedAt: Date.now() });\n this.#emitter.emit('tokens', { accessToken });\n }\n\n /** Текущая сессия целиком. Полезно, чтобы сохранить её самому. */\n async getSession(): Promise<ItdSession | null> {\n return this.#loadSession();\n }\n\n /** Заменяет сессию целиком. */\n async setSession(session: ItdSession): Promise<void> {\n this.#jar.deserialize(session.cookies);\n this.#deviceId ??= session.deviceId;\n await this.#saveSession(session);\n this.#seedRefreshCookie();\n }\n\n /**\n * Забывает сессию и cookie. Сетевой запрос не выполняется.\n *\n * Идентификатор устройства выход переживает: иначе каждая пара «выход — вход» плодила бы\n * новую запись в списке сессий.\n */\n async clear(): Promise<void> {\n this.#session = null;\n this.#jar.clear();\n await this.#config.storage.clear();\n\n if (this.#deviceId) await this.#saveSession({ deviceId: this.#deviceId });\n\n this.#emitter.emit('signOut', undefined);\n }\n\n async #loadSession(): Promise<ItdSession | null> {\n if (this.#session !== undefined) return this.#session;\n\n const stored = (await this.#config.storage.get()) ?? null;\n\n // Восстанавливаем cookie: без них не выйдет обновить токен после перезапуска процесса.\n if (stored?.cookies) this.#jar.deserialize(stored.cookies);\n\n const fromConfig = this.#sessionFromConfig(this.#config.auth);\n\n // Хранилище отвечает за состояние сессии и всегда важнее, но недостающие поля\n // берутся из конфигурации: типичный случай — сохранён только accessToken,\n // а refresh-токен приходит из настроек приложения.\n this.#session =\n stored && fromConfig\n ? {\n ...stored,\n accessToken: stored.accessToken ?? fromConfig.accessToken,\n refreshToken: stored.refreshToken ?? fromConfig.refreshToken,\n }\n : (stored ?? fromConfig);\n\n this.#seedRefreshCookie();\n\n return this.#session;\n }\n\n /**\n * Кладёт refresh-токен в jar как cookie `refresh_token`.\n *\n * `POST /api/v1/auth/refresh` читает токен только из cookie, поэтому переданный строкой\n * приходится превращать в неё. В браузере это невозможно — cookie помечена `HttpOnly`,\n * и там обновление работает только на той, что поставил сам сервер.\n */\n #seedRefreshCookie(): void {\n if (!this.#config.useCookieJar) return;\n\n const refreshToken = this.#session?.refreshToken;\n if (!refreshToken) return;\n if (this.#jar.has(REFRESH_COOKIE)) return;\n\n this.#jar.set(this.#config.baseUrl, REFRESH_COOKIE, refreshToken, REFRESH_COOKIE_PATH);\n }\n\n #sessionFromConfig(auth: AuthInput | undefined): ItdSession | null {\n if (!auth) return null;\n if (typeof auth === 'string') return { accessToken: auth, obtainedAt: Date.now() };\n\n if ('accessToken' in auth) {\n return {\n accessToken: auth.accessToken,\n refreshToken: auth.refreshToken,\n obtainedAt: Date.now(),\n };\n }\n\n return null;\n }\n\n async #saveSession(session: ItdSession): Promise<void> {\n const cookies = this.#config.useCookieJar ? this.#jar.serialize() : undefined;\n const deviceId = session.deviceId ?? this.#deviceId;\n\n const next: ItdSession = {\n ...session,\n ...(cookies?.length ? { cookies } : {}),\n ...(deviceId ? { deviceId } : {}),\n };\n\n this.#session = next;\n await this.#config.storage.set(next);\n }\n\n /**\n * Обновление с дедупликацией.\n *\n * Все, кто пришёл, пока обновление уже идёт, получают его результат, а не запускают своё.\n */\n #refreshDeduplicated(): Promise<string | null> {\n if (this.#refreshing) return this.#refreshing;\n\n const promise = this.#performRefresh().finally(() => {\n this.#refreshing = null;\n });\n\n this.#refreshing = promise;\n return promise;\n }\n\n async #performRefresh(): Promise<string | null> {\n await this.#loadSession();\n\n if (!this.#hasRefreshSession()) {\n // Нет признаков сессии — обновлять нечего. При наличии логина и пароля\n // пробуем войти заново.\n return this.#reloginOrNull();\n }\n\n try {\n const payload = await this.#http.request<unknown>({\n method: 'POST',\n path: AUTH_PATHS.refresh,\n // Тела нет намеренно: сервер читает refresh-токен только из cookie — см.\n // #seedRefreshCookie. По той же причине не нужен и устаревший Bearer.\n skipAuth: true,\n // Без этого 401 на самом обновлении вызвал бы новое обновление — и так по кругу.\n skipAuthRefresh: true,\n // Обновление почти всегда запускается изнутри запроса, который занимает место\n // в очереди и ждёт его результата. Встать в ту же очередь — значит зависнуть.\n skipQueue: true,\n });\n\n const accessToken = readAccessToken(payload);\n if (!accessToken) return this.#reloginOrNull();\n\n // Сервер выдаёт при обновлении **новый** refresh-токен (`Set-Cookie: refresh_token=…;\n // Max-Age=2592000`) и тут же гасит прежний. Забрать его из jar обязательно: иначе\n // сохранённая строка протухнет и восстановление сессии из хранилища перестанет работать.\n const rotated = this.#jar.getValue(\n REFRESH_COOKIE,\n this.#config.baseUrl + REFRESH_COOKIE_PATH,\n );\n\n await this.#saveSession({\n ...(this.#session ?? {}),\n accessToken,\n ...(rotated ? { refreshToken: rotated } : {}),\n obtainedAt: Date.now(),\n });\n\n this.#emitter.emit('tokens', { accessToken });\n return accessToken;\n } catch (error) {\n if (error instanceof ItdApiError) {\n // Сессия недействительна — чистим её, иначе будем биться в стену на каждом запросе.\n this.#session = null;\n this.#jar.clear();\n await this.#config.storage.clear();\n\n const relogged = await this.#reloginOrNull();\n if (relogged !== null) return relogged;\n\n // Войти заново нечем — отдаём ошибку сервера как есть. Именно она объясняет,\n // что произошло: REFRESH_TOKEN_MISSING, SESSION_NOT_FOUND, SESSION_REVOKED.\n throw error;\n }\n throw error;\n }\n }\n\n /** Повторный вход, если разрешён настройкой и есть логин с паролем. */\n async #reloginOrNull(): Promise<string | null> {\n const auth = this.#config.auth;\n\n if (\n !this.#config.reloginOnRefreshFailure ||\n !auth ||\n typeof auth !== 'object' ||\n !('email' in auth)\n ) {\n return null;\n }\n\n try {\n return await this.#signInWithCredentials(auth);\n } catch {\n return null;\n }\n }\n\n /**\n * Вход по логину и паролю.\n *\n * Параллельные вызовы объединяются: одновременный старт нескольких запросов не должен\n * приводить к нескольким попыткам входа и блокировке аккаунта.\n */\n #signInWithCredentials(credentials: CredentialsAuth): Promise<string> {\n if (this.#signingIn) return this.#signingIn;\n\n const promise = this.#performSignIn(credentials).finally(() => {\n this.#signingIn = null;\n });\n\n this.#signingIn = promise;\n return promise;\n }\n\n /**\n * Берёт токен капчи для входа.\n *\n * `getTurnstileToken` приоритетнее готовой строки: токен Turnstile одноразовый и живёт\n * несколько минут, поэтому при повторном входе через сутки годится только свежий.\n */\n async #resolveTurnstileToken(credentials: CredentialsAuth): Promise<string> {\n if (credentials.getTurnstileToken) {\n const token = await credentials.getTurnstileToken();\n if (token) return token;\n }\n\n if (credentials.turnstileToken) return credentials.turnstileToken;\n\n throw new ItdConfigError(\n 'Вход по email и паролю требует токен капчи Cloudflare Turnstile: без него сервер ' +\n 'отвечает 422. Передайте auth.getTurnstileToken (источник свежего токена) либо ' +\n 'разовый auth.turnstileToken. Ключ виджета — TURNSTILE_SITE_KEY. В Node токен умеет ' +\n 'добывать отдельный пакет: npm i itd-api-turnstile, затем ' +\n 'getTurnstileToken: createTurnstileSolver().',\n );\n }\n\n async #performSignIn(credentials: CredentialsAuth): Promise<string> {\n const turnstileToken = await this.#resolveTurnstileToken(credentials);\n\n const payload = await this.#http.request<unknown>({\n method: 'POST',\n path: AUTH_PATHS.signIn,\n body: { email: credentials.email, password: credentials.password, turnstileToken },\n skipAuth: true,\n skipAuthRefresh: true,\n // Отложенный вход происходит при сборке заголовков уже начатого запроса — тот держит\n // место в очереди и ждёт токена. См. `skipQueue` в RawRequestOptions.\n skipQueue: true,\n });\n\n const accessToken = readAccessToken(payload);\n\n if (!accessToken) {\n // Сервер запросил подтверждение по коду — автоматически это не пройти.\n throw new ItdConfigError(\n 'Вход по email и паролю требует подтверждения кодом из письма. Автоматический вход ' +\n 'невозможен: воспользуйтесь itd.auth.signInWithOtp() и передайте полученный ' +\n 'accessToken в конфигурацию клиента.',\n );\n }\n\n // Прежний refresh-токен и cookie намеренно не переносятся: вход выдал новую сессию,\n // и держаться за старую было бы ошибкой. Идентификатор устройства добавит #saveSession.\n await this.#saveSession({ accessToken, obtainedAt: Date.now() });\n this.#emitter.emit('tokens', { accessToken });\n this.#emitter.emit('signIn', { accessToken });\n\n return accessToken;\n }\n}\n","import { hasLocalStorage } from './runtime.js';\n\n/**\n * Сохранённая сессия.\n *\n * Кроме токенов сюда попадают cookie: refresh-токен итд.com живёт именно в cookie, и без них\n * восстановить сессию после перезапуска процесса невозможно.\n */\nexport interface ItdSession {\n /** Токен доступа для заголовка `Authorization: Bearer`. */\n accessToken?: string | undefined;\n /**\n * Refresh-токен, если удалось получить его явным значением.\n *\n * Обычно сервер держит его в httpOnly-cookie и наружу не отдаёт — тогда поле останется\n * пустым, а обновление пойдёт через {@link ItdSession.cookies}.\n */\n refreshToken?: string | undefined;\n /** Сырые cookie в форме `имя=значение`, привязанные к origin API. */\n cookies?: string[] | undefined;\n /**\n * Идентификатор устройства для заголовка `X-Device-Id`.\n *\n * Сервер различает по нему записи в списке сессий, поэтому значение должно пережить\n * перезапуск процесса — иначе каждый старт бота порождает новую сессию. Библиотека\n * заводит его сама при первом запросе и хранит здесь.\n */\n deviceId?: string | undefined;\n /** Когда сессия получена, мс с начала эпохи. Нужно для диагностики. */\n obtainedAt?: number | undefined;\n}\n\n/**\n * Хранилище сессии.\n *\n * Подключаемый компонент: библиотека не знает, где вы держите токены, и обращается к ним\n * только через этот интерфейс. Все методы могут быть как синхронными, так и асинхронными.\n *\n * @example Своё хранилище поверх AsyncStorage в React Native\n * ```ts\n * const storage = createTokenStorage({\n * get: async () => JSON.parse((await AsyncStorage.getItem('itd')) ?? 'null'),\n * set: (session) => AsyncStorage.setItem('itd', JSON.stringify(session)),\n * clear: () => AsyncStorage.removeItem('itd'),\n * });\n * ```\n */\nexport interface TokenStorage {\n /** Прочитать сессию. `null`, если её нет. */\n get(): ItdSession | null | Promise<ItdSession | null>;\n /** Сохранить сессию целиком. */\n set(session: ItdSession): void | Promise<void>;\n /** Удалить сессию. Вызывается при выходе и при неудачном обновлении токена. */\n clear(): void | Promise<void>;\n}\n\n/**\n * Хранилище в памяти процесса — вариант по умолчанию.\n *\n * Сессия теряется при перезапуске. Для долгоживущих ботов возьмите `FileTokenStorage`\n * из `itd-api/node`, для браузера — {@link LocalStorageTokenStorage}.\n */\nexport class MemoryTokenStorage implements TokenStorage {\n #session: ItdSession | null = null;\n\n constructor(initial?: ItdSession | null) {\n this.#session = initial ?? null;\n }\n\n get(): ItdSession | null {\n return this.#session;\n }\n\n set(session: ItdSession): void {\n this.#session = session;\n }\n\n clear(): void {\n this.#session = null;\n }\n}\n\n/**\n * Хранилище поверх `localStorage` браузера.\n *\n * Если `localStorage` недоступен (приватный режим, серверный рендеринг), молча работает\n * как хранилище в памяти — библиотека не должна падать из-за настроек браузера.\n *\n * Помните, что `localStorage` доступен любому скрипту на странице: не используйте его,\n * если для вашего приложения это неприемлемый риск.\n */\nexport class LocalStorageTokenStorage implements TokenStorage {\n readonly #key: string;\n readonly #fallback = new MemoryTokenStorage();\n readonly #available: boolean;\n\n /** @param key ключ в `localStorage`. По умолчанию `itd-api:session`. */\n constructor(key = 'itd-api:session') {\n this.#key = key;\n this.#available = hasLocalStorage();\n }\n\n get(): ItdSession | null {\n if (!this.#available) return this.#fallback.get();\n\n try {\n const raw = globalThis.localStorage.getItem(this.#key);\n if (!raw) return null;\n const parsed: unknown = JSON.parse(raw);\n return typeof parsed === 'object' && parsed !== null ? (parsed as ItdSession) : null;\n } catch {\n // Повреждённое значение — ведём себя так, будто сессии нет.\n return null;\n }\n }\n\n set(session: ItdSession): void {\n if (!this.#available) {\n this.#fallback.set(session);\n return;\n }\n\n try {\n globalThis.localStorage.setItem(this.#key, JSON.stringify(session));\n } catch {\n // Переполненное или заблокированное хранилище не должно ломать запрос.\n this.#fallback.set(session);\n }\n }\n\n clear(): void {\n if (!this.#available) {\n this.#fallback.clear();\n return;\n }\n\n try {\n globalThis.localStorage.removeItem(this.#key);\n } catch {\n this.#fallback.clear();\n }\n }\n}\n\n/**\n * Собирает {@link TokenStorage} из трёх функций — когда заводить класс избыточно.\n *\n * @example\n * ```ts\n * const storage = createTokenStorage({\n * get: () => db.getSession(userId),\n * set: (session) => db.saveSession(userId, session),\n * clear: () => db.deleteSession(userId),\n * });\n * ```\n */\nexport function createTokenStorage(handlers: TokenStorage): TokenStorage {\n return handlers;\n}\n","import { ItdConfigError } from './errors.js';\n\n/** Значение параметра запроса. `undefined` и `null` в строку не попадают. */\nexport type QueryValue =\n | string\n | number\n | boolean\n | null\n | undefined\n | readonly (string | number | boolean)[];\n\n/** Параметры строки запроса. */\nexport type QueryParams = Record<string, QueryValue>;\n\n/**\n * Собирает строку запроса.\n *\n * Правила:\n * - `undefined` и `null` пропускаются целиком — не нужно чистить объект перед вызовом;\n * - `boolean` превращается в `true` / `false`;\n * - массив повторяет ключ (`ids=1&ids=2`).\n *\n * @returns строка вида `?a=1&b=2` либо пустая строка, если параметров нет\n *\n * @example\n * ```ts\n * buildQuery({ tab: 'popular', limit: 20, cursor: undefined });\n * // '?tab=popular&limit=20'\n * ```\n */\nexport function buildQuery(params?: QueryParams): string {\n if (!params) return '';\n\n const search = new URLSearchParams();\n\n for (const [key, value] of Object.entries(params)) {\n if (value === undefined || value === null) continue;\n\n if (Array.isArray(value)) {\n for (const item of value) {\n if (item === undefined || item === null) continue;\n search.append(key, String(item));\n }\n continue;\n }\n\n search.append(key, String(value));\n }\n\n const query = search.toString();\n return query ? `?${query}` : '';\n}\n\n/**\n * Кодирует значение для подстановки в путь.\n *\n * Нужно для сегментов, которые могут содержать что угодно, — прежде всего хэштегов\n * в `/api/hashtags/{tag}/posts`.\n *\n * @throws {ItdConfigError} если значение пустое\n */\nexport function encodePathSegment(value: string, name = 'параметр пути'): string {\n if (typeof value !== 'string' || value.trim() === '') {\n throw new ItdConfigError(\n `${name} должен быть непустой строкой, получено: ${JSON.stringify(value)}`,\n );\n }\n return encodeURIComponent(value);\n}\n\n/**\n * Склеивает базовый URL и путь.\n *\n * Завершающий слэш пути сохраняется: он значим для `/api/notifications/`\n * и `/api/v1/subscription/`, без него сервер отвечает ошибкой.\n *\n * @example\n * ```ts\n * joinUrl('https://xn--d1ah4a.com/', '/api/notifications/');\n * // 'https://xn--d1ah4a.com/api/notifications/'\n * ```\n */\nexport function joinUrl(baseUrl: string, path: string): string {\n const base = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;\n const suffix = path.startsWith('/') ? path : `/${path}`;\n return `${base}${suffix}`;\n}\n\n/** Приводит базовый URL к каноничному виду и проверяет, что он вообще похож на URL. */\nexport function normalizeBaseUrl(baseUrl: string): string {\n let parsed: URL;\n try {\n parsed = new URL(baseUrl);\n } catch {\n throw new ItdConfigError(\n `baseUrl должен быть абсолютным URL, получено: ${JSON.stringify(baseUrl)}`,\n );\n }\n\n if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {\n throw new ItdConfigError(\n `baseUrl должен использовать http или https, получено: ${parsed.protocol}`,\n );\n }\n\n return parsed.origin + (parsed.pathname === '/' ? '' : parsed.pathname.replace(/\\/$/, ''));\n}\n","import type { AuthInput, ClientHooks, ItdClientOptions, Logger } from '../types/options.js';\nimport { ItdConfigError } from './errors.js';\nimport { RuntimeMode, resolveFetch, shouldSendCredentials, shouldUseCookieJar } from './runtime.js';\nimport { MemoryTokenStorage, type TokenStorage } from './storage.js';\nimport { normalizeBaseUrl } from './url.js';\n\n/** Базовый URL API итд.com. Домен записан в punycode: `итд.com`. */\nexport const DEFAULT_BASE_URL = 'https://xn--d1ah4a.com';\n\n/** Таймаут запроса по умолчанию. Столько же использует официальный клиент итд.com. */\nexport const DEFAULT_TIMEOUT = 30_000;\n\n/**\n * Версия библиотеки — попадает в `User-Agent`.\n */\nexport const LIBRARY_VERSION = '0.0.6';\n\n/**\n * `User-Agent` по умолчанию.\n *\n * Сайт стоит за DDoS-Guard, и запросы вовсе без `User-Agent` (так делает `fetch` в Node)\n * имеют шанс не пройти фильтр. Префикс `Mozilla/5.0` — дань традиции таких фильтров,\n * дальше идёт честное имя библиотеки: подделываться под браузер она не должна.\n *\n * В браузере заголовок не выставляется — `User-Agent` там запрещён к изменению, и среда\n * молча его игнорирует.\n */\nexport const DEFAULT_USER_AGENT = `Mozilla/5.0 (compatible; itd-api/${LIBRARY_VERSION}; +https://github.com/KiowDev/itd-api)`;\n\n/**\n * Настройки повторов со всеми значениями по умолчанию.\n *\n * Поля перечислены явно, а не через `Required<RetryOptions>`: тот снимает необязательность,\n * но оставляет `| undefined` в типе значения, раз оно указано в исходном интерфейсе.\n */\nexport interface ResolvedRetryOptions {\n attempts: number;\n baseDelay: number;\n maxDelay: number;\n jitter: number;\n retryWrites: boolean;\n shouldRetry: ((error: unknown, attempt: number) => boolean) | undefined;\n}\n\n/**\n * Паузы перед повторами при ответе `429`.\n *\n * Сервер итд.com не присылает `Retry-After` и не сообщает время сброса окна, поэтому\n * паузу приходится подбирать лестницей: от секунды, если окно почти истекло,\n * до полутора минут, если лимит исчерпан всерьёз.\n */\nexport const DEFAULT_RATE_LIMIT_DELAYS = Object.freeze([1000, 5000, 30_000, 60_000, 90_000]);\n\n/** Настройки очереди со всеми значениями по умолчанию. */\nexport interface ResolvedRateLimitOptions {\n concurrency: number;\n rps: number | undefined;\n retryDelays: readonly number[];\n respectHeaders: boolean;\n}\n\n/** Конфигурация клиента после подстановки значений по умолчанию и проверок. */\nexport interface ResolvedConfig {\n baseUrl: string;\n auth: AuthInput | undefined;\n storage: TokenStorage;\n autoRefresh: boolean;\n reloginOnRefreshFailure: boolean;\n fetch: typeof fetch;\n timeout: number;\n retry: ResolvedRetryOptions | undefined;\n rateLimit: ResolvedRateLimitOptions | undefined;\n hooks: ClientHooks;\n logger: Logger | undefined;\n headers: Record<string, string>;\n /** Значение заголовка `X-Device-Id`, если задано вручную. Иначе заводится само. */\n deviceId: string | undefined;\n /** Значение заголовка `User-Agent`. `undefined` — заголовок не выставляется. */\n userAgent: string | undefined;\n mode: RuntimeMode;\n /** Вести ли собственный cookie-jar (вне браузера и React Native). */\n useCookieJar: boolean;\n /** Отправлять ли `credentials: 'include'` (в браузере). */\n sendCredentials: boolean;\n}\n\nfunction requirePositive(value: number, name: string): number {\n if (!Number.isFinite(value) || value < 0) {\n throw new ItdConfigError(`${name} должен быть неотрицательным числом, получено: ${value}`);\n }\n return value;\n}\n\n/** Логгер поверх `console` — включается опцией `logger: true`. */\nfunction consoleLogger(): Logger {\n return {\n debug: (message, ...args) => console.debug(`[itd-api] ${message}`, ...args),\n info: (message, ...args) => console.info(`[itd-api] ${message}`, ...args),\n warn: (message, ...args) => console.warn(`[itd-api] ${message}`, ...args),\n error: (message, ...args) => console.error(`[itd-api] ${message}`, ...args),\n };\n}\n\nfunction resolveRetry(retry: ItdClientOptions['retry']): ResolvedRetryOptions | undefined {\n if (retry === false) return undefined;\n\n const options = retry ?? {};\n const attempts = options.attempts ?? 3;\n\n if (!Number.isInteger(attempts) || attempts < 1) {\n throw new ItdConfigError(`retry.attempts должен быть целым числом от 1, получено: ${attempts}`);\n }\n\n const jitter = options.jitter ?? 0.3;\n if (jitter < 0 || jitter > 1) {\n throw new ItdConfigError(`retry.jitter должен быть в диапазоне 0…1, получено: ${jitter}`);\n }\n\n // Одна попытка означает отсутствие повторов — очередь ретраев можно не поднимать.\n if (attempts === 1) return undefined;\n\n return {\n attempts,\n baseDelay: requirePositive(options.baseDelay ?? 500, 'retry.baseDelay'),\n maxDelay: requirePositive(options.maxDelay ?? 30_000, 'retry.maxDelay'),\n jitter,\n retryWrites: options.retryWrites ?? false,\n shouldRetry: options.shouldRetry,\n };\n}\n\nfunction resolveRateLimit(\n rateLimit: ItdClientOptions['rateLimit'],\n): ResolvedRateLimitOptions | undefined {\n if (rateLimit === false) return undefined;\n\n const defaults = {\n concurrency: 6,\n rps: undefined,\n retryDelays: DEFAULT_RATE_LIMIT_DELAYS,\n respectHeaders: true,\n };\n if (!rateLimit) return defaults;\n\n const concurrency = rateLimit.concurrency ?? 6;\n if (!Number.isInteger(concurrency) || concurrency < 1) {\n throw new ItdConfigError(\n `rateLimit.concurrency должен быть целым числом от 1, получено: ${concurrency}`,\n );\n }\n\n if (rateLimit.rps !== undefined && (!Number.isFinite(rateLimit.rps) || rateLimit.rps <= 0)) {\n throw new ItdConfigError(\n `rateLimit.rps должен быть положительным числом, получено: ${rateLimit.rps}`,\n );\n }\n\n const retryDelays = rateLimit.retryDelays ?? defaults.retryDelays;\n for (const delay of retryDelays) requirePositive(delay, 'rateLimit.retryDelays');\n\n return {\n concurrency,\n rps: rateLimit.rps,\n retryDelays,\n respectHeaders: rateLimit.respectHeaders ?? true,\n };\n}\n\n/**\n * Проверяет форму `auth` и сообщает о типичных ошибках понятным текстом.\n *\n * Молчаливое игнорирование неверной формы приводит к загадочным `401`, поэтому\n * ошибка возникает сразу при создании клиента.\n */\nfunction validateAuth(auth: AuthInput | undefined): AuthInput | undefined {\n if (auth === undefined) return undefined;\n\n if (typeof auth === 'string') {\n if (auth.trim() === '') {\n throw new ItdConfigError('auth: передана пустая строка вместо accessToken');\n }\n return auth;\n }\n\n if (typeof auth !== 'object' || auth === null) {\n throw new ItdConfigError(\n `auth должен быть строкой с токеном или объектом, получено: ${typeof auth}`,\n );\n }\n\n if ('getToken' in auth) {\n if (typeof auth.getToken !== 'function') {\n throw new ItdConfigError('auth.getToken должен быть функцией');\n }\n return auth;\n }\n\n if ('accessToken' in auth) {\n if (typeof auth.accessToken !== 'string' || auth.accessToken.trim() === '') {\n throw new ItdConfigError('auth.accessToken должен быть непустой строкой');\n }\n return auth;\n }\n\n if ('email' in auth || 'password' in auth) {\n const { email, password, turnstileToken, getTurnstileToken } = auth as {\n email?: unknown;\n password?: unknown;\n turnstileToken?: unknown;\n getTurnstileToken?: unknown;\n };\n if (typeof email !== 'string' || email.trim() === '') {\n throw new ItdConfigError('auth.email должен быть непустой строкой');\n }\n if (typeof password !== 'string' || password === '') {\n throw new ItdConfigError('auth.password должен быть непустой строкой');\n }\n if (getTurnstileToken !== undefined && typeof getTurnstileToken !== 'function') {\n throw new ItdConfigError('auth.getTurnstileToken должен быть функцией');\n }\n if (\n turnstileToken !== undefined &&\n (typeof turnstileToken !== 'string' || turnstileToken.trim() === '')\n ) {\n throw new ItdConfigError('auth.turnstileToken должен быть непустой строкой');\n }\n\n // Отсутствие капчи — не ошибка конфигурации: сессия может быть восстановлена из\n // хранилища, и до входа по паролю дело вообще не дойдёт. Ошибка возникнет в момент\n // входа, где её текст может объяснить, что именно нужно сделать.\n return auth;\n }\n\n throw new ItdConfigError(\n 'auth не распознан. Ожидается строка с accessToken либо объект ' +\n '{ accessToken }, { email, password } или { getToken }',\n );\n}\n\n/**\n * Приводит пользовательские опции к полной конфигурации.\n *\n * Все проверки выполняются здесь, до единого сетевого запроса: неверная настройка должна\n * проявляться при создании клиента, а не через полчаса работы бота.\n *\n * @throws {ItdConfigError} при некорректных значениях\n */\nexport function resolveConfig(options: ItdClientOptions = {}): ResolvedConfig {\n const mode: RuntimeMode = options.mode ?? RuntimeMode.Auto;\n\n if (!Object.values(RuntimeMode).includes(mode)) {\n throw new ItdConfigError(\n `mode должен быть одним из ${Object.values(RuntimeMode).join(', ')}, получено: ${mode}`,\n );\n }\n\n const timeout = requirePositive(options.timeout ?? DEFAULT_TIMEOUT, 'timeout');\n\n if (\n options.deviceId !== undefined &&\n (typeof options.deviceId !== 'string' || options.deviceId.trim() === '')\n ) {\n throw new ItdConfigError('deviceId должен быть непустой строкой');\n }\n\n return {\n baseUrl: normalizeBaseUrl(options.baseUrl ?? DEFAULT_BASE_URL),\n auth: validateAuth(options.auth),\n storage: options.storage ?? new MemoryTokenStorage(),\n autoRefresh: options.autoRefresh ?? true,\n reloginOnRefreshFailure: options.reloginOnRefreshFailure ?? true,\n fetch: resolveFetch(options.fetch),\n timeout,\n retry: resolveRetry(options.retry),\n rateLimit: resolveRateLimit(options.rateLimit),\n hooks: options.hooks ?? {},\n logger: options.logger === true ? consoleLogger() : options.logger || undefined,\n headers: { ...options.headers },\n deviceId: options.deviceId,\n // `false` — способ не слать заголовок вовсе; строка заменяет умолчание.\n userAgent: options.userAgent === false ? undefined : (options.userAgent ?? DEFAULT_USER_AGENT),\n mode,\n useCookieJar: shouldUseCookieJar(mode),\n sendCredentials: shouldSendCredentials(mode),\n };\n}\n","import { isBlob } from './runtime.js';\n\n/** Заголовки, значение которых нельзя писать в лог целиком. */\nconst SECRET_HEADERS = new Set(['authorization', 'cookie', 'set-cookie', 'x-api-key']);\n\n/** Поля тела запроса, значение которых нельзя писать в лог. */\nconst SECRET_FIELDS = new Set([\n 'password',\n 'oldpassword',\n 'newpassword',\n 'accesstoken',\n 'refreshtoken',\n 'currentpassword',\n 'flowtoken',\n 'token',\n 'turnstiletoken',\n 'otp',\n]);\n\n/**\n * Прячет середину секрета, оставляя концы для сопоставления.\n *\n * @example\n * ```ts\n * maskSecret('eyJhbGciOiJIUzI1NiJ9.abc'); // 'eyJh…(24)…abc'\n * ```\n */\nexport function maskSecret(value: string): string {\n if (value.length <= 8) return '…';\n return `${value.slice(0, 4)}…(${value.length})…${value.slice(-3)}`;\n}\n\n/**\n * Готовит заголовки к записи в лог.\n *\n * `Authorization` и `Cookie` маскируются: логи часто уезжают в системы сбора,\n * и токен доступа в них попадать не должен.\n */\nexport function redactHeaders(headers: Headers): Record<string, string> {\n const result: Record<string, string> = {};\n\n headers.forEach((value, name) => {\n if (SECRET_HEADERS.has(name.toLowerCase())) {\n // У Authorization маскируем только сам токен, схему («Bearer») оставляем видимой.\n const spaceAt = value.indexOf(' ');\n result[name] =\n spaceAt > 0\n ? `${value.slice(0, spaceAt)} ${maskSecret(value.slice(spaceAt + 1))}`\n : maskSecret(value);\n return;\n }\n result[name] = value;\n });\n\n return result;\n}\n\n/**\n * Готовит тело запроса к записи в лог: пароли, токены и коды OTP заменяются заглушкой.\n *\n * Обходит вложенные объекты и массивы. `FormData` и бинарные тела не раскрываются вовсе.\n */\nexport function redactBody(body: unknown): unknown {\n if (body === null || body === undefined) return body;\n\n if (typeof FormData !== 'undefined' && body instanceof FormData) return '[FormData]';\n if (isBlob(body)) return '[Blob]';\n if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) return '[binary]';\n\n if (Array.isArray(body)) return body.map(redactBody);\n\n if (typeof body === 'object') {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(body)) {\n result[key] = SECRET_FIELDS.has(key.toLowerCase()) ? '[скрыто]' : redactBody(value);\n }\n return result;\n }\n\n return body;\n}\n","/**\n * Снимает внешнюю обёртку `{ data: … }`.\n *\n * Это единственное преобразование ответа, которое делает транспортный слой. Формы ответов у\n * итд.com непоследовательны: одни эндпоинты заворачивают полезную нагрузку в `data`, другие\n * отдают её напрямую (`GET /api/notifications/` → `{ notifications, hasMore }`), третьи кладут\n * список в поле по имени сущности. Угадывать имя поля опасно, поэтому его разбирает каждый\n * метод ресурса явно, а здесь снимается только однозначная обёртка.\n *\n * Обёртка считается обёрткой, лишь когда `data` — **единственный** ключ объекта. Ответ\n * `{ data: …, meta: … }` вернётся как есть.\n *\n * @example\n * ```ts\n * unwrapData({ data: { posts: [] } }); // { posts: [] }\n * unwrapData({ notifications: [], hasMore }); // без изменений\n * unwrapData({ data: [], hasMore: true }); // без изменений — ключей больше одного\n * ```\n */\nexport function unwrapData(body: unknown): unknown {\n if (typeof body !== 'object' || body === null || Array.isArray(body)) return body;\n\n const keys = Object.keys(body);\n if (keys.length !== 1 || keys[0] !== 'data') return body;\n\n return (body as { data: unknown }).data;\n}\n\n/**\n * Обычный объект — не `null`, не массив.\n *\n * Живёт здесь, а не в каждом разборщике ответа: одна и та же проверка нужна и фабрике\n * ошибок, и приведению уведомлений.\n */\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/** Непустая строка либо `undefined`. Отличается от {@link pickString} тем, что берёт значение, а не поле. */\nexport function asString(value: unknown): string | undefined {\n return typeof value === 'string' && value.length > 0 ? value : undefined;\n}\n\n/**\n * Достаёт поле-список из ответа, уже прошедшего {@link unwrapData}.\n *\n * Если поля нет или оно не массив, возвращается пустой массив: сервер иногда опускает\n * пустые коллекции, и падать из-за этого библиотека не должна.\n */\nexport function pickArray<T>(source: unknown, field: string): T[] {\n if (typeof source !== 'object' || source === null) return [];\n const value = (source as Record<string, unknown>)[field];\n return Array.isArray(value) ? (value as T[]) : [];\n}\n\n/** Достаёт объект по имени поля. Возвращает `undefined`, если это не объект. */\nexport function pickObject(source: unknown, field: string): Record<string, unknown> | undefined {\n if (typeof source !== 'object' || source === null) return undefined;\n const value = (source as Record<string, unknown>)[field];\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return undefined;\n return value as Record<string, unknown>;\n}\n\n/** Достаёт булево поле. Возвращает `fallback`, если поля нет или тип не тот. */\nexport function pickBoolean(source: unknown, field: string, fallback = false): boolean {\n if (typeof source !== 'object' || source === null) return fallback;\n const value = (source as Record<string, unknown>)[field];\n return typeof value === 'boolean' ? value : fallback;\n}\n\n/** Достаёт числовое поле. Возвращает `fallback`, если поля нет или значение не конечное число. */\nexport function pickNumber(source: unknown, field: string, fallback: number): number {\n if (typeof source !== 'object' || source === null) return fallback;\n const value = (source as Record<string, unknown>)[field];\n return typeof value === 'number' && Number.isFinite(value) ? value : fallback;\n}\n\n/** Достаёт строковое поле. Возвращает `undefined`, если поля нет, оно пустое или не строка. */\nexport function pickString(source: unknown, field: string): string | undefined {\n if (typeof source !== 'object' || source === null) return undefined;\n const value = (source as Record<string, unknown>)[field];\n return typeof value === 'string' && value.length > 0 ? value : undefined;\n}\n","import type { ItdErrorCode } from '../types/enums.js';\nimport {\n type ItdApiError,\n ItdApiError as ItdApiErrorClass,\n ItdAuthError,\n ItdConflictError,\n type ItdFieldErrors,\n ItdForbiddenError,\n ItdNotFoundError,\n ItdPhoneVerificationError,\n ItdRateLimitError,\n ItdServerError,\n ItdValidationError,\n} from './errors.js';\nimport { redactBody } from './redact.js';\nimport { asString, isRecord } from './unwrap.js';\n\n/** Разобранное тело ошибки, приведённое к одной форме. */\nexport interface ParsedErrorBody {\n code: ItdErrorCode;\n message: string;\n detail: string | undefined;\n title: string | undefined;\n fieldErrors: ItdFieldErrors;\n /** Идентификатор пользователя, если сервер его вернул (нужен для ссылки подтверждения телефона). */\n userId: string | undefined;\n}\n\n/**\n * Сводит ошибки по полям к единой форме `{ поле: [сообщения] }`.\n *\n * Понимает две документированные формы:\n * - `errors: { email: ['…'] }` либо `errors: { email: '…' }`\n * - `violations: [{ field: 'email', message: '…' }]`\n */\nfunction collectFieldErrors(source: Record<string, unknown>): ItdFieldErrors {\n const result: ItdFieldErrors = {};\n\n const errors = source.errors;\n if (isRecord(errors)) {\n for (const [field, value] of Object.entries(errors)) {\n if (Array.isArray(value)) {\n const messages = value.filter((item): item is string => typeof item === 'string');\n if (messages.length > 0) result[field] = messages;\n } else if (typeof value === 'string') {\n result[field] = [value];\n }\n }\n }\n\n const violations = source.violations;\n if (Array.isArray(violations)) {\n for (const violation of violations) {\n if (!isRecord(violation)) continue;\n const field = asString(violation.field) ?? asString(violation.property);\n const message = asString(violation.message);\n if (!field || !message) continue;\n const existing = result[field];\n if (existing) existing.push(message);\n else result[field] = [message];\n }\n }\n\n return result;\n}\n\n/**\n * Разбирает тело ответа с ошибкой.\n *\n * API отдаёт ошибки в двух формах — с обёрткой `{ error: … }` и без неё, — а при сбое на\n * уровне прокси может вернуть вообще не JSON. Все три случая сводятся к одной структуре.\n *\n * @param body тело ответа: разобранный JSON, строка или `undefined`\n * @param status HTTP-статус, используется для сообщения по умолчанию\n * @param statusText текст статуса из ответа\n */\nexport function parseErrorBody(body: unknown, status: number, statusText = ''): ParsedErrorBody {\n const fallbackMessage = statusText ? `HTTP ${status} ${statusText}` : `HTTP ${status}`;\n\n // Не-JSON: HTML от прокси, простой текст, пустое тело.\n if (typeof body === 'string') {\n return {\n code: 'UNKNOWN_ERROR',\n message: asString(body.trim()) ?? fallbackMessage,\n detail: undefined,\n title: undefined,\n fieldErrors: {},\n userId: undefined,\n };\n }\n\n if (!isRecord(body)) {\n return {\n code: 'UNKNOWN_ERROR',\n message: fallbackMessage,\n detail: undefined,\n title: undefined,\n fieldErrors: {},\n userId: undefined,\n };\n }\n\n // Ответ вида `{ type: \"validation\", on: \"query\", found: {…} }` — так сервер сообщает\n // о непрошедшей проверке параметров. Ни кода, ни текста в нём нет.\n if (body.type === 'validation') {\n const target = asString(body.on);\n\n return {\n code: 'VALIDATION_ERROR',\n message: target\n ? `Проверка не пройдена: некорректные данные в «${target}»`\n : 'Проверка входных данных не пройдена',\n detail: undefined,\n title: undefined,\n fieldErrors: {},\n userId: undefined,\n };\n }\n\n // Форма `{ error: { code, message, … } }` — работаем с вложенным объектом,\n // но поля верхнего уровня остаются запасным источником.\n const inner = isRecord(body.error) ? body.error : body;\n\n const message =\n asString(inner.message) ??\n asString(inner.detail) ??\n asString(inner.title) ??\n // `{ \"error\": \"Invalid token\" }` — так отвечает сервер на недействительный токен.\n asString(body.error) ??\n fallbackMessage;\n\n return {\n code: (asString(inner.code) ?? asString(body.code) ?? 'UNKNOWN_ERROR') as ItdErrorCode,\n message,\n detail: asString(inner.detail),\n title: asString(inner.title),\n fieldErrors: { ...collectFieldErrors(body), ...collectFieldErrors(inner) },\n userId: asString(inner.userId) ?? asString(body.userId),\n };\n}\n\n/**\n * Переводит заголовок `Retry-After` в миллисекунды.\n *\n * Поддерживает обе формы из спецификации HTTP: число секунд и дату.\n * Возвращает `undefined`, если заголовка нет или он не разбирается.\n */\nexport function parseRetryAfter(\n header: string | null | undefined,\n now = Date.now(),\n): number | undefined {\n if (!header) return undefined;\n\n const seconds = Number(header);\n if (Number.isFinite(seconds)) return Math.max(0, seconds * 1000);\n\n const date = Date.parse(header);\n if (Number.isFinite(date)) return Math.max(0, date - now);\n\n return undefined;\n}\n\n/** Читает целое число из заголовка. */\nfunction readIntHeader(headers: Headers | undefined, name: string): number | undefined {\n const raw = headers?.get(name);\n if (raw === null || raw === undefined) return undefined;\n\n const value = Number.parseInt(raw, 10);\n return Number.isFinite(value) ? value : undefined;\n}\n\n/**\n * Читает сведения об ограничении частоты.\n *\n * Сервер сообщает размер окна и остаток, но **не сообщает время сброса** — поэтому\n * точный момент, когда можно повторить, из ответа не вывести.\n */\nexport function readRateLimit(headers: Headers | undefined): {\n limit: number | undefined;\n remaining: number | undefined;\n} {\n return {\n limit: readIntHeader(headers, 'x-ratelimit-limit'),\n remaining: readIntHeader(headers, 'x-ratelimit-remaining'),\n };\n}\n\nconst REQUEST_ID_HEADERS = ['x-request-id', 'x-requestid', 'request-id', 'x-correlation-id'];\n\n/** Достаёт идентификатор запроса из заголовков ответа — пригодится при обращении в поддержку. */\nexport function getRequestId(headers: Headers | undefined): string | undefined {\n if (!headers) return undefined;\n for (const name of REQUEST_ID_HEADERS) {\n const value = headers.get(name);\n if (value) return value;\n }\n return undefined;\n}\n\n/** Соответствие кода ошибки конкретному классу. Приоритетнее, чем HTTP-статус. */\nconst CODE_TO_CLASS: Record<string, new (init: never) => ItdApiError> = {\n VALIDATION_ERROR: ItdValidationError,\n RATE_LIMIT_EXCEEDED: ItdRateLimitError,\n UNAUTHORIZED: ItdAuthError,\n SESSION_EXPIRED: ItdAuthError,\n SESSION_REVOKED: ItdAuthError,\n SESSION_INVALID_REFRESH_TOKEN: ItdAuthError,\n // Оба приходят с `/auth/refresh`: первый — когда cookie refresh_token не долетела,\n // второй — когда она есть, но сессия за ней уже мертва.\n REFRESH_TOKEN_MISSING: ItdAuthError,\n SESSION_NOT_FOUND: ItdAuthError,\n ACCOUNT_INVALID_CREDENTIALS: ItdAuthError,\n ACCESS_DENIED: ItdForbiddenError,\n ENTITY_NOT_FOUND: ItdNotFoundError,\n // Сервер отвечает именно так: `{ error: { code: 'NOT_FOUND', message: 'Post not found' } }`.\n NOT_FOUND: ItdNotFoundError,\n ENTITY_ALREADY_EXISTS: ItdConflictError,\n};\n\n/** Соответствие HTTP-статуса классу — запасной вариант, когда код ничего не говорит. */\nfunction classByStatus(status: number): new (init: never) => ItdApiError {\n if (status === 401) return ItdAuthError;\n if (status === 403) return ItdForbiddenError;\n if (status === 404) return ItdNotFoundError;\n if (status === 409) return ItdConflictError;\n if (status === 422) return ItdValidationError;\n if (status === 429) return ItdRateLimitError;\n if (status >= 500) return ItdServerError;\n return ItdApiErrorClass;\n}\n\n/**\n * Готовит тело ответа к сохранению в `ItdApiError.raw`.\n *\n * При `422` сервер возвращает присланное тело эхом: `{ type: 'validation', on: 'body',\n * found: { email: '…', password: '…' } }`. Ошибка обычно доезжает до логов и систем сбора\n * вроде Sentry — пароль в ней оказаться не должен. Имена полей для диагностики остаются,\n * значения секретов заменяются заглушкой.\n */\nfunction safeRawBody(body: unknown): unknown {\n if (!isRecord(body) || body.type !== 'validation' || !isRecord(body.found)) return body;\n\n return { ...body, found: redactBody(body.found) };\n}\n\n/** Что нужно знать о запросе, чтобы построить ошибку. */\nexport interface ErrorContext {\n method: string;\n path: string;\n status: number;\n statusText?: string | undefined;\n headers?: Headers | undefined;\n response?: Response | undefined;\n /** Тело ответа: разобранный JSON либо строка. */\n body: unknown;\n}\n\n/**\n * Строит типизированную ошибку из ответа сервера.\n *\n * Класс выбирается сначала по коду ошибки, затем по HTTP-статусу — так `VALIDATION_ERROR`\n * со статусом `400` всё равно станет {@link ItdValidationError}.\n */\nexport function createApiError(context: ErrorContext): ItdApiError {\n const parsed = parseErrorBody(context.body, context.status, context.statusText);\n const rateLimit = readRateLimit(context.headers);\n\n const init = {\n rateLimit: rateLimit.limit,\n rateLimitRemaining: rateLimit.remaining,\n status: context.status,\n code: parsed.code,\n message: parsed.message,\n detail: parsed.detail,\n title: parsed.title,\n fieldErrors: parsed.fieldErrors,\n requestId: getRequestId(context.headers),\n method: context.method,\n path: context.path,\n raw: safeRawBody(context.body),\n response: context.response,\n retryAfter: parseRetryAfter(context.headers?.get('retry-after')),\n };\n\n if (parsed.code === 'PHONE_VERIFICATION_REQUIRED') {\n return new ItdPhoneVerificationError({ ...init, userId: parsed.userId });\n }\n\n const Ctor = CODE_TO_CLASS[parsed.code] ?? classByStatus(context.status);\n return new Ctor(init as never);\n}\n","import type { RawRequestOptions } from '../types/options.js';\nimport type { ResolvedConfig } from './config.js';\nimport { createApiError, readRateLimit } from './error-factory.js';\nimport { ItdAbortError, ItdConfigError, ItdNetworkError, ItdTimeoutError } from './errors.js';\nimport type { PluginRegistry } from './plugins.js';\nimport { redactBody, redactHeaders } from './redact.js';\nimport { isBlob } from './runtime.js';\nimport { unwrapData } from './unwrap.js';\nimport { buildQuery, joinUrl } from './url.js';\n\n/**\n * Подключаемые части конвейера.\n *\n * Авторизация, cookie, очередь и повторы живут в отдельных модулях и подставляются сюда.\n * Благодаря этому транспорт тестируется изолированно, а `HttpClient` ничего не знает\n * о том, как именно добывается токен.\n */\nexport interface HttpCollaborators {\n /** Заголовки авторизации для запроса. Вызывается перед каждой попыткой. */\n getAuthHeaders?(): Promise<Record<string, string>> | Record<string, string>;\n /**\n * Реакция на ответ `401`.\n *\n * Должна вернуть `true`, если токен обновлён и запрос имеет смысл повторить.\n * Повтор выполняется ровно один раз.\n */\n onUnauthorized?(): Promise<boolean>;\n /**\n * Идентификатор устройства для заголовка `X-Device-Id`.\n *\n * Отдельно от {@link getAuthHeaders}, потому что нужен и на анонимных запросах —\n * например на `sign-in`, где заголовка авторизации ещё нет.\n */\n getDeviceId?(): Promise<string> | string;\n /** Значение заголовка `Cookie` для указанного URL. */\n getCookieHeader?(url: string): string | undefined;\n /** Приём `Set-Cookie` из ответа. */\n saveCookies?(url: string, response: Response): void;\n /** Очередь запросов: ограничение конкурентности и частоты. */\n schedule?<T>(task: () => Promise<T>): Promise<T>;\n /**\n * Сообщает об остатке лимита из заголовков ответа.\n *\n * Вызывается после **каждого** ответа, включая ошибочные, — так очередь узнаёт\n * об исчерпании лимита заранее и успевает притормозить до отказа сервера.\n */\n onRateLimit?(limit: number | undefined, remaining: number | undefined): void;\n /**\n * Планировщик повторов.\n *\n * Возвращает паузу в мс перед следующей попыткой либо `undefined`, если повторять не нужно.\n */\n nextRetryDelay?(error: unknown, attempt: number, method: string): number | undefined;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/** Отдаётся, пока плагинов нет: заводить набор на каждый запрос незачем. */\nconst EMPTY_KEYS: ReadonlySet<string> = new Set<string>();\n\n/**\n * Ставит заголовок, превращая ограничение HTTP в понятное сообщение.\n *\n * Значения заголовков ограничены latin1, поэтому кириллица в них невозможна. Среда\n * сообщает об этом невнятным `Cannot convert argument to a ByteString`, что при русских\n * названиях приложений сбивает с толку.\n */\nfunction setHeader(headers: Headers, name: string, value: string): void {\n try {\n headers.set(name, value);\n } catch {\n throw new ItdConfigError(\n `Значение заголовка ${name} содержит символы вне latin1. HTTP-заголовки не могут ` +\n 'содержать кириллицу — закодируйте значение, например через encodeURIComponent.',\n );\n }\n}\n\n/** Тело, которое отправляется как есть, без сериализации в JSON. */\nfunction isRawBody(body: unknown): body is BodyInit {\n if (typeof body !== 'object' || body === null) return typeof body === 'string';\n return (\n (typeof FormData !== 'undefined' && body instanceof FormData) ||\n isBlob(body) ||\n (typeof URLSearchParams !== 'undefined' && body instanceof URLSearchParams) ||\n (typeof ReadableStream !== 'undefined' && body instanceof ReadableStream) ||\n body instanceof ArrayBuffer ||\n ArrayBuffer.isView(body)\n );\n}\n\n/**\n * Читает тело ответа один раз.\n *\n * Ответ можно прочитать только однократно, а тело нужно и при успехе, и при ошибке,\n * поэтому чтение происходит здесь, до ветвления по статусу.\n */\nasync function readBody(response: Response): Promise<unknown> {\n if (response.status === 204 || response.status === 205) return undefined;\n if (response.headers.get('content-length') === '0') return undefined;\n\n const contentType = response.headers.get('content-type') ?? '';\n\n if (contentType.includes('json')) {\n const text = await response.text();\n if (text === '') return undefined;\n try {\n return JSON.parse(text) as unknown;\n } catch {\n // Заголовок обещал JSON, но тело им не является — отдаём как текст,\n // чтобы сообщение об ошибке осталось информативным.\n return text;\n }\n }\n\n const text = await response.text();\n return text === '' ? undefined : text;\n}\n\n/** Результат объединения пользовательской отмены и таймаута. */\ninterface AbortBundle {\n signal: AbortSignal;\n /** Сработал ли именно таймаут — от этого зависит класс ошибки. */\n timedOut: () => boolean;\n cleanup: () => void;\n}\n\n/**\n * Объединяет пользовательский `AbortSignal` с таймаутом.\n *\n * Реализовано вручную, а не через `AbortSignal.any`: последний появился только в Node 20,\n * а библиотека поддерживает Node 18.\n */\nfunction createAbortBundle(userSignal: AbortSignal | undefined, timeout: number): AbortBundle {\n const controller = new AbortController();\n let timedOut = false;\n\n const onUserAbort = () => controller.abort(userSignal?.reason);\n\n if (userSignal) {\n if (userSignal.aborted) controller.abort(userSignal.reason);\n else userSignal.addEventListener('abort', onUserAbort, { once: true });\n }\n\n const timer =\n timeout > 0\n ? setTimeout(() => {\n timedOut = true;\n controller.abort();\n }, timeout)\n : undefined;\n\n return {\n signal: controller.signal,\n timedOut: () => timedOut,\n cleanup: () => {\n if (timer !== undefined) clearTimeout(timer);\n userSignal?.removeEventListener('abort', onUserAbort);\n },\n };\n}\n\n/**\n * Транспортный слой: единственное место, откуда библиотека ходит в сеть.\n *\n * Отвечает за сборку URL, заголовки, таймауты, разбор ответа и превращение любой неудачи\n * в типизированную ошибку. Авторизация, cookie, очередь и повторы подключаются извне\n * через {@link HttpCollaborators}.\n */\nexport class HttpClient {\n readonly #config: ResolvedConfig;\n #collaborators: HttpCollaborators;\n #plugins: PluginRegistry | undefined;\n\n constructor(config: ResolvedConfig, collaborators: HttpCollaborators = {}) {\n this.#config = config;\n this.#collaborators = collaborators;\n }\n\n /** Базовый URL, к которому обращается клиент. */\n get baseUrl(): string {\n return this.#config.baseUrl;\n }\n\n /**\n * Имена опций запроса, заявленные плагинами.\n *\n * Читается ресурсами: они переносят в транспорт только известные поля, а чужие,\n * если их никто не заявил, отсеивают.\n */\n get pluginOptionKeys(): ReadonlySet<string> {\n return this.#plugins?.optionKeys ?? EMPTY_KEYS;\n }\n\n /** Подключает список плагинов. Реестр общий с клиентом и пополняется через `itd.use()`. */\n usePlugins(plugins: PluginRegistry): void {\n this.#plugins = plugins;\n }\n\n /**\n * Подключает недостающие части конвейера.\n *\n * Нужно из-за кольцевой зависимости: слой авторизации сам выполняет запросы, поэтому\n * не может быть передан в конструктор до создания транспорта.\n */\n setCollaborators(collaborators: HttpCollaborators): void {\n this.#collaborators = { ...this.#collaborators, ...collaborators };\n }\n\n /**\n * Выполняет запрос к API.\n *\n * @typeParam T ожидаемая форма ответа после снятия обёртки `{ data: … }`\n * @throws {ItdApiError} если сервер ответил статусом ≥ 400\n * @throws {ItdTimeoutError} если истёк таймаут\n * @throws {ItdAbortError} если запрос отменён через `signal`\n * @throws {ItdNetworkError} если запрос не дошёл до сервера\n */\n async request<T = unknown>(options: RawRequestOptions): Promise<T> {\n const task = () => this.#withPlugins<T>(options);\n\n // `skipQueue` разрывает круговое ожидание: запрос, порождённый изнутри другого запроса\n // (продление токена, отложенный вход), не может ждать места в очереди — это место\n // занято тем самым запросом, который ждёт его результата.\n if (!this.#collaborators.schedule || options.skipQueue) return task();\n\n return this.#collaborators.schedule(task);\n }\n\n /**\n * Прогоняет запрос через обёртки плагинов.\n *\n * Цепочка стоит **снаружи повторов и внутри очереди**: плагин должен увидеть запрос\n * и ответ по одному разу, независимо от того, сколько попыток понадобилось, — иначе,\n * например, текст поста зашифруется повторно на второй попытке.\n */\n #withPlugins<T>(options: RawRequestOptions): Promise<T> {\n const plugins = this.#plugins;\n if (!plugins || plugins.size === 0) return this.#withRetries<T>(options);\n\n return plugins.run(options, (request) => this.#withRetries<T>(request)) as Promise<T>;\n }\n\n async #withRetries<T>(options: RawRequestOptions): Promise<T> {\n const method = options.method.toUpperCase();\n\n for (let attempt = 1; ; attempt++) {\n try {\n return await this.#attempt<T>(options, attempt);\n } catch (error) {\n const delay = this.#collaborators.nextRetryDelay?.(error, attempt, method);\n if (delay === undefined) throw error;\n\n await this.#config.hooks.onRetry?.({\n method,\n path: options.path,\n url: this.#buildUrl(options),\n headers: new Headers(),\n attempt,\n error,\n delay,\n });\n\n this.#config.logger?.debug(\n `повтор ${method} ${options.path}, попытка ${attempt + 1} через ${delay} мс`,\n );\n\n await sleep(delay);\n }\n }\n }\n\n #buildUrl(options: RawRequestOptions): string {\n return joinUrl(this.#config.baseUrl, options.path) + buildQuery(options.query);\n }\n\n async #buildHeaders(options: RawRequestOptions, url: string): Promise<Headers> {\n const headers = new Headers();\n\n headers.set('Accept', 'application/json');\n // Сервер этот заголовок не требует, но ожидает: дешевле отправить, чем разбираться,\n // почему часть запросов не проходит фильтры.\n headers.set('X-Requested-With', 'XMLHttpRequest');\n\n // В браузере это запрещённый заголовок: среда молча его игнорирует, ошибки не будет.\n if (this.#config.userAgent) setHeader(headers, 'User-Agent', this.#config.userAgent);\n\n if (this.#collaborators.getDeviceId) {\n setHeader(headers, 'X-Device-Id', await this.#collaborators.getDeviceId());\n }\n\n // Пользовательские заголовки идут после умолчаний, чтобы их можно было переопределить.\n for (const [name, value] of Object.entries(this.#config.headers))\n setHeader(headers, name, value);\n\n if (!options.skipAuth && this.#collaborators.getAuthHeaders) {\n const auth = await this.#collaborators.getAuthHeaders();\n for (const [name, value] of Object.entries(auth)) setHeader(headers, name, value);\n }\n\n if (this.#config.useCookieJar && this.#collaborators.getCookieHeader) {\n const cookie = this.#collaborators.getCookieHeader(url);\n if (cookie) setHeader(headers, 'Cookie', cookie);\n }\n\n for (const [name, value] of Object.entries(options.headers ?? {})) {\n setHeader(headers, name, value);\n }\n\n return headers;\n }\n\n async #attempt<T>(options: RawRequestOptions, attempt: number): Promise<T> {\n const method = options.method.toUpperCase();\n const url = this.#buildUrl(options);\n const headers = await this.#buildHeaders(options, url);\n\n let body: BodyInit | undefined;\n if (options.body !== undefined && options.body !== null) {\n if (isRawBody(options.body)) {\n // Content-Type для FormData выставляет сама среда — вместе с boundary.\n body = options.body;\n } else {\n body = JSON.stringify(options.body);\n if (!headers.has('Content-Type')) headers.set('Content-Type', 'application/json');\n }\n }\n\n const context = { method, path: options.path, url, headers, attempt };\n await this.#config.hooks.onRequest?.(context);\n\n const timeout = options.timeout ?? this.#config.timeout;\n const abort = createAbortBundle(options.signal, timeout);\n const startedAt = Date.now();\n\n this.#config.logger?.debug(`→ ${method} ${options.path}`, {\n headers: redactHeaders(headers),\n body: redactBody(options.body),\n });\n\n let response: Response;\n try {\n response = await this.#config.fetch(url, {\n method,\n headers,\n signal: abort.signal,\n ...(body !== undefined ? { body } : {}),\n ...(this.#config.sendCredentials ? { credentials: 'include' as const } : {}),\n });\n } catch (error) {\n const duration = Date.now() - startedAt;\n const failure = this.#toTransportError(error, abort, options, method, timeout);\n\n await this.#config.hooks.onError?.({ ...context, duration, error: failure });\n this.#config.logger?.warn(`× ${method} ${options.path} (${duration} мс): ${failure.message}`);\n\n throw failure;\n } finally {\n abort.cleanup();\n }\n\n const duration = Date.now() - startedAt;\n\n if (this.#collaborators.onRateLimit) {\n const { limit, remaining } = readRateLimit(response.headers);\n this.#collaborators.onRateLimit(limit, remaining);\n }\n\n if (this.#config.useCookieJar) this.#collaborators.saveCookies?.(url, response);\n\n const payload = await readBody(response);\n\n if (!response.ok) {\n // Обновление токена и повтор — ровно один раз, чтобы не зациклиться, если\n // сервер отдаёт 401 и на свежем токене.\n if (\n response.status === 401 &&\n !options.skipAuthRefresh &&\n this.#config.autoRefresh &&\n this.#collaborators.onUnauthorized\n ) {\n const refreshed = await this.#collaborators.onUnauthorized();\n if (refreshed) {\n this.#config.logger?.debug(`токен обновлён, повторяю ${method} ${options.path}`);\n return this.#attempt<T>({ ...options, skipAuthRefresh: true }, attempt);\n }\n }\n\n const error = createApiError({\n method,\n path: options.path,\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n response,\n body: payload,\n });\n\n await this.#config.hooks.onError?.({ ...context, duration, error });\n this.#config.logger?.warn(\n `← ${response.status} ${method} ${options.path} (${duration} мс): ${error.message}`,\n );\n\n throw error;\n }\n\n await this.#config.hooks.onResponse?.({\n ...context,\n status: response.status,\n duration,\n response,\n });\n\n this.#config.logger?.debug(`← ${response.status} ${method} ${options.path} (${duration} мс)`);\n\n return (options.raw ? payload : unwrapData(payload)) as T;\n }\n\n /** Превращает исключение `fetch` в понятную ошибку библиотеки. */\n #toTransportError(\n error: unknown,\n abort: AbortBundle,\n options: RawRequestOptions,\n method: string,\n timeout: number,\n ): ItdTimeoutError | ItdAbortError | ItdNetworkError {\n const aborted = error instanceof Error && error.name === 'AbortError';\n\n if (aborted && abort.timedOut()) {\n return new ItdTimeoutError({ timeout, method, path: options.path });\n }\n\n if (aborted) {\n return new ItdAbortError(`Запрос ${method} ${options.path} отменён`);\n }\n\n return new ItdNetworkError(\n `Не удалось выполнить ${method} ${options.path}: ${error instanceof Error ? error.message : String(error)}`,\n { method, path: options.path, cause: error },\n );\n }\n}\n","import type { Logger, RawRequestOptions } from '../types/options.js';\nimport { ItdConfigError } from './errors.js';\n\n/**\n * Обёртка вокруг запроса.\n *\n * Получает описание запроса и продолжение цепочки. Может изменить запрос перед отправкой,\n * посмотреть и подменить разобранный ответ или вовсе не вызывать `next` и вернуть своё.\n *\n * @param request что уходит на сервер; изменять сам объект не нужно — передайте копию в `next`\n * @param next продолжение: либо следующая обёртка, либо настоящий запрос\n * @returns тело ответа в том виде, в каком его получит вызывающий код\n *\n * @example Дописать заголовок ко всем запросам\n * ```ts\n * const transformer: Transformer = (request, next) =>\n * next({ ...request, headers: { ...request.headers, 'X-Trace': trace() } });\n * ```\n */\nexport type Transformer = (\n request: RawRequestOptions,\n next: (request: RawRequestOptions) => Promise<unknown>,\n) => Promise<unknown>;\n\n/** Что плагин получает при подключении. */\nexport interface PluginContext {\n /** Базовый URL клиента — например чтобы разобрать абсолютные ссылки из ответа. */\n baseUrl: string;\n /** Отладочный вывод клиента, если он включён. */\n logger: Logger | undefined;\n /** Добавляет обёртку запроса. Подключённые раньше оказываются снаружи. */\n use(transformer: Transformer): void;\n}\n\n/**\n * Плагин клиента.\n *\n * Подключается через `itd.use(plugin)` и работает на уровне транспорта: видит запрос\n * до отправки и разобранный ответ. Библиотека не знает, что именно делает плагин, —\n * ей достаточно списка обёрток и имён опций, которые он читает.\n *\n * @example\n * ```ts\n * const logging: ItdPlugin = {\n * name: 'logging',\n * install({ use, logger }) {\n * use(async (request, next) => {\n * logger?.info(`${request.method} ${request.path}`);\n * return next(request);\n * });\n * },\n * };\n *\n * itd.use(logging);\n * ```\n */\nexport interface ItdPlugin {\n /** Имя плагина. Должно быть уникальным: повторное подключение — ошибка. */\n name: string;\n /**\n * Имена опций запроса, которые плагин читает у методов ресурсов.\n *\n * Библиотека этих опций не понимает и ничего с ними не делает — только доносит\n * от вызова метода до обёртки нетронутыми. Без такого списка чужие поля отсеиваются,\n * чтобы случайная опечатка в параметрах не уезжала на сервер.\n *\n * Имена полей самого запроса (`path`, `body`, `headers`, `signal` и прочие из\n * `RawRequestOptions`) заявить нельзя: подключение такого плагина завершится ошибкой.\n *\n * Типы для них плагин объявляет сам, дополняя `RequestOptions`:\n * ```ts\n * declare module 'itd-api' {\n * interface RequestOptions { encrypt?: string | undefined }\n * }\n * ```\n */\n optionKeys?: readonly string[];\n /** Вызывается один раз при подключении. */\n install(context: PluginContext): void;\n}\n\n/** Пустой набор — отдаётся, пока плагинов нет, чтобы не заводить объект на каждый запрос. */\nconst NO_KEYS: ReadonlySet<string> = new Set<string>();\n\n/**\n * Имена, которые плагин заявить не может.\n *\n * Заявленные опции ресурсы переносят в описание запроса поверх собранных полей, поэтому\n * имя из {@link RawRequestOptions} подменило бы путь, тело или заголовки любого вызова.\n */\nconst RESERVED_OPTION_KEYS: ReadonlySet<string> = new Set([\n 'signal',\n 'timeout',\n 'headers',\n 'retry',\n 'method',\n 'path',\n 'query',\n 'body',\n 'skipAuth',\n 'skipAuthRefresh',\n 'skipQueue',\n 'raw',\n]);\n\n/**\n * Список подключённых плагинов и собранная из них цепочка обёрток.\n *\n * Живёт в клиенте, а работает в транспорте: {@link HttpClient} прогоняет через `run`\n * каждый запрос, если плагины есть.\n */\nexport class PluginRegistry {\n readonly #transformers: Transformer[] = [];\n readonly #optionKeys = new Set<string>();\n readonly #names = new Set<string>();\n\n /** Сколько обёрток подключено. Ноль означает, что запрос идёт прежним путём. */\n get size(): number {\n return this.#transformers.length;\n }\n\n /** Имена опций запроса, заявленные плагинами. */\n get optionKeys(): ReadonlySet<string> {\n return this.#optionKeys.size === 0 ? NO_KEYS : this.#optionKeys;\n }\n\n /**\n * Подключает плагин.\n *\n * @throws {ItdConfigError} если плагин задан неверно, уже подключён или заявил занятое\n * имя опции\n */\n add(plugin: ItdPlugin, context: Omit<PluginContext, 'use'>): void {\n if (typeof plugin?.install !== 'function') {\n throw new ItdConfigError('Плагин должен быть объектом с методом install()');\n }\n\n const name = plugin.name;\n if (typeof name !== 'string' || name.trim() === '') {\n throw new ItdConfigError('У плагина должно быть непустое имя');\n }\n\n // Повторное подключение почти всегда означает недосмотр, а последствия у него\n // молчаливые: обёртка отработает дважды — текст зашифруется два раза подряд.\n if (this.#names.has(name)) {\n throw new ItdConfigError(`Плагин «${name}» уже подключён`);\n }\n\n const keys = plugin.optionKeys ?? [];\n for (const key of keys) {\n if (typeof key !== 'string' || key.trim() === '') {\n throw new ItdConfigError(`Плагин «${name}» заявил пустое имя опции`);\n }\n if (RESERVED_OPTION_KEYS.has(key)) {\n throw new ItdConfigError(\n `Плагин «${name}» заявил опцию «${key}»: это поле запроса, имя занято. ` +\n `Занятые имена: ${[...RESERVED_OPTION_KEYS].join(', ')}`,\n );\n }\n }\n\n // Реестр меняется только после того, как install() отработал целиком: иначе упавший\n // на середине плагин оставит занятое имя и половину обёрток.\n const before = this.#transformers.length;\n try {\n plugin.install({\n ...context,\n use: (transformer) => {\n if (typeof transformer !== 'function') {\n throw new ItdConfigError(`Плагин «${name}» передал в use() не функцию`);\n }\n this.#transformers.push(transformer);\n },\n });\n } catch (error) {\n this.#transformers.length = before;\n throw error;\n }\n\n this.#names.add(name);\n for (const key of keys) this.#optionKeys.add(key);\n }\n\n /**\n * Прогоняет запрос через цепочку обёрток.\n *\n * Цепочка собирается на каждый запрос заново: плагин можно подключить в любой момент,\n * а обёрток единицы — экономить тут не на чем.\n *\n * @param execute настоящий запрос, вызывается самой внутренней обёрткой\n */\n run(\n request: RawRequestOptions,\n execute: (request: RawRequestOptions) => Promise<unknown>,\n ): Promise<unknown> {\n const chain = this.#transformers.reduceRight<(r: RawRequestOptions) => Promise<unknown>>(\n (next, transformer) => (current) => transformer(current, next),\n execute,\n );\n\n return chain(request);\n }\n}\n","import type { ResolvedRateLimitOptions } from './config.js';\n\n/** Задача, ожидающая своей очереди. */\ninterface QueuedTask {\n run: () => void;\n}\n\n/**\n * Очередь запросов: ограничивает одновременность и частоту.\n *\n * Нужна прежде всего ботам: без неё цикл по сотне постов уходит в API одним залпом\n * и упирается в `RATE_LIMIT_EXCEEDED`.\n *\n * Частота выдерживается равномерным разносом стартов (`1000 / rps` между запросами),\n * а не окном со счётчиком: так нагрузка ровная, без всплеска в начале каждой секунды.\n *\n * @example\n * ```ts\n * const queue = new RequestQueue({ concurrency: 4, rps: 8 });\n * await Promise.all(ids.map((id) => queue.schedule(() => itd.posts.get(id))));\n * ```\n */\nexport class RequestQueue {\n readonly #concurrency: number;\n /** Минимальный промежуток между стартами, мс. `0` — без ограничения частоты. */\n readonly #minGap: number;\n\n readonly #waiting: QueuedTask[] = [];\n #active = 0;\n /** Момент, раньше которого следующий запрос стартовать не должен. */\n #nextSlot = 0;\n #timer: ReturnType<typeof setTimeout> | undefined;\n\n constructor(options: ResolvedRateLimitOptions) {\n this.#concurrency = options.concurrency;\n this.#minGap = options.rps ? 1000 / options.rps : 0;\n }\n\n /** Сколько задач выполняется прямо сейчас. */\n get active(): number {\n return this.#active;\n }\n\n /** Сколько задач ждёт очереди. */\n get pending(): number {\n return this.#waiting.length;\n }\n\n /**\n * Ставит задачу в очередь.\n *\n * @returns результат задачи; ошибка задачи пробрасывается без изменений\n */\n schedule<T>(task: () => Promise<T>): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n const run = () => {\n this.#active += 1;\n\n task()\n .then(resolve, reject)\n .finally(() => {\n this.#active -= 1;\n this.#drain();\n });\n };\n\n this.#waiting.push({ run });\n this.#drain();\n });\n }\n\n /**\n * Придерживает всю очередь на заданное время.\n *\n * Вызывается при получении `429` с заголовком `Retry-After`: тормозить нужно все запросы,\n * а не только тот, который наткнулся на лимит, — иначе остальные продолжат добивать API.\n */\n pause(ms: number): void {\n if (ms <= 0) return;\n this.#nextSlot = Math.max(this.#nextSlot, Date.now() + ms);\n }\n\n /** Запускает столько ожидающих задач, сколько позволяют ограничения. */\n #drain(): void {\n if (this.#waiting.length === 0) return;\n if (this.#active >= this.#concurrency) return;\n // Ждём уже запланированного пробуждения, чтобы не плодить таймеры.\n if (this.#timer !== undefined) return;\n\n const now = Date.now();\n\n if (this.#nextSlot > now) {\n this.#timer = setTimeout(() => {\n this.#timer = undefined;\n this.#drain();\n }, this.#nextSlot - now);\n return;\n }\n\n const next = this.#waiting.shift();\n if (!next) return;\n\n if (this.#minGap > 0) this.#nextSlot = now + this.#minGap;\n\n next.run();\n\n // Следующая задача может стартовать сразу, если позволяет конкурентность.\n this.#drain();\n }\n}\n","import type { ResolvedRetryOptions } from './config.js';\nimport { ItdAbortError, ItdApiError, ItdNetworkError, ItdTimeoutError } from './errors.js';\n\n/**\n * Решает, повторять ли запрос.\n *\n * @returns пауза в миллисекундах перед следующей попыткой либо `undefined`, если повторять не нужно\n */\nexport type RetryScheduler = (\n error: unknown,\n attempt: number,\n method: string,\n) => number | undefined;\n\n/**\n * Методы, повтор которых безопасен по определению.\n *\n * `DELETE` формально тоже идемпотентен, но его повтор после успеха вернёт `404`\n * и собьёт с толку — в список он не входит.\n */\nconst IDEMPOTENT_METHODS = new Set(['GET', 'HEAD', 'OPTIONS']);\n\n/**\n * Стоит ли повторять запрос после этой ошибки.\n *\n * Отдельно разобран `429`: он повторяется даже для запросов на запись, потому что\n * гарантирует, что запрос **не был обработан**. Обрыв сети и `5xx` такой гарантии не дают —\n * сервер мог успеть создать пост, — поэтому запись по умолчанию не повторяется.\n */\nfunction isRetryable(error: unknown, method: string, retryWrites: boolean): boolean {\n // Отмену повторять нельзя ни при каких условиях: её попросил пользователь.\n if (error instanceof ItdAbortError) return false;\n\n const safeToRepeat = retryWrites || IDEMPOTENT_METHODS.has(method);\n\n if (error instanceof ItdApiError) {\n if (error.status === 429) return true;\n if (error.status >= 500) return safeToRepeat;\n return false;\n }\n\n if (error instanceof ItdNetworkError || error instanceof ItdTimeoutError) return safeToRepeat;\n\n return false;\n}\n\n/** Экспоненциальная пауза со случайным разбросом. */\nfunction backoffDelay(\n attempt: number,\n options: ResolvedRetryOptions,\n random: () => number,\n): number {\n const exponential = options.baseDelay * 2 ** (attempt - 1);\n const capped = Math.min(exponential, options.maxDelay);\n const spread = capped * options.jitter * (random() * 2 - 1);\n\n return Math.max(0, Math.round(capped + spread));\n}\n\n/**\n * Собирает планировщик повторов для транспорта.\n *\n * Поведение при `Retry-After`: пауза, названная сервером, соблюдается точно — она\n * авторитетнее нашего расчёта. Но если сервер просит ждать дольше, чем `maxDelay`,\n * повтор **не выполняется вовсе**: молча спать десять минут внутри вызова библиотека\n * не должна, лучше отдать {@link ItdRateLimitError} и дать решить вызывающему коду.\n *\n * @param options настройки повторов после подстановки значений по умолчанию\n * @param random источник случайности; подменяется в тестах ради предсказуемости\n *\n * @example\n * ```ts\n * const scheduler = createRetryScheduler(config.retry);\n * const delay = scheduler(error, 1, 'GET'); // 500 мс ± 30%\n * ```\n */\nexport function createRetryScheduler(\n options: ResolvedRetryOptions,\n random: () => number = Math.random,\n): RetryScheduler {\n return (error, attempt, method) => {\n if (attempt >= options.attempts) return undefined;\n\n if (options.shouldRetry) {\n return options.shouldRetry(error, attempt)\n ? backoffDelay(attempt, options, random)\n : undefined;\n }\n\n if (!isRetryable(error, method, options.retryWrites)) return undefined;\n\n if (error instanceof ItdApiError && error.retryAfter !== undefined) {\n return error.retryAfter > options.maxDelay ? undefined : error.retryAfter;\n }\n\n return backoffDelay(attempt, options, random);\n };\n}\n","import { NotificationType } from '../types/enums.js';\n\n/**\n * Соответствие коротких имён типов уведомлений развёрнутым.\n *\n * Сервер — и в списке, и в потоке событий — присылает короткие имена: `like`, `comment`,\n * `reply`, `repost`, `comment_like`. Развёрнутые (`post_reaction`, `post_comment`)\n * встречаются в оформлении интерфейса, поэтому библиотека приводит типы к ним:\n * они однозначно называют и объект, и действие.\n *\n * Пришедшее значение всегда остаётся в поле `rawType`.\n */\nexport const NOTIFICATION_TYPE_ALIASES: Readonly<Record<string, NotificationType>> = Object.freeze({\n like: NotificationType.PostReaction,\n comment: NotificationType.PostComment,\n comment_like: NotificationType.CommentReaction,\n reply: NotificationType.CommentReply,\n repost: NotificationType.PostRepost,\n mention: NotificationType.PostMention,\n});\n\nconst KNOWN_TYPES = new Set<string>(Object.values(NotificationType));\n\n/**\n * Приводит имя типа к каноническому.\n *\n * Неизвестное значение возвращается без изменений. Официальный клиент в этом случае\n * подставляет `follow`, из-за чего новое уведомление выглядит как подписка, — здесь\n * такого не происходит.\n *\n * @example\n * ```ts\n * canonicalNotificationType('like'); // 'post_reaction'\n * canonicalNotificationType('post_reaction'); // 'post_reaction'\n * canonicalNotificationType('новое_событие'); // 'новое_событие'\n * ```\n */\nexport function canonicalNotificationType(rawType: string): NotificationType {\n return NOTIFICATION_TYPE_ALIASES[rawType] ?? rawType;\n}\n\n/**\n * Известен ли библиотеке этот тип уведомления.\n *\n * Полезно, чтобы решить, показывать ли уведомление, для которого нет своего оформления.\n */\nexport function isKnownNotificationType(type: string): boolean {\n return KNOWN_TYPES.has(canonicalNotificationType(type));\n}\n","import { asString, isRecord } from '../core/unwrap.js';\nimport type { Actor, Notification } from '../types/models.js';\nimport { canonicalNotificationType } from './type-map.js';\n\n/** Событие потока уведомлений после разбора. */\nexport interface NotificationEvent {\n /** Само уведомление в единой форме. */\n notification: Notification;\n /**\n * Актуальное число непрочитанных, если сервер его сообщил.\n *\n * Клиент не увеличивает счётчик сам: значение приходит с сервера.\n */\n unreadCount: number | undefined;\n /** Нужно ли проиграть звук. */\n sound: boolean;\n}\n\nfunction asActor(value: unknown): Actor | undefined {\n if (!isRecord(value)) return undefined;\n const id = asString(value.id);\n if (!id) return undefined;\n\n return {\n id,\n username: asString(value.username) ?? '',\n displayName: asString(value.displayName) ?? '',\n avatar: asString(value.avatar) ?? '',\n ...(typeof value.isFollowing === 'boolean' ? { isFollowing: value.isFollowing } : {}),\n ...(typeof value.isFollowedBy === 'boolean' ? { isFollowedBy: value.isFollowedBy } : {}),\n };\n}\n\n/** Собирает участников: сервер присылает либо одного `actor`, либо массив `actors`. */\nfunction readActors(source: Record<string, unknown>): Actor[] {\n if (Array.isArray(source.actors)) {\n return source.actors.map(asActor).filter((actor): actor is Actor => actor !== undefined);\n }\n\n const single = asActor(source.actor);\n return single ? [single] : [];\n}\n\n/**\n * Приводит уведомление к единой форме.\n *\n * Нужна потому, что REST-список и поток событий описывают одно и то же событие по-разному:\n * различаются имена типов (`like` против `post_reaction`), имена полей\n * (`targetId`/`entityId`, `read`/`isRead`, `preview`/`entityPreview`) и число участников\n * (`actor` против массива `actors`). После приведения объекты из обоих источников\n * можно складывать в один список.\n *\n * Исходные данные не теряются: имя типа с сервера остаётся в `rawType`,\n * весь объект целиком — в `raw`.\n *\n * @param input уведомление из REST-ответа либо полезная нагрузка события потока\n *\n * @example\n * ```ts\n * const fromRest = normalizeNotification(restItem);\n * const fromStream = normalizeNotification(event.payload);\n * // одинаковая форма — можно объединять\n * ```\n */\nexport function normalizeNotification(input: unknown): Notification {\n const source = isRecord(input) ? input : {};\n\n // Поток кладёт полезную нагрузку то в payload, то прямо в корень события.\n const payload = isRecord(source.payload) ? source.payload : source;\n\n const rawType = asString(payload.type) ?? asString(source.type) ?? '';\n const createdAt = asString(payload.createdAt) ?? asString(source.createdAt) ?? '';\n const readAt = asString(payload.readAt) ?? asString(source.readAt);\n\n const isRead =\n typeof payload.isRead === 'boolean'\n ? payload.isRead\n : typeof payload.read === 'boolean'\n ? payload.read\n : Boolean(readAt);\n\n // Сервер описывает событие парой «цель — предмет», и смысл пары зависит от типа:\n //\n // комментарий, реакция на него — цель = пост, предмет = комментарий\n // репост — цель = сам репост, предмет = исходный пост\n // реакция на пост, подписка — предмета нет\n //\n // Событие относится к предмету, только когда тот является комментарием; иначе объект\n // события — цель. Без этого различия ссылка на репост вела бы на чужой исходный пост.\n const subjectId = asString(payload.subjectId);\n const targetId = asString(payload.targetId);\n const subjectIsComment = payload.subjectType === 'comment';\n const clickUrl = asString(payload.clickUrl);\n\n return {\n id: asString(payload.id) ?? asString(source.id) ?? '',\n type: canonicalNotificationType(rawType),\n rawType,\n entityId:\n asString(payload.entityId) ?? (subjectIsComment ? (subjectId ?? targetId) : targetId) ?? null,\n parentEntityId:\n asString(payload.parentEntityId) ?? (subjectIsComment ? (targetId ?? null) : null),\n isRead,\n actors: readActors(payload),\n count: typeof payload.count === 'number' && payload.count > 0 ? payload.count : 1,\n preview: asString(payload.entityPreview) ?? asString(payload.preview) ?? null,\n ...(clickUrl ? { clickUrl } : {}),\n createdAt,\n updatedAt: asString(payload.updatedAt) ?? readAt ?? createdAt,\n raw: input,\n };\n}\n\n/**\n * Разбирает событие `notification` из потока.\n *\n * Кроме самого уведомления событие несёт служебные поля уровня конверта: актуальный\n * счётчик непрочитанных и признак звука.\n */\nexport function readNotificationEvent(data: unknown): NotificationEvent {\n const source = isRecord(data) ? data : {};\n\n return {\n notification: normalizeNotification(data),\n unreadCount: typeof source.unreadCount === 'number' ? source.unreadCount : undefined,\n sound: source.sound === true,\n };\n}\n\n/**\n * Разбирает событие `unread_count` из потока.\n *\n * Возвращает `undefined`, если сервер прислал событие без вложенного `payload`.\n * Официальный клиент в этом случае **обнуляет** счётчик — это ошибка, из-за которой\n * непрочитанные пропадают из интерфейса.\n */\nexport function readUnreadCountEvent(data: unknown): number | undefined {\n if (!isRecord(data)) return undefined;\n\n const payload = isRecord(data.payload) ? data.payload : undefined;\n if (!payload) return undefined;\n\n return typeof payload.count === 'number' ? payload.count : undefined;\n}\n","/** Событие, пришедшее по каналу реального времени. */\nexport interface TransportEvent {\n /** Имя события: `notification`, `unread_count` и другие. */\n name: string;\n /** Полезная нагрузка, уже разобранная из JSON. */\n data: unknown;\n}\n\n/** Что транспорт получает от клиента при подключении. */\nexport interface TransportContext {\n /** Базовый URL API. */\n baseUrl: string;\n /** Реализация `fetch`. */\n fetch: typeof fetch;\n /** Текущий токен доступа. */\n getToken: () => Promise<string | null>;\n /** Отмена подключения. */\n signal: AbortSignal;\n /** Сообщает о полученном событии. */\n onEvent: (event: TransportEvent) => void;\n /** Сообщает о разобранном, но некорректном сообщении. Соединение при этом живёт. */\n onParseError: (error: unknown, raw: string) => void;\n /** Вызывается, когда соединение установлено. */\n onOpen: () => void;\n}\n\n/**\n * Канал получения событий в реальном времени.\n *\n * Сейчас у платформы один такой канал — поток `text/event-stream`. Абстракция нужна\n * на будущее: политика безопасности сайта уже разрешает `wss://*.xn--d1ah4a.com`,\n * и когда появится WebSocket, достаточно будет добавить ещё одну реализацию этого\n * интерфейса. Переподключение, обновление токена и разбор уведомлений от транспорта\n * не зависят.\n */\nexport interface RealtimeTransport {\n /** Понятное имя для логов и диагностики. */\n readonly name: string;\n\n /**\n * Держит соединение, пока оно живо.\n *\n * Должен завершиться, когда поток закрылся, и бросить исключение при ошибке.\n * Отмена через `context.signal` должна приводить к `AbortError`.\n */\n connect(context: TransportContext): Promise<void>;\n}\n\n/** Ошибка, по которой видно, что сервер отверг авторизацию потока. */\nexport class UnauthorizedStreamError extends Error {\n constructor() {\n super('Поток уведомлений отверг токен доступа');\n this.name = 'UnauthorizedStreamError';\n }\n}\n","import { pickArray, pickNumber } from '../core/unwrap.js';\nimport { joinUrl } from '../core/url.js';\nimport type { RealtimeTransport, TransportContext } from './transport.js';\nimport { UnauthorizedStreamError } from './transport.js';\n\n/** Настройки опроса. */\nexport interface PollTransportOptions {\n /** Как часто опрашивать сервер, мс. По умолчанию 15 000. */\n interval?: number;\n /** Сколько уведомлений запрашивать за раз. По умолчанию 20. */\n limit?: number;\n}\n\n/**\n * Запасной транспорт: обычный опрос REST вместо потока.\n *\n * Нужен там, где `fetch` не умеет отдавать тело по частям, — например в части сборок\n * React Native. Наружу выдаёт те же события, что и {@link SseTransport}, поэтому\n * вызывающий код разницы не замечает.\n *\n * Новыми считаются уведомления, которых не было в предыдущем ответе; чтобы список\n * известных не рос бесконечно, он ограничен последними двумя страницами.\n */\nexport class PollTransport implements RealtimeTransport {\n readonly name = 'poll';\n\n readonly #interval: number;\n readonly #limit: number;\n\n constructor(options: PollTransportOptions = {}) {\n this.#interval = options.interval ?? 15_000;\n this.#limit = options.limit ?? 20;\n }\n\n async connect(context: TransportContext): Promise<void> {\n const seen = new Set<string>();\n let firstRun = true;\n let lastUnreadCount: number | undefined;\n\n context.onOpen();\n\n while (!context.signal.aborted) {\n const token = await context.getToken();\n if (!token) throw new UnauthorizedStreamError();\n\n const headers = new Headers({\n Accept: 'application/json',\n Authorization: `Bearer ${token}`,\n });\n\n const response = await context.fetch(\n `${joinUrl(context.baseUrl, '/api/notifications/')}?limit=${this.#limit}&offset=0`,\n { method: 'GET', headers, signal: context.signal },\n );\n\n if (response.status === 401) throw new UnauthorizedStreamError();\n if (!response.ok) throw new Error(`Опрос уведомлений вернул статус ${response.status}`);\n\n const body: unknown = await response.json();\n const payload =\n typeof body === 'object' && body !== null && 'data' in body\n ? (body as { data: unknown }).data\n : body;\n\n const items = pickArray<Record<string, unknown>>(payload, 'notifications');\n\n for (const item of [...items].reverse()) {\n const id = typeof item.id === 'string' ? item.id : undefined;\n if (!id || seen.has(id)) continue;\n\n seen.add(id);\n // На первом проходе список уже существующих уведомлений не считается новыми\n // событиями: иначе подключение сразу выдало бы всю историю.\n if (!firstRun) context.onEvent({ name: 'notification', data: { payload: item } });\n }\n\n // Ограничиваем память: держим только последние две страницы идентификаторов.\n if (seen.size > this.#limit * 2) {\n const excess = [...seen].slice(0, seen.size - this.#limit * 2);\n for (const id of excess) seen.delete(id);\n }\n\n const count = await this.#readCount(context, headers);\n if (count !== undefined && count !== lastUnreadCount) {\n lastUnreadCount = count;\n context.onEvent({ name: 'unread_count', data: { payload: { count } } });\n }\n\n firstRun = false;\n await this.#wait(context.signal);\n }\n }\n\n async #readCount(context: TransportContext, headers: Headers): Promise<number | undefined> {\n try {\n const response = await context.fetch(joinUrl(context.baseUrl, '/api/notifications/count'), {\n method: 'GET',\n headers,\n signal: context.signal,\n });\n\n if (!response.ok) return undefined;\n\n const body: unknown = await response.json();\n const payload =\n typeof body === 'object' && body !== null && 'data' in body\n ? (body as { data: unknown }).data\n : body;\n\n return pickNumber(payload, 'count', 0);\n } catch {\n // Счётчик — вспомогательная величина: его недоступность не должна рвать опрос.\n return undefined;\n }\n }\n\n /** Ждёт следующего опроса, прерываясь при отмене. */\n #wait(signal: AbortSignal): Promise<void> {\n // Подписка на уже сработавший сигнал не вызывается никогда — без этой проверки\n // отмена, пришедшая перед самым ожиданием, стоила бы лишнего интервала.\n if (signal.aborted) return Promise.resolve();\n\n return new Promise<void>((resolve) => {\n const timer = setTimeout(finish, this.#interval);\n\n function finish() {\n clearTimeout(timer);\n signal.removeEventListener('abort', finish);\n resolve();\n }\n\n signal.addEventListener('abort', finish, { once: true });\n });\n }\n}\n","/**\n * Паузы перед попытками переподключения, мс.\n *\n * Значения совпадают с теми, что использует сайт итд.com, — поведение библиотеки\n * не отличается от привычного пользователю.\n */\nexport const RECONNECT_BACKOFF = Object.freeze([1000, 2000, 4000, 8000, 16000, 30000]);\n\n/** Доля случайного разброса паузы. */\nexport const RECONNECT_JITTER = 0.3;\n\n/**\n * Сколько раз пытаться переподключиться подряд.\n *\n * После исчерпания поток сообщает `giveup` и ждёт ручного `connect()`.\n */\nexport const MAX_RECONNECT_ATTEMPTS = 15;\n\n/** Настройки переподключения. */\nexport interface ReconnectOptions {\n /** Таблица пауз. Последнее значение действует для всех дальнейших попыток. */\n backoff?: readonly number[];\n /** Доля разброса, 0…1. */\n jitter?: number;\n /** Предел числа попыток. */\n maxAttempts?: number;\n}\n\n/**\n * Вычисляет паузу перед попыткой переподключения.\n *\n * Разброс нужен, чтобы клиенты, отключившиеся одновременно из-за перезапуска сервера,\n * не вернулись тоже одновременно.\n *\n * @param attempt номер попытки, начиная с нуля\n * @param random источник случайности; подменяется в тестах\n */\nexport function reconnectDelay(\n attempt: number,\n options: ReconnectOptions = {},\n random: () => number = Math.random,\n): number {\n const backoff = options.backoff ?? RECONNECT_BACKOFF;\n const jitter = options.jitter ?? RECONNECT_JITTER;\n\n const base = backoff[Math.min(attempt, backoff.length - 1)] ?? 30_000;\n const spread = base * jitter * (random() * 2 - 1);\n\n return Math.max(0, Math.round(base + spread));\n}\n","/**\n * The type of error that occurred.\n * @public\n */\nexport type ErrorType = 'invalid-retry' | 'unknown-field' | 'max-buffer-size-exceeded'\n\n/**\n * Error thrown when encountering an issue during parsing.\n *\n * @public\n */\nexport class ParseError extends Error {\n /**\n * The type of error that occurred.\n */\n type: ErrorType\n\n /**\n * In the case of an unknown field encountered in the stream, this will be the field name.\n */\n field?: string | undefined\n\n /**\n * In the case of an unknown field encountered in the stream, this will be the value of the field.\n */\n value?: string | undefined\n\n /**\n * The line that caused the error, if available.\n */\n line?: string | undefined\n\n constructor(\n message: string,\n options: {type: ErrorType; field?: string; value?: string; line?: string},\n ) {\n super(message)\n this.name = 'ParseError'\n this.type = options.type\n this.field = options.field\n this.value = options.value\n this.line = options.line\n }\n}\n","/**\n * EventSource/Server-Sent Events parser\n * @see https://html.spec.whatwg.org/multipage/server-sent-events.html\n */\nimport {ParseError} from './errors.ts'\nimport type {EventSourceParser, ParserConfig} from './types.ts'\n\n// ASCII codes used in the hot parsing paths.\nconst LF = 10\nconst CR = 13\nconst SPACE = 32\n\n// oxlint-disable-next-line no-unused-vars\nfunction noop(_arg: unknown) {\n // intentional noop\n}\n\n/**\n * Creates a new EventSource parser.\n *\n * @param config - Parser configuration. Accepts callbacks (see {@link ParserCallbacks})\n * and options like `maxBufferSize` (see {@link ParserConfig}).\n *\n * @returns A new EventSource parser, with `feed` and `reset` methods.\n * @public\n */\nexport function createParser(config: ParserConfig): EventSourceParser {\n if (typeof config === 'function') {\n throw new TypeError(\n '`config` must be an object, got a function instead. Did you mean `createParser({onEvent: fn})`?',\n )\n }\n\n const {onEvent = noop, onError = noop, onRetry = noop, onComment, maxBufferSize} = config\n\n // Trailing bytes from prior `feed()` calls that did not yet form a complete line.\n // Stored as an array of fragments and only joined when a line terminator arrives.\n // Concatenating per-feed (`prefix + chunk`) is O(N²) when a single SSE line spans\n // many chunks (e.g. a large `data:` payload streamed in tiny slices, or an MCP-style\n // server that emits one giant content block). Buffering as fragments + joining once\n // makes the same workload linear.\n const pendingFragments: string[] = []\n\n // Running total of `pendingFragments` lengths, kept in sync with the array so the\n // `maxBufferSize` check doesn't have to walk the fragment list on every feed.\n let pendingFragmentsLength = 0\n\n let isFirstChunk = true\n let id: string | undefined\n let data = ''\n let dataLines = 0\n let eventType: string | undefined\n\n // Set after a `maxBufferSize` overflow. Once tripped, `feed()` throws until\n // `reset()` is called — see the comment on `maxBufferSize` in `ParserConfig`.\n let terminated = false\n\n /**\n * Feeds a chunk of the SSE stream to the parser. Any trailing bytes that do\n * not yet form a complete line are held back and prepended to the next chunk,\n * so callers can pass arbitrary slices of the stream without worrying about\n * line boundaries.\n *\n * Per the SSE spec, a UTF-8 BOM (0xEF 0xBB 0xBF) at the start of the very\n * first chunk is stripped before parsing.\n *\n * @see https://html.spec.whatwg.org/multipage/server-sent-events.html#parsing-an-event-stream\n */\n function feed(chunk: string) {\n if (terminated) {\n throw new Error(\n 'Cannot feed parser: it was terminated after exceeding the configured max buffer size. Call `reset()` to resume parsing.',\n )\n }\n\n if (isFirstChunk) {\n isFirstChunk = false\n // Match and strip UTF-8 BOM from the start of the stream, if present.\n // (Per the spec, this is only valid at the very start of the stream)\n if (\n chunk.charCodeAt(0) === 0xef &&\n chunk.charCodeAt(1) === 0xbb &&\n chunk.charCodeAt(2) === 0xbf\n ) {\n chunk = chunk.slice(3)\n }\n }\n\n // Hot path: no buffered prefix from a prior partial line. Hand the chunk\n // straight to `processLines`, exactly like the original implementation.\n // Zero new work in the common case (every chunk ends with `\\n\\n`).\n if (pendingFragments.length === 0) {\n const trailing = processLines(chunk)\n if (trailing !== '') {\n pendingFragments.push(trailing)\n pendingFragmentsLength = trailing.length\n }\n checkBufferSize()\n return\n }\n\n // We have a buffered prefix. If this chunk also has no terminator, append\n // to the buffer without concatenating — that's the O(N²) trap we're\n // avoiding (large single `data:` payload split across many tiny chunks).\n if (chunk.indexOf('\\n') === -1 && chunk.indexOf('\\r') === -1) {\n pendingFragments.push(chunk)\n pendingFragmentsLength += chunk.length\n checkBufferSize()\n return\n }\n\n // Terminator arrived. Join the accumulated fragments + this chunk once,\n // process, and buffer any new trailing partial line.\n pendingFragments.push(chunk)\n const input = pendingFragments.join('')\n pendingFragments.length = 0\n pendingFragmentsLength = 0\n const trailing = processLines(input)\n if (trailing !== '') {\n pendingFragments.push(trailing)\n pendingFragmentsLength = trailing.length\n }\n checkBufferSize()\n }\n\n function checkBufferSize() {\n if (maxBufferSize === undefined) return\n if (pendingFragmentsLength + data.length <= maxBufferSize) return\n\n terminated = true\n pendingFragments.length = 0\n pendingFragmentsLength = 0\n id = undefined\n data = ''\n dataLines = 0\n eventType = undefined\n onError(\n new ParseError(`Buffered data exceeded max buffer size of ${maxBufferSize} characters`, {\n type: 'max-buffer-size-exceeded',\n }),\n )\n }\n\n /**\n * Splits `chunk` into SSE lines and dispatches each to the appropriate handler.\n * Returns any trailing bytes that did not terminate with a line break, so the\n * caller can prepend them to the next chunk.\n *\n * The SSE spec permits three line terminators: `\\n`, `\\r`, and `\\r\\n`. Real-world\n * streams almost always use plain `\\n`, so we take a fast path when no `\\r` is\n * present in the chunk. The slow path is spec-correct but does more work per line.\n */\n function processLines(chunk: string): string {\n let searchIndex = 0\n\n // Fast path: LF-only chunk (the common case for typical SSE servers).\n // We can scan forward with a single `indexOf('\\n')` per line and inline\n // the hot-path branches for `data:` and `event:` without the CR bookkeeping\n // the slow path needs.\n if (chunk.indexOf('\\r') === -1) {\n let lfIndex = chunk.indexOf('\\n', searchIndex)\n while (lfIndex !== -1) {\n // Blank line: end-of-event marker. Dispatch the accumulated event (if any)\n // and reset the buffered fields. This is hoisted out of `parseLine` because\n // it's the single most common line shape after `data:` lines.\n if (searchIndex === lfIndex) {\n if (dataLines > 0) {\n onEvent({id, event: eventType, data})\n }\n id = undefined\n data = ''\n dataLines = 0\n eventType = undefined\n searchIndex = lfIndex + 1\n lfIndex = chunk.indexOf('\\n', searchIndex)\n continue\n }\n const firstCharCode = chunk.charCodeAt(searchIndex)\n if (isDataPrefix(chunk, searchIndex, firstCharCode)) {\n // `data:` line — append the value to the event's data buffer.\n // 'data:'.length === 5, 'data: '.length === 6\n const valueStart =\n chunk.charCodeAt(searchIndex + 5) === SPACE ? searchIndex + 6 : searchIndex + 5\n const value = chunk.slice(valueStart, lfIndex)\n // Fast path within a fast path: if this is the first data line AND the\n // next char is another LF (i.e. `data:foo\\n\\n`), dispatch immediately\n // without ever writing to the `data` buffer. This is the shape of a\n // typical single-line SSE event (ChatGPT-style streams, etc.) and is\n // hot enough to be worth the duplication.\n if (dataLines === 0 && chunk.charCodeAt(lfIndex + 1) === LF) {\n onEvent({id, event: eventType, data: value})\n id = undefined\n data = ''\n eventType = undefined\n searchIndex = lfIndex + 2\n lfIndex = chunk.indexOf('\\n', searchIndex)\n continue\n }\n // Multi-line data: concatenate with newline separator per spec.\n data = dataLines === 0 ? value : `${data}\\n${value}`\n dataLines++\n } else if (isEventPrefix(chunk, searchIndex, firstCharCode)) {\n // `event:` line — set the event type for the next dispatch. Per spec,\n // an empty value resets `event type` to its default (undefined here).\n // 'event:'.length === 6, 'event: '.length === 7\n eventType =\n chunk.slice(\n chunk.charCodeAt(searchIndex + 6) === SPACE ? searchIndex + 7 : searchIndex + 6,\n lfIndex,\n ) || undefined\n } else {\n // Everything else: `id:`, `retry:`, comment lines (`:` prefix), unknown\n // fields, or malformed lines. These are rarer and go through the full\n // per-line parser, which handles the SSE field grammar in detail.\n parseLine(chunk, searchIndex, lfIndex)\n }\n searchIndex = lfIndex + 1\n lfIndex = chunk.indexOf('\\n', searchIndex)\n }\n return chunk.slice(searchIndex)\n }\n\n // Slow path: the chunk contains at least one `\\r`, so lines may be terminated\n // by `\\r`, `\\n`, or `\\r\\n`. We locate the next terminator by looking at both\n // the nearest `\\r` and `\\n` and picking whichever comes first.\n while (searchIndex < chunk.length) {\n const crIndex = chunk.indexOf('\\r', searchIndex)\n const lfIndex = chunk.indexOf('\\n', searchIndex)\n\n let lineEnd = -1\n if (crIndex !== -1 && lfIndex !== -1) {\n lineEnd = crIndex < lfIndex ? crIndex : lfIndex\n } else if (crIndex !== -1) {\n // A trailing `\\r` at the very end of the chunk is ambiguous: it could be\n // a bare-CR terminator, or the first half of a `\\r\\n` whose `\\n` arrives\n // in the next chunk. Defer until we see more input.\n if (crIndex === chunk.length - 1) {\n lineEnd = -1\n } else {\n lineEnd = crIndex\n }\n } else if (lfIndex !== -1) {\n lineEnd = lfIndex\n }\n\n if (lineEnd === -1) {\n break\n }\n\n parseLine(chunk, searchIndex, lineEnd)\n searchIndex = lineEnd + 1\n // If we just consumed a `\\r` and the next char is `\\n`, skip it so the\n // pair is treated as a single terminator rather than an empty line.\n if (chunk.charCodeAt(searchIndex - 1) === CR && chunk.charCodeAt(searchIndex) === LF) {\n searchIndex++\n }\n }\n\n return chunk.slice(searchIndex)\n }\n\n function parseLine(chunk: string, start: number, end: number) {\n if (start === end) {\n dispatchEvent()\n return\n }\n\n const firstCharCode = chunk.charCodeAt(start)\n\n if (isDataPrefix(chunk, start, firstCharCode)) {\n // 'data:'.length === 5, 'data: '.length === 6\n const valueStart = chunk.charCodeAt(start + 5) === SPACE ? start + 6 : start + 5\n const value = chunk.slice(valueStart, end)\n data = dataLines === 0 ? value : `${data}\\n${value}`\n dataLines++\n return\n }\n\n if (isEventPrefix(chunk, start, firstCharCode)) {\n // 'event:'.length === 6, 'event: '.length === 7\n eventType =\n chunk.slice(chunk.charCodeAt(start + 6) === SPACE ? start + 7 : start + 6, end) || undefined\n return\n }\n\n // Fast path for \"id:\" — 'i' = 105, 'd' = 100, ':' = 58\n if (\n firstCharCode === 105 &&\n chunk.charCodeAt(start + 1) === 100 &&\n chunk.charCodeAt(start + 2) === 58\n ) {\n // 'id:'.length === 3, 'id: '.length === 4\n const value = chunk.slice(chunk.charCodeAt(start + 3) === SPACE ? start + 4 : start + 3, end)\n id = value.includes('\\0') ? undefined : value\n return\n }\n\n // Comment line — ':' = 58\n if (firstCharCode === 58) {\n if (onComment) {\n const line = chunk.slice(start, end)\n // skip ':' (+1), or ': ' (+2) when a space follows\n onComment(line.slice(chunk.charCodeAt(start + 1) === SPACE ? 2 : 1))\n }\n return\n }\n\n const line = chunk.slice(start, end)\n const fieldSeparatorIndex = line.indexOf(':')\n if (fieldSeparatorIndex === -1) {\n processField(line, '', line)\n return\n }\n\n const field = line.slice(0, fieldSeparatorIndex)\n // skip ':' (+1), or ': ' (+2) when a space follows\n const offset = line.charCodeAt(fieldSeparatorIndex + 1) === SPACE ? 2 : 1\n const value = line.slice(fieldSeparatorIndex + offset)\n processField(field, value, line)\n }\n\n function processField(field: string, value: string, line: string) {\n // Field names must be compared literally, with no case folding performed.\n switch (field) {\n case 'event':\n // Set the `event type` buffer to field value\n eventType = value || undefined\n break\n case 'data':\n data = dataLines === 0 ? value : `${data}\\n${value}`\n dataLines++\n break\n case 'id':\n // If the field value does not contain U+0000 NULL, then set the `ID` buffer to\n // the field value. Otherwise, ignore the field.\n id = value.includes('\\0') ? undefined : value\n break\n case 'retry':\n // If the field value consists of only ASCII digits, then interpret the field value as an\n // integer in base ten, and set the event stream's reconnection time to that integer.\n // Otherwise, ignore the field.\n if (/^\\d+$/.test(value)) {\n onRetry(parseInt(value, 10))\n } else {\n onError(\n new ParseError(`Invalid \\`retry\\` value: \"${value}\"`, {\n type: 'invalid-retry',\n value,\n line,\n }),\n )\n }\n break\n default:\n // Otherwise, the field is ignored.\n onError(\n new ParseError(\n `Unknown field \"${field.length > 20 ? `${field.slice(0, 20)}…` : field}\"`,\n {type: 'unknown-field', field, value, line},\n ),\n )\n break\n }\n }\n\n function dispatchEvent() {\n if (dataLines > 0) {\n onEvent({\n id,\n event: eventType,\n data,\n })\n }\n\n id = undefined\n data = ''\n dataLines = 0\n eventType = undefined\n }\n\n function reset(options: {consume?: boolean} = {}) {\n if (options.consume && pendingFragments.length > 0) {\n const incompleteLine = pendingFragments.join('')\n parseLine(incompleteLine, 0, incompleteLine.length)\n }\n\n isFirstChunk = true\n id = undefined\n data = ''\n dataLines = 0\n eventType = undefined\n pendingFragments.length = 0\n pendingFragmentsLength = 0\n terminated = false\n }\n\n return {feed, reset}\n}\n\n/**\n * Checks if `chunk` starts with the literal `data:` at index `i`.\n *\n * Equivalent to `chunk.startsWith('data:', i)`, but benchmarks show this\n * hand-unrolled char-code comparison is ~20% faster on common event types.\n * The caller passes `firstCharCode` (the code at `i`) so it can be reused\n * across prefix checks.\n *\n * ASCII: 'd' = 100, 'a' = 97, 't' = 116, 'a' = 97, ':' = 58\n */\nfunction isDataPrefix(chunk: string, i: number, firstCharCode: number): boolean {\n return (\n firstCharCode === 100 &&\n chunk.charCodeAt(i + 1) === 97 &&\n chunk.charCodeAt(i + 2) === 116 &&\n chunk.charCodeAt(i + 3) === 97 &&\n chunk.charCodeAt(i + 4) === 58\n )\n}\n\n/**\n * Checks if `chunk` starts with the literal `event:` at index `i`.\n *\n * See {@link isDataPrefix} for why this is hand-unrolled rather than using\n * `String.prototype.startsWith`.\n *\n * ASCII: 'e' = 101, 'v' = 118, 'e' = 101, 'n' = 110, 't' = 116, ':' = 58\n */\nfunction isEventPrefix(chunk: string, i: number, firstCharCode: number): boolean {\n return (\n firstCharCode === 101 &&\n chunk.charCodeAt(i + 1) === 118 &&\n chunk.charCodeAt(i + 2) === 101 &&\n chunk.charCodeAt(i + 3) === 110 &&\n chunk.charCodeAt(i + 4) === 116 &&\n chunk.charCodeAt(i + 5) === 58\n )\n}\n","import { createParser } from 'eventsource-parser';\nimport { joinUrl } from '../core/url.js';\nimport {\n type RealtimeTransport,\n type TransportContext,\n UnauthorizedStreamError,\n} from './transport.js';\n\n/** Путь потока уведомлений. */\nexport const STREAM_PATH = '/api/notifications/stream';\n\n/** Настройки SSE-транспорта. */\nexport interface SseTransportOptions {\n /**\n * Сколько миллисекунд ждать данных, прежде чем считать соединение мёртвым.\n *\n * Сервер не присылает keep-alive, а оборванное TCP-соединение может не закрыться\n * само — без этой проверки поток «тихо умирает» и новых уведомлений не приходит.\n * По умолчанию 90 000. `0` отключает проверку.\n */\n idleTimeout?: number;\n}\n\n/**\n * Транспорт поверх Server-Sent Events.\n *\n * Нативный `EventSource` не подходит: он не умеет отправлять заголовок `Authorization`,\n * а поток требует Bearer-токен. Поэтому используется `fetch` с чтением тела по частям.\n *\n * Разбор кадров делегирован `eventsource-parser`, который корректно обрабатывает\n * многострочный `data:`, перевод строки `\\r\\n`, `data:` без пробела и кадр, разорванный\n * между сетевыми чанками. В разборе на сайте итд.com каждый из этих случаев обрабатывается\n * неверно.\n */\nexport class SseTransport implements RealtimeTransport {\n readonly name = 'sse';\n\n readonly #idleTimeout: number;\n /** Идентификатор последнего события — отправляется при переподключении. */\n #lastEventId: string | undefined;\n\n constructor(options: SseTransportOptions = {}) {\n this.#idleTimeout = options.idleTimeout ?? 90_000;\n }\n\n async connect(context: TransportContext): Promise<void> {\n const token = await context.getToken();\n if (!token) throw new UnauthorizedStreamError();\n\n const headers = new Headers({\n Accept: 'text/event-stream',\n Authorization: `Bearer ${token}`,\n 'Cache-Control': 'no-cache',\n });\n\n // Сервер пока не присылает id, но поддержка не мешает и пригодится, если начнёт.\n if (this.#lastEventId) headers.set('Last-Event-ID', this.#lastEventId);\n\n const response = await context.fetch(joinUrl(context.baseUrl, STREAM_PATH), {\n method: 'GET',\n headers,\n signal: context.signal,\n });\n\n if (response.status === 401) throw new UnauthorizedStreamError();\n if (!response.ok) throw new Error(`Поток уведомлений вернул статус ${response.status}`);\n if (!response.body) throw new Error('Ответ потока уведомлений пуст');\n\n context.onOpen();\n\n await this.#read(response.body, context);\n }\n\n async #read(body: ReadableStream<Uint8Array>, context: TransportContext): Promise<void> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n\n const parser = createParser({\n onEvent: (message) => {\n if (message.id) this.#lastEventId = message.id;\n\n let data: unknown;\n try {\n data = JSON.parse(message.data);\n } catch (error) {\n // Одно битое сообщение не повод рвать соединение.\n context.onParseError(error, message.data);\n return;\n }\n\n // Имя события может отсутствовать — тогда тип лежит внутри полезной нагрузки.\n const name =\n message.event ??\n (typeof data === 'object' && data !== null && 'type' in data\n ? String((data as { type: unknown }).type)\n : 'message');\n\n context.onEvent({ name, data });\n },\n });\n\n let idleTimer: ReturnType<typeof setTimeout> | undefined;\n\n const armIdleTimer = () => {\n if (this.#idleTimeout <= 0) return;\n if (idleTimer !== undefined) clearTimeout(idleTimer);\n\n idleTimer = setTimeout(() => {\n // Отмена чтения завершит цикл, и внешний код переподключится.\n void reader.cancel(new Error('Поток молчит дольше допустимого')).catch(() => {});\n }, this.#idleTimeout);\n };\n\n armIdleTimer();\n\n try {\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n\n armIdleTimer();\n parser.feed(decoder.decode(value, { stream: true }));\n }\n } finally {\n if (idleTimer !== undefined) clearTimeout(idleTimer);\n reader.releaseLock?.();\n }\n }\n}\n","import { Emitter, type Listener, type Unsubscribe } from '../core/emitter.js';\nimport { supportsStreamingBody } from '../core/runtime.js';\nimport { pickString } from '../core/unwrap.js';\nimport {\n type NotificationEvent,\n readNotificationEvent,\n readUnreadCountEvent,\n} from '../notifications/normalize.js';\nimport { RealtimeStatus } from '../types/enums.js';\nimport type { Logger } from '../types/options.js';\nimport { PollTransport } from './poll.js';\nimport { MAX_RECONNECT_ATTEMPTS, type ReconnectOptions, reconnectDelay } from './reconnect.js';\nimport { SseTransport } from './sse.js';\nimport { type RealtimeTransport, UnauthorizedStreamError } from './transport.js';\n\n/** События потока уведомлений. */\nexport interface RealtimeEvents {\n /** Пришло новое уведомление. */\n notification: NotificationEvent;\n /**\n * Сервер подтвердил подключение и назвал получателя событий.\n *\n * Приходит первым кадром сразу после установки соединения.\n */\n ready: { userId: string | undefined };\n /**\n * Сервер сообщил актуальное число непрочитанных.\n *\n * На практике сервер этого не делает: за всё наблюдение он не прислал ни одного\n * такого кадра, а в уведомлениях нет поля со счётчиком. Держите счётчик сами\n * либо запрашивайте `itd.notifications.count()`.\n */\n unreadCount: number;\n /** Изменилось состояние соединения. */\n status: RealtimeStatus;\n /** Соединение оборвалось; будет предпринята попытка переподключения. */\n error: { error: unknown; willReconnect: boolean };\n /** Сообщение не удалось разобрать. Соединение при этом продолжает работать. */\n parseError: { error: unknown; raw: string };\n /** Запланировано переподключение. */\n reconnect: { attempt: number; delay: number };\n /** Попытки исчерпаны — соединение восстановится только ручным `connect()`. */\n giveup: undefined;\n /** Любое событие потока в необработанном виде, включая неизвестные библиотеке. */\n message: { name: string; data: unknown };\n}\n\n/** Способ получения событий. */\nexport const RealtimeTransportKind = Object.freeze({\n /** Поток событий, если среда умеет читать тело по частям, иначе опрос. */\n Auto: 'auto',\n /** Поток `text/event-stream`. */\n Sse: 'sse',\n /** Периодический опрос REST. */\n Poll: 'poll',\n} as const);\nexport type RealtimeTransportKind =\n (typeof RealtimeTransportKind)[keyof typeof RealtimeTransportKind];\n\n/** Настройки потока уведомлений. */\nexport interface RealtimeOptions extends ReconnectOptions {\n /**\n * Транспорт. По умолчанию `auto`: поток событий, если среда умеет читать тело ответа\n * по частям, иначе опрос.\n *\n * Можно передать и свою реализацию {@link RealtimeTransport} — это пригодится, если\n * у платформы появится WebSocket либо нужен нестандартный способ доставки.\n */\n transport?: RealtimeTransportKind | RealtimeTransport;\n /**\n * Молчание сервера, после которого соединение считается мёртвым, мс. По умолчанию 90 000.\n *\n * Сервер не присылает keep-alive, поэтому без этой проверки оборванное соединение\n * может незаметно «зависнуть».\n */\n idleTimeout?: number;\n /** Как часто опрашивать сервер, если используется запасной транспорт. */\n pollInterval?: number;\n /**\n * Запрашивать число непрочитанных при подключении. По умолчанию `true`.\n *\n * Так поступает сайт итд.com: поток присылает только новые события, а начальное\n * значение счётчика нужно получить отдельно.\n */\n syncCount?: boolean;\n /**\n * Переподключаться, когда вкладка снова становится видимой. По умолчанию `true`.\n *\n * Только в браузере. У сайта итд.com такой обработки нет, из-за чего вкладка,\n * пролежавшая в фоне, может остаться без соединения.\n */\n reconnectOnVisible?: boolean;\n /** Переподключаться при восстановлении сети. По умолчанию `true`. Только в браузере. */\n reconnectOnOnline?: boolean;\n}\n\n/** Что поток получает от клиента. */\nexport interface RealtimeDeps {\n baseUrl: string;\n fetch: typeof fetch;\n getToken: () => Promise<string | null>;\n /** Обновляет токен после отказа авторизации. Возвращает `true`, если удалось. */\n refresh: () => Promise<boolean>;\n /** Загружает начальное число непрочитанных. */\n fetchUnreadCount: () => Promise<number>;\n logger?: Logger | undefined;\n}\n\n/**\n * Поток уведомлений в реальном времени.\n *\n * Получается вызовом `itd.realtime()`. Соединение поднимается методом {@link connect}\n * и держится само: обрывы, обновление токена и повторные попытки библиотека берёт на себя.\n *\n * @example\n * ```ts\n * const stream = itd.realtime();\n *\n * stream.on('notification', ({ notification, unreadCount }) => {\n * console.log(formatNotificationText(notification), unreadCount);\n * });\n * stream.on('status', (status) => console.log('соединение:', status));\n *\n * await stream.connect();\n * // …позже\n * stream.disconnect();\n * ```\n */\nexport class ItdRealtime {\n readonly #deps: RealtimeDeps;\n readonly #options: RealtimeOptions;\n readonly #emitter = new Emitter<RealtimeEvents>();\n readonly #transport: RealtimeTransport;\n readonly #maxAttempts: number;\n\n #controller: AbortController | undefined;\n /**\n * Хочет ли вызывающий код, чтобы соединение было живо.\n *\n * Отдельно от `#controller`, потому что тот появляется только после `await` внутри\n * {@link connect}. Без этого флага два вызова подряд проскочили бы проверку оба\n * и подняли два соединения, а `disconnect()` во время ожидания счётчика не был бы\n * замечен и соединение поднялось бы уже после отмены.\n */\n #wanted = false;\n #status: RealtimeStatus = RealtimeStatus.Disconnected;\n #attempt = 0;\n #timer: ReturnType<typeof setTimeout> | undefined;\n #detachEnvironment: (() => void) | undefined;\n\n constructor(deps: RealtimeDeps, options: RealtimeOptions = {}) {\n this.#deps = deps;\n this.#options = options;\n this.#maxAttempts = options.maxAttempts ?? MAX_RECONNECT_ATTEMPTS;\n this.#transport = this.#createTransport();\n }\n\n /** Текущее состояние соединения. */\n get status(): RealtimeStatus {\n return this.#status;\n }\n\n /** Какой транспорт используется: `sse` или `poll`. */\n get transport(): string {\n return this.#transport.name;\n }\n\n /** Подписывается на событие потока. @returns функция отписки */\n on<K extends keyof RealtimeEvents>(event: K, listener: Listener<RealtimeEvents[K]>): Unsubscribe {\n return this.#emitter.on(event, listener);\n }\n\n /** Подписывается на одно срабатывание. */\n once<K extends keyof RealtimeEvents>(\n event: K,\n listener: Listener<RealtimeEvents[K]>,\n ): Unsubscribe {\n return this.#emitter.once(event, listener);\n }\n\n /**\n * Поднимает соединение.\n *\n * Повторный вызов при уже живом соединении ничего не делает — это защита от двойного\n * подключения при перерисовке интерфейса.\n *\n * Возвращает управление сразу после запуска: соединение живёт в фоне.\n */\n async connect(): Promise<void> {\n if (this.#wanted) return;\n this.#wanted = true;\n\n this.#attachEnvironmentListeners();\n\n if (this.#options.syncCount !== false) {\n try {\n this.#emitter.emit('unreadCount', await this.#deps.fetchUnreadCount());\n } catch (error) {\n // Начальный счётчик — вспомогательная величина, из-за неё поток не отменяется.\n this.#deps.logger?.debug('не удалось получить число непрочитанных', error);\n }\n }\n\n // Пока ждали счётчик, могли успеть вызвать disconnect().\n if (this.#wanted) this.#run();\n }\n\n /** Закрывает соединение и отменяет запланированные попытки. */\n disconnect(): void {\n this.#wanted = false;\n\n if (this.#timer !== undefined) {\n clearTimeout(this.#timer);\n this.#timer = undefined;\n }\n\n this.#detachEnvironment?.();\n this.#detachEnvironment = undefined;\n\n this.#controller?.abort();\n this.#controller = undefined;\n this.#attempt = 0;\n\n this.#setStatus(RealtimeStatus.Disconnected);\n }\n\n /** Снимает все подписки. Соединение при этом не закрывается. */\n removeAllListeners(): void {\n this.#emitter.removeAllListeners();\n }\n\n #createTransport(): RealtimeTransport {\n const kind = this.#options.transport ?? RealtimeTransportKind.Auto;\n\n if (typeof kind === 'object') return kind;\n\n if (\n kind === RealtimeTransportKind.Poll ||\n (kind === RealtimeTransportKind.Auto && !supportsStreamingBody())\n ) {\n return new PollTransport({\n ...(this.#options.pollInterval !== undefined\n ? { interval: this.#options.pollInterval }\n : {}),\n });\n }\n\n return new SseTransport({\n ...(this.#options.idleTimeout !== undefined\n ? { idleTimeout: this.#options.idleTimeout }\n : {}),\n });\n }\n\n /** Запускает попытку подключения; повторы планирует сам. */\n #run(): void {\n // Страховка от потерянного соединения: если предыдущее ещё живо, закрываем его,\n // иначе его AbortController остался бы недостижимым и поток — незакрытым.\n this.#controller?.abort();\n\n const controller = new AbortController();\n this.#controller = controller;\n this.#setStatus(RealtimeStatus.Connecting);\n\n void this.#transport\n .connect({\n baseUrl: this.#deps.baseUrl,\n fetch: this.#deps.fetch,\n getToken: this.#deps.getToken,\n signal: controller.signal,\n onOpen: () => {\n this.#attempt = 0;\n this.#setStatus(RealtimeStatus.Connected);\n },\n onEvent: (event) => this.#handleEvent(event.name, event.data),\n onParseError: (error, raw) => this.#emitter.emit('parseError', { error, raw }),\n })\n .then(\n () => {\n // Штатное закрытие потока — тоже повод переподключиться.\n if (!controller.signal.aborted) {\n this.#handleFailure(new Error('Соединение с потоком уведомлений закрыто'));\n }\n },\n (error: unknown) => {\n if (controller.signal.aborted) return;\n this.#handleFailure(error);\n },\n );\n }\n\n #handleEvent(name: string, data: unknown): void {\n this.#emitter.emit('message', { name, data });\n\n if (name === 'connected') {\n // Строго строка: `String(null)` дал бы подписчику осмысленно выглядящее «null».\n this.#emitter.emit('ready', { userId: pickString(data, 'userId') });\n return;\n }\n\n if (name === 'notification') {\n const event = readNotificationEvent(data);\n this.#emitter.emit('notification', event);\n\n // Счётчик обновляется только если сервер его прислал: сам библиотека не считает.\n if (event.unreadCount !== undefined) this.#emitter.emit('unreadCount', event.unreadCount);\n return;\n }\n\n if (name === 'unread_count') {\n const count = readUnreadCountEvent(data);\n // Событие без вложенного payload игнорируется. Сайт итд.com в этом случае\n // обнуляет счётчик, из-за чего непрочитанные пропадают из интерфейса.\n if (count !== undefined) this.#emitter.emit('unreadCount', count);\n }\n }\n\n #handleFailure(error: unknown): void {\n this.#controller = undefined;\n\n if (error instanceof UnauthorizedStreamError) {\n void this.#refreshAndReconnect(error);\n return;\n }\n\n this.#setStatus(RealtimeStatus.Error);\n this.#scheduleReconnect(error);\n }\n\n /** Обновляет токен и переподключается; при неудаче прекращает попытки. */\n async #refreshAndReconnect(error: unknown): Promise<void> {\n this.#setStatus(RealtimeStatus.Error);\n\n const refreshed = await this.#deps.refresh().catch(() => false);\n\n if (!refreshed) {\n this.#emitter.emit('error', { error, willReconnect: false });\n this.#emitter.emit('giveup', undefined);\n return;\n }\n\n this.#scheduleReconnect(error);\n }\n\n #scheduleReconnect(error: unknown): void {\n if (this.#attempt >= this.#maxAttempts) {\n this.#emitter.emit('error', { error, willReconnect: false });\n this.#emitter.emit('giveup', undefined);\n return;\n }\n\n const delay = reconnectDelay(this.#attempt, this.#options);\n this.#attempt += 1;\n\n this.#emitter.emit('error', { error, willReconnect: true });\n this.#emitter.emit('reconnect', { attempt: this.#attempt, delay });\n\n this.#timer = setTimeout(() => {\n this.#timer = undefined;\n this.#run();\n }, delay);\n }\n\n /**\n * Подписывается на события среды.\n *\n * Возврат вкладки из фона и восстановление сети — самые частые причины «мёртвого»\n * соединения. У сайта итд.com такой обработки нет.\n */\n #attachEnvironmentListeners(): void {\n if (this.#detachEnvironment) return;\n\n const target = globalThis as unknown as {\n addEventListener?: (type: string, listener: () => void) => void;\n removeEventListener?: (type: string, listener: () => void) => void;\n document?: { visibilityState?: string };\n };\n\n if (typeof target.addEventListener !== 'function') return;\n\n const wake = () => {\n // Реагируем, только если соединения сейчас нет и попытка не запланирована.\n if (this.#controller || this.#timer !== undefined) return;\n if (this.#status === RealtimeStatus.Disconnected) return;\n\n this.#attempt = 0;\n this.#run();\n };\n\n const onVisibility = () => {\n if (target.document?.visibilityState === 'visible') wake();\n };\n\n const listeners: [string, () => void][] = [];\n\n if (this.#options.reconnectOnVisible !== false && target.document) {\n listeners.push(['visibilitychange', onVisibility]);\n }\n if (this.#options.reconnectOnOnline !== false) {\n listeners.push(['online', wake]);\n }\n\n for (const [type, listener] of listeners) target.addEventListener(type, listener);\n\n this.#detachEnvironment = () => {\n for (const [type, listener] of listeners) target.removeEventListener?.(type, listener);\n };\n }\n\n #setStatus(status: RealtimeStatus): void {\n if (this.#status === status) return;\n this.#status = status;\n this.#emitter.emit('status', status);\n }\n}\n","import { pickArray, pickBoolean, pickNumber, pickObject, pickString } from './unwrap.js';\n\n/**\n * Страница списка — единая форма для всех трёх схем пагинации API.\n *\n * Какие необязательные поля заполнены, зависит от эндпоинта: у ленты это `nextCursor`,\n * у подписчиков — `page` и `total`, у уведомлений — `nextOffset`. Обычно они не нужны:\n * перебор берёт на себя {@link Paginator}.\n */\nexport interface Page<T> {\n /** Элементы страницы. */\n items: T[];\n /** Есть ли следующая страница. */\n hasMore: boolean;\n /**\n * Курсор следующей страницы.\n *\n * Непрозрачен: у вкладки `popular` это номер страницы, у `following` — отметка времени.\n * Передавайте его обратно как есть и не пытайтесь разобрать.\n */\n nextCursor?: string | null | undefined;\n /** Номер текущей страницы при постраничной схеме. */\n page?: number | undefined;\n /** Запрошенный размер страницы. */\n limit?: number | undefined;\n /** Общее число элементов, если сервер его сообщил. */\n total?: number | undefined;\n /** Смещение для следующего запроса при схеме со смещением. */\n nextOffset?: number | undefined;\n /** Исходный ответ — на случай, если документация разошлась с реальностью. */\n raw: unknown;\n}\n\n/** Схема пагинации эндпоинта. */\nexport const PaginationMode = Object.freeze({\n /** Следующая страница запрашивается непрозрачным курсором. */\n Cursor: 'cursor',\n /** Следующая страница запрашивается номером. */\n Page: 'page',\n /** Следующая страница запрашивается смещением от начала списка. */\n Offset: 'offset',\n} as const);\nexport type PaginationMode = (typeof PaginationMode)[keyof typeof PaginationMode];\n\n/** Применяет преобразование к элементам страницы, сохраняя сведения о пагинации. */\nexport function mapPage<T, R>(page: Page<T>, map: (item: T) => R): Page<R> {\n return { ...page, items: page.items.map(map) };\n}\n\n/** Позиция, с которой запрашивается очередная страница. */\nexport interface PageState {\n cursor?: string | undefined;\n page?: number | undefined;\n offset?: number | undefined;\n}\n\n/** Настройки перебора страниц. */\nexport interface PaginatorOptions<T> {\n mode: PaginationMode;\n /** Загружает одну страницу для указанной позиции. */\n load: (state: PageState) => Promise<Page<T>>;\n /**\n * С какой позиции начать. По умолчанию с начала списка.\n *\n * Нужно, чтобы перебор можно было продолжить с сохранённого курсора, а не только\n * начать заново.\n */\n start?: PageState | undefined;\n /**\n * Предохранитель от бесконечного перебора. По умолчанию 1000.\n *\n * Сработает, только если сервер бесконечно сообщает `hasMore` — при нормальной работе\n * перебор останавливается сам.\n */\n maxPages?: number | undefined;\n /** Отмена перебора. */\n signal?: AbortSignal | undefined;\n}\n\n/**\n * Достаёт список из ответа, перебирая все формы, которые встречаются у сервера.\n *\n * Разбор клиента итд.com показал, что список приходит по-разному: под именем сущности,\n * под её альтернативным именем (`followers` вместо `users`) либо голым массивом.\n * Официальный клиент проверяет все варианты, и библиотека делает то же самое.\n *\n * @param fields имена полей в порядке предпочтения\n */\nfunction readItems<T>(body: unknown, fields: readonly string[]): T[] {\n if (Array.isArray(body)) return body as T[];\n\n for (const field of fields) {\n const items = pickArray<T>(body, field);\n if (items.length > 0) return items;\n }\n\n // Пустой список тоже валиден: возвращаем по первому известному имени.\n const primary = fields[0];\n return primary === undefined ? [] : pickArray<T>(body, primary);\n}\n\n/**\n * Достаёт курсор следующей страницы.\n *\n * Проверяются все известные места: внутри `pagination`, рядом со списком и во вложенном\n * объекте `meta.cursor.next`.\n */\nfunction readCursor(body: unknown): string | null {\n const pagination = pickObject(body, 'pagination');\n const meta = pickObject(body, 'meta');\n const metaCursor = pickObject(meta, 'cursor');\n\n return (\n pickString(pagination, 'nextCursor') ??\n pickString(body, 'nextCursor') ??\n pickString(body, 'cursor') ??\n pickString(metaCursor, 'next') ??\n null\n );\n}\n\n/**\n * Читает страницу курсорной схемы.\n *\n * Используется лентой, постами пользователя и постами по хэштегу.\n *\n * @param fields имена возможных полей со списком; первое — основное\n */\nexport function readCursorPage<T>(body: unknown, ...fields: string[]): Page<T> {\n const pagination = pickObject(body, 'pagination');\n const items = readItems<T>(body, fields);\n const nextCursor = readCursor(body);\n\n return {\n items,\n // Если признака продолжения нет, ориентируемся на наличие курсора.\n hasMore: pickBoolean(pagination, 'hasMore', pickBoolean(body, 'hasMore', nextCursor !== null)),\n nextCursor,\n limit: pickNumber(pagination, 'limit', 0) || undefined,\n raw: body,\n };\n}\n\n/**\n * Читает страницу курсорной схемы с курсором рядом со списком.\n *\n * Так устроены комментарии к посту и ответы на комментарий: `nextCursor` и `hasMore`\n * лежат на одном уровне со списком, а не внутри объекта `pagination`.\n */\nexport function readFlatCursorPage<T>(body: unknown, ...fields: string[]): Page<T> {\n const items = readItems<T>(body, fields);\n const nextCursor = readCursor(body);\n const total = pickNumber(body, 'total', -1);\n\n return {\n items,\n hasMore: pickBoolean(body, 'hasMore', nextCursor !== null),\n nextCursor,\n ...(total >= 0 ? { total } : {}),\n raw: body,\n };\n}\n\n/**\n * Читает страницу постраничной схемы: `data.pagination.{page,limit,total,hasMore}`.\n *\n * Если сервер вместо этого прислал курсор, он тоже подхватывается — некоторые списки\n * отвечают в курсорной форме, хотя документация описывает постраничную.\n */\nexport function readPagedPage<T>(body: unknown, ...fields: string[]): Page<T> {\n const pagination = pickObject(body, 'pagination');\n const items = readItems<T>(body, fields);\n const nextCursor = readCursor(body);\n\n return {\n items,\n hasMore: pickBoolean(pagination, 'hasMore', pickBoolean(body, 'hasMore', nextCursor !== null)),\n page: pickNumber(pagination, 'page', 1),\n limit: pickNumber(pagination, 'limit', 0) || undefined,\n total: pickNumber(pagination, 'total', 0),\n ...(nextCursor !== null ? { nextCursor } : {}),\n raw: body,\n };\n}\n\n/**\n * Читает страницу схемы со смещением.\n *\n * Так работают уведомления. Официальный клиент подменяет смещение псевдокурсором-строкой,\n * которую потом разбирает обратно; библиотека отдаёт честное числовое смещение.\n */\nexport function readOffsetPage<T>(body: unknown, field: string, offset: number): Page<T> {\n const items = pickArray<T>(body, field);\n\n return {\n items,\n hasMore: pickBoolean(body, 'hasMore'),\n nextOffset: offset + items.length,\n raw: body,\n };\n}\n\n/**\n * Перебор страниц списка.\n *\n * Скрывает различия трёх схем пагинации: перебор элементов, страниц и сбор в массив\n * выглядят одинаково независимо от эндпоинта.\n *\n * **Одноразовый.** Позиция хранится внутри, поэтому повторный перебор того же объекта\n * ничего не вернёт: он продолжится с места, где закончился прошлый. Нужен второй проход —\n * возьмите новый перебор у того же метода ресурса.\n *\n * @example Перебор элементов\n * ```ts\n * for await (const post of itd.posts.iterate({ tab: 'following' })) {\n * console.log(post.content);\n * }\n * ```\n *\n * @example Первые сто элементов\n * ```ts\n * const posts = await itd.posts.iterate({ tab: 'popular' }).collect(100);\n * ```\n *\n * @example Постранично\n * ```ts\n * for await (const page of itd.users.followers('durov').pages()) {\n * console.log(page.items.length, 'из', page.total);\n * }\n * ```\n */\nexport class Paginator<T> implements AsyncIterable<T> {\n readonly #options: PaginatorOptions<T>;\n readonly #maxPages: number;\n\n #state: PageState;\n #finished = false;\n #pagesLoaded = 0;\n\n constructor(options: PaginatorOptions<T>) {\n this.#options = options;\n this.#maxPages = options.maxPages ?? 1000;\n this.#state = options.start ?? {};\n }\n\n /**\n * Загружает следующую страницу.\n *\n * @returns страница либо `null`, если перебор закончен\n */\n async next(): Promise<Page<T> | null> {\n if (this.#finished) return null;\n if (this.#options.signal?.aborted) return null;\n\n if (this.#pagesLoaded >= this.#maxPages) {\n this.#finished = true;\n return null;\n }\n\n const previous = this.#state;\n const page = await this.#options.load(previous);\n this.#pagesLoaded += 1;\n\n this.#state = this.#advance(previous, page);\n return page;\n }\n\n /**\n * Перебирает страницы целиком.\n *\n * Полезно, когда нужны сведения о самой странице — например `total`.\n */\n async *pages(): AsyncGenerator<Page<T>, void, undefined> {\n for (;;) {\n const page = await this.next();\n if (!page) return;\n yield page;\n }\n }\n\n /** Перебирает элементы всех страниц подряд. */\n async *[Symbol.asyncIterator](): AsyncGenerator<T, void, undefined> {\n for await (const page of this.pages()) {\n for (const item of page.items) {\n if (this.#options.signal?.aborted) return;\n yield item;\n }\n }\n }\n\n /**\n * Собирает элементы в массив.\n *\n * @param max сколько элементов достаточно; без него перебираются все страницы\n */\n async collect(max?: number): Promise<T[]> {\n const result: T[] = [];\n\n for await (const item of this) {\n result.push(item);\n if (max !== undefined && result.length >= max) break;\n }\n\n return result;\n }\n\n /**\n * Вычисляет позицию следующей страницы и решает, продолжать ли.\n *\n * Здесь же стоят предохранители: пустая страница при `hasMore`, неизменившийся курсор\n * и отсутствие курсора останавливают перебор. Без них ошибка на сервере превратилась бы\n * в бесконечный цикл запросов.\n */\n #advance(previous: PageState, page: Page<T>): PageState {\n if (!page.hasMore || page.items.length === 0) {\n this.#finished = true;\n return previous;\n }\n\n if (this.#options.mode === PaginationMode.Cursor) {\n const cursor = page.nextCursor ?? undefined;\n\n if (!cursor || cursor === previous.cursor) {\n this.#finished = true;\n return previous;\n }\n\n return { cursor };\n }\n\n if (this.#options.mode === PaginationMode.Page) {\n return { page: (previous.page ?? 1) + 1 };\n }\n\n return { offset: page.nextOffset ?? (previous.offset ?? 0) + page.items.length };\n }\n}\n","import type { HttpClient } from '../core/http.js';\nimport type { Page, PageState, PaginationMode } from '../core/pagination.js';\nimport { Paginator } from '../core/pagination.js';\nimport type { QueryParams } from '../core/url.js';\nimport type { RequestOptions } from '../types/options.js';\n\n/** Общая основа всех групп методов клиента. */\nexport class BaseResource {\n /** @internal */\n protected readonly http: HttpClient;\n\n constructor(http: HttpClient) {\n this.http = http;\n }\n\n /**\n * Переносит общие поля опций запроса в параметры транспорта.\n *\n * Поля перечислены поимённо, а не скопированы целиком: параметры методов наследуют\n * {@link RequestOptions} и приносят с собой `limit`, `cursor` и прочее, чему в описании\n * запроса делать нечего. Исключение — опции, заявленные плагинами: их библиотека\n * не понимает, но обязана донести до обёрток нетронутыми.\n */\n protected requestOptions(options: RequestOptions | undefined): Partial<RequestOptions> {\n if (!options) return {};\n\n const result: Partial<RequestOptions> = {\n ...(options.signal !== undefined ? { signal: options.signal } : {}),\n ...(options.timeout !== undefined ? { timeout: options.timeout } : {}),\n ...(options.headers !== undefined ? { headers: options.headers } : {}),\n ...(options.retry !== undefined ? { retry: options.retry } : {}),\n };\n\n const pluginKeys = this.http.pluginOptionKeys;\n if (pluginKeys.size === 0) return result;\n\n const source = options as Record<string, unknown>;\n const target = result as Record<string, unknown>;\n for (const key of pluginKeys) {\n const value = source[key];\n if (value !== undefined) target[key] = value;\n }\n\n return result;\n }\n\n /**\n * Собирает перебор страниц.\n *\n * @param mode схема пагинации эндпоинта\n * @param load загружает одну страницу для указанной позиции\n * @param options `maxPages` и `signal`, а также `start` — позиция, с которой продолжить\n */\n protected paginate<T>(\n mode: PaginationMode,\n load: (state: PageState) => Promise<Page<T>>,\n options?: RequestOptions & { maxPages?: number; start?: PageState },\n ): Paginator<T> {\n return new Paginator<T>({\n mode,\n load,\n ...(options?.maxPages !== undefined ? { maxPages: options.maxPages } : {}),\n ...(options?.signal !== undefined ? { signal: options.signal } : {}),\n ...(options?.start !== undefined ? { start: options.start } : {}),\n });\n }\n}\n\n/** Добавляет позицию страницы в параметры запроса. */\nexport function withPageState(query: QueryParams, state: PageState): QueryParams {\n return {\n ...query,\n ...(state.cursor !== undefined ? { cursor: state.cursor } : {}),\n ...(state.page !== undefined ? { page: state.page } : {}),\n ...(state.offset !== undefined ? { offset: state.offset } : {}),\n };\n}\n","import type { AuthManager, TURNSTILE_SITE_KEY } from '../core/auth.js';\nimport { ItdConfigError } from '../core/errors.js';\nimport type { HttpClient } from '../core/http.js';\nimport { pickArray, pickString } from '../core/unwrap.js';\nimport { joinUrl } from '../core/url.js';\nimport type { Session } from '../types/models.js';\nimport type { RequestOptions } from '../types/options.js';\nimport { BaseResource } from './base.js';\n\n/** Учётные данные для входа. */\nexport interface Credentials {\n email: string;\n password: string;\n}\n\n/**\n * Учётные данные вместе с токеном капчи.\n *\n * `turnstileToken` обязателен: без него сервер отвечает `VALIDATION_ERROR`, с недействительным —\n * `TURNSTILE_VERIFICATION_FAILED`. Токен даёт виджет Cloudflare Turnstile с ключом\n * {@link TURNSTILE_SITE_KEY}; он одноразовый и живёт несколько минут.\n */\nexport interface CaptchaCredentials extends Credentials {\n turnstileToken: string;\n}\n\n/** Запрос письма для сброса пароля. Капча обязательна, как и при входе. */\nexport interface ForgotPasswordInput {\n email: string;\n turnstileToken: string;\n}\n\n/**\n * Установка нового пароля.\n *\n * Сброс идёт тем же потоком с кодом, что и вход: {@link AuthResource.forgotPassword} выдаёт\n * `flowToken`, письмо приносит `otp`, и всё это вместе с новым паролем уходит сюда.\n */\nexport interface ResetPasswordInput {\n email: string;\n otp: string;\n flowToken: string;\n newPassword: string;\n}\n\n/** Провайдер внешнего входа. */\nexport const OAuthProvider = Object.freeze({\n Yandex: 'yandex',\n Google: 'google',\n} as const);\nexport type OAuthProvider = (typeof OAuthProvider)[keyof typeof OAuthProvider];\n\n/** Чем закончился вход: сразу токеном или запросом кода подтверждения. */\nexport const SignInStatus = Object.freeze({\n Authenticated: 'authenticated',\n OtpRequired: 'otp_required',\n} as const);\nexport type SignInStatus = (typeof SignInStatus)[keyof typeof SignInStatus];\n\n/**\n * Результат входа.\n *\n * Сервер может как сразу выдать токен, так и потребовать код подтверждения — размеченное\n * объединение делает оба случая явными.\n */\nexport type SignInResult =\n | { status: typeof SignInStatus.Authenticated; accessToken: string }\n | { status: typeof SignInStatus.OtpRequired; flowToken: string | undefined };\n\n/**\n * Авторизация, сессии и пароли.\n *\n * Доступна как `itd.auth`.\n */\nexport class AuthResource extends BaseResource {\n readonly #auth: AuthManager;\n\n constructor(http: HttpClient, deps: { auth: AuthManager }) {\n super(http);\n this.#auth = deps.auth;\n }\n\n /**\n * Регистрирует аккаунт и запускает подтверждение по коду.\n *\n * @returns `flowToken`, который нужно передать в {@link verifyOtp}\n */\n async signUp(credentials: CaptchaCredentials, options: RequestOptions = {}): Promise<string> {\n const body = await this.http.request({\n method: 'POST',\n path: '/api/v1/auth/sign-up',\n body: credentials,\n skipAuth: true,\n skipAuthRefresh: true,\n ...this.requestOptions(options),\n });\n\n const flowToken = pickString(body, 'flowToken');\n if (!flowToken) {\n throw new ItdConfigError('Сервер не вернул flowToken при регистрации');\n }\n\n return flowToken;\n }\n\n /**\n * Выполняет вход.\n *\n * Если сервер потребовал код подтверждения, вернётся `status: 'otp_required'` —\n * тогда продолжайте через {@link verifyOtp} либо воспользуйтесь {@link signInWithOtp}.\n *\n * При успешном входе токен сохраняется в клиенте автоматически.\n *\n * @param credentials email, пароль и обязательный токен капчи — см. {@link CaptchaCredentials}\n */\n async signIn(\n credentials: CaptchaCredentials,\n options: RequestOptions = {},\n ): Promise<SignInResult> {\n const body = await this.http.request({\n method: 'POST',\n path: '/api/v1/auth/sign-in',\n body: credentials,\n skipAuth: true,\n skipAuthRefresh: true,\n ...this.requestOptions(options),\n });\n\n const accessToken = pickString(body, 'accessToken');\n\n if (accessToken) {\n await this.#auth.setAccessToken(accessToken);\n return { status: SignInStatus.Authenticated, accessToken };\n }\n\n return { status: SignInStatus.OtpRequired, flowToken: pickString(body, 'flowToken') };\n }\n\n /**\n * Подтверждает вход кодом из письма.\n *\n * Полученный токен сохраняется в клиенте автоматически.\n */\n async verifyOtp(\n input: Credentials & { otp: string; flowToken: string },\n options: RequestOptions = {},\n ): Promise<string> {\n const body = await this.http.request({\n method: 'POST',\n path: '/api/v1/auth/verify-otp',\n body: input,\n skipAuth: true,\n skipAuthRefresh: true,\n ...this.requestOptions(options),\n });\n\n const accessToken = pickString(body, 'accessToken');\n if (!accessToken) {\n throw new ItdConfigError('Сервер не вернул accessToken после подтверждения кода');\n }\n\n await this.#auth.setAccessToken(accessToken);\n return accessToken;\n }\n\n /** Отправляет код подтверждения повторно. */\n resendOtp(\n input: { email: string; flowToken: string },\n options: RequestOptions = {},\n ): Promise<void> {\n return this.http.request<void>({\n method: 'POST',\n path: '/api/v1/auth/resend-otp',\n body: input,\n skipAuth: true,\n skipAuthRefresh: true,\n ...this.requestOptions(options),\n });\n }\n\n /**\n * Полный вход с подтверждением по коду.\n *\n * Удобно для скриптов и ботов: код запрашивается функцией `getOtp`, а всё остальное\n * библиотека делает сама.\n *\n * @example\n * ```ts\n * import { createInterface } from 'node:readline/promises';\n *\n * const rl = createInterface({ input: process.stdin, output: process.stdout });\n *\n * const token = await itd.auth.signInWithOtp({\n * email, password,\n * getOtp: () => rl.question('Код из письма: '),\n * });\n * ```\n */\n async signInWithOtp(\n input: CaptchaCredentials & { getOtp: () => string | Promise<string> },\n options: RequestOptions = {},\n ): Promise<string> {\n const { getOtp, ...credentials } = input;\n const result = await this.signIn(credentials, options);\n\n if (result.status === SignInStatus.Authenticated) return result.accessToken;\n\n if (!result.flowToken) {\n throw new ItdConfigError(\n 'Сервер запросил код подтверждения, но не вернул flowToken — продолжить вход невозможно',\n );\n }\n\n const otp = await getOtp();\n\n // Токен капчи сюда не передаётся: он одноразовый и уже потрачен на sign-in,\n // а verify-otp капчу не требует.\n return this.verifyOtp(\n {\n email: credentials.email,\n password: credentials.password,\n otp,\n flowToken: result.flowToken,\n },\n options,\n );\n }\n\n /**\n * Обновляет токен доступа.\n *\n * Параллельные вызовы объединяются в один сетевой запрос. При включённом `autoRefresh`\n * вызывать вручную обычно не нужно.\n */\n refresh(): Promise<string> {\n return this.#auth.refresh();\n }\n\n /**\n * Есть ли признак живой сессии обновления.\n *\n * Проверяет cookie `is_auth`, которую сервер ставит рядом с refresh-токеном, а также\n * refresh-токен, переданный строкой. Позволяет не дёргать API у неавторизованного\n * пользователя. В браузере всегда `true`: cookie ведёт сама среда, и прочитать её\n * из JS нельзя.\n *\n * Читает {@link TokenStorage}, поэтому результат верен и до первого запроса.\n *\n * @example\n * ```ts\n * if (await itd.auth.hasRefreshSession()) await itd.auth.refresh();\n * else redirectToLogin();\n * ```\n */\n hasRefreshSession(): Promise<boolean> {\n return this.#auth.hasRefreshSession();\n }\n\n /** Завершает текущую сессию на сервере и очищает локальную. */\n async logout(options: RequestOptions = {}): Promise<void> {\n await this.http.request<void>({\n method: 'POST',\n path: '/api/v1/auth/logout',\n skipAuthRefresh: true,\n ...this.requestOptions(options),\n });\n\n await this.#auth.clear();\n }\n\n /**\n * Завершает все сессии пользователя и очищает локальную.\n *\n * Собран из двух запросов, потому что единого эндпоинта на сервере нет:\n * `POST /api/v1/auth/logout-all` отвечает `404`. Сначала отзываются все прочие сессии\n * (`DELETE /api/v1/auth/sessions`), затем завершается текущая — в обратном порядке\n * отзывать было бы уже нечем.\n */\n async logoutAll(options: RequestOptions = {}): Promise<void> {\n await this.revokeOtherSessions(options);\n await this.logout(options);\n }\n\n /** Забывает сессию локально, не обращаясь к серверу. */\n signOut(): Promise<void> {\n return this.#auth.clear();\n }\n\n /**\n * Запрашивает письмо с кодом для сброса пароля.\n *\n * @returns `flowToken`, который нужно передать в {@link resetPassword}\n */\n async forgotPassword(input: ForgotPasswordInput, options: RequestOptions = {}): Promise<string> {\n const body = await this.http.request({\n method: 'POST',\n path: '/api/v1/auth/forgot-password',\n body: input,\n skipAuth: true,\n skipAuthRefresh: true,\n ...this.requestOptions(options),\n });\n\n const flowToken = pickString(body, 'flowToken');\n if (!flowToken) {\n throw new ItdConfigError('Сервер не вернул flowToken при запросе сброса пароля');\n }\n\n return flowToken;\n }\n\n /**\n * Устанавливает новый пароль по коду из письма.\n *\n * Сервер ждёт все четыре поля сразу — `email`, `otp`, `flowToken` и `newPassword`;\n * при нехватке любого отвечает `422`.\n */\n resetPassword(input: ResetPasswordInput, options: RequestOptions = {}): Promise<void> {\n return this.http.request<void>({\n method: 'POST',\n path: '/api/v1/auth/reset-password',\n body: input,\n skipAuth: true,\n skipAuthRefresh: true,\n ...this.requestOptions(options),\n });\n }\n\n /**\n * Полный сброс пароля с кодом из письма.\n *\n * Тот же приём, что и {@link signInWithOtp}: код запрашивается функцией `getOtp`,\n * остальное библиотека делает сама.\n *\n * @example\n * ```ts\n * await itd.auth.resetPasswordWithOtp({\n * email,\n * turnstileToken,\n * newPassword,\n * getOtp: () => rl.question('Код из письма: '),\n * });\n * ```\n */\n async resetPasswordWithOtp(\n input: ForgotPasswordInput & {\n newPassword: string;\n getOtp: () => string | Promise<string>;\n },\n options: RequestOptions = {},\n ): Promise<void> {\n const flowToken = await this.forgotPassword(\n { email: input.email, turnstileToken: input.turnstileToken },\n options,\n );\n\n const otp = await input.getOtp();\n\n await this.resetPassword(\n { email: input.email, otp, flowToken, newPassword: input.newPassword },\n options,\n );\n }\n\n /**\n * Меняет пароль. Требует действующей сессии.\n *\n * При неверном текущем пароле сервер отвечает `ACCOUNT_CURRENT_PASSWORD_INCORRECT`.\n */\n changePassword(\n input: { oldPassword: string; newPassword: string },\n options: RequestOptions = {},\n ): Promise<void> {\n return this.http.request<void>({\n method: 'POST',\n path: '/api/v1/auth/change-password',\n // Текущий пароль уходит под двумя именами: какое из них ждёт сервер, снаружи\n // не проверить, а лишнее поле он игнорирует.\n body: { ...input, currentPassword: input.oldPassword },\n ...this.requestOptions(options),\n });\n }\n\n /**\n * Возвращает адрес для входа через внешнего провайдера.\n *\n * Сам переход выполняет приложение: в браузере — редиректом, в приложении — открытием\n * системного браузера.\n *\n * @example\n * ```ts\n * window.location.href = itd.auth.oauthUrl('yandex');\n * ```\n */\n oauthUrl(provider: OAuthProvider): string {\n return joinUrl(this.http.baseUrl, `/api/v1/auth/login/${provider}`);\n }\n\n /** Загружает список активных сессий. У текущей поле `isCurrent` равно `true`. */\n async sessions(options: RequestOptions = {}): Promise<Session[]> {\n const body = await this.http.request({\n method: 'GET',\n path: '/api/v1/auth/sessions',\n ...this.requestOptions(options),\n });\n\n return pickArray<Session>(body, 'sessions');\n }\n\n /** Завершает указанную сессию. */\n revokeSession(sessionId: string, options: RequestOptions = {}): Promise<void> {\n return this.http.request<void>({\n method: 'DELETE',\n path: `/api/v1/auth/sessions/${encodeURIComponent(sessionId)}`,\n ...this.requestOptions(options),\n });\n }\n\n /** Завершает все сессии, кроме текущей. */\n revokeOtherSessions(options: RequestOptions = {}): Promise<void> {\n return this.http.request<void>({\n method: 'DELETE',\n path: '/api/v1/auth/sessions',\n ...this.requestOptions(options),\n });\n }\n}\n","import { type CommentInput, resolveComment } from '../builders/comment.js';\nimport type { HttpClient } from '../core/http.js';\nimport { type Page, PaginationMode, type Paginator, readPagedPage } from '../core/pagination.js';\nimport { encodePathSegment } from '../core/url.js';\nimport type { Comment, LikeResult } from '../types/models.js';\nimport type { RequestOptions } from '../types/options.js';\nimport type { FileInput } from '../types/params.js';\nimport { BaseResource, withPageState } from './base.js';\n\n/** Параметры запроса ответов на комментарий. */\nexport interface RepliesParams extends RequestOptions {\n limit?: number;\n page?: number;\n maxPages?: number;\n}\n\n/**\n * Комментарии и ответы на них.\n *\n * Доступна как `itd.comments`. Комментарии **к посту** живут в `itd.posts`:\n * `itd.posts.comments()` и `itd.posts.comment()`.\n */\nexport class CommentsResource extends BaseResource {\n readonly #uploadFiles: (files: FileInput[], options?: RequestOptions) => Promise<string[]>;\n\n constructor(\n http: HttpClient,\n deps: { uploadFiles: (files: FileInput[], options?: RequestOptions) => Promise<string[]> },\n ) {\n super(http);\n this.#uploadFiles = deps.uploadFiles;\n }\n\n /**\n * Загружает страницу ответов на комментарий.\n *\n * Здесь пагинация **постраничная**, в отличие от комментариев к посту, где курсорная.\n */\n async replies(commentId: string, params: RepliesParams = {}): Promise<Page<Comment>> {\n const body = await this.http.request({\n method: 'GET',\n path: `/api/comments/${encodePathSegment(commentId, 'commentId')}/replies`,\n query: { limit: params.limit, page: params.page },\n ...this.requestOptions(params),\n });\n\n return readPagedPage<Comment>(body, 'replies');\n }\n\n /** Перебирает ответы на комментарий. */\n iterateReplies(commentId: string, params: RepliesParams = {}): Paginator<Comment> {\n const path = `/api/comments/${encodePathSegment(commentId, 'commentId')}/replies`;\n\n return this.paginate<Comment>(\n PaginationMode.Page,\n async (state) => {\n const body = await this.http.request({\n method: 'GET',\n path,\n query: withPageState({ limit: params.limit }, state),\n ...this.requestOptions(params),\n });\n return readPagedPage<Comment>(body, 'replies');\n },\n { ...params, ...(params.page !== undefined ? { start: { page: params.page } } : {}) },\n );\n }\n\n /**\n * Отвечает на комментарий.\n *\n * @example\n * ```ts\n * await itd.comments.reply(commentId, 'согласен');\n * await itd.comments.reply(commentId, (c) => c.content('и вот почему').replyTo(userId));\n * ```\n */\n async reply(\n commentId: string,\n input: CommentInput | string,\n options: RequestOptions = {},\n ): Promise<Comment> {\n const data = resolveComment(typeof input === 'string' ? { content: input } : input, true);\n\n const existing = data.attachmentIds ?? [];\n const files = data.files ?? [];\n const attachmentIds =\n files.length > 0 ? [...existing, ...(await this.#uploadFiles(files, options))] : existing;\n\n return this.http.request<Comment>({\n method: 'POST',\n path: `/api/comments/${encodePathSegment(commentId, 'commentId')}/replies`,\n body: {\n content: data.content ?? '',\n attachmentIds,\n ...(data.replyToUserId ? { replyToUserId: data.replyToUserId } : {}),\n },\n ...this.requestOptions(options),\n });\n }\n\n /** Редактирует текст комментария. */\n update(commentId: string, content: string, options: RequestOptions = {}): Promise<Comment> {\n return this.http.request<Comment>({\n method: 'PATCH',\n path: `/api/comments/${encodePathSegment(commentId, 'commentId')}`,\n body: { content },\n ...this.requestOptions(options),\n });\n }\n\n /** Удаляет комментарий. Восстановить его можно через {@link restore}. */\n remove(commentId: string, options: RequestOptions = {}): Promise<void> {\n return this.http.request<void>({\n method: 'DELETE',\n path: `/api/comments/${encodePathSegment(commentId, 'commentId')}`,\n ...this.requestOptions(options),\n });\n }\n\n /** Восстанавливает удалённый комментарий. */\n restore(commentId: string, options: RequestOptions = {}): Promise<Comment> {\n return this.http.request<Comment>({\n method: 'POST',\n path: `/api/comments/${encodePathSegment(commentId, 'commentId')}/restore`,\n ...this.requestOptions(options),\n });\n }\n\n /** Ставит реакцию на комментарий. */\n like(commentId: string, options: RequestOptions = {}): Promise<LikeResult> {\n return this.http.request<LikeResult>({\n method: 'POST',\n path: `/api/comments/${encodePathSegment(commentId, 'commentId')}/like`,\n ...this.requestOptions(options),\n });\n }\n\n /** Убирает реакцию с комментария. */\n unlike(commentId: string, options: RequestOptions = {}): Promise<LikeResult> {\n return this.http.request<LikeResult>({\n method: 'DELETE',\n path: `/api/comments/${encodePathSegment(commentId, 'commentId')}/like`,\n ...this.requestOptions(options),\n });\n }\n}\n","import { ItdConfigError } from './errors.js';\n\n/** Изображения, которые принимает `POST /api/files/upload`. */\nexport const IMAGE_MIME_TYPES = Object.freeze([\n 'image/jpeg',\n 'image/png',\n 'image/gif',\n 'image/webp',\n 'image/avif',\n 'image/heic',\n 'image/heif',\n] as const);\nexport type ImageMimeType = (typeof IMAGE_MIME_TYPES)[number];\n\n/** Видео, которые принимает `POST /api/files/upload`. */\nexport const VIDEO_MIME_TYPES = Object.freeze([\n 'video/mp4',\n 'video/webm',\n 'video/quicktime',\n] as const);\nexport type VideoMimeType = (typeof VIDEO_MIME_TYPES)[number];\n\n/** Аудио для голосовых комментариев. */\nexport const AUDIO_MIME_TYPES = Object.freeze(['audio/ogg'] as const);\nexport type AudioMimeType = (typeof AUDIO_MIME_TYPES)[number];\n\n/** Все типы, которые принимает загрузка. */\nexport const ALLOWED_MIME_TYPES = Object.freeze([\n ...IMAGE_MIME_TYPES,\n ...VIDEO_MIME_TYPES,\n ...AUDIO_MIME_TYPES,\n] as const);\nexport type AllowedMimeType = (typeof ALLOWED_MIME_TYPES)[number];\n\n/**\n * Соответствие расширения и MIME-типа.\n *\n * Своя маленькая таблица вместо зависимости: библиотеке нужны ровно те типы,\n * которые принимает API.\n */\nconst EXTENSION_TO_MIME: Readonly<Record<string, string>> = Object.freeze({\n jpg: 'image/jpeg',\n jpeg: 'image/jpeg',\n jfif: 'image/jpeg',\n png: 'image/png',\n gif: 'image/gif',\n webp: 'image/webp',\n avif: 'image/avif',\n heic: 'image/heic',\n heif: 'image/heif',\n mp4: 'video/mp4',\n m4v: 'video/mp4',\n webm: 'video/webm',\n mov: 'video/quicktime',\n qt: 'video/quicktime',\n ogg: 'audio/ogg',\n oga: 'audio/ogg',\n opus: 'audio/ogg',\n});\n\n/** Определяет MIME-тип по расширению имени файла. */\nexport function mimeFromFilename(filename: string): string | undefined {\n const dot = filename.lastIndexOf('.');\n if (dot < 0) return undefined;\n\n return EXTENSION_TO_MIME[filename.slice(dot + 1).toLowerCase()];\n}\n\n/** Разрешён ли тип к загрузке. */\nexport function isAllowedMime(mimeType: string): mimeType is AllowedMimeType {\n return (ALLOWED_MIME_TYPES as readonly string[]).includes(mimeType.toLowerCase());\n}\n\n/**\n * Проверяет тип файла до отправки.\n *\n * Отказ на стороне клиента экономит и время, и трафик: тот же `UNSUPPORTED_FILE_TYPE`\n * пришёл бы с сервера, но уже после загрузки всего файла.\n *\n * @throws {ItdConfigError} если тип не поддерживается\n */\nexport function assertAllowedMime(mimeType: string | undefined, filename?: string): void {\n if (!mimeType) {\n throw new ItdConfigError(\n `Не удалось определить тип файла${filename ? ` «${filename}»` : ''}. ` +\n 'Укажите его явно: { data, filename, contentType }.',\n );\n }\n\n if (!isAllowedMime(mimeType)) {\n throw new ItdConfigError(\n `Тип «${mimeType}» не поддерживается загрузкой. Допустимые: ${ALLOWED_MIME_TYPES.join(', ')}.`,\n );\n }\n}\n","import { ItdConfigError } from '../core/errors.js';\nimport type { HttpClient } from '../core/http.js';\nimport { assertAllowedMime, mimeFromFilename } from '../core/mime.js';\nimport { isBlob, isFile } from '../core/runtime.js';\nimport { encodePathSegment } from '../core/url.js';\nimport type { RequestOptions } from '../types/options.js';\nimport type { FileInput } from '../types/params.js';\nimport { BaseResource } from './base.js';\n\n/** Ответ загрузки файла. */\nexport interface UploadedFile {\n /** Идентификатор вложения — его передают в `attachmentIds`. */\n id: string;\n /** Адрес файла на CDN. */\n url: string;\n}\n\n/** Настройки загрузки. */\nexport interface UploadOptions extends RequestOptions {\n /** Имя файла. По нему определяется тип, если он не задан явно. */\n filename?: string;\n /** MIME-тип. Если не указан, определяется по имени файла или по самому `Blob`. */\n contentType?: string;\n /**\n * Проверять тип файла до отправки. По умолчанию `true`.\n *\n * Отключайте, если API начал принимать формат, которого ещё нет в списке библиотеки.\n */\n validateMime?: boolean;\n}\n\n/**\n * Таймаут загрузки файла по умолчанию.\n *\n * Заметно больше обычного: видео на несколько десятков мегабайт не укладывается\n * в стандартные 30 секунд, и запрос обрывался бы на середине.\n */\nexport const DEFAULT_UPLOAD_TIMEOUT = 300_000;\n\n/** Чтение файла по пути — подставляется точкой входа `itd-api/node`. */\nexport type FileReader = (path: string) => Promise<{ data: Uint8Array; filename: string }>;\n\n/** Приведённый к отправке файл. */\ninterface PreparedFile {\n blob: Blob;\n filename: string;\n}\n\n/**\n * Файлы и медиа.\n *\n * Доступна как `itd.files`. Обычно вызывать её напрямую не нужно: `itd.posts.create()`\n * и `itd.posts.comment()` загружают файлы сами.\n */\nexport class FilesResource extends BaseResource {\n #readFile: FileReader | undefined;\n\n constructor(http: HttpClient, deps: { readFile?: FileReader } = {}) {\n super(http);\n this.#readFile = deps.readFile;\n }\n\n /**\n * Подключает чтение файлов с диска.\n *\n * Вызывается точкой входа `itd-api/node`; в основном бандле работы с файловой\n * системой нет, чтобы браузерные сборщики не пытались разрешить `node:fs`.\n */\n setFileReader(readFile: FileReader): void {\n this.#readFile = readFile;\n }\n\n /**\n * Загружает файл и возвращает его идентификатор.\n *\n * @remarks\n * Кроме типа сервер проверяет и само изображение: слишком маленькие картинки\n * он отклоняет сообщением «Не удалось проверить изображение». Точный порог\n * неизвестен, но 64×64 проходит.\n *\n * @example\n * ```ts\n * const file = await itd.files.upload(blob, { filename: 'photo.jpg' });\n * await itd.posts.create({ content: 'смотрите', attachmentIds: [file.id] });\n * ```\n */\n async upload(input: FileInput, options: UploadOptions = {}): Promise<UploadedFile> {\n const prepared = await this.#prepare(input, options);\n\n const form = new FormData();\n form.set('file', prepared.blob, prepared.filename);\n\n return this.http.request<UploadedFile>({\n method: 'POST',\n path: '/api/files/upload',\n body: form,\n timeout: options.timeout ?? DEFAULT_UPLOAD_TIMEOUT,\n ...this.requestOptions(options),\n });\n }\n\n /**\n * Загружает несколько файлов, сохраняя порядок.\n *\n * Файлы отправляются последовательно: параллельная загрузка нескольких видео легко\n * упирается в ограничение частоты, а порядок вложений в посте важен.\n *\n * @returns идентификаторы вложений в том же порядке, что и входные файлы\n */\n async uploadMany(files: FileInput[], options: UploadOptions = {}): Promise<string[]> {\n const ids: string[] = [];\n\n for (const file of files) {\n const uploaded = await this.upload(file, options);\n ids.push(uploaded.id);\n }\n\n return ids;\n }\n\n /**\n * Загружает сведения о файле.\n *\n * @remarks\n * Сервер отвечает `404` даже на только что загруженный файл, который ещё никуда\n * не прикреплён, — проверено на боевом API. Практической пользы у метода пока нет,\n * он оставлен для полноты.\n */\n get(fileId: string, options: RequestOptions = {}): Promise<unknown> {\n return this.http.request({\n method: 'GET',\n path: `/api/files/${encodePathSegment(fileId, 'fileId')}`,\n ...this.requestOptions(options),\n });\n }\n\n /** Удаляет загруженный файл. */\n remove(fileId: string, options: RequestOptions = {}): Promise<void> {\n return this.http.request<void>({\n method: 'DELETE',\n path: `/api/files/${encodePathSegment(fileId, 'fileId')}`,\n ...this.requestOptions(options),\n });\n }\n\n /** Приводит любой поддерживаемый вход к `Blob` с именем и проверенным типом. */\n async #prepare(input: FileInput, options: UploadOptions): Promise<PreparedFile> {\n const { data, filename, contentType } = await this.#normalize(input, options);\n\n const type =\n contentType ?? ((isBlob(data) ? data.type : undefined) || mimeFromFilename(filename));\n\n if (options.validateMime !== false) assertAllowedMime(type || undefined, filename);\n\n const blob =\n isBlob(data) && (!type || data.type === type)\n ? data\n : new Blob([data as BlobPart], { type: type ?? '' });\n\n return { blob, filename };\n }\n\n async #normalize(\n input: FileInput,\n options: UploadOptions,\n ): Promise<{ data: Blob | ArrayBuffer | Uint8Array; filename: string; contentType?: string }> {\n if (typeof input === 'string') {\n if (!this.#readFile) {\n throw new ItdConfigError(\n `Загрузка по пути «${input}» доступна только в Node, Bun и Deno. ` +\n \"Подключите её импортом 'itd-api/node' либо передайте Blob или File.\",\n );\n }\n\n const file = await this.#readFile(input);\n return {\n data: file.data,\n filename: options.filename ?? file.filename,\n ...(options.contentType ? { contentType: options.contentType } : {}),\n };\n }\n\n if (input instanceof ArrayBuffer || ArrayBuffer.isView(input) || isBlob(input)) {\n const fallbackName = isFile(input)\n ? input.name\n : (options.filename ?? this.#nameFromMime(options.contentType));\n\n return {\n data: input as Blob | ArrayBuffer | Uint8Array,\n filename: options.filename ?? fallbackName,\n ...(options.contentType ? { contentType: options.contentType } : {}),\n };\n }\n\n const contentType = input.contentType ?? options.contentType;\n\n return {\n data: input.data,\n filename: input.filename ?? options.filename ?? this.#nameFromMime(contentType),\n ...(contentType ? { contentType } : {}),\n };\n }\n\n /** Подбирает имя файла, когда его не передали: сервер ждёт непустое поле. */\n #nameFromMime(contentType: string | undefined): string {\n const extension = contentType?.split('/')[1]?.split(';')[0];\n return extension ? `file.${extension}` : 'file';\n }\n}\n","import { type ReportInput, resolveReport } from '../builders/report.js';\nimport { type Page, PaginationMode, type Paginator, readCursorPage } from '../core/pagination.js';\nimport { pickArray } from '../core/unwrap.js';\nimport { encodePathSegment } from '../core/url.js';\nimport type {\n Announcement,\n ChangelogEntry,\n Hashtag,\n PaymentMethod,\n Portal,\n Post,\n Report,\n Subscription,\n UserSummary,\n VerificationStatus,\n} from '../types/models.js';\nimport type { RequestOptions } from '../types/options.js';\nimport { BaseResource, withPageState } from './base.js';\n\n/** Параметры запроса постов по хэштегу. */\nexport interface HashtagPostsParams extends RequestOptions {\n limit?: number;\n cursor?: string;\n maxPages?: number;\n}\n\n/** Результат глобального поиска. */\nexport interface SearchResult {\n users: UserSummary[];\n hashtags: Hashtag[];\n}\n\n/**\n * Хэштеги.\n *\n * Доступна как `itd.hashtags`.\n */\nexport class HashtagsResource extends BaseResource {\n /**\n * Ищет хэштеги.\n *\n * Без строки запроса возвращает общий список.\n */\n async search(\n query?: string,\n params: { limit?: number } & RequestOptions = {},\n ): Promise<Hashtag[]> {\n const body = await this.http.request({\n method: 'GET',\n path: '/api/hashtags',\n query: { q: query, limit: params.limit },\n ...this.requestOptions(params),\n });\n\n return pickArray<Hashtag>(body, 'hashtags');\n }\n\n /** Загружает трендовые хэштеги. */\n async trending(params: { limit?: number } & RequestOptions = {}): Promise<Hashtag[]> {\n const body = await this.http.request({\n method: 'GET',\n path: '/api/hashtags/trending',\n query: { limit: params.limit },\n ...this.requestOptions(params),\n });\n\n return pickArray<Hashtag>(body, 'hashtags');\n }\n\n /**\n * Загружает страницу постов по хэштегу.\n *\n * @param tag название без решётки; кодируется автоматически, поэтому кириллица\n * и пробелы допустимы\n */\n async posts(tag: string, params: HashtagPostsParams = {}): Promise<Page<Post>> {\n const body = await this.http.request({\n method: 'GET',\n path: `/api/hashtags/${encodePathSegment(tag, 'tag')}/posts`,\n query: { limit: params.limit, cursor: params.cursor },\n ...this.requestOptions(params),\n });\n\n return readCursorPage<Post>(body, 'posts');\n }\n\n /** Перебирает посты по хэштегу. */\n iteratePosts(tag: string, params: HashtagPostsParams = {}): Paginator<Post> {\n const path = `/api/hashtags/${encodePathSegment(tag, 'tag')}/posts`;\n\n return this.paginate<Post>(\n PaginationMode.Cursor,\n async (state) => {\n const body = await this.http.request({\n method: 'GET',\n path,\n query: withPageState({ limit: params.limit }, state),\n ...this.requestOptions(params),\n });\n return readCursorPage<Post>(body, 'posts');\n },\n { ...params, ...(params.cursor ? { start: { cursor: params.cursor } } : {}) },\n );\n }\n}\n\n/**\n * Глобальный поиск.\n *\n * Доступна как `itd.search`.\n */\nexport class SearchResource extends BaseResource {\n /**\n * Ищет пользователей и хэштеги одним запросом.\n *\n * @example\n * ```ts\n * const { users, hashtags } = await itd.search.all('арт');\n * ```\n */\n async all(query: string, options: RequestOptions = {}): Promise<SearchResult> {\n const body = await this.http.request({\n method: 'GET',\n path: '/api/search',\n query: { q: query },\n ...this.requestOptions(options),\n });\n\n return {\n users: pickArray<UserSummary>(body, 'users'),\n hashtags: pickArray<Hashtag>(body, 'hashtags'),\n };\n }\n}\n\n/**\n * Жалобы на контент и пользователей.\n *\n * Доступна как `itd.reports`.\n */\nexport class ReportsResource extends BaseResource {\n /**\n * Отправляет жалобу.\n *\n * Повторная жалоба на тот же объект отклоняется сервером с сообщением\n * «Вы уже отправляли жалобу на этот контент».\n *\n * @example\n * ```ts\n * await itd.reports.create(report.post(postId).reason('spam'));\n * await itd.reports.create({ targetType: 'user', targetId, reason: 'fraud' });\n * ```\n */\n create(input: ReportInput, options: RequestOptions = {}): Promise<Report> {\n const data = resolveReport(input);\n\n return this.http.request<Report>({\n method: 'POST',\n path: '/api/reports',\n body: data,\n ...this.requestOptions(options),\n });\n }\n}\n\n/**\n * Верификация профиля.\n *\n * Доступна как `itd.verification`.\n */\nexport class VerificationResource extends BaseResource {\n /** Загружает статус заявки. Значение `none` означает, что заявка не подавалась. */\n status(options: RequestOptions = {}): Promise<VerificationStatus> {\n return this.http.request<VerificationStatus>({\n method: 'GET',\n path: '/api/verification/status',\n ...this.requestOptions(options),\n });\n }\n\n /** Подаёт заявку на верификацию с видео. */\n submit(videoUrl: string, options: RequestOptions = {}): Promise<unknown> {\n return this.http.request({\n method: 'POST',\n path: '/api/verification/submit',\n body: { videoUrl },\n ...this.requestOptions(options),\n });\n }\n}\n\n/**\n * Подписка и способы оплаты.\n *\n * Доступна как `itd.subscription`.\n */\nexport class SubscriptionResource extends BaseResource {\n /** Загружает состояние подписки и её цену. */\n status(options: RequestOptions = {}): Promise<Subscription> {\n return this.http.request<Subscription>({\n method: 'GET',\n // Завершающий слэш обязателен.\n path: '/api/v1/subscription/',\n ...this.requestOptions(options),\n });\n }\n\n /**\n * Запускает оплату подписки.\n *\n * Форма ответа в документации API не описана, поэтому тип результата не уточняется.\n */\n pay(options: RequestOptions = {}): Promise<unknown> {\n return this.http.request({\n method: 'POST',\n path: '/api/v1/subscription/pay',\n ...this.requestOptions(options),\n });\n }\n\n /** Включает или отключает автопродление. */\n setAutoRenewal(enabled: boolean, options: RequestOptions = {}): Promise<unknown> {\n return this.http.request({\n method: 'POST',\n path: '/api/v1/subscription/auto-renewal',\n body: { enabled },\n ...this.requestOptions(options),\n });\n }\n\n /** Запускает привязку карты. */\n bindCard(options: RequestOptions = {}): Promise<unknown> {\n return this.http.request({\n method: 'POST',\n path: '/api/v1/subscription/bind-card',\n ...this.requestOptions(options),\n });\n }\n\n /** Загружает список способов оплаты. Пустой массив, если карт нет. */\n async methods(options: RequestOptions = {}): Promise<PaymentMethod[]> {\n const body = await this.http.request({\n method: 'GET',\n path: '/api/v1/subscription/methods',\n ...this.requestOptions(options),\n });\n\n return Array.isArray(body) ? (body as PaymentMethod[]) : [];\n }\n\n /** Делает способ оплаты основным. */\n setDefaultMethod(methodId: string, options: RequestOptions = {}): Promise<unknown> {\n return this.http.request({\n method: 'POST',\n path: `/api/v1/subscription/methods/${encodePathSegment(methodId, 'methodId')}/default`,\n ...this.requestOptions(options),\n });\n }\n\n /** Удаляет способ оплаты. */\n removeMethod(methodId: string, options: RequestOptions = {}): Promise<void> {\n return this.http.request<void>({\n method: 'DELETE',\n path: `/api/v1/subscription/methods/${encodePathSegment(methodId, 'methodId')}`,\n ...this.requestOptions(options),\n });\n }\n}\n\n/**\n * Сведения о платформе: изменения, анонсы, баннер события.\n *\n * Доступна как `itd.platform`.\n */\nexport class PlatformResource extends BaseResource {\n /** Загружает журнал изменений. */\n async changelog(options: RequestOptions = {}): Promise<ChangelogEntry[]> {\n const body = await this.http.request({\n method: 'GET',\n path: '/api/platform/changelog',\n ...this.requestOptions(options),\n });\n\n return Array.isArray(body) ? (body as ChangelogEntry[]) : [];\n }\n\n /** Загружает анонсы платформы. */\n async announcements(options: RequestOptions = {}): Promise<Announcement[]> {\n const body = await this.http.request({\n method: 'GET',\n path: '/api/platform/announcements',\n ...this.requestOptions(options),\n });\n\n return pickArray<Announcement>(body, 'announcements');\n }\n\n /** Загружает баннер текущего события — виджет «портал». */\n portal(options: RequestOptions = {}): Promise<Portal> {\n return this.http.request<Portal>({\n method: 'GET',\n path: '/api/v1/portal',\n ...this.requestOptions(options),\n });\n }\n}\n\n/** Запись о времени просмотра поста. */\nexport interface DwellEntry {\n /** Идентификатор поста. */\n postId: string;\n /** Сколько миллисекунд пост был виден. */\n duration: number;\n /** Служебная метка показа из поля `vs` объекта поста. */\n vs?: string;\n}\n\n/** Запись о взаимодействии с контентом. */\nexport interface InteractionEntry {\n /** Тип взаимодействия: `photo_open`, `video_progress` и подобные. */\n type: string;\n /** Значение, смысл которого зависит от типа: доля просмотра, номер кадра. */\n value?: number;\n /** Идентификатор поста. */\n postId?: string;\n /** Идентификатор вложения. */\n attachmentId?: string;\n /** Служебная метка показа. */\n vs?: string;\n}\n\n/**\n * Телеметрия просмотров.\n *\n * @experimental Эндпоинты `/api/v1/i` и `/api/v1/x` нигде не описаны, а схема их полей\n * не проверена на реальных запросах и может измениться без предупреждения.\n *\n * **Библиотека никогда не отправляет телеметрию сама.** Эти методы нужны только тем,\n * кто пишет собственный клиент платформы; всем остальным их вызывать не требуется.\n *\n * Доступна как `itd.telemetry`.\n */\nexport class TelemetryResource extends BaseResource {\n /**\n * Отправляет время просмотра постов.\n *\n * @experimental Имена полей на проводе сжаты (`ai`, `v`, `s`), и их соответствие\n * смыслу **не проверено** на реальных запросах. Может измениться без предупреждения.\n */\n dwell(entries: DwellEntry[], options: RequestOptions = {}): Promise<unknown> {\n return this.http.request({\n method: 'POST',\n path: '/api/v1/i',\n body: {\n items: entries.map((entry) => ({\n ai: entry.postId,\n v: entry.duration,\n ...(entry.vs ? { s: entry.vs } : {}),\n })),\n },\n ...this.requestOptions(options),\n });\n }\n\n /**\n * Отправляет события взаимодействия с контентом.\n *\n * @experimental См. предупреждение у {@link TelemetryResource}.\n */\n interaction(entries: InteractionEntry[], options: RequestOptions = {}): Promise<unknown> {\n return this.http.request({\n method: 'POST',\n path: '/api/v1/x',\n body: {\n items: entries.map((entry) => ({\n t: entry.type,\n ...(entry.value !== undefined ? { v: entry.value } : {}),\n ...(entry.postId ? { ai: entry.postId } : {}),\n ...(entry.attachmentId ? { mi: entry.attachmentId } : {}),\n ...(entry.vs ? { s: entry.vs } : {}),\n })),\n },\n ...this.requestOptions(options),\n });\n }\n}\n","import { type Page, PaginationMode, type Paginator, readOffsetPage } from '../core/pagination.js';\nimport { pickBoolean, pickNumber } from '../core/unwrap.js';\nimport { encodePathSegment } from '../core/url.js';\nimport { normalizeNotification } from '../notifications/normalize.js';\nimport type { Notification, NotificationSettings } from '../types/models.js';\nimport type { RequestOptions } from '../types/options.js';\nimport { BaseResource } from './base.js';\n\n/**\n * Сколько идентификаторов уходит в одном запросе на отметку прочтения.\n *\n * Столько же отправляет сайт итд.com — значит на сервере, скорее всего, есть ограничение.\n */\nconst READ_BATCH_SIZE = 20;\n\n/** Параметры запроса списка уведомлений. */\nexport interface NotificationListParams extends RequestOptions {\n limit?: number;\n /** Смещение от начала списка. */\n offset?: number;\n maxPages?: number;\n}\n\n/** Изменяемые настройки уведомлений. */\nexport type UpdateNotificationSettingsInput = Partial<NotificationSettings>;\n\n/**\n * Читает настройки уведомлений.\n *\n * Сервер отдаёт плоский объект: `enabled`, `sound`, `follows`, `wallPosts`, `likes`,\n * `comments`, `mentions`. Отсутствующая настройка считается включённой — так же\n * ведёт себя сайт итд.com.\n */\nfunction readSettings(body: unknown): NotificationSettings {\n return {\n enabled: pickBoolean(body, 'enabled', true),\n sound: pickBoolean(body, 'sound', true),\n follows: pickBoolean(body, 'follows', true),\n wallPosts: pickBoolean(body, 'wallPosts', true),\n likes: pickBoolean(body, 'likes', true),\n comments: pickBoolean(body, 'comments', true),\n mentions: pickBoolean(body, 'mentions', true),\n };\n}\n\n/**\n * Уведомления: список, счётчик, отметки о прочтении, настройки.\n *\n * Доступна как `itd.notifications`. Все уведомления приведены к единой форме, поэтому\n * объекты отсюда и из потока событий можно складывать в один список.\n */\nexport class NotificationsResource extends BaseResource {\n /**\n * Загружает страницу уведомлений.\n *\n * Пагинация здесь основана на смещении. Сайт итд.com оборачивает смещение в строку\n * и притворяется, что это курсор; библиотека отдаёт честное число.\n *\n * @example\n * ```ts\n * const page = await itd.notifications.list({ limit: 20 });\n * const next = await itd.notifications.list({ limit: 20, offset: page.nextOffset });\n * ```\n */\n list(params: NotificationListParams = {}): Promise<Page<Notification>> {\n return this.#loadPage(params, params.offset ?? 0);\n }\n\n /** Общая загрузка страницы для {@link list} и {@link iterate}. */\n async #loadPage(params: NotificationListParams, offset: number): Promise<Page<Notification>> {\n const body = await this.http.request({\n method: 'GET',\n // Завершающий слэш обязателен: без него сервер отвечает ошибкой.\n path: '/api/notifications/',\n query: { limit: params.limit, offset },\n ...this.requestOptions(params),\n });\n\n const page = readOffsetPage<unknown>(body, 'notifications', offset);\n\n return { ...page, items: page.items.map(normalizeNotification) };\n }\n\n /**\n * Перебирает уведомления.\n *\n * @example\n * ```ts\n * for await (const notification of itd.notifications.iterate()) {\n * console.log(formatNotificationText(notification));\n * }\n * ```\n */\n iterate(params: NotificationListParams = {}): Paginator<Notification> {\n return this.paginate<Notification>(\n PaginationMode.Offset,\n (state) => this.#loadPage(params, state.offset ?? 0),\n { ...params, ...(params.offset !== undefined ? { start: { offset: params.offset } } : {}) },\n );\n }\n\n /** Загружает число непрочитанных уведомлений. */\n async count(options: RequestOptions = {}): Promise<number> {\n const body = await this.http.request({\n method: 'GET',\n path: '/api/notifications/count',\n ...this.requestOptions(options),\n });\n\n return pickNumber(body, 'count', 0);\n }\n\n /**\n * Отмечает уведомление прочитанным.\n *\n * @returns сколько записей отметил сервер\n */\n async markRead(notificationId: string, options: RequestOptions = {}): Promise<number> {\n const body = await this.http.request({\n method: 'POST',\n path: `/api/notifications/${encodePathSegment(notificationId, 'notificationId')}/read`,\n ...this.requestOptions(options),\n });\n\n return pickNumber(body, 'markedCount', 0);\n }\n\n /**\n * Отмечает прочитанными сразу несколько уведомлений.\n *\n * Список автоматически режется на части по 20 идентификаторов — столько же отправляет\n * сайт итд.com, поэтому на сервере вероятен предел. Части уходят последовательно,\n * результат суммируется.\n *\n * @returns сколько записей отметил сервер суммарно\n */\n async markReadBatch(ids: string[], options: RequestOptions = {}): Promise<number> {\n let marked = 0;\n\n for (let index = 0; index < ids.length; index += READ_BATCH_SIZE) {\n const chunk = ids.slice(index, index + READ_BATCH_SIZE);\n\n const body = await this.http.request({\n method: 'POST',\n path: '/api/notifications/read-batch',\n body: { ids: chunk },\n ...this.requestOptions(options),\n });\n\n marked += pickNumber(body, 'markedCount', 0);\n }\n\n return marked;\n }\n\n /** Отмечает прочитанными все уведомления. */\n async markAllRead(options: RequestOptions = {}): Promise<number> {\n const body = await this.http.request({\n method: 'POST',\n path: '/api/notifications/read-all',\n ...this.requestOptions(options),\n });\n\n return pickNumber(body, 'markedCount', 0);\n }\n\n /** Загружает настройки уведомлений. */\n async getSettings(options: RequestOptions = {}): Promise<NotificationSettings> {\n const body = await this.http.request({\n method: 'GET',\n path: '/api/notifications/settings',\n ...this.requestOptions(options),\n });\n\n return readSettings(body);\n }\n\n /**\n * Обновляет настройки уведомлений.\n *\n * Отправляются только изменяемые поля, в том же виде, в каком сервер их возвращает.\n */\n async updateSettings(\n input: UpdateNotificationSettingsInput,\n options: RequestOptions = {},\n ): Promise<NotificationSettings> {\n const payload: Record<string, boolean> = {};\n\n for (const key of [\n 'enabled',\n 'sound',\n 'follows',\n 'wallPosts',\n 'likes',\n 'comments',\n 'mentions',\n ] as const) {\n const value = input[key];\n if (value !== undefined) payload[key] = value;\n }\n\n const body = await this.http.request({\n method: 'PUT',\n path: '/api/notifications/settings',\n body: payload,\n ...this.requestOptions(options),\n });\n\n return readSettings(body);\n }\n}\n","import { type CommentInput, resolveComment } from '../builders/comment.js';\nimport { type PostInput, resolvePost } from '../builders/post.js';\nimport type { HttpClient } from '../core/http.js';\nimport {\n type Page,\n type PageState,\n PaginationMode,\n type Paginator,\n readCursorPage,\n readFlatCursorPage,\n} from '../core/pagination.js';\nimport { pickArray } from '../core/unwrap.js';\nimport { encodePathSegment } from '../core/url.js';\nimport type { CommentSort, FeedTab } from '../types/enums.js';\nimport type {\n Comment,\n LikeResult,\n PinPostResult,\n Poll,\n Post,\n PostStats,\n UserRef,\n} from '../types/models.js';\nimport type { RequestOptions } from '../types/options.js';\nimport type { CreateCommentInput, CreatePostInput, FileInput } from '../types/params.js';\nimport { BaseResource, withPageState } from './base.js';\n\n/** Параметры запроса ленты. */\nexport interface FeedParams extends RequestOptions {\n /** Вкладка ленты. По умолчанию сервер отдаёт популярное. */\n tab?: FeedTab;\n /** Сколько постов на страницу. */\n limit?: number;\n /**\n * Курсор следующей страницы из предыдущего ответа.\n *\n * Передавайте значение как есть: его формат зависит от вкладки и может измениться.\n */\n cursor?: string;\n /** Ограничение числа страниц при переборе. */\n maxPages?: number;\n}\n\n/** Параметры запроса постов пользователя. */\nexport interface UserPostsParams extends RequestOptions {\n limit?: number;\n cursor?: string;\n /** Порядок сортировки. */\n sort?: string;\n /** Закреплённый пост, чтобы сервер поднял его наверх. */\n pinnedPostId?: string;\n maxPages?: number;\n}\n\n/** Параметры запроса комментариев к посту. */\nexport interface CommentsParams extends RequestOptions {\n limit?: number;\n /**\n * Курсор следующей страницы: идентификатор последнего полученного комментария.\n *\n * Передавайте значение из `nextCursor` предыдущего ответа как есть.\n */\n cursor?: string;\n sort?: CommentSort;\n maxPages?: number;\n}\n\n/**\n * Посты: лента, публикация, реакции, репосты, комментарии.\n *\n * Доступна как `itd.posts`.\n */\nexport class PostsResource extends BaseResource {\n readonly #uploadFiles: (files: FileInput[], options?: RequestOptions) => Promise<string[]>;\n\n constructor(\n http: HttpClient,\n deps: { uploadFiles: (files: FileInput[], options?: RequestOptions) => Promise<string[]> },\n ) {\n super(http);\n this.#uploadFiles = deps.uploadFiles;\n }\n\n /**\n * Загружает страницу ленты.\n *\n * @example\n * ```ts\n * const page = await itd.posts.list({ tab: FeedTab.Following, limit: 20 });\n * const next = await itd.posts.list({ tab: FeedTab.Following, cursor: page.nextCursor ?? undefined });\n * ```\n */\n async list(params: FeedParams = {}): Promise<Page<Post>> {\n const body = await this.http.request({\n method: 'GET',\n path: '/api/posts',\n query: { tab: params.tab, limit: params.limit, cursor: params.cursor },\n ...this.requestOptions(params),\n });\n\n return readCursorPage<Post>(body, 'posts');\n }\n\n /**\n * Перебирает ленту, сама подставляя курсоры.\n *\n * @example\n * ```ts\n * for await (const post of itd.posts.iterate({ tab: 'following' })) {\n * console.log(post.author.username, post.content);\n * }\n * ```\n */\n iterate(params: FeedParams = {}): Paginator<Post> {\n return this.paginate<Post>(\n PaginationMode.Cursor,\n async (state: PageState) => {\n const body = await this.http.request({\n method: 'GET',\n path: '/api/posts',\n query: withPageState({ tab: params.tab, limit: params.limit }, state),\n ...this.requestOptions(params),\n });\n return readCursorPage<Post>(body, 'posts');\n },\n { ...params, ...(params.cursor ? { start: { cursor: params.cursor } } : {}) },\n );\n }\n\n /**\n * Публикует пост.\n *\n * Принимает обычный объект, {@link PostBuilder} или функцию-настройщик. Файлы из поля\n * `files` загружаются автоматически, порядок вложений сохраняется.\n *\n * @example\n * ```ts\n * await itd.posts.create({ content: 'привет' });\n * await itd.posts.create((p) => p.content('привет').attach('./photo.jpg'));\n * ```\n */\n async create(input: PostInput, options: RequestOptions = {}): Promise<Post> {\n const data = resolvePost(input);\n const attachmentIds = await this.#collectAttachments(data, options);\n\n return this.http.request<Post>({\n method: 'POST',\n path: '/api/posts',\n body: {\n content: data.content ?? '',\n ...(data.spans ? { spans: data.spans } : {}),\n ...(data.wallRecipientId ? { wallRecipientId: data.wallRecipientId } : {}),\n ...(attachmentIds.length > 0 ? { attachmentIds } : {}),\n ...(data.poll ? { poll: data.poll } : {}),\n },\n ...this.requestOptions(options),\n });\n }\n\n /**\n * Загружает один пост вместе с топовыми комментариями.\n *\n * В отличие от списков, здесь у поста заполнено поле `comments`.\n */\n get(postId: string, options: RequestOptions = {}): Promise<Post> {\n return this.http.request<Post>({\n method: 'GET',\n path: `/api/posts/${encodePathSegment(postId, 'postId')}`,\n ...this.requestOptions(options),\n });\n }\n\n /** Редактирует текст поста. */\n update(\n postId: string,\n input: Pick<CreatePostInput, 'content' | 'spans'>,\n options: RequestOptions = {},\n ): Promise<Post> {\n return this.http.request<Post>({\n method: 'PUT',\n path: `/api/posts/${encodePathSegment(postId, 'postId')}`,\n body: { content: input.content ?? '', ...(input.spans ? { spans: input.spans } : {}) },\n ...this.requestOptions(options),\n });\n }\n\n /** Удаляет пост. Восстановить его можно через {@link restore}. */\n remove(postId: string, options: RequestOptions = {}): Promise<void> {\n return this.http.request<void>({\n method: 'DELETE',\n path: `/api/posts/${encodePathSegment(postId, 'postId')}`,\n ...this.requestOptions(options),\n });\n }\n\n /** Восстанавливает удалённый пост. */\n restore(postId: string, options: RequestOptions = {}): Promise<Post> {\n return this.http.request<Post>({\n method: 'POST',\n path: `/api/posts/${encodePathSegment(postId, 'postId')}/restore`,\n ...this.requestOptions(options),\n });\n }\n\n /** Ставит реакцию на пост. */\n like(postId: string, options: RequestOptions = {}): Promise<LikeResult> {\n return this.http.request<LikeResult>({\n method: 'POST',\n path: `/api/posts/${encodePathSegment(postId, 'postId')}/like`,\n ...this.requestOptions(options),\n });\n }\n\n /** Убирает реакцию с поста. */\n unlike(postId: string, options: RequestOptions = {}): Promise<LikeResult> {\n return this.http.request<LikeResult>({\n method: 'DELETE',\n path: `/api/posts/${encodePathSegment(postId, 'postId')}/like`,\n ...this.requestOptions(options),\n });\n }\n\n /**\n * Делает репост с необязательным комментарием.\n *\n * Вложения к репосту не поддерживаются: сервер их игнорирует, поэтому параметров\n * для файлов здесь нет.\n */\n repost(postId: string, content = '', options: RequestOptions = {}): Promise<Post> {\n return this.http.request<Post>({\n method: 'POST',\n path: `/api/posts/${encodePathSegment(postId, 'postId')}/repost`,\n body: { content },\n ...this.requestOptions(options),\n });\n }\n\n /** Отменяет репост. */\n unrepost(postId: string, options: RequestOptions = {}): Promise<void> {\n return this.http.request<void>({\n method: 'DELETE',\n path: `/api/posts/${encodePathSegment(postId, 'postId')}/repost`,\n ...this.requestOptions(options),\n });\n }\n\n /** Закрепляет пост в профиле. */\n pin(postId: string, options: RequestOptions = {}): Promise<PinPostResult> {\n return this.http.request<PinPostResult>({\n method: 'POST',\n path: `/api/posts/${encodePathSegment(postId, 'postId')}/pin`,\n ...this.requestOptions(options),\n });\n }\n\n /** Открепляет пост. */\n unpin(postId: string, options: RequestOptions = {}): Promise<PinPostResult> {\n return this.http.request<PinPostResult>({\n method: 'DELETE',\n path: `/api/posts/${encodePathSegment(postId, 'postId')}/pin`,\n ...this.requestOptions(options),\n });\n }\n\n /**\n * Голосует в опросе.\n *\n * @param optionIds выбранные варианты; несколько допустимы только при `multipleChoice`\n */\n vote(postId: string, optionIds: string[], options: RequestOptions = {}): Promise<Poll> {\n return this.http.request<Poll>({\n method: 'POST',\n path: `/api/posts/${encodePathSegment(postId, 'postId')}/poll/vote`,\n body: { optionIds },\n ...this.requestOptions(options),\n });\n }\n\n /** Запрашивает счётчики сразу для нескольких постов. */\n async stats(ids: string[], options: RequestOptions = {}): Promise<PostStats[]> {\n const body = await this.http.request({\n method: 'POST',\n path: '/api/posts/stats',\n body: { ids },\n ...this.requestOptions(options),\n });\n\n return pickArray<PostStats>(body, 'posts');\n }\n\n /**\n * Загружает страницу стены пользователя.\n *\n * Это **не только его собственные посты**: сюда попадают и записи, которые другие\n * оставили на его стене — у них `author` чужой, а `wallRecipient` указывает на владельца\n * стены. Поэтому число записей обычно больше, чем `postsCount` из профиля; чтобы\n * получить только авторские посты, отфильтруйте по `post.author.id`.\n *\n * Принимает и UUID, и имя пользователя.\n */\n async byUser(user: UserRef, params: UserPostsParams = {}): Promise<Page<Post>> {\n const body = await this.http.request({\n method: 'GET',\n path: `/api/posts/user/${encodePathSegment(user, 'user')}`,\n query: {\n limit: params.limit,\n cursor: params.cursor,\n sort: params.sort,\n pinnedPostId: params.pinnedPostId,\n },\n ...this.requestOptions(params),\n });\n\n return readCursorPage<Post>(body, 'posts');\n }\n\n /** Перебирает стену пользователя. Что именно в неё входит — см. {@link byUser}. */\n iterateByUser(user: UserRef, params: UserPostsParams = {}): Paginator<Post> {\n const path = `/api/posts/user/${encodePathSegment(user, 'user')}`;\n\n return this.paginate<Post>(\n PaginationMode.Cursor,\n async (state) => {\n const body = await this.http.request({\n method: 'GET',\n path,\n query: withPageState(\n { limit: params.limit, sort: params.sort, pinnedPostId: params.pinnedPostId },\n state,\n ),\n ...this.requestOptions(params),\n });\n return readCursorPage<Post>(body, 'posts');\n },\n { ...params, ...(params.cursor ? { start: { cursor: params.cursor } } : {}) },\n );\n }\n\n /** Загружает страницу постов, которые пользователь отметил реакцией. */\n async likedByUser(user: UserRef, params: UserPostsParams = {}): Promise<Page<Post>> {\n const body = await this.http.request({\n method: 'GET',\n path: `/api/posts/user/${encodePathSegment(user, 'user')}/liked`,\n query: { limit: params.limit, cursor: params.cursor },\n ...this.requestOptions(params),\n });\n\n return readCursorPage<Post>(body, 'posts');\n }\n\n /** Перебирает посты, которые пользователь отметил реакцией. */\n iterateLikedByUser(user: UserRef, params: UserPostsParams = {}): Paginator<Post> {\n const path = `/api/posts/user/${encodePathSegment(user, 'user')}/liked`;\n\n return this.paginate<Post>(\n PaginationMode.Cursor,\n async (state) => {\n const body = await this.http.request({\n method: 'GET',\n path,\n query: withPageState({ limit: params.limit }, state),\n ...this.requestOptions(params),\n });\n return readCursorPage<Post>(body, 'posts');\n },\n { ...params, ...(params.cursor ? { start: { cursor: params.cursor } } : {}) },\n );\n }\n\n /**\n * Загружает страницу комментариев к посту.\n *\n * У этого эндпоинта курсор и признак продолжения лежат рядом со списком, а не внутри\n * объекта `pagination`, как у остальных, — разница скрыта внутри.\n */\n async comments(postId: string, params: CommentsParams = {}): Promise<Page<Comment>> {\n const body = await this.http.request({\n method: 'GET',\n path: `/api/posts/${encodePathSegment(postId, 'postId')}/comments`,\n query: { limit: params.limit, cursor: params.cursor, sort: params.sort },\n ...this.requestOptions(params),\n });\n\n return readFlatCursorPage<Comment>(body, 'comments');\n }\n\n /** Перебирает комментарии к посту. */\n iterateComments(postId: string, params: CommentsParams = {}): Paginator<Comment> {\n const path = `/api/posts/${encodePathSegment(postId, 'postId')}/comments`;\n\n return this.paginate<Comment>(\n PaginationMode.Cursor,\n async (state) => {\n const body = await this.http.request({\n method: 'GET',\n path,\n query: withPageState({ limit: params.limit, sort: params.sort }, state),\n ...this.requestOptions(params),\n });\n return readFlatCursorPage<Comment>(body, 'comments');\n },\n { ...params, ...(params.cursor ? { start: { cursor: params.cursor } } : {}) },\n );\n }\n\n /**\n * Комментирует пост.\n *\n * @example\n * ```ts\n * await itd.posts.comment(postId, 'согласен');\n * await itd.posts.comment(postId, (c) => c.content('смотри').attach('./meme.png'));\n * ```\n */\n async comment(\n postId: string,\n input: CommentInput | string,\n options: RequestOptions = {},\n ): Promise<Comment> {\n const data = resolveComment(typeof input === 'string' ? { content: input } : input);\n const attachmentIds = await this.#collectAttachments(data, options);\n\n return this.http.request<Comment>({\n method: 'POST',\n path: `/api/posts/${encodePathSegment(postId, 'postId')}/comments`,\n body: { content: data.content ?? '', attachmentIds },\n ...this.requestOptions(options),\n });\n }\n\n /**\n * Отправляет голосовой комментарий.\n *\n * Текста у такого комментария нет: сервер ждёт пустой `content` и одно аудиовложение\n * в формате `audio/ogg`.\n *\n * @example\n * ```ts\n * await itd.posts.voiceComment(postId, './answer.ogg');\n * ```\n */\n voiceComment(postId: string, audio: FileInput, options: RequestOptions = {}): Promise<Comment> {\n return this.comment(postId, { content: '', files: [audio] }, options);\n }\n\n /** Загружает файлы из входных данных и объединяет их с уже готовыми идентификаторами. */\n async #collectAttachments(\n data: CreatePostInput | CreateCommentInput,\n options: RequestOptions,\n ): Promise<string[]> {\n const existing = data.attachmentIds ?? [];\n const files = data.files ?? [];\n\n if (files.length === 0) return existing;\n\n const uploaded = await this.#uploadFiles(files, options);\n return [...existing, ...uploaded];\n }\n}\n","import {\n type Page,\n type PageState,\n PaginationMode,\n type Paginator,\n readPagedPage,\n} from '../core/pagination.js';\nimport { pickArray, pickBoolean, pickString } from '../core/unwrap.js';\nimport { encodePathSegment } from '../core/url.js';\nimport type {\n Clan,\n FollowResult,\n MyProfile,\n PinsResult,\n PrivacySettings,\n PublicProfile,\n UserId,\n UserRef,\n UserSummary,\n} from '../types/models.js';\nimport type { RequestOptions } from '../types/options.js';\nimport { BaseResource, withPageState } from './base.js';\n\n/**\n * Параметры списков пользователей.\n *\n * ⚠️ Списки подписчиков, подписок и заблокированных на сервере **не листаются**:\n * `page` он игнорирует, а `limit` зажимает на 20. Подробности — в {@link UsersResource.followers}.\n */\nexport interface UserListParams extends RequestOptions {\n /** Сколько записей вернуть. Значения больше 20 сервер молча уменьшает до 20. */\n limit?: number;\n /** Номер страницы. Сервер его игнорирует — оставлен на случай, если пагинацию починят. */\n page?: number;\n maxPages?: number;\n}\n\n/** Изменяемые поля своего профиля. */\nexport interface UpdateProfileInput {\n displayName?: string;\n username?: string;\n /** Эмодзи-аватар: символ клана, а не адрес картинки. */\n avatar?: string;\n bio?: string;\n /** Адрес изображения-шапки. */\n banner?: string;\n}\n\n/** Изменяемые настройки приватности. */\nexport type UpdatePrivacyInput = Partial<PrivacySettings>;\n\n/**\n * Пользователи: профили, подписки, блокировки, приватность.\n *\n * Доступна как `itd.users`.\n */\nexport class UsersResource extends BaseResource {\n /** Загружает свой профиль — с подпиской и признаком подтверждённого телефона. */\n me(options: RequestOptions = {}): Promise<MyProfile> {\n return this.http.request<MyProfile>({\n method: 'GET',\n path: '/api/users/me',\n ...this.requestOptions(options),\n });\n }\n\n /** Обновляет свой профиль. Передавайте только изменяемые поля. */\n updateMe(input: UpdateProfileInput, options: RequestOptions = {}): Promise<MyProfile> {\n return this.http.request<MyProfile>({\n method: 'PUT',\n path: '/api/users/me',\n body: input,\n ...this.requestOptions(options),\n });\n }\n\n /** Деактивирует аккаунт. Вернуть его можно через {@link restore}. */\n deactivate(options: RequestOptions = {}): Promise<void> {\n return this.http.request<void>({\n method: 'DELETE',\n path: '/api/users/me',\n ...this.requestOptions(options),\n });\n }\n\n /** Восстанавливает деактивированный аккаунт. */\n restore(options: RequestOptions = {}): Promise<void> {\n return this.http.request<void>({\n method: 'POST',\n path: '/api/users/me/restore',\n ...this.requestOptions(options),\n });\n }\n\n /** Создаёт профиль после регистрации. */\n createProfile(\n input: { username: string; displayName: string; avatar?: string },\n options: RequestOptions = {},\n ): Promise<MyProfile> {\n return this.http.request<MyProfile>({\n method: 'POST',\n path: '/api/users/profile',\n body: input,\n ...this.requestOptions(options),\n });\n }\n\n /**\n * Загружает профиль пользователя.\n *\n * @param user UUID **или** имя пользователя — подходит и то, и другое\n *\n * @example\n * ```ts\n * const profile = await itd.users.get('durov');\n * await itd.posts.create({ content: 'привет', wallRecipientId: profile.id });\n * ```\n */\n get(user: UserRef, options: RequestOptions = {}): Promise<PublicProfile> {\n return this.http.request<PublicProfile>({\n method: 'GET',\n path: `/api/users/${encodePathSegment(user, 'user')}`,\n ...this.requestOptions(options),\n });\n }\n\n /** Проверяет, свободно ли имя пользователя. */\n async checkUsername(username: string, options: RequestOptions = {}): Promise<boolean> {\n const body = await this.http.request({\n method: 'GET',\n path: '/api/users/check-username',\n query: { username },\n ...this.requestOptions(options),\n });\n\n return pickBoolean(body, 'available');\n }\n\n /** Ищет пользователей по строке запроса. */\n async search(\n query: string,\n params: { limit?: number } & RequestOptions = {},\n ): Promise<UserSummary[]> {\n const body = await this.http.request({\n method: 'GET',\n path: '/api/users/search',\n query: { q: query, limit: params.limit },\n ...this.requestOptions(params),\n });\n\n return pickArray<UserSummary>(body, 'users');\n }\n\n /** Загружает рекомендации, на кого подписаться. */\n async whoToFollow(options: RequestOptions = {}): Promise<UserSummary[]> {\n const body = await this.http.request({\n method: 'GET',\n path: '/api/users/suggestions/who-to-follow',\n ...this.requestOptions(options),\n });\n\n return pickArray<UserSummary>(body, 'users');\n }\n\n /** Загружает рейтинг кланов. */\n async topClans(options: RequestOptions = {}): Promise<Clan[]> {\n const body = await this.http.request({\n method: 'GET',\n path: '/api/users/stats/top-clans',\n ...this.requestOptions(options),\n });\n\n return pickArray<Clan>(body, 'clans');\n }\n\n /**\n * Подписывается на пользователя.\n *\n * У закрытого профиля вместо подписки отправляется заявка — это видно по полю `status`.\n */\n follow(user: UserRef, options: RequestOptions = {}): Promise<FollowResult> {\n return this.http.request<FollowResult>({\n method: 'POST',\n path: `/api/users/${encodePathSegment(user, 'user')}/follow`,\n body: {},\n ...this.requestOptions(options),\n });\n }\n\n /** Отписывается от пользователя. */\n unfollow(user: UserRef, options: RequestOptions = {}): Promise<void> {\n return this.http.request<void>({\n method: 'DELETE',\n path: `/api/users/${encodePathSegment(user, 'user')}/follow`,\n ...this.requestOptions(options),\n });\n }\n\n /**\n * Загружает подписчиков пользователя.\n *\n * ⚠️ **Сервер этот список не листает.** Возвращаются первые 20 записей и только они:\n * параметр `page` игнорируется (любая страница отдаёт те же записи и `pagination.page: 1`),\n * `limit` больше 20 молча уменьшается, а `hasMore` всегда `false`. Последнее честно —\n * получить продолжение нечем.\n *\n * Числу `total` доверять тоже не стоит: оно расходится с `followersCount` из профиля —\n * на проверенных аккаунтах занижено примерно на 1–4%.\n */\n followers(user: UserRef, params: UserListParams = {}): Promise<Page<UserSummary>> {\n return this.#userPage(`/api/users/${encodePathSegment(user, 'user')}/followers`, params);\n }\n\n /**\n * Перебирает подписчиков.\n *\n * ⚠️ Перебор закончится после первых 20 записей: сервер список не листает —\n * см. {@link followers}. Метод оставлен на случай, если пагинацию починят.\n */\n iterateFollowers(user: UserRef, params: UserListParams = {}): Paginator<UserSummary> {\n return this.#userPaginator(`/api/users/${encodePathSegment(user, 'user')}/followers`, params);\n }\n\n /** Загружает подписки пользователя. Ограничения те же, что у {@link followers}. */\n following(user: UserRef, params: UserListParams = {}): Promise<Page<UserSummary>> {\n return this.#userPage(`/api/users/${encodePathSegment(user, 'user')}/following`, params);\n }\n\n /** Перебирает подписки. Закончится после первых 20 записей — см. {@link followers}. */\n iterateFollowing(user: UserRef, params: UserListParams = {}): Paginator<UserSummary> {\n return this.#userPaginator(`/api/users/${encodePathSegment(user, 'user')}/following`, params);\n }\n\n /**\n * Проверяет, подписаны ли вы, сразу для нескольких пользователей.\n *\n * @returns объект «идентификатор пользователя → подписаны ли вы»\n *\n * @example\n * ```ts\n * const statuses = await itd.users.followStatus([userA, userB]);\n * // { 'b89dee4f-…': true, '35ea3059-…': false }\n * ```\n */\n followStatus(userIds: UserId[], options: RequestOptions = {}): Promise<Record<string, boolean>> {\n return this.http.request<Record<string, boolean>>({\n method: 'POST',\n path: '/api/users/follow-status',\n body: { userIds },\n ...this.requestOptions(options),\n });\n }\n\n /** Блокирует пользователя. */\n block(user: UserRef, options: RequestOptions = {}): Promise<void> {\n return this.http.request<void>({\n method: 'POST',\n path: `/api/users/${encodePathSegment(user, 'user')}/block`,\n body: {},\n ...this.requestOptions(options),\n });\n }\n\n /** Снимает блокировку. */\n unblock(user: UserRef, options: RequestOptions = {}): Promise<void> {\n return this.http.request<void>({\n method: 'DELETE',\n path: `/api/users/${encodePathSegment(user, 'user')}/block`,\n ...this.requestOptions(options),\n });\n }\n\n /** Загружает заблокированных пользователей. Ограничения те же, что у {@link followers}. */\n blocked(params: UserListParams = {}): Promise<Page<UserSummary>> {\n return this.#userPage('/api/users/me/blocked', params);\n }\n\n /** Перебирает заблокированных. Закончится после первых 20 записей — см. {@link followers}. */\n iterateBlocked(params: UserListParams = {}): Paginator<UserSummary> {\n return this.#userPaginator('/api/users/me/blocked', params);\n }\n\n /** Загружает настройки приватности. */\n getPrivacy(options: RequestOptions = {}): Promise<PrivacySettings> {\n return this.http.request<PrivacySettings>({\n method: 'GET',\n path: '/api/users/me/privacy',\n ...this.requestOptions(options),\n });\n }\n\n /** Обновляет настройки приватности. Передавайте только изменяемые поля. */\n updatePrivacy(input: UpdatePrivacyInput, options: RequestOptions = {}): Promise<PrivacySettings> {\n return this.http.request<PrivacySettings>({\n method: 'PUT',\n path: '/api/users/me/privacy',\n body: input,\n ...this.requestOptions(options),\n });\n }\n\n /**\n * Загружает значки профиля и выбранный из них.\n *\n * `activePin` — строка-идентификатор, а не объект.\n */\n async pins(options: RequestOptions = {}): Promise<PinsResult> {\n const body = await this.http.request({\n method: 'GET',\n path: '/api/users/me/pins',\n ...this.requestOptions(options),\n });\n\n return {\n pins: pickArray(body, 'pins'),\n // Сервер отдаёт здесь строку-идентификатор, а не объект значка.\n activePin: pickString(body, 'activePin') ?? null,\n };\n }\n\n /** Выбирает активный значок профиля. */\n setPin(slug: string, options: RequestOptions = {}): Promise<void> {\n return this.http.request<void>({\n method: 'PUT',\n path: '/api/users/me/pin',\n body: { slug },\n ...this.requestOptions(options),\n });\n }\n\n /** Снимает активный значок. */\n removePin(options: RequestOptions = {}): Promise<void> {\n return this.http.request<void>({\n method: 'DELETE',\n path: '/api/users/me/pin',\n ...this.requestOptions(options),\n });\n }\n\n /**\n * Загружает одну страницу списка пользователей.\n *\n * Имена полей перечислены с запасом: списки подписчиков и заблокированных приходят\n * под `users`, но альтернативное имя ничего не стоит и спасает, если эндпоинт назовёт\n * список по-своему.\n *\n * `page` уходит в запрос, хотя сервер его сейчас не читает (см. {@link followers}):\n * когда пагинацию починят, работать начнёт само.\n */\n async #loadUserPage(\n path: string,\n params: UserListParams,\n state: PageState,\n ): Promise<Page<UserSummary>> {\n const body = await this.http.request({\n method: 'GET',\n path,\n query: withPageState({ limit: params.limit }, state),\n ...this.requestOptions(params),\n });\n\n return readPagedPage<UserSummary>(body, 'users', 'followers', 'following', 'blocked');\n }\n\n #userPage(path: string, params: UserListParams): Promise<Page<UserSummary>> {\n return this.#loadUserPage(path, params, {\n ...(params.page !== undefined ? { page: params.page } : {}),\n });\n }\n\n #userPaginator(path: string, params: UserListParams): Paginator<UserSummary> {\n return this.paginate<UserSummary>(\n PaginationMode.Page,\n (state) => this.#loadUserPage(path, params, state),\n // Без `start` перебор начинался бы с первой страницы, молча игнорируя `page`.\n { ...params, ...(params.page !== undefined ? { start: { page: params.page } } : {}) },\n );\n }\n}\n","import { type AuthEvents, AuthManager } from './core/auth.js';\nimport { type ResolvedConfig, resolveConfig } from './core/config.js';\nimport { CookieJar } from './core/cookies.js';\nimport type { Listener, Unsubscribe } from './core/emitter.js';\nimport { isItdRateLimitError } from './core/errors.js';\nimport { HttpClient } from './core/http.js';\nimport { type ItdPlugin, PluginRegistry } from './core/plugins.js';\nimport { RequestQueue } from './core/rate-limit.js';\nimport { createRetryScheduler } from './core/retry.js';\nimport type { ItdSession } from './core/storage.js';\nimport { ItdRealtime, type RealtimeOptions } from './realtime/stream.js';\nimport { AuthResource } from './resources/auth.js';\nimport { CommentsResource } from './resources/comments.js';\nimport { type FileReader, FilesResource } from './resources/files.js';\nimport {\n HashtagsResource,\n PlatformResource,\n ReportsResource,\n SearchResource,\n SubscriptionResource,\n TelemetryResource,\n VerificationResource,\n} from './resources/misc.js';\nimport { NotificationsResource } from './resources/notifications.js';\nimport { PostsResource } from './resources/posts.js';\nimport { UsersResource } from './resources/users.js';\nimport type { ItdClientOptions, RawRequestOptions, RequestOptions } from './types/options.js';\nimport type { FileInput } from './types/params.js';\n\n/**\n * Клиент API итд.com.\n *\n * Методы сгруппированы по разделам: `itd.posts`, `itd.users`, `itd.comments`, `itd.auth`,\n * `itd.files`. Авторизация, обновление токена, повторы и очередь запросов работают сами.\n *\n * @example Готовый токен — для разового вызова\n * ```ts\n * const itd = new ItdClient({ auth: '<accessToken>' });\n * const me = await itd.users.me();\n * ```\n *\n * @example Полноценная сессия для бота\n * ```ts\n * import { ItdClient } from 'itd-api';\n * import { FileTokenStorage } from 'itd-api/node';\n *\n * const itd = new ItdClient({\n * // `auth` не обязателен: когда хранилище уже содержит сессию, токен берётся оттуда,\n * // а истёкший продлевается сам. Здесь он нужен на первый запуск.\n * // Вход по паролю требует токена капчи — см. AuthInput и TURNSTILE_SITE_KEY.\n * auth: { email, password, getTurnstileToken },\n * storage: new FileTokenStorage('./.itd-session.json'),\n * rateLimit: { concurrency: 4, rps: 8 },\n * });\n *\n * for await (const post of itd.posts.iterate({ tab: 'following' })) {\n * if (!post.isLiked) await itd.posts.like(post.id);\n * }\n * ```\n */\nexport class ItdClient {\n readonly #config: ResolvedConfig;\n readonly #http: HttpClient;\n readonly #authManager: AuthManager;\n readonly #jar: CookieJar;\n readonly #queue: RequestQueue | undefined;\n readonly #plugins = new PluginRegistry();\n\n /** Авторизация, сессии и пароли. */\n readonly auth: AuthResource;\n /** Профили, подписки, блокировки, приватность. */\n readonly users: UsersResource;\n /** Лента, публикация, реакции, репосты, комментарии к постам. */\n readonly posts: PostsResource;\n /** Ответы на комментарии и действия над ними. */\n readonly comments: CommentsResource;\n /** Загрузка файлов и медиа. */\n readonly files: FilesResource;\n /** Уведомления: список, счётчик, отметки о прочтении, настройки. */\n readonly notifications: NotificationsResource;\n /** Хэштеги и посты по ним. */\n readonly hashtags: HashtagsResource;\n /** Глобальный поиск по пользователям и хэштегам. */\n readonly search: SearchResource;\n /** Жалобы на контент и пользователей. */\n readonly reports: ReportsResource;\n /** Верификация профиля. */\n readonly verification: VerificationResource;\n /** Подписка и способы оплаты. */\n readonly subscription: SubscriptionResource;\n /** Сведения о платформе: изменения, анонсы, баннер события. */\n readonly platform: PlatformResource;\n /**\n * Телеметрия просмотров.\n *\n * @experimental Недокументированные эндпоинты. Библиотека никогда не отправляет их сама.\n */\n readonly telemetry: TelemetryResource;\n\n constructor(options: ItdClientOptions = {}) {\n this.#config = resolveConfig(options);\n this.#jar = new CookieJar();\n this.#http = new HttpClient(this.#config);\n this.#authManager = new AuthManager(this.#config, this.#http, this.#jar);\n\n this.#queue = this.#config.rateLimit ? new RequestQueue(this.#config.rateLimit) : undefined;\n\n // Реестр пуст и остаётся пустым, пока не вызовут `use()`: до этого момента запрос\n // идёт ровно тем же путём, что и раньше.\n this.#http.usePlugins(this.#plugins);\n\n this.#http.setCollaborators({\n getAuthHeaders: () => this.#authManager.getAuthHeaders(),\n getDeviceId: () => this.#authManager.getDeviceId(),\n onUnauthorized: () => this.#authManager.onUnauthorized(),\n getCookieHeader: (url) => this.#jar.getHeader(url),\n saveCookies: (url, response) => this.#jar.setFromResponse(url, response),\n ...(this.#queue ? { schedule: this.#queue.schedule.bind(this.#queue) } : {}),\n // Планировщик нужен, даже когда обычные повторы выключены: лимит частоты\n // живёт по своим правилам и настраивается отдельно, в `rateLimit`.\n ...(this.#config.retry || this.#config.rateLimit\n ? { nextRetryDelay: this.#createRetryScheduler() }\n : {}),\n ...(this.#queue && this.#config.rateLimit?.respectHeaders\n ? { onRateLimit: this.#throttleByHeaders.bind(this) }\n : {}),\n });\n\n this.files = new FilesResource(this.#http);\n\n const uploadFiles = (files: FileInput[], requestOptions?: RequestOptions) =>\n this.files.uploadMany(files, requestOptions ?? {});\n\n this.auth = new AuthResource(this.#http, { auth: this.#authManager });\n this.users = new UsersResource(this.#http);\n this.posts = new PostsResource(this.#http, { uploadFiles });\n this.comments = new CommentsResource(this.#http, { uploadFiles });\n this.notifications = new NotificationsResource(this.#http);\n this.hashtags = new HashtagsResource(this.#http);\n this.search = new SearchResource(this.#http);\n this.reports = new ReportsResource(this.#http);\n this.verification = new VerificationResource(this.#http);\n this.subscription = new SubscriptionResource(this.#http);\n this.platform = new PlatformResource(this.#http);\n this.telemetry = new TelemetryResource(this.#http);\n }\n\n /** Базовый URL, к которому обращается клиент. */\n get baseUrl(): string {\n return this.#config.baseUrl;\n }\n\n /**\n * Выполняет произвольный запрос к API.\n *\n * Запасной путь для случаев, когда нужного метода ещё нет или ответ сервера разошёлся\n * с документацией. Проходит через ту же авторизацию, очередь и обработку ошибок.\n *\n * @example\n * ```ts\n * const raw = await itd.request({ method: 'GET', path: '/api/posts', raw: true });\n * ```\n */\n request<T = unknown>(options: RawRequestOptions): Promise<T> {\n return this.#http.request<T>(options);\n }\n\n /**\n * Подключает плагин.\n *\n * Плагин работает на уровне транспорта: видит запрос до отправки и разобранный ответ,\n * поэтому одна обёртка охватывает сразу все методы клиента. Подключать можно в любой\n * момент, но обычно это делают сразу после создания клиента.\n *\n * @throws {ItdConfigError} если плагин задан неверно или уже подключён\n *\n * @example\n * ```ts\n * import { crypt } from 'itd-api-crypto';\n *\n * itd.use(crypt());\n * await itd.posts.create({ content: 'секрет' }, { encrypt: 'invis' });\n * ```\n */\n use(plugin: ItdPlugin): this {\n this.#plugins.add(plugin, { baseUrl: this.#config.baseUrl, logger: this.#config.logger });\n return this;\n }\n\n /**\n * Подписывается на события авторизации.\n *\n * Полезно, чтобы сохранять сессию во внешнее хранилище или узнавать, что вход\n * окончательно потерян.\n *\n * @returns функция отписки\n *\n * @example\n * ```ts\n * itd.on('tokens', ({ accessToken }) => cache.set('itd', accessToken));\n * itd.on('authError', () => notifyUser('Сессия истекла, войдите заново'));\n * ```\n */\n on<K extends keyof AuthEvents>(event: K, listener: Listener<AuthEvents[K]>): Unsubscribe {\n return this.#authManager.on(event, listener);\n }\n\n /**\n * Создаёт поток уведомлений в реальном времени.\n *\n * Каждый вызов даёт новый независимый поток; обычно он нужен один на приложение.\n * Соединение поднимается методом `connect()` и держится само.\n *\n * @example\n * ```ts\n * const stream = itd.realtime();\n *\n * stream.on('notification', ({ notification }) => {\n * console.log(formatNotificationText(notification));\n * });\n * stream.on('unreadCount', (count) => setBadge(count));\n *\n * await stream.connect();\n * ```\n */\n realtime(options: RealtimeOptions = {}): ItdRealtime {\n return new ItdRealtime(\n {\n baseUrl: this.#config.baseUrl,\n fetch: this.#config.fetch,\n getToken: () => this.#authManager.getAccessToken(),\n refresh: () => this.#authManager.onUnauthorized(),\n fetchUnreadCount: () => this.notifications.count(),\n logger: this.#config.logger,\n },\n options,\n );\n }\n\n /** Текущая сессия целиком — чтобы сохранить её самостоятельно. */\n getSession(): Promise<ItdSession | null> {\n return this.#authManager.getSession();\n }\n\n /** Восстанавливает сохранённую сессию, включая cookie. */\n setSession(session: ItdSession): Promise<void> {\n return this.#authManager.setSession(session);\n }\n\n /**\n * Подключает чтение файлов с диска.\n *\n * Вызывается из `itd-api/node`; напрямую обычно не нужно.\n *\n * @internal\n */\n setFileReader(readFile: FileReader): void {\n this.files.setFileReader(readFile);\n }\n\n /**\n * Придерживает очередь, когда лимит сервера исчерпан.\n *\n * Сервер сообщает остаток в заголовке `x-ratelimit-remaining`. Как только тот доходит\n * до нуля, очередь встаёт на первую паузу лестницы — короткую, потому что окно могло\n * почти истечь. Если оно ещё действует, следующий запрос получит `429`, и дальше\n * лестницу отработает планировщик повторов.\n *\n * Смысл этой паузы прежде всего в том, чтобы при работе в несколько потоков остальные\n * запросы не улетели в стену все разом.\n */\n #throttleByHeaders(limit: number | undefined, remaining: number | undefined): void {\n if (remaining === undefined || remaining > 0) return;\n\n const first = this.#config.rateLimit?.retryDelays[0];\n if (first === undefined) return;\n\n this.#queue?.pause(first);\n this.#config.logger?.debug(\n `лимит сервера исчерпан (${remaining} из ${limit ?? '?'}), очередь ждёт ${first} мс`,\n );\n }\n\n /**\n * Собирает планировщик повторов и связывает его с очередью.\n *\n * Ответ `429` обрабатывается отдельно от прочих ошибок. Причина в том, что сервер\n * не присылает `Retry-After` и не сообщает время сброса окна: экспоненциальный откат\n * в сотни миллисекунд здесь бесполезен, а окно измеряется десятками секунд. Вместо\n * расчёта берётся лестница пауз `rateLimit.retryDelays`, и она не зависит\n * от `retry.attempts`, у которого совсем другая задача.\n *\n * Пауза накладывается на всю очередь: иначе остальные запросы продолжат добивать API,\n * пока первый ждёт.\n */\n #createRetryScheduler() {\n const retry = this.#config.retry;\n const scheduler = retry ? createRetryScheduler(retry) : undefined;\n const queue = this.#queue;\n const delays = this.#config.rateLimit?.retryDelays ?? [];\n\n return (error: unknown, attempt: number, method: string): number | undefined => {\n if (isItdRateLimitError(error)) {\n // Пауза, названная сервером, важнее нашей лестницы — но он её не присылает.\n const wait = error.retryAfter ?? delays[attempt - 1];\n\n // Лестница закончилась: дальше ждать вслепую бессмысленно, отдаём ошибку.\n if (wait === undefined) return undefined;\n\n queue?.pause(wait);\n this.#config.logger?.debug(`лимит частоты, попытка ${attempt + 1} через ${wait} мс`);\n\n return wait;\n }\n\n return scheduler?.(error, attempt, method);\n };\n }\n}\n\n/**\n * Создаёт клиент API итд.com.\n *\n * То же, что `new ItdClient(options)`, — для тех, кому привычнее фабрика.\n *\n * @example\n * ```ts\n * const itd = createClient({ auth: token });\n * ```\n */\nexport function createClient(options: ItdClientOptions = {}): ItdClient {\n return new ItdClient(options);\n}\n","import { NotificationType } from '../types/enums.js';\nimport type { Notification } from '../types/models.js';\n\n/** Имя, которое подставляется, если участник неизвестен. */\nconst UNKNOWN_ACTOR = 'Пользователь';\n\n/** Текст, который подставляется для неизвестного типа уведомления. */\nconst FALLBACK_TEXT = 'Новое уведомление';\n\n/**\n * Шаблоны текстов уведомлений.\n *\n * Для каждого типа задано две формы: для одного участника и для схлопнутого уведомления,\n * где действие совершили несколько человек.\n */\nconst TEMPLATES: Readonly<\n Record<string, { one: (name: string) => string; many: (name: string, others: number) => string }>\n> = Object.freeze({\n [NotificationType.Follow]: {\n one: (name) => `${name} подписался(-ась) на вас`,\n many: (name, others) => `${name} и ещё ${others} подписались на вас`,\n },\n [NotificationType.FollowRequest]: {\n one: (name) => `${name} хочет подписаться на вас`,\n many: (name, others) => `${name} и ещё ${others} хотят подписаться на вас`,\n },\n [NotificationType.FollowAccepted]: {\n one: (name) => `${name} принял(а) вашу заявку`,\n many: (name, others) => `${name} и ещё ${others} приняли вашу заявку`,\n },\n [NotificationType.PostReaction]: {\n one: (name) => `${name} оценил(а) ваш пост`,\n many: (name, others) => `${name} и ещё ${others} оценили ваш пост`,\n },\n [NotificationType.PostComment]: {\n one: (name) => `${name} прокомментировал(а) ваш пост`,\n many: (name, others) => `${name} и ещё ${others} прокомментировали ваш пост`,\n },\n [NotificationType.PostRepost]: {\n one: (name) => `${name} сделал(а) репост`,\n many: (name, others) => `${name} и ещё ${others} сделали репост`,\n },\n [NotificationType.CommentReaction]: {\n one: (name) => `${name} оценил(а) ваш комментарий`,\n many: (name, others) => `${name} и ещё ${others} оценили ваш комментарий`,\n },\n [NotificationType.CommentReply]: {\n one: (name) => `${name} ответил(а) на ваш комментарий`,\n many: (name, others) => `${name} и ещё ${others} ответили на ваш комментарий`,\n },\n [NotificationType.PostMention]: {\n one: (name) => `${name} упомянул(а) вас в посте`,\n many: (name, others) => `${name} и ещё ${others} упомянули вас в посте`,\n },\n [NotificationType.CommentMention]: {\n one: (name) => `${name} упомянул(а) вас в комментарии`,\n many: (name, others) => `${name} и ещё ${others} упомянули вас в комментарии`,\n },\n [NotificationType.WallPost]: {\n one: (name) => `${name} написал(а) на вашей стене`,\n many: (name, others) => `${name} и ещё ${others} написали на вашей стене`,\n },\n [NotificationType.VerificationApproved]: {\n one: () => 'Ваша заявка на верификацию одобрена',\n many: () => 'Ваша заявка на верификацию одобрена',\n },\n [NotificationType.VerificationRejected]: {\n one: () => 'Ваша заявка на верификацию отклонена',\n many: () => 'Ваша заявка на верификацию отклонена',\n },\n});\n\n/**\n * Собирает текст уведомления на русском.\n *\n * Повторяет формулировки сайта итд.com. Для неизвестного типа возвращает\n * «Новое уведомление» — библиотека не выдумывает текст, которого нет.\n *\n * @example\n * ```ts\n * formatNotificationText(notification);\n * // 'Аня и ещё 2 оценили ваш пост'\n * ```\n */\nexport function formatNotificationText(notification: Notification): string {\n const template = TEMPLATES[notification.type];\n if (!template) return FALLBACK_TEXT;\n\n const first = notification.actors[0];\n const name = first?.displayName || first?.username || UNKNOWN_ACTOR;\n\n const others = notification.count - 1;\n return others > 0 ? template.many(name, others) : template.one(name);\n}\n","import { NotificationType } from '../types/enums.js';\nimport type { Notification } from '../types/models.js';\n\n/** Типы, ведущие на пост. */\nconst POST_TYPES = new Set<string>([\n NotificationType.PostReaction,\n NotificationType.PostRepost,\n NotificationType.PostMention,\n NotificationType.WallPost,\n]);\n\n/** Типы, ведущие на комментарий внутри поста. */\nconst COMMENT_TYPES = new Set<string>([\n NotificationType.PostComment,\n NotificationType.CommentReaction,\n NotificationType.CommentReply,\n NotificationType.CommentMention,\n]);\n\n/** Типы, ведущие на профиль. */\nconst FOLLOW_TYPES = new Set<string>([\n NotificationType.Follow,\n NotificationType.FollowRequest,\n NotificationType.FollowAccepted,\n]);\n\n/**\n * Вычисляет адрес, на который ведёт уведомление.\n *\n * Возвращает путь внутри сайта — без домена, чтобы его можно было передать роутеру\n * приложения. Поле `clickUrl` от сервера используется только как запасной вариант:\n * вычисленный путь точнее, поскольку учитывает родительский пост у комментариев.\n *\n * @example\n * ```ts\n * const url = resolveNotificationUrl(notification);\n * // '/@durov/post/9f1c…?comment=2b7e…'\n * ```\n */\nexport function resolveNotificationUrl(notification: Notification): string {\n const { type, entityId, parentEntityId, clickUrl } = notification;\n const username = notification.actors[0]?.username;\n\n if (username && entityId) {\n if (POST_TYPES.has(type)) return `/@${username}/post/${entityId}`;\n\n if (COMMENT_TYPES.has(type)) {\n return parentEntityId\n ? `/@${username}/post/${parentEntityId}?comment=${entityId}`\n : `/@${username}/post/${entityId}`;\n }\n }\n\n if (username && FOLLOW_TYPES.has(type)) return `/@${username}`;\n\n return clickUrl || '/notifications';\n}\n","import type {\n AttachmentType,\n LikesVisibility,\n Loose,\n NotificationType,\n SpanType,\n WallAccess,\n} from './enums.js';\n\n/**\n * Дата и время в формате ISO-8601, например `2026-07-21T14:30:00.000Z`.\n *\n * Библиотека не превращает такие поля в `Date`: строку проще сравнивать, логировать\n * и передавать дальше без потерь. Для разбора есть {@link toDate}.\n */\nexport type IsoDate = string;\n\n/**\n * Идентификатор пользователя — **строго UUID**.\n *\n * Отличается от {@link UserRef} тем, что имя пользователя здесь не подойдёт. Так помечены\n * места, где API принимает только UUID: например `wallRecipientId` при постинге на чужую стену.\n */\nexport type UserId = string;\n\n/**\n * Ссылка на пользователя: **UUID либо имя пользователя**.\n *\n * Пути вида `/api/users/{id}` принимают оба варианта, поэтому `itd.users.get('durov')`\n * работает так же, как `itd.users.get('9f1c…')`.\n */\nexport type UserRef = string;\n\n/**\n * Разметка в тексте поста.\n *\n * Приходит от сервера и отправляется обратно как есть — библиотека разметку не генерирует\n * и не пересчитывает.\n *\n * Единицы `offset` и `length` в документации API не уточнены (UTF-16 или кодовые точки),\n * поэтому при работе с эмодзи проверяйте результат.\n */\nexport interface Span {\n /** Тип фрагмента — см. {@link SpanType}. */\n type: SpanType;\n /** Смещение от начала текста. */\n offset: number;\n /** Длина фрагмента. */\n length: number;\n /** Имя хэштега без решётки либо имя пользователя. */\n tag?: string;\n /** Адрес ссылки. Только у `link`: у него вместо `tag` отдельное поле. */\n url?: string;\n}\n\n/**\n * Значок-«пин» в профиле — награда или отметка платформы.\n */\nexport interface Pin {\n /** Постоянный идентификатор, например `epepuy_202605_59`. */\n slug: string;\n /** Отображаемое название. */\n name: string;\n /** Описание, за что выдан. */\n description: string;\n /** Адрес изображения. */\n url: string;\n /** Когда выдан. Приходит только в списке своих пинов. */\n grantedAt?: IsoDate;\n}\n\n/**\n * Автор поста или комментария.\n *\n * Встречается внутри `post.author` и `comment.author`.\n */\nexport interface Author {\n id: UserId;\n username: string;\n displayName: string;\n /**\n * **Эмодзи, а не картинка.**\n *\n * На итд.com аватар — это символ клана (`🩵`, `🦎`), а не адрес изображения.\n * Отрисовывать его нужно как текст.\n */\n avatar: string;\n /** Пройдена ли верификация. */\n verified: boolean;\n /** Активный значок профиля. Может отсутствовать. */\n pin?: Pin | null;\n /** Есть ли премиум-подписка (значок NUKSTA). */\n hasNuksta?: boolean;\n}\n\n/**\n * Участник события в уведомлении.\n *\n * Отличается от {@link Author} набором полей: вместо значков приходит связь с вами.\n */\nexport interface Actor {\n id: UserId;\n username: string;\n displayName: string;\n /** Эмодзи-аватар, см. {@link Author.avatar}. */\n avatar: string;\n /** Подписаны ли вы на этого пользователя. */\n isFollowing?: boolean;\n /** Подписан ли он на вас. */\n isFollowedBy?: boolean;\n}\n\n/**\n * Пользователь в списках.\n *\n * Набор полей зависит от эндпоинта: подписчики и подписки приносят `isFollowing`,\n * поиск и рекомендации — `followersCount` и `hasNuksta`. Необязательные поля отражают\n * это различие.\n */\nexport interface UserSummary {\n id: UserId;\n username: string;\n displayName: string;\n /** Эмодзи-аватар, см. {@link Author.avatar}. */\n avatar: string;\n verified: boolean;\n /** Подписаны ли вы. Приходит в списках подписчиков и подписок. */\n isFollowing?: boolean;\n /** Есть ли премиум. Приходит в поиске и рекомендациях. */\n hasNuksta?: boolean;\n /** Число подписчиков. Приходит в поиске и рекомендациях. */\n followersCount?: number;\n}\n\n/** Поля профиля, общие для своего и чужого. */\ninterface ProfileBase {\n id: UserId;\n username: string;\n displayName: string;\n /** Эмодзи-аватар, см. {@link Author.avatar}. */\n avatar: string;\n /** Адрес изображения-шапки либо `null`. В отличие от аватара это настоящий URL. */\n banner: string | null;\n /** Описание профиля. */\n bio: string;\n verified: boolean;\n pin?: Pin | null;\n /** Кто может писать на стену. */\n wallAccess: WallAccess;\n /** Кто видит реакции. */\n likesVisibility: LikesVisibility;\n followersCount: number;\n followingCount: number;\n postsCount: number;\n createdAt: IsoDate;\n}\n\n/** Состояние подписки на премиум. */\nexport interface SubscriptionState {\n isActive: boolean;\n expiresAt: IsoDate | null;\n autoRenewal: boolean;\n}\n\n/**\n * Свой профиль — ответ `GET /api/users/me`.\n *\n * Отличается от чужого наличием {@link subscription} и {@link isPhoneVerified}\n * и отсутствием полей связи (`isFollowing`, `online`).\n */\nexport interface MyProfile extends ProfileBase {\n /** Закрыт ли профиль. */\n isPrivate: boolean;\n /** Подтверждён ли телефон. Без него часть действий недоступна. */\n isPhoneVerified: boolean;\n /** Своя премиум-подписка. */\n subscription: SubscriptionState;\n}\n\n/**\n * Чужой профиль — ответ `GET /api/users/{id|username}`.\n *\n * Вместо своей подписки содержит связь с вами и присутствие.\n */\nexport interface PublicProfile extends ProfileBase {\n hasNuksta?: boolean;\n /** Закреплённый пост, если он есть. */\n pinnedPostId: string | null;\n /** Подписаны ли вы на него. */\n isFollowing: boolean;\n /** Подписан ли он на вас. */\n isFollowedBy: boolean;\n /** Сейчас ли пользователь в сети. */\n online: boolean;\n /** Когда был в сети. `null`, если скрыто настройками приватности. */\n lastSeen: IsoDate | null;\n}\n\n/** Профиль: свой либо чужой. Различаются функцией {@link isMyProfile}. */\nexport type Profile = MyProfile | PublicProfile;\n\n/**\n * Свой ли это профиль.\n *\n * @example\n * ```ts\n * if (isMyProfile(profile)) console.log(profile.subscription.isActive);\n * ```\n */\nexport function isMyProfile(profile: Profile): profile is MyProfile {\n return 'subscription' in profile;\n}\n\n/** Вложение поста или комментария. */\nexport interface Attachment {\n id: string;\n type: AttachmentType;\n /** Адрес файла на CDN. */\n url: string;\n /** Ширина изображения или видео в пикселях. */\n width?: number;\n /** Высота изображения или видео в пикселях. */\n height?: number;\n mimeType: string;\n /** Исходное имя файла. Приходит не всегда. */\n filename?: string;\n /** Размер в байтах. Приходит не всегда. */\n size?: number;\n /** Длительность аудио или видео в секундах. */\n duration?: number | null;\n /** Порядковый номер во вложениях поста. */\n order?: number;\n}\n\n/** Вариант ответа в опросе. */\nexport interface PollOption {\n id: string;\n text: string;\n /** Сколько голосов отдано за этот вариант. */\n votesCount: number;\n /** Порядковый номер варианта, начиная с нуля. */\n position: number;\n}\n\n/** Опрос внутри поста. */\nexport interface Poll {\n id: string;\n /** Пост, которому принадлежит опрос. */\n postId: string;\n question: string;\n /** Можно ли выбрать несколько вариантов. */\n multipleChoice: boolean;\n options: PollOption[];\n totalVotes: number;\n /** Голосовали ли вы. */\n hasVoted: boolean;\n /** За что проголосовали вы. Пустой массив, если голоса не было. */\n votedOptionIds: string[];\n createdAt: IsoDate;\n}\n\n/** Пост ленты, стены или профиля. */\nexport interface Post {\n id: string;\n content: string;\n /** Разметка текста. Передаётся без изменений, см. {@link Span}. */\n spans: Span[];\n author: Author;\n attachments: Attachment[];\n likesCount: number;\n commentsCount: number;\n repostsCount: number;\n viewsCount: number;\n /** Чья это стена, если пост опубликован не у себя. */\n wallRecipientId: UserId | null;\n /** Владелец стены. Приходит не во всех ответах. */\n wallRecipient?: Author | null;\n /** Поставили ли вы реакцию. */\n isLiked: boolean;\n /** Делали ли вы репост. */\n isReposted: boolean;\n /** Засчитан ли просмотр. */\n isViewed: boolean;\n /** Ваш ли это пост. */\n isOwner: boolean;\n /** Исходный пост, если это репост. */\n originalPost?: Post | null;\n poll?: Poll | null;\n /** Преобладающая реакция — эмодзи либо `null`. */\n dominantEmoji?: string | null;\n /** Когда пост отредактировали. `null`, если не редактировали. */\n editedAt: IsoDate | null;\n createdAt: IsoDate;\n /**\n * Служебная метка показа для телеметрии.\n *\n * Нужна только эндпоинтам `itd.telemetry.*`. В остальных случаях игнорируйте.\n */\n vs?: string;\n /**\n * Топовые комментарии. Приходят только в ответе `GET /api/posts/{id}`.\n *\n * В списках постов поле отсутствует.\n */\n comments?: Comment[];\n}\n\n/** На чей комментарий дан ответ. */\nexport interface CommentReplyTo {\n id: string;\n username: string;\n displayName: string;\n}\n\n/** Комментарий к посту или ответ на комментарий. */\nexport interface Comment {\n id: string;\n /** Текст. У голосового комментария пустой. */\n content: string;\n author: Author;\n likesCount: number;\n repliesCount: number;\n isLiked: boolean;\n createdAt: IsoDate;\n /** Вложения. У голосового — одно аудио с `mimeType: 'audio/ogg'`. */\n attachments?: Attachment[];\n /** Вложенные ответы. В списках приходит превью, полный список — через `itd.comments.replies()`. */\n replies?: Comment[];\n /** Заполнено только у ответов. */\n replyTo?: CommentReplyTo;\n}\n\n/**\n * Уведомление в единой форме.\n *\n * REST-список и SSE-поток отдают уведомления по-разному — разные имена типов, разные имена\n * полей, один участник против массива. Библиотека приводит оба вида к этой структуре,\n * поэтому объекты из `itd.notifications.list()` и из потока можно складывать в один список.\n *\n * Исходные данные не теряются: сервeрное имя типа остаётся в {@link rawType},\n * а весь необработанный объект — в {@link raw}.\n */\nexport interface Notification {\n id: string;\n /** Канонический тип. Старые имена (`like`, `comment`) приведены к новым. */\n type: NotificationType;\n /** Имя типа в том виде, в каком его прислал сервер. */\n rawType: string;\n /** Объект события: пост, комментарий, пользователь. */\n entityId: string | null;\n /** Пост, которому принадлежит комментарий, если событие о комментарии. */\n parentEntityId: string | null;\n /** Прочитано ли уведомление. */\n isRead: boolean;\n /** Кто совершил действие. Для схлопнутых уведомлений — несколько человек. */\n actors: Actor[];\n /** Сколько участников схлопнуто в одно уведомление. Минимум 1. */\n count: number;\n /** Текст или заголовок объекта события. */\n preview: string | null;\n /** Ссылка перехода, предложенная сервером. Обычно точнее её `resolveNotificationUrl()`. */\n clickUrl?: string;\n createdAt: IsoDate;\n /** Когда уведомление изменилось — например было прочитано. */\n updatedAt: IsoDate;\n /** Исходный объект как он пришёл от сервера. */\n raw: unknown;\n}\n\n/** Настройки приватности профиля. */\nexport interface PrivacySettings {\n /** Закрыт ли профиль: подписка требует одобрения. */\n isPrivate: boolean;\n wallAccess: WallAccess;\n likesVisibility: LikesVisibility;\n /** Показывать ли время последнего посещения. */\n showLastSeen: boolean;\n}\n\n/**\n * Настройки уведомлений.\n *\n * Сервер отдаёт плоский объект, но исторически знает два набора имён для одних и тех же\n * настроек (`likes` и `reactions`, `comments` и `replies`). При сохранении библиотека\n * отправляет оба, при чтении принимает любой.\n */\nexport interface NotificationSettings {\n /** Общий выключатель доставки. */\n enabled: boolean;\n /** Звук уведомления. */\n sound: boolean;\n /** Новые подписчики. */\n follows: boolean;\n /** Записи на вашей стене. */\n wallPosts: boolean;\n /** Реакции на ваши записи. */\n likes: boolean;\n /** Комментарии и ответы. */\n comments: boolean;\n /** Упоминания. */\n mentions: boolean;\n}\n\n/** Активная сессия входа. */\nexport interface Session {\n id: string;\n /** Та ли это сессия, из которой выполнен запрос. */\n isCurrent: boolean;\n createdAt: IsoDate;\n lastUsedAt: IsoDate;\n expiresAt: IsoDate;\n ipAddress: string;\n /** Код страны по IP, например `RU`. */\n ipCountry: string | null;\n ipCity: string | null;\n deviceType: Loose<'desktop' | 'mobile'>;\n osName: string | null;\n osVersion: string | null;\n /** Название браузера или приложения. */\n clientName: string | null;\n clientVersion: string | null;\n deviceModel: string | null;\n}\n\n/** Состояние платной подписки и её цена. */\nexport interface Subscription {\n /** Активна ли подписка сейчас. */\n active: boolean;\n /** Включено ли автопродление. */\n recurringEnabled: boolean;\n /** Цена в рублях. */\n price: number;\n}\n\n/** Сохранённый способ оплаты. */\nexport interface PaymentMethod {\n id: string;\n /** Последние четыре цифры карты. */\n last4?: string;\n /** Платёжная система: `visa`, `mastercard`, `mir`. */\n brand?: string;\n /** Основной ли это способ оплаты. */\n isDefault?: boolean;\n expiresAt?: IsoDate | null;\n}\n\n/** Хэштег. */\nexport interface Hashtag {\n id: string;\n /** Название без решётки. */\n name: string;\n /** Сколько постов с этим хэштегом. */\n postsCount: number;\n}\n\n/** Клан в рейтинге. */\nexport interface Clan {\n /** Эмодзи клана — оно же аватар его участников. */\n avatar: string;\n memberCount: number;\n}\n\n/**\n * Результат подписки на пользователя.\n *\n * @example\n * ```ts\n * const result = await itd.users.follow('durov');\n * // { following: true, followersCount: 11 }\n * ```\n */\nexport interface FollowResult {\n /** Подписка оформлена. У закрытого профиля отправляется заявка, и здесь будет `false`. */\n following: boolean;\n /** Сколько подписчиков стало у пользователя после действия. */\n followersCount?: number;\n /** Статус заявки, если профиль закрыт. */\n status?: Loose<'following' | 'requested'>;\n}\n\n/** Запись журнала изменений платформы. */\nexport interface ChangelogEntry {\n version: string;\n date: string;\n changes: string[];\n}\n\n/** Кнопка в анонсе платформы. */\nexport interface AnnouncementButton {\n title: string;\n /** Оформление: `primary`, `secondary` и другие. */\n style: string;\n action: { type: string; [key: string]: unknown };\n}\n\n/** Анонс на главной странице платформы. */\nexport interface Announcement {\n id: string;\n image: { url: string; width: number; height: number };\n title: string;\n description: string;\n /** Дополнительный текст мелким шрифтом. */\n additional_text?: string;\n buttons: AnnouncementButton[];\n}\n\n/** Баннер текущего события — виджет «портал». */\nexport interface Portal {\n active: boolean;\n title: string;\n url: string;\n}\n\n/** Статус заявки на верификацию. `none` означает, что заявка не подавалась. */\nexport interface VerificationStatus {\n status: Loose<'none' | 'pending' | 'approved' | 'rejected'>;\n}\n\n/** Созданная жалоба. */\nexport interface Report {\n id: string;\n createdAt: IsoDate;\n}\n\n/** Счётчики поста из `itd.posts.stats()`. */\nexport interface PostStats {\n id: string;\n likesCount: number;\n commentsCount: number;\n repostsCount: number;\n viewsCount: number;\n /** Преобладающая реакция — эмодзи либо `null`. */\n dominantEmoji: string | null;\n}\n\n/** Результат реакции на пост. */\nexport interface LikeResult {\n liked: boolean;\n likesCount: number;\n}\n\n/** Результат закрепления поста в профиле. */\nexport interface PinPostResult {\n success: boolean;\n pinnedPostId: string | null;\n}\n\n/** Закреплённые значки профиля и выбранный из них. */\nexport interface PinsResult {\n pins: Pin[];\n /** Идентификатор активного значка — строка, а не объект. */\n activePin: string | null;\n}\n\n/**\n * Разбирает дату API в объект `Date`.\n *\n * @returns `null`, если строки нет или она не разбирается\n *\n * @example\n * ```ts\n * const created = toDate(post.createdAt);\n * ```\n */\nexport function toDate(value: IsoDate | null | undefined): Date | null {\n if (!value) return null;\n const date = new Date(value);\n return Number.isFinite(date.getTime()) ? date : null;\n}\n"]}