planvortex 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/version.ts","../src/core/errors.ts","../src/core/auth.ts","../src/core/http.ts","../src/core/pagination.ts","../src/resources/base.ts","../src/resources/accounts.ts","../src/resources/catalog.ts","../src/resources/clients.ts","../src/resources/organizations.ts","../src/resources/publications.ts","../src/core/files.ts","../src/resources/uploads.ts","../src/client.ts","../src/types.ts"],"names":["listQuery","basename"],"mappings":";;;;;AAOO,IAAM,kBAAA,GAAqB;AAS3B,IAAM,OAAA,GAAU;;;ACOhB,IAAM,uBAAA,GAA2D;AAAA,EACpE,EAAE,IAAA,EAAM,GAAA,EAAK,EAAA,EAAI,GAAA,EAAK,QAAQ,MAAA,EAAO;AAAA,EACrC,EAAE,IAAA,EAAM,GAAA,EAAK,EAAA,EAAI,GAAA,EAAK,QAAQ,MAAA,EAAO;AAAA,EACrC,EAAE,IAAA,EAAM,GAAA,EAAK,EAAA,EAAI,GAAA,EAAK,QAAQ,SAAA,EAAU;AAAA,EACxC,EAAE,IAAA,EAAM,GAAA,EAAK,EAAA,EAAI,GAAA,EAAK,QAAQ,MAAA,EAAO;AAAA,EACrC,EAAE,IAAA,EAAM,GAAA,EAAK,EAAA,EAAI,GAAA,EAAK,QAAQ,aAAA,EAAc;AAAA,EAC5C,EAAE,IAAA,EAAM,GAAA,EAAM,EAAA,EAAI,IAAA,EAAM,QAAQ,SAAA,EAAU;AAAA,EAC1C,EAAE,IAAA,EAAM,IAAA,EAAM,EAAA,EAAI,IAAA,EAAM,QAAQ,cAAA,EAAe;AAAA,EAC/C,EAAE,IAAA,EAAM,IAAA,EAAM,EAAA,EAAI,IAAA,EAAM,QAAQ,MAAA,EAAO;AAAA,EACvC,EAAE,IAAA,EAAM,IAAA,EAAM,EAAA,EAAI,IAAA,EAAM,QAAQ,YAAA,EAAa;AAAA,EAC7C,EAAE,IAAA,EAAM,IAAA,EAAM,EAAA,EAAI,IAAA,EAAM,QAAQ,YAAA,EAAa;AAAA,EAC7C,EAAE,IAAA,EAAM,IAAA,EAAM,EAAA,EAAI,IAAA,EAAM,QAAQ,WAAA,EAAY;AAAA,EAC5C,EAAE,IAAA,EAAM,IAAA,EAAM,EAAA,EAAI,IAAA,EAAM,QAAQ,SAAA,EAAU;AAAA,EAC1C,EAAE,IAAA,EAAM,IAAA,EAAM,EAAA,EAAI,IAAA,EAAM,QAAQ,SAAA,EAAU;AAAA,EAC1C,EAAE,IAAA,EAAM,GAAA,EAAM,EAAA,EAAI,IAAA,EAAM,QAAQ,SAAA,EAAU;AAAA,EAC1C,EAAE,IAAA,EAAM,IAAA,EAAM,EAAA,EAAI,IAAA,EAAM,QAAQ,SAAA,EAAU;AAAA,EAC1C,EAAE,IAAA,EAAM,IAAA,EAAM,EAAA,EAAI,IAAA,EAAM,QAAQ,aAAA;AACpC;AASO,IAAM,aAAA,GAAgB;AAStB,IAAM,iBAAA,GAAuC,CAAC,GAAA,EAAK,GAAG;AA2BtD,IAAM,eAAA,GAAN,cAA8B,KAAA,CAAM;AAAA;AAAA,EAE9B,IAAA;AAAA;AAAA,EAEA,MAAA;AAAA;AAAA,EAEA,IAAA;AAAA;AAAA,EAEA,MAAA;AAAA;AAAA,EAEA,SAAA;AAAA;AAAA,EAEA,UAAA;AAAA,EAET,WAAA,CAAY,IAAA,EAAc,OAAA,EAAiB,OAAA,GAAkC,EAAC,EAAG;AAC7E,IAAA,KAAA,CAAM,OAAA,EAAS,QAAQ,KAAA,KAAU,MAAA,GAAY,SAAY,EAAE,KAAA,EAAO,OAAA,CAAQ,KAAA,EAAO,CAAA;AACjF,IAAA,IAAA,CAAK,OAAO,GAAA,CAAA,MAAA,CAAW,IAAA;AACvB,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AACZ,IAAA,IAAA,CAAK,MAAA,GAAS,OAAA,CAAQ,MAAA,IAAU,kBAAA,CAAmB,IAAI,CAAA,IAAK,SAAA;AAC5D,IAAA,IAAA,CAAK,IAAA,GAAO,OAAA,CAAQ,IAAA,IAAQ,EAAC;AAC7B,IAAA,IAAA,CAAK,SAAS,OAAA,CAAQ,MAAA;AACtB,IAAA,IAAA,CAAK,YAAY,OAAA,CAAQ,SAAA;AACzB,IAAA,IAAA,CAAK,aAAa,OAAA,CAAQ,UAAA;AAAA,EAC9B;AACJ;AAGO,IAAM,SAAA,GAAN,cAAwB,eAAA,CAAgB;AAAC;AAEzC,IAAM,SAAA,GAAN,cAAwB,eAAA,CAAgB;AAAC;AAEzC,IAAM,YAAA,GAAN,cAA2B,eAAA,CAAgB;AAAC;AAE5C,IAAM,SAAA,GAAN,cAAwB,eAAA,CAAgB;AAAC;AAEzC,IAAM,gBAAA,GAAN,cAA+B,eAAA,CAAgB;AAAC;AAEhD,IAAM,iBAAA,GAAN,cAAgC,eAAA,CAAgB;AAAC;AAOjD,IAAM,cAAA,GAAN,cAA6B,eAAA,CAAgB;AAAC;AAE9C,IAAM,cAAA,GAAN,cAA6B,eAAA,CAAgB;AAAC;AAE9C,IAAM,YAAA,GAAN,cAA2B,eAAA,CAAgB;AAAC;AAE5C,IAAM,YAAA,GAAN,cAA2B,eAAA,CAAgB;AAAC;AAE5C,IAAM,WAAA,GAAN,cAA0B,eAAA,CAAgB;AAAC;AAE3C,IAAM,gBAAA,GAAN,cAA+B,eAAA,CAAgB;AAAC;AAOhD,IAAM,yBAAA,GAAN,cAAwC,eAAA,CAAgB;AAAA;AAAA,EAElD,OAAA;AAAA,EAET,WAAA,CAAY,OAAA,EAAiB,OAAA,GAA0D,EAAC,EAAG;AACvF,IAAA,KAAA,CAAM,eAAe,OAAA,EAAS,EAAE,GAAG,OAAA,EAAS,MAAA,EAAQ,cAAc,CAAA;AAClE,IAAA,IAAA,CAAK,OAAA,GAAU,QAAQ,OAAA,IAAW,KAAA;AAAA,EACtC;AACJ;AAUO,IAAM,6BAAA,GAAN,cAA4C,eAAA,CAAgB;AAAA;AAAA,EAEtD,UAAA;AAAA,EAET,WAAA,CAAY,UAAA,EAAoB,WAAA,EAAqB,OAAA,GAAkC,EAAC,EAAG;AACvF,IAAA,KAAA,CAAM,eAAe,WAAA,EAAa,EAAE,GAAG,OAAA,EAAS,MAAA,EAAQ,SAAS,CAAA;AACjE,IAAA,IAAA,CAAK,UAAA,GAAa,UAAA;AAAA,EACtB;AACJ;AAMO,IAAM,qBAAA,GAAN,cAAoC,eAAA,CAAgB;AAAA,EACvD,YAAY,OAAA,EAAiB;AACzB,IAAA,KAAA,CAAM,aAAA,EAAe,OAAA,EAAS,EAAE,MAAA,EAAQ,UAAU,CAAA;AAAA,EACtD;AACJ;AAGO,SAAS,mBAAmB,IAAA,EAAkC;AACjE,EAAA,OAAO,uBAAA,CAAwB,IAAA,CAAK,CAAC,KAAA,KAAU,IAAA,IAAQ,MAAM,IAAA,IAAQ,IAAA,IAAQ,KAAA,CAAM,EAAE,CAAA,EAAG,MAAA;AAC5F;AAOA,IAAM,cAAA,GAAyD;AAAA,EAC3D,IAAA,EAAM,SAAA;AAAA,EACN,IAAA,EAAM,SAAA;AAAA,EACN,OAAA,EAAS,YAAA;AAAA,EACT,IAAA,EAAM,SAAA;AAAA,EACN,WAAA,EAAa,gBAAA;AAAA,EACb,YAAA,EAAc,iBAAA;AAAA,EACd,UAAA,EAAY,cAAA;AAAA,EACZ,SAAA,EAAW,cAAA;AAAA,EACX,OAAA,EAAS,YAAA;AAAA,EACT,OAAA,EAAS,YAAA;AAAA,EACT,OAAA,EAAS,WAAA;AAAA,EACT,WAAA,EAAa;AACjB,CAAA;AASA,SAAS,eAAe,IAAA,EAAqC;AACzD,EAAA,OAAO,OAAO,IAAA,KAAS,QAAA,IAAY,SAAS,IAAA,IAAQ,OAAQ,KAAsB,IAAA,KAAS,QAAA;AAC/F;AASO,SAAS,wBAAwB,KAAA,EAKpB;AAChB,EAAA,MAAM,OAAA,GAAkC;AAAA,IACpC,QAAQ,KAAA,CAAM,MAAA;AAAA,IACd,GAAI,MAAM,SAAA,KAAc,MAAA,GAAY,EAAC,GAAI,EAAE,SAAA,EAAW,KAAA,CAAM,SAAA,EAAU;AAAA,IACtE,GAAI,MAAM,UAAA,KAAe,MAAA,GAAY,EAAC,GAAI,EAAE,UAAA,EAAY,KAAA,CAAM,UAAA;AAAW,GAC7E;AAEA,EAAA,IAAI,cAAA,CAAe,KAAA,CAAM,IAAI,CAAA,EAAG;AAC5B,IAAA,MAAM,MAAA,GAAS,kBAAA,CAAmB,KAAA,CAAM,IAAA,CAAK,IAAI,CAAA;AACjD,IAAA,MAAM,cAAc,MAAA,KAAW,MAAA,GAAY,MAAA,GAAY,cAAA,CAAe,MAAM,CAAA,KAAM,eAAA;AAClF,IAAA,OAAO,IAAI,WAAW,KAAA,CAAM,IAAA,CAAK,MAAM,KAAA,CAAM,IAAA,CAAK,WAAW,kBAAA,EAAoB;AAAA,MAC7E,GAAG,OAAA;AAAA,MACH,IAAA,EAAM,KAAA,CAAM,IAAA,CAAK,IAAA,IAAQ;AAAC,KAC7B,CAAA;AAAA,EACL;AAEA,EAAA,OAAO,IAAI,eAAA,CAAgB,aAAA,EAAe,CAAA,KAAA,EAAQ,KAAA,CAAM,MAAM,CAAA,CAAA,EAAI;AAAA,IAC9D,GAAG,OAAA;AAAA,IACH,MAAA,EAAQ,MAAA;AAAA,IACR,IAAA,EACI,OAAO,KAAA,CAAM,IAAA,KAAS,QAAA,IAAY,KAAA,CAAM,IAAA,KAAS,IAAA,GAC1C,KAAA,CAAM,IAAA,GACP,EAAE,IAAA,EAAM,MAAM,IAAA;AAAK,GAChC,CAAA;AACL;AAGO,SAAS,kBAAkB,KAAA,EAA0C;AACxE,EAAA,OAAO,KAAA,YAAiB,eAAA;AAC5B;AAOO,SAAS,aAAa,KAAA,EAAyB;AAClD,EAAA,OAAO,kBAAkB,KAAK,CAAA,IAAK,iBAAA,CAAkB,QAAA,CAAS,MAAM,IAAI,CAAA;AAC5E;;;ACpOO,IAAM,uBAAA,GAA0B;AAGhC,IAAM,UAAA,GAAa,cAAA;AASnB,IAAM,kBAAN,MAA8C;AAAA,EACjD,YAA6B,KAAA,EAAe;AAAf,IAAA,IAAA,CAAA,KAAA,GAAA,KAAA;AAAA,EAAgB;AAAA,EAAhB,KAAA;AAAA,EAE7B,QAAA,GAA4B;AACxB,IAAA,OAAO,OAAA,CAAQ,OAAA,CAAQ,IAAA,CAAK,KAAK,CAAA;AAAA,EACrC;AAAA,EAEA,UAAA,GAAmB;AAAA,EAEnB;AACJ,CAAA;AAeO,IAAM,wBAAN,MAAoD;AAAA,EAMvD,WAAA,CACqB,MACA,OAAA,EACnB;AAFmB,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AACA,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAEjB,IAAA,IAAA,CAAK,GAAA,GAAM,OAAA,CAAQ,GAAA,IAAO,IAAA,CAAK,GAAA;AAAA,EACnC;AAAA,EAJqB,IAAA;AAAA,EACA,OAAA;AAAA,EAPJ,GAAA;AAAA,EACT,MAAA;AAAA;AAAA,EAEA,OAAA;AAAA,EASR,MAAM,QAAA,GAA4B;AAC9B,IAAA,MAAM,SAAS,IAAA,CAAK,MAAA;AACpB,IAAA,IAAI,UAAU,MAAA,CAAO,SAAA,GAAY,IAAA,CAAK,GAAA,KAAQ,uBAAA,EAAyB;AACnE,MAAA,OAAO,MAAA,CAAO,KAAA;AAAA,IAClB;AAEA,IAAA,IAAA,CAAK,OAAA,KAAY,IAAA,CAAK,UAAA,EAAW,CAAE,QAAQ,MAAM;AAC7C,MAAA,IAAA,CAAK,OAAA,GAAU,MAAA;AAAA,IACnB,CAAC,CAAA;AACD,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,EAChB;AAAA,EAEA,UAAA,GAAmB;AACf,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AAAA,EAClB;AAAA,EAEA,MAAc,UAAA,GAA8B;AACxC,IAAA,MAAM,IAAA,GAAO,IAAI,eAAA,CAAgB;AAAA,MAC7B,UAAA,EAAY,oBAAA;AAAA,MACZ,SAAA,EAAW,KAAK,OAAA,CAAQ,QAAA;AAAA,MACxB,aAAA,EAAe,KAAK,OAAA,CAAQ;AAAA,KAC/B,CAAA;AACD,IAAA,IAAI,IAAA,CAAK,QAAQ,KAAA,EAAO;AACpB,MAAA,IAAA,CAAK,GAAA,CAAI,OAAA,EAAS,IAAA,CAAK,OAAA,CAAQ,KAAK,CAAA;AAAA,IACxC;AAEA,IAAA,IAAI,KAAA;AACJ,IAAA,IAAI;AACA,MAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,IAAA,CAAK,OAAA,CAAgC;AAAA,QAC7D,MAAA,EAAQ,MAAA;AAAA,QACR,IAAA,EAAM,UAAA;AAAA,QACN,IAAA;AAAA;AAAA,QAEA,UAAA,EAAY;AAAA,OACf,CAAA;AACD,MAAA,KAAA,GAAQ,QAAA,CAAS,IAAA;AAAA,IACrB,SAAS,KAAA,EAAO;AACZ,MAAA,MAAM,sBAAsB,KAAK,CAAA;AAAA,IACrC;AAEA,IAAA,IAAI,CAAC,OAAO,YAAA,EAAc;AACtB,MAAA,MAAM,IAAI,6BAAA;AAAA,QACN,cAAA;AAAA,QACA;AAAA,OACJ;AAAA,IACJ;AAIA,IAAA,MAAM,UAAA,GAAA,CAAc,MAAA,CAAO,KAAA,CAAM,UAAU,CAAA,GAAI,IAAI,MAAA,CAAO,KAAA,CAAM,UAAU,CAAA,GAAI,IAAA,IAAQ,GAAA;AACtF,IAAA,IAAA,CAAK,MAAA,GAAS,EAAE,KAAA,EAAO,KAAA,CAAM,cAAc,SAAA,EAAW,IAAA,CAAK,GAAA,EAAI,GAAI,UAAA,EAAW;AAC9E,IAAA,OAAO,KAAA,CAAM,YAAA;AAAA,EACjB;AACJ,CAAA;AAcO,SAAS,sBAAsB,KAAA,EAAyB;AAC3D,EAAA,IAAI,CAAC,iBAAA,CAAkB,KAAK,CAAA,IAAK,KAAA,CAAM,WAAW,MAAA,EAAW;AACzD,IAAA,OAAO,KAAA;AAAA,EACX;AACA,EAAA,MAAM,OAAO,KAAA,CAAM,IAAA;AACnB,EAAA,MAAM,aAAa,OAAO,IAAA,CAAK,KAAA,KAAU,QAAA,GAAW,KAAK,KAAA,GAAQ,gBAAA;AACjE,EAAA,MAAM,cAAc,OAAO,IAAA,CAAK,sBAAsB,QAAA,GAAW,IAAA,CAAK,oBAAoB,KAAA,CAAM,OAAA;AAEhG,EAAA,OAAO,IAAI,6BAAA,CAA8B,UAAA,EAAY,WAAA,EAAa;AAAA,IAC9D,QAAQ,KAAA,CAAM,MAAA;AAAA,IACd,GAAI,MAAM,SAAA,KAAc,MAAA,GAAY,EAAC,GAAI,EAAE,SAAA,EAAW,KAAA,CAAM,SAAA,EAAU;AAAA,IACtE,GAAI,MAAM,UAAA,KAAe,MAAA,GAAY,EAAC,GAAI,EAAE,UAAA,EAAY,KAAA,CAAM,UAAA,EAAW;AAAA,IACzE,KAAA,EAAO;AAAA,GACV,CAAA;AACL;;;AC3HO,IAAM,aAAA,GAA6B;AAAA,EACtC,UAAA,EAAY,CAAA;AAAA,EACZ,WAAA,EAAa,GAAA;AAAA,EACb,UAAA,EAAY;AAChB;AAGO,IAAM,kBAAA,GAAqB;AAGlC,IAAM,gBAAA,uBAAuB,GAAA,CAAI,CAAC,KAAK,GAAA,EAAK,GAAA,EAAK,GAAA,EAAK,GAAG,CAAC,CAAA;AAS1D,IAAM,wBAAA,uBAA+B,GAAA,CAAI;AAAA,EACrC,cAAA;AAAA,EACA,WAAA;AAAA,EACA,WAAA;AAAA,EACA,cAAA;AAAA,EACA;AACJ,CAAC,CAAA;AA6ED,SAAS,aAAa,OAAA,EAA+B;AACjD,EAAA,OAAO,OAAA,CAAQ,UAAA,IAAc,OAAA,CAAQ,MAAA,KAAW,MAAA;AACpD;AAGA,SAAS,iBAAiB,KAAA,EAAoC;AAC1D,EAAA,MAAM,QAAS,KAAA,EAA+B,KAAA;AAC9C,EAAA,MAAM,IAAA,GAAQ,KAAA,EAA8B,IAAA,IAAS,KAAA,EAA8B,IAAA;AACnF,EAAA,OAAO,OAAO,IAAA,KAAS,QAAA,GAAW,IAAA,GAAO,MAAA;AAC7C;AAGO,SAAS,eAAA,CAAgB,MAAA,EAAuB,GAAA,GAAc,IAAA,CAAK,KAAI,EAAuB;AACjG,EAAA,IAAI,CAAC,MAAA,EAAQ;AACT,IAAA,OAAO,MAAA;AAAA,EACX;AACA,EAAA,MAAM,OAAA,GAAU,OAAO,MAAM,CAAA;AAC7B,EAAA,IAAI,MAAA,CAAO,QAAA,CAAS,OAAO,CAAA,IAAK,WAAW,CAAA,EAAG;AAC1C,IAAA,OAAO,OAAA;AAAA,EACX;AACA,EAAA,MAAM,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,MAAM,CAAA;AAC9B,EAAA,IAAI,MAAA,CAAO,KAAA,CAAM,IAAI,CAAA,EAAG;AACpB,IAAA,OAAO,MAAA;AAAA,EACX;AACA,EAAA,OAAO,IAAA,CAAK,IAAI,CAAA,EAAG,IAAA,CAAK,OAAO,IAAA,GAAO,GAAA,IAAO,GAAI,CAAC,CAAA;AACtD;AAEA,SAAS,WAAW,KAAA,EAAuD;AACvE,EAAA,IAAI,CAAC,KAAA,EAAO;AACR,IAAA,OAAO,EAAA;AAAA,EACX;AACA,EAAA,MAAM,MAAA,GAAS,IAAI,eAAA,EAAgB;AACnC,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA,EAAG;AAC9C,IAAA,IAAI,KAAA,KAAU,MAAA,IAAa,KAAA,KAAU,IAAA,EAAM;AACvC,MAAA;AAAA,IACJ;AACA,IAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AAEtB,MAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACtB,QAAA,MAAA,CAAO,MAAA,CAAO,GAAA,EAAK,MAAA,CAAO,IAAI,CAAC,CAAA;AAAA,MACnC;AACA,MAAA;AAAA,IACJ;AACA,IAAA,MAAA,CAAO,MAAA,CAAO,KAAK,KAAA,YAAiB,IAAA,GAAO,MAAM,WAAA,EAAY,GAAI,MAAA,CAAO,KAAK,CAAC,CAAA;AAAA,EAClF;AACA,EAAA,MAAM,UAAA,GAAa,OAAO,QAAA,EAAS;AACnC,EAAA,OAAO,UAAA,GAAa,CAAA,CAAA,EAAI,UAAU,CAAA,CAAA,GAAK,EAAA;AAC3C;AAEA,SAAS,MAAM,EAAA,EAA2B;AACtC,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,KAAY;AAC5B,IAAA,UAAA,CAAW,SAAS,EAAE,CAAA;AAAA,EAC1B,CAAC,CAAA;AACL;AAEO,IAAM,aAAN,MAAiB;AAAA,EACH,OAAA;AAAA,EACA,SAAA;AAAA,EACA,KAAA;AAAA,EACA,KAAA;AAAA,EACA,SAAA;AAAA,EACA,WAAA;AAAA,EAEjB,YAAY,MAAA,EAA0B;AAClC,IAAA,IAAA,CAAK,OAAA,GAAU,MAAA,CAAO,OAAA,CAAQ,OAAA,CAAQ,QAAQ,EAAE,CAAA;AAChD,IAAA,IAAA,CAAK,SAAA,GAAY,OAAO,SAAA,IAAa,kBAAA;AACrC,IAAA,IAAA,CAAK,QAAQ,EAAE,GAAG,aAAA,EAAe,GAAG,OAAO,KAAA,EAAM;AACjD,IAAA,IAAA,CAAK,KAAA,GAAQ,MAAA,CAAO,KAAA,IAAS,EAAC;AAE9B,IAAA,IAAA,CAAK,SAAA,GAAY,OAAO,KAAA,KAAU,CAAC,OAAO,IAAA,KAAS,UAAA,CAAW,KAAA,CAAM,KAAA,EAAO,IAAI,CAAA,CAAA;AAE/E,IAAA,IAAA,CAAK,cAAc,MAAA,CAAO,WAAA;AAAA,MACtB,OAAO,OAAA,CAAQ,MAAA,CAAO,WAAW,EAAE,EAAE,GAAA,CAAI,CAAC,CAAC,GAAA,EAAK,KAAK,CAAA,KAAM,CAAC,IAAI,WAAA,EAAY,EAAG,KAAK,CAAC;AAAA,KACzF;AAAA,EACJ;AAAA,EAEA,MAAM,QAAW,OAAA,EAAgD;AAC7D,IAAA,MAAM,GAAA,GAAM,CAAA,EAAG,IAAA,CAAK,OAAO,CAAA,EAAG,OAAA,CAAQ,IAAI,CAAA,EAAG,UAAA,CAAW,OAAA,CAAQ,KAAK,CAAC,CAAA,CAAA;AACtE,IAAA,MAAM,EAAE,IAAA,EAAM,OAAA,EAAQ,GAAI,IAAA,CAAK,YAAY,OAAO,CAAA;AAClD,IAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,SAAA,IAAa,IAAA,CAAK,SAAA;AAC5C,IAAA,MAAM,SAAA,GAAY,aAAa,OAAO,CAAA;AAEtC,IAAA,IAAI,OAAA,GAAU,CAAA;AACd,IAAA,WAAS;AACL,MAAA,OAAA,EAAA;AACA,MAAA,IAAA,CAAK,KAAA,CAAM,YAAY,EAAE,MAAA,EAAQ,QAAQ,MAAA,EAAQ,GAAA,EAAK,SAAS,CAAA;AAC/D,MAAA,MAAM,SAAA,GAAY,KAAK,GAAA,EAAI;AAE3B,MAAA,IAAI,QAAA;AACJ,MAAA,IAAI;AACA,QAAA,QAAA,GAAW,MAAM,IAAA,CAAK,IAAA,CAAK,KAAK,OAAA,EAAS,IAAA,EAAM,SAAS,SAAS,CAAA;AAAA,MACrE,SAAS,KAAA,EAAO;AACZ,QAAA,MAAM,OAAA,GAAU,IAAA,CAAK,iBAAA,CAAkB,KAAA,EAAO,SAAS,SAAS,CAAA;AAEhE,QAAA,MAAM,WAAW,SAAA,IAAa,wBAAA,CAAyB,IAAI,gBAAA,CAAiB,KAAK,KAAK,EAAE,CAAA;AACxF,QAAA,IAAI,CAAC,QAAA,IAAY,OAAA,GAAU,IAAA,CAAK,MAAM,UAAA,EAAY;AAC9C,UAAA,MAAM,OAAA;AAAA,QACV;AACA,QAAA,MAAM,OAAA,GAAU,IAAA,CAAK,OAAA,CAAQ,OAAO,CAAA;AACpC,QAAA,IAAA,CAAK,MAAM,OAAA,GAAU;AAAA,UACjB,QAAQ,OAAA,CAAQ,MAAA;AAAA,UAChB,GAAA;AAAA,UACA,OAAA;AAAA,UACA,OAAA;AAAA,UACA,MAAA,EAAQ,MAAA;AAAA,UACR;AAAA,SACH,CAAA;AACD,QAAA,MAAM,MAAM,OAAO,CAAA;AACnB,QAAA;AAAA,MACJ;AAEA,MAAA,IAAA,CAAK,MAAM,UAAA,GAAa;AAAA,QACpB,QAAQ,OAAA,CAAQ,MAAA;AAAA,QAChB,GAAA;AAAA,QACA,OAAA;AAAA,QACA,QAAQ,QAAA,CAAS,MAAA;AAAA,QACjB,UAAA,EAAY,IAAA,CAAK,GAAA,EAAI,GAAI;AAAA,OAC5B,CAAA;AAED,MAAA,MAAM,SAAA,GAAY,QAAA,CAAS,OAAA,CAAQ,GAAA,CAAI,cAAc,CAAA,IAAK,MAAA;AAE1D,MAAA,IAAI,SAAS,EAAA,EAAI;AACb,QAAA,OAAO;AAAA,UACH,IAAA,EAAO,MAAM,IAAA,CAAK,SAAA,CAAU,UAAU,OAAO,CAAA;AAAA,UAC7C,QAAQ,QAAA,CAAS,MAAA;AAAA,UACjB,SAAS,QAAA,CAAS,OAAA;AAAA,UAClB;AAAA,SACJ;AAAA,MACJ;AAEA,MAAA,MAAM,aAAa,eAAA,CAAgB,QAAA,CAAS,OAAA,CAAQ,GAAA,CAAI,aAAa,CAAC,CAAA;AACtE,MAAA,MAAM,WAAA,GACF,aAAa,gBAAA,CAAiB,GAAA,CAAI,SAAS,MAAM,CAAA,IAAK,OAAA,IAAW,IAAA,CAAK,KAAA,CAAM,UAAA;AAChF,MAAA,MAAM,SAAS,UAAA,KAAe,MAAA,GAAY,KAAK,OAAA,CAAQ,OAAO,IAAI,UAAA,GAAa,GAAA;AAI/E,MAAA,IAAI,CAAC,WAAA,IAAe,MAAA,GAAS,IAAA,CAAK,MAAM,UAAA,EAAY;AAChD,QAAA,MAAM,MAAM,IAAA,CAAK,UAAA,CAAW,QAAA,EAAU,WAAW,UAAU,CAAA;AAAA,MAC/D;AAGA,MAAA,MAAM,QAAA,CAAS,WAAA,EAAY,CAAE,KAAA,CAAM,MAAM,MAAS,CAAA;AAClD,MAAA,IAAA,CAAK,MAAM,OAAA,GAAU;AAAA,QACjB,QAAQ,OAAA,CAAQ,MAAA;AAAA,QAChB,GAAA;AAAA,QACA,OAAA;AAAA,QACA,OAAA,EAAS,MAAA;AAAA,QACT,QAAQ,QAAA,CAAS,MAAA;AAAA,QACjB,KAAA,EAAO;AAAA,OACV,CAAA;AACD,MAAA,MAAM,MAAM,MAAM,CAAA;AAAA,IACtB;AAAA,EACJ;AAAA;AAAA,EAGQ,QAAQ,OAAA,EAAyB;AACrC,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,GAAA,CAAI,IAAA,CAAK,KAAA,CAAM,UAAA,EAAY,IAAA,CAAK,KAAA,CAAM,WAAA,GAAc,CAAA,KAAM,OAAA,GAAU,CAAA,CAAE,CAAA;AAC3F,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,MAAA,KAAW,OAAO,CAAA;AAAA,EAC7C;AAAA,EAEQ,YAAY,OAAA,EAGlB;AACE,IAAA,MAAM,UAAkC,EAAE,MAAA,EAAQ,kBAAA,EAAoB,GAAG,KAAK,WAAA,EAAY;AAC1F,IAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,CAAA,IAAK,MAAA,CAAO,QAAQ,OAAA,CAAQ,OAAA,IAAW,EAAE,CAAA,EAAG;AAC9D,MAAA,OAAA,CAAQ,GAAA,CAAI,WAAA,EAAa,CAAA,GAAI,KAAA;AAAA,IACjC;AAEA,IAAA,IAAI,OAAA,CAAQ,SAAS,MAAA,EAAW;AAC5B,MAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAW,OAAA,EAAQ;AAAA,IACtC;AAEA,IAAA,IAAI,OAAA,CAAQ,IAAA,YAAgB,QAAA,IAAY,OAAA,CAAQ,gBAAgB,eAAA,EAAiB;AAC7E,MAAA,OAAO,EAAE,IAAA,EAAM,OAAA,CAAQ,IAAA,EAAM,OAAA,EAAQ;AAAA,IACzC;AACA,IAAA,IAAI,OAAO,OAAA,CAAQ,IAAA,KAAS,QAAA,IAAY,OAAA,CAAQ,gBAAgB,UAAA,EAAY;AACxE,MAAA,OAAO,EAAE,IAAA,EAAM,OAAA,CAAQ,IAAA,EAAqB,OAAA,EAAQ;AAAA,IACxD;AACA,IAAA,OAAA,CAAQ,cAAc,CAAA,GAAI,kBAAA;AAC1B,IAAA,OAAO,EAAE,IAAA,EAAM,IAAA,CAAK,UAAU,OAAA,CAAQ,IAAI,GAAG,OAAA,EAAQ;AAAA,EACzD;AAAA,EAEA,MAAc,IAAA,CACV,GAAA,EACA,OAAA,EACA,IAAA,EACA,SACA,SAAA,EACiB;AACjB,IAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,IAAA,MAAM,KAAA,GAAQ,WAAW,MAAM,UAAA,CAAW,MAAM,IAAI,iBAAA,EAAmB,CAAA,EAAG,SAAS,CAAA;AAGnF,IAAA,MAAM,WAAW,OAAA,CAAQ,MAAA;AACzB,IAAA,MAAM,OAAA,GAAU,MAAM,UAAA,CAAW,KAAA,CAAM,UAAU,MAAM,CAAA;AACvD,IAAA,IAAI,QAAA,EAAU;AACV,MAAA,IAAI,SAAS,OAAA,EAAS;AAClB,QAAA,YAAA,CAAa,KAAK,CAAA;AAClB,QAAA,MAAM,QAAA,CAAS,MAAA;AAAA,MACnB;AACA,MAAA,QAAA,CAAS,iBAAiB,OAAA,EAAS,OAAA,EAAS,EAAE,IAAA,EAAM,MAAM,CAAA;AAAA,IAC9D;AAEA,IAAA,IAAI;AACA,MAAA,OAAO,MAAM,IAAA,CAAK,SAAA,CAAU,GAAA,EAAK;AAAA,QAC7B,QAAQ,OAAA,CAAQ,MAAA;AAAA,QAChB,GAAI,IAAA,KAAS,KAAA,CAAA,GAAY,EAAC,GAAI,EAAE,IAAA,EAAK;AAAA,QACrC,OAAA;AAAA,QACA,QAAQ,UAAA,CAAW;AAAA,OACtB,CAAA;AAAA,IACL,SAAS,KAAA,EAAO;AAGZ,MAAA,IAAI,WAAW,MAAA,CAAO,MAAA,YAAkB,iBAAA,IAAqB,CAAC,UAAU,OAAA,EAAS;AAC7E,QAAA,MAAM,WAAW,MAAA,CAAO,MAAA;AAAA,MAC5B;AACA,MAAA,MAAM,KAAA;AAAA,IACV,CAAA,SAAE;AACE,MAAA,YAAA,CAAa,KAAK,CAAA;AAClB,MAAA,QAAA,EAAU,mBAAA,CAAoB,SAAS,OAAO,CAAA;AAAA,IAClD;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,iBAAA,CAAkB,KAAA,EAAgB,OAAA,EAAsB,SAAA,EAA4B;AACxF,IAAA,IAAI,KAAA,YAAiB,iBAAA,IAAsB,KAAA,EAA6B,IAAA,KAAS,cAAA,EAAgB;AAC7F,MAAA,OAAO,IAAI,yBAAA;AAAA,QACP,GAAG,OAAA,CAAQ,MAAM,IAAI,OAAA,CAAQ,IAAI,2BAAwB,SAAS,CAAA,GAAA,CAAA;AAAA,QAClE,EAAE,OAAA,EAAS,IAAA,EAAM,KAAA,EAAO,KAAA;AAAM,OAClC;AAAA,IACJ;AACA,IAAA,IAAI,OAAA,CAAQ,QAAQ,OAAA,EAAS;AACzB,MAAA,OAAO,KAAA;AAAA,IACX;AACA,IAAA,MAAM,IAAA,GAAO,iBAAiB,KAAK,CAAA;AACnC,IAAA,OAAO,IAAI,yBAAA;AAAA,MACP,CAAA,EAAG,OAAA,CAAQ,MAAM,CAAA,CAAA,EAAI,OAAA,CAAQ,IAAI,CAAA,iBAAA,EAAoB,IAAA,GAAO,CAAA,EAAA,EAAK,IAAI,CAAA,CAAA,CAAA,GAAM,EAAE,CAAA,CAAA;AAAA,MAC7E,EAAE,OAAA,EAAS,KAAA,EAAO,KAAA,EAAO,KAAA;AAAM,KACnC;AAAA,EACJ;AAAA,EAEA,MAAc,UAAA,CACV,QAAA,EACA,SAAA,EACA,UAAA,EACwB;AACxB,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,QAAA,CAAS,QAAQ,CAAA;AACzC,IAAA,OAAO,uBAAA,CAAwB,EAAE,IAAA,EAAM,MAAA,EAAQ,SAAS,MAAA,EAAQ,SAAA,EAAW,YAAY,CAAA;AAAA,EAC3F;AAAA,EAEA,MAAc,SAAA,CAAU,QAAA,EAAoB,OAAA,EAAwC;AAChF,IAAA,IAAI,OAAA,CAAQ,KAAA,KAAU,MAAA,IAAU,QAAA,CAAS,WAAW,GAAA,EAAK;AACrD,MAAA,OAAO,MAAA;AAAA,IACX;AACA,IAAA,OAAO,IAAA,CAAK,SAAS,QAAQ,CAAA;AAAA,EACjC;AAAA;AAAA,EAGA,MAAc,SAAS,QAAA,EAAsC;AACzD,IAAA,MAAM,OAAO,MAAM,QAAA,CAAS,MAAK,CAAE,KAAA,CAAM,MAAM,EAAE,CAAA;AACjD,IAAA,IAAI,CAAC,IAAA,EAAM;AACP,MAAA,OAAO,MAAA;AAAA,IACX;AACA,IAAA,IAAI;AACA,MAAA,OAAO,IAAA,CAAK,MAAM,IAAI,CAAA;AAAA,IAC1B,CAAA,CAAA,MAAQ;AACJ,MAAA,OAAO,IAAA;AAAA,IACX;AAAA,EACJ;AACJ,CAAA;AAGA,IAAM,iBAAA,GAAN,cAAgC,KAAA,CAAM;AAAA,EAClC,WAAA,GAAc;AACV,IAAA,KAAA,CAAM,4BAA4B,CAAA;AAClC,IAAA,IAAA,CAAK,IAAA,GAAO,cAAA;AAAA,EAChB;AACJ,CAAA;;;ACnZO,IAAM,iBAAA,GAAoB;AAM1B,IAAM,SAAA,GAAY;AAuBlB,SAAS,UAAA,CAAc,MAAe,GAAA,EAA2B;AACpE,EAAA,MAAM,QAAA,GAAW,IAAA;AACjB,EAAA,MAAM,IAAA,GAAO,WAAW,GAAG,CAAA;AAE3B,EAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA,EAAG;AACtB,IAAA,MAAM,IAAI,eAAA;AAAA,MACN,aAAA;AAAA,MACA,yBAAyB,GAAG,CAAA,0CAAA,CAAA;AAAA,MAC5B;AAAA,QACI,MAAA,EAAQ,MAAA;AAAA,QACR,IAAA,EAAM,EAAE,QAAA,EAAU,GAAA,EAAK,QAAA,EAAU,WAAW,MAAA,CAAO,IAAA,CAAK,QAAQ,CAAA,GAAI,QAAA;AAAS;AACjF,KACJ;AAAA,EACJ;AAEA,EAAA,MAAM,QAAQ,QAAA,EAAU,KAAA;AACxB,EAAA,OAAO;AAAA,IACH,IAAA;AAAA;AAAA;AAAA,IAGA,KAAA,EAAO,OAAO,KAAA,KAAU,QAAA,GAAW,QAAQ,IAAA,CAAK;AAAA,GACpD;AACJ;AAGO,SAAS,SAAA,CAAa,MAAe,GAAA,EAAgB;AACxD,EAAA,MAAM,QAAA,GAAW,IAAA;AACjB,EAAA,MAAM,KAAA,GAAQ,WAAW,GAAG,CAAA;AAE5B,EAAA,IAAI,KAAA,KAAU,MAAA,IAAa,KAAA,KAAU,IAAA,EAAM;AACvC,IAAA,MAAM,IAAI,eAAA,CAAgB,aAAA,EAAe,CAAA,sBAAA,EAAyB,GAAG,CAAA,EAAA,CAAA,EAAM;AAAA,MACvE,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,EAAE,QAAA,EAAU,GAAA,EAAK,QAAA,EAAU,WAAW,MAAA,CAAO,IAAA,CAAK,QAAQ,CAAA,GAAI,QAAA;AAAS,KAChF,CAAA;AAAA,EACL;AACA,EAAA,OAAO,KAAA;AACX;AAQA,gBAAuB,YAAA,CACnB,SAAA,EACA,OAAA,GAAuB,EAAC,EACP;AACjB,EAAA,MAAM,KAAA,GAAQ,QAAQ,KAAA,IAAS,iBAAA;AAC/B,EAAA,IAAI,MAAA,GAAS,QAAQ,MAAA,IAAU,CAAA;AAE/B,EAAA,KAAA,IAAS,IAAA,GAAO,CAAA,EAAG,IAAA,GAAO,SAAA,EAAW,IAAA,EAAA,EAAQ;AACzC,IAAA,MAAM,EAAE,MAAK,GAAI,MAAM,UAAU,EAAE,KAAA,EAAO,QAAQ,CAAA;AAClD,IAAA,IAAI,CAAC,KAAK,MAAA,EAAQ;AACd,MAAA;AAAA,IACJ;AACA,IAAA,KAAA,MAAW,QAAQ,IAAA,EAAM;AACrB,MAAA,MAAM,IAAA;AAAA,IACV;AAGA,IAAA,IAAI,IAAA,CAAK,SAAS,KAAA,EAAO;AACrB,MAAA;AAAA,IACJ;AACA,IAAA,MAAA,IAAU,IAAA,CAAK,MAAA;AAAA,EACnB;AAEA,EAAA,MAAM,IAAI,eAAA;AAAA,IACN,aAAA;AAAA,IACA,+BAAyB,SAAS,CAAA,4DAAA,CAAA;AAAA,IAClC,EAAE,QAAQ,MAAA;AAAO,GACrB;AACJ;;;AC1GO,IAAe,WAAf,MAAwB;AAAA,EAC3B,YAA+B,MAAA,EAAuB;AAAvB,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAAA,EAAwB;AAAA,EAAxB,MAAA;AAAA,EAE/B,MAAgB,IAAA,CAAQ,OAAA,EAAsB,OAAA,GAA0B,EAAC,EAAe;AACpF,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,MAAA,CAAO,OAAA,CAAW;AAAA,MAC1C,GAAG,OAAA;AAAA,MACH,GAAI,QAAQ,MAAA,KAAW,MAAA,GAAY,EAAC,GAAI,EAAE,MAAA,EAAQ,OAAA,CAAQ,MAAA,EAAO;AAAA,MACjE,GAAI,QAAQ,SAAA,KAAc,MAAA,GAAY,EAAC,GAAI,EAAE,SAAA,EAAW,OAAA,CAAQ,SAAA;AAAU,KAC7E,CAAA;AACD,IAAA,OAAO,QAAA,CAAS,IAAA;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASU,OAAA,CAAW,IAAA,EAAc,KAAA,EAAe,OAAA,EAAsC;AACpF,IAAA,OAAO,IAAA,CAAK,IAAA,CAAQ,EAAE,MAAA,EAAQ,OAAO,IAAA,EAAM,GAAI,KAAA,GAAQ,EAAE,KAAA,EAAM,GAAI,EAAC,IAAM,OAAO,CAAA;AAAA,EACrF;AAAA,EAEU,QAAA,CAAY,IAAA,EAAc,IAAA,EAAgB,OAAA,EAA0B,KAAA,EAA2B;AACrG,IAAA,OAAO,IAAA,CAAK,IAAA;AAAA,MACR,EAAE,MAAA,EAAQ,MAAA,EAAQ,MAAM,GAAI,IAAA,KAAS,SAAY,EAAC,GAAI,EAAE,IAAA,IAAS,GAAI,KAAA,GAAQ,EAAE,KAAA,EAAM,GAAI,EAAC,EAAG;AAAA,MAC7F;AAAA,KACJ;AAAA,EACJ;AAAA,EAEU,OAAA,CAAW,IAAA,EAAc,IAAA,EAAgB,OAAA,EAAsC;AACrF,IAAA,OAAO,IAAA,CAAK,IAAA,CAAQ,EAAE,MAAA,EAAQ,OAAO,IAAA,EAAM,GAAI,IAAA,KAAS,MAAA,GAAY,EAAC,GAAI,EAAE,IAAA,EAAK,IAAM,OAAO,CAAA;AAAA,EACjG;AAAA,EAEU,UAAA,CAAc,IAAA,EAAc,KAAA,EAAe,OAAA,EAAsC;AACvF,IAAA,OAAO,IAAA,CAAK,IAAA,CAAQ,EAAE,MAAA,EAAQ,UAAU,IAAA,EAAM,GAAI,KAAA,GAAQ,EAAE,KAAA,EAAM,GAAI,EAAC,IAAM,OAAO,CAAA;AAAA,EACxF;AAAA;AAAA,EAGA,MAAgB,OAAA,CACZ,IAAA,EACA,GAAA,EACA,OACA,OAAA,EACqB;AACrB,IAAA,OAAO,UAAA,CAAc,MAAM,IAAA,CAAK,OAAA,CAAiB,MAAM,KAAA,EAAO,OAAO,GAAG,GAAG,CAAA;AAAA,EAC/E;AAAA;AAAA,EAGA,MAAgB,MAAA,CACZ,IAAA,EACA,GAAA,EACA,OACA,OAAA,EACU;AACV,IAAA,OAAO,SAAA,CAAa,MAAM,IAAA,CAAK,OAAA,CAAiB,MAAM,KAAA,EAAO,OAAO,GAAG,GAAG,CAAA;AAAA,EAC9E;AAAA;AAAA,EAGA,MAAgB,OAAA,CACZ,IAAA,EACA,GAAA,EACA,IAAA,EACA,SACA,KAAA,EACU;AACV,IAAA,OAAO,SAAA,CAAa,MAAM,IAAA,CAAK,QAAA,CAAkB,MAAM,IAAA,EAAM,OAAA,EAAS,KAAK,CAAA,EAAG,GAAG,CAAA;AAAA,EACrF;AAAA;AAAA,EAGA,MAAgB,MAAA,CACZ,IAAA,EACA,GAAA,EACA,MACA,OAAA,EACU;AACV,IAAA,OAAO,SAAA,CAAa,MAAM,IAAA,CAAK,OAAA,CAAiB,MAAM,IAAA,EAAM,OAAO,GAAG,GAAG,CAAA;AAAA,EAC7E;AACJ,CAAA;AAOO,SAAS,SAAA,CAAU,OAAe,IAAA,EAAsB;AAC3D,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,CAAC,KAAA,CAAM,MAAK,EAAG;AAC5C,IAAA,MAAM,IAAI,SAAA,CAAU,CAAA,MAAA,EAAS,IAAI,CAAA,CAAA,CAAG,CAAA;AAAA,EACxC;AACA,EAAA,OAAO,KAAA;AACX;;;ACnCO,IAAM,gBAAA,GAAN,cAA+B,QAAA,CAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAc3C,MAAM,YAAA,CAAa,cAAA,EAAwB,OAAA,GAA+B,EAAC,EAA2B;AAClG,IAAA,OAAO,SAAA;AAAA,MACH,MAAM,IAAA,CAAK,OAAA;AAAA,QACP,CAAA,eAAA,EAAkB,SAAA,CAAU,cAAA,EAAgB,gBAAgB,CAAC,CAAA,cAAA,CAAA;AAAA,QAC7D,EAAE,cAAA,EAAgB,OAAA,CAAQ,cAAA,EAAgB,YAAA,EAAc,QAAQ,YAAA,EAAa;AAAA,QAC7E;AAAA,OACJ;AAAA,MACA;AAAA,KACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoBA,MAAM,QACF,cAAA,EACA,aAAA,EACA,SAAgC,EAAC,EACjC,OAAA,GAA0B,EAAC,EACL;AACtB,IAAA,MAAM,IAAA,GACF,CAAA,eAAA,EAAkB,SAAA,CAAU,cAAA,EAAgB,gBAAgB,CAAC,CAAA,iBAAA,EACzC,SAAA,CAAU,aAAA,EAAe,eAAe,CAAC,CAAA,CAAA;AACjE,IAAA,MAAM,OAAO,MAAM,IAAA,CAAK,OAAA,CAKrB,IAAA,EAAM,QAAiB,OAAO,CAAA;AAEjC,IAAA,IAAI,KAAK,SAAA,EAAW;AAIhB,MAAA,MAAM,IAAA,GAAO,MAAA,CAAO,IAAA,CAAK,SAAS,CAAA;AAClC,MAAA,MAAM,uBAAA,CAAwB;AAAA,QAC1B,IAAA,EAAM;AAAA,UACF,IAAA,EAAM,MAAA,CAAO,QAAA,CAAS,IAAI,IAAI,IAAA,GAAO,aAAA;AAAA,UACrC,OAAA,EAAS,IAAA,CAAK,QAAA,IAAY,CAAA,kCAAA,EAA+B,KAAK,SAAS,CAAA,EAAA;AAAA,SAC3E;AAAA,QACA,MAAA,EAAQ;AAAA,OACX,CAAA;AAAA,IACL;AAEA,IAAA,OAAO;AAAA,MACH,QAAA,EAAU,IAAA,CAAK,QAAA,IAAY,EAAC;AAAA,MAC5B,GAAI,KAAK,YAAA,KAAiB,MAAA,GAAY,EAAC,GAAI,EAAE,YAAA,EAAc,IAAA,CAAK,YAAA;AAAa,KACjF;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,MAAA,CACF,cAAA,EACA,SAAA,EACA,OAAA,GAA0B,EAAC,EACN;AACrB,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,QAAA;AAAA,MACpB,CAAA,EAAG,IAAA,CAAK,IAAA,CAAK,cAAA,EAAgB,SAAS,CAAC,CAAA,OAAA,CAAA;AAAA,MACvC,MAAA;AAAA,MACA;AAAA,KACJ;AAGA,IAAA,OAAO,IAAA,CAAK,iBAAiB,MAAA,GAAY,KAAK,EAAE,YAAA,EAAc,KAAK,YAAA,EAAa;AAAA,EACpF;AAAA;AAAA,EAGA,MAAM,IAAA,CACF,cAAA,EACA,OAAA,GAA+C,EAAC,EACrB;AAC3B,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,MACR,CAAA,eAAA,EAAkB,SAAA,CAAU,cAAA,EAAgB,gBAAgB,CAAC,CAAA,SAAA,CAAA;AAAA,MAC7D,UAAA;AAAA,MACA;AAAA,QACI,QAAQ,OAAA,CAAQ,MAAA;AAAA,QAChB,OAAO,OAAA,CAAQ,KAAA;AAAA,QACf,MAAM,OAAA,CAAQ,IAAA;AAAA,QACd,gBAAgB,OAAA,CAAQ,cAAA;AAAA,QACxB,UAAU,OAAA,CAAQ,QAAA;AAAA,QAClB,YAAY,OAAA,CAAQ;AAAA,OACxB;AAAA,MACA;AAAA,KACJ;AAAA,EACJ;AAAA;AAAA,EAGA,OAAA,CACI,cAAA,EACA,OAAA,GAA+C,EAAC,EACzB;AACvB,IAAA,OAAO,YAAA,CAAsB,CAAC,IAAA,KAAS,IAAA,CAAK,IAAA,CAAK,cAAA,EAAgB,EAAE,GAAG,OAAA,EAAS,GAAG,IAAA,EAAM,GAAG,OAAO,CAAA;AAAA,EACtG;AAAA;AAAA,EAGA,MAAM,GAAA,CAAI,cAAA,EAAwB,SAAA,EAAmB,OAAA,GAA0B,EAAC,EAAqB;AACjG,IAAA,OAAO,IAAA,CAAK,OAAgB,IAAA,CAAK,IAAA,CAAK,gBAAgB,SAAS,CAAA,EAAG,SAAA,EAAW,MAAA,EAAW,OAAO,CAAA;AAAA,EACnG;AAAA;AAAA,EAGA,MAAM,MAAA,CACF,cAAA,EACA,WACA,IAAA,EACA,OAAA,GAA0B,EAAC,EACX;AAChB,IAAA,OAAO,IAAA,CAAK,OAAgB,IAAA,CAAK,IAAA,CAAK,gBAAgB,SAAS,CAAA,EAAG,SAAA,EAAW,IAAA,EAAM,OAAO,CAAA;AAAA,EAC9F;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,MAAA,CAAO,cAAA,EAAwB,SAAA,EAAmB,OAAA,GAA0B,EAAC,EAAkB;AACjG,IAAA,MAAM,IAAA,CAAK,WAA4B,IAAA,CAAK,IAAA,CAAK,gBAAgB,SAAS,CAAA,EAAG,QAAW,OAAO,CAAA;AAAA,EACnG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,OAAA,CACF,cAAA,EACA,SAAA,EACA,OAAA,GAAiC,EAAC,EACX;AACvB,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,MACR,CAAA,EAAG,IAAA,CAAK,IAAA,CAAK,cAAA,EAAgB,SAAS,CAAC,CAAA,QAAA,CAAA;AAAA,MACvC;AAAA,QACI,WAAW,OAAA,CAAQ,SAAA;AAAA,QACnB,SAAS,OAAA,CAAQ,OAAA;AAAA,QACjB,OAAO,OAAA,CAAQ;AAAA,OACnB;AAAA,MACA;AAAA,KACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,UAAA,CACF,cAAA,EACA,SAAA,EACA,OAAA,GAA0B,EAAC,EACV;AACjB,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,MACR,CAAA,EAAG,IAAA,CAAK,IAAA,CAAK,cAAA,EAAgB,SAAS,CAAC,CAAA,YAAA,CAAA;AAAA,MACvC,MAAA;AAAA,MACA;AAAA,KACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,iBAAA,CACF,cAAA,EACA,SAAA,EACA,OAAA,GAA0B,EAAC,EACJ;AACvB,IAAA,OAAO,SAAA;AAAA,MACH,MAAM,IAAA,CAAK,OAAA;AAAA,QACP,CAAA,EAAG,IAAA,CAAK,IAAA,CAAK,cAAA,EAAgB,SAAS,CAAC,CAAA,gBAAA,CAAA;AAAA,QACvC,MAAA;AAAA,QACA;AAAA,OACJ;AAAA,MACA;AAAA,KACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,iBAAA,CACF,cAAA,EACA,WACA,IAAA,EACA,OAAA,GAA0B,EAAC,EACJ;AACvB,IAAA,OAAO,SAAA;AAAA,MACH,MAAM,IAAA,CAAK,QAAA;AAAA,QACP,CAAA,EAAG,IAAA,CAAK,IAAA,CAAK,cAAA,EAAgB,SAAS,CAAC,CAAA,gBAAA,CAAA;AAAA,QACvC,EAAE,iBAAiB,IAAA,EAAK;AAAA,QACxB;AAAA,OACJ;AAAA,MACA;AAAA,KACJ;AAAA,EACJ;AAAA,EAEQ,IAAA,CAAK,gBAAwB,SAAA,EAA2B;AAC5D,IAAA,OAAO,CAAA,eAAA,EAAkB,UAAU,cAAA,EAAgB,gBAAgB,CAAC,CAAA,UAAA,EAAa,SAAA,CAAU,SAAA,EAAW,WAAW,CAAC,CAAA,CAAA;AAAA,EACtH;AACJ;;;ACtSO,IAAM,eAAA,GAAN,cAA8B,QAAA,CAAS;AAAA,EACzB,KAAA,uBAAY,GAAA,EAA8B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO3D,MAAM,eAAe,OAAA,EAAoD;AACrE,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,MAAO,kBAAA;AAAA,MAAoB,MACnC,IAAA,CAAK,OAAA,CAAyB,kBAAA,EAAoB,QAAW,OAAO;AAAA,KACxE;AAAA,EACJ;AAAA;AAAA,EAGA,MAAM,0BAA0B,OAAA,EAAoD;AAChF,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,MAAO,8BAAA;AAAA,MAAgC,MAC/C,IAAA,CAAK,OAAA,CAAyB,8BAAA,EAAgC,QAAW,OAAO;AAAA,KACpF;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,sBAAsB,OAAA,EAAoD;AAC5E,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,MAAO,0BAAA;AAAA,MAA4B,MAC3C,IAAA,CAAK,QAAA,CAA0B,0BAAA,EAA4B,QAAW,OAAO;AAAA,KACjF;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,mBAAmB,OAAA,EAAuE;AAC5F,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,MAAO,sBAAA;AAAA,MAAwB,MACvC,IAAA,CAAK,OAAA,CAA4C,sBAAA,EAAwB,QAAW,OAAO;AAAA,KAC/F;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,qBAAqB,OAAA,EAAmE;AAC1F,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,MAAO,yBAAA;AAAA,MAA2B,MAC1C,IAAA,CAAK,OAAA,CAAwC,yBAAA,EAA2B,QAAW,OAAO;AAAA,KAC9F;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,aAAa,OAAA,EAAiD;AAChE,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,MAAO,gBAAA;AAAA,MAAkB,MACjC,IAAA,CAAK,OAAA,CAAsB,gBAAA,EAAkB,QAAW,OAAO;AAAA,KACnE;AAAA,EACJ;AAAA;AAAA,EAGA,MAAM,kBAAkB,OAAA,EAAsD;AAC1E,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,MAAO,qBAAA;AAAA,MAAuB,MACtC,IAAA,CAAK,OAAA,CAA2B,qBAAA,EAAuB,QAAW,OAAO;AAAA,KAC7E;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,oBAAoB,OAAA,EAA0D;AAChF,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,MAAO,wBAAA;AAAA,MAA0B,MACzC,IAAA,CAAK,OAAA,CAA+B,wBAAA,EAA0B,QAAW,OAAO;AAAA,KACpF;AAAA,EACJ;AAAA;AAAA,EAGA,UAAA,GAAmB;AACf,IAAA,IAAA,CAAK,MAAM,KAAA,EAAM;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,MAAA,CAAU,KAAa,KAAA,EAAqC;AAChE,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,GAAG,CAAA;AAC9B,IAAA,IAAI,GAAA,EAAK;AACL,MAAA,OAAO,GAAA;AAAA,IACX;AACA,IAAA,MAAM,OAAA,GAAU,KAAA,EAAM,CAAE,KAAA,CAAM,CAAC,KAAA,KAAmB;AAC9C,MAAA,IAAA,CAAK,KAAA,CAAM,OAAO,GAAG,CAAA;AACrB,MAAA,MAAM,KAAA;AAAA,IACV,CAAC,CAAA;AACD,IAAA,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,GAAA,EAAK,OAAO,CAAA;AAC3B,IAAA,OAAO,OAAA;AAAA,EACX;AACJ;;;AC/GO,IAAM,eAAA,GAAN,cAA8B,QAAA,CAAS;AAAA;AAAA,EAE1C,MAAM,IAAA,CAAK,OAAA,GAA8C,EAAC,EAA+B;AACrF,IAAA,OAAO,KAAK,OAAA,CAAgB,UAAA,EAAY,WAAW,SAAA,CAAU,OAAO,GAAG,OAAO,CAAA;AAAA,EAClF;AAAA;AAAA,EAGA,OAAA,CAAQ,OAAA,GAA8C,EAAC,EAA2B;AAC9E,IAAA,OAAO,YAAA,CAAqB,CAAC,IAAA,KAAS,IAAA,CAAK,IAAA,CAAK,EAAE,GAAG,OAAA,EAAS,GAAG,IAAA,EAAM,CAAA,EAAG,OAAO,CAAA;AAAA,EACrF;AAAA;AAAA,EAGA,MAAM,GAAA,CACF,QAAA,EACA,OAAA,GAA6D,EAAC,EAC/C;AACf,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,MACR,CAAA,SAAA,EAAY,SAAA,CAAU,QAAA,EAAU,UAAU,CAAC,CAAA,CAAA;AAAA,MAC3C,QAAA;AAAA,MACA,OAAA,CAAQ,MAAA,GAAS,EAAE,MAAA,EAAQ,MAAK,GAAI,MAAA;AAAA,MACpC;AAAA,KACJ;AAAA,EACJ;AAAA;AAAA,EAGA,MAAM,MAAA,CAAO,QAAA,EAAkB,IAAA,EAAyB,OAAA,GAA0B,EAAC,EAAoB;AACnG,IAAA,OAAO,IAAA,CAAK,MAAA,CAAO,CAAA,SAAA,EAAY,SAAA,CAAU,QAAA,EAAU,UAAU,CAAC,CAAA,CAAA,EAAI,QAAA,EAAU,IAAA,EAAM,OAAO,CAAA;AAAA,EAC7F;AAAA;AAAA,EAGA,MAAM,aAAA,CACF,QAAA,EACA,OAAA,GAAoD,EAAC,EACrB;AAChC,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,MACR,CAAA,SAAA,EAAY,SAAA,CAAU,QAAA,EAAU,UAAU,CAAC,CAAA,cAAA,CAAA;AAAA,MAC3C,eAAA;AAAA,MACA,EAAE,GAAG,SAAA,CAAU,OAAO,CAAA,EAAG,IAAA,EAAM,QAAQ,IAAA,EAAK;AAAA,MAC5C;AAAA,KACJ;AAAA,EACJ;AAAA;AAAA,EAGA,oBAAA,CACI,QAAA,EACA,OAAA,GAAoD,EAAC,EACzB;AAC5B,IAAA,OAAO,YAAA;AAAA,MACH,CAAC,IAAA,KAAS,IAAA,CAAK,aAAA,CAAc,QAAA,EAAU,EAAE,GAAG,OAAA,EAAS,GAAG,IAAA,EAAM,CAAA;AAAA,MAC9D;AAAA,KACJ;AAAA,EACJ;AAAA;AAAA,EAGA,MAAM,kBAAA,CACF,QAAA,EACA,IAAA,EACA,OAAA,GAA0B,EAAC,EACN;AACrB,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,MACR,CAAA,SAAA,EAAY,SAAA,CAAU,QAAA,EAAU,UAAU,CAAC,CAAA,cAAA,CAAA;AAAA,MAC3C,cAAA;AAAA,MACA,IAAA;AAAA,MACA;AAAA,KACJ;AAAA,EACJ;AAAA;AAAA,EAGA,MAAM,kBAAA,CACF,QAAA,EACA,gBACA,IAAA,EACA,OAAA,GAA0B,EAAC,EACN;AACrB,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,MACR,CAAA,SAAA,EAAY,UAAU,QAAA,EAAU,UAAU,CAAC,CAAA,eAAA,EAAkB,SAAA,CAAU,cAAA,EAAgB,gBAAgB,CAAC,CAAA,CAAA;AAAA,MACxG,cAAA;AAAA,MACA,IAAA;AAAA,MACA;AAAA,KACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,kBAAA,CACF,QAAA,EACA,cAAA,EACA,OAAA,GAA0B,EAAC,EACd;AACb,IAAA,MAAM,IAAA,CAAK,UAAA;AAAA,MACP,CAAA,SAAA,EAAY,UAAU,QAAA,EAAU,UAAU,CAAC,CAAA,eAAA,EAAkB,SAAA,CAAU,cAAA,EAAgB,gBAAgB,CAAC,CAAA,CAAA;AAAA,MACxG,MAAA;AAAA,MACA;AAAA,KACJ;AAAA,EACJ;AACJ;AAEA,SAAS,UAAU,OAAA,EAAmF;AAClG,EAAA,OAAO;AAAA,IACH,QAAQ,OAAA,CAAQ,MAAA;AAAA,IAChB,OAAO,OAAA,CAAQ,KAAA;AAAA;AAAA,IAEf,MAAA,EAAQ,OAAA,CAAQ,MAAA,GAAS,IAAA,GAAO;AAAA,GACpC;AACJ;;;AClGO,IAAM,qBAAA,GAAN,cAAoC,QAAA,CAAS;AAAA;AAAA,EAEhD,MAAM,GAAA,CAAI,cAAA,EAAwB,OAAA,GAA+B,EAAC,EAA0B;AACxF,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,MACR,CAAA,eAAA,EAAkB,SAAA,CAAU,cAAA,EAAgB,gBAAgB,CAAC,CAAA,CAAA;AAAA,MAC7D,cAAA;AAAA,MACA,OAAA,CAAQ,MAAA,GAAS,EAAE,MAAA,EAAQ,MAAK,GAAI,MAAA;AAAA,MACpC;AAAA,KACJ;AAAA,EACJ;AAAA;AAAA,EAGA,MAAM,MAAA,CACF,cAAA,EACA,IAAA,EACA,OAAA,GAA0B,EAAC,EACN;AACrB,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,MACR,CAAA,eAAA,EAAkB,SAAA,CAAU,cAAA,EAAgB,gBAAgB,CAAC,CAAA,CAAA;AAAA,MAC7D,cAAA;AAAA,MACA,IAAA;AAAA,MACA;AAAA,KACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,MAAA,CAAO,cAAA,EAAwB,OAAA,GAA0B,EAAC,EAAkB;AAC9E,IAAA,MAAM,IAAA,CAAK,UAAA;AAAA,MACP,CAAA,eAAA,EAAkB,SAAA,CAAU,cAAA,EAAgB,gBAAgB,CAAC,CAAA,CAAA;AAAA,MAC7D,MAAA;AAAA,MACA;AAAA,KACJ;AAAA,EACJ;AAAA;AAAA,EAGA,MAAM,QAAA,CACF,cAAA,EACA,OAAA,GAAwC,EAAC,EACT;AAChC,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,MACR,CAAA,eAAA,EAAkB,SAAA,CAAU,cAAA,EAAgB,gBAAgB,CAAC,CAAA,cAAA,CAAA;AAAA,MAC7D,eAAA;AAAA,MACA;AAAA,QACI,QAAQ,OAAA,CAAQ,MAAA;AAAA,QAChB,OAAO,OAAA,CAAQ,KAAA;AAAA,QACf,MAAM,OAAA,CAAQ,IAAA;AAAA,QACd,MAAA,EAAQ,OAAA,CAAQ,MAAA,GAAS,IAAA,GAAO;AAAA,OACpC;AAAA,MACA;AAAA,KACJ;AAAA,EACJ;AAAA;AAAA,EAGA,eAAA,CACI,cAAA,EACA,OAAA,GAAwC,EAAC,EACb;AAC5B,IAAA,OAAO,YAAA;AAAA,MACH,CAAC,IAAA,KAAS,IAAA,CAAK,QAAA,CAAS,cAAA,EAAgB,EAAE,GAAG,OAAA,EAAS,GAAG,IAAA,EAAM,CAAA;AAAA,MAC/D;AAAA,KACJ;AAAA,EACJ;AAAA;AAAA,EAGA,MAAM,WAAA,CACF,cAAA,EACA,IAAA,EACA,OAAA,GAA0B,EAAC,EACN;AACrB,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,MACR,CAAA,eAAA,EAAkB,SAAA,CAAU,cAAA,EAAgB,gBAAgB,CAAC,CAAA,cAAA,CAAA;AAAA,MAC7D,cAAA;AAAA,MACA,IAAA;AAAA,MACA;AAAA,KACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,MAAA,CAAO,cAAA,EAAwB,OAAA,GAA0B,EAAC,EAAsB;AAClF,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,MACR,CAAA,eAAA,EAAkB,SAAA,CAAU,cAAA,EAAgB,gBAAgB,CAAC,CAAA,OAAA,CAAA;AAAA,MAC7D,MAAA;AAAA,MACA;AAAA,KACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,GAAA,CACF,cAAA,EACA,OAAA,GAA0B,EAAC,EACwD;AACnF,IAAA,MAAM,YAAA,GAAe,MAAM,IAAA,CAAK,GAAA,CAAI,cAAA,EAAgB,EAAE,GAAG,OAAA,EAAS,MAAA,EAAQ,IAAA,EAAM,CAAA;AAChF,IAAA,OAAO,EAAE,UAAA,EAAY,YAAA,CAAa,UAAA,EAAY,cAAA,EAAgB,aAAa,cAAA,EAAe;AAAA,EAC9F;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoBA,MAAM,kBAAA,CACF,cAAA,EACA,OAAA,GAA+B,EAAC,EACX;AACrB,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,MACR,CAAA,eAAA,EAAkB,SAAA,CAAU,cAAA,EAAgB,gBAAgB,CAAC,CAAA,uBAAA,CAAA;AAAA,MAC7D,EAAE,cAAA,EAAgB,OAAA,CAAQ,cAAA,EAAgB,YAAA,EAAc,QAAQ,YAAA,EAAa;AAAA,MAC7E;AAAA,KACJ;AAAA,EACJ;AACJ;;;AC1HO,IAAM,oBAAA,GAAN,cAAmC,QAAA,CAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgB/C,MAAM,MAAA,CACF,cAAA,EACA,WACA,IAAA,EACA,OAAA,GAA0B,EAAC,EACP;AACpB,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,MACR,CAAA,eAAA,EAAkB,UAAU,cAAA,EAAgB,gBAAgB,CAAC,CAAA,UAAA,EAAa,SAAA,CAAU,SAAA,EAAW,WAAW,CAAC,CAAA,QAAA,CAAA;AAAA,MAC3G,aAAA;AAAA,MACA,eAAe,IAAI,CAAA;AAAA,MACnB;AAAA,KACJ;AAAA,EACJ;AAAA;AAAA,EAGA,MAAM,GAAA,CACF,cAAA,EACA,aAAA,EACA,OAAA,GAA0B,EAAC,EACP;AACpB,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,MACR,IAAA,CAAK,IAAA,CAAK,cAAA,EAAgB,aAAa,CAAA;AAAA,MACvC,aAAA;AAAA,MACA,MAAA;AAAA,MACA;AAAA,KACJ;AAAA,EACJ;AAAA;AAAA,EAGA,MAAM,IAAA,CACF,cAAA,EACA,OAAA,GAAmD,EAAC,EACrB;AAC/B,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,MACR,CAAA,eAAA,EAAkB,SAAA,CAAU,cAAA,EAAgB,gBAAgB,CAAC,CAAA,QAAA,CAAA;AAAA,MAC7D,cAAA;AAAA,MACAA,WAAU,OAAO,CAAA;AAAA,MACjB;AAAA,KACJ;AAAA,EACJ;AAAA;AAAA,EAGA,OAAA,CACI,cAAA,EACA,OAAA,GAAmD,EAAC,EACzB;AAC3B,IAAA,OAAO,YAAA;AAAA,MACH,CAAC,IAAA,KAAS,IAAA,CAAK,IAAA,CAAK,cAAA,EAAgB,EAAE,GAAG,OAAA,EAAS,GAAG,IAAA,EAAM,CAAA;AAAA,MAC3D;AAAA,KACJ;AAAA,EACJ;AAAA;AAAA,EAGA,MAAM,aAAA,CACF,cAAA,EACA,SAAA,EACA,OAAA,GAAmD,EAAC,EACrB;AAC/B,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,MACR,CAAA,eAAA,EAAkB,UAAU,cAAA,EAAgB,gBAAgB,CAAC,CAAA,UAAA,EAAa,SAAA,CAAU,SAAA,EAAW,WAAW,CAAC,CAAA,QAAA,CAAA;AAAA,MAC3G,cAAA;AAAA,MACAA,WAAU,OAAO,CAAA;AAAA,MACjB;AAAA,KACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,MAAA,CACF,cAAA,EACA,eACA,IAAA,EACA,OAAA,GAA0B,EAAC,EACP;AACpB,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,MACR,IAAA,CAAK,IAAA,CAAK,cAAA,EAAgB,aAAa,CAAA;AAAA,MACvC,aAAA;AAAA,MACA,eAAe,IAAI,CAAA;AAAA,MACnB;AAAA,KACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,MAAA,CAAO,cAAA,EAAwB,aAAA,EAAuB,OAAA,GAA0B,EAAC,EAAkB;AACrG,IAAA,MAAM,IAAA,CAAK,WAA4B,IAAA,CAAK,IAAA,CAAK,gBAAgB,aAAa,CAAA,EAAG,QAAW,OAAO,CAAA;AAAA,EACvG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,KAAA,CACF,cAAA,EACA,aAAA,EACA,OAAA,GAA0B,EAAC,EACI;AAC/B,IAAA,OAAO,IAAA,CAAK,QAAA;AAAA,MACR,CAAA,EAAG,IAAA,CAAK,IAAA,CAAK,cAAA,EAAgB,aAAa,CAAC,CAAA,MAAA,CAAA;AAAA,MAC3C,MAAA;AAAA,MACA;AAAA,KACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,OAAA,CACF,cAAA,EACA,aAAA,EACA,OAAA,GAA0B,EAAC,EACF;AACzB,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,MACR,CAAA,EAAG,IAAA,CAAK,IAAA,CAAK,cAAA,EAAgB,aAAa,CAAC,CAAA,QAAA,CAAA;AAAA,MAC3C,MAAA;AAAA,MACA;AAAA,KACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,KAAA,CACF,cAAA,EACA,aAAA,EACA,OAAA,GAA0B,EAAC,EACK;AAChC,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,MACR,CAAA,EAAG,IAAA,CAAK,IAAA,CAAK,cAAA,EAAgB,aAAa,CAAC,CAAA,MAAA,CAAA;AAAA,MAC3C,MAAA;AAAA,MACA;AAAA,KACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,aAAA,CACF,cAAA,EACA,SAAA,EACA,OAAA,GAAwC,EAAC,EACV;AAC/B,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,MACR,CAAA,eAAA,EAAkB,UAAU,cAAA,EAAgB,gBAAgB,CAAC,CAAA,UAAA,EAAa,SAAA,CAAU,SAAA,EAAW,WAAW,CAAC,CAAA,oBAAA,CAAA;AAAA,MAC3G,cAAA;AAAA,MACA,EAAE,MAAA,EAAQ,OAAA,CAAQ,MAAA,EAAQ,KAAA,EAAO,QAAQ,KAAA,EAAM;AAAA,MAC/C;AAAA,KACJ;AAAA,EACJ;AAAA,EAEQ,IAAA,CAAK,gBAAwB,aAAA,EAA+B;AAChE,IAAA,OAAO,CAAA,eAAA,EAAkB,UAAU,cAAA,EAAgB,gBAAgB,CAAC,CAAA,SAAA,EAAY,SAAA,CAAU,aAAA,EAAe,eAAe,CAAC,CAAA,CAAA;AAAA,EAC7H;AACJ;AAEA,SAASA,WAAU,OAAA,EAAwC;AACvD,EAAA,OAAO;AAAA,IACH,QAAQ,OAAA,CAAQ,MAAA;AAAA,IAChB,OAAO,OAAA,CAAQ,KAAA;AAAA,IACf,WAAW,OAAA,CAAQ,SAAA;AAAA,IACnB,SAAS,OAAA,CAAQ,OAAA;AAAA,IACjB,QAAQ,OAAA,CAAQ,MAAA;AAAA;AAAA,IAEhB,cAAA,EAAgB,OAAA,CAAQ,cAAA,GAAiB,IAAA,GAAO,MAAA;AAAA,IAChD,OAAO,OAAA,CAAQ,KAAA;AAAA,IACf,UAAU,OAAA,CAAQ,QAAA;AAAA,IAClB,gBAAgB,OAAA,CAAQ;AAAA,GAC5B;AACJ;AASA,SAAS,eAAe,IAAA,EAA0D;AAC9E,EAAA,MAAM,EAAE,YAAA,EAAc,GAAG,IAAA,EAAK,GAAI,IAAA;AAClC,EAAA,OAAO;AAAA,IACH,GAAG,IAAA;AAAA,IACH,GAAI,YAAA,KAAiB,MAAA,GACf,EAAC,GACD,EAAE,YAAA,EAAc,OAAO,YAAA,KAAiB,QAAA,GAAW,YAAA,GAAe,YAAA,CAAa,aAAY;AAAE,GACvG;AACJ;ACrOA,IAAM,iBAAA,GAAsD;AAAA,EACxD,GAAA,EAAK,YAAA;AAAA,EACL,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,GAAA,EAAK;AACT,CAAA;AAGO,SAAS,iBAAiB,QAAA,EAAsC;AACnE,EAAA,MAAM,YAAY,QAAA,CAAS,KAAA,CAAM,GAAG,CAAA,CAAE,GAAA,IAAO,WAAA,EAAY;AACzD,EAAA,OAAO,SAAA,GAAY,iBAAA,CAAkB,SAAS,CAAA,GAAI,MAAA;AACtD;AAEA,SAAS,SAAS,KAAA,EAA8C;AAC5D,EAAA,OAAO,KAAA,YAAiB,UAAA;AAC5B;AAQA,eAAsB,WAAW,KAAA,EAA6D;AAC1F,EAAA,MAAM,EAAE,MAAK,GAAI,KAAA;AAEjB,EAAA,IAAI,OAAO,SAAS,QAAA,EAAU;AAC1B,IAAA,MAAM,QAAA,GAAW,KAAA,CAAM,QAAA,IAAYC,aAAA,CAAS,IAAI,CAAA;AAChD,IAAA,MAAM,IAAA,GAAO,KAAA,CAAM,WAAA,IAAe,gBAAA,CAAiB,QAAQ,CAAA;AAC3D,IAAA,IAAI,CAAC,IAAA,EAAM;AACP,MAAA,MAAM,IAAI,qBAAA;AAAA,QACN,mCAAmC,QAAQ,CAAA,4GAAA;AAAA,OAE/C;AAAA,IACJ;AACA,IAAA,OAAO,EAAE,IAAA,EAAM,MAAM,eAAe,IAAA,EAAM,IAAI,GAAG,QAAA,EAAS;AAAA,EAC9D;AAEA,EAAA,IAAI,QAAA,CAAS,IAAI,CAAA,EAAG;AAChB,IAAA,MAAM,WAAW,KAAA,CAAM,QAAA;AACvB,IAAA,IAAI,CAAC,QAAA,EAAU;AACX,MAAA,MAAM,IAAI,sBAAsB,4DAA4D,CAAA;AAAA,IAChG;AACA,IAAA,MAAM,IAAA,GAAO,KAAA,CAAM,WAAA,IAAe,gBAAA,CAAiB,QAAQ,CAAA;AAC3D,IAAA,IAAI,CAAC,IAAA,EAAM;AACP,MAAA,MAAM,IAAI,qBAAA;AAAA,QACN,mCAAmC,QAAQ,CAAA,oBAAA;AAAA,OAC/C;AAAA,IACJ;AAEA,IAAA,OAAO,EAAE,IAAA,EAAM,IAAI,IAAA,CAAK,CAAC,IAAA,CAAK,KAAA,EAAO,CAAA,EAAG,EAAE,IAAA,EAAM,GAAG,QAAA,EAAS;AAAA,EAChE;AAEA,EAAA,IAAI,gBAAgB,IAAA,EAAM;AACtB,IAAA,MAAM,WAAW,KAAA,CAAM,QAAA,KAAa,IAAA,YAAgB,IAAA,GAAO,KAAK,IAAA,GAAO,MAAA,CAAA;AACvE,IAAA,IAAI,CAAC,QAAA,EAAU;AACX,MAAA,MAAM,IAAI,sBAAsB,qDAAqD,CAAA;AAAA,IACzF;AACA,IAAA,MAAM,OAAO,KAAA,CAAM,WAAA,KAAgB,IAAA,CAAK,IAAA,IAAQ,iBAAiB,QAAQ,CAAA,CAAA;AACzE,IAAA,IAAI,CAAC,IAAA,EAAM;AACP,MAAA,MAAM,IAAI,qBAAA;AAAA,QACN,mCAAmC,QAAQ,CAAA,oBAAA;AAAA,OAC/C;AAAA,IACJ;AAGA,IAAA,OAAO,EAAE,IAAA,EAAM,IAAA,CAAK,IAAA,KAAS,IAAA,GAAO,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,IAAA,CAAK,IAAA,EAAM,IAAI,GAAG,QAAA,EAAS;AAAA,EACxF;AAEA,EAAA,MAAM,IAAI,sBAAsB,yDAAyD,CAAA;AAC7F;AAQA,eAAsB,gBAAgB,KAAA,EAAqC;AACvE,EAAA,MAAM,EAAE,IAAA,EAAM,QAAA,EAAS,GAAI,MAAM,WAAW,KAAK,CAAA;AACjD,EAAA,MAAM,IAAA,GAAO,IAAI,QAAA,EAAS;AAC1B,EAAA,IAAA,CAAK,MAAA,CAAO,MAAA,EAAQ,IAAA,EAAM,QAAQ,CAAA;AAClC,EAAA,OAAO,IAAA;AACX;AAQA,eAAe,cAAA,CAAe,MAAc,IAAA,EAA6B;AACrE,EAAA,MAAM,EAAA,GAAK,MAAM,OAAO,IAAS,CAAA;AACjC,EAAA,MAAM,aAAc,EAAA,CACf,UAAA;AAEL,EAAA,IAAI,OAAO,eAAe,UAAA,EAAY;AAClC,IAAA,OAAO,UAAA,CAAW,IAAA,EAAM,EAAE,IAAA,EAAM,CAAA;AAAA,EACpC;AACA,EAAA,MAAM,EAAE,QAAA,EAAS,GAAI,MAAM,OAAO,aAAkB,CAAA;AACpD,EAAA,OAAO,IAAI,IAAA,CAAK,CAAC,MAAM,QAAA,CAAS,IAAI,CAAC,CAAA,EAAG,EAAE,IAAA,EAAM,CAAA;AACpD;;;ACvFO,IAAM,eAAA,GAAN,cAA8B,QAAA,CAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAW1C,MAAM,MAAA,CAAO,cAAA,EAAwB,KAAA,EAAkB,OAAA,GAA0B,EAAC,EAAoB;AAClG,IAAA,MAAM,IAAA,GAAO,MAAM,eAAA,CAAgB,KAAK,CAAA;AACxC,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,MACR,CAAA,eAAA,EAAkB,SAAA,CAAU,cAAA,EAAgB,gBAAgB,CAAC,CAAA,QAAA,CAAA;AAAA,MAC7D,QAAA;AAAA,MACA,IAAA;AAAA,MACA;AAAA,KACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,IAAA,CACF,cAAA,EACA,OAAA,GAAwC,EAAC,EACf;AAC1B,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,MACR,CAAA,eAAA,EAAkB,SAAA,CAAU,cAAA,EAAgB,gBAAgB,CAAC,CAAA,QAAA,CAAA;AAAA,MAC7D,SAAA;AAAA,MACA,EAAE,MAAA,EAAQ,OAAA,CAAQ,MAAA,EAAQ,KAAA,EAAO,QAAQ,KAAA,EAAM;AAAA,MAC/C;AAAA,KACJ;AAAA,EACJ;AAAA;AAAA,EAGA,OAAA,CAAQ,cAAA,EAAwB,OAAA,GAAwC,EAAC,EAA2B;AAChG,IAAA,OAAO,YAAA,CAAqB,CAAC,IAAA,KAAS,IAAA,CAAK,IAAA,CAAK,cAAA,EAAgB,EAAE,GAAG,OAAA,EAAS,GAAG,IAAA,EAAM,GAAG,OAAO,CAAA;AAAA,EACrG;AAAA;AAAA,EAGA,MAAM,GAAA,CAAI,cAAA,EAAwB,QAAA,EAAkB,OAAA,GAA0B,EAAC,EAAoB;AAC/F,IAAA,OAAO,IAAA,CAAK,OAAe,IAAA,CAAK,IAAA,CAAK,gBAAgB,QAAQ,CAAA,EAAG,QAAA,EAAU,MAAA,EAAW,OAAO,CAAA;AAAA,EAChG;AAAA;AAAA,EAGA,MAAM,MAAA,CACF,cAAA,EACA,UACA,IAAA,EACA,OAAA,GAA0B,EAAC,EACZ;AACf,IAAA,OAAO,IAAA,CAAK,OAAe,IAAA,CAAK,IAAA,CAAK,gBAAgB,QAAQ,CAAA,EAAG,QAAA,EAAU,IAAA,EAAM,OAAO,CAAA;AAAA,EAC3F;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,MAAA,CACF,cAAA,EACA,QAAA,EACA,OAAA,GAA4D,EAAC,EAChD;AACb,IAAA,MAAM,IAAA,CAAK,UAAA;AAAA,MACP,IAAA,CAAK,IAAA,CAAK,cAAA,EAAgB,QAAQ,CAAA;AAAA,MAClC,OAAA,CAAQ,KAAA,GAAQ,EAAE,WAAA,EAAa,MAAK,GAAI,MAAA;AAAA,MACxC;AAAA,KACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,MAAA,CACF,cAAA,EACA,eACA,KAAA,EACA,OAAA,GAA0B,EAAC,EACN;AACrB,IAAA,OAAO,IAAA,CAAK,QAAA;AAAA,MACR,CAAA,eAAA,EAAkB,SAAA,CAAU,cAAA,EAAgB,gBAAgB,CAAC,CAAA,eAAA,CAAA;AAAA,MAC7D,EAAE,cAAA,EAAgB,SAAA,CAAU,aAAA,EAAe,eAAe,GAAG,KAAA,EAAM;AAAA,MACnE;AAAA,KACJ;AAAA,EACJ;AAAA,EAEQ,IAAA,CAAK,gBAAwB,QAAA,EAA0B;AAC3D,IAAA,OAAO,CAAA,eAAA,EAAkB,UAAU,cAAA,EAAgB,gBAAgB,CAAC,CAAA,SAAA,EAAY,SAAA,CAAU,QAAA,EAAU,UAAU,CAAC,CAAA,CAAA;AAAA,EACnH;AACJ;;;ACnHA,SAAS,cAAA,GAAyB;AAC9B,EAAA,MAAM,OAAA,GACF,OAAO,OAAA,KAAY,WAAA,IAAe,OAAA,CAAQ,QAAA,EAAU,IAAA,GAAO,CAAA,MAAA,EAAS,OAAA,CAAQ,QAAA,CAAS,IAAI,CAAA,CAAA,GAAK,EAAA;AAClG,EAAA,OAAO,CAAA,gBAAA,EAAmB,OAAO,CAAA,EAAG,OAAO,CAAA,CAAA;AAC/C;AAEA,SAAS,QAAQ,IAAA,EAAkC;AAC/C,EAAA,OAAO,OAAO,OAAA,KAAY,WAAA,GAAc,OAAA,CAAQ,GAAA,GAAM,IAAI,CAAA,GAAI,MAAA;AAClE;AAKA,SAAS,gBAAA,GAA4B;AACjC,EAAA,MAAM,cAAe,UAAA,CAAmD,MAAA;AACxE,EAAA,OAAO,WAAA,KAAgB,MAAA,IAAa,WAAA,CAAY,QAAA,KAAa,MAAA;AACjE;AAEO,IAAM,UAAA,GAAN,MAAM,WAAA,CAAW;AAAA;AAAA,EAEX,OAAA;AAAA;AAAA,EAGA,OAAA;AAAA;AAAA,EAEA,OAAA;AAAA;AAAA,EAEA,aAAA;AAAA;AAAA,EAEA,QAAA;AAAA;AAAA,EAEA,OAAA;AAAA;AAAA,EAEA,YAAA;AAAA,EAEQ,IAAA;AAAA,EACA,IAAA;AAAA,EACA,OAAA;AAAA,EAEjB,WAAA,CAAY,OAAA,GAA6B,EAAC,EAAG;AACzC,IAAA,IAAI,gBAAA,EAAiB,IAAK,OAAA,CAAQ,uBAAA,KAA4B,IAAA,EAAM;AAChE,MAAA,MAAM,IAAI,qBAAA;AAAA,QACN;AAAA,OAEJ;AAAA,IACJ;AAEA,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA;AACf,IAAA,IAAA,CAAK,WAAW,OAAA,CAAQ,OAAA,IAAW,OAAA,CAAQ,qBAAqB,KAAK,kBAAA,EAAoB,OAAA;AAAA,MACrF,MAAA;AAAA,MACA;AAAA,KACJ;AAEA,IAAA,IAAA,CAAK,IAAA,GAAO,IAAI,UAAA,CAAW;AAAA,MACvB,SAAS,IAAA,CAAK,OAAA;AAAA,MACd,GAAI,QAAQ,SAAA,KAAc,MAAA,GAAY,EAAC,GAAI,EAAE,SAAA,EAAW,OAAA,CAAQ,SAAA,EAAU;AAAA,MAC1E,GAAI,QAAQ,KAAA,KAAU,MAAA,GAAY,EAAC,GAAI,EAAE,KAAA,EAAO,OAAA,CAAQ,KAAA,EAAM;AAAA,MAC9D,GAAI,QAAQ,KAAA,KAAU,MAAA,GAAY,EAAC,GAAI,EAAE,KAAA,EAAO,OAAA,CAAQ,KAAA,EAAM;AAAA,MAC9D,GAAI,QAAQ,KAAA,KAAU,MAAA,GAAY,EAAC,GAAI,EAAE,KAAA,EAAO,OAAA,CAAQ,KAAA,EAAM;AAAA,MAC9D,OAAA,EAAS,EAAE,YAAA,EAAc,cAAA,EAAe;AAAE,KAC7C,CAAA;AAED,IAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,QAAA,IAAY,OAAA,CAAQ,sBAAsB,CAAA;AACnE,IAAA,MAAM,YAAA,GAAe,OAAA,CAAQ,YAAA,IAAgB,OAAA,CAAQ,0BAA0B,CAAA;AAE/E,IAAA,IAAI,QAAQ,WAAA,EAAa;AACrB,MAAA,IAAA,CAAK,IAAA,GAAO,IAAI,eAAA,CAAgB,OAAA,CAAQ,WAAW,CAAA;AAAA,IACvD,CAAA,MAAA,IAAW,YAAY,YAAA,EAAc;AACjC,MAAA,IAAA,CAAK,IAAA,GAAO,IAAI,qBAAA,CAAsB,IAAA,CAAK,IAAA,EAAM;AAAA,QAC7C,QAAA;AAAA,QACA,YAAA;AAAA,QACA,OAAO,OAAA,CAAQ;AAAA,OAClB,CAAA;AAAA,IACL,CAAA,MAAO;AACH,MAAA,MAAM,IAAI,qBAAA;AAAA,QACN;AAAA,OAEJ;AAAA,IACJ;AAKA,IAAA,IAAA,CAAK,OAAA,GAAU,IAAI,eAAA,CAAgB,IAAI,CAAA;AACvC,IAAA,IAAA,CAAK,OAAA,GAAU,IAAI,eAAA,CAAgB,IAAI,CAAA;AACvC,IAAA,IAAA,CAAK,aAAA,GAAgB,IAAI,qBAAA,CAAsB,IAAI,CAAA;AACnD,IAAA,IAAA,CAAK,QAAA,GAAW,IAAI,gBAAA,CAAiB,IAAI,CAAA;AACzC,IAAA,IAAA,CAAK,OAAA,GAAU,IAAI,eAAA,CAAgB,IAAI,CAAA;AACvC,IAAA,IAAA,CAAK,YAAA,GAAe,IAAI,oBAAA,CAAqB,IAAI,CAAA;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,QAAW,OAAA,EAAgD;AAC7D,IAAA,IAAI;AACA,MAAA,OAAO,MAAM,IAAA,CAAK,IAAA,CAAQ,OAAO,CAAA;AAAA,IACrC,SAAS,KAAA,EAAO;AACZ,MAAA,IAAI,CAAC,YAAA,CAAa,KAAK,CAAA,EAAG;AACtB,QAAA,MAAM,KAAA;AAAA,MACV;AACA,MAAA,IAAA,CAAK,KAAK,UAAA,EAAW;AACrB,MAAA,OAAO,IAAA,CAAK,KAAQ,OAAO,CAAA;AAAA,IAC/B;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,gBAAgB,KAAA,EAA2B;AACvC,IAAA,OAAO,IAAI,WAAA,CAAW;AAAA,MAClB,GAAG,IAAA,CAAK,OAAA;AAAA,MACR,QAAA,EAAU,MAAA;AAAA,MACV,YAAA,EAAc,MAAA;AAAA,MACd,WAAA,EAAa,KAAA;AAAA,MACb,SAAS,IAAA,CAAK;AAAA,KACjB,CAAA;AAAA,EACL;AAAA,EAEA,MAAc,KAAQ,OAAA,EAAgD;AAClE,IAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,IAAA,CAAK,QAAA,EAAS;AACvC,IAAA,OAAO,IAAA,CAAK,KAAK,OAAA,CAAW;AAAA,MACxB,GAAG,OAAA;AAAA,MACH,OAAA,EAAS,EAAE,GAAG,OAAA,CAAQ,SAAS,aAAA,EAAe,CAAA,OAAA,EAAU,KAAK,CAAA,CAAA;AAAG,KACnE,CAAA;AAAA,EACL;AACJ;;;ACkRO,SAAS,UAAU,WAAA,EAAsD;AAC5E,EAAA,MAAM,QAAQ,WAAA,CAAY,UAAA;AAC1B,EAAA,OAAO,OAAO,KAAA,KAAU,QAAA,GAAW,KAAA,GAAQ,KAAA,CAAM,GAAA;AACrD;AAMO,SAAS,QAAQ,WAAA,EAAmE;AACvF,EAAA,MAAM,QAAQ,WAAA,CAAY,UAAA;AAC1B,EAAA,OAAO,OAAO,KAAA,KAAU,QAAA,GAAW,MAAA,GAAY,KAAA;AACnD;AAUO,SAAS,iBACZ,OAAA,EACmC;AACnC,EAAA,IAAI,QAAQ,eAAA,EAAiB;AACzB,IAAA,OAAO,UAAA;AAAA,EACX;AACA,EAAA,OAAO,OAAA,CAAQ,aAAa,UAAA,GAAa,SAAA;AAC7C;AAQO,SAAS,iBACZ,OAAA,EACkB;AAClB,EAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,eAAA,IAAmB,OAAA,CAAQ,UAAA;AACjD,EAAA,IAAI,UAAU,MAAA,EAAW;AACrB,IAAA,OAAO,MAAA;AAAA,EACX;AACA,EAAA,OAAO,OAAO,KAAA,KAAU,QAAA,GAAW,KAAA,GAAQ,KAAA,CAAM,GAAA;AACrD;AAMO,SAAS,eACZ,OAAA,EACmB;AACnB,EAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,eAAA,IAAmB,OAAA,CAAQ,UAAA;AACjD,EAAA,OAAO,KAAA,KAAU,MAAA,IAAa,OAAO,KAAA,KAAU,WAAW,MAAA,GAAY,KAAA;AAC1E;AAMO,SAAS,aAAa,OAAA,EAAqD;AAC9E,EAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,eAAA,EAAiB,KAAA,IAAS,EAAC;AACjD,EAAA,OAAO,MAAM,MAAA,CAAO,CAAC,IAAA,KAAyB,OAAO,SAAS,QAAQ,CAAA;AAC1E;AAGO,SAAS,eAAe,OAAA,EAAqD;AAChF,EAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,eAAA,EAAiB,KAAA,IAAS,EAAC;AACjD,EAAA,OAAO,KAAA,CAAM,IAAI,CAAC,IAAA,KAAU,OAAO,IAAA,KAAS,QAAA,GAAW,IAAA,GAAO,IAAA,CAAK,GAAI,CAAA;AAC3E","file":"index.cjs","sourcesContent":["/**\n * Las dos constantes que todo lo demás necesita. Viven aparte de `index.ts` para que `client.ts`\n * pueda leerlas sin importar el punto de entrada, que a su vez le importa a él: el ciclo compila,\n * pero deja el orden de inicialización en manos del bundler y eso se paga tarde y mal.\n */\n\n/** La única URL que un integrador configura. El proveedor de identidad no es parte del contrato. */\nexport const PLANVORTEX_API_URL = \"https://api.planvortex.com/v1.0.0\";\n\n/**\n * Versión del paquete, en el `User-Agent` de cada petición.\n *\n * Es una constante y no un `require(\"../package.json\")` a propósito: leer el package.json en tiempo\n * de ejecución obliga a empaquetarlo y se rompe distinto en ESM y en CJS. La mantiene sincronizada\n * un test.\n */\nexport const VERSION = \"0.0.1\";\n","/**\n * El catálogo de errores de PlanVortex, por rangos, y las clases que salen de él.\n *\n * LA REGLA, y no es negociable: **los errores se clasifican por `body.code`, nunca por el status\n * HTTP.** Todo error de dominio viaja con un 400 — un token caducado, una cuenta desconectada, el\n * cupo del plan agotado y un texto demasiado largo son los cuatro un 400. Sólo el 520 (permisos)\n * sale 401 y un fallo inesperado sale 500. Un `if (response.status === 401) refreshToken()` sería\n * un bug silencioso: los códigos de token, 501 y 522, viajan dentro de un 400.\n *\n * El catálogo del servidor crece cada mes, así que un código fuera de estos rangos NO es un error\n * del cliente: cae en la clase base con su `code` y su `message` intactos. Nunca se traga y nunca\n * se renombra.\n */\n\nexport type PlanVortexErrorRange = {\n /** Primer código del rango, incluido */\n from: number;\n /** Último código del rango, incluido */\n to: number;\n /** Qué familia de problemas es */\n family: string;\n};\n\nexport const PLANVORTEX_ERROR_RANGES: readonly PlanVortexErrorRange[] = [\n { from: 500, to: 541, family: \"auth\" },\n { from: 601, to: 612, family: \"user\" },\n { from: 700, to: 715, family: \"account\" },\n { from: 800, to: 810, family: \"file\" },\n { from: 900, to: 960, family: \"publication\" },\n { from: 1000, to: 1003, family: \"general\" },\n { from: 1100, to: 1111, family: \"organization\" },\n { from: 1200, to: 1207, family: \"role\" },\n { from: 1300, to: 1307, family: \"plan_limit\" },\n { from: 1400, to: 1408, family: \"plan_limit\" },\n { from: 1500, to: 1512, family: \"messaging\" },\n { from: 1600, to: 1601, family: \"contact\" },\n { from: 1900, to: 1906, family: \"payment\" },\n { from: 2000, to: 2099, family: \"product\" },\n { from: 2100, to: 2199, family: \"ai_plan\" },\n { from: 2200, to: 2299, family: \"integration\" },\n] as const;\n\n/**\n * El `code` que lleva un error que **no** trae código del servidor: un fallo de red, un timeout, un\n * 502 de un proxy con cuerpo HTML, o el propio constructor quejándose de la configuración.\n *\n * El servidor no emite nunca el 0, así que sirve de centinela sin pisar el catálogo. Cuál de esos\n * casos es se distingue por `family`: `connection`, `http`, `oauth`, `config` o `webhook`.\n */\nexport const NO_ERROR_CODE = 0;\n\n/**\n * Los dos códigos que significan \"tu token ya no sirve\". Los dos llegan **dentro de un 400**, que es\n * justo por lo que existe esta constante: quien mire el status no los va a encontrar.\n *\n * El 520 (permisos) NO está aquí a propósito: sale 401, pero pedir un token nuevo no lo arregla — a\n * la app le faltan permisos, y con un token recién emitido le seguirán faltando.\n */\nexport const TOKEN_ERROR_CODES: readonly number[] = [501, 522];\n\n/** Opciones de construcción de un error. Todas opcionales: un error siempre se puede construir. */\nexport interface PlanVortexErrorOptions {\n /** El `data` del cuerpo — lo que el servidor adjuntó con `.withData({...})`. `{}` si no vino nada. */\n data?: Record<string, unknown>;\n /** Status HTTP. `undefined` cuando la petición no llegó a tener respuesta. */\n status?: number;\n /** `x-request-id` de la respuesta, si el despliegue lo pone delante. */\n requestId?: string;\n /** Segundos de la cabecera `Retry-After`, cuando la hay. */\n retryAfter?: number;\n /** El error original (un `TypeError` de `fetch`, por ejemplo). */\n cause?: unknown;\n /**\n * Familia, sólo para los errores que NO salen del catálogo: `connection`, `http`, `oauth`,\n * `config` y `webhook`. Los de dominio la deducen de su `code` y no la pasan nunca.\n */\n family?: string;\n}\n\n/**\n * La base de todo lo que lanza esta librería.\n *\n * Un `catch (e) { if (e instanceof PlanVortexError) }` los coge todos: los de dominio, los de red y\n * los de configuración. Para afinar están las subclases y el `code`.\n */\nexport class PlanVortexError extends Error {\n /** El `code` del cuerpo, tal cual. {@link NO_ERROR_CODE} si el error no viene del catálogo. */\n readonly code: number;\n /** La familia del rango: `auth`, `publication`, `plan_limit`... Ver {@link PLANVORTEX_ERROR_RANGES}. */\n readonly family: string;\n /** El `data` del cuerpo. */\n readonly data: Record<string, unknown>;\n /** Status HTTP, o `undefined` si nunca hubo respuesta. */\n readonly status: number | undefined;\n /** `x-request-id`, si el despliegue lo pone. Hoy el servidor no lo emite; un proxy delante sí. */\n readonly requestId: string | undefined;\n /** Segundos que pidió esperar la cabecera `Retry-After`, si llegó. */\n readonly retryAfter: number | undefined;\n\n constructor(code: number, message: string, options: PlanVortexErrorOptions = {}) {\n super(message, options.cause === undefined ? undefined : { cause: options.cause });\n this.name = new.target.name;\n this.code = code;\n this.family = options.family ?? errorFamilyForCode(code) ?? \"unknown\";\n this.data = options.data ?? {};\n this.status = options.status;\n this.requestId = options.requestId;\n this.retryAfter = options.retryAfter;\n }\n}\n\n/** 500-541 — tokens, apps de cliente, permisos. Incluye el 501 y el 522, los de token caducado. */\nexport class AuthError extends PlanVortexError {}\n/** 601-612 — el usuario final. */\nexport class UserError extends PlanVortexError {}\n/** 700-715 — cuentas sociales: desconectada, sin permisos en la red, sin refrescar. */\nexport class AccountError extends PlanVortexError {}\n/** 800-810 — ficheros: formato no admitido, demasiado grande, conversión fallida. */\nexport class FileError extends PlanVortexError {}\n/** 900-960 — publicaciones, incluidos los límites por red (caracteres, imágenes, duración). */\nexport class PublicationError extends PlanVortexError {}\n/** 1100-1111 — organizaciones, y el token temporal atado a una sola de ellas (1101). */\nexport class OrganizationError extends PlanVortexError {}\n/**\n * 1300-1307 y 1400-1408 — el cupo del plan, del cliente o de la organización.\n *\n * Es el error que un integrador **sí** quiere distinguir: no se arregla reintentando, se arregla\n * cambiando de plan. Por eso los dos rangos comparten clase.\n */\nexport class PlanLimitError extends PlanVortexError {}\n/** 1500-1512 — conversaciones, mensajes y plantillas. Exige plan de pago. */\nexport class MessagingError extends PlanVortexError {}\n/** 1600-1601 — contactos. */\nexport class ContactError extends PlanVortexError {}\n/** 2000-2099 — catálogos y productos (sólo Facebook e Instagram). */\nexport class ProductError extends PlanVortexError {}\n/** 2100-2199 — planes de publicaciones generados con IA. */\nexport class AiPlanError extends PlanVortexError {}\n/** 2200-2299 — integraciones: Google Drive, RSS. */\nexport class IntegrationError extends PlanVortexError {}\n\n/**\n * La petición no llegó a tener respuesta: DNS, conexión rechazada, socket cortado o timeout.\n *\n * No lleva código del catálogo porque el servidor nunca llegó a opinar.\n */\nexport class PlanVortexConnectionError extends PlanVortexError {\n /** `true` si lo que se agotó fue nuestro propio timeout, no la red. */\n readonly timeout: boolean;\n\n constructor(message: string, options: PlanVortexErrorOptions & { timeout?: boolean } = {}) {\n super(NO_ERROR_CODE, message, { ...options, family: \"connection\" });\n this.timeout = options.timeout ?? false;\n }\n}\n\n/**\n * `POST /oauth/token` rechazó las credenciales.\n *\n * Es el ÚNICO sitio del API con forma de error distinta: `{error, error_description}` de OAuth2, no\n * el `{code, message, data}` de todo lo demás. Y por eso el `code` es {@link NO_ERROR_CODE}: el\n * servidor tiene códigos para esto (538-541) pero **no los manda en el cuerpo**, así que ponerlos\n * aquí sería inventarse algo que nadie dijo. Lo que sí viaja es `oauthError`.\n */\nexport class PlanVortexAuthenticationError extends PlanVortexError {\n /** `invalid_client`, `invalid_request`, `unsupported_grant_type`, `slow_down` o `server_error`. */\n readonly oauthError: string;\n\n constructor(oauthError: string, description: string, options: PlanVortexErrorOptions = {}) {\n super(NO_ERROR_CODE, description, { ...options, family: \"oauth\" });\n this.oauthError = oauthError;\n }\n}\n\n/**\n * La librería está mal configurada y no ha llegado a salir de casa: sin credenciales, o instanciada\n * en un navegador (§ trampa 9 del roadmap).\n */\nexport class PlanVortexConfigError extends PlanVortexError {\n constructor(message: string) {\n super(NO_ERROR_CODE, message, { family: \"config\" });\n }\n}\n\n/** La familia a la que pertenece un código, o `undefined` si cae fuera del catálogo conocido. */\nexport function errorFamilyForCode(code: number): string | undefined {\n return PLANVORTEX_ERROR_RANGES.find((range) => code >= range.from && code <= range.to)?.family;\n}\n\n/**\n * Familia -> clase. Las que faltan —`general`, `role`, `payment` y cualquier rango nuevo— caen a\n * propósito en la clase base: existen en el servidor pero no son superficie de integración, y darles\n * clase propia sería prometer un `instanceof` que luego habría que mantener.\n */\nconst FAMILY_CLASSES: Record<string, typeof PlanVortexError> = {\n auth: AuthError,\n user: UserError,\n account: AccountError,\n file: FileError,\n publication: PublicationError,\n organization: OrganizationError,\n plan_limit: PlanLimitError,\n messaging: MessagingError,\n contact: ContactError,\n product: ProductError,\n ai_plan: AiPlanError,\n integration: IntegrationError,\n};\n\n/** El cuerpo de error del API: `{code, message, data}`. */\nexport interface ApiErrorBody {\n code: number;\n message?: string;\n data?: Record<string, unknown>;\n}\n\nfunction isApiErrorBody(body: unknown): body is ApiErrorBody {\n return typeof body === \"object\" && body !== null && typeof (body as ApiErrorBody).code === \"number\";\n}\n\n/**\n * Convierte una respuesta de error en la clase que le toca.\n *\n * Un cuerpo sin `code` —un 502 de un proxy, la página HTML de un balanceador— no es un error de\n * dominio: sale como clase base con `family: \"http\"` y el cuerpo entero en `data`, que es además lo\n * que necesita `auth.ts` para reconocer el `{error, error_description}` de OAuth2.\n */\nexport function createErrorFromResponse(input: {\n body: unknown;\n status: number;\n requestId?: string | undefined;\n retryAfter?: number | undefined;\n}): PlanVortexError {\n const options: PlanVortexErrorOptions = {\n status: input.status,\n ...(input.requestId === undefined ? {} : { requestId: input.requestId }),\n ...(input.retryAfter === undefined ? {} : { retryAfter: input.retryAfter }),\n };\n\n if (isApiErrorBody(input.body)) {\n const family = errorFamilyForCode(input.body.code);\n const ErrorClass = (family === undefined ? undefined : FAMILY_CLASSES[family]) ?? PlanVortexError;\n return new ErrorClass(input.body.code, input.body.message ?? \"PlanVortex error\", {\n ...options,\n data: input.body.data ?? {},\n });\n }\n\n return new PlanVortexError(NO_ERROR_CODE, `HTTP ${input.status}`, {\n ...options,\n family: \"http\",\n data:\n typeof input.body === \"object\" && input.body !== null\n ? (input.body as Record<string, unknown>)\n : { body: input.body },\n });\n}\n\n/** ¿Es un error de esta librería? Útil en un `catch` donde no apetece importar la clase. */\nexport function isPlanVortexError(error: unknown): error is PlanVortexError {\n return error instanceof PlanVortexError;\n}\n\n/**\n * ¿Dice este error que el token ya no sirve? (los códigos 501 y 522, los dos dentro de un 400).\n *\n * Es lo que dispara el único reintento con token nuevo del cliente.\n */\nexport function isTokenError(error: unknown): boolean {\n return isPlanVortexError(error) && TOKEN_ERROR_CODES.includes(error.code);\n}\n","/**\n * La autenticación: `client_credentials` contra `POST /oauth/token`, con el token en memoria.\n *\n * La librería **no habla con Keycloak** (§ decisión 2 del roadmap). El proveedor de identidad no es\n * parte del contrato público: el integrador configura una sola URL, `api.planvortex.com`, y el día\n * que cambiemos de proveedor no se entera nadie.\n *\n * LO QUE HAY QUE ENTENDER ANTES DE TOCAR ESTE FICHERO:\n *\n * - **Un token, no veinte.** Diez llamadas en paralelo con el token caducado tienen que pedir UNA\n * petición de token, no diez. El freno del servidor son 30 intentos por minuto y por `client_id`\n * (§ fase 1): sin el cerrojo, un arranque con veinte peticiones se come el cupo él solito.\n * - **Se refresca ANTES de caducar**, con 60 s de margen. Un token que caduca a mitad de vuelo se\n * convierte en un 400 con `code: 501` que el integrador no puede prevenir.\n * - **El error de esta ruta tiene forma de OAuth2**, `{error, error_description}`, no el\n * `{code, message, data}` del resto del API. Es la única excepción del servidor y aquí se\n * traduce a {@link PlanVortexAuthenticationError}.\n */\nimport { PlanVortexAuthenticationError, isPlanVortexError } from \"./errors.js\";\nimport type { HttpClient } from \"./http.js\";\n\n/** Lo que devuelve `POST /oauth/token`. Ni `refresh_token` ni `id_token`: no existen aquí. */\nexport interface ClientCredentialsToken {\n access_token: string;\n token_type: string;\n /** Segundos de vida. Keycloak da 300 hoy, pero es dato del servidor: nunca se asume. */\n expires_in: number;\n scope?: string;\n}\n\n/**\n * De dónde sale el `Authorization` de cada petición. Dos implementaciones: las credenciales de app\n * ({@link ClientCredentialsAuth}) y el token temporal de conexión ({@link StaticTokenAuth}).\n */\nexport interface AuthProvider {\n /** El token a poner en `Authorization: Bearer`. Pide uno nuevo si hace falta. */\n getToken(): Promise<string>;\n /** Tira el token cacheado. Lo llama el cliente cuando el servidor responde 501 o 522. */\n invalidate(): void;\n}\n\n/** Margen con el que se pide un token nuevo antes de que caduque el que hay. */\nexport const TOKEN_REFRESH_MARGIN_MS = 60_000;\n\n/** La ruta de la fachada OAuth2. Relativa a la `baseUrl`, que ya lleva el `/v1.0.0`. */\nexport const TOKEN_PATH = \"/oauth/token\";\n\n/**\n * Un token ya emitido, que no se renueva: el `temporal_connect_token` con el que una PERSONA conecta\n * su cuenta social (§ trampa 2 del roadmap).\n *\n * Dura una hora, va atado a **una** organización y no se puede refrescar — cuando caduca, la app\n * emite otro. Por eso `invalidate()` no hace nada: no hay nada que volver a pedir.\n */\nexport class StaticTokenAuth implements AuthProvider {\n constructor(private readonly token: string) {}\n\n getToken(): Promise<string> {\n return Promise.resolve(this.token);\n }\n\n invalidate(): void {\n //A propósito vacío: un token temporal no se renueva solo.\n }\n}\n\nexport interface ClientCredentialsAuthOptions {\n clientId: string;\n clientSecret: string;\n scope?: string | undefined;\n /**\n * Reloj inyectable. Existe para poder probar la caducidad sin esperar cinco minutos ni tocar los\n * timers globales.\n *\n * @internal\n */\n now?: () => number;\n}\n\nexport class ClientCredentialsAuth implements AuthProvider {\n private readonly now: () => number;\n private cached: { token: string; expiresAt: number } | undefined;\n /** La petición de token en vuelo. Es el cerrojo: mientras exista, todos esperan a ésta. */\n private pending: Promise<string> | undefined;\n\n constructor(\n private readonly http: HttpClient,\n private readonly options: ClientCredentialsAuthOptions,\n ) {\n this.now = options.now ?? Date.now;\n }\n\n async getToken(): Promise<string> {\n const cached = this.cached;\n if (cached && cached.expiresAt - this.now() > TOKEN_REFRESH_MARGIN_MS) {\n return cached.token;\n }\n //Sin esto, veinte llamadas en paralelo con el token caducado son veinte peticiones de token.\n this.pending ??= this.fetchToken().finally(() => {\n this.pending = undefined;\n });\n return this.pending;\n }\n\n invalidate(): void {\n this.cached = undefined;\n }\n\n private async fetchToken(): Promise<string> {\n const body = new URLSearchParams({\n grant_type: \"client_credentials\",\n client_id: this.options.clientId,\n client_secret: this.options.clientSecret,\n });\n if (this.options.scope) {\n body.set(\"scope\", this.options.scope);\n }\n\n let token: ClientCredentialsToken;\n try {\n const response = await this.http.request<ClientCredentialsToken>({\n method: \"POST\",\n path: TOKEN_PATH,\n body,\n //Es el único POST reintentable de la librería: pedir un token no crea nada.\n idempotent: true,\n });\n token = response.data;\n } catch (error) {\n throw toAuthenticationError(error);\n }\n\n if (!token?.access_token) {\n throw new PlanVortexAuthenticationError(\n \"server_error\",\n \"El endpoint de token respondió sin access_token\",\n );\n }\n\n //`expires_in` es del servidor y podría no venir; una hora es lo que dura el token más largo\n //que emite hoy, así que como suelo es conservador y el 501 lo cubre igual.\n const lifetimeMs = (Number(token.expires_in) > 0 ? Number(token.expires_in) : 3600) * 1000;\n this.cached = { token: token.access_token, expiresAt: this.now() + lifetimeMs };\n return token.access_token;\n }\n}\n\n/** El cuerpo de error de OAuth2, que es lo que devuelve —y sólo devuelve— el endpoint de token. */\ninterface OAuthErrorBody {\n error?: unknown;\n error_description?: unknown;\n}\n\n/**\n * Traduce lo que salga del endpoint de token.\n *\n * Un fallo de red se deja pasar tal cual: no es que las credenciales estén mal, es que no hubo\n * conversación, y confundir las dos cosas manda al integrador a revisar un secreto que está bien.\n */\nexport function toAuthenticationError(error: unknown): unknown {\n if (!isPlanVortexError(error) || error.status === undefined) {\n return error;\n }\n const body = error.data as OAuthErrorBody;\n const oauthError = typeof body.error === \"string\" ? body.error : \"invalid_client\";\n const description = typeof body.error_description === \"string\" ? body.error_description : error.message;\n\n return new PlanVortexAuthenticationError(oauthError, description, {\n status: error.status,\n ...(error.requestId === undefined ? {} : { requestId: error.requestId }),\n ...(error.retryAfter === undefined ? {} : { retryAfter: error.retryAfter }),\n cause: error,\n });\n}\n","/**\n * El transporte: `fetch`, timeouts, reintentos y hooks. No sabe nada de autenticación —de eso va\n * `auth.ts`— ni de recursos. Todo lo que sale de la librería hacia el API pasa por aquí, incluida\n * la petición de token, que es lo que hace que el `User-Agent`, el timeout y el backoff sean uno\n * solo y no dos implementaciones que se separan con el tiempo.\n *\n * LAS DOS REGLAS DE REINTENTO, que son las que evitan un desastre silencioso:\n *\n * 1. **Un 400 con código de dominio NO se reintenta nunca.** Repetir \"el texto es demasiado largo\"\n * no lo arregla, y en este API todos los errores de dominio son 400 (§ trampa 1 del roadmap).\n * Sólo se reintentan 429, 502, 503 y 504, que son los que dicen \"vuelve luego\".\n * 2. **Un POST que llegó al servidor NO se reintenta.** Publicar dos veces es peor que fallar, y\n * no hay clave de idempotencia en el API todavía. Un POST sólo se repite cuando el fallo es de\n * los que demuestran que la petición ni salió —DNS, conexión rechazada— y jamás por un 5xx,\n * que es la respuesta de un servidor que sí la recibió.\n */\nimport { PlanVortexConnectionError, createErrorFromResponse } from \"./errors.js\";\nimport type { PlanVortexError } from \"./errors.js\";\n\n/** `fetch` con la firma que usamos. Se puede sustituir en tests o para meter un proxy. */\nexport type FetchLike = (input: string, init: RequestInit) => Promise<Response>;\n\n/**\n * Lo que `fetch` acepta como cuerpo. Se saca de `RequestInit` en vez de nombrar `BodyInit`: ese tipo\n * es global en el DOM pero no en `@types/node`, y el paquete compila sólo con los tipos de Node.\n */\ntype RequestBody = NonNullable<RequestInit[\"body\"]>;\n\nexport type HttpMethod = \"GET\" | \"POST\" | \"PUT\" | \"PATCH\" | \"DELETE\";\n\n/** Valores admitidos en la query. `undefined` y `null` se omiten; un array repite la clave. */\nexport type QueryValue =\n string | number | boolean | Date | null | undefined | readonly (string | number | boolean)[];\n\nexport interface RetryConfig {\n /** Cuántas veces se REPITE una petición fallida. `0` desactiva los reintentos. */\n maxRetries: number;\n /** Espera base del backoff exponencial, en ms. La real es aleatoria entre 0 y el tope. */\n baseDelayMs: number;\n /**\n * Tope de espera entre intentos, en ms.\n *\n * Además de recortar el backoff, decide qué hacer con un `Retry-After` largo: si el servidor\n * pide más que esto, la librería **no** espera — lanza el error con `retryAfter` puesto y deja\n * que el integrador decida. Un `Retry-After: 300` del freno del token endpoint no puede\n * traducirse en una llamada que se queda cinco minutos colgada.\n */\n maxDelayMs: number;\n}\n\nexport const DEFAULT_RETRY: RetryConfig = {\n maxRetries: 2,\n baseDelayMs: 500,\n maxDelayMs: 8_000,\n};\n\n/** 120 s, como el panel: subir y publicar un vídeo es lento de verdad. */\nexport const DEFAULT_TIMEOUT_MS = 120_000;\n\n/** Los únicos status que se reintentan. Un 400, un 401 o un 404 no se arreglan repitiéndolos. */\nconst RETRYABLE_STATUS = new Set([408, 429, 502, 503, 504]);\n\n/**\n * Códigos de error de red que demuestran que la petición **no llegó**: no hay servidor, no hay DNS\n * o la conexión fue rechazada antes de mandar nada. Son los únicos con los que se repite un POST.\n *\n * `ECONNRESET`, `ETIMEDOUT` y un abort por timeout NO están aquí a propósito: pueden pasar después\n * de que el servidor recibiera el cuerpo, y entonces repetir el POST publica dos veces.\n */\nconst PRE_FLIGHT_NETWORK_CODES = new Set([\n \"ECONNREFUSED\",\n \"ENOTFOUND\",\n \"EAI_AGAIN\",\n \"EHOSTUNREACH\",\n \"ENETUNREACH\",\n]);\n\nexport interface RequestInfo {\n method: HttpMethod;\n url: string;\n /** 1 la primera vez. */\n attempt: number;\n}\n\nexport interface ResponseInfo extends RequestInfo {\n status: number;\n /** Milisegundos de ese intento. */\n durationMs: number;\n}\n\nexport interface RetryInfo extends RequestInfo {\n /** Espera antes del siguiente intento, en ms. */\n delayMs: number;\n /** El status que provocó el reintento, o `undefined` si fue un fallo de red. */\n status: number | undefined;\n /** El error de red, si lo hubo. */\n error: unknown;\n}\n\n/**\n * Ganchos para el logger del integrador. Son síncronos a propósito: si uno lanza, lanza en su\n * llamada, no en medio del reintento.\n */\nexport interface HttpHooks {\n onRequest?: (info: RequestInfo) => void;\n onResponse?: (info: ResponseInfo) => void;\n onRetry?: (info: RetryInfo) => void;\n}\n\nexport interface HttpClientConfig {\n /** Sin barra final. */\n baseUrl: string;\n timeoutMs?: number;\n retry?: Partial<RetryConfig>;\n hooks?: HttpHooks;\n fetch?: FetchLike;\n /** Cabeceras fijas de todas las peticiones — el `User-Agent`, por ejemplo. */\n headers?: Record<string, string>;\n}\n\nexport interface HttpRequest {\n method: HttpMethod;\n /** Empieza por `/`, relativo a `baseUrl`. */\n path: string;\n query?: Record<string, QueryValue>;\n /**\n * `FormData`, `URLSearchParams` o `string` viajan tal cual; cualquier otra cosa se serializa a\n * JSON. `undefined` es \"sin cuerpo\".\n */\n body?: unknown;\n headers?: Record<string, string>;\n timeoutMs?: number;\n /** Del integrador, para cancelar. Se combina con el timeout interno. */\n signal?: AbortSignal | undefined;\n /**\n * Fuerza que la petición se pueda reintentar aunque sea un POST. Sólo para POSTs que no crean\n * nada — hoy, `POST /oauth/token`.\n */\n idempotent?: boolean;\n /** `none` salta el parseo del cuerpo. Por defecto se intenta JSON. */\n parse?: \"json\" | \"none\";\n}\n\nexport interface HttpResponse<T> {\n data: T;\n status: number;\n headers: Headers;\n /** `x-request-id`, cuando el despliegue lo pone. */\n requestId: string | undefined;\n}\n\n/** Los métodos que se pueden repetir sin cambiar nada en el servidor. */\nfunction isIdempotent(request: HttpRequest): boolean {\n return request.idempotent ?? request.method !== \"POST\";\n}\n\n/** Saca el `code` de un error de red de undici, que lo esconde en `cause`. */\nfunction networkErrorCode(error: unknown): string | undefined {\n const cause = (error as { cause?: unknown })?.cause;\n const code = (cause as { code?: unknown })?.code ?? (error as { code?: unknown })?.code;\n return typeof code === \"string\" ? code : undefined;\n}\n\n/** `Retry-After` llega en segundos o como fecha HTTP. Devuelve segundos, o `undefined`. */\nexport function parseRetryAfter(header: string | null, now: number = Date.now()): number | undefined {\n if (!header) {\n return undefined;\n }\n const seconds = Number(header);\n if (Number.isFinite(seconds) && seconds >= 0) {\n return seconds;\n }\n const date = Date.parse(header);\n if (Number.isNaN(date)) {\n return undefined;\n }\n return Math.max(0, Math.round((date - now) / 1000));\n}\n\nfunction buildQuery(query: Record<string, QueryValue> | undefined): string {\n if (!query) {\n return \"\";\n }\n const params = new URLSearchParams();\n for (const [key, value] of Object.entries(query)) {\n if (value === undefined || value === null) {\n continue;\n }\n if (Array.isArray(value)) {\n //El servidor lee los arrays como clave repetida (`?state=pending&state=error`).\n for (const item of value) {\n params.append(key, String(item));\n }\n continue;\n }\n params.append(key, value instanceof Date ? value.toISOString() : String(value));\n }\n const serialized = params.toString();\n return serialized ? `?${serialized}` : \"\";\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => {\n setTimeout(resolve, ms);\n });\n}\n\nexport class HttpClient {\n private readonly baseUrl: string;\n private readonly timeoutMs: number;\n private readonly retry: RetryConfig;\n private readonly hooks: HttpHooks;\n private readonly fetchImpl: FetchLike;\n private readonly baseHeaders: Record<string, string>;\n\n constructor(config: HttpClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/+$/, \"\");\n this.timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n this.retry = { ...DEFAULT_RETRY, ...config.retry };\n this.hooks = config.hooks ?? {};\n //`globalThis.fetch` sin ligar al objeto global revienta en Node con \"Illegal invocation\".\n this.fetchImpl = config.fetch ?? ((input, init) => globalThis.fetch(input, init));\n //En minúsculas para que no convivan `User-Agent` y `user-agent` en la misma petición.\n this.baseHeaders = Object.fromEntries(\n Object.entries(config.headers ?? {}).map(([key, value]) => [key.toLowerCase(), value]),\n );\n }\n\n async request<T>(request: HttpRequest): Promise<HttpResponse<T>> {\n const url = `${this.baseUrl}${request.path}${buildQuery(request.query)}`;\n const { body, headers } = this.prepareBody(request);\n const timeoutMs = request.timeoutMs ?? this.timeoutMs;\n const retryable = isIdempotent(request);\n\n let attempt = 0;\n for (;;) {\n attempt++;\n this.hooks.onRequest?.({ method: request.method, url, attempt });\n const startedAt = Date.now();\n\n let response: Response;\n try {\n response = await this.send(url, request, body, headers, timeoutMs);\n } catch (error) {\n const failure = this.toConnectionError(error, request, timeoutMs);\n //Un POST sólo se repite si el fallo demuestra que la petición ni salió.\n const canRetry = retryable || PRE_FLIGHT_NETWORK_CODES.has(networkErrorCode(error) ?? \"\");\n if (!canRetry || attempt > this.retry.maxRetries) {\n throw failure;\n }\n const delayMs = this.backoff(attempt);\n this.hooks.onRetry?.({\n method: request.method,\n url,\n attempt,\n delayMs,\n status: undefined,\n error,\n });\n await sleep(delayMs);\n continue;\n }\n\n this.hooks.onResponse?.({\n method: request.method,\n url,\n attempt,\n status: response.status,\n durationMs: Date.now() - startedAt,\n });\n\n const requestId = response.headers.get(\"x-request-id\") ?? undefined;\n\n if (response.ok) {\n return {\n data: (await this.parseBody(response, request)) as T,\n status: response.status,\n headers: response.headers,\n requestId,\n };\n }\n\n const retryAfter = parseRetryAfter(response.headers.get(\"retry-after\"));\n const shouldRetry =\n retryable && RETRYABLE_STATUS.has(response.status) && attempt <= this.retry.maxRetries;\n const waitMs = retryAfter === undefined ? this.backoff(attempt) : retryAfter * 1000;\n\n //Un `Retry-After` más largo que el tope no se espera: se devuelve el error con el dato\n //dentro para que lo decida quien llama.\n if (!shouldRetry || waitMs > this.retry.maxDelayMs) {\n throw await this.toApiError(response, requestId, retryAfter);\n }\n\n //El cuerpo se descarta, pero hay que consumirlo para que undici libere la conexión.\n await response.arrayBuffer().catch(() => undefined);\n this.hooks.onRetry?.({\n method: request.method,\n url,\n attempt,\n delayMs: waitMs,\n status: response.status,\n error: undefined,\n });\n await sleep(waitMs);\n }\n }\n\n /** Backoff exponencial con jitter completo: aleatorio entre 0 y el tope de ese intento. */\n private backoff(attempt: number): number {\n const ceiling = Math.min(this.retry.maxDelayMs, this.retry.baseDelayMs * 2 ** (attempt - 1));\n return Math.round(Math.random() * ceiling);\n }\n\n private prepareBody(request: HttpRequest): {\n body: RequestBody | undefined;\n headers: Record<string, string>;\n } {\n const headers: Record<string, string> = { accept: \"application/json\", ...this.baseHeaders };\n for (const [key, value] of Object.entries(request.headers ?? {})) {\n headers[key.toLowerCase()] = value;\n }\n\n if (request.body === undefined) {\n return { body: undefined, headers };\n }\n //`FormData` pone su propio `content-type` con el boundary: tocarlo rompe el multipart.\n if (request.body instanceof FormData || request.body instanceof URLSearchParams) {\n return { body: request.body, headers };\n }\n if (typeof request.body === \"string\" || request.body instanceof Uint8Array) {\n return { body: request.body as RequestBody, headers };\n }\n headers[\"content-type\"] = \"application/json\";\n return { body: JSON.stringify(request.body), headers };\n }\n\n private async send(\n url: string,\n request: HttpRequest,\n body: RequestBody | undefined,\n headers: Record<string, string>,\n timeoutMs: number,\n ): Promise<Response> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(new PlanVortexTimeout()), timeoutMs);\n //`AbortSignal.any` no existe hasta Node 20.3 y el paquete admite Node 20 entero, así que la\n //señal del integrador se enlaza a mano.\n const external = request.signal;\n const forward = () => controller.abort(external?.reason);\n if (external) {\n if (external.aborted) {\n clearTimeout(timer);\n throw external.reason;\n }\n external.addEventListener(\"abort\", forward, { once: true });\n }\n\n try {\n return await this.fetchImpl(url, {\n method: request.method,\n ...(body === undefined ? {} : { body }),\n headers,\n signal: controller.signal,\n });\n } catch (error) {\n //Según la implementación de `fetch`, un abort rechaza con la razón o con un\n //`AbortError` genérico. Mirando la razón, el timeout se reconoce en los dos casos.\n if (controller.signal.reason instanceof PlanVortexTimeout && !external?.aborted) {\n throw controller.signal.reason;\n }\n throw error;\n } finally {\n clearTimeout(timer);\n external?.removeEventListener(\"abort\", forward);\n }\n }\n\n /**\n * Un abort tiene dos orígenes y sólo uno es nuestro: si canceló el integrador, su error sale tal\n * cual —envolverlo le rompería el `if (e.name === \"AbortError\")` que tenga escrito.\n */\n private toConnectionError(error: unknown, request: HttpRequest, timeoutMs: number): unknown {\n if (error instanceof PlanVortexTimeout || (error as { name?: string })?.name === \"TimeoutError\") {\n return new PlanVortexConnectionError(\n `${request.method} ${request.path} agotó el timeout de ${timeoutMs} ms`,\n { timeout: true, cause: error },\n );\n }\n if (request.signal?.aborted) {\n return error;\n }\n const code = networkErrorCode(error);\n return new PlanVortexConnectionError(\n `${request.method} ${request.path} no pudo conectar${code ? ` (${code})` : \"\"}`,\n { timeout: false, cause: error },\n );\n }\n\n private async toApiError(\n response: Response,\n requestId: string | undefined,\n retryAfter: number | undefined,\n ): Promise<PlanVortexError> {\n const body = await this.readBody(response);\n return createErrorFromResponse({ body, status: response.status, requestId, retryAfter });\n }\n\n private async parseBody(response: Response, request: HttpRequest): Promise<unknown> {\n if (request.parse === \"none\" || response.status === 204) {\n return undefined;\n }\n return this.readBody(response);\n }\n\n /** JSON si se puede; si no, el texto crudo. Un cuerpo vacío es `undefined`, nunca un throw. */\n private async readBody(response: Response): Promise<unknown> {\n const text = await response.text().catch(() => \"\");\n if (!text) {\n return undefined;\n }\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n }\n}\n\n/** Marca interna para distinguir NUESTRO timeout de un abort del integrador. */\nclass PlanVortexTimeout extends Error {\n constructor() {\n super(\"PlanVortex request timeout\");\n this.name = \"TimeoutError\";\n }\n}\n","/**\n * Paginación: `list()` devuelve una página y `iterate()` las encadena solo.\n *\n * POR QUÉ ES UN FICHERO Y NO TRES LÍNEAS EN CADA RECURSO: la API pagina con `offset`/`limit` y\n * envuelve cada lista con el nombre de su recurso —`{publications, total}`, `{accounts, total}`,\n * `{uploads, total}`— (§ trampa 6 del roadmap). El sobre es un detalle del transporte, así que se\n * desenvuelve aquí una vez y todos los dominios devuelven la misma `{data, total}`.\n *\n * DOS COSAS QUE HAY QUE SABER DEL `iterate()`:\n *\n * 1. **Corta cuando una página viene vacía**, no cuando ha leído `total`. `total` se cuenta con un\n * `countDocuments` aparte de la consulta, así que en una colección que se está moviendo puede\n * no cuadrar con lo que devuelven las páginas; fiarse de él daría o un bucle infinito o una\n * página perdida. También corta si el servidor devolviera una página más corta que el `limit`,\n * que es la señal de que ya no hay más.\n * 2. **Tiene tope de páginas.** Un servidor que ignorase el `offset` devolvería la misma página\n * para siempre, y un `for await` sin tope se lleva por delante el proceso del integrador.\n * `MAX_PAGES` es un seguro, no un límite de uso: a 100 elementos por página son un millón.\n */\nimport { NO_ERROR_CODE, PlanVortexError } from \"./errors.js\";\nimport type { Paginated } from \"../types.js\";\n\n/** Lo que admite cualquier `list()` del paquete, además de los filtros propios de su dominio. */\nexport interface PageOptions {\n /** Cuántos elementos pedir. Sin él manda el servidor, que no siempre pagina igual. */\n limit?: number | undefined;\n /** Cuántos saltar. `0` es la primera página. */\n offset?: number | undefined;\n}\n\n/** Elementos por página cuando `iterate()` no recibe `limit`. */\nexport const DEFAULT_PAGE_SIZE = 50;\n\n/**\n * El seguro contra un bucle infinito. No es un límite de cuánto se puede leer: es lo que hace que\n * un servidor que ignore el `offset` falle en vez de colgar el proceso.\n */\nexport const MAX_PAGES = 10_000;\n\n/**\n * La página concreta que {@link iteratePages} pide. Se declara aparte y no como\n * `Required<PageOptions>`: con `exactOptionalPropertyTypes`, `Required` quita el `?` pero deja el\n * `| undefined`, y entonces el tipo dice que el iterador puede pedir una página sin `limit`.\n */\nexport interface Page {\n limit: number;\n offset: number;\n}\n\n/** Una función que devuelve una página. Es lo que cada recurso le pasa a {@link iteratePages}. */\nexport type PageFetcher<T> = (page: Page) => Promise<Paginated<T>>;\n\n/**\n * Saca `{data, total}` del sobre con el que la API envuelve una lista.\n *\n * `key` es el nombre EXACTO del campo que trae el array (`publications`, `accounts`, ...). Si no\n * está, es que el sobre cambió o que se pasó el nombre equivocado, y eso se dice en voz alta: sin\n * esta comprobación el método devolvería `{data: undefined}` y el fallo aparecería tres capas más\n * arriba. Es literalmente lo que le pasó al spec de publicaciones, que anunciaba `{uploads, total}`.\n */\nexport function unwrapList<T>(body: unknown, key: string): Paginated<T> {\n const envelope = body as Record<string, unknown> | undefined;\n const data = envelope?.[key];\n\n if (!Array.isArray(data)) {\n throw new PlanVortexError(\n NO_ERROR_CODE,\n `La respuesta no trae \"${key}\": el sobre de la lista no es el esperado.`,\n {\n family: \"http\",\n data: { expected: key, received: envelope ? Object.keys(envelope) : envelope },\n },\n );\n }\n\n const total = envelope?.total;\n return {\n data: data as T[],\n //`total` viaja siempre, pero si un despliegue viejo no lo mandara, la longitud de la\n //página es mejor respuesta que un `undefined` colándose como número.\n total: typeof total === \"number\" ? total : data.length,\n };\n}\n\n/** Saca un recurso suelto del sobre con el que la API lo envuelve (`{publication}`, `{account}`). */\nexport function unwrapOne<T>(body: unknown, key: string): T {\n const envelope = body as Record<string, unknown> | undefined;\n const value = envelope?.[key];\n\n if (value === undefined || value === null) {\n throw new PlanVortexError(NO_ERROR_CODE, `La respuesta no trae \"${key}\".`, {\n family: \"http\",\n data: { expected: key, received: envelope ? Object.keys(envelope) : envelope },\n });\n }\n return value as T;\n}\n\n/**\n * Encadena páginas hasta que se acaben, entregando los elementos de uno en uno.\n *\n * Se corta con un `break` en el `for await` como cualquier iterador: la página que se estuviera\n * pidiendo se descarta y no se pide ninguna más.\n */\nexport async function* iteratePages<T>(\n fetchPage: PageFetcher<T>,\n options: PageOptions = {},\n): AsyncGenerator<T> {\n const limit = options.limit ?? DEFAULT_PAGE_SIZE;\n let offset = options.offset ?? 0;\n\n for (let page = 0; page < MAX_PAGES; page++) {\n const { data } = await fetchPage({ limit, offset });\n if (!data.length) {\n return;\n }\n for (const item of data) {\n yield item;\n }\n //Una página más corta que el límite es la última: pedir la siguiente sería una llamada\n //que se sabe vacía.\n if (data.length < limit) {\n return;\n }\n offset += data.length;\n }\n\n throw new PlanVortexError(\n NO_ERROR_CODE,\n `La paginación pasó de ${MAX_PAGES} páginas: el servidor no está avanzando con el offset.`,\n { family: \"http\" },\n );\n}\n","/**\n * Lo que comparten todos los recursos: una petición autenticada y el desenvuelto del sobre.\n *\n * Un recurso no construye su propio transporte: recibe el {@link PlanVortex} y usa su `request`,\n * que es lo que hace que el token, los reintentos y los hooks sean unos para toda la instancia.\n * Y no importa `client.ts` ni por el tipo — sólo la forma que necesita— porque `client.ts` sí\n * importa los recursos, y el ciclo compilaría dejando el orden de inicialización en manos del\n * bundler.\n */\nimport type { HttpRequest, HttpResponse, QueryValue } from \"../core/http.js\";\nimport { unwrapList, unwrapOne } from \"../core/pagination.js\";\nimport type { Paginated } from \"../types.js\";\n\n/** Lo único que un recurso necesita del cliente. */\nexport interface RequestSender {\n request<T>(request: HttpRequest): Promise<HttpResponse<T>>;\n}\n\nexport type Query = Record<string, QueryValue>;\n\n/** Opciones por llamada que cualquier método acepta: cancelar y ajustar el timeout. */\nexport interface RequestOptions {\n signal?: AbortSignal | undefined;\n timeoutMs?: number | undefined;\n}\n\nexport abstract class Resource {\n constructor(protected readonly client: RequestSender) {}\n\n protected async send<T>(request: HttpRequest, options: RequestOptions = {}): Promise<T> {\n const response = await this.client.request<T>({\n ...request,\n ...(options.signal === undefined ? {} : { signal: options.signal }),\n ...(options.timeoutMs === undefined ? {} : { timeoutMs: options.timeoutMs }),\n });\n return response.data;\n }\n\n /*\n * Los cuatro verbos se llaman `httpGet`/`httpPost`/... y no `get`/`post`/... porque los\n * recursos que heredan de aquí SÍ tienen métodos públicos con esos nombres —`uploads.get(org,\n * id)` es lo que un integrador escribe— y en TypeScript una subclase no puede declarar un\n * miembro con la firma de uno heredado. Sin el prefijo, `this.get(...)` dentro de un recurso\n * resolvía a su propio método público y compilaba llamando a otra cosa.\n */\n protected httpGet<T>(path: string, query?: Query, options?: RequestOptions): Promise<T> {\n return this.send<T>({ method: \"GET\", path, ...(query ? { query } : {}) }, options);\n }\n\n protected httpPost<T>(path: string, body?: unknown, options?: RequestOptions, query?: Query): Promise<T> {\n return this.send<T>(\n { method: \"POST\", path, ...(body === undefined ? {} : { body }), ...(query ? { query } : {}) },\n options,\n );\n }\n\n protected httpPut<T>(path: string, body?: unknown, options?: RequestOptions): Promise<T> {\n return this.send<T>({ method: \"PUT\", path, ...(body === undefined ? {} : { body }) }, options);\n }\n\n protected httpDelete<T>(path: string, query?: Query, options?: RequestOptions): Promise<T> {\n return this.send<T>({ method: \"DELETE\", path, ...(query ? { query } : {}) }, options);\n }\n\n /** `GET` de una lista, ya desenvuelta a `{data, total}`. */\n protected async getList<T>(\n path: string,\n key: string,\n query?: Query,\n options?: RequestOptions,\n ): Promise<Paginated<T>> {\n return unwrapList<T>(await this.httpGet<unknown>(path, query, options), key);\n }\n\n /** `GET` de un recurso suelto, ya sacado de su sobre. */\n protected async getOne<T>(\n path: string,\n key: string,\n query?: Query,\n options?: RequestOptions,\n ): Promise<T> {\n return unwrapOne<T>(await this.httpGet<unknown>(path, query, options), key);\n }\n\n /** `POST` que devuelve un recurso envuelto. */\n protected async postOne<T>(\n path: string,\n key: string,\n body?: unknown,\n options?: RequestOptions,\n query?: Query,\n ): Promise<T> {\n return unwrapOne<T>(await this.httpPost<unknown>(path, body, options, query), key);\n }\n\n /** `PUT` que devuelve un recurso envuelto. */\n protected async putOne<T>(\n path: string,\n key: string,\n body?: unknown,\n options?: RequestOptions,\n ): Promise<T> {\n return unwrapOne<T>(await this.httpPut<unknown>(path, body, options), key);\n }\n}\n\n/**\n * Un identificador de Mongo tal y como viaja en la URL. Se comprueba aquí y no en el servidor\n * porque un `undefined` interpolado en la ruta da un 404 con la URL `/organizations/undefined/...`,\n * y ese error no dice lo que pasó — que a quien llama se le olvidó un argumento.\n */\nexport function requireId(value: string, name: string): string {\n if (typeof value !== \"string\" || !value.trim()) {\n throw new TypeError(`Falta ${name}.`);\n }\n return value;\n}\n\n/** `{success: true}` es lo que devuelve todo lo que no tiene nada que contar. */\nexport interface SuccessResponse {\n success?: boolean;\n}\n","/**\n * Cuentas sociales conectadas a una organización.\n *\n * DOS COSAS QUE NO SE ADIVINAN SOLAS:\n *\n * - **Una app no puede CONECTAR una cuenta.** Conectar Instagram es un OAuth con una persona\n * delante, y las credenciales de app no valen para eso: {@link AccountsResource.connectLinks},\n * {@link AccountsResource.connect} y {@link AccountsResource.enable} contestan 519 si se llaman\n * con ellas. Se emite un token temporal\n * (`organizations.createConnectToken`), se le pasa a la persona, y se llaman con un cliente\n * autenticado con ese token: `pv.asTemporalToken(token)`.\n * - **`error_code` distinto de 0 es una cuenta rota**, no un fallo de esta llamada. Sigue en la\n * lista con sus datos, pero ni publica ni mide hasta que alguien la reconecte.\n */\nimport { Resource, requireId } from \"./base.js\";\nimport type { Query, RequestOptions, SuccessResponse } from \"./base.js\";\nimport { NO_ERROR_CODE, createErrorFromResponse } from \"../core/errors.js\";\nimport type { PageOptions } from \"../core/pagination.js\";\nimport { iteratePages, unwrapOne } from \"../core/pagination.js\";\nimport type {\n Account,\n AccountMetrics,\n ConnectLink,\n ConnectResult,\n EnableResult,\n Paginated,\n PersistentMenu,\n SocialNetwork,\n} from \"../types.js\";\n\n/**\n * Las capacidades por las que se puede filtrar la lista. Son las mismas que publica\n * `catalog.socialCapabilities()`, aplicadas en el servidor: es la forma de pedir \"las cuentas con\n * las que puedo publicar\" sin mantener tu propia tabla de qué red hace qué.\n */\nexport type AccountCapability =\n \"publications\" | \"messages\" | \"products\" | \"webhooks\" | \"persistent_menu\" | \"comments\";\n\nexport interface AccountListOptions extends PageOptions {\n /** Búsqueda libre sobre el nombre y el usuario de la cuenta. */\n name?: string | undefined;\n /** Sólo estas redes. */\n social_network?: readonly SocialNetwork[] | undefined;\n /** Sólo estas cuentas, por identificador. */\n accounts?: readonly string[] | undefined;\n /** Sólo las cuentas cuya red sabe hacer esto. */\n capability?: AccountCapability | undefined;\n}\n\nexport interface AccountMetricsOptions extends RequestOptions {\n /** Principio del rango. Por defecto, un día antes de `to_date`. */\n from_date?: Date | string | undefined;\n /** Final del rango. Por defecto, ahora. */\n to_date?: Date | string | undefined;\n /**\n * Sólo estas métricas, por su nombre CRUDO — los que devuelve {@link AccountsResource.metricList}.\n * Sin esto vuelven todas las medidas.\n */\n names?: readonly string[] | undefined;\n}\n\nexport interface ConnectLinksOptions extends RequestOptions {\n /** Sólo estas redes. Sin esto vuelven todas las que la organización pueda conectar ahora. */\n social_network?: readonly SocialNetwork[] | undefined;\n /**\n * A qué front de PlanVortex devuelve la red al usuario, para un despliegue de marca blanca.\n *\n * **No es una URL tuya**, y no puede serlo: las redes sólo aceptan `redirect_uri` registrados\n * en su propia configuración de aplicación. Tiene que ser uno de los fronts que el servidor\n * tiene dados de alta o la llamada contesta 532. A dónde vuelve TU usuario cuando termina se\n * decide en `organizations.createConnectToken({redirect_uri})`.\n */\n redirect_uri?: string | undefined;\n}\n\n/**\n * Lo que la red social pegó a la URL de vuelta. Se pasa **tal cual**, sin tocar ni filtrar: cada\n * red manda lo suyo (`code` y `state` casi todas, `oauth_token`/`oauth_verifier` X, ...).\n */\nexport type ConnectCallbackParams = Record<string, string | readonly string[] | undefined>;\n\nexport class AccountsResource extends Resource {\n /**\n * Los enlaces de autorización de cada red conectable, para mandar a la persona a la suya.\n *\n * **Con credenciales de app contesta 519.** Se llama con un cliente autenticado con el token\n * temporal: `pv.asTemporalToken(token).accounts.connectLinks(orgId)`.\n *\n * **Una red que no puede dar enlace simplemente no aparece**, y eso es una respuesta legítima y\n * no un fallo: es lo que pasa con Discord en una organización que todavía no ha guardado sus\n * propias credenciales de bot.\n *\n * OJO: la red devuelve al usuario a un front de PlanVortex, no a una URL tuya — ver\n * `redirect_uri` en {@link ConnectLinksOptions}.\n */\n async connectLinks(idOrganization: string, options: ConnectLinksOptions = {}): Promise<ConnectLink[]> {\n return unwrapOne<ConnectLink[]>(\n await this.httpGet<unknown>(\n `/organizations/${requireId(idOrganization, \"idOrganization\")}/connect_links`,\n { social_network: options.social_network, redirect_uri: options.redirect_uri },\n options,\n ),\n \"links\",\n );\n }\n\n /**\n * Completa la conexión con lo que la red social pegó a la URL de vuelta.\n *\n * **Esta llamada no la necesita la mayoría.** La URL de vuelta la construye la red a partir del\n * enlace de {@link connectLinks}, y apunta a un front de PlanVortex: es ese front el que llama\n * aquí. El método existe para quien sirve su propia interfaz en uno de los dominios registrados\n * en el servidor. En la integración normal —la del ejemplo `connect-flow`— basta con mandar al\n * usuario a la `url` del token temporal y esperarlo de vuelta.\n *\n * **El endpoint contesta 200 aunque haya fallado**, con el error dentro del cuerpo, porque el\n * navegador aterriza aquí desde una redirección y un 400 crudo sería una página rota. La\n * librería deshace ese apaño: si viene `errorCode`, **lanza** el error que le toca, igual que\n * cualquier otro método. Lo que devuelve son sólo cuentas buenas.\n *\n * **Y vuelven SIN habilitar**: no ocupan plaza del plan ni publican hasta que se llama a\n * {@link enable}. Una sola autorización puede dejar varias — un usuario de Facebook con cuatro\n * páginas son cuatro—, y por eso hay un paso de elección en medio.\n */\n async connect(\n idOrganization: string,\n socialNetwork: SocialNetwork,\n params: ConnectCallbackParams = {},\n options: RequestOptions = {},\n ): Promise<ConnectResult> {\n const path =\n `/organizations/${requireId(idOrganization, \"idOrganization\")}` +\n `/account-connect/${requireId(socialNetwork, \"socialNetwork\")}`;\n const body = await this.httpGet<{\n accounts?: Account[];\n errorCode?: string;\n errorMsg?: string;\n redirect_uri?: string;\n }>(path, params as Query, options);\n\n if (body.errorCode) {\n //El `errorCode` viaja como CADENA y es el código del catálogo, así que se reconstruye\n //el error como si hubiera venido en un cuerpo de error normal: así el integrador coge\n //un `AccountError` o un `PlanLimitError` y no una forma distinta sólo aquí.\n const code = Number(body.errorCode);\n throw createErrorFromResponse({\n body: {\n code: Number.isFinite(code) ? code : NO_ERROR_CODE,\n message: body.errorMsg || `La conexión no se completó (${body.errorCode}).`,\n },\n status: 200,\n });\n }\n\n return {\n accounts: body.accounts ?? [],\n ...(body.redirect_uri === undefined ? {} : { redirect_uri: body.redirect_uri }),\n };\n }\n\n /**\n * Da de alta una de las cuentas que dejó {@link connect}, o recupera una que se desconectó\n * mientras su token guardado siga sirviendo (si no, error 700 y hay que autorizar otra vez).\n *\n * **Es el paso que ocupa plaza del plan**: con el cupo lleno contesta 706, así que se llama una\n * a una y se mira el hueco antes (`organizations.limits`). Y es también el que enciende los\n * webhooks de la red, en cualquier plan que no sea el gratuito.\n */\n async enable(\n idOrganization: string,\n idAccount: string,\n options: RequestOptions = {},\n ): Promise<EnableResult> {\n const body = await this.httpPost<{ success?: boolean; redirect_uri?: string }>(\n `${this.path(idOrganization, idAccount)}/enable`,\n undefined,\n options,\n );\n //`success: true` no se devuelve: un fallo llega como excepción, así que aquí sólo interesa\n //si el token temporal traía un sitio al que mandar al usuario después.\n return body.redirect_uri === undefined ? {} : { redirect_uri: body.redirect_uri };\n }\n\n /** Las cuentas de una organización. */\n async list(\n idOrganization: string,\n options: AccountListOptions & RequestOptions = {},\n ): Promise<Paginated<Account>> {\n return this.getList<Account>(\n `/organizations/${requireId(idOrganization, \"idOrganization\")}/accounts`,\n \"accounts\",\n {\n offset: options.offset,\n limit: options.limit,\n name: options.name,\n social_network: options.social_network,\n accounts: options.accounts,\n capability: options.capability,\n },\n options,\n );\n }\n\n /** Las cuentas de una organización, encadenando páginas. */\n iterate(\n idOrganization: string,\n options: AccountListOptions & RequestOptions = {},\n ): AsyncGenerator<Account> {\n return iteratePages<Account>((page) => this.list(idOrganization, { ...options, ...page }), options);\n }\n\n /** La ficha de una cuenta. */\n async get(idOrganization: string, idAccount: string, options: RequestOptions = {}): Promise<Account> {\n return this.getOne<Account>(this.path(idOrganization, idAccount), \"account\", undefined, options);\n }\n\n /** Cambia el nombre con el que la cuenta se ve en PlanVortex. Es lo único editable. */\n async update(\n idOrganization: string,\n idAccount: string,\n body: { name?: string },\n options: RequestOptions = {},\n ): Promise<Account> {\n return this.putOne<Account>(this.path(idOrganization, idAccount), \"account\", body, options);\n }\n\n /**\n * Desconecta la cuenta y **borra sus publicaciones**. Lo ya publicado en la red se queda donde\n * está: esto no la toca.\n */\n async remove(idOrganization: string, idAccount: string, options: RequestOptions = {}): Promise<void> {\n await this.httpDelete<SuccessResponse>(this.path(idOrganization, idAccount), undefined, options);\n }\n\n /**\n * La serie de métricas ya medidas de una cuenta.\n *\n * Es lectura de lo guardado, no una llamada a la red: mirar la gráfica no cuesta créditos. El\n * agrupado lo decide el rango — hasta 31 días por día, hasta 720 por mes, y de ahí por año— y\n * viene dicho en `group`.\n */\n async metrics(\n idOrganization: string,\n idAccount: string,\n options: AccountMetricsOptions = {},\n ): Promise<AccountMetrics> {\n return this.httpGet<AccountMetrics>(\n `${this.path(idOrganization, idAccount)}/metrics`,\n {\n from_date: options.from_date,\n to_date: options.to_date,\n names: options.names,\n },\n options,\n );\n }\n\n /**\n * Los nombres CRUDOS de las métricas que publica la red de esta cuenta.\n *\n * Son los que se pasan a {@link metrics} y los que vuelven en cada fila. No es el vocabulario\n * común —eso es `metrics` de una publicación—: aquí cada red habla su idioma\n * (`page_impressions`, `total_interactions`, `allPageViews`).\n */\n async metricList(\n idOrganization: string,\n idAccount: string,\n options: RequestOptions = {},\n ): Promise<string[]> {\n return this.httpGet<string[]>(\n `${this.path(idOrganization, idAccount)}/metric_list`,\n undefined,\n options,\n );\n }\n\n /**\n * El menú fijo del chat, una entrada por idioma.\n *\n * Sólo las redes con mensajería lo tienen: en las demás la llamada devuelve el error 710. Se\n * comprueba con `persistent_menu` de `catalog.socialCapabilities()`.\n */\n async getPersistentMenu(\n idOrganization: string,\n idAccount: string,\n options: RequestOptions = {},\n ): Promise<PersistentMenu> {\n return unwrapOne<PersistentMenu>(\n await this.httpGet<unknown>(\n `${this.path(idOrganization, idAccount)}/persistent_menu`,\n undefined,\n options,\n ),\n \"persistent_menu\",\n );\n }\n\n /**\n * Reemplaza el menú fijo del chat. Es un REEMPLAZO: lo que no vaya en el array desaparece.\n *\n * La entrada con `locale: \"default\"` es obligatoria — es la que se enseña cuando ninguna otra\n * encaja.\n */\n async setPersistentMenu(\n idOrganization: string,\n idAccount: string,\n menu: PersistentMenu,\n options: RequestOptions = {},\n ): Promise<PersistentMenu> {\n return unwrapOne<PersistentMenu>(\n await this.httpPost<unknown>(\n `${this.path(idOrganization, idAccount)}/persistent_menu`,\n { persistent_menu: menu },\n options,\n ),\n \"persistent_menu\",\n );\n }\n\n private path(idOrganization: string, idAccount: string): string {\n return `/organizations/${requireId(idOrganization, \"idOrganization\")}/accounts/${requireId(idAccount, \"idAccount\")}`;\n }\n}\n","/**\n * El catálogo: qué redes hay, qué sabe hacer cada una y contra qué límites se valida.\n *\n * POR QUÉ SE CACHEA: son constantes del despliegue. No dependen del cliente, no dependen de la\n * organización y no cambian entre dos llamadas — cambian cuando se despliega el servidor. Un\n * compositor que valide el texto mientras se escribe pediría `/social_limits` en cada tecla; con la\n * caché lo pide una vez por instancia de {@link PlanVortex}.\n *\n * POR QUÉ SE PIDEN Y NO SE ESCRIBEN AQUÍ: es la regla de la casa — quien valida el límite es quien\n * lo anuncia. El panel tenía su propia tabla y divergió: contaba LinkedIn hasta 3.000 mientras el\n * servidor lo tumbaba a los 1.300, así que el usuario escribía un texto que el contador daba por\n * bueno y la API rechazaba. Una copia dentro de esta librería sería el mismo error un piso más\n * abajo, y encima repartido por npm.\n *\n * LA CACHÉ ES POR INSTANCIA Y NO CADUCA. Un proceso de días que quiera enterarse de una red nueva\n * llama a {@link CatalogResource.clearCache}; un proceso normal se muere antes de que importe.\n */\nimport { Resource } from \"./base.js\";\nimport type { RequestOptions } from \"./base.js\";\nimport type {\n AspectRatiosByNetwork,\n CommentActions,\n PublicationLimits,\n SocialCapabilities,\n SocialLimits,\n SocialNetwork,\n} from \"../types.js\";\n\nexport class CatalogResource extends Resource {\n private readonly cache = new Map<string, Promise<unknown>>();\n\n /**\n * Las redes soportadas.\n *\n * **La lista crece varias veces al año.** No la copies a una constante tuya: pídela.\n */\n async socialNetworks(options?: RequestOptions): Promise<SocialNetwork[]> {\n return this.cached(\"/social_networks\", () =>\n this.httpGet<SocialNetwork[]>(\"/social_networks\", undefined, options),\n );\n }\n\n /** Las redes que aceptan publicaciones. Ni WhatsApp ni Google Business están. */\n async allowedSocialPublications(options?: RequestOptions): Promise<SocialNetwork[]> {\n return this.cached(\"/allowed_social_publications\", () =>\n this.httpGet<SocialNetwork[]>(\"/allowed_social_publications\", undefined, options),\n );\n }\n\n /**\n * Las redes con conversaciones.\n *\n * Va en `POST` y no en `GET`, que es raro y es así: es la ruta que hay. No manda cuerpo.\n */\n async allowedSocialMessages(options?: RequestOptions): Promise<SocialNetwork[]> {\n return this.cached(\"/allowed_social_messages\", () =>\n this.httpPost<SocialNetwork[]>(\"/allowed_social_messages\", undefined, options),\n );\n }\n\n /**\n * La matriz red → qué sabe hacer: publicar, mensajes, productos, webhooks, menú persistente y\n * comentarios.\n *\n * Es lo que evita ofrecer una cuenta en una pantalla que su red no soporta — WhatsApp en el\n * compositor, LinkedIn en el chat.\n */\n async socialCapabilities(options?: RequestOptions): Promise<Record<string, SocialCapabilities>> {\n return this.cached(\"/social_capabilities\", () =>\n this.httpGet<Record<string, SocialCapabilities>>(\"/social_capabilities\", undefined, options),\n );\n }\n\n /**\n * La matriz red → qué se puede hacer con un comentario: responder, ocultar, borrar el propio y\n * borrar el de otro.\n *\n * Va **aparte** de {@link socialCapabilities} porque aquélla es `{[capacidad]: boolean}` y esto\n * es un objeto por red: meterlo dentro rompería su forma. Que la red tenga comentarios no dice\n * lo suficiente — Instagram, X y Bluesky no dejan borrar el de otro, LinkedIn no tiene\n * \"ocultar\", y Google Business sólo deja borrar **nuestra propia respuesta**.\n */\n async socialCommentActions(options?: RequestOptions): Promise<Record<string, CommentActions>> {\n return this.cached(\"/social_comment_actions\", () =>\n this.httpGet<Record<string, CommentActions>>(\"/social_comment_actions\", undefined, options),\n );\n }\n\n /**\n * Los topes de cada red, por los que el servidor valida.\n *\n * Bluesky lleva **dos** cuentas del mismo texto y en unidades distintas: 300 grafemas en\n * `characters` y 3.000 bytes en `max_post_bytes`. `.length` miente en las dos direcciones —un\n * emoji de familia es UN grafema y 25 bytes—, así que un contador que use `.length` da por\n * bueno lo que la API rechaza y al revés.\n */\n async socialLimits(options?: RequestOptions): Promise<SocialLimits> {\n return this.cached(\"/social_limits\", () =>\n this.httpGet<SocialLimits>(\"/social_limits\", undefined, options),\n );\n }\n\n /** Los topes de una publicación que no dependen de la red: hoy, cuántos reintentos manuales admite. */\n async publicationLimits(options?: RequestOptions): Promise<PublicationLimits> {\n return this.cached(\"/publication_limits\", () =>\n this.httpGet<PublicationLimits>(\"/publication_limits\", undefined, options),\n );\n }\n\n /**\n * Los recortes que acepta cada red.\n *\n * Se indexa por red **y por formato** (`facebook`, `facebook_reels`, `facebook_stories`), así\n * que no todas las claves son una red. `values` y `text` son arrays paralelos: mismo índice,\n * mismo recorte.\n */\n async allowedAspectRatios(options?: RequestOptions): Promise<AspectRatiosByNetwork> {\n return this.cached(\"/allowed_aspect_ratios\", () =>\n this.httpGet<AspectRatiosByNetwork>(\"/allowed_aspect_ratios\", undefined, options),\n );\n }\n\n /** Tira la caché. Para un proceso largo que quiera enterarse de una red nueva sin reiniciar. */\n clearCache(): void {\n this.cache.clear();\n }\n\n /**\n * Guarda la PROMESA, no el resultado: dos llamadas a la vez comparten una petición en vez de\n * lanzar dos. Si falla, la entrada se retira para que el siguiente intento vuelva a pedirla —\n * cachear un fallo de red deja la instancia rota para siempre.\n */\n private cached<T>(key: string, fetch: () => Promise<T>): Promise<T> {\n const hit = this.cache.get(key);\n if (hit) {\n return hit as Promise<T>;\n }\n const pending = fetch().catch((error: unknown) => {\n this.cache.delete(key);\n throw error;\n });\n this.cache.set(key, pending);\n return pending;\n }\n}\n","/**\n * Clientes: quien contrata el plan y a quien cuelgan las organizaciones.\n *\n * LO QUE HAY QUE ENTENDER DEL PLAN, porque el spec lo describía mal hasta la fase 6 y era fácil\n * leer el campo equivocado: `client.actual_plan` es la **suscripción** (si está activa, qué plan\n * es, cuándo acaba el periodo), y los números están dentro, en `actual_plan.plan_data`. Mirar\n * `plan_identifier` para saber los límites es el error clásico: un plan `custom` lleva los suyos.\n *\n * Y el CONSUMO no viaja si no se pide: `actual_use` y `actual_asigned` sólo aparecen con\n * `getUse: true`, porque contarlos es una agregación sobre todas las organizaciones del cliente.\n */\nimport { Resource, requireId } from \"./base.js\";\nimport type { RequestOptions, SuccessResponse } from \"./base.js\";\nimport type { PageOptions } from \"../core/pagination.js\";\nimport { iteratePages } from \"../core/pagination.js\";\nimport type { Client, Organization, Paginated } from \"../types.js\";\n\nexport interface ClientListOptions extends PageOptions {\n /** Trae también `actual_use` y `actual_asigned`. Cuesta una agregación: no lo pidas por costumbre. */\n getUse?: boolean | undefined;\n}\n\nexport interface OrganizationListOptions extends ClientListOptions {\n /** Búsqueda por nombre. */\n name?: string | undefined;\n}\n\n/** Lo que se manda para crear una organización. `actual_plan` es el cupo que se le asigna. */\nexport interface OrganizationInput {\n name: string;\n actual_plan?: Partial<Organization[\"actual_plan\"]> | undefined;\n}\n\nexport class ClientsResource extends Resource {\n /** Los clientes que puede ver quien llama. Con credenciales de app, el suyo. */\n async list(options: ClientListOptions & RequestOptions = {}): Promise<Paginated<Client>> {\n return this.getList<Client>(\"/clients\", \"clients\", listQuery(options), options);\n }\n\n /** Los clientes, página a página, sin tener que llevar el `offset` a mano. */\n iterate(options: ClientListOptions & RequestOptions = {}): AsyncGenerator<Client> {\n return iteratePages<Client>((page) => this.list({ ...options, ...page }), options);\n }\n\n /** La ficha de un cliente. */\n async get(\n idClient: string,\n options: { getUse?: boolean | undefined } & RequestOptions = {},\n ): Promise<Client> {\n return this.getOne<Client>(\n `/clients/${requireId(idClient, \"idClient\")}`,\n \"client\",\n options.getUse ? { getUse: true } : undefined,\n options,\n );\n }\n\n /** Cambia lo poco que de un cliente se puede cambiar: hoy, su nombre. */\n async update(idClient: string, body: { name?: string }, options: RequestOptions = {}): Promise<Client> {\n return this.putOne(`/clients/${requireId(idClient, \"idClient\")}`, \"client\", body, options);\n }\n\n /** Las organizaciones RAÍZ de un cliente. Las hijas cuelgan de cada una. */\n async organizations(\n idClient: string,\n options: OrganizationListOptions & RequestOptions = {},\n ): Promise<Paginated<Organization>> {\n return this.getList<Organization>(\n `/clients/${requireId(idClient, \"idClient\")}/organizations`,\n \"organizations\",\n { ...listQuery(options), name: options.name },\n options,\n );\n }\n\n /** Las organizaciones raíz de un cliente, encadenando páginas. */\n iterateOrganizations(\n idClient: string,\n options: OrganizationListOptions & RequestOptions = {},\n ): AsyncGenerator<Organization> {\n return iteratePages<Organization>(\n (page) => this.organizations(idClient, { ...options, ...page }),\n options,\n );\n }\n\n /** Crea una organización raíz. Lo que se le asigne se descuenta de lo que el cliente tiene. */\n async createOrganization(\n idClient: string,\n body: OrganizationInput,\n options: RequestOptions = {},\n ): Promise<Organization> {\n return this.postOne(\n `/clients/${requireId(idClient, \"idClient\")}/organizations`,\n \"organization\",\n body,\n options,\n );\n }\n\n /** Cambia una organización raíz: su nombre o el cupo que tiene asignado. */\n async updateOrganization(\n idClient: string,\n idOrganization: string,\n body: Partial<OrganizationInput>,\n options: RequestOptions = {},\n ): Promise<Organization> {\n return this.putOne(\n `/clients/${requireId(idClient, \"idClient\")}/organizations/${requireId(idOrganization, \"idOrganization\")}`,\n \"organization\",\n body,\n options,\n );\n }\n\n /**\n * Borra una organización raíz **con todo lo que tiene dentro**: sus organizaciones hijas, sus\n * cuentas, sus publicaciones, sus ficheros y sus comentarios. No se deshace.\n */\n async deleteOrganization(\n idClient: string,\n idOrganization: string,\n options: RequestOptions = {},\n ): Promise<void> {\n await this.httpDelete<SuccessResponse>(\n `/clients/${requireId(idClient, \"idClient\")}/organizations/${requireId(idOrganization, \"idOrganization\")}`,\n undefined,\n options,\n );\n }\n}\n\nfunction listQuery(options: ClientListOptions): Record<string, string | number | boolean | undefined> {\n return {\n offset: options.offset,\n limit: options.limit,\n //`getUse` sólo se manda cuando se pide: un `getUse=false` en la query es ruido en el log.\n getUse: options.getUse ? true : undefined,\n };\n}\n","/**\n * Organizaciones: el contenedor de cuentas, publicaciones y ficheros, y el que reparte el cupo.\n *\n * LO QUE SORPRENDE: `organization.actual_plan` es lo ASIGNADO, y **falta cuando no se le asignó\n * nada**. Una organización sin plan propio comparte el del primer padre que tenga uno, y si no lo\n * hay, el resto sin repartir del cliente. Así que para saber qué puede hacer de verdad no se lee\n * `actual_plan`: se llama a {@link OrganizationsResource.limits}, que es quien resuelve la cascada.\n */\nimport { Resource, requireId } from \"./base.js\";\nimport type { RequestOptions, SuccessResponse } from \"./base.js\";\nimport type { PageOptions } from \"../core/pagination.js\";\nimport { iteratePages } from \"../core/pagination.js\";\nimport type { ConnectToken, Organization, Paginated, PlanData, SocialNetwork } from \"../types.js\";\nimport type { OrganizationInput } from \"./clients.js\";\n\nexport interface OrganizationOptions extends RequestOptions {\n /** Trae también `actual_use` y `actual_asigned`. Cuesta una agregación: no lo pidas por costumbre. */\n getUse?: boolean | undefined;\n}\n\nexport interface ChildOrganizationListOptions extends OrganizationOptions, PageOptions {\n /** Búsqueda por nombre. */\n name?: string | undefined;\n}\n\n/** Lo que se puede repartir a una organización hija. Todo son números del plan del padre. */\nexport type OrganizationPlanInput = Partial<PlanData>;\n\nexport interface ConnectTokenOptions extends RequestOptions {\n /**\n * La red que la persona va a conectar. Viaja dentro de la `url` para que el panel no vuelva a\n * preguntarla. Sin esto, el usuario elige red al llegar.\n */\n social_network?: SocialNetwork | undefined;\n /**\n * A dónde vuelve el usuario cuando termina. Tiene que ser uno de los `redirect_urls`\n * registrados en la app, o la llamada contesta el error 532.\n */\n redirect_uri?: string | undefined;\n}\n\nexport class OrganizationsResource extends Resource {\n /** La ficha de una organización. */\n async get(idOrganization: string, options: OrganizationOptions = {}): Promise<Organization> {\n return this.getOne<Organization>(\n `/organizations/${requireId(idOrganization, \"idOrganization\")}`,\n \"organization\",\n options.getUse ? { getUse: true } : undefined,\n options,\n );\n }\n\n /** Cambia el nombre de una organización o el cupo que tiene asignado. */\n async update(\n idOrganization: string,\n body: Partial<OrganizationInput>,\n options: RequestOptions = {},\n ): Promise<Organization> {\n return this.putOne<Organization>(\n `/organizations/${requireId(idOrganization, \"idOrganization\")}`,\n \"organization\",\n body,\n options,\n );\n }\n\n /**\n * Borra una organización **con todo lo que tiene dentro**: sus hijas, sus cuentas, sus\n * publicaciones, sus ficheros y sus comentarios. No se deshace.\n */\n async remove(idOrganization: string, options: RequestOptions = {}): Promise<void> {\n await this.httpDelete<SuccessResponse>(\n `/organizations/${requireId(idOrganization, \"idOrganization\")}`,\n undefined,\n options,\n );\n }\n\n /** Las organizaciones que cuelgan de ésta. */\n async children(\n idOrganization: string,\n options: ChildOrganizationListOptions = {},\n ): Promise<Paginated<Organization>> {\n return this.getList<Organization>(\n `/organizations/${requireId(idOrganization, \"idOrganization\")}/organizations`,\n \"organizations\",\n {\n offset: options.offset,\n limit: options.limit,\n name: options.name,\n getUse: options.getUse ? true : undefined,\n },\n options,\n );\n }\n\n /** Las organizaciones hijas, encadenando páginas. */\n iterateChildren(\n idOrganization: string,\n options: ChildOrganizationListOptions = {},\n ): AsyncGenerator<Organization> {\n return iteratePages<Organization>(\n (page) => this.children(idOrganization, { ...options, ...page }),\n options,\n );\n }\n\n /** Crea una organización hija con el cupo que se le reparta del plan de ésta. */\n async createChild(\n idOrganization: string,\n body: OrganizationInput,\n options: RequestOptions = {},\n ): Promise<Organization> {\n return this.postOne<Organization>(\n `/organizations/${requireId(idOrganization, \"idOrganization\")}/organizations`,\n \"organization\",\n body,\n options,\n );\n }\n\n /**\n * Lo que esta organización puede usar de verdad, con la cascada ya resuelta: su plan propio, o\n * el del primer padre que tenga uno, o el resto sin repartir del cliente.\n *\n * Es lo que hay que mirar antes de conectar una cuenta o programar una publicación, no\n * `organization.actual_plan`.\n */\n async limits(idOrganization: string, options: RequestOptions = {}): Promise<PlanData> {\n return this.httpGet<PlanData>(\n `/organizations/${requireId(idOrganization, \"idOrganization\")}/limits`,\n undefined,\n options,\n );\n }\n\n /**\n * El consumo de esta organización y lo que ya tiene repartido a sus hijas.\n *\n * Es un atajo de `get(id, {getUse: true})` que devuelve sólo las dos cifras, que es lo que se\n * quiere cuando se está pintando una barra de \"3 de 5 cuentas\".\n */\n async use(\n idOrganization: string,\n options: RequestOptions = {},\n ): Promise<{ actual_use: PlanData | undefined; actual_asigned: PlanData | undefined }> {\n const organization = await this.get(idOrganization, { ...options, getUse: true });\n return { actual_use: organization.actual_use, actual_asigned: organization.actual_asigned };\n }\n\n /**\n * Emite el token temporal con el que **una persona** conecta una cuenta social a esta\n * organización. Es la única forma que tiene una app de que se le conecte una cuenta.\n *\n * Y es el reverso exacto del resto del flujo: éste es el endpoint que **exige credenciales de\n * app** —con un token de usuario contesta 514—, mientras que los tres que vienen después\n * (`accounts.connectLinks`, `accounts.connect`, `accounts.enable`) las rechazan con un 519.\n *\n * Vuelven las dos formas del mismo credencial, y las dos sirven:\n *\n * - **`url`** — el camino alojado. Se redirige al usuario ahí y PlanVortex se encarga de la\n * elección de red, del OAuth y de la pantalla donde elige qué cuentas dar de alta. Es lo que\n * hace el ejemplo `examples/connect-flow`, y lo que casi todo el mundo quiere.\n * - **`token`** — el credencial suelto, para `pv.asTemporalToken(token)` cuando la interfaz la\n * pone el integrador.\n *\n * Caduca en una hora y **sólo vale para esta organización**: usarlo contra otra contesta 1101.\n */\n async createConnectToken(\n idOrganization: string,\n options: ConnectTokenOptions = {},\n ): Promise<ConnectToken> {\n return this.httpGet<ConnectToken>(\n `/organizations/${requireId(idOrganization, \"idOrganization\")}/temporal_connect_token`,\n { social_network: options.social_network, redirect_uri: options.redirect_uri },\n options,\n );\n }\n}\n","/**\n * Publicaciones: el camino que vende `/developers`.\n *\n * LO QUE HAY QUE SABER ANTES DE LLAMAR A NADA DE AQUÍ:\n *\n * - **Crear una publicación con contenido inválido NO da error.** El servidor la guarda en estado\n * `withErrors` con el motivo dentro (`publication_errors`), porque el contenido se valida contra\n * la red y eso no es un fallo de la petición. Un `try/catch` no basta: hay que mirar `state`.\n * - **Sin `publish_date` sale YA**, en la propia petición. Con fecha futura queda `ready` y la\n * manda el robot a su hora.\n * - **`files` se manda como identificadores y vuelve poblado.** Lo que llega en la respuesta son\n * `Upload` enteros, no ids (§ el aviso de `Publication`).\n * - **`id_account` cambia de forma según la operación**: aquí (crear, leer, reintentar) viene\n * resuelto, y en el listado y al actualizar viene como identificador. `accountId(publication)`\n * lo tapa.\n * - **Borrar una publicación la borra TAMBIÉN de la red social.** No es sólo quitarla de la\n * biblioteca.\n */\nimport { Resource, requireId } from \"./base.js\";\nimport type { Query, RequestOptions, SuccessResponse } from \"./base.js\";\nimport type { PageOptions } from \"../core/pagination.js\";\nimport { iteratePages } from \"../core/pagination.js\";\nimport type {\n Paginated,\n Publication,\n PublicationInput,\n PublicationState,\n PublicationStats,\n PublicationStatsHistory,\n SocialNetwork,\n} from \"../types.js\";\n\nexport interface PublicationListOptions extends PageOptions {\n /** Sólo las publicadas o creadas a partir de esta fecha, según `orderByPublish`. */\n from_date?: Date | string | undefined;\n /** Sólo hasta esta fecha. */\n to_date?: Date | string | undefined;\n /** Búsqueda de texto sobre el nombre, el texto y el título. */\n search?: string | undefined;\n /** Ordena y filtra por `publish_date` en vez de por `creation_date`. */\n orderByPublish?: boolean | undefined;\n /** Sólo estos estados. */\n state?: readonly PublicationState[] | undefined;\n /** Sólo estas cuentas, por identificador. */\n accounts?: readonly string[] | undefined;\n /** Sólo estas redes. */\n social_network?: readonly SocialNetwork[] | undefined;\n}\n\n/** Lo que devuelve reintentar: la publicación tal y como quedó, y el tope que aplica el servidor. */\nexport interface PublicationRetryResult {\n publication: Publication;\n /** Reintentos manuales que admite en total. Léelo de aquí en vez de escribirlo tú. */\n max_retries: number;\n}\n\nexport class PublicationsResource extends Resource {\n /**\n * Crea una publicación en una cuenta.\n *\n * Sin `publish_date` se envía en esta misma petición y la respuesta ya dice si salió\n * (`state: \"sended\"`) o si falló y por qué. Con fecha futura queda `ready`.\n *\n * ```ts\n * const publication = await pv.publications.create(orgId, accountId, {\n * social_network: \"instagram\",\n * text: \"Nuevo horno, nuevas hogazas\",\n * files: [upload._id],\n * publish_date: new Date(\"2026-09-01T10:00:00Z\"),\n * });\n * ```\n */\n async create(\n idOrganization: string,\n idAccount: string,\n body: PublicationInput,\n options: RequestOptions = {},\n ): Promise<Publication> {\n return this.postOne<Publication>(\n `/organizations/${requireId(idOrganization, \"idOrganization\")}/accounts/${requireId(idAccount, \"idAccount\")}/publish`,\n \"publication\",\n serializeInput(body),\n options,\n );\n }\n\n /** Una publicación, con sus ficheros y su cuenta ya resueltos. */\n async get(\n idOrganization: string,\n idPublication: string,\n options: RequestOptions = {},\n ): Promise<Publication> {\n return this.getOne<Publication>(\n this.path(idOrganization, idPublication),\n \"publication\",\n undefined,\n options,\n );\n }\n\n /** Las publicaciones de una organización. */\n async list(\n idOrganization: string,\n options: PublicationListOptions & RequestOptions = {},\n ): Promise<Paginated<Publication>> {\n return this.getList<Publication>(\n `/organizations/${requireId(idOrganization, \"idOrganization\")}/publish`,\n \"publications\",\n listQuery(options),\n options,\n );\n }\n\n /** Las publicaciones de una organización, encadenando páginas. */\n iterate(\n idOrganization: string,\n options: PublicationListOptions & RequestOptions = {},\n ): AsyncGenerator<Publication> {\n return iteratePages<Publication>(\n (page) => this.list(idOrganization, { ...options, ...page }),\n options,\n );\n }\n\n /** Las publicaciones de UNA cuenta. Mismos filtros que {@link list}. */\n async listByAccount(\n idOrganization: string,\n idAccount: string,\n options: PublicationListOptions & RequestOptions = {},\n ): Promise<Paginated<Publication>> {\n return this.getList<Publication>(\n `/organizations/${requireId(idOrganization, \"idOrganization\")}/accounts/${requireId(idAccount, \"idAccount\")}/publish`,\n \"publications\",\n listQuery(options),\n options,\n );\n }\n\n /**\n * Cambia una publicación que todavía no ha salido. Una `sended` devuelve el error 921.\n *\n * Editar PONE EL CONTADOR DE REINTENTOS A CERO: el contador cuenta intentos de publicar *ese*\n * contenido, y acabas de cambiarlo. Es además la salida cuando se agotan los tres.\n */\n async update(\n idOrganization: string,\n idPublication: string,\n body: Partial<PublicationInput>,\n options: RequestOptions = {},\n ): Promise<Publication> {\n return this.putOne<Publication>(\n this.path(idOrganization, idPublication),\n \"publication\",\n serializeInput(body),\n options,\n );\n }\n\n /**\n * Borra una publicación **y también el post en la red social**.\n *\n * En X borrar cuesta créditos: sin ellos devuelve un 940 en vez de un error genérico.\n */\n async remove(idOrganization: string, idPublication: string, options: RequestOptions = {}): Promise<void> {\n await this.httpDelete<SuccessResponse>(this.path(idOrganization, idPublication), undefined, options);\n }\n\n /**\n * Vuelve a intentar una publicación que falló, sin tocar su contenido.\n *\n * Se reintenta EN LA PETICIÓN, así que la respuesta ya dice si esta vez salió. Cada llamada\n * gasta un reintento aunque vuelva a fallar por el contenido; sólo los créditos de X cortan\n * antes de gastarlo. Una publicación que no está en `withErrors` devuelve un 949, y agotar el\n * tope, un 950.\n */\n async retry(\n idOrganization: string,\n idPublication: string,\n options: RequestOptions = {},\n ): Promise<PublicationRetryResult> {\n return this.httpPost<PublicationRetryResult>(\n `${this.path(idOrganization, idPublication)}/retry`,\n undefined,\n options,\n );\n }\n\n /**\n * Pide las métricas A LA RED, en vivo, y devuelve su desglose crudo.\n *\n * **En X esto cuesta un crédito por lectura.** Para pintar una gráfica usa {@link stats}, que\n * lee lo ya medido y no cuesta nada.\n */\n async metrics(\n idOrganization: string,\n idPublication: string,\n options: RequestOptions = {},\n ): Promise<PublicationStats> {\n return this.httpGet<PublicationStats>(\n `${this.path(idOrganization, idPublication)}/metrics`,\n undefined,\n options,\n );\n }\n\n /**\n * La evolución medida de una publicación: una fila por día, más su última medición.\n *\n * Es lectura pura de lo guardado: mirar la gráfica no llama a la red y no cuesta créditos. Una\n * `series` vacía es una respuesta válida —recién enviada, o una red sin estadísticas—, no un\n * error. Cada `metrics` es el ACUMULADO a esa fecha, no el incremento del día.\n */\n async stats(\n idOrganization: string,\n idPublication: string,\n options: RequestOptions = {},\n ): Promise<PublicationStatsHistory> {\n return this.httpGet<PublicationStatsHistory>(\n `${this.path(idOrganization, idPublication)}/stats`,\n undefined,\n options,\n );\n }\n\n /**\n * Lo que hay publicado en el muro de la cuenta **según la red**, no según PlanVortex: incluye\n * lo que se publicó por fuera.\n *\n * **En X cuesta un crédito por elemento leído**, así que el `limit` es dinero.\n */\n async listOnNetwork(\n idOrganization: string,\n idAccount: string,\n options: PageOptions & RequestOptions = {},\n ): Promise<Paginated<Publication>> {\n return this.getList<Publication>(\n `/organizations/${requireId(idOrganization, \"idOrganization\")}/accounts/${requireId(idAccount, \"idAccount\")}/social_publications`,\n \"publications\",\n { offset: options.offset, limit: options.limit },\n options,\n );\n }\n\n private path(idOrganization: string, idPublication: string): string {\n return `/organizations/${requireId(idOrganization, \"idOrganization\")}/publish/${requireId(idPublication, \"idPublication\")}`;\n }\n}\n\nfunction listQuery(options: PublicationListOptions): Query {\n return {\n offset: options.offset,\n limit: options.limit,\n from_date: options.from_date,\n to_date: options.to_date,\n search: options.search,\n //El servidor lo lee como el literal \"true\": un `false` no cambia nada, así que se omite.\n orderByPublish: options.orderByPublish ? true : undefined,\n state: options.state,\n accounts: options.accounts,\n social_network: options.social_network,\n };\n}\n\n/**\n * Un `Date` en `publish_date` se manda en ISO.\n *\n * `buildQuery` ya lo hace en la query, pero el cuerpo va por `JSON.stringify`, que serializa un\n * `Date` en ISO igualmente — esto es para que el tipo lo admita sin que quien llama tenga que\n * escribir `.toISOString()`, que es lo primero que se olvida.\n */\nfunction serializeInput(body: Partial<PublicationInput>): Record<string, unknown> {\n const { publish_date, ...rest } = body;\n return {\n ...rest,\n ...(publish_date === undefined\n ? {}\n : { publish_date: typeof publish_date === \"string\" ? publish_date : publish_date.toISOString() }),\n };\n}\n","/**\n * De \"un fichero\" a la parte `file` de un `multipart/form-data` que el servidor acepte.\n *\n * TRES COSAS QUE NO SE PUEDEN IMPROVISAR (§ trampa 10 del roadmap):\n *\n * 1. **Un vídeo no se lee a un `Buffer`.** El límite del servidor son 200 MB por vídeo; leerlo\n * entero a memoria funciona con una foto y tumba el proceso con un vídeo real. Se usa\n * `fs.openAsBlob()`, que devuelve un `Blob` PEREZOSO: `fetch` lo va leyendo del disco a medida\n * que lo manda. El `Buffer` sólo aparece si esa función no existe (Node < 20.4).\n * 2. **El `content-type` de la parte decide qué guarda el servidor.** `file_type` (imagen o vídeo)\n * y `file_format` salen del MIME que mande el cliente, no del contenido ni del nombre. Un\n * `application/octet-stream` —que es lo que pone un `Blob` sin `type`— se lleva un error 805\n * («no es una imagen ni un vídeo») con un JPEG perfectamente válido dentro. Por eso se deduce\n * de la extensión y por eso se puede pasar a mano.\n * 3. **El `content-type` de la PETICIÓN no se toca.** Lo pone `FormData` con su `boundary`, y\n * escribirlo a mano rompe el multipart entero. `HttpClient` ya lo respeta; esto sólo lo\n * recuerda para el día que alguien añada una cabecera \"por si acaso\".\n */\nimport { basename } from \"node:path\";\n\nimport { PlanVortexConfigError } from \"./errors.js\";\n\n/**\n * Un fichero, en cualquiera de las formas en que un integrador lo tiene a mano.\n *\n * La ruta es la buena para lo grande: es la única que no pasa por memoria.\n */\nexport type FileSource = string | Buffer | Uint8Array | Blob;\n\nexport interface FileInput {\n /** Ruta en disco, `Buffer` o `Blob`. */\n file: FileSource;\n /**\n * Nombre con el que se guarda. Con una ruta se deduce del último tramo; con un `Buffer` es\n * obligatorio, porque no hay de dónde sacarlo.\n */\n filename?: string | undefined;\n /**\n * MIME de la parte. Se deduce de la extensión; pásalo cuando el nombre no la tenga o mienta.\n * Es lo que decide `file_type` y `file_format` en el servidor.\n */\n contentType?: string | undefined;\n}\n\n/**\n * Extensión -> MIME, sólo de lo que el servidor acepta en la puerta\n * (`ALLOWED_FILES_FORMATS`). `heic`/`heif` entran y se convierten a JPEG durante la ingesta, así\n * que se mandan tal cual: es el servidor quien los convierte, no la librería.\n */\nconst MIME_BY_EXTENSION: Readonly<Record<string, string>> = {\n jpg: \"image/jpeg\",\n jpeg: \"image/jpeg\",\n png: \"image/png\",\n gif: \"image/gif\",\n heic: \"image/heic\",\n heif: \"image/heif\",\n mp4: \"video/mp4\",\n};\n\n/** El MIME que le corresponde a un nombre de fichero, o `undefined` si la extensión no se conoce. */\nexport function guessContentType(filename: string): string | undefined {\n const extension = filename.split(\".\").pop()?.toLowerCase();\n return extension ? MIME_BY_EXTENSION[extension] : undefined;\n}\n\nfunction isBinary(value: unknown): value is Buffer | Uint8Array {\n return value instanceof Uint8Array;\n}\n\n/**\n * Convierte un {@link FileInput} en el `Blob` y el nombre con los que se monta el `FormData`.\n *\n * Se exporta aparte de {@link buildUploadForm} porque es lo único de aquí que hace E/S y lo que un\n * test quiere mirar por su cuenta.\n */\nexport async function toFilePart(input: FileInput): Promise<{ blob: Blob; filename: string }> {\n const { file } = input;\n\n if (typeof file === \"string\") {\n const filename = input.filename ?? basename(file);\n const type = input.contentType ?? guessContentType(filename);\n if (!type) {\n throw new PlanVortexConfigError(\n `No se puede deducir el tipo de \"${filename}\": pasa contentType. El servidor decide ` +\n \"si es imagen o vídeo por el tipo que mandes, no por el contenido.\",\n );\n }\n return { blob: await openFileAsBlob(file, type), filename };\n }\n\n if (isBinary(file)) {\n const filename = input.filename;\n if (!filename) {\n throw new PlanVortexConfigError(\"Un Buffer no lleva nombre: pasa filename junto al fichero.\");\n }\n const type = input.contentType ?? guessContentType(filename);\n if (!type) {\n throw new PlanVortexConfigError(\n `No se puede deducir el tipo de \"${filename}\": pasa contentType.`,\n );\n }\n //`Uint8Array` puede ser una vista de un ArrayBuffer más grande: se copia el tramo suyo.\n return { blob: new Blob([file.slice()], { type }), filename };\n }\n\n if (file instanceof Blob) {\n const filename = input.filename ?? (file instanceof File ? file.name : undefined);\n if (!filename) {\n throw new PlanVortexConfigError(\"Un Blob sin nombre: pasa filename junto al fichero.\");\n }\n const type = input.contentType ?? (file.type || guessContentType(filename));\n if (!type) {\n throw new PlanVortexConfigError(\n `No se puede deducir el tipo de \"${filename}\": pasa contentType.`,\n );\n }\n //Sólo se re-envuelve si hay que cambiarle el tipo: `slice` de un Blob perezoso conserva la\n //pereza, pero envolver por envolver es una copia que no hace falta.\n return { blob: file.type === type ? file : file.slice(0, file.size, type), filename };\n }\n\n throw new PlanVortexConfigError(\"El fichero tiene que ser una ruta, un Buffer o un Blob.\");\n}\n\n/**\n * El `FormData` de `POST /organizations/{id}/uploads`.\n *\n * El nombre del campo es `file` y no es negociable: el servidor lo lee con\n * `uploadMulter.single(\"file\")` y cualquier otro nombre llega como \"no se subió ningún fichero\".\n */\nexport async function buildUploadForm(input: FileInput): Promise<FormData> {\n const { blob, filename } = await toFilePart(input);\n const form = new FormData();\n form.append(\"file\", blob, filename);\n return form;\n}\n\n/**\n * `fs.openAsBlob` cuando existe, y leer el fichero entero cuando no.\n *\n * La primera llegó en Node 20.4 y este paquete admite Node 20 entero, así que hace falta la\n * segunda — con el aviso de que en un Node viejo un vídeo de 200 MB pasa por memoria.\n */\nasync function openFileAsBlob(path: string, type: string): Promise<Blob> {\n const fs = await import(\"node:fs\");\n const openAsBlob = (fs as unknown as { openAsBlob?: (p: string, o?: { type?: string }) => Promise<Blob> })\n .openAsBlob;\n\n if (typeof openAsBlob === \"function\") {\n return openAsBlob(path, { type });\n }\n const { readFile } = await import(\"node:fs/promises\");\n return new Blob([await readFile(path)], { type });\n}\n","/**\n * La biblioteca de ficheros de una organización: lo que se adjunta a una publicación.\n *\n * TRES AVISOS QUE AHORRAN UNA TARDE:\n *\n * 1. **`public_path` caduca.** Es una URL firmada, no un enlace permanente: se mantiene idéntica\n * dentro de la misma hora —cachearla ese rato es correcto— y después deja de servir.\n * Guardarla en tu base de datos es el error clásico; a los tres días están todas rotas.\n * 2. **El tipo lo decide el `content-type` que mandes**, no el contenido ni la extensión. La\n * librería lo deduce del nombre; si el nombre no lleva extensión, pásalo (§ `core/files.ts`).\n * 3. **Los topes son del servidor**: 5 MB por imagen y 200 MB por vídeo, más la cuota de espacio\n * de la organización. Los tres se comprueban contra los bytes que llegan de verdad, así que un\n * fichero grande falla a mitad de subida con un 802, un 803 o un 804 — no antes de empezar.\n */\nimport { Resource, requireId } from \"./base.js\";\nimport type { RequestOptions, SuccessResponse } from \"./base.js\";\nimport { buildUploadForm } from \"../core/files.js\";\nimport type { FileInput } from \"../core/files.js\";\nimport type { PageOptions } from \"../core/pagination.js\";\nimport { iteratePages } from \"../core/pagination.js\";\nimport type { Paginated, Upload } from \"../types.js\";\n\n/** Un fichero de una integración que se quiere traer a la biblioteca. */\nexport interface ImportFileInput {\n /** Identificador del fichero en el proveedor (el id del fichero en Drive). */\n external_id: string;\n /** Nombre que enseñó el selector. Se usa para el nombre visible y para decir cuál falló. */\n name?: string | undefined;\n /** Tipo que declaró el selector. Sirve para rechazar pronto; manda el tipo real del cuerpo. */\n mime_type?: string | undefined;\n}\n\n/** Lo que NO entró en una importación, fichero a fichero. */\nexport interface ImportError {\n external_id?: string;\n name?: string;\n code: number;\n message: string;\n data?: Record<string, unknown>;\n}\n\n/**\n * El resultado de una importación, que es PARCIAL a propósito: `uploads` con lo que entró y\n * `errors` con lo que no, para poder decir cuál de los seis ficheros elegidos falló y por qué.\n */\nexport interface ImportResult {\n uploads: Upload[];\n errors: ImportError[];\n}\n\n/** Los ajustes de portada de un vídeo. Lo único que un upload deja cambiar. */\nexport interface UploadUpdate {\n /**\n * Identificador de OTRO upload, que tiene que ser una imagen, para usarlo de portada.\n * Reemplazar una portada borra la anterior.\n */\n cover_image?: string | undefined;\n /**\n * Momento del vídeo, en milisegundos, que se usa de fotograma de portada.\n *\n * CUIDADO: **se escribe siempre**, así que omitirlo borra el valor guardado. Si sólo quieres\n * cambiar `cover_image`, manda también el `cover_offset` que ya tenía.\n */\n cover_offset?: number | undefined;\n}\n\nexport class UploadsResource extends Resource {\n /**\n * Sube un fichero. Admite una ruta en disco, un `Buffer` o un `Blob`.\n *\n * La ruta es la buena para lo grande: es la única forma que no pasa el fichero por memoria.\n *\n * ```ts\n * await pv.uploads.create(orgId, { file: \"./hogaza.jpg\" });\n * await pv.uploads.create(orgId, { file: bytes, filename: \"hogaza.jpg\" });\n * ```\n */\n async create(idOrganization: string, input: FileInput, options: RequestOptions = {}): Promise<Upload> {\n const form = await buildUploadForm(input);\n return this.postOne<Upload>(\n `/organizations/${requireId(idOrganization, \"idOrganization\")}/uploads`,\n \"upload\",\n form,\n options,\n );\n }\n\n /**\n * Los ficheros de la biblioteca.\n *\n * No salen aquí los recortes que la plataforma se hace para sí misma (`is_temporal`) ni las\n * portadas de vídeo, que son otro upload y viajan dentro del suyo.\n */\n async list(\n idOrganization: string,\n options: PageOptions & RequestOptions = {},\n ): Promise<Paginated<Upload>> {\n return this.getList<Upload>(\n `/organizations/${requireId(idOrganization, \"idOrganization\")}/uploads`,\n \"uploads\",\n { offset: options.offset, limit: options.limit },\n options,\n );\n }\n\n /** Los ficheros de la biblioteca, encadenando páginas. */\n iterate(idOrganization: string, options: PageOptions & RequestOptions = {}): AsyncGenerator<Upload> {\n return iteratePages<Upload>((page) => this.list(idOrganization, { ...options, ...page }), options);\n }\n\n /** Un fichero. Pídelo de nuevo cuando necesites un `public_path` vigente. */\n async get(idOrganization: string, idUpload: string, options: RequestOptions = {}): Promise<Upload> {\n return this.getOne<Upload>(this.path(idOrganization, idUpload), \"upload\", undefined, options);\n }\n\n /** Cambia la portada de un vídeo. Ojo con `cover_offset`: se escribe siempre (ver arriba). */\n async update(\n idOrganization: string,\n idUpload: string,\n body: UploadUpdate,\n options: RequestOptions = {},\n ): Promise<Upload> {\n return this.putOne<Upload>(this.path(idOrganization, idUpload), \"upload\", body, options);\n }\n\n /**\n * Borra un fichero.\n *\n * Con `force` se borra aunque una publicación siga apuntándolo; sin él, un fichero en uso se\n * conserva y sólo se saca de la biblioteca.\n */\n async remove(\n idOrganization: string,\n idUpload: string,\n options: { force?: boolean | undefined } & RequestOptions = {},\n ): Promise<void> {\n await this.httpDelete<SuccessResponse>(\n this.path(idOrganization, idUpload),\n options.force ? { forceDelete: true } : undefined,\n options,\n );\n }\n\n /**\n * Trae a la biblioteca ficheros elegidos en una integración (el selector de Drive).\n *\n * La respuesta es PARCIAL a propósito: mira `errors` aunque `uploads` traiga algo — de seis\n * ficheros pueden entrar cuatro. Un `2204` significa que el proveedor no da los bytes: un\n * documento nativo de Google no tiene fichero que descargar.\n */\n async import(\n idOrganization: string,\n idIntegration: string,\n files: readonly ImportFileInput[],\n options: RequestOptions = {},\n ): Promise<ImportResult> {\n return this.httpPost<ImportResult>(\n `/organizations/${requireId(idOrganization, \"idOrganization\")}/uploads/import`,\n { id_integration: requireId(idIntegration, \"idIntegration\"), files },\n options,\n );\n }\n\n private path(idOrganization: string, idUpload: string): string {\n return `/organizations/${requireId(idOrganization, \"idOrganization\")}/uploads/${requireId(idUpload, \"idUpload\")}`;\n }\n}\n","/**\n * `PlanVortex`: el objeto que un integrador construye una vez y usa para todo.\n *\n * De la fase 4 tiene el núcleo —transporte, autenticación y errores— y de la 6 el camino de\n * publicar: `pv.catalog`, `pv.clients`, `pv.organizations`, `pv.accounts`, `pv.uploads` y\n * `pv.publications`. Los demás recursos llegan en la fase 7 colgando de este mismo objeto y usando\n * su {@link PlanVortex.request}.\n */\nimport { ClientCredentialsAuth, StaticTokenAuth } from \"./core/auth.js\";\nimport type { AuthProvider } from \"./core/auth.js\";\nimport { PlanVortexConfigError, isTokenError } from \"./core/errors.js\";\nimport { HttpClient } from \"./core/http.js\";\nimport type { FetchLike, HttpHooks, HttpRequest, HttpResponse, RetryConfig } from \"./core/http.js\";\nimport { AccountsResource } from \"./resources/accounts.js\";\nimport { CatalogResource } from \"./resources/catalog.js\";\nimport { ClientsResource } from \"./resources/clients.js\";\nimport { OrganizationsResource } from \"./resources/organizations.js\";\nimport { PublicationsResource } from \"./resources/publications.js\";\nimport { UploadsResource } from \"./resources/uploads.js\";\nimport { PLANVORTEX_API_URL, VERSION } from \"./version.js\";\n\nexport interface PlanVortexOptions {\n /** El identificador de la app de cliente. Por defecto, `process.env.PLANVORTEX_CLIENT_ID`. */\n clientId?: string | undefined;\n /** El secreto de la app. Por defecto, `process.env.PLANVORTEX_CLIENT_SECRET`. */\n clientSecret?: string | undefined;\n /**\n * Un token ya emitido, en vez de credenciales: el `temporal_connect_token` con el que una\n * persona conecta su cuenta social. No se refresca solo (§ trampa 2 del roadmap).\n */\n accessToken?: string | undefined;\n /** Por defecto `https://api.planvortex.com/v1.0.0`. Sin barra final. */\n baseUrl?: string | undefined;\n /** Timeout por petición. 120 s por defecto: publicar un vídeo es lento. */\n timeoutMs?: number | undefined;\n retry?: Partial<RetryConfig> | undefined;\n /** `onRequest` / `onResponse` / `onRetry`, para enchufar el logger de casa. */\n hooks?: HttpHooks | undefined;\n /** `fetch` alternativo: un proxy, un mock, una implementación instrumentada. */\n fetch?: FetchLike | undefined;\n /** `scope` opcional del `client_credentials`. Casi nadie lo necesita. */\n scope?: string | undefined;\n /**\n * Deja construir el cliente en un navegador. **No lo pongas.** El `client_credentials` exige el\n * `client_secret`, y un secreto en un bundle de front es la cuenta entera regalada\n * (§ trampa 9). Para el navegador existe el token temporal de conexión.\n */\n dangerouslyAllowBrowser?: boolean | undefined;\n}\n\n/** El `User-Agent` de cada petición: nuestra versión y la de Node, que es lo que se busca en un log. */\nfunction buildUserAgent(): string {\n const runtime =\n typeof process !== \"undefined\" && process.versions?.node ? ` node/${process.versions.node}` : \"\";\n return `planvortex-node/${VERSION}${runtime}`;\n}\n\nfunction readEnv(name: string): string | undefined {\n return typeof process !== \"undefined\" ? process.env?.[name] : undefined;\n}\n\n/**\n * Un navegador de verdad, no un test con `jsdom` a medias: `window` **y** `window.document`.\n */\nfunction looksLikeBrowser(): boolean {\n const maybeWindow = (globalThis as { window?: { document?: unknown } }).window;\n return maybeWindow !== undefined && maybeWindow.document !== undefined;\n}\n\nexport class PlanVortex {\n /** Sin barra final. Útil para componer una URL a mano cuando haga falta. */\n readonly baseUrl: string;\n\n /** Metadatos estáticos de las redes: qué hay, qué sabe hacer cada una y sus límites. Cacheado. */\n readonly catalog: CatalogResource;\n /** Clientes: el plan contratado y sus organizaciones raíz. */\n readonly clients: ClientsResource;\n /** Organizaciones: la ficha, las hijas, y el cupo que tienen y gastan. */\n readonly organizations: OrganizationsResource;\n /** Cuentas sociales conectadas. Conectar una es otra cosa: hace falta una persona (§ fase 9). */\n readonly accounts: AccountsResource;\n /** La biblioteca de ficheros de una organización. */\n readonly uploads: UploadsResource;\n /** Publicaciones: crear, programar, reintentar y medir. */\n readonly publications: PublicationsResource;\n\n private readonly http: HttpClient;\n private readonly auth: AuthProvider;\n private readonly options: PlanVortexOptions;\n\n constructor(options: PlanVortexOptions = {}) {\n if (looksLikeBrowser() && options.dangerouslyAllowBrowser !== true) {\n throw new PlanVortexConfigError(\n \"planvortex es un paquete de servidor: el client_secret no puede vivir en un \" +\n \"navegador. Para conectar una cuenta desde el front usa el temporal_connect_token.\",\n );\n }\n\n this.options = options;\n this.baseUrl = (options.baseUrl ?? readEnv(\"PLANVORTEX_BASE_URL\") ?? PLANVORTEX_API_URL).replace(\n /\\/+$/,\n \"\",\n );\n\n this.http = new HttpClient({\n baseUrl: this.baseUrl,\n ...(options.timeoutMs === undefined ? {} : { timeoutMs: options.timeoutMs }),\n ...(options.retry === undefined ? {} : { retry: options.retry }),\n ...(options.hooks === undefined ? {} : { hooks: options.hooks }),\n ...(options.fetch === undefined ? {} : { fetch: options.fetch }),\n headers: { \"user-agent\": buildUserAgent() },\n });\n\n const clientId = options.clientId ?? readEnv(\"PLANVORTEX_CLIENT_ID\");\n const clientSecret = options.clientSecret ?? readEnv(\"PLANVORTEX_CLIENT_SECRET\");\n\n if (options.accessToken) {\n this.auth = new StaticTokenAuth(options.accessToken);\n } else if (clientId && clientSecret) {\n this.auth = new ClientCredentialsAuth(this.http, {\n clientId,\n clientSecret,\n scope: options.scope,\n });\n } else {\n throw new PlanVortexConfigError(\n \"Faltan credenciales: pasa clientId y clientSecret (o PLANVORTEX_CLIENT_ID y \" +\n \"PLANVORTEX_CLIENT_SECRET en el entorno), o un accessToken.\",\n );\n }\n\n //Los recursos reciben `this` y usan su `request`, así que comparten token, reintentos y\n //hooks. Se construyen aquí y no bajo demanda para que `pv.publications` sea siempre el\n //mismo objeto: la caché del catálogo depende de ello.\n this.catalog = new CatalogResource(this);\n this.clients = new ClientsResource(this);\n this.organizations = new OrganizationsResource(this);\n this.accounts = new AccountsResource(this);\n this.uploads = new UploadsResource(this);\n this.publications = new PublicationsResource(this);\n }\n\n /**\n * Una petición autenticada. Es lo que usarán los recursos de las fases 6 y 7; un integrador no\n * debería necesitarla, pero está expuesta para no dejar a nadie tirado ante un endpoint que la\n * librería aún no cubra.\n *\n * Reintenta **una sola vez** ante los códigos de token (501 y 522), que llegan dentro de un 400.\n * Un token puede morir antes de su `expires_in` —un despliegue de Keycloak, la app revocada— y\n * ese caso se arregla pidiendo otro; si el segundo también falla, el error sale.\n */\n async request<T>(request: HttpRequest): Promise<HttpResponse<T>> {\n try {\n return await this.send<T>(request);\n } catch (error) {\n if (!isTokenError(error)) {\n throw error;\n }\n this.auth.invalidate();\n return this.send<T>(request);\n }\n }\n\n /**\n * El mismo cliente, con la misma forma, autenticado con un token temporal de conexión.\n *\n * Es la pieza del flujo de conexión de cuentas (§ trampa 2): una app **no** puede conectar una\n * cuenta de Instagram —eso es un OAuth con una persona delante—, así que emite un token\n * temporal, se lo pasa a su usuario y con él se piden los `connect_links`. El token va atado a\n * una sola organización: usarlo contra otra devuelve el error 1101.\n */\n asTemporalToken(token: string): PlanVortex {\n return new PlanVortex({\n ...this.options,\n clientId: undefined,\n clientSecret: undefined,\n accessToken: token,\n baseUrl: this.baseUrl,\n });\n }\n\n private async send<T>(request: HttpRequest): Promise<HttpResponse<T>> {\n const token = await this.auth.getToken();\n return this.http.request<T>({\n ...request,\n headers: { ...request.headers, authorization: `Bearer ${token}` },\n });\n }\n}\n","/**\n * Los tipos PUBLICOS del paquete: los nombres con los que se habla de la API.\n *\n * Debajo de cada uno esta `src/generated/openapi.d.ts`, que sale del OpenAPI publico y no se toca\n * a mano. Este fichero es la capa fina que hay encima y hace tres cosas que un generador no puede:\n *\n * 1. **Pone nombres legibles.** En lo generado un esquema se llama `PublicationsPublication`,\n * porque los 16 documentos del spec se unen en uno y el `Plan` de un cliente no es el `Plan`\n * de una organizacion. Aqui se llama `Publication`.\n * 2. **Abre las enumeraciones que crecen** (§ trampa 8 del roadmap). `ALLOWED_RRSS` va por diez\n * redes y sube varias veces al ano. Si `social_network` fuera una union cerrada, el dia que\n * entre la undecima **dejaria de compilar el codigo de todos los integradores** hasta que\n * actualizasen el paquete, y lo unico que habria pasado es que la API devuelve un valor mas.\n * Con `T | (string & {})` se autocompletan las conocidas y una nueva sigue compilando.\n * 3. **Avisa de lo que el tipo no puede decir por si solo**, como que `public_path` caduca.\n *\n * NOTA SOBRE LOS CAMPOS OPCIONALES: un `?` aqui significa que el spec no declara ese campo\n * `required`. La fase 6 audito esquema a esquema los del camino de publicar —catalogo, clientes,\n * organizaciones, cuentas, ficheros y publicaciones— contra `src/domain/**` del servidor y declaro\n * lo que siempre viaja, asi que en esos ya no sobra ni un `?`. En los demas todavia sobran: se\n * arreglan en el spec —en PlanVortexHome—, nunca aqui, porque si este fichero declarase\n * obligatorio algo que el spec da por opcional habria dos verdades y solo una estaria publicada.\n */\nimport type { components, operations } from \"./generated/openapi.js\";\n\n/** Escotilla de salida: los tipos generados en crudo, por si hace falta uno que no este aqui. */\nexport type {\n components as OpenApiComponents,\n operations as OpenApiOperations,\n paths as OpenApiPaths,\n webhooks as OpenApiWebhooks,\n} from \"./generated/openapi.js\";\n\ntype Schemas = components[\"schemas\"];\ntype Operations = operations;\n\n/**\n * Una enumeracion ABIERTA: autocompleta los valores conocidos y admite uno nuevo sin romper.\n *\n * El `(string & {})` no es un truco de estilo, es lo unico que consigue las dos cosas a la vez:\n * `T | string` se colapsa a `string` y se pierde el autocompletado, y `T` a secas rompe la\n * compilacion en cuanto la API devuelve un valor que este paquete todavia no conoce.\n */\nexport type OpenEnum<T extends string> = T | (string & {});\n\ntype OptionalKeys<T> = { [K in keyof T]-?: Record<string, never> extends Pick<T, K> ? K : never }[keyof T];\ntype RequiredKeys<T> = Exclude<keyof T, OptionalKeys<T>>;\n\n/**\n * Sustituye el tipo de unos campos CONSERVANDO si el spec los declara obligatorios u opcionales.\n *\n * La version anterior los dejaba opcionales siempre, que era lo correcto mientras el spec no\n * declaraba un solo `required`. Ahora que los declara, hacerlo asi borraria justo el trabajo de la\n * auditoria: `Publication.social_network` volveria a ser un `string | undefined` que obliga a\n * comprobarlo aunque la API lo mande siempre.\n */\ntype Override<T, R extends Partial<Record<keyof T, unknown>>> = Omit<T, keyof R> & {\n [K in Extract<keyof R, OptionalKeys<T>>]?: R[K];\n} & {\n [K in Extract<keyof R, RequiredKeys<T>>]: R[K];\n};\n\n/**\n * Lo que devuelve cualquier `list()` del paquete: la pagina y el total.\n *\n * La API envuelve cada lista con el nombre de su recurso —`{publications, total}`,\n * `{accounts, total}`, `{comments, total}`— y en dos sitios lo envuelve de otra manera. La\n * libreria desenvuelve y entrega siempre la misma forma (§ trampa 6): el sobre es un detalle del\n * transporte. Lo que NO se traduce son los campos del recurso: `_id` sigue siendo `_id`.\n */\nexport interface Paginated<T> {\n data: T[];\n total: number;\n}\n\n// ---------------------------------------------------------------------------------------------\n// Enumeraciones abiertas\n// ---------------------------------------------------------------------------------------------\n\n/**\n * Una red social soportada. **La lista crece**: no rechaces un valor que no reconozcas.\n *\n * Y no todas hacen lo mismo: `whatsapp` es mensajeria sin muro y `google_business` es una ficha de\n * negocio que recibe resenas, asi que ninguna de las dos publica. Quien manda es\n * `GET /social_capabilities`.\n */\nexport type SocialNetwork = OpenEnum<Schemas[\"SocialNetwork\"]>;\n\n/** Una red que tiene comentarios. Tambien crece. */\nexport type CommentNetwork = OpenEnum<Schemas[\"CommentsCommentNetworkName\"]>;\n\n/**\n * El estado de una publicacion.\n *\n * `draft` no se envia nunca; `ready` esta programada; `publishing` esta en manos de la red en este\n * momento; `sended` salio; `withErrors` fallo y trae el motivo en `publication_errors`.\n */\nexport type PublicationState = OpenEnum<Schemas[\"PublicationsPublication\"][\"state\"]>;\n\n/** Donde se publica dentro de la red: perfil, pagina, grupo, reel o story. */\nexport type PublicationType = OpenEnum<Schemas[\"PublicationsPublication\"][\"publication_type\"]>;\n\n/** `image` o `video`. Abierto porque el catalogo de formatos se ha ampliado antes (HEIC). */\nexport type FileType = OpenEnum<Schemas[\"Upload\"][\"file_type\"]>;\n\n/** La extension real del fichero ya guardado. Un HEIC entra pero se convierte a JPEG al subirlo. */\nexport type FileFormat = OpenEnum<Schemas[\"Upload\"][\"file_format\"]>;\n\n/**\n * Sobre que se divide el engagement de una publicacion.\n *\n * No todas las redes dan alcance, asi que se cae en cascada: `reach`, si no `impressions`, si no\n * `followers` (que es lo unico que hay en Bluesky y en Discord). **Dos filas con base distinta no\n * son comparables**: si las pones en la misma tabla, di cual es.\n */\nexport type EngagementBase = OpenEnum<\n NonNullable<Schemas[\"PublicationsPublicationStatsPoint\"][\"engagement_base\"]>\n>;\n\n// ---------------------------------------------------------------------------------------------\n// Catalogo\n// ---------------------------------------------------------------------------------------------\n\n/**\n * Los limites por red: caracteres, imagenes, duracion de video, tamano de fichero.\n *\n * Los publica el servidor, que es quien los valida. Bluesky lleva **dos** cuentas distintas del\n * mismo texto —300 grafemas en `characters` y 3.000 bytes en `max_post_bytes`— porque `.length`\n * miente en las dos direcciones. Un `0` en `max_post_bytes`, `comment_characters` o\n * `title_characters` significa \"esta red no mide eso\", no \"cero\".\n */\nexport type SocialLimits = Schemas[\"CatalogSocialLimits\"];\n\n/** Un numero por red, con TODAS las redes presentes. Lo obliga el conformance del servidor. */\nexport type SocialLimitsMap = Schemas[\"CatalogSocialLimitsMap\"];\n\n/** Los recortes que acepta una red, como numero y como se escribe. Indices paralelos. */\nexport type AspectRatios = Schemas[\"CatalogAspectRatios\"];\n\n/**\n * Los recortes de cada red, indexados por red **y por tipo de publicacion**: hay entradas como\n * `facebook_reels` que no son una red, sino una red y un formato.\n */\nexport type AspectRatiosByNetwork = Record<string, AspectRatios>;\n\n/** Los topes de una publicacion que no dependen de la red. Hoy, cuantos reintentos manuales admite. */\nexport interface PublicationLimits {\n max_retries: number;\n}\n\n/** Que sabe hacer una red: publicar, mensajes, productos, webhooks, menu persistente, comentarios. */\nexport type SocialCapabilities = Schemas[\"CommentsSocialCapabilities\"];\n\n/**\n * Que se puede hacer con los comentarios de una red, una a una.\n *\n * No basta con saber que la red tiene comentarios: Instagram, X y Bluesky no dejan borrar el de\n * otro, LinkedIn no tiene \"ocultar\" y Google Business solo deja borrar **nuestra propia**\n * respuesta. Se pide en `GET /social_comment_actions`, y es lo que decide que botones se pintan.\n */\nexport type CommentActions = Schemas[\"CommentsCommentActions\"];\n\n// ---------------------------------------------------------------------------------------------\n// Cliente, organizacion y plan\n// ---------------------------------------------------------------------------------------------\n\n/**\n * Los recursos que reparte un plan. En un cliente es lo contratado; en una organizacion, la\n * porcion que se le asigno.\n *\n * OJO CON LA SUMA: lo asignado a las organizaciones de un cliente nunca puede pasar de lo que el\n * cliente tiene contratado — pedir mas devuelve un 1400-1408.\n */\nexport type PlanData = Schemas[\"PlanData\"];\n\n/**\n * La SUSCRIPCION de un cliente, que no es lo mismo que los recursos que da: los numeros estan en\n * `plan_data`. Leer `plan_identifier` para saber los limites es el error clasico — un plan\n * `custom` los lleva propios.\n */\nexport type ClientPlan = Schemas[\"ClientsPlan\"];\n\n/** Un cliente: quien contrata el plan y a quien cuelgan las organizaciones. */\nexport type Client = Schemas[\"ClientsClient\"];\n\n/**\n * Una organizacion: el contenedor de cuentas, publicaciones y ficheros.\n *\n * `actual_plan` es lo ASIGNADO, y **falta cuando no se le asigno nada** — entonces comparte el del\n * primer padre que tenga uno, o el resto sin repartir del cliente. Para los numeros que de verdad\n * aplican, `pv.organizations.limits(id)`.\n */\nexport type Organization = Schemas[\"Organization\"];\n\n/** El contexto de marca que la IA usa al escribir para esta organizacion. */\nexport type AiContext = Schemas[\"AiContext\"];\n\n/** Las credenciales de la aplicacion propia de una organizacion (BYOB). Los secretos nunca salen. */\nexport type SocialCredentials = Schemas[\"SocialCredentials\"];\n\n// ---------------------------------------------------------------------------------------------\n// Recursos\n// ---------------------------------------------------------------------------------------------\n\n/**\n * Una cuenta social conectada a una organizacion.\n *\n * En Discord una cuenta es un **canal**, no un perfil: publicar en dos canales del mismo servidor\n * gasta dos cuentas del plan. `error_code` distinto de 0 significa que la conexion se rompio —\n * token caducado, permisos retirados— y hay que reconectarla.\n */\nexport type Account = Override<\n Schemas[\"Account\"],\n {\n social_network: SocialNetwork;\n }\n>;\n\n/**\n * La serie de una metrica de cuenta, ya agrupada.\n *\n * `group` dice que cubre cada fila: un rango de 31 dias o menos se agrupa por dia, hasta 720 por\n * mes, y de ahi en adelante por ano. Los `name` son los nombres CRUDOS de la red — los mismos que\n * devuelve `metricList()`—, no el vocabulario comun.\n */\nexport type AccountMetrics = Schemas[\"AccountsMetricModel\"];\n\n/** Una fila de {@link AccountMetrics}. */\nexport type AccountMetricRow = AccountMetrics[\"stats\"][number];\n\n/** El menu fijo del chat, en el formato de Meta. Solo lo tienen las redes con mensajeria. */\nexport type PersistentMenu = Schemas[\"AccountsPersistentMenu\"];\n\n// ---------------------------------------------------------------------------------------------\n// Conexion de cuentas\n// ---------------------------------------------------------------------------------------------\n\n/**\n * El token temporal con el que UNA PERSONA conecta una cuenta social, y la URL a la que mandarla.\n *\n * Las dos cosas valen: `url` es el camino alojado —se redirige al usuario y PlanVortex se encarga\n * de todo—, y `token` es el mismo credencial suelto, para pasarselo a `pv.asTemporalToken(token)`\n * y conducir el flujo desde el front propio. Caduca a la hora (`expires_at`) y sirve para UNA\n * organizacion.\n */\nexport type ConnectToken =\n Operations[\"createTemporalConnectToken\"][\"responses\"][200][\"content\"][\"application/json\"];\n\n/**\n * El enlace de autorizacion de UNA red. Se manda al usuario ahi y la red lo devuelve al panel de\n * PlanVortex, que es quien completa la conexion.\n */\nexport type ConnectLink = Schemas[\"AccountsSocialLinksList\"][\"links\"][number];\n\n/**\n * Lo que dejo una autorizacion: las cuentas que se pueden dar de alta.\n *\n * **Todavia no cuentan para el plan**: hasta que no se llama a `accounts.enable()` no ocupan plaza\n * ni publican. Una sola autorizacion puede dejar varias (un usuario de Facebook con cuatro paginas\n * son cuatro), y por eso hay un paso de eleccion en medio.\n *\n * No lleva `errorCode`: el endpoint contesta 200 con el error dentro y la libreria lo convierte en\n * la excepcion que le toca (§ `AccountsResource.connect`).\n */\nexport interface ConnectResult {\n /** Las cuentas conectadas, aun sin habilitar. Vacio si la autorizacion no dejo nada utilizable. */\n accounts: Account[];\n /** A donde mandar al usuario despues, si el token temporal llevaba `redirect_uri`. */\n redirect_uri?: string;\n}\n\n/** Lo que devuelve habilitar una cuenta. Un fallo no llega aqui: se lanza. */\nexport interface EnableResult {\n /** A donde mandar al usuario despues, si el token temporal llevaba `redirect_uri`. */\n redirect_uri?: string;\n}\n\n/**\n * Un fichero de la biblioteca de la organizacion.\n *\n * CUIDADO CON `public_path`: es una URL **firmada y temporal**, no un enlace permanente. Se\n * mantiene identica dentro de la misma hora —asi que cachearla ese rato es correcto— y despues\n * deja de servir. Guardarla en tu base de datos es el error clasico: a los tres dias todas las\n * miniaturas estan rotas. Vuelve a pedir el upload cuando la necesites.\n */\nexport type Upload = Override<\n Schemas[\"Upload\"],\n {\n file_type: FileType;\n file_format: FileFormat;\n }\n>;\n\n/** Ancho, alto, duracion y tamano de un fichero, mas en que redes cabe **por su recorte**. */\nexport type FileProperties = Schemas[\"FileProperties\"];\n\n/**\n * Una publicacion: programada, enviada o fallida.\n *\n * DOS COSAS QUE SORPRENDEN, las dos comprobadas contra el servidor en la fase 6:\n *\n * - **`files` viene POBLADO**: son `Upload` enteros, no identificadores. Identificadores es lo\n * que se MANDA ({@link PublicationInput}).\n * - **`id_account` cambia de forma segun la operacion**: las de una sola publicacion (crear,\n * leer, reintentar) lo devuelven resuelto y el listado y la actualizacion lo devuelven como\n * identificador. Usa {@link accountId} o {@link account} en vez de asumir una de las dos.\n *\n * Si `state` es `withErrors`, el motivo esta en `publication_errors` —que es un ARRAY— y su `code`\n * es un codigo del catalogo de PlanVortex, nunca un status HTTP.\n */\nexport type Publication = Override<\n Schemas[\"PublicationsPublication\"],\n {\n social_network: SocialNetwork;\n state: PublicationState;\n publication_type: PublicationType;\n engagement_base: EngagementBase;\n files: Upload[];\n //Se reescribe con NUESTRO `Account`, el de la enumeracion abierta. Con el generado, una\n //cuenta de una red que este paquete todavia no conozca no encajaria aqui.\n id_account: string | Account;\n }\n>;\n\n/**\n * Un motivo por el que una publicacion fallo, tal y como viaja en `publication_errors`.\n *\n * NO confundir con `PublicationError`, que es la EXCEPCION que lanza la libreria cuando la\n * peticion falla. Esto es un dato dentro de una respuesta correcta: la publicacion se guardo, y\n * aqui pone por que no salio.\n */\nexport type PublicationErrorDetail = Publication[\"publication_errors\"][number];\n\n/**\n * Lo que se manda para crear o actualizar una publicacion. Aqui `files` SI son identificadores.\n *\n * `publish_date` admite un `Date` ademas de la cadena ISO: la libreria lo convierte. Sin eso, el\n * primer olvido es siempre el `.toISOString()`.\n */\nexport type PublicationInput = Override<\n Schemas[\"PublicationsPublicationInput\"],\n {\n social_network: SocialNetwork;\n state: PublicationState;\n publication_type: PublicationType;\n publish_date: string | Date;\n }\n>;\n\n/** El desglose crudo de metricas que da la red, que no es el mismo en dos redes cualesquiera. */\nexport type PublicationStats = Schemas[\"PublicationsPublicationStats\"];\n\n/** Las metricas comparables entre redes: las que se pueden sumar en una grafica. */\nexport type PublicationMetrics = Schemas[\"PublicationsNormalizedMetrics\"];\n\n/** La serie historica de una publicacion, mas su ultima medicion. */\nexport type PublicationStatsHistory = Override<\n Schemas[\"PublicationsPublicationStatsHistory\"],\n {\n social_network: SocialNetwork;\n engagement_base: EngagementBase;\n }\n>;\n\n/** Una medicion de la serie: el ACUMULADO a esa fecha, no el incremento del dia. */\nexport type PublicationStatsPoint = Override<\n Schemas[\"PublicationsPublicationStatsPoint\"],\n {\n engagement_base: EngagementBase;\n }\n>;\n\n/**\n * Un comentario, o una resena de Google Business.\n *\n * `id_publication` **falta** cuando el comentario cuelga de una ficha y no de una publicacion\n * nuestra, que es justo el caso de Google Business: ahi `publication_external_id` es la ficha\n * (`locations/{id}`). `rating` solo llega donde se valora con estrellas, y una resena puede venir\n * sin texto ninguno. De lo nuestro solo son `read` y `replied`: todo lo demas lo manda la red.\n */\nexport type Comment = Override<\n Schemas[\"CommentsComment\"],\n {\n social_network: CommentNetwork;\n }\n>;\n\n/** Quien escribio un comentario. `is_own` distingue el nuestro del de un tercero. */\nexport type CommentAuthor = Schemas[\"CommentsCommentAuthor\"];\n\n/** Una conversacion de mensajeria con un contacto. */\nexport type Conversation = Schemas[\"MessagesConversation\"];\n\n/**\n * Un mensaje intercambiado con un contacto.\n *\n * OJO CON LOS TRES CAMPOS DE REFERENCIA. `contact_id`, `from_contact_id` y\n * `message_options.files` llegan **poblados** —el objeto entero, no el identificador— en el\n * listado de mensajes y en el webhook que PlanVortex manda a tu app, y como identificador a secas\n * en el resto. Es la misma asimetria que `Publication.id_account`, y se tapa igual: con\n * {@link messageContact}, {@link messageContactId} y {@link messageFiles}, para no escribir el\n * `typeof` en cada sitio.\n */\nexport type Message = Override<Schemas[\"Message\"], { message_options: MessageOptions }>;\n\n/**\n * Lo que un mensaje lleva ademas del texto: ficheros, plantilla, payload, tarjetas de Meta.\n *\n * `files` se reescribe para que los adjuntos poblados sean el {@link Upload} PUBLICO —el de los\n * formatos abiertos— y no el generado: si no, un fichero de un mensaje y uno de una publicacion\n * serian dos tipos distintos para el mismo objeto del servidor.\n */\nexport type MessageOptions = Override<\n Schemas[\"MessageOptions\"],\n { files: (string | Upload)[] }\n>;\n\n/** Que clase de mensaje es. `simple_message` y `file_message` valen en todas las redes. */\nexport type MessageType = Schemas[\"MessageType\"];\n\n/** Un contacto de la agenda de la organizacion. */\nexport type Contact = Schemas[\"Contact\"];\n\n/** El mismo contacto, en un canal. Es una red social o `email`. */\nexport type SocialIdentifier = Schemas[\"SocialIdentifier\"];\n\n/** Donde se puede alcanzar a un contacto: cualquier red con mensajeria, o `email`. */\nexport type ContactChannel = OpenEnum<Schemas[\"ContactChannel\"]>;\n\n/** Un producto del catalogo de una cuenta (solo en las redes que venden). */\nexport type Product = Schemas[\"ProductsProduct\"];\n\n/** Una conexion con una herramienta de la que se traen materiales: Google Drive, un RSS. */\nexport type Integration = Schemas[\"IntegrationsIntegration\"];\n\n/** Un plan de publicaciones generado con IA. */\nexport type AiPlan = Schemas[\"AiPlansAiPlan\"];\n\n/** Una app de cliente: las credenciales con las que una integracion se autentica. */\nexport type ClientApp = Schemas[\"AppsClientApp\"];\n\n/**\n * Los cambios que se entregan a la url de webhook de una app NO se tipan aqui.\n *\n * El spec los describe planos —un solo objeto con casi todo opcional, porque eso es lo que se ve\n * en el cable— y lo que el integrador necesita es una union discriminada por `field` con\n * predicados que la estrechen. Eso vive en `planvortex/webhooks`, junto a la verificacion de la\n * firma, que es donde se van a buscar. Los tipos se reexportan desde el punto de entrada\n * principal, asi que `import type { WebhookChange } from \"planvortex\"` sigue valiendo.\n */\n\n// ---------------------------------------------------------------------------------------------\n// Ayudas para los campos que la API devuelve de dos formas\n// ---------------------------------------------------------------------------------------------\n\n/**\n * El identificador de la cuenta de una publicacion, venga poblada o no.\n *\n * `id_account` llega resuelto en las operaciones de una sola publicacion y como cadena en el\n * listado (§ el aviso de {@link Publication}). Esto lo tapa sin obligar a escribir el `typeof` en\n * cada sitio.\n */\nexport function accountId(publication: Pick<Publication, \"id_account\">): string {\n const value = publication.id_account;\n return typeof value === \"string\" ? value : value._id;\n}\n\n/**\n * La cuenta de una publicacion cuando viene poblada, y `undefined` cuando la API solo mando el\n * identificador. Contrapartida de {@link accountId}.\n */\nexport function account(publication: Pick<Publication, \"id_account\">): Account | undefined {\n const value = publication.id_account;\n return typeof value === \"string\" ? undefined : value;\n}\n\n/**\n * Hacia donde va un mensaje.\n *\n * No es un campo: se deduce de CUAL de los dos contactos trae. `from_contact_id` es el contacto\n * escribiendonos y `contact_id` nosotros escribiendole, y el servidor garantiza que viene\n * exactamente uno (`ERROR_CODE_1503` si no viene ninguno, `1504` si vienen los dos). El\n * `\"unknown\"` esta para el mensaje que se construye a mano y todavia no ha pasado por ahi.\n */\nexport function messageDirection(\n message: Pick<Message, \"contact_id\" | \"from_contact_id\">,\n): \"incoming\" | \"outgoing\" | \"unknown\" {\n if (message.from_contact_id) {\n return \"incoming\";\n }\n return message.contact_id ? \"outgoing\" : \"unknown\";\n}\n\n/**\n * El identificador del contacto de un mensaje, venga poblado o no y escriba quien escriba.\n *\n * Para saber la direccion esta {@link messageDirection}; aqui lo que interesa es CON QUIEN se\n * habla, que es la misma persona en los dos sentidos.\n */\nexport function messageContactId(\n message: Pick<Message, \"contact_id\" | \"from_contact_id\">,\n): string | undefined {\n const value = message.from_contact_id ?? message.contact_id;\n if (value === undefined) {\n return undefined;\n }\n return typeof value === \"string\" ? value : value._id;\n}\n\n/**\n * El contacto de un mensaje cuando viene poblado —el listado y el webhook—, y `undefined` cuando\n * la API solo mando el identificador. Contrapartida de {@link messageContactId}.\n */\nexport function messageContact(\n message: Pick<Message, \"contact_id\" | \"from_contact_id\">,\n): Contact | undefined {\n const value = message.from_contact_id ?? message.contact_id;\n return value === undefined || typeof value === \"string\" ? undefined : value;\n}\n\n/**\n * Los ficheros adjuntos de un mensaje que vienen poblados. Los que llegaron como identificador\n * NO salen aqui: para esos esta {@link messageFileIds}.\n */\nexport function messageFiles(message: Pick<Message, \"message_options\">): Upload[] {\n const files = message.message_options?.files ?? [];\n return files.filter((file): file is Upload => typeof file !== \"string\");\n}\n\n/** Los identificadores de los ficheros adjuntos de un mensaje, vengan poblados o no. */\nexport function messageFileIds(message: Pick<Message, \"message_options\">): string[] {\n const files = message.message_options?.files ?? [];\n return files.map((file) => (typeof file === \"string\" ? file : file._id));\n}\n"]}