drizzle-multitenant 1.0.7 → 1.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/config.ts","../src/types.ts","../src/pool.ts","../src/manager.ts","../src/context.ts","../src/migrator/table-format.ts","../src/migrator/migrator.ts","../src/cross-schema/cross-schema.ts"],"names":["Pool","join"],"mappings":";;;;;;;;;;AAgCO,SAAS,aAGd,MAAA,EAAoF;AACpF,EAAA,cAAA,CAAe,MAAM,CAAA;AACrB,EAAA,OAAO,MAAA;AACT;AAKA,SAAS,eAGP,MAAA,EAAoD;AAEpD,EAAA,IAAI,CAAC,MAAA,CAAO,UAAA,CAAW,GAAA,EAAK;AAC1B,IAAA,MAAM,IAAI,MAAM,kDAAkD,CAAA;AAAA,EACpE;AAGA,EAAA,IAAI,CAAC,MAAA,CAAO,SAAA,CAAU,QAAA,EAAU;AAC9B,IAAA,MAAM,IAAI,MAAM,sDAAsD,CAAA;AAAA,EACxE;AAEA,EAAA,IAAI,MAAA,CAAO,SAAA,CAAU,QAAA,KAAa,QAAA,EAAU;AAC1C,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,0CAAA,EAA6C,MAAA,CAAO,SAAA,CAAU,QAAQ,CAAA,6DAAA;AAAA,KACxE;AAAA,EACF;AAEA,EAAA,IAAI,CAAC,MAAA,CAAO,SAAA,CAAU,kBAAA,EAAoB;AACxC,IAAA,MAAM,IAAI,MAAM,gEAAgE,CAAA;AAAA,EAClF;AAEA,EAAA,IAAI,OAAO,MAAA,CAAO,SAAA,CAAU,kBAAA,KAAuB,UAAA,EAAY;AAC7D,IAAA,MAAM,IAAI,MAAM,uEAAuE,CAAA;AAAA,EACzF;AAGA,EAAA,IAAI,CAAC,MAAA,CAAO,OAAA,CAAQ,MAAA,EAAQ;AAC1B,IAAA,MAAM,IAAI,MAAM,kDAAkD,CAAA;AAAA,EACpE;AAGA,EAAA,IAAI,OAAO,SAAA,CAAU,QAAA,KAAa,UAAa,MAAA,CAAO,SAAA,CAAU,WAAW,CAAA,EAAG;AAC5E,IAAA,MAAM,IAAI,MAAM,6DAA6D,CAAA;AAAA,EAC/E;AAEA,EAAA,IAAI,OAAO,SAAA,CAAU,SAAA,KAAc,UAAa,MAAA,CAAO,SAAA,CAAU,YAAY,CAAA,EAAG;AAC9E,IAAA,MAAM,IAAI,MAAM,gEAAgE,CAAA;AAAA,EAClF;AACF;;;ACwDO,IAAM,cAAA,GAAiB;AAAA,EAC5B,QAAA,EAAU,EAAA;AAAA,EACV,SAAA,EAAW,KAAK,EAAA,GAAK,GAAA;AAAA;AAAA,EACrB,iBAAA,EAAmB,GAAA;AAAA;AAAA,EACnB,UAAA,EAAY;AAAA,IACV,GAAA,EAAK,EAAA;AAAA,IACL,iBAAA,EAAmB,GAAA;AAAA,IACnB,uBAAA,EAAyB;AAAA;AAE7B;;;ACvIO,IAAM,cAAN,MAGL;AAAA,EAQA,YAA6B,MAAA,EAA8C;AAA9C,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAC3B,IAAA,MAAM,QAAA,GAAW,MAAA,CAAO,SAAA,CAAU,QAAA,IAAY,cAAA,CAAS,QAAA;AAEvD,IAAA,IAAA,CAAK,KAAA,GAAQ,IAAI,QAAA,CAA2C;AAAA,MAC1D,GAAA,EAAK,QAAA;AAAA,MACL,OAAA,EAAS,CAAC,KAAA,EAAO,GAAA,KAAQ;AACvB,QAAA,IAAA,CAAK,gBAAA,CAAiB,OAAO,GAAG,CAAA;AAAA,MAClC,CAAA;AAAA,MACA,cAAA,EAAgB;AAAA,KACjB,CAAA;AAAA,EACH;AAAA,EAjBiB,KAAA;AAAA,EACA,gBAAA,uBAA4C,GAAA,EAAI;AAAA,EACzD,UAAA,GAA0B,IAAA;AAAA,EAC1B,QAAA,GAA2C,IAAA;AAAA,EAC3C,eAAA,GAAyD,IAAA;AAAA,EACzD,QAAA,GAAW,KAAA;AAAA;AAAA;AAAA;AAAA,EAiBnB,MAAM,QAAA,EAA2C;AAC/C,IAAA,IAAA,CAAK,iBAAA,EAAkB;AAEvB,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,MAAA,CAAO,SAAA,CAAU,mBAAmB,QAAQ,CAAA;AACpE,IAAA,IAAI,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,UAAU,CAAA;AAErC,IAAA,IAAI,CAAC,KAAA,EAAO;AACV,MAAA,KAAA,GAAQ,IAAA,CAAK,eAAA,CAAgB,QAAA,EAAU,UAAU,CAAA;AACjD,MAAA,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,UAAA,EAAY,KAAK,CAAA;AAChC,MAAA,IAAA,CAAK,gBAAA,CAAiB,GAAA,CAAI,UAAA,EAAY,QAAQ,CAAA;AAG9C,MAAA,KAAK,IAAA,CAAK,MAAA,CAAO,KAAA,EAAO,aAAA,GAAgB,QAAQ,CAAA;AAAA,IAClD;AAEA,IAAA,KAAA,CAAM,UAAA,GAAa,KAAK,GAAA,EAAI;AAC5B,IAAA,OAAO,KAAA,CAAM,EAAA;AAAA,EACf;AAAA;AAAA;AAAA;AAAA,EAKA,WAAA,GAAuC;AACrC,IAAA,IAAA,CAAK,iBAAA,EAAkB;AAEvB,IAAA,IAAI,CAAC,KAAK,QAAA,EAAU;AAClB,MAAA,IAAA,CAAK,UAAA,GAAa,IAAI,IAAA,CAAK;AAAA,QACzB,gBAAA,EAAkB,IAAA,CAAK,MAAA,CAAO,UAAA,CAAW,GAAA;AAAA,QACzC,GAAG,cAAA,CAAS,UAAA;AAAA,QACZ,GAAG,IAAA,CAAK,MAAA,CAAO,UAAA,CAAW;AAAA,OAC3B,CAAA;AAED,MAAA,IAAA,CAAK,UAAA,CAAW,EAAA,CAAG,OAAA,EAAS,CAAC,GAAA,KAAQ;AACnC,QAAA,KAAK,IAAA,CAAK,MAAA,CAAO,KAAA,EAAO,OAAA,GAAU,UAAU,GAAG,CAAA;AAAA,MACjD,CAAC,CAAA;AAED,MAAA,IAAA,CAAK,QAAA,GAAW,OAAA,CAAQ,IAAA,CAAK,UAAA,EAAY;AAAA,QACvC,MAAA,EAAQ,IAAA,CAAK,MAAA,CAAO,OAAA,CAAQ;AAAA,OAC7B,CAAA;AAAA,IACH;AAEA,IAAA,OAAO,IAAA,CAAK,QAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc,QAAA,EAA0B;AACtC,IAAA,OAAO,IAAA,CAAK,MAAA,CAAO,SAAA,CAAU,kBAAA,CAAmB,QAAQ,CAAA;AAAA,EAC1D;AAAA;AAAA;AAAA;AAAA,EAKA,QAAQ,QAAA,EAA2B;AACjC,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,MAAA,CAAO,SAAA,CAAU,mBAAmB,QAAQ,CAAA;AACpE,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,UAAU,CAAA;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA,EAKA,YAAA,GAAuB;AACrB,IAAA,OAAO,KAAK,KAAA,CAAM,IAAA;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA,EAKA,kBAAA,GAA+B;AAC7B,IAAA,OAAO,KAAA,CAAM,IAAA,CAAK,IAAA,CAAK,gBAAA,CAAiB,QAAQ,CAAA;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,UAAU,QAAA,EAAiC;AAC/C,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,MAAA,CAAO,SAAA,CAAU,mBAAmB,QAAQ,CAAA;AACpE,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,UAAU,CAAA;AAEvC,IAAA,IAAI,KAAA,EAAO;AACT,MAAA,IAAA,CAAK,KAAA,CAAM,OAAO,UAAU,CAAA;AAC5B,MAAA,IAAA,CAAK,gBAAA,CAAiB,OAAO,UAAU,CAAA;AACvC,MAAA,MAAM,IAAA,CAAK,SAAA,CAAU,KAAA,CAAM,IAAA,EAAM,QAAQ,CAAA;AAAA,IAC3C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,YAAA,GAAqB;AACnB,IAAA,IAAI,KAAK,eAAA,EAAiB;AAE1B,IAAA,MAAM,SAAA,GAAY,IAAA,CAAK,MAAA,CAAO,SAAA,CAAU,aAAa,cAAA,CAAS,SAAA;AAC9D,IAAA,MAAM,oBAAoB,cAAA,CAAS,iBAAA;AAEnC,IAAA,IAAA,CAAK,eAAA,GAAkB,YAAY,MAAM;AACvC,MAAA,KAAK,IAAA,CAAK,iBAAiB,SAAS,CAAA;AAAA,IACtC,GAAG,iBAAiB,CAAA;AAGpB,IAAA,IAAA,CAAK,gBAAgB,KAAA,EAAM;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA,EAKA,WAAA,GAAoB;AAClB,IAAA,IAAI,KAAK,eAAA,EAAiB;AACxB,MAAA,aAAA,CAAc,KAAK,eAAe,CAAA;AAClC,MAAA,IAAA,CAAK,eAAA,GAAkB,IAAA;AAAA,IACzB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAA,GAAyB;AAC7B,IAAA,IAAI,KAAK,QAAA,EAAU;AAEnB,IAAA,IAAA,CAAK,QAAA,GAAW,IAAA;AAChB,IAAA,IAAA,CAAK,WAAA,EAAY;AAGjB,IAAA,MAAM,gBAAiC,EAAC;AAExC,IAAA,KAAA,MAAW,CAAC,UAAA,EAAY,KAAK,KAAK,IAAA,CAAK,KAAA,CAAM,SAAQ,EAAG;AACtD,MAAA,MAAM,QAAA,GAAW,IAAA,CAAK,gBAAA,CAAiB,GAAA,CAAI,UAAU,CAAA;AACrD,MAAA,aAAA,CAAc,KAAK,IAAA,CAAK,SAAA,CAAU,MAAM,IAAA,EAAM,QAAA,IAAY,UAAU,CAAC,CAAA;AAAA,IACvE;AAEA,IAAA,IAAA,CAAK,MAAM,KAAA,EAAM;AACjB,IAAA,IAAA,CAAK,iBAAiB,KAAA,EAAM;AAG5B,IAAA,IAAI,KAAK,UAAA,EAAY;AACnB,MAAA,aAAA,CAAc,KAAK,IAAA,CAAK,SAAA,CAAU,IAAA,CAAK,UAAA,EAAY,QAAQ,CAAC,CAAA;AAC5D,MAAA,IAAA,CAAK,UAAA,GAAa,IAAA;AAClB,MAAA,IAAA,CAAK,QAAA,GAAW,IAAA;AAAA,IAClB;AAEA,IAAA,MAAM,OAAA,CAAQ,IAAI,aAAa,CAAA;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAA,CAAgB,UAAkB,UAAA,EAA8C;AACtF,IAAA,MAAM,IAAA,GAAO,IAAI,IAAA,CAAK;AAAA,MACpB,gBAAA,EAAkB,IAAA,CAAK,MAAA,CAAO,UAAA,CAAW,GAAA;AAAA,MACzC,GAAG,cAAA,CAAS,UAAA;AAAA,MACZ,GAAG,IAAA,CAAK,MAAA,CAAO,UAAA,CAAW,UAAA;AAAA,MAC1B,OAAA,EAAS,kBAAkB,UAAU,CAAA,OAAA;AAAA,KACtC,CAAA;AAED,IAAA,IAAA,CAAK,EAAA,CAAG,OAAA,EAAS,OAAO,GAAA,KAAQ;AAC9B,MAAA,KAAK,IAAA,CAAK,MAAA,CAAO,KAAA,EAAO,OAAA,GAAU,UAAU,GAAG,CAAA;AAC/C,MAAA,MAAM,IAAA,CAAK,UAAU,QAAQ,CAAA;AAAA,IAC/B,CAAC,CAAA;AAED,IAAA,MAAM,EAAA,GAAK,QAAQ,IAAA,EAAM;AAAA,MACvB,MAAA,EAAQ,IAAA,CAAK,MAAA,CAAO,OAAA,CAAQ;AAAA,KAC7B,CAAA;AAED,IAAA,OAAO;AAAA,MACL,EAAA;AAAA,MACA,IAAA;AAAA,MACA,UAAA,EAAY,KAAK,GAAA,EAAI;AAAA,MACrB;AAAA,KACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,gBAAA,CAAiB,OAAiC,UAAA,EAA0B;AAClF,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,gBAAA,CAAiB,GAAA,CAAI,UAAU,CAAA;AACrD,IAAA,IAAA,CAAK,gBAAA,CAAiB,OAAO,UAAU,CAAA;AAEvC,IAAA,KAAK,IAAA,CAAK,UAAU,KAAA,CAAM,IAAA,EAAM,YAAY,UAAU,CAAA,CAAE,KAAK,MAAM;AACjE,MAAA,IAAI,QAAA,EAAU;AACZ,QAAA,KAAK,IAAA,CAAK,MAAA,CAAO,KAAA,EAAO,aAAA,GAAgB,QAAQ,CAAA;AAAA,MAClD;AAAA,IACF,CAAC,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,SAAA,CAAU,IAAA,EAAY,UAAA,EAAmC;AACrE,IAAA,IAAI;AACF,MAAA,MAAM,KAAK,GAAA,EAAI;AAAA,IACjB,SAAS,KAAA,EAAO;AACd,MAAA,KAAK,IAAA,CAAK,MAAA,CAAO,KAAA,EAAO,OAAA,GAAU,YAAY,KAAc,CAAA;AAAA,IAC9D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,iBAAiB,SAAA,EAAkC;AAC/D,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,IAAA,MAAM,UAAoB,EAAC;AAE3B,IAAA,KAAA,MAAW,CAAC,UAAA,EAAY,KAAK,KAAK,IAAA,CAAK,KAAA,CAAM,SAAQ,EAAG;AACtD,MAAA,IAAI,GAAA,GAAM,KAAA,CAAM,UAAA,GAAa,SAAA,EAAW;AACtC,QAAA,OAAA,CAAQ,KAAK,UAAU,CAAA;AAAA,MACzB;AAAA,IACF;AAEA,IAAA,KAAA,MAAW,cAAc,OAAA,EAAS;AAChC,MAAA,MAAM,QAAA,GAAW,IAAA,CAAK,gBAAA,CAAiB,GAAA,CAAI,UAAU,CAAA;AACrD,MAAA,IAAI,QAAA,EAAU;AACZ,QAAA,MAAM,IAAA,CAAK,UAAU,QAAQ,CAAA;AAAA,MAC/B;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,iBAAA,GAA0B;AAChC,IAAA,IAAI,KAAK,QAAA,EAAU;AACjB,MAAA,MAAM,IAAI,MAAM,uDAAuD,CAAA;AAAA,IACzE;AAAA,EACF;AACF,CAAA;;;AC5OO,SAAS,oBAGd,MAAA,EAA2F;AAC3F,EAAA,MAAM,WAAA,GAAc,IAAI,WAAA,CAAY,MAAM,CAAA;AAG1C,EAAA,WAAA,CAAY,YAAA,EAAa;AAEzB,EAAA,OAAO;AAAA,IACL,MAAM,QAAA,EAA2C;AAC/C,MAAA,OAAO,WAAA,CAAY,MAAM,QAAQ,CAAA;AAAA,IACnC,CAAA;AAAA,IAEA,WAAA,GAAuC;AACrC,MAAA,OAAO,YAAY,WAAA,EAAY;AAAA,IACjC,CAAA;AAAA,IAEA,cAAc,QAAA,EAA0B;AACtC,MAAA,OAAO,WAAA,CAAY,cAAc,QAAQ,CAAA;AAAA,IAC3C,CAAA;AAAA,IAEA,QAAQ,QAAA,EAA2B;AACjC,MAAA,OAAO,WAAA,CAAY,QAAQ,QAAQ,CAAA;AAAA,IACrC,CAAA;AAAA,IAEA,YAAA,GAAuB;AACrB,MAAA,OAAO,YAAY,YAAA,EAAa;AAAA,IAClC,CAAA;AAAA,IAEA,kBAAA,GAA+B;AAC7B,MAAA,OAAO,YAAY,kBAAA,EAAmB;AAAA,IACxC,CAAA;AAAA,IAEA,MAAM,UAAU,QAAA,EAAiC;AAC/C,MAAA,MAAM,WAAA,CAAY,UAAU,QAAQ,CAAA;AAAA,IACtC,CAAA;AAAA,IAEA,MAAM,OAAA,GAAyB;AAC7B,MAAA,MAAM,YAAY,OAAA,EAAQ;AAAA,IAC5B;AAAA,GACF;AACF;ACmBO,SAAS,oBAKd,OAAA,EACsD;AACtD,EAAA,MAAM,OAAA,GAAU,IAAI,iBAAA,EAA8C;AAElE,EAAA,SAAS,eAAA,GAA0D;AACjE,IAAA,OAAO,QAAQ,QAAA,EAAS;AAAA,EAC1B;AAEA,EAAA,SAAS,SAAA,GAAwC;AAC/C,IAAA,MAAM,UAAU,eAAA,EAAgB;AAChC,IAAA,IAAI,CAAC,OAAA,EAAS;AACZ,MAAA,MAAM,IAAI,KAAA;AAAA,QACR;AAAA,OAEF;AAAA,IACF;AACA,IAAA,OAAO,OAAA;AAAA,EACT;AAEA,EAAA,SAAS,WAAA,GAAsB;AAC7B,IAAA,OAAO,WAAU,CAAE,QAAA;AAAA,EACrB;AAEA,EAAA,SAAS,WAAA,GAAuC;AAC9C,IAAA,MAAM,WAAW,WAAA,EAAY;AAC7B,IAAA,OAAO,OAAA,CAAQ,MAAM,QAAQ,CAAA;AAAA,EAC/B;AAEA,EAAA,SAAS,WAAA,GAAuC;AAC9C,IAAA,OAAO,QAAQ,WAAA,EAAY;AAAA,EAC7B;AAEA,EAAA,SAAS,iBAAA,GAA6B;AACpC,IAAA,OAAO,iBAAgB,KAAM,MAAA;AAAA,EAC/B;AAEA,EAAA,SAAS,aAAA,CACP,SACA,QAAA,EACgB;AAChB,IAAA,IAAI,CAAC,QAAQ,QAAA,EAAU;AACrB,MAAA,MAAM,IAAI,MAAM,uDAAuD,CAAA;AAAA,IACzE;AACA,IAAA,OAAO,OAAA,CAAQ,GAAA,CAAI,OAAA,EAAS,QAAQ,CAAA;AAAA,EACtC;AAEA,EAAA,OAAO;AAAA,IACL,aAAA;AAAA,IACA,SAAA;AAAA,IACA,eAAA;AAAA,IACA,WAAA;AAAA,IACA,WAAA;AAAA,IACA,WAAA;AAAA,IACA;AAAA,GACF;AACF;;;ACnFA,eAAsB,iBAAA,CACpB,IAAA,EACA,UAAA,EACA,SAAA,EACgC;AAEhC,EAAA,MAAM,WAAA,GAAc,MAAM,IAAA,CAAK,KAAA;AAAA,IAC7B,CAAA;AAAA;AAAA;AAAA,eAAA,CAAA;AAAA,IAIA,CAAC,YAAY,SAAS;AAAA,GACxB;AAEA,EAAA,IAAI,CAAC,WAAA,CAAY,IAAA,CAAK,CAAC,GAAG,MAAA,EAAQ;AAChC,IAAA,OAAO,IAAA;AAAA,EACT;AAGA,EAAA,MAAM,aAAA,GAAgB,MAAM,IAAA,CAAK,KAAA;AAAA,IAC/B,CAAA;AAAA;AAAA,gDAAA,CAAA;AAAA,IAGA,CAAC,YAAY,SAAS;AAAA,GACxB;AAEA,EAAA,MAAM,YAAY,IAAI,GAAA;AAAA,IACpB,aAAA,CAAc,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,KAAM,CAAC,CAAA,CAAE,WAAA,EAAa,CAAA,CAAE,SAAS,CAAC;AAAA,GAC5D;AAGA,EAAA,IAAI,SAAA,CAAU,GAAA,CAAI,MAAM,CAAA,EAAG;AAEzB,IAAA,OAAO;AAAA,MACL,MAAA,EAAQ,MAAA;AAAA,MACR,SAAA;AAAA,MACA,OAAA,EAAS;AAAA,QACP,UAAA,EAAY,MAAA;AAAA,QACZ,SAAA,EAAW,SAAA,CAAU,GAAA,CAAI,YAAY,IAAI,YAAA,GAAe,YAAA;AAAA,QACxD,aAAA,EAAe;AAAA;AACjB,KACF;AAAA,EACF;AAEA,EAAA,IAAI,SAAA,CAAU,GAAA,CAAI,MAAM,CAAA,EAAG;AACzB,IAAA,MAAM,aAAA,GAAgB,SAAA,CAAU,GAAA,CAAI,YAAY,CAAA;AAGhD,IAAA,IAAI,kBAAkB,QAAA,EAAU;AAC9B,MAAA,OAAO;AAAA,QACL,MAAA,EAAQ,aAAA;AAAA,QACR,SAAA;AAAA,QACA,OAAA,EAAS;AAAA,UACP,UAAA,EAAY,MAAA;AAAA,UACZ,SAAA,EAAW,YAAA;AAAA,UACX,aAAA,EAAe;AAAA;AACjB,OACF;AAAA,IACF;AAGA,IAAA,OAAO;AAAA,MACL,MAAA,EAAQ,MAAA;AAAA,MACR,SAAA;AAAA,MACA,OAAA,EAAS;AAAA,QACP,UAAA,EAAY,MAAA;AAAA,QACZ,SAAA,EAAW,YAAA;AAAA,QACX,aAAA,EAAe;AAAA;AACjB,KACF;AAAA,EACF;AAGA,EAAA,OAAO,IAAA;AACT;AAKO,SAAS,eAAA,CACd,MAAA,EACA,SAAA,GAAoB,sBAAA,EACJ;AAChB,EAAA,QAAQ,MAAA;AAAQ,IACd,KAAK,MAAA;AACH,MAAA,OAAO;AAAA,QACL,MAAA,EAAQ,MAAA;AAAA,QACR,SAAA;AAAA,QACA,OAAA,EAAS;AAAA,UACP,UAAA,EAAY,MAAA;AAAA,UACZ,SAAA,EAAW,YAAA;AAAA,UACX,aAAA,EAAe;AAAA;AACjB,OACF;AAAA,IACF,KAAK,MAAA;AACH,MAAA,OAAO;AAAA,QACL,MAAA,EAAQ,MAAA;AAAA,QACR,SAAA;AAAA,QACA,OAAA,EAAS;AAAA,UACP,UAAA,EAAY,MAAA;AAAA,UACZ,SAAA,EAAW,YAAA;AAAA,UACX,aAAA,EAAe;AAAA;AACjB,OACF;AAAA,IACF,KAAK,aAAA;AACH,MAAA,OAAO;AAAA,QACL,MAAA,EAAQ,aAAA;AAAA,QACR,SAAA;AAAA,QACA,OAAA,EAAS;AAAA,UACP,UAAA,EAAY,MAAA;AAAA,UACZ,SAAA,EAAW,YAAA;AAAA,UACX,aAAA,EAAe;AAAA;AACjB,OACF;AAAA;AAEN;;;ACrKA,IAAM,wBAAA,GAA2B,sBAAA;AAK1B,IAAM,WAAN,MAGL;AAAA,EAGA,WAAA,CACmB,cACA,cAAA,EACjB;AAFiB,IAAA,IAAA,CAAA,YAAA,GAAA,YAAA;AACA,IAAA,IAAA,CAAA,cAAA,GAAA,cAAA;AAEjB,IAAA,IAAA,CAAK,eAAA,GAAkB,eAAe,eAAA,IAAmB,wBAAA;AAAA,EAC3D;AAAA,EAPiB,eAAA;AAAA;AAAA;AAAA;AAAA,EAYjB,MAAM,UAAA,CAAW,OAAA,GAA0B,EAAC,EAA8B;AACxE,IAAA,MAAM;AAAA,MACJ,WAAA,GAAc,EAAA;AAAA,MACd,UAAA;AAAA,MACA,OAAA;AAAA,MACA,MAAA,GAAS;AAAA,KACX,GAAI,OAAA;AAEJ,IAAA,MAAM,SAAA,GAAY,MAAM,IAAA,CAAK,cAAA,CAAe,eAAA,EAAgB;AAC5D,IAAA,MAAM,UAAA,GAAa,MAAM,IAAA,CAAK,cAAA,EAAe;AAE7C,IAAA,MAAM,UAAmC,EAAC;AAC1C,IAAA,IAAI,OAAA,GAAU,KAAA;AAGd,IAAA,KAAA,IAAS,CAAA,GAAI,GAAG,CAAA,GAAI,SAAA,CAAU,UAAU,CAAC,OAAA,EAAS,KAAK,WAAA,EAAa;AAClE,MAAA,MAAM,KAAA,GAAQ,SAAA,CAAU,KAAA,CAAM,CAAA,EAAG,IAAI,WAAW,CAAA;AAEhD,MAAA,MAAM,YAAA,GAAe,MAAM,OAAA,CAAQ,GAAA;AAAA,QACjC,KAAA,CAAM,GAAA,CAAI,OAAO,QAAA,KAAa;AAC5B,UAAA,IAAI,OAAA,EAAS;AACX,YAAA,OAAO,IAAA,CAAK,oBAAoB,QAAQ,CAAA;AAAA,UAC1C;AAEA,UAAA,IAAI;AACF,YAAA,UAAA,GAAa,UAAU,UAAU,CAAA;AACjC,YAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,aAAA,CAAc,UAAU,UAAA,EAAY,EAAE,MAAA,EAAQ,UAAA,EAAY,CAAA;AACpF,YAAA,UAAA,GAAa,QAAA,EAAU,MAAA,CAAO,OAAA,GAAU,WAAA,GAAc,QAAQ,CAAA;AAC9D,YAAA,OAAO,MAAA;AAAA,UACT,SAAS,KAAA,EAAO;AACd,YAAA,UAAA,GAAa,UAAU,QAAQ,CAAA;AAC/B,YAAA,MAAM,MAAA,GAAS,OAAA,GAAU,QAAA,EAAU,KAAc,CAAA;AACjD,YAAA,IAAI,WAAW,OAAA,EAAS;AACtB,cAAA,OAAA,GAAU,IAAA;AAAA,YACZ;AACA,YAAA,OAAO,IAAA,CAAK,iBAAA,CAAkB,QAAA,EAAU,KAAc,CAAA;AAAA,UACxD;AAAA,QACF,CAAC;AAAA,OACH;AAEA,MAAA,OAAA,CAAQ,IAAA,CAAK,GAAG,YAAY,CAAA;AAAA,IAC9B;AAGA,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,MAAM,SAAA,GAAY,SAAA,CAAU,KAAA,CAAM,OAAA,CAAQ,MAAM,CAAA;AAChD,MAAA,KAAA,MAAW,YAAY,SAAA,EAAW;AAChC,QAAA,OAAA,CAAQ,IAAA,CAAK,IAAA,CAAK,mBAAA,CAAoB,QAAQ,CAAC,CAAA;AAAA,MACjD;AAAA,IACF;AAEA,IAAA,OAAO,IAAA,CAAK,iBAAiB,OAAO,CAAA;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAAA,CACJ,QAAA,EACA,UAAA,EACA,OAAA,GAA2E,EAAC,EAC5C;AAChC,IAAA,MAAM,SAAA,GAAY,KAAK,GAAA,EAAI;AAC3B,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,YAAA,CAAa,SAAA,CAAU,mBAAmB,QAAQ,CAAA;AAC1E,IAAA,MAAM,oBAA8B,EAAC;AAErC,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,UAAA,CAAW,UAAU,CAAA;AAE7C,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,CAAK,cAAA,CAAe,KAAA,EAAO,YAAA,GAAe,QAAQ,CAAA;AAGxD,MAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,iBAAA,CAAkB,MAAM,UAAU,CAAA;AAG5D,MAAA,MAAM,IAAA,CAAK,qBAAA,CAAsB,IAAA,EAAM,UAAA,EAAY,MAAM,CAAA;AAGzD,MAAA,MAAM,aAAA,GAAgB,UAAA,IAAc,MAAM,IAAA,CAAK,cAAA,EAAe;AAG9D,MAAA,MAAM,UAAU,MAAM,IAAA,CAAK,oBAAA,CAAqB,IAAA,EAAM,YAAY,MAAM,CAAA;AACxE,MAAA,MAAM,UAAA,GAAa,IAAI,GAAA,CAAI,OAAA,CAAQ,IAAI,CAAC,CAAA,KAAM,CAAA,CAAE,UAAU,CAAC,CAAA;AAG3D,MAAA,MAAM,UAAU,aAAA,CAAc,MAAA;AAAA,QAC5B,CAAC,CAAA,KAAM,CAAC,KAAK,kBAAA,CAAmB,CAAA,EAAG,YAAY,MAAM;AAAA,OACvD;AAEA,MAAA,IAAI,QAAQ,MAAA,EAAQ;AAClB,QAAA,OAAO;AAAA,UACL,QAAA;AAAA,UACA,UAAA;AAAA,UACA,OAAA,EAAS,IAAA;AAAA,UACT,mBAAmB,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,KAAM,EAAE,IAAI,CAAA;AAAA,UAC5C,UAAA,EAAY,IAAA,CAAK,GAAA,EAAI,GAAI,SAAA;AAAA,UACzB,QAAQ,MAAA,CAAO;AAAA,SACjB;AAAA,MACF;AAGA,MAAA,KAAA,MAAW,aAAa,OAAA,EAAS;AAC/B,QAAA,MAAM,cAAA,GAAiB,KAAK,GAAA,EAAI;AAChC,QAAA,OAAA,CAAQ,UAAA,GAAa,QAAA,EAAU,WAAA,EAAa,SAAA,CAAU,IAAI,CAAA;AAE1D,QAAA,MAAM,KAAK,cAAA,CAAe,KAAA,EAAO,eAAA,GAAkB,QAAA,EAAU,UAAU,IAAI,CAAA;AAC3E,QAAA,MAAM,IAAA,CAAK,cAAA,CAAe,IAAA,EAAM,UAAA,EAAY,WAAW,MAAM,CAAA;AAC7D,QAAA,MAAM,IAAA,CAAK,eAAe,KAAA,EAAO,cAAA;AAAA,UAC/B,QAAA;AAAA,UACA,SAAA,CAAU,IAAA;AAAA,UACV,IAAA,CAAK,KAAI,GAAI;AAAA,SACf;AAEA,QAAA,iBAAA,CAAkB,IAAA,CAAK,UAAU,IAAI,CAAA;AAAA,MACvC;AAEA,MAAA,MAAM,MAAA,GAAgC;AAAA,QACpC,QAAA;AAAA,QACA,UAAA;AAAA,QACA,OAAA,EAAS,IAAA;AAAA,QACT,iBAAA;AAAA,QACA,UAAA,EAAY,IAAA,CAAK,GAAA,EAAI,GAAI,SAAA;AAAA,QACzB,QAAQ,MAAA,CAAO;AAAA,OACjB;AAEA,MAAA,MAAM,IAAA,CAAK,cAAA,CAAe,KAAA,EAAO,WAAA,GAAc,UAAU,MAAM,CAAA;AAE/D,MAAA,OAAO,MAAA;AAAA,IACT,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,MAAA,GAAgC;AAAA,QACpC,QAAA;AAAA,QACA,UAAA;AAAA,QACA,OAAA,EAAS,KAAA;AAAA,QACT,iBAAA;AAAA,QACA,OAAQ,KAAA,CAAgB,OAAA;AAAA,QACxB,UAAA,EAAY,IAAA,CAAK,GAAA,EAAI,GAAI;AAAA,OAC3B;AAEA,MAAA,MAAM,IAAA,CAAK,cAAA,CAAe,KAAA,EAAO,WAAA,GAAc,UAAU,MAAM,CAAA;AAE/D,MAAA,OAAO,MAAA;AAAA,IACT,CAAA,SAAE;AACA,MAAA,MAAM,KAAK,GAAA,EAAI;AAAA,IACjB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAAA,CAAe,SAAA,EAAqB,OAAA,GAA0B,EAAC,EAA8B;AACjG,IAAA,MAAM,UAAA,GAAa,MAAM,IAAA,CAAK,cAAA,EAAe;AAC7C,IAAA,MAAM,UAAmC,EAAC;AAE1C,IAAA,MAAM,EAAE,WAAA,GAAc,EAAA,EAAI,UAAA,EAAY,SAAQ,GAAI,OAAA;AAElD,IAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,SAAA,CAAU,MAAA,EAAQ,KAAK,WAAA,EAAa;AACtD,MAAA,MAAM,KAAA,GAAQ,SAAA,CAAU,KAAA,CAAM,CAAA,EAAG,IAAI,WAAW,CAAA;AAEhD,MAAA,MAAM,YAAA,GAAe,MAAM,OAAA,CAAQ,GAAA;AAAA,QACjC,KAAA,CAAM,GAAA,CAAI,OAAO,QAAA,KAAa;AAC5B,UAAA,IAAI;AACF,YAAA,UAAA,GAAa,UAAU,UAAU,CAAA;AACjC,YAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,aAAA,CAAc,QAAA,EAAU,UAAA,EAAY,EAAE,MAAA,EAAQ,OAAA,CAAQ,MAAA,IAAU,KAAA,EAAO,UAAA,EAAY,CAAA;AAC7G,YAAA,UAAA,GAAa,QAAA,EAAU,MAAA,CAAO,OAAA,GAAU,WAAA,GAAc,QAAQ,CAAA;AAC9D,YAAA,OAAO,MAAA;AAAA,UACT,SAAS,KAAA,EAAO;AACd,YAAA,UAAA,GAAa,UAAU,QAAQ,CAAA;AAC/B,YAAA,OAAA,GAAU,UAAU,KAAc,CAAA;AAClC,YAAA,OAAO,IAAA,CAAK,iBAAA,CAAkB,QAAA,EAAU,KAAc,CAAA;AAAA,UACxD;AAAA,QACF,CAAC;AAAA,OACH;AAEA,MAAA,OAAA,CAAQ,IAAA,CAAK,GAAG,YAAY,CAAA;AAAA,IAC9B;AAEA,IAAA,OAAO,IAAA,CAAK,iBAAiB,OAAO,CAAA;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAAA,GAA8C;AAClD,IAAA,MAAM,SAAA,GAAY,MAAM,IAAA,CAAK,cAAA,CAAe,eAAA,EAAgB;AAC5D,IAAA,MAAM,UAAA,GAAa,MAAM,IAAA,CAAK,cAAA,EAAe;AAC7C,IAAA,MAAM,WAAoC,EAAC;AAE3C,IAAA,KAAA,MAAW,YAAY,SAAA,EAAW;AAChC,MAAA,QAAA,CAAS,KAAK,MAAM,IAAA,CAAK,eAAA,CAAgB,QAAA,EAAU,UAAU,CAAC,CAAA;AAAA,IAChE;AAEA,IAAA,OAAO,QAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,eAAA,CAAgB,QAAA,EAAkB,UAAA,EAA8D;AACpG,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,YAAA,CAAa,SAAA,CAAU,mBAAmB,QAAQ,CAAA;AAC1E,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,UAAA,CAAW,UAAU,CAAA;AAE7C,IAAA,IAAI;AACF,MAAA,MAAM,aAAA,GAAgB,UAAA,IAAc,MAAM,IAAA,CAAK,cAAA,EAAe;AAG9D,MAAA,MAAM,WAAA,GAAc,MAAM,IAAA,CAAK,qBAAA,CAAsB,MAAM,UAAU,CAAA;AACrE,MAAA,IAAI,CAAC,WAAA,EAAa;AAChB,QAAA,OAAO;AAAA,UACL,QAAA;AAAA,UACA,UAAA;AAAA,UACA,YAAA,EAAc,CAAA;AAAA,UACd,cAAc,aAAA,CAAc,MAAA;AAAA,UAC5B,mBAAmB,aAAA,CAAc,GAAA,CAAI,CAAC,CAAA,KAAM,EAAE,IAAI,CAAA;AAAA,UAClD,MAAA,EAAQ,aAAA,CAAc,MAAA,GAAS,CAAA,GAAI,QAAA,GAAW,IAAA;AAAA,UAC9C,MAAA,EAAQ;AAAA;AAAA,SACV;AAAA,MACF;AAGA,MAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,iBAAA,CAAkB,MAAM,UAAU,CAAA;AAE5D,MAAA,MAAM,UAAU,MAAM,IAAA,CAAK,oBAAA,CAAqB,IAAA,EAAM,YAAY,MAAM,CAAA;AACxE,MAAA,MAAM,UAAA,GAAa,IAAI,GAAA,CAAI,OAAA,CAAQ,IAAI,CAAC,CAAA,KAAM,CAAA,CAAE,UAAU,CAAC,CAAA;AAG3D,MAAA,MAAM,UAAU,aAAA,CAAc,MAAA;AAAA,QAC5B,CAAC,CAAA,KAAM,CAAC,KAAK,kBAAA,CAAmB,CAAA,EAAG,YAAY,MAAM;AAAA,OACvD;AAEA,MAAA,OAAO;AAAA,QACL,QAAA;AAAA,QACA,UAAA;AAAA,QACA,cAAc,OAAA,CAAQ,MAAA;AAAA,QACtB,cAAc,OAAA,CAAQ,MAAA;AAAA,QACtB,mBAAmB,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,KAAM,EAAE,IAAI,CAAA;AAAA,QAC5C,MAAA,EAAQ,OAAA,CAAQ,MAAA,GAAS,CAAA,GAAI,QAAA,GAAW,IAAA;AAAA,QACxC,QAAQ,MAAA,CAAO;AAAA,OACjB;AAAA,IACF,SAAS,KAAA,EAAO;AACd,MAAA,OAAO;AAAA,QACL,QAAA;AAAA,QACA,UAAA;AAAA,QACA,YAAA,EAAc,CAAA;AAAA,QACd,YAAA,EAAc,CAAA;AAAA,QACd,mBAAmB,EAAC;AAAA,QACpB,MAAA,EAAQ,OAAA;AAAA,QACR,OAAQ,KAAA,CAAgB,OAAA;AAAA,QACxB,MAAA,EAAQ;AAAA,OACV;AAAA,IACF,CAAA,SAAE;AACA,MAAA,MAAM,KAAK,GAAA,EAAI;AAAA,IACjB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YAAA,CAAa,QAAA,EAAkB,OAAA,GAA+B,EAAC,EAAkB;AACrF,IAAA,MAAM,EAAE,OAAA,GAAU,IAAA,EAAK,GAAI,OAAA;AAC3B,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,YAAA,CAAa,SAAA,CAAU,mBAAmB,QAAQ,CAAA;AAE1E,IAAA,MAAM,IAAA,GAAO,IAAIA,IAAAA,CAAK;AAAA,MACpB,gBAAA,EAAkB,IAAA,CAAK,YAAA,CAAa,UAAA,CAAW,GAAA;AAAA,MAC/C,GAAG,IAAA,CAAK,YAAA,CAAa,UAAA,CAAW;AAAA,KACjC,CAAA;AAED,IAAA,IAAI;AAEF,MAAA,MAAM,IAAA,CAAK,KAAA,CAAM,CAAA,6BAAA,EAAgC,UAAU,CAAA,CAAA,CAAG,CAAA;AAE9D,MAAA,IAAI,OAAA,EAAS;AAEX,QAAA,MAAM,IAAA,CAAK,cAAc,QAAQ,CAAA;AAAA,MACnC;AAAA,IACF,CAAA,SAAE;AACA,MAAA,MAAM,KAAK,GAAA,EAAI;AAAA,IACjB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,UAAA,CAAW,QAAA,EAAkB,OAAA,GAA6B,EAAC,EAAkB;AACjF,IAAA,MAAM,EAAE,OAAA,GAAU,IAAA,EAAK,GAAI,OAAA;AAC3B,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,YAAA,CAAa,SAAA,CAAU,mBAAmB,QAAQ,CAAA;AAE1E,IAAA,MAAM,IAAA,GAAO,IAAIA,IAAAA,CAAK;AAAA,MACpB,gBAAA,EAAkB,IAAA,CAAK,YAAA,CAAa,UAAA,CAAW,GAAA;AAAA,MAC/C,GAAG,IAAA,CAAK,YAAA,CAAa,UAAA,CAAW;AAAA,KACjC,CAAA;AAED,IAAA,IAAI;AACF,MAAA,MAAM,UAAA,GAAa,UAAU,SAAA,GAAY,UAAA;AACzC,MAAA,MAAM,KAAK,KAAA,CAAM,CAAA,uBAAA,EAA0B,UAAU,CAAA,EAAA,EAAK,UAAU,CAAA,CAAE,CAAA;AAAA,IACxE,CAAA,SAAE;AACA,MAAA,MAAM,KAAK,GAAA,EAAI;AAAA,IACjB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAAa,QAAA,EAAoC;AACrD,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,YAAA,CAAa,SAAA,CAAU,mBAAmB,QAAQ,CAAA;AAE1E,IAAA,MAAM,IAAA,GAAO,IAAIA,IAAAA,CAAK;AAAA,MACpB,gBAAA,EAAkB,IAAA,CAAK,YAAA,CAAa,UAAA,CAAW,GAAA;AAAA,MAC/C,GAAG,IAAA,CAAK,YAAA,CAAa,UAAA,CAAW;AAAA,KACjC,CAAA;AAED,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,KAAA;AAAA,QACxB,CAAA,gEAAA,CAAA;AAAA,QACA,CAAC,UAAU;AAAA,OACb;AACA,MAAA,OAAO,MAAA,CAAO,QAAA,KAAa,IAAA,IAAQ,MAAA,CAAO,QAAA,GAAW,CAAA;AAAA,IACvD,CAAA,SAAE;AACA,MAAA,MAAM,KAAK,GAAA,EAAI;AAAA,IACjB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,cAAA,GAA2C;AACvD,IAAA,MAAM,KAAA,GAAQ,MAAM,OAAA,CAAQ,IAAA,CAAK,eAAe,gBAAgB,CAAA;AAEhE,IAAA,MAAM,aAA8B,EAAC;AAErC,IAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,MAAA,IAAI,CAAC,IAAA,CAAK,QAAA,CAAS,MAAM,CAAA,EAAG;AAE5B,MAAA,MAAM,QAAA,GAAW,IAAA,CAAK,IAAA,CAAK,cAAA,CAAe,kBAAkB,IAAI,CAAA;AAChE,MAAA,MAAM,OAAA,GAAU,MAAM,QAAA,CAAS,QAAA,EAAU,OAAO,CAAA;AAGhD,MAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,SAAS,CAAA;AAClC,MAAA,MAAM,SAAA,GAAY,QAAQ,CAAC,CAAA,GAAI,SAAS,KAAA,CAAM,CAAC,CAAA,EAAG,EAAE,CAAA,GAAI,CAAA;AAGxD,MAAA,MAAM,IAAA,GAAO,WAAW,QAAQ,CAAA,CAAE,OAAO,OAAO,CAAA,CAAE,OAAO,KAAK,CAAA;AAE9D,MAAA,UAAA,CAAW,IAAA,CAAK;AAAA,QACd,IAAA,EAAM,QAAA,CAAS,IAAA,EAAM,MAAM,CAAA;AAAA,QAC3B,IAAA,EAAM,QAAA;AAAA,QACN,GAAA,EAAK,OAAA;AAAA,QACL,SAAA;AAAA,QACA;AAAA,OACD,CAAA;AAAA,IACH;AAGA,IAAA,OAAO,UAAA,CAAW,KAAK,CAAC,CAAA,EAAG,MAAM,CAAA,CAAE,SAAA,GAAY,EAAE,SAAS,CAAA;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,WAAW,UAAA,EAAmC;AAC1D,IAAA,OAAO,IAAIA,IAAAA,CAAK;AAAA,MACd,gBAAA,EAAkB,IAAA,CAAK,YAAA,CAAa,UAAA,CAAW,GAAA;AAAA,MAC/C,GAAG,IAAA,CAAK,YAAA,CAAa,UAAA,CAAW,UAAA;AAAA,MAChC,OAAA,EAAS,mBAAmB,UAAU,CAAA,QAAA;AAAA,KACvC,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,qBAAA,CACZ,IAAA,EACA,UAAA,EACA,MAAA,EACe;AACf,IAAA,MAAM,EAAE,UAAA,EAAY,SAAA,EAAW,aAAA,KAAkB,MAAA,CAAO,OAAA;AAGxD,IAAA,MAAM,aAAA,GAAgB,UAAA,KAAe,MAAA,GACjC,mCAAA,GACA,oBAAA;AAEJ,IAAA,MAAM,eAAe,aAAA,KAAkB,QAAA,GACnC,GAAG,SAAS,CAAA,gBAAA,CAAA,GACZ,GAAG,SAAS,CAAA,mDAAA,CAAA;AAEhB,IAAA,MAAM,KAAK,KAAA,CAAM;AAAA,kCAAA,EACe,UAAU,CAAA,GAAA,EAAM,MAAA,CAAO,SAAS,CAAA;AAAA;AAAA,QAAA,EAE1D,aAAa,CAAA;AAAA,QAAA,EACb,YAAY;AAAA;AAAA,IAAA,CAEjB,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,qBAAA,CAAsB,IAAA,EAAY,UAAA,EAAsC;AACpF,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,KAAA;AAAA,MACxB,CAAA;AAAA,kDAAA,CAAA;AAAA,MAEA,CAAC,UAAA,EAAY,IAAA,CAAK,eAAe;AAAA,KACnC;AACA,IAAA,OAAO,MAAA,CAAO,QAAA,KAAa,IAAA,IAAQ,MAAA,CAAO,QAAA,GAAW,CAAA;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,oBAAA,CACZ,IAAA,EACA,UAAA,EACA,MAAA,EAC6B;AAC7B,IAAA,MAAM,gBAAA,GAAmB,OAAO,OAAA,CAAQ,UAAA;AACxC,IAAA,MAAM,eAAA,GAAkB,OAAO,OAAA,CAAQ,SAAA;AAEvC,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,KAAA;AAAA,MACxB,CAAA,YAAA,EAAe,gBAAgB,CAAA,kBAAA,EAAqB,eAAe,CAAA;AAAA,aAAA,EAC1D,UAAU,CAAA,GAAA,EAAM,MAAA,CAAO,SAAS,CAAA;AAAA,kBAAA;AAAA,KAE3C;AAEA,IAAA,OAAO,MAAA,CAAO,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,KAAQ;AAE9B,MAAA,MAAM,SAAA,GAAY,MAAA,CAAO,OAAA,CAAQ,aAAA,KAAkB,WAC/C,IAAI,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,UAAU,CAAC,CAAA,GAC/B,IAAI,IAAA,CAAK,IAAI,UAAU,CAAA;AAE3B,MAAA,OAAO;AAAA,QACL,IAAI,GAAA,CAAI,EAAA;AAAA,QACR,YAAY,GAAA,CAAI,UAAA;AAAA;AAAA,QAEhB,GAAI,MAAA,CAAO,OAAA,CAAQ,UAAA,KAAe,MAAA,GAC9B,EAAE,IAAA,EAAM,GAAA,CAAI,UAAA,EAAW,GACvB,EAAE,IAAA,EAAM,IAAI,UAAA,EAAW;AAAA,QAC3B;AAAA,OACF;AAAA,IACF,CAAC,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKQ,kBAAA,CACN,SAAA,EACA,kBAAA,EACA,MAAA,EACS;AACT,IAAA,IAAI,MAAA,CAAO,OAAA,CAAQ,UAAA,KAAe,MAAA,EAAQ;AACxC,MAAA,OAAO,kBAAA,CAAmB,GAAA,CAAI,SAAA,CAAU,IAAI,CAAA;AAAA,IAC9C;AAIA,IAAA,OAAO,kBAAA,CAAmB,IAAI,SAAA,CAAU,IAAI,KAAK,kBAAA,CAAmB,GAAA,CAAI,UAAU,IAAI,CAAA;AAAA,EACxF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,iBAAA,CACZ,IAAA,EACA,UAAA,EACyB;AACzB,IAAA,MAAM,gBAAA,GAAmB,IAAA,CAAK,cAAA,CAAe,WAAA,IAAe,MAAA;AAG5D,IAAA,IAAI,qBAAqB,MAAA,EAAQ;AAC/B,MAAA,OAAO,eAAA,CAAgB,gBAAA,EAAkB,IAAA,CAAK,eAAe,CAAA;AAAA,IAC/D;AAGA,IAAA,MAAM,WAAW,MAAM,iBAAA,CAAkB,IAAA,EAAM,UAAA,EAAY,KAAK,eAAe,CAAA;AAE/E,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,OAAO,QAAA;AAAA,IACT;AAGA,IAAA,MAAM,aAAA,GAA6B,IAAA,CAAK,cAAA,CAAe,aAAA,IAAiB,MAAA;AACxE,IAAA,OAAO,eAAA,CAAgB,aAAA,EAAe,IAAA,CAAK,eAAe,CAAA;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,cAAA,CACZ,IAAA,EACA,UAAA,EACA,WACA,MAAA,EACe;AACf,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,OAAA,EAAQ;AAElC,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,CAAO,MAAM,OAAO,CAAA;AAG1B,MAAA,MAAM,MAAA,CAAO,KAAA,CAAM,SAAA,CAAU,GAAG,CAAA;AAGhC,MAAA,MAAM,EAAE,UAAA,EAAY,SAAA,EAAW,aAAA,KAAkB,MAAA,CAAO,OAAA;AACxD,MAAA,MAAM,eAAA,GAAkB,UAAA,KAAe,MAAA,GAAS,SAAA,CAAU,OAAO,SAAA,CAAU,IAAA;AAC3E,MAAA,MAAM,iBAAiB,aAAA,KAAkB,QAAA,GAAW,KAAK,GAAA,EAAI,uBAAQ,IAAA,EAAK;AAE1E,MAAA,MAAM,MAAA,CAAO,KAAA;AAAA,QACX,CAAA,aAAA,EAAgB,UAAU,CAAA,GAAA,EAAM,MAAA,CAAO,SAAS,CAAA,IAAA,EAAO,UAAU,OAAO,SAAS,CAAA,kBAAA,CAAA;AAAA,QACjF,CAAC,iBAAiB,cAAc;AAAA,OAClC;AAEA,MAAA,MAAM,MAAA,CAAO,MAAM,QAAQ,CAAA;AAAA,IAC7B,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,MAAA,CAAO,MAAM,UAAU,CAAA;AAC7B,MAAA,MAAM,KAAA;AAAA,IACR,CAAA,SAAE;AACA,MAAA,MAAA,CAAO,OAAA,EAAQ;AAAA,IACjB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,oBAAoB,QAAA,EAAyC;AACnE,IAAA,OAAO;AAAA,MACL,QAAA;AAAA,MACA,UAAA,EAAY,IAAA,CAAK,YAAA,CAAa,SAAA,CAAU,mBAAmB,QAAQ,CAAA;AAAA,MACnE,OAAA,EAAS,KAAA;AAAA,MACT,mBAAmB,EAAC;AAAA,MACpB,KAAA,EAAO,sBAAA;AAAA,MACP,UAAA,EAAY;AAAA,KACd;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,iBAAA,CAAkB,UAAkB,KAAA,EAAqC;AAC/E,IAAA,OAAO;AAAA,MACL,QAAA;AAAA,MACA,UAAA,EAAY,IAAA,CAAK,YAAA,CAAa,SAAA,CAAU,mBAAmB,QAAQ,CAAA;AAAA,MACnE,OAAA,EAAS,KAAA;AAAA,MACT,mBAAmB,EAAC;AAAA,MACpB,OAAO,KAAA,CAAM,OAAA;AAAA,MACb,UAAA,EAAY;AAAA,KACd;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,iBAAiB,OAAA,EAAoD;AAC3E,IAAA,OAAO;AAAA,MACL,OAAO,OAAA,CAAQ,MAAA;AAAA,MACf,WAAW,OAAA,CAAQ,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,OAAO,CAAA,CAAE,MAAA;AAAA,MAC5C,MAAA,EAAQ,OAAA,CAAQ,MAAA,CAAO,CAAC,CAAA,KAAM,CAAC,CAAA,CAAE,OAAA,IAAW,CAAA,CAAE,KAAA,KAAU,sBAAsB,CAAA,CAAE,MAAA;AAAA,MAChF,OAAA,EAAS,QAAQ,MAAA,CAAO,CAAC,MAAM,CAAA,CAAE,KAAA,KAAU,sBAAsB,CAAA,CAAE,MAAA;AAAA,MACnE,OAAA,EAAS;AAAA,KACX;AAAA,EACF;AACF;AAKO,SAAS,cAAA,CAId,cACA,cAAA,EACwC;AACxC,EAAA,OAAO,IAAI,QAAA,CAAS,YAAA,EAAc,cAAc,CAAA;AAClD;ACrkBO,IAAM,0BAAN,MAGL;AAAA,EAeA,YAA6B,OAAA,EAA2D;AAA3D,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAAA,EAA4D;AAAA,EAdjF,SAAA,GAA+E,IAAA;AAAA,EAC/E,QAMH,EAAC;AAAA,EACE,eAAuC,EAAC;AAAA,EACxC,cAAA,GAAsC,IAAA;AAAA,EACtC,gBAAgC,EAAC;AAAA,EACjC,UAAA,GAA4B,IAAA;AAAA,EAC5B,WAAA,GAA6B,IAAA;AAAA;AAAA;AAAA;AAAA,EAOrC,IAAA,CAAsB,QAAsB,KAAA,EAAgB;AAC1D,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,aAAA,CAAc,MAAM,CAAA;AAC5C,IAAA,IAAA,CAAK,SAAA,GAAY,EAAE,KAAA,EAAO,MAAA,EAAQ,UAAA,EAAW;AAC7C,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,SAAA,CAA2B,MAAA,EAAsB,KAAA,EAAU,SAAA,EAAgC;AACzF,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,MAAA,EAAQ,KAAA,EAAO,WAAW,OAAO,CAAA;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA,EAKA,QAAA,CAA0B,MAAA,EAAsB,KAAA,EAAU,SAAA,EAAgC;AACxF,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,MAAA,EAAQ,KAAA,EAAO,WAAW,MAAM,CAAA;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA,EAKA,SAAA,CAA2B,MAAA,EAAsB,KAAA,EAAU,SAAA,EAAgC;AACzF,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,MAAA,EAAQ,KAAA,EAAO,WAAW,OAAO,CAAA;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA,EAKA,QAAA,CAA0B,MAAA,EAAsB,KAAA,EAAU,SAAA,EAAgC;AACxF,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,MAAA,EAAQ,KAAA,EAAO,WAAW,MAAM,CAAA;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA,EAKA,OAAyC,MAAA,EAAiB;AACxD,IAAA,IAAA,CAAK,YAAA,GAAe,MAAA;AACpB,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAAA,EAA+B;AACnC,IAAA,IAAA,CAAK,cAAA,GAAiB,SAAA;AACtB,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW,MAAA,EAA8B;AACvC,IAAA,IAAA,CAAK,aAAA,GAAgB,MAAA;AACrB,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,KAAA,EAAqB;AACzB,IAAA,IAAA,CAAK,UAAA,GAAa,KAAA;AAClB,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,KAAA,EAAqB;AAC1B,IAAA,IAAA,CAAK,WAAA,GAAc,KAAA;AACnB,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAA,GAAiE;AACrE,IAAA,IAAI,CAAC,KAAK,SAAA,EAAW;AACnB,MAAA,MAAM,IAAI,MAAM,8DAA8D,CAAA;AAAA,IAChF;AAEA,IAAA,MAAM,QAAA,GAAW,KAAK,QAAA,EAAS;AAG/B,IAAA,MAAM,SAAS,MAAM,IAAA,CAAK,OAAA,CAAQ,QAAA,CAAS,QAAQ,QAAQ,CAAA;AAE3D,IAAA,OAAO,MAAA,CAAO,IAAA;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKQ,QAAA,GAAyB;AAC/B,IAAA,IAAI,CAAC,KAAK,SAAA,EAAW;AACnB,MAAA,MAAM,IAAI,MAAM,0CAA0C,CAAA;AAAA,IAC5D;AAEA,IAAA,MAAM,QAAwB,EAAC;AAG/B,IAAA,MAAM,WAAA,GAAc,MAAA,CAAO,OAAA,CAAQ,IAAA,CAAK,YAAY,CAAA,CAAE,GAAA,CAAI,CAAC,CAAC,KAAA,EAAO,MAAM,CAAA,KAAM;AAC7E,MAAA,MAAM,aAAa,MAAA,CAAO,IAAA;AAC1B,MAAA,OAAO,GAAA,CAAA,EAAM,GAAA,CAAI,GAAA,CAAI,CAAA,CAAA,EAAI,UAAU,CAAA,CAAA,CAAG,CAAC,CAAA,IAAA,EAAO,GAAA,CAAI,GAAA,CAAI,CAAA,CAAA,EAAI,KAAK,GAAG,CAAC,CAAA,CAAA;AAAA,IACrE,CAAC,CAAA;AAED,IAAA,IAAI,WAAA,CAAY,WAAW,CAAA,EAAG;AAC5B,MAAA,KAAA,CAAM,KAAK,GAAA,CAAA,QAAA,CAAa,CAAA;AAAA,IAC1B,CAAA,MAAO;AACL,MAAA,KAAA,CAAM,KAAK,GAAA,CAAA,OAAA,EAAa,GAAA,CAAI,KAAK,WAAA,EAAa,GAAA,CAAA,EAAA,CAAO,CAAC,CAAA,CAAE,CAAA;AAAA,IAC1D;AAGA,IAAA,MAAM,YAAA,GAAe,KAAK,gBAAA,CAAiB,IAAA,CAAK,UAAU,UAAA,EAAY,IAAA,CAAK,UAAU,KAAK,CAAA;AAC1F,IAAA,KAAA,CAAM,KAAK,GAAA,CAAA,MAAA,EAAY,GAAA,CAAI,GAAA,CAAI,YAAY,CAAC,CAAA,CAAE,CAAA;AAG9C,IAAA,KAAA,MAAWC,KAAAA,IAAQ,KAAK,KAAA,EAAO;AAC7B,MAAA,MAAM,eAAe,IAAA,CAAK,gBAAA,CAAiBA,KAAAA,CAAK,UAAA,EAAYA,MAAK,KAAK,CAAA;AACtE,MAAA,MAAM,QAAA,GAAW,IAAA,CAAK,cAAA,CAAeA,KAAAA,CAAK,IAAI,CAAA;AAC9C,MAAA,KAAA,CAAM,IAAA,CAAK,GAAA,CAAA,CAAA,EAAO,GAAA,CAAI,GAAA,CAAI,QAAQ,CAAC,CAAA,CAAA,EAAI,GAAA,CAAI,GAAA,CAAI,YAAY,CAAC,CAAA,IAAA,EAAOA,KAAAA,CAAK,SAAS,CAAA,CAAE,CAAA;AAAA,IACrF;AAGA,IAAA,IAAI,KAAK,cAAA,EAAgB;AACvB,MAAA,KAAA,CAAM,IAAA,CAAK,GAAA,CAAA,OAAA,EAAa,IAAA,CAAK,cAAc,CAAA,CAAE,CAAA;AAAA,IAC/C;AAGA,IAAA,IAAI,IAAA,CAAK,aAAA,CAAc,MAAA,GAAS,CAAA,EAAG;AACjC,MAAA,KAAA,CAAM,IAAA,CAAK,gBAAgB,GAAA,CAAI,IAAA,CAAK,KAAK,aAAA,EAAe,GAAA,CAAA,EAAA,CAAO,CAAC,CAAA,CAAE,CAAA;AAAA,IACpE;AAGA,IAAA,IAAI,IAAA,CAAK,eAAe,IAAA,EAAM;AAC5B,MAAA,KAAA,CAAM,IAAA,CAAK,aAAa,GAAA,CAAI,GAAA,CAAI,KAAK,UAAA,CAAW,QAAA,EAAU,CAAC,CAAA,CAAE,CAAA;AAAA,IAC/D;AAGA,IAAA,IAAI,IAAA,CAAK,gBAAgB,IAAA,EAAM;AAC7B,MAAA,KAAA,CAAM,IAAA,CAAK,cAAc,GAAA,CAAI,GAAA,CAAI,KAAK,WAAA,CAAY,QAAA,EAAU,CAAC,CAAA,CAAE,CAAA;AAAA,IACjE;AAEA,IAAA,OAAO,GAAA,CAAI,IAAA,CAAK,KAAA,EAAO,GAAA,CAAA,CAAK,CAAA;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA,EAKQ,OAAA,CACN,MAAA,EACA,KAAA,EACA,SAAA,EACA,IAAA,EACM;AACN,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,aAAA,CAAc,MAAM,CAAA;AAC5C,IAAA,IAAA,CAAK,KAAA,CAAM,KAAK,EAAE,KAAA,EAAO,QAAQ,UAAA,EAAY,SAAA,EAAW,MAAM,CAAA;AAC9D,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,cAAc,MAAA,EAA8B;AAClD,IAAA,IAAI,WAAW,QAAA,EAAU;AACvB,MAAA,OAAO,IAAA,CAAK,QAAQ,YAAA,IAAgB,QAAA;AAAA,IACtC;AACA,IAAA,OAAO,IAAA,CAAK,QAAQ,YAAA,IAAgB,QAAA;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKQ,gBAAA,CAAiB,YAAoB,KAAA,EAAsB;AACjE,IAAA,MAAM,SAAA,GAAY,aAAa,KAAK,CAAA;AACpC,IAAA,OAAO,CAAA,CAAA,EAAI,UAAU,CAAA,GAAA,EAAM,SAAS,CAAA,CAAA,CAAA;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAe,IAAA,EAAwB;AAC7C,IAAA,QAAQ,IAAA;AAAM,MACZ,KAAK,OAAA;AACH,QAAA,OAAO,YAAA;AAAA,MACT,KAAK,MAAA;AACH,QAAA,OAAO,WAAA;AAAA,MACT,KAAK,OAAA;AACH,QAAA,OAAO,YAAA;AAAA,MACT,KAAK,MAAA;AACH,QAAA,OAAO,iBAAA;AAAA;AACX,EACF;AACF;AAKO,SAAS,uBAId,OAAA,EACuD;AACvD,EAAA,OAAO,IAAI,wBAAwB,OAAO,CAAA;AAC5C;AAiBA,eAAsB,iBAIpB,MAAA,EAAgH;AAChH,EAAA,MAAM;AAAA,IACJ,QAAA;AAAA,IACA,WAAA;AAAA,IACA,WAAA;AAAA,IACA,UAAA;AAAA,IACA,SAAA,GAAY,IAAA;AAAA,IACZ,YAAA;AAAA,IACA,KAAA,EAAO;AAAA,GACT,GAAI,MAAA;AAGJ,EAAA,MAAM,eAAA,GAAkB,aAAa,WAAW,CAAA;AAChD,EAAA,MAAM,eAAA,GAAkB,aAAa,WAAW,CAAA;AAGhD,EAAA,MAAM,eAAA,GAAkB,YAAA,CACrB,GAAA,CAAI,CAAC,KAAA,KAAU,CAAA,GAAA,EAAM,MAAA,CAAO,KAAK,CAAC,CAAA,CAAA,CAAG,CAAA,CACrC,IAAA,CAAK,IAAI,CAAA;AAGZ,EAAA,MAAM,UAAA,GAAa;AAAA,IACjB,eAAe,eAAe,CAAA,CAAA;AAAA,IAC9B,SAAS,eAAe,CAAA,GAAA,CAAA;AAAA,IACxB,CAAA,oBAAA,EAAuB,eAAe,CAAA,UAAA,EAAa,MAAA,CAAO,UAAU,CAAC,CAAA,OAAA,EAAU,MAAA,CAAO,SAAS,CAAC,CAAA,CAAA;AAAA,GAClG;AAEA,EAAA,IAAI,cAAA,EAAgB;AAClB,IAAA,UAAA,CAAW,KAAK,OAAO,CAAA;AAAA,EAEzB;AAEA,EAAA,MAAM,WAAW,GAAA,CAAI,GAAA,CAAI,UAAA,CAAW,IAAA,CAAK,GAAG,CAAC,CAAA;AAE7C,EAAA,MAAM,MAAA,GAAS,MAAM,QAAA,CAAS,OAAA,CAAQ,QAAQ,CAAA;AAE9C,EAAA,OAAO,MAAA,CAAO,IAAA;AAChB;AAkBA,eAAsB,cAAA,CACpB,IACA,OAAA,EACoB;AACpB,EAAA,MAAM,EAAE,YAAA,EAAc,YAAA,EAAc,GAAA,EAAK,QAAO,GAAI,OAAA;AAGpD,EAAA,MAAM,YAAA,GAAe,MAAA,CAClB,OAAA,CAAQ,aAAA,EAAe,CAAA,CAAA,EAAI,YAAY,CAAA,EAAA,CAAI,CAAA,CAC3C,OAAA,CAAQ,aAAA,EAAe,CAAA,CAAA,EAAI,YAAY,CAAA,EAAA,CAAI,CAAA;AAE9C,EAAA,MAAM,KAAA,GAAQ,GAAA,CAAI,GAAA,CAAI,YAAY,CAAA;AAElC,EAAA,MAAM,MAAA,GAAS,MAAM,EAAA,CAAG,OAAA,CAAQ,KAAK,CAAA;AAErC,EAAA,OAAO,MAAA,CAAO,IAAA;AAChB;AAsBO,SAAS,sBAAA,CACd,MAAA,EACA,YAAA,EACA,aAAA,EACgD;AAChD,EAAA,MAAM,OAAA,GAAU,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA,CAAE,IAAI,CAAC,CAAC,KAAA,EAAO,MAAM,CAAA,KAAM;AAC9D,IAAA,MAAM,aAAa,MAAA,CAAO,IAAA;AAC1B,IAAA,OAAO,CAAA,CAAA,EAAI,UAAU,CAAA,MAAA,EAAS,KAAK,CAAA,CAAA,CAAA;AAAA,EACrC,CAAC,CAAA;AAED,EAAA,MAAM,YAAY,MAAc;AAG9B,IAAA,OAAO,YAAA;AAAA,EACT,CAAA;AAEA,EAAA,OAAO,EAAE,SAAS,SAAA,EAAU;AAC9B","file":"index.js","sourcesContent":["import type { Config } from './types.js';\n\n/**\n * Define configuration for drizzle-multitenant\n *\n * @example\n * ```typescript\n * import { defineConfig } from 'drizzle-multitenant';\n * import * as tenantSchema from './schemas/tenant';\n * import * as sharedSchema from './schemas/shared';\n *\n * export default defineConfig({\n * connection: {\n * url: process.env.DATABASE_URL!,\n * poolConfig: {\n * max: 10,\n * idleTimeoutMillis: 30000,\n * },\n * },\n * isolation: {\n * strategy: 'schema',\n * schemaNameTemplate: (tenantId) => `tenant_${tenantId.replace(/-/g, '_')}`,\n * maxPools: 50,\n * poolTtlMs: 60 * 60 * 1000,\n * },\n * schemas: {\n * tenant: tenantSchema,\n * shared: sharedSchema,\n * },\n * });\n * ```\n */\nexport function defineConfig<\n TTenantSchema extends Record<string, unknown>,\n TSharedSchema extends Record<string, unknown> = Record<string, unknown>,\n>(config: Config<TTenantSchema, TSharedSchema>): Config<TTenantSchema, TSharedSchema> {\n validateConfig(config);\n return config;\n}\n\n/**\n * Validate configuration at runtime\n */\nfunction validateConfig<\n TTenantSchema extends Record<string, unknown>,\n TSharedSchema extends Record<string, unknown>,\n>(config: Config<TTenantSchema, TSharedSchema>): void {\n // Connection validation\n if (!config.connection.url) {\n throw new Error('[drizzle-multitenant] connection.url is required');\n }\n\n // Isolation validation\n if (!config.isolation.strategy) {\n throw new Error('[drizzle-multitenant] isolation.strategy is required');\n }\n\n if (config.isolation.strategy !== 'schema') {\n throw new Error(\n `[drizzle-multitenant] isolation.strategy \"${config.isolation.strategy}\" is not yet supported. Only \"schema\" is currently available.`\n );\n }\n\n if (!config.isolation.schemaNameTemplate) {\n throw new Error('[drizzle-multitenant] isolation.schemaNameTemplate is required');\n }\n\n if (typeof config.isolation.schemaNameTemplate !== 'function') {\n throw new Error('[drizzle-multitenant] isolation.schemaNameTemplate must be a function');\n }\n\n // Schema validation\n if (!config.schemas.tenant) {\n throw new Error('[drizzle-multitenant] schemas.tenant is required');\n }\n\n // Pool limits validation\n if (config.isolation.maxPools !== undefined && config.isolation.maxPools < 1) {\n throw new Error('[drizzle-multitenant] isolation.maxPools must be at least 1');\n }\n\n if (config.isolation.poolTtlMs !== undefined && config.isolation.poolTtlMs < 0) {\n throw new Error('[drizzle-multitenant] isolation.poolTtlMs must be non-negative');\n }\n}\n","import type { Pool, PoolConfig } from 'pg';\nimport type { NodePgDatabase } from 'drizzle-orm/node-postgres';\n\n/**\n * Isolation strategy for multi-tenancy\n */\nexport type IsolationStrategy = 'schema' | 'database' | 'row';\n\n/**\n * Connection configuration\n */\nexport interface ConnectionConfig {\n /** PostgreSQL connection URL */\n url: string;\n /** Pool configuration options */\n poolConfig?: Omit<PoolConfig, 'connectionString'>;\n}\n\n/**\n * Isolation configuration\n */\nexport interface IsolationConfig {\n /** Isolation strategy (currently only 'schema' is supported) */\n strategy: IsolationStrategy;\n /** Function to generate schema name from tenant ID */\n schemaNameTemplate: (tenantId: string) => string;\n /** Maximum number of simultaneous pools (LRU eviction) */\n maxPools?: number;\n /** TTL in milliseconds before pool cleanup */\n poolTtlMs?: number;\n}\n\n/**\n * Schema definitions\n */\nexport interface SchemasConfig<\n TTenantSchema extends Record<string, unknown> = Record<string, unknown>,\n TSharedSchema extends Record<string, unknown> = Record<string, unknown>,\n> {\n /** Schema applied per tenant */\n tenant: TTenantSchema;\n /** Shared schema (public) */\n shared?: TSharedSchema;\n}\n\n/**\n * Lifecycle hooks\n */\nexport interface Hooks {\n /** Called when a new pool is created */\n onPoolCreated?: (tenantId: string) => void | Promise<void>;\n /** Called when a pool is evicted */\n onPoolEvicted?: (tenantId: string) => void | Promise<void>;\n /** Called on pool error */\n onError?: (tenantId: string, error: Error) => void | Promise<void>;\n}\n\n/**\n * Metrics configuration\n */\nexport interface MetricsConfig {\n /** Enable metrics collection */\n enabled: boolean;\n /** Prefix for metric names */\n prefix?: string;\n}\n\n/**\n * Main configuration interface\n */\nexport interface Config<\n TTenantSchema extends Record<string, unknown> = Record<string, unknown>,\n TSharedSchema extends Record<string, unknown> = Record<string, unknown>,\n> {\n /** Database connection settings */\n connection: ConnectionConfig;\n /** Tenant isolation settings */\n isolation: IsolationConfig;\n /** Drizzle schemas */\n schemas: SchemasConfig<TTenantSchema, TSharedSchema>;\n /** Lifecycle hooks */\n hooks?: Hooks;\n /** Metrics configuration */\n metrics?: MetricsConfig;\n}\n\n/**\n * Internal pool entry for LRU cache\n */\nexport interface PoolEntry<TSchema extends Record<string, unknown> = Record<string, unknown>> {\n /** Drizzle database instance */\n db: NodePgDatabase<TSchema>;\n /** PostgreSQL pool */\n pool: Pool;\n /** Last access timestamp */\n lastAccess: number;\n /** Schema name */\n schemaName: string;\n}\n\n/**\n * Type for tenant database instance\n */\nexport type TenantDb<TSchema extends Record<string, unknown> = Record<string, unknown>> =\n NodePgDatabase<TSchema>;\n\n/**\n * Type for shared database instance\n */\nexport type SharedDb<TSchema extends Record<string, unknown> = Record<string, unknown>> =\n NodePgDatabase<TSchema>;\n\n/**\n * Tenant manager interface\n */\nexport interface TenantManager<\n TTenantSchema extends Record<string, unknown> = Record<string, unknown>,\n TSharedSchema extends Record<string, unknown> = Record<string, unknown>,\n> {\n /** Get database instance for a specific tenant */\n getDb(tenantId: string): TenantDb<TTenantSchema>;\n /** Get shared database instance */\n getSharedDb(): SharedDb<TSharedSchema>;\n /** Get the schema name for a tenant */\n getSchemaName(tenantId: string): string;\n /** Check if a tenant pool exists */\n hasPool(tenantId: string): boolean;\n /** Get active pool count */\n getPoolCount(): number;\n /** Get all active tenant IDs */\n getActiveTenantIds(): string[];\n /** Manually evict a tenant pool */\n evictPool(tenantId: string): Promise<void>;\n /** Dispose all pools and cleanup */\n dispose(): Promise<void>;\n}\n\n/**\n * Default configuration values\n */\nexport const DEFAULT_CONFIG = {\n maxPools: 50,\n poolTtlMs: 60 * 60 * 1000, // 1 hour\n cleanupIntervalMs: 60_000, // 1 minute\n poolConfig: {\n max: 10,\n idleTimeoutMillis: 30_000,\n connectionTimeoutMillis: 5_000,\n },\n} as const;\n","import { Pool } from 'pg';\nimport { drizzle } from 'drizzle-orm/node-postgres';\nimport { LRUCache } from 'lru-cache';\nimport type {\n Config,\n PoolEntry,\n TenantDb,\n SharedDb,\n} from './types.js';\nimport { DEFAULT_CONFIG as defaults } from './types.js';\n\n/**\n * Pool manager that handles tenant database connections with LRU eviction\n */\nexport class PoolManager<\n TTenantSchema extends Record<string, unknown>,\n TSharedSchema extends Record<string, unknown>,\n> {\n private readonly pools: LRUCache<string, PoolEntry<TTenantSchema>>;\n private readonly tenantIdBySchema: Map<string, string> = new Map();\n private sharedPool: Pool | null = null;\n private sharedDb: SharedDb<TSharedSchema> | null = null;\n private cleanupInterval: ReturnType<typeof setInterval> | null = null;\n private disposed = false;\n\n constructor(private readonly config: Config<TTenantSchema, TSharedSchema>) {\n const maxPools = config.isolation.maxPools ?? defaults.maxPools;\n\n this.pools = new LRUCache<string, PoolEntry<TTenantSchema>>({\n max: maxPools,\n dispose: (entry, key) => {\n this.disposePoolEntry(entry, key);\n },\n noDisposeOnSet: true,\n });\n }\n\n /**\n * Get or create a database connection for a tenant\n */\n getDb(tenantId: string): TenantDb<TTenantSchema> {\n this.ensureNotDisposed();\n\n const schemaName = this.config.isolation.schemaNameTemplate(tenantId);\n let entry = this.pools.get(schemaName);\n\n if (!entry) {\n entry = this.createPoolEntry(tenantId, schemaName);\n this.pools.set(schemaName, entry);\n this.tenantIdBySchema.set(schemaName, tenantId);\n\n // Fire hook asynchronously\n void this.config.hooks?.onPoolCreated?.(tenantId);\n }\n\n entry.lastAccess = Date.now();\n return entry.db;\n }\n\n /**\n * Get or create the shared database connection\n */\n getSharedDb(): SharedDb<TSharedSchema> {\n this.ensureNotDisposed();\n\n if (!this.sharedDb) {\n this.sharedPool = new Pool({\n connectionString: this.config.connection.url,\n ...defaults.poolConfig,\n ...this.config.connection.poolConfig,\n });\n\n this.sharedPool.on('error', (err) => {\n void this.config.hooks?.onError?.('shared', err);\n });\n\n this.sharedDb = drizzle(this.sharedPool, {\n schema: this.config.schemas.shared,\n }) as SharedDb<TSharedSchema>;\n }\n\n return this.sharedDb;\n }\n\n /**\n * Get schema name for a tenant\n */\n getSchemaName(tenantId: string): string {\n return this.config.isolation.schemaNameTemplate(tenantId);\n }\n\n /**\n * Check if a pool exists for a tenant\n */\n hasPool(tenantId: string): boolean {\n const schemaName = this.config.isolation.schemaNameTemplate(tenantId);\n return this.pools.has(schemaName);\n }\n\n /**\n * Get count of active pools\n */\n getPoolCount(): number {\n return this.pools.size;\n }\n\n /**\n * Get all active tenant IDs\n */\n getActiveTenantIds(): string[] {\n return Array.from(this.tenantIdBySchema.values());\n }\n\n /**\n * Manually evict a tenant pool\n */\n async evictPool(tenantId: string): Promise<void> {\n const schemaName = this.config.isolation.schemaNameTemplate(tenantId);\n const entry = this.pools.get(schemaName);\n\n if (entry) {\n this.pools.delete(schemaName);\n this.tenantIdBySchema.delete(schemaName);\n await this.closePool(entry.pool, tenantId);\n }\n }\n\n /**\n * Start automatic cleanup of idle pools\n */\n startCleanup(): void {\n if (this.cleanupInterval) return;\n\n const poolTtlMs = this.config.isolation.poolTtlMs ?? defaults.poolTtlMs;\n const cleanupIntervalMs = defaults.cleanupIntervalMs;\n\n this.cleanupInterval = setInterval(() => {\n void this.cleanupIdlePools(poolTtlMs);\n }, cleanupIntervalMs);\n\n // Don't prevent process exit\n this.cleanupInterval.unref();\n }\n\n /**\n * Stop automatic cleanup\n */\n stopCleanup(): void {\n if (this.cleanupInterval) {\n clearInterval(this.cleanupInterval);\n this.cleanupInterval = null;\n }\n }\n\n /**\n * Dispose all pools and cleanup resources\n */\n async dispose(): Promise<void> {\n if (this.disposed) return;\n\n this.disposed = true;\n this.stopCleanup();\n\n // Close all tenant pools\n const closePromises: Promise<void>[] = [];\n\n for (const [schemaName, entry] of this.pools.entries()) {\n const tenantId = this.tenantIdBySchema.get(schemaName);\n closePromises.push(this.closePool(entry.pool, tenantId ?? schemaName));\n }\n\n this.pools.clear();\n this.tenantIdBySchema.clear();\n\n // Close shared pool\n if (this.sharedPool) {\n closePromises.push(this.closePool(this.sharedPool, 'shared'));\n this.sharedPool = null;\n this.sharedDb = null;\n }\n\n await Promise.all(closePromises);\n }\n\n /**\n * Create a new pool entry for a tenant\n */\n private createPoolEntry(tenantId: string, schemaName: string): PoolEntry<TTenantSchema> {\n const pool = new Pool({\n connectionString: this.config.connection.url,\n ...defaults.poolConfig,\n ...this.config.connection.poolConfig,\n options: `-c search_path=${schemaName},public`,\n });\n\n pool.on('error', async (err) => {\n void this.config.hooks?.onError?.(tenantId, err);\n await this.evictPool(tenantId);\n });\n\n const db = drizzle(pool, {\n schema: this.config.schemas.tenant,\n }) as TenantDb<TTenantSchema>;\n\n return {\n db,\n pool,\n lastAccess: Date.now(),\n schemaName,\n };\n }\n\n /**\n * Dispose a pool entry (called by LRU cache)\n */\n private disposePoolEntry(entry: PoolEntry<TTenantSchema>, schemaName: string): void {\n const tenantId = this.tenantIdBySchema.get(schemaName);\n this.tenantIdBySchema.delete(schemaName);\n\n void this.closePool(entry.pool, tenantId ?? schemaName).then(() => {\n if (tenantId) {\n void this.config.hooks?.onPoolEvicted?.(tenantId);\n }\n });\n }\n\n /**\n * Close a pool gracefully\n */\n private async closePool(pool: Pool, identifier: string): Promise<void> {\n try {\n await pool.end();\n } catch (error) {\n void this.config.hooks?.onError?.(identifier, error as Error);\n }\n }\n\n /**\n * Cleanup pools that have been idle for too long\n */\n private async cleanupIdlePools(poolTtlMs: number): Promise<void> {\n const now = Date.now();\n const toEvict: string[] = [];\n\n for (const [schemaName, entry] of this.pools.entries()) {\n if (now - entry.lastAccess > poolTtlMs) {\n toEvict.push(schemaName);\n }\n }\n\n for (const schemaName of toEvict) {\n const tenantId = this.tenantIdBySchema.get(schemaName);\n if (tenantId) {\n await this.evictPool(tenantId);\n }\n }\n }\n\n /**\n * Ensure the manager hasn't been disposed\n */\n private ensureNotDisposed(): void {\n if (this.disposed) {\n throw new Error('[drizzle-multitenant] TenantManager has been disposed');\n }\n }\n}\n","import { PoolManager } from './pool.js';\nimport type { Config, TenantManager, TenantDb, SharedDb } from './types.js';\n\n/**\n * Create a tenant manager instance\n *\n * @example\n * ```typescript\n * import { createTenantManager, defineConfig } from 'drizzle-multitenant';\n *\n * const config = defineConfig({\n * connection: { url: process.env.DATABASE_URL! },\n * isolation: {\n * strategy: 'schema',\n * schemaNameTemplate: (id) => `tenant_${id}`,\n * },\n * schemas: { tenant: tenantSchema },\n * });\n *\n * const tenants = createTenantManager(config);\n *\n * // Get database for a specific tenant\n * const db = tenants.getDb('tenant-uuid');\n * const users = await db.select().from(schema.users);\n *\n * // Get shared database\n * const sharedDb = tenants.getSharedDb();\n * const plans = await sharedDb.select().from(sharedSchema.plans);\n * ```\n */\nexport function createTenantManager<\n TTenantSchema extends Record<string, unknown>,\n TSharedSchema extends Record<string, unknown> = Record<string, unknown>,\n>(config: Config<TTenantSchema, TSharedSchema>): TenantManager<TTenantSchema, TSharedSchema> {\n const poolManager = new PoolManager(config);\n\n // Start automatic cleanup\n poolManager.startCleanup();\n\n return {\n getDb(tenantId: string): TenantDb<TTenantSchema> {\n return poolManager.getDb(tenantId);\n },\n\n getSharedDb(): SharedDb<TSharedSchema> {\n return poolManager.getSharedDb();\n },\n\n getSchemaName(tenantId: string): string {\n return poolManager.getSchemaName(tenantId);\n },\n\n hasPool(tenantId: string): boolean {\n return poolManager.hasPool(tenantId);\n },\n\n getPoolCount(): number {\n return poolManager.getPoolCount();\n },\n\n getActiveTenantIds(): string[] {\n return poolManager.getActiveTenantIds();\n },\n\n async evictPool(tenantId: string): Promise<void> {\n await poolManager.evictPool(tenantId);\n },\n\n async dispose(): Promise<void> {\n await poolManager.dispose();\n },\n };\n}\n","import { AsyncLocalStorage } from 'node:async_hooks';\nimport type { TenantManager, TenantDb, SharedDb } from './types.js';\n\n/**\n * Base tenant context data\n */\nexport interface BaseTenantContext {\n tenantId: string;\n}\n\n/**\n * Tenant context with optional custom data\n */\nexport type TenantContextData<TCustom extends Record<string, unknown> = Record<string, unknown>> =\n BaseTenantContext & TCustom;\n\n/**\n * Tenant context API\n */\nexport interface TenantContext<\n TTenantSchema extends Record<string, unknown>,\n TSharedSchema extends Record<string, unknown>,\n TCustom extends Record<string, unknown> = Record<string, unknown>,\n> {\n /**\n * Run a callback with tenant context\n */\n runWithTenant<T>(\n context: TenantContextData<TCustom>,\n callback: () => T | Promise<T>\n ): T | Promise<T>;\n\n /**\n * Get current tenant context (throws if not in context)\n */\n getTenant(): TenantContextData<TCustom>;\n\n /**\n * Get current tenant context or undefined\n */\n getTenantOrNull(): TenantContextData<TCustom> | undefined;\n\n /**\n * Get current tenant ID (throws if not in context)\n */\n getTenantId(): string;\n\n /**\n * Get database for current tenant (throws if not in context)\n */\n getTenantDb(): TenantDb<TTenantSchema>;\n\n /**\n * Get shared database\n */\n getSharedDb(): SharedDb<TSharedSchema>;\n\n /**\n * Check if currently running within a tenant context\n */\n isInTenantContext(): boolean;\n}\n\n/**\n * Create a tenant context with AsyncLocalStorage\n *\n * @example\n * ```typescript\n * import { createTenantContext, createTenantManager } from 'drizzle-multitenant';\n *\n * const manager = createTenantManager(config);\n *\n * const {\n * runWithTenant,\n * getTenant,\n * getTenantDb,\n * getSharedDb,\n * } = createTenantContext(manager);\n *\n * // Use in request handler\n * app.get('/users', async (req, res) => {\n * const tenantId = req.headers['x-tenant-id'];\n *\n * await runWithTenant({ tenantId }, async () => {\n * const db = getTenantDb();\n * const users = await db.select().from(schema.users);\n * res.json(users);\n * });\n * });\n * ```\n */\nexport function createTenantContext<\n TTenantSchema extends Record<string, unknown>,\n TSharedSchema extends Record<string, unknown> = Record<string, unknown>,\n TCustom extends Record<string, unknown> = Record<string, unknown>,\n>(\n manager: TenantManager<TTenantSchema, TSharedSchema>\n): TenantContext<TTenantSchema, TSharedSchema, TCustom> {\n const storage = new AsyncLocalStorage<TenantContextData<TCustom>>();\n\n function getTenantOrNull(): TenantContextData<TCustom> | undefined {\n return storage.getStore();\n }\n\n function getTenant(): TenantContextData<TCustom> {\n const context = getTenantOrNull();\n if (!context) {\n throw new Error(\n '[drizzle-multitenant] No tenant context found. ' +\n 'Make sure you are calling this within runWithTenant().'\n );\n }\n return context;\n }\n\n function getTenantId(): string {\n return getTenant().tenantId;\n }\n\n function getTenantDb(): TenantDb<TTenantSchema> {\n const tenantId = getTenantId();\n return manager.getDb(tenantId);\n }\n\n function getSharedDb(): SharedDb<TSharedSchema> {\n return manager.getSharedDb();\n }\n\n function isInTenantContext(): boolean {\n return getTenantOrNull() !== undefined;\n }\n\n function runWithTenant<T>(\n context: TenantContextData<TCustom>,\n callback: () => T | Promise<T>\n ): T | Promise<T> {\n if (!context.tenantId) {\n throw new Error('[drizzle-multitenant] tenantId is required in context');\n }\n return storage.run(context, callback);\n }\n\n return {\n runWithTenant,\n getTenant,\n getTenantOrNull,\n getTenantId,\n getTenantDb,\n getSharedDb,\n isInTenantContext,\n };\n}\n","import type { Pool } from 'pg';\n\n/**\n * Table format for tracking migrations\n * - \"name\": drizzle-multitenant native (filename-based)\n * - \"hash\": SHA-256 hash with timestamp\n * - \"drizzle-kit\": Exact drizzle-kit format (hash + bigint timestamp)\n */\nexport type TableFormat = 'name' | 'hash' | 'drizzle-kit';\n\n/**\n * Detected table format information\n */\nexport interface DetectedFormat {\n /** The detected format type */\n format: TableFormat;\n /** The table name */\n tableName: string;\n /** Column configuration */\n columns: {\n /** Column used for identifying migrations */\n identifier: 'name' | 'hash';\n /** Column used for timestamp */\n timestamp: 'applied_at' | 'created_at';\n /** Data type of timestamp column */\n timestampType: 'timestamp' | 'bigint';\n };\n}\n\n/**\n * Default format configuration for new tables\n */\nexport const DEFAULT_FORMAT: DetectedFormat = {\n format: 'name',\n tableName: '__drizzle_migrations',\n columns: {\n identifier: 'name',\n timestamp: 'applied_at',\n timestampType: 'timestamp',\n },\n};\n\n/**\n * drizzle-kit format configuration\n */\nexport const DRIZZLE_KIT_FORMAT: DetectedFormat = {\n format: 'drizzle-kit',\n tableName: '__drizzle_migrations',\n columns: {\n identifier: 'hash',\n timestamp: 'created_at',\n timestampType: 'bigint',\n },\n};\n\ninterface ColumnInfo {\n column_name: string;\n data_type: string;\n}\n\n/**\n * Detect the format of an existing migrations table\n *\n * @param pool - Database connection pool\n * @param schemaName - Schema to check\n * @param tableName - Migrations table name\n * @returns Detected format or null if table doesn't exist\n */\nexport async function detectTableFormat(\n pool: Pool,\n schemaName: string,\n tableName: string\n): Promise<DetectedFormat | null> {\n // Check if table exists\n const tableExists = await pool.query<{ exists: boolean }>(\n `SELECT EXISTS (\n SELECT 1 FROM information_schema.tables\n WHERE table_schema = $1 AND table_name = $2\n ) as exists`,\n [schemaName, tableName]\n );\n\n if (!tableExists.rows[0]?.exists) {\n return null;\n }\n\n // Get column information\n const columnsResult = await pool.query<ColumnInfo>(\n `SELECT column_name, data_type\n FROM information_schema.columns\n WHERE table_schema = $1 AND table_name = $2`,\n [schemaName, tableName]\n );\n\n const columnMap = new Map<string, string>(\n columnsResult.rows.map((r) => [r.column_name, r.data_type])\n );\n\n // Detect format based on columns\n if (columnMap.has('name')) {\n // drizzle-multitenant native format\n return {\n format: 'name',\n tableName,\n columns: {\n identifier: 'name',\n timestamp: columnMap.has('applied_at') ? 'applied_at' : 'created_at',\n timestampType: 'timestamp',\n },\n };\n }\n\n if (columnMap.has('hash')) {\n const createdAtType = columnMap.get('created_at');\n\n // drizzle-kit uses bigint for created_at\n if (createdAtType === 'bigint') {\n return {\n format: 'drizzle-kit',\n tableName,\n columns: {\n identifier: 'hash',\n timestamp: 'created_at',\n timestampType: 'bigint',\n },\n };\n }\n\n // Custom hash-based format with regular timestamp\n return {\n format: 'hash',\n tableName,\n columns: {\n identifier: 'hash',\n timestamp: 'created_at',\n timestampType: 'timestamp',\n },\n };\n }\n\n // Unknown format - return null to trigger error handling\n return null;\n}\n\n/**\n * Get the format configuration for a specific format type\n */\nexport function getFormatConfig(\n format: TableFormat,\n tableName: string = '__drizzle_migrations'\n): DetectedFormat {\n switch (format) {\n case 'name':\n return {\n format: 'name',\n tableName,\n columns: {\n identifier: 'name',\n timestamp: 'applied_at',\n timestampType: 'timestamp',\n },\n };\n case 'hash':\n return {\n format: 'hash',\n tableName,\n columns: {\n identifier: 'hash',\n timestamp: 'created_at',\n timestampType: 'timestamp',\n },\n };\n case 'drizzle-kit':\n return {\n format: 'drizzle-kit',\n tableName,\n columns: {\n identifier: 'hash',\n timestamp: 'created_at',\n timestampType: 'bigint',\n },\n };\n }\n}\n","import { readdir, readFile } from 'node:fs/promises';\nimport { join, basename } from 'node:path';\nimport { createHash } from 'node:crypto';\nimport { Pool } from 'pg';\nimport type { Config } from '../types.js';\nimport type {\n MigratorConfig,\n MigrationFile,\n MigrateOptions,\n TenantMigrationResult,\n MigrationResults,\n TenantMigrationStatus,\n AppliedMigration,\n CreateTenantOptions,\n DropTenantOptions,\n} from './types.js';\nimport { detectTableFormat, getFormatConfig, type DetectedFormat, type TableFormat } from './table-format.js';\n\nconst DEFAULT_MIGRATIONS_TABLE = '__drizzle_migrations';\n\n/**\n * Parallel migration engine for multi-tenant applications\n */\nexport class Migrator<\n TTenantSchema extends Record<string, unknown>,\n TSharedSchema extends Record<string, unknown>,\n> {\n private readonly migrationsTable: string;\n\n constructor(\n private readonly tenantConfig: Config<TTenantSchema, TSharedSchema>,\n private readonly migratorConfig: MigratorConfig\n ) {\n this.migrationsTable = migratorConfig.migrationsTable ?? DEFAULT_MIGRATIONS_TABLE;\n }\n\n /**\n * Migrate all tenants in parallel\n */\n async migrateAll(options: MigrateOptions = {}): Promise<MigrationResults> {\n const {\n concurrency = 10,\n onProgress,\n onError,\n dryRun = false,\n } = options;\n\n const tenantIds = await this.migratorConfig.tenantDiscovery();\n const migrations = await this.loadMigrations();\n\n const results: TenantMigrationResult[] = [];\n let aborted = false;\n\n // Process tenants in batches\n for (let i = 0; i < tenantIds.length && !aborted; i += concurrency) {\n const batch = tenantIds.slice(i, i + concurrency);\n\n const batchResults = await Promise.all(\n batch.map(async (tenantId) => {\n if (aborted) {\n return this.createSkippedResult(tenantId);\n }\n\n try {\n onProgress?.(tenantId, 'starting');\n const result = await this.migrateTenant(tenantId, migrations, { dryRun, onProgress });\n onProgress?.(tenantId, result.success ? 'completed' : 'failed');\n return result;\n } catch (error) {\n onProgress?.(tenantId, 'failed');\n const action = onError?.(tenantId, error as Error);\n if (action === 'abort') {\n aborted = true;\n }\n return this.createErrorResult(tenantId, error as Error);\n }\n })\n );\n\n results.push(...batchResults);\n }\n\n // Mark remaining tenants as skipped if aborted\n if (aborted) {\n const remaining = tenantIds.slice(results.length);\n for (const tenantId of remaining) {\n results.push(this.createSkippedResult(tenantId));\n }\n }\n\n return this.aggregateResults(results);\n }\n\n /**\n * Migrate a single tenant\n */\n async migrateTenant(\n tenantId: string,\n migrations?: MigrationFile[],\n options: { dryRun?: boolean; onProgress?: MigrateOptions['onProgress'] } = {}\n ): Promise<TenantMigrationResult> {\n const startTime = Date.now();\n const schemaName = this.tenantConfig.isolation.schemaNameTemplate(tenantId);\n const appliedMigrations: string[] = [];\n\n const pool = await this.createPool(schemaName);\n\n try {\n await this.migratorConfig.hooks?.beforeTenant?.(tenantId);\n\n // Detect or determine the format before creating table\n const format = await this.getOrDetectFormat(pool, schemaName);\n\n // Ensure migrations table exists with correct format\n await this.ensureMigrationsTable(pool, schemaName, format);\n\n // Load migrations if not provided\n const allMigrations = migrations ?? await this.loadMigrations();\n\n // Get applied migrations using format-aware query\n const applied = await this.getAppliedMigrations(pool, schemaName, format);\n const appliedSet = new Set(applied.map((m) => m.identifier));\n\n // Filter pending migrations using format-aware comparison\n const pending = allMigrations.filter(\n (m) => !this.isMigrationApplied(m, appliedSet, format)\n );\n\n if (options.dryRun) {\n return {\n tenantId,\n schemaName,\n success: true,\n appliedMigrations: pending.map((m) => m.name),\n durationMs: Date.now() - startTime,\n format: format.format,\n };\n }\n\n // Apply pending migrations\n for (const migration of pending) {\n const migrationStart = Date.now();\n options.onProgress?.(tenantId, 'migrating', migration.name);\n\n await this.migratorConfig.hooks?.beforeMigration?.(tenantId, migration.name);\n await this.applyMigration(pool, schemaName, migration, format);\n await this.migratorConfig.hooks?.afterMigration?.(\n tenantId,\n migration.name,\n Date.now() - migrationStart\n );\n\n appliedMigrations.push(migration.name);\n }\n\n const result: TenantMigrationResult = {\n tenantId,\n schemaName,\n success: true,\n appliedMigrations,\n durationMs: Date.now() - startTime,\n format: format.format,\n };\n\n await this.migratorConfig.hooks?.afterTenant?.(tenantId, result);\n\n return result;\n } catch (error) {\n const result: TenantMigrationResult = {\n tenantId,\n schemaName,\n success: false,\n appliedMigrations,\n error: (error as Error).message,\n durationMs: Date.now() - startTime,\n };\n\n await this.migratorConfig.hooks?.afterTenant?.(tenantId, result);\n\n return result;\n } finally {\n await pool.end();\n }\n }\n\n /**\n * Migrate specific tenants\n */\n async migrateTenants(tenantIds: string[], options: MigrateOptions = {}): Promise<MigrationResults> {\n const migrations = await this.loadMigrations();\n const results: TenantMigrationResult[] = [];\n\n const { concurrency = 10, onProgress, onError } = options;\n\n for (let i = 0; i < tenantIds.length; i += concurrency) {\n const batch = tenantIds.slice(i, i + concurrency);\n\n const batchResults = await Promise.all(\n batch.map(async (tenantId) => {\n try {\n onProgress?.(tenantId, 'starting');\n const result = await this.migrateTenant(tenantId, migrations, { dryRun: options.dryRun ?? false, onProgress });\n onProgress?.(tenantId, result.success ? 'completed' : 'failed');\n return result;\n } catch (error) {\n onProgress?.(tenantId, 'failed');\n onError?.(tenantId, error as Error);\n return this.createErrorResult(tenantId, error as Error);\n }\n })\n );\n\n results.push(...batchResults);\n }\n\n return this.aggregateResults(results);\n }\n\n /**\n * Get migration status for all tenants\n */\n async getStatus(): Promise<TenantMigrationStatus[]> {\n const tenantIds = await this.migratorConfig.tenantDiscovery();\n const migrations = await this.loadMigrations();\n const statuses: TenantMigrationStatus[] = [];\n\n for (const tenantId of tenantIds) {\n statuses.push(await this.getTenantStatus(tenantId, migrations));\n }\n\n return statuses;\n }\n\n /**\n * Get migration status for a specific tenant\n */\n async getTenantStatus(tenantId: string, migrations?: MigrationFile[]): Promise<TenantMigrationStatus> {\n const schemaName = this.tenantConfig.isolation.schemaNameTemplate(tenantId);\n const pool = await this.createPool(schemaName);\n\n try {\n const allMigrations = migrations ?? await this.loadMigrations();\n\n // Check if migrations table exists\n const tableExists = await this.migrationsTableExists(pool, schemaName);\n if (!tableExists) {\n return {\n tenantId,\n schemaName,\n appliedCount: 0,\n pendingCount: allMigrations.length,\n pendingMigrations: allMigrations.map((m) => m.name),\n status: allMigrations.length > 0 ? 'behind' : 'ok',\n format: null, // New tenant, no table yet\n };\n }\n\n // Detect the table format\n const format = await this.getOrDetectFormat(pool, schemaName);\n\n const applied = await this.getAppliedMigrations(pool, schemaName, format);\n const appliedSet = new Set(applied.map((m) => m.identifier));\n\n // Use format-aware comparison\n const pending = allMigrations.filter(\n (m) => !this.isMigrationApplied(m, appliedSet, format)\n );\n\n return {\n tenantId,\n schemaName,\n appliedCount: applied.length,\n pendingCount: pending.length,\n pendingMigrations: pending.map((m) => m.name),\n status: pending.length > 0 ? 'behind' : 'ok',\n format: format.format,\n };\n } catch (error) {\n return {\n tenantId,\n schemaName,\n appliedCount: 0,\n pendingCount: 0,\n pendingMigrations: [],\n status: 'error',\n error: (error as Error).message,\n format: null,\n };\n } finally {\n await pool.end();\n }\n }\n\n /**\n * Create a new tenant schema and optionally apply migrations\n */\n async createTenant(tenantId: string, options: CreateTenantOptions = {}): Promise<void> {\n const { migrate = true } = options;\n const schemaName = this.tenantConfig.isolation.schemaNameTemplate(tenantId);\n\n const pool = new Pool({\n connectionString: this.tenantConfig.connection.url,\n ...this.tenantConfig.connection.poolConfig,\n });\n\n try {\n // Create schema\n await pool.query(`CREATE SCHEMA IF NOT EXISTS \"${schemaName}\"`);\n\n if (migrate) {\n // Apply all migrations\n await this.migrateTenant(tenantId);\n }\n } finally {\n await pool.end();\n }\n }\n\n /**\n * Drop a tenant schema\n */\n async dropTenant(tenantId: string, options: DropTenantOptions = {}): Promise<void> {\n const { cascade = true } = options;\n const schemaName = this.tenantConfig.isolation.schemaNameTemplate(tenantId);\n\n const pool = new Pool({\n connectionString: this.tenantConfig.connection.url,\n ...this.tenantConfig.connection.poolConfig,\n });\n\n try {\n const cascadeSql = cascade ? 'CASCADE' : 'RESTRICT';\n await pool.query(`DROP SCHEMA IF EXISTS \"${schemaName}\" ${cascadeSql}`);\n } finally {\n await pool.end();\n }\n }\n\n /**\n * Check if a tenant schema exists\n */\n async tenantExists(tenantId: string): Promise<boolean> {\n const schemaName = this.tenantConfig.isolation.schemaNameTemplate(tenantId);\n\n const pool = new Pool({\n connectionString: this.tenantConfig.connection.url,\n ...this.tenantConfig.connection.poolConfig,\n });\n\n try {\n const result = await pool.query(\n `SELECT 1 FROM information_schema.schemata WHERE schema_name = $1`,\n [schemaName]\n );\n return result.rowCount !== null && result.rowCount > 0;\n } finally {\n await pool.end();\n }\n }\n\n /**\n * Load migration files from the migrations folder\n */\n private async loadMigrations(): Promise<MigrationFile[]> {\n const files = await readdir(this.migratorConfig.migrationsFolder);\n\n const migrations: MigrationFile[] = [];\n\n for (const file of files) {\n if (!file.endsWith('.sql')) continue;\n\n const filePath = join(this.migratorConfig.migrationsFolder, file);\n const content = await readFile(filePath, 'utf-8');\n\n // Extract timestamp from filename (e.g., 0001_migration_name.sql)\n const match = file.match(/^(\\d+)_/);\n const timestamp = match?.[1] ? parseInt(match[1], 10) : 0;\n\n // Compute SHA-256 hash for drizzle-kit compatibility\n const hash = createHash('sha256').update(content).digest('hex');\n\n migrations.push({\n name: basename(file, '.sql'),\n path: filePath,\n sql: content,\n timestamp,\n hash,\n });\n }\n\n // Sort by timestamp\n return migrations.sort((a, b) => a.timestamp - b.timestamp);\n }\n\n /**\n * Create a pool for a specific schema\n */\n private async createPool(schemaName: string): Promise<Pool> {\n return new Pool({\n connectionString: this.tenantConfig.connection.url,\n ...this.tenantConfig.connection.poolConfig,\n options: `-c search_path=\"${schemaName}\",public`,\n });\n }\n\n /**\n * Ensure migrations table exists with the correct format\n */\n private async ensureMigrationsTable(\n pool: Pool,\n schemaName: string,\n format: DetectedFormat\n ): Promise<void> {\n const { identifier, timestamp, timestampType } = format.columns;\n\n // Build column definitions based on format\n const identifierCol = identifier === 'name'\n ? 'name VARCHAR(255) NOT NULL UNIQUE'\n : 'hash TEXT NOT NULL';\n\n const timestampCol = timestampType === 'bigint'\n ? `${timestamp} BIGINT NOT NULL`\n : `${timestamp} TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP`;\n\n await pool.query(`\n CREATE TABLE IF NOT EXISTS \"${schemaName}\".\"${format.tableName}\" (\n id SERIAL PRIMARY KEY,\n ${identifierCol},\n ${timestampCol}\n )\n `);\n }\n\n /**\n * Check if migrations table exists\n */\n private async migrationsTableExists(pool: Pool, schemaName: string): Promise<boolean> {\n const result = await pool.query(\n `SELECT 1 FROM information_schema.tables\n WHERE table_schema = $1 AND table_name = $2`,\n [schemaName, this.migrationsTable]\n );\n return result.rowCount !== null && result.rowCount > 0;\n }\n\n /**\n * Get applied migrations for a schema\n */\n private async getAppliedMigrations(\n pool: Pool,\n schemaName: string,\n format: DetectedFormat\n ): Promise<AppliedMigration[]> {\n const identifierColumn = format.columns.identifier;\n const timestampColumn = format.columns.timestamp;\n\n const result = await pool.query<{ id: number; identifier: string; applied_at: string | number }>(\n `SELECT id, \"${identifierColumn}\" as identifier, \"${timestampColumn}\" as applied_at\n FROM \"${schemaName}\".\"${format.tableName}\"\n ORDER BY id`\n );\n\n return result.rows.map((row) => {\n // Convert timestamp based on format\n const appliedAt = format.columns.timestampType === 'bigint'\n ? new Date(Number(row.applied_at))\n : new Date(row.applied_at);\n\n return {\n id: row.id,\n identifier: row.identifier,\n // Set name or hash based on format\n ...(format.columns.identifier === 'name'\n ? { name: row.identifier }\n : { hash: row.identifier }),\n appliedAt,\n };\n });\n }\n\n /**\n * Check if a migration has been applied\n */\n private isMigrationApplied(\n migration: MigrationFile,\n appliedIdentifiers: Set<string>,\n format: DetectedFormat\n ): boolean {\n if (format.columns.identifier === 'name') {\n return appliedIdentifiers.has(migration.name);\n }\n\n // Hash-based: check both hash AND name for backwards compatibility\n // This allows migration from name-based to hash-based tracking\n return appliedIdentifiers.has(migration.hash) || appliedIdentifiers.has(migration.name);\n }\n\n /**\n * Get or detect the format for a schema\n * Returns the configured format or auto-detects from existing table\n */\n private async getOrDetectFormat(\n pool: Pool,\n schemaName: string\n ): Promise<DetectedFormat> {\n const configuredFormat = this.migratorConfig.tableFormat ?? 'auto';\n\n // If not auto, return the configured format\n if (configuredFormat !== 'auto') {\n return getFormatConfig(configuredFormat, this.migrationsTable);\n }\n\n // Auto-detect from existing table\n const detected = await detectTableFormat(pool, schemaName, this.migrationsTable);\n\n if (detected) {\n return detected;\n }\n\n // No table exists, use default format\n const defaultFormat: TableFormat = this.migratorConfig.defaultFormat ?? 'name';\n return getFormatConfig(defaultFormat, this.migrationsTable);\n }\n\n /**\n * Apply a migration to a schema\n */\n private async applyMigration(\n pool: Pool,\n schemaName: string,\n migration: MigrationFile,\n format: DetectedFormat\n ): Promise<void> {\n const client = await pool.connect();\n\n try {\n await client.query('BEGIN');\n\n // Execute migration SQL\n await client.query(migration.sql);\n\n // Record migration using format-aware insert\n const { identifier, timestamp, timestampType } = format.columns;\n const identifierValue = identifier === 'name' ? migration.name : migration.hash;\n const timestampValue = timestampType === 'bigint' ? Date.now() : new Date();\n\n await client.query(\n `INSERT INTO \"${schemaName}\".\"${format.tableName}\" (\"${identifier}\", \"${timestamp}\") VALUES ($1, $2)`,\n [identifierValue, timestampValue]\n );\n\n await client.query('COMMIT');\n } catch (error) {\n await client.query('ROLLBACK');\n throw error;\n } finally {\n client.release();\n }\n }\n\n /**\n * Create a skipped result\n */\n private createSkippedResult(tenantId: string): TenantMigrationResult {\n return {\n tenantId,\n schemaName: this.tenantConfig.isolation.schemaNameTemplate(tenantId),\n success: false,\n appliedMigrations: [],\n error: 'Skipped due to abort',\n durationMs: 0,\n };\n }\n\n /**\n * Create an error result\n */\n private createErrorResult(tenantId: string, error: Error): TenantMigrationResult {\n return {\n tenantId,\n schemaName: this.tenantConfig.isolation.schemaNameTemplate(tenantId),\n success: false,\n appliedMigrations: [],\n error: error.message,\n durationMs: 0,\n };\n }\n\n /**\n * Aggregate migration results\n */\n private aggregateResults(results: TenantMigrationResult[]): MigrationResults {\n return {\n total: results.length,\n succeeded: results.filter((r) => r.success).length,\n failed: results.filter((r) => !r.success && r.error !== 'Skipped due to abort').length,\n skipped: results.filter((r) => r.error === 'Skipped due to abort').length,\n details: results,\n };\n }\n}\n\n/**\n * Create a migrator instance\n */\nexport function createMigrator<\n TTenantSchema extends Record<string, unknown>,\n TSharedSchema extends Record<string, unknown>,\n>(\n tenantConfig: Config<TTenantSchema, TSharedSchema>,\n migratorConfig: MigratorConfig\n): Migrator<TTenantSchema, TSharedSchema> {\n return new Migrator(tenantConfig, migratorConfig);\n}\n","import { sql, getTableName } from 'drizzle-orm';\nimport type { NodePgDatabase } from 'drizzle-orm/node-postgres';\nimport type { SQL, Table, Column } from 'drizzle-orm';\nimport type {\n CrossSchemaContext,\n SchemaSource,\n JoinType,\n JoinCondition,\n SharedLookupConfig,\n CrossSchemaRawOptions,\n} from './types.js';\n\n/**\n * Cross-schema query builder for joining tenant and shared data\n *\n * @example\n * ```typescript\n * const query = createCrossSchemaQuery({\n * tenantDb: tenants.getDb('tenant-uuid'),\n * sharedDb: tenants.getSharedDb(),\n * });\n *\n * const results = await query\n * .from('tenant', orders)\n * .leftJoin('shared', subscriptionPlans, eq(orders.planId, subscriptionPlans.id))\n * .select({\n * orderId: orders.id,\n * planName: subscriptionPlans.name,\n * })\n * .execute();\n * ```\n */\nexport class CrossSchemaQueryBuilder<\n TTenantSchema extends Record<string, unknown> = Record<string, unknown>,\n TSharedSchema extends Record<string, unknown> = Record<string, unknown>,\n> {\n private fromTable: { table: Table; source: SchemaSource; schemaName: string } | null = null;\n private joins: Array<{\n table: Table;\n source: SchemaSource;\n schemaName: string;\n condition: JoinCondition;\n type: JoinType;\n }> = [];\n private selectFields: Record<string, Column> = {};\n private whereCondition: SQL<unknown> | null = null;\n private orderByFields: SQL<unknown>[] = [];\n private limitValue: number | null = null;\n private offsetValue: number | null = null;\n\n constructor(private readonly context: CrossSchemaContext<TTenantSchema, TSharedSchema>) {}\n\n /**\n * Set the main table to query from\n */\n from<T extends Table>(source: SchemaSource, table: T): this {\n const schemaName = this.getSchemaName(source);\n this.fromTable = { table, source, schemaName };\n return this;\n }\n\n /**\n * Add an inner join\n */\n innerJoin<T extends Table>(source: SchemaSource, table: T, condition: JoinCondition): this {\n return this.addJoin(source, table, condition, 'inner');\n }\n\n /**\n * Add a left join\n */\n leftJoin<T extends Table>(source: SchemaSource, table: T, condition: JoinCondition): this {\n return this.addJoin(source, table, condition, 'left');\n }\n\n /**\n * Add a right join\n */\n rightJoin<T extends Table>(source: SchemaSource, table: T, condition: JoinCondition): this {\n return this.addJoin(source, table, condition, 'right');\n }\n\n /**\n * Add a full outer join\n */\n fullJoin<T extends Table>(source: SchemaSource, table: T, condition: JoinCondition): this {\n return this.addJoin(source, table, condition, 'full');\n }\n\n /**\n * Select specific fields\n */\n select<T extends Record<string, Column>>(fields: T): this {\n this.selectFields = fields;\n return this;\n }\n\n /**\n * Add a where condition\n */\n where(condition: SQL<unknown>): this {\n this.whereCondition = condition;\n return this;\n }\n\n /**\n * Add order by\n */\n orderBy(...fields: SQL<unknown>[]): this {\n this.orderByFields = fields;\n return this;\n }\n\n /**\n * Set limit\n */\n limit(value: number): this {\n this.limitValue = value;\n return this;\n }\n\n /**\n * Set offset\n */\n offset(value: number): this {\n this.offsetValue = value;\n return this;\n }\n\n /**\n * Execute the query and return typed results\n */\n async execute<TResult = Record<string, unknown>>(): Promise<TResult[]> {\n if (!this.fromTable) {\n throw new Error('[drizzle-multitenant] No table specified. Use .from() first.');\n }\n\n const sqlQuery = this.buildSql();\n\n // Use the tenant db to execute (it has access to both schemas via search_path)\n const result = await this.context.tenantDb.execute(sqlQuery);\n\n return result.rows as TResult[];\n }\n\n /**\n * Build the SQL query\n */\n private buildSql(): SQL<unknown> {\n if (!this.fromTable) {\n throw new Error('[drizzle-multitenant] No table specified');\n }\n\n const parts: SQL<unknown>[] = [];\n\n // SELECT clause\n const selectParts = Object.entries(this.selectFields).map(([alias, column]) => {\n const columnName = column.name;\n return sql`${sql.raw(`\"${columnName}\"`)} as ${sql.raw(`\"${alias}\"`)}`;\n });\n\n if (selectParts.length === 0) {\n parts.push(sql`SELECT *`);\n } else {\n parts.push(sql`SELECT ${sql.join(selectParts, sql`, `)}`);\n }\n\n // FROM clause\n const fromTableRef = this.getFullTableName(this.fromTable.schemaName, this.fromTable.table);\n parts.push(sql` FROM ${sql.raw(fromTableRef)}`);\n\n // JOIN clauses\n for (const join of this.joins) {\n const joinTableRef = this.getFullTableName(join.schemaName, join.table);\n const joinType = this.getJoinKeyword(join.type);\n parts.push(sql` ${sql.raw(joinType)} ${sql.raw(joinTableRef)} ON ${join.condition}`);\n }\n\n // WHERE clause\n if (this.whereCondition) {\n parts.push(sql` WHERE ${this.whereCondition}`);\n }\n\n // ORDER BY clause\n if (this.orderByFields.length > 0) {\n parts.push(sql` ORDER BY ${sql.join(this.orderByFields, sql`, `)}`);\n }\n\n // LIMIT clause\n if (this.limitValue !== null) {\n parts.push(sql` LIMIT ${sql.raw(this.limitValue.toString())}`);\n }\n\n // OFFSET clause\n if (this.offsetValue !== null) {\n parts.push(sql` OFFSET ${sql.raw(this.offsetValue.toString())}`);\n }\n\n return sql.join(parts, sql``);\n }\n\n /**\n * Add a join to the query\n */\n private addJoin<T extends Table>(\n source: SchemaSource,\n table: T,\n condition: JoinCondition,\n type: JoinType\n ): this {\n const schemaName = this.getSchemaName(source);\n this.joins.push({ table, source, schemaName, condition, type });\n return this;\n }\n\n /**\n * Get schema name for a source\n */\n private getSchemaName(source: SchemaSource): string {\n if (source === 'tenant') {\n return this.context.tenantSchema ?? 'tenant';\n }\n return this.context.sharedSchema ?? 'public';\n }\n\n /**\n * Get fully qualified table name\n */\n private getFullTableName(schemaName: string, table: Table): string {\n const tableName = getTableName(table);\n return `\"${schemaName}\".\"${tableName}\"`;\n }\n\n /**\n * Get SQL keyword for join type\n */\n private getJoinKeyword(type: JoinType): string {\n switch (type) {\n case 'inner':\n return 'INNER JOIN';\n case 'left':\n return 'LEFT JOIN';\n case 'right':\n return 'RIGHT JOIN';\n case 'full':\n return 'FULL OUTER JOIN';\n }\n }\n}\n\n/**\n * Create a cross-schema query builder\n */\nexport function createCrossSchemaQuery<\n TTenantSchema extends Record<string, unknown> = Record<string, unknown>,\n TSharedSchema extends Record<string, unknown> = Record<string, unknown>,\n>(\n context: CrossSchemaContext<TTenantSchema, TSharedSchema>\n): CrossSchemaQueryBuilder<TTenantSchema, TSharedSchema> {\n return new CrossSchemaQueryBuilder(context);\n}\n\n/**\n * Helper for common pattern: tenant table with shared lookup\n *\n * @example\n * ```typescript\n * const ordersWithPlans = await withSharedLookup({\n * tenantDb,\n * sharedDb,\n * tenantTable: orders,\n * sharedTable: subscriptionPlans,\n * foreignKey: 'planId',\n * sharedFields: ['name', 'features', 'price'],\n * });\n * ```\n */\nexport async function withSharedLookup<\n TTenantTable extends Table,\n TSharedTable extends Table,\n TSharedFields extends keyof TSharedTable['_']['columns'],\n>(config: SharedLookupConfig<TTenantTable, TSharedTable, TSharedFields>): Promise<Array<Record<string, unknown>>> {\n const {\n tenantDb,\n tenantTable,\n sharedTable,\n foreignKey,\n sharedKey = 'id' as keyof TSharedTable['_']['columns'],\n sharedFields,\n where: whereCondition,\n } = config;\n\n // Get table names using Drizzle's utility\n const tenantTableName = getTableName(tenantTable);\n const sharedTableName = getTableName(sharedTable);\n\n // Build field list for shared table\n const sharedFieldList = sharedFields\n .map((field) => `s.\"${String(field)}\"`)\n .join(', ');\n\n // Build the query\n const queryParts = [\n `SELECT t.*, ${sharedFieldList}`,\n `FROM \"${tenantTableName}\" t`,\n `LEFT JOIN \"public\".\"${sharedTableName}\" s ON t.\"${String(foreignKey)}\" = s.\"${String(sharedKey)}\"`,\n ];\n\n if (whereCondition) {\n queryParts.push('WHERE');\n // We'll need to use raw SQL for the where condition\n }\n\n const sqlQuery = sql.raw(queryParts.join(' '));\n\n const result = await tenantDb.execute(sqlQuery);\n\n return result.rows as Array<Record<string, unknown>>;\n}\n\n/**\n * Execute raw cross-schema SQL with type safety\n *\n * @example\n * ```typescript\n * const result = await crossSchemaRaw<{ userName: string; planName: string }>({\n * tenantSchema: 'tenant_abc123',\n * sharedSchema: 'public',\n * sql: `\n * SELECT u.name as \"userName\", p.name as \"planName\"\n * FROM $tenant.users u\n * JOIN $shared.plans p ON u.plan_id = p.id\n * `,\n * });\n * ```\n */\nexport async function crossSchemaRaw<TResult = Record<string, unknown>>(\n db: NodePgDatabase<Record<string, unknown>>,\n options: CrossSchemaRawOptions\n): Promise<TResult[]> {\n const { tenantSchema, sharedSchema, sql: rawSql } = options;\n\n // Replace $tenant and $shared placeholders\n const processedSql = rawSql\n .replace(/\\$tenant\\./g, `\"${tenantSchema}\".`)\n .replace(/\\$shared\\./g, `\"${sharedSchema}\".`);\n\n const query = sql.raw(processedSql);\n\n const result = await db.execute(query);\n\n return result.rows as TResult[];\n}\n\n/**\n * Create a typed cross-schema query using SQL template\n *\n * @example\n * ```typescript\n * const users = await crossSchemaSelect(tenantDb, {\n * tenantSchema: 'tenant_abc',\n * sharedSchema: 'public',\n * select: {\n * id: users.id,\n * name: users.name,\n * planName: plans.name,\n * },\n * from: { table: users, schema: 'tenant' },\n * joins: [\n * { table: plans, schema: 'shared', on: eq(users.planId, plans.id), type: 'left' },\n * ],\n * });\n * ```\n */\nexport function buildCrossSchemaSelect<T extends Record<string, Column>>(\n fields: T,\n tenantSchema: string,\n _sharedSchema: string\n): { columns: string[]; getSchema: () => string } {\n const columns = Object.entries(fields).map(([alias, column]) => {\n const columnName = column.name;\n return `\"${columnName}\" as \"${alias}\"`;\n });\n\n const getSchema = (): string => {\n // This would need more context to determine which schema a column belongs to\n // For now, return tenant schema as default\n return tenantSchema;\n };\n\n return { columns, getSchema };\n}\n"]}
1
+ {"version":3,"sources":["../src/config.ts","../src/types.ts","../src/debug.ts","../src/retry.ts","../src/pool.ts","../src/manager.ts","../src/context.ts","../src/migrator/table-format.ts","../src/migrator/migrator.ts","../src/cross-schema/cross-schema.ts","../src/cross-schema/with-shared.ts"],"names":["Pool","join","sql","getTableName"],"mappings":"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","file":"index.js","sourcesContent":["import type { Config } from './types.js';\n\n/**\n * Define configuration for drizzle-multitenant\n *\n * @example\n * ```typescript\n * import { defineConfig } from 'drizzle-multitenant';\n * import * as tenantSchema from './schemas/tenant';\n * import * as sharedSchema from './schemas/shared';\n *\n * export default defineConfig({\n * connection: {\n * url: process.env.DATABASE_URL!,\n * poolConfig: {\n * max: 10,\n * idleTimeoutMillis: 30000,\n * },\n * },\n * isolation: {\n * strategy: 'schema',\n * schemaNameTemplate: (tenantId) => `tenant_${tenantId.replace(/-/g, '_')}`,\n * maxPools: 50,\n * poolTtlMs: 60 * 60 * 1000,\n * },\n * schemas: {\n * tenant: tenantSchema,\n * shared: sharedSchema,\n * },\n * });\n * ```\n */\nexport function defineConfig<\n TTenantSchema extends Record<string, unknown>,\n TSharedSchema extends Record<string, unknown> = Record<string, unknown>,\n>(config: Config<TTenantSchema, TSharedSchema>): Config<TTenantSchema, TSharedSchema> {\n validateConfig(config);\n return config;\n}\n\n/**\n * Validate configuration at runtime\n */\nfunction validateConfig<\n TTenantSchema extends Record<string, unknown>,\n TSharedSchema extends Record<string, unknown>,\n>(config: Config<TTenantSchema, TSharedSchema>): void {\n // Connection validation\n if (!config.connection.url) {\n throw new Error('[drizzle-multitenant] connection.url is required');\n }\n\n // Isolation validation\n if (!config.isolation.strategy) {\n throw new Error('[drizzle-multitenant] isolation.strategy is required');\n }\n\n if (config.isolation.strategy !== 'schema') {\n throw new Error(\n `[drizzle-multitenant] isolation.strategy \"${config.isolation.strategy}\" is not yet supported. Only \"schema\" is currently available.`\n );\n }\n\n if (!config.isolation.schemaNameTemplate) {\n throw new Error('[drizzle-multitenant] isolation.schemaNameTemplate is required');\n }\n\n if (typeof config.isolation.schemaNameTemplate !== 'function') {\n throw new Error('[drizzle-multitenant] isolation.schemaNameTemplate must be a function');\n }\n\n // Schema validation\n if (!config.schemas.tenant) {\n throw new Error('[drizzle-multitenant] schemas.tenant is required');\n }\n\n // Pool limits validation\n if (config.isolation.maxPools !== undefined && config.isolation.maxPools < 1) {\n throw new Error('[drizzle-multitenant] isolation.maxPools must be at least 1');\n }\n\n if (config.isolation.poolTtlMs !== undefined && config.isolation.poolTtlMs < 0) {\n throw new Error('[drizzle-multitenant] isolation.poolTtlMs must be non-negative');\n }\n\n // Retry config validation\n if (config.connection.retry) {\n const retry = config.connection.retry;\n\n if (retry.maxAttempts !== undefined && retry.maxAttempts < 1) {\n throw new Error('[drizzle-multitenant] connection.retry.maxAttempts must be at least 1');\n }\n\n if (retry.initialDelayMs !== undefined && retry.initialDelayMs < 0) {\n throw new Error('[drizzle-multitenant] connection.retry.initialDelayMs must be non-negative');\n }\n\n if (retry.maxDelayMs !== undefined && retry.maxDelayMs < 0) {\n throw new Error('[drizzle-multitenant] connection.retry.maxDelayMs must be non-negative');\n }\n\n if (retry.backoffMultiplier !== undefined && retry.backoffMultiplier < 1) {\n throw new Error('[drizzle-multitenant] connection.retry.backoffMultiplier must be at least 1');\n }\n\n if (\n retry.initialDelayMs !== undefined &&\n retry.maxDelayMs !== undefined &&\n retry.initialDelayMs > retry.maxDelayMs\n ) {\n throw new Error(\n '[drizzle-multitenant] connection.retry.initialDelayMs cannot be greater than maxDelayMs'\n );\n }\n }\n}\n","import type { Pool, PoolConfig } from 'pg';\nimport type { NodePgDatabase } from 'drizzle-orm/node-postgres';\n\n/**\n * Isolation strategy for multi-tenancy\n */\nexport type IsolationStrategy = 'schema' | 'database' | 'row';\n\n/**\n * Retry configuration for connection attempts\n */\nexport interface RetryConfig {\n /** Maximum number of retry attempts (default: 3) */\n maxAttempts?: number;\n /** Initial delay in milliseconds before first retry (default: 100) */\n initialDelayMs?: number;\n /** Maximum delay in milliseconds between retries (default: 5000) */\n maxDelayMs?: number;\n /** Multiplier for exponential backoff (default: 2) */\n backoffMultiplier?: number;\n /** Whether to add jitter to delays to avoid thundering herd (default: true) */\n jitter?: boolean;\n /** Custom function to determine if an error is retryable */\n isRetryable?: (error: Error) => boolean;\n /** Called on each retry attempt */\n onRetry?: (attempt: number, error: Error, delayMs: number) => void;\n}\n\n/**\n * Connection configuration\n */\nexport interface ConnectionConfig {\n /** PostgreSQL connection URL */\n url: string;\n /** Pool configuration options */\n poolConfig?: Omit<PoolConfig, 'connectionString'>;\n /** Retry configuration for connection failures */\n retry?: RetryConfig;\n}\n\n/**\n * Isolation configuration\n */\nexport interface IsolationConfig {\n /** Isolation strategy (currently only 'schema' is supported) */\n strategy: IsolationStrategy;\n /** Function to generate schema name from tenant ID */\n schemaNameTemplate: (tenantId: string) => string;\n /** Maximum number of simultaneous pools (LRU eviction) */\n maxPools?: number;\n /** TTL in milliseconds before pool cleanup */\n poolTtlMs?: number;\n}\n\n/**\n * Schema definitions\n */\nexport interface SchemasConfig<\n TTenantSchema extends Record<string, unknown> = Record<string, unknown>,\n TSharedSchema extends Record<string, unknown> = Record<string, unknown>,\n> {\n /** Schema applied per tenant */\n tenant: TTenantSchema;\n /** Shared schema (public) */\n shared?: TSharedSchema;\n}\n\n/**\n * Lifecycle hooks\n */\nexport interface Hooks {\n /** Called when a new pool is created */\n onPoolCreated?: (tenantId: string) => void | Promise<void>;\n /** Called when a pool is evicted */\n onPoolEvicted?: (tenantId: string) => void | Promise<void>;\n /** Called on pool error */\n onError?: (tenantId: string, error: Error) => void | Promise<void>;\n}\n\n/**\n * Metrics configuration\n */\nexport interface MetricsConfig {\n /** Enable metrics collection */\n enabled: boolean;\n /** Prefix for metric names */\n prefix?: string;\n}\n\n/**\n * Debug configuration for development and troubleshooting\n */\nexport interface DebugConfig {\n /** Enable debug mode */\n enabled: boolean;\n /** Log SQL queries with tenant context */\n logQueries?: boolean;\n /** Log pool lifecycle events (created, evicted) */\n logPoolEvents?: boolean;\n /** Threshold in ms to log slow queries (default: 1000) */\n slowQueryThreshold?: number;\n /** Custom logger function (default: console.log) */\n logger?: (message: string, context?: DebugContext) => void;\n}\n\n/**\n * Context passed to debug logger\n */\nexport interface DebugContext {\n /** Event type */\n type: 'query' | 'slow_query' | 'pool_created' | 'pool_evicted' | 'pool_error' | 'warmup' | 'connection_retry';\n /** Tenant ID */\n tenantId?: string;\n /** Schema name */\n schemaName?: string;\n /** SQL query (for query events) */\n query?: string;\n /** Query duration in ms */\n durationMs?: number;\n /** Error message */\n error?: string;\n /** Additional metadata */\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Main configuration interface\n */\nexport interface Config<\n TTenantSchema extends Record<string, unknown> = Record<string, unknown>,\n TSharedSchema extends Record<string, unknown> = Record<string, unknown>,\n> {\n /** Database connection settings */\n connection: ConnectionConfig;\n /** Tenant isolation settings */\n isolation: IsolationConfig;\n /** Drizzle schemas */\n schemas: SchemasConfig<TTenantSchema, TSharedSchema>;\n /** Lifecycle hooks */\n hooks?: Hooks;\n /** Metrics configuration */\n metrics?: MetricsConfig;\n /** Debug configuration */\n debug?: DebugConfig;\n}\n\n/**\n * Internal pool entry for LRU cache\n */\nexport interface PoolEntry<TSchema extends Record<string, unknown> = Record<string, unknown>> {\n /** Drizzle database instance */\n db: NodePgDatabase<TSchema>;\n /** PostgreSQL pool */\n pool: Pool;\n /** Last access timestamp */\n lastAccess: number;\n /** Schema name */\n schemaName: string;\n}\n\n/**\n * Type for tenant database instance\n */\nexport type TenantDb<TSchema extends Record<string, unknown> = Record<string, unknown>> =\n NodePgDatabase<TSchema>;\n\n/**\n * Type for shared database instance\n */\nexport type SharedDb<TSchema extends Record<string, unknown> = Record<string, unknown>> =\n NodePgDatabase<TSchema>;\n\n/**\n * Options for pool warmup\n */\nexport interface WarmupOptions {\n /** Number of concurrent warmup operations */\n concurrency?: number;\n /** Execute a ping query to verify connection */\n ping?: boolean;\n /** Callback for progress updates */\n onProgress?: (tenantId: string, status: 'starting' | 'completed' | 'failed') => void;\n}\n\n/**\n * Result for a single tenant warmup\n */\nexport interface TenantWarmupResult {\n tenantId: string;\n success: boolean;\n /** Whether the pool was already warm */\n alreadyWarm: boolean;\n durationMs: number;\n error?: string;\n}\n\n/**\n * Aggregate warmup results\n */\nexport interface WarmupResult {\n total: number;\n succeeded: number;\n failed: number;\n alreadyWarm: number;\n durationMs: number;\n details: TenantWarmupResult[];\n}\n\n/**\n * Tenant manager interface\n */\nexport interface TenantManager<\n TTenantSchema extends Record<string, unknown> = Record<string, unknown>,\n TSharedSchema extends Record<string, unknown> = Record<string, unknown>,\n> {\n /** Get database instance for a specific tenant (sync, no validation) */\n getDb(tenantId: string): TenantDb<TTenantSchema>;\n /** Get database instance for a specific tenant with retry and validation */\n getDbAsync(tenantId: string): Promise<TenantDb<TTenantSchema>>;\n /** Get shared database instance (sync, no validation) */\n getSharedDb(): SharedDb<TSharedSchema>;\n /** Get shared database instance with retry and validation */\n getSharedDbAsync(): Promise<SharedDb<TSharedSchema>>;\n /** Get the schema name for a tenant */\n getSchemaName(tenantId: string): string;\n /** Check if a tenant pool exists */\n hasPool(tenantId: string): boolean;\n /** Get active pool count */\n getPoolCount(): number;\n /** Get all active tenant IDs */\n getActiveTenantIds(): string[];\n /** Get the retry configuration */\n getRetryConfig(): Required<RetryConfig>;\n /** Manually evict a tenant pool */\n evictPool(tenantId: string): Promise<void>;\n /** Pre-warm pools for specified tenants to reduce cold start latency */\n warmup(tenantIds: string[], options?: WarmupOptions): Promise<WarmupResult>;\n /** Dispose all pools and cleanup */\n dispose(): Promise<void>;\n}\n\n/**\n * Default configuration values\n */\nexport const DEFAULT_CONFIG = {\n maxPools: 50,\n poolTtlMs: 60 * 60 * 1000, // 1 hour\n cleanupIntervalMs: 60_000, // 1 minute\n poolConfig: {\n max: 10,\n idleTimeoutMillis: 30_000,\n connectionTimeoutMillis: 5_000,\n },\n retry: {\n maxAttempts: 3,\n initialDelayMs: 100,\n maxDelayMs: 5_000,\n backoffMultiplier: 2,\n jitter: true,\n },\n} as const;\n","import type { DebugConfig, DebugContext } from './types.js';\n\nconst PREFIX = '[drizzle-multitenant]';\nconst DEFAULT_SLOW_QUERY_THRESHOLD = 1000;\n\n/**\n * Debug logger for drizzle-multitenant\n * Provides structured logging for queries, pool events, and performance monitoring\n */\nexport class DebugLogger {\n private readonly enabled: boolean;\n private readonly logQueries: boolean;\n private readonly logPoolEvents: boolean;\n private readonly slowQueryThreshold: number;\n private readonly logger: (message: string, context?: DebugContext) => void;\n\n constructor(config?: DebugConfig) {\n this.enabled = config?.enabled ?? false;\n this.logQueries = config?.logQueries ?? true;\n this.logPoolEvents = config?.logPoolEvents ?? true;\n this.slowQueryThreshold = config?.slowQueryThreshold ?? DEFAULT_SLOW_QUERY_THRESHOLD;\n this.logger = config?.logger ?? this.defaultLogger;\n }\n\n /**\n * Check if debug mode is enabled\n */\n isEnabled(): boolean {\n return this.enabled;\n }\n\n /**\n * Log a query execution\n */\n logQuery(tenantId: string, query: string, durationMs: number): void {\n if (!this.enabled || !this.logQueries) return;\n\n const isSlowQuery = durationMs >= this.slowQueryThreshold;\n const type = isSlowQuery ? 'slow_query' : 'query';\n\n const context: DebugContext = {\n type,\n tenantId,\n query: this.truncateQuery(query),\n durationMs,\n };\n\n if (isSlowQuery) {\n this.logger(\n `${PREFIX} tenant=${tenantId} SLOW_QUERY duration=${durationMs}ms query=\"${this.truncateQuery(query)}\"`,\n context\n );\n } else {\n this.logger(\n `${PREFIX} tenant=${tenantId} query=\"${this.truncateQuery(query)}\" duration=${durationMs}ms`,\n context\n );\n }\n }\n\n /**\n * Log pool creation\n */\n logPoolCreated(tenantId: string, schemaName: string): void {\n if (!this.enabled || !this.logPoolEvents) return;\n\n const context: DebugContext = {\n type: 'pool_created',\n tenantId,\n schemaName,\n };\n\n this.logger(\n `${PREFIX} tenant=${tenantId} POOL_CREATED schema=${schemaName}`,\n context\n );\n }\n\n /**\n * Log pool eviction\n */\n logPoolEvicted(tenantId: string, schemaName: string, reason?: string): void {\n if (!this.enabled || !this.logPoolEvents) return;\n\n const context: DebugContext = {\n type: 'pool_evicted',\n tenantId,\n schemaName,\n metadata: reason ? { reason } : undefined,\n };\n\n const reasonStr = reason ? ` reason=${reason}` : '';\n this.logger(\n `${PREFIX} tenant=${tenantId} POOL_EVICTED schema=${schemaName}${reasonStr}`,\n context\n );\n }\n\n /**\n * Log pool error\n */\n logPoolError(tenantId: string, error: Error): void {\n if (!this.enabled || !this.logPoolEvents) return;\n\n const context: DebugContext = {\n type: 'pool_error',\n tenantId,\n error: error.message,\n };\n\n this.logger(\n `${PREFIX} tenant=${tenantId} POOL_ERROR error=\"${error.message}\"`,\n context\n );\n }\n\n /**\n * Log warmup event\n */\n logWarmup(tenantId: string, success: boolean, durationMs: number, alreadyWarm: boolean): void {\n if (!this.enabled || !this.logPoolEvents) return;\n\n const context: DebugContext = {\n type: 'warmup',\n tenantId,\n durationMs,\n metadata: { success, alreadyWarm },\n };\n\n const status = alreadyWarm ? 'already_warm' : (success ? 'success' : 'failed');\n this.logger(\n `${PREFIX} tenant=${tenantId} WARMUP status=${status} duration=${durationMs}ms`,\n context\n );\n }\n\n /**\n * Log connection retry event\n */\n logConnectionRetry(\n identifier: string,\n attempt: number,\n maxAttempts: number,\n error: Error,\n delayMs: number\n ): void {\n if (!this.enabled || !this.logPoolEvents) return;\n\n const context: DebugContext = {\n type: 'connection_retry',\n tenantId: identifier,\n error: error.message,\n metadata: { attempt, maxAttempts, delayMs },\n };\n\n this.logger(\n `${PREFIX} tenant=${identifier} CONNECTION_RETRY attempt=${attempt}/${maxAttempts} delay=${delayMs}ms error=\"${error.message}\"`,\n context\n );\n }\n\n /**\n * Log connection success after retries\n */\n logConnectionSuccess(identifier: string, attempts: number, totalTimeMs: number): void {\n if (!this.enabled || !this.logPoolEvents) return;\n\n const context: DebugContext = {\n type: 'pool_created',\n tenantId: identifier,\n durationMs: totalTimeMs,\n metadata: { attempts },\n };\n\n if (attempts > 1) {\n this.logger(\n `${PREFIX} tenant=${identifier} CONNECTION_SUCCESS attempts=${attempts} totalTime=${totalTimeMs}ms`,\n context\n );\n }\n }\n\n /**\n * Log a custom debug message\n */\n log(message: string, context?: Partial<DebugContext>): void {\n if (!this.enabled) return;\n\n this.logger(`${PREFIX} ${message}`, context as DebugContext);\n }\n\n /**\n * Default logger implementation using console\n */\n private defaultLogger(message: string, _context?: DebugContext): void {\n console.log(message);\n }\n\n /**\n * Truncate long queries for readability\n */\n private truncateQuery(query: string, maxLength = 100): string {\n const normalized = query.replace(/\\s+/g, ' ').trim();\n if (normalized.length <= maxLength) {\n return normalized;\n }\n return normalized.substring(0, maxLength - 3) + '...';\n }\n}\n\n/**\n * Create a debug logger instance\n */\nexport function createDebugLogger(config?: DebugConfig): DebugLogger {\n return new DebugLogger(config);\n}\n","import type { RetryConfig } from './types.js';\nimport { DEFAULT_CONFIG } from './types.js';\n\n/**\n * Default function to determine if an error is retryable\n * Focuses on transient connection errors\n */\nexport function isRetryableError(error: Error): boolean {\n const message = error.message.toLowerCase();\n\n // Connection errors\n if (\n message.includes('econnrefused') ||\n message.includes('econnreset') ||\n message.includes('etimedout') ||\n message.includes('enotfound') ||\n message.includes('connection refused') ||\n message.includes('connection reset') ||\n message.includes('connection terminated') ||\n message.includes('connection timed out') ||\n message.includes('timeout expired') ||\n message.includes('socket hang up')\n ) {\n return true;\n }\n\n // PostgreSQL specific transient errors\n if (\n message.includes('too many connections') ||\n message.includes('sorry, too many clients') ||\n message.includes('the database system is starting up') ||\n message.includes('the database system is shutting down') ||\n message.includes('server closed the connection unexpectedly') ||\n message.includes('could not connect to server')\n ) {\n return true;\n }\n\n // SSL/TLS errors that might be transient\n if (\n message.includes('ssl connection') ||\n message.includes('ssl handshake')\n ) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Calculate delay with exponential backoff and optional jitter\n */\nexport function calculateDelay(\n attempt: number,\n config: Required<Pick<RetryConfig, 'initialDelayMs' | 'maxDelayMs' | 'backoffMultiplier' | 'jitter'>>\n): number {\n // Exponential backoff: initialDelay * (multiplier ^ attempt)\n const exponentialDelay = config.initialDelayMs * Math.pow(config.backoffMultiplier, attempt);\n\n // Cap at maxDelay\n const cappedDelay = Math.min(exponentialDelay, config.maxDelayMs);\n\n // Add jitter to avoid thundering herd\n if (config.jitter) {\n // Random jitter between 0% and 25% of the delay\n const jitterFactor = 1 + Math.random() * 0.25;\n return Math.floor(cappedDelay * jitterFactor);\n }\n\n return Math.floor(cappedDelay);\n}\n\n/**\n * Sleep for a given number of milliseconds\n */\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Retry result with metadata\n */\nexport interface RetryResult<T> {\n /** The result value if successful */\n result: T;\n /** Number of attempts made (1 = first try succeeded) */\n attempts: number;\n /** Total time spent including retries in ms */\n totalTimeMs: number;\n}\n\n/**\n * Retry an async operation with exponential backoff\n *\n * @example\n * ```typescript\n * const result = await withRetry(\n * () => pool.connect(),\n * {\n * maxAttempts: 3,\n * initialDelayMs: 100,\n * maxDelayMs: 5000,\n * backoffMultiplier: 2,\n * onRetry: (attempt, error, delay) => {\n * console.log(`Retry ${attempt} after ${delay}ms: ${error.message}`);\n * },\n * }\n * );\n * ```\n */\nexport async function withRetry<T>(\n operation: () => Promise<T>,\n config?: RetryConfig\n): Promise<RetryResult<T>> {\n const retryConfig = {\n maxAttempts: config?.maxAttempts ?? DEFAULT_CONFIG.retry.maxAttempts,\n initialDelayMs: config?.initialDelayMs ?? DEFAULT_CONFIG.retry.initialDelayMs,\n maxDelayMs: config?.maxDelayMs ?? DEFAULT_CONFIG.retry.maxDelayMs,\n backoffMultiplier: config?.backoffMultiplier ?? DEFAULT_CONFIG.retry.backoffMultiplier,\n jitter: config?.jitter ?? DEFAULT_CONFIG.retry.jitter,\n isRetryable: config?.isRetryable ?? isRetryableError,\n onRetry: config?.onRetry,\n };\n\n const startTime = Date.now();\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt < retryConfig.maxAttempts; attempt++) {\n try {\n const result = await operation();\n return {\n result,\n attempts: attempt + 1,\n totalTimeMs: Date.now() - startTime,\n };\n } catch (error) {\n lastError = error as Error;\n\n // Check if this is the last attempt\n const isLastAttempt = attempt >= retryConfig.maxAttempts - 1;\n\n // Check if error is retryable\n if (isLastAttempt || !retryConfig.isRetryable(lastError)) {\n throw lastError;\n }\n\n // Calculate delay for this attempt\n const delay = calculateDelay(attempt, retryConfig);\n\n // Call onRetry hook\n retryConfig.onRetry?.(attempt + 1, lastError, delay);\n\n // Wait before next attempt\n await sleep(delay);\n }\n }\n\n // This should never be reached, but TypeScript needs it\n throw lastError ?? new Error('Retry failed with no error');\n}\n\n/**\n * Create a retry wrapper with pre-configured options\n *\n * @example\n * ```typescript\n * const retrier = createRetrier({\n * maxAttempts: 5,\n * initialDelayMs: 200,\n * });\n *\n * // Use the same config for multiple operations\n * const result1 = await retrier(() => connectToDb());\n * const result2 = await retrier(() => fetchData());\n * ```\n */\nexport function createRetrier(config: RetryConfig) {\n return <T>(operation: () => Promise<T>): Promise<RetryResult<T>> => {\n return withRetry(operation, config);\n };\n}\n","import { Pool } from 'pg';\nimport { drizzle } from 'drizzle-orm/node-postgres';\nimport { LRUCache } from 'lru-cache';\nimport type {\n Config,\n PoolEntry,\n TenantDb,\n SharedDb,\n WarmupOptions,\n WarmupResult,\n TenantWarmupResult,\n RetryConfig,\n} from './types.js';\nimport { DEFAULT_CONFIG as defaults } from './types.js';\nimport { createDebugLogger, DebugLogger } from './debug.js';\nimport { withRetry, isRetryableError } from './retry.js';\n\n/**\n * Pool manager that handles tenant database connections with LRU eviction\n */\nexport class PoolManager<\n TTenantSchema extends Record<string, unknown>,\n TSharedSchema extends Record<string, unknown>,\n> {\n private readonly pools: LRUCache<string, PoolEntry<TTenantSchema>>;\n private readonly tenantIdBySchema: Map<string, string> = new Map();\n private readonly pendingConnections: Map<string, Promise<PoolEntry<TTenantSchema>>> = new Map();\n private sharedPool: Pool | null = null;\n private sharedDb: SharedDb<TSharedSchema> | null = null;\n private sharedDbPending: Promise<SharedDb<TSharedSchema>> | null = null;\n private cleanupInterval: ReturnType<typeof setInterval> | null = null;\n private disposed = false;\n private readonly debugLogger: DebugLogger;\n private readonly retryConfig: Required<RetryConfig>;\n\n constructor(private readonly config: Config<TTenantSchema, TSharedSchema>) {\n const maxPools = config.isolation.maxPools ?? defaults.maxPools;\n\n this.debugLogger = createDebugLogger(config.debug);\n\n // Initialize retry config with defaults\n const userRetry = config.connection.retry ?? {};\n this.retryConfig = {\n maxAttempts: userRetry.maxAttempts ?? defaults.retry.maxAttempts,\n initialDelayMs: userRetry.initialDelayMs ?? defaults.retry.initialDelayMs,\n maxDelayMs: userRetry.maxDelayMs ?? defaults.retry.maxDelayMs,\n backoffMultiplier: userRetry.backoffMultiplier ?? defaults.retry.backoffMultiplier,\n jitter: userRetry.jitter ?? defaults.retry.jitter,\n isRetryable: userRetry.isRetryable ?? isRetryableError,\n onRetry: userRetry.onRetry,\n };\n\n this.pools = new LRUCache<string, PoolEntry<TTenantSchema>>({\n max: maxPools,\n dispose: (entry, key) => {\n this.disposePoolEntry(entry, key);\n },\n noDisposeOnSet: true,\n });\n }\n\n /**\n * Get or create a database connection for a tenant\n */\n getDb(tenantId: string): TenantDb<TTenantSchema> {\n this.ensureNotDisposed();\n\n const schemaName = this.config.isolation.schemaNameTemplate(tenantId);\n let entry = this.pools.get(schemaName);\n\n if (!entry) {\n entry = this.createPoolEntry(tenantId, schemaName);\n this.pools.set(schemaName, entry);\n this.tenantIdBySchema.set(schemaName, tenantId);\n\n // Log pool creation\n this.debugLogger.logPoolCreated(tenantId, schemaName);\n\n // Fire hook asynchronously\n void this.config.hooks?.onPoolCreated?.(tenantId);\n }\n\n entry.lastAccess = Date.now();\n return entry.db;\n }\n\n /**\n * Get or create a database connection for a tenant with retry and validation\n *\n * This async version validates the connection by executing a ping query\n * and retries on transient failures with exponential backoff.\n *\n * @example\n * ```typescript\n * // Get tenant database with automatic retry\n * const db = await manager.getDbAsync('tenant-123');\n *\n * // Queries will use the validated connection\n * const users = await db.select().from(users);\n * ```\n */\n async getDbAsync(tenantId: string): Promise<TenantDb<TTenantSchema>> {\n this.ensureNotDisposed();\n\n const schemaName = this.config.isolation.schemaNameTemplate(tenantId);\n let entry = this.pools.get(schemaName);\n\n if (entry) {\n entry.lastAccess = Date.now();\n return entry.db;\n }\n\n // Check if there's already a pending connection for this tenant\n const pending = this.pendingConnections.get(schemaName);\n if (pending) {\n entry = await pending;\n entry.lastAccess = Date.now();\n return entry.db;\n }\n\n // Create connection with retry\n const connectionPromise = this.connectWithRetry(tenantId, schemaName);\n this.pendingConnections.set(schemaName, connectionPromise);\n\n try {\n entry = await connectionPromise;\n this.pools.set(schemaName, entry);\n this.tenantIdBySchema.set(schemaName, tenantId);\n\n // Log pool creation\n this.debugLogger.logPoolCreated(tenantId, schemaName);\n\n // Fire hook asynchronously\n void this.config.hooks?.onPoolCreated?.(tenantId);\n\n entry.lastAccess = Date.now();\n return entry.db;\n } finally {\n this.pendingConnections.delete(schemaName);\n }\n }\n\n /**\n * Connect to a tenant database with retry logic\n */\n private async connectWithRetry(\n tenantId: string,\n schemaName: string\n ): Promise<PoolEntry<TTenantSchema>> {\n const maxAttempts = this.retryConfig.maxAttempts;\n\n const result = await withRetry(\n async () => {\n // Create pool entry\n const entry = this.createPoolEntry(tenantId, schemaName);\n\n try {\n // Validate connection with ping query\n await entry.pool.query('SELECT 1');\n return entry;\n } catch (error) {\n // Clean up failed pool before retrying\n try {\n await entry.pool.end();\n } catch {\n // Ignore cleanup errors\n }\n throw error;\n }\n },\n {\n ...this.retryConfig,\n onRetry: (attempt, error, delayMs) => {\n // Log retry event\n this.debugLogger.logConnectionRetry(tenantId, attempt, maxAttempts, error, delayMs);\n\n // Call user-provided onRetry hook\n this.retryConfig.onRetry?.(attempt, error, delayMs);\n },\n }\n );\n\n // Log success if multiple attempts were needed\n this.debugLogger.logConnectionSuccess(tenantId, result.attempts, result.totalTimeMs);\n\n return result.result;\n }\n\n /**\n * Get or create the shared database connection\n */\n getSharedDb(): SharedDb<TSharedSchema> {\n this.ensureNotDisposed();\n\n if (!this.sharedDb) {\n this.sharedPool = new Pool({\n connectionString: this.config.connection.url,\n ...defaults.poolConfig,\n ...this.config.connection.poolConfig,\n });\n\n this.sharedPool.on('error', (err) => {\n void this.config.hooks?.onError?.('shared', err);\n });\n\n this.sharedDb = drizzle(this.sharedPool, {\n schema: this.config.schemas.shared,\n }) as SharedDb<TSharedSchema>;\n }\n\n return this.sharedDb;\n }\n\n /**\n * Get or create the shared database connection with retry and validation\n *\n * This async version validates the connection by executing a ping query\n * and retries on transient failures with exponential backoff.\n *\n * @example\n * ```typescript\n * // Get shared database with automatic retry\n * const sharedDb = await manager.getSharedDbAsync();\n *\n * // Queries will use the validated connection\n * const plans = await sharedDb.select().from(plans);\n * ```\n */\n async getSharedDbAsync(): Promise<SharedDb<TSharedSchema>> {\n this.ensureNotDisposed();\n\n if (this.sharedDb) {\n return this.sharedDb;\n }\n\n // Check if there's already a pending connection\n if (this.sharedDbPending) {\n return this.sharedDbPending;\n }\n\n // Create connection with retry\n this.sharedDbPending = this.connectSharedWithRetry();\n\n try {\n const db = await this.sharedDbPending;\n return db;\n } finally {\n this.sharedDbPending = null;\n }\n }\n\n /**\n * Connect to shared database with retry logic\n */\n private async connectSharedWithRetry(): Promise<SharedDb<TSharedSchema>> {\n const maxAttempts = this.retryConfig.maxAttempts;\n\n const result = await withRetry(\n async () => {\n const pool = new Pool({\n connectionString: this.config.connection.url,\n ...defaults.poolConfig,\n ...this.config.connection.poolConfig,\n });\n\n try {\n // Validate connection with ping query\n await pool.query('SELECT 1');\n\n pool.on('error', (err) => {\n void this.config.hooks?.onError?.('shared', err);\n });\n\n this.sharedPool = pool;\n this.sharedDb = drizzle(pool, {\n schema: this.config.schemas.shared,\n }) as SharedDb<TSharedSchema>;\n\n return this.sharedDb;\n } catch (error) {\n // Clean up failed pool before retrying\n try {\n await pool.end();\n } catch {\n // Ignore cleanup errors\n }\n throw error;\n }\n },\n {\n ...this.retryConfig,\n onRetry: (attempt, error, delayMs) => {\n // Log retry event\n this.debugLogger.logConnectionRetry('shared', attempt, maxAttempts, error, delayMs);\n\n // Call user-provided onRetry hook\n this.retryConfig.onRetry?.(attempt, error, delayMs);\n },\n }\n );\n\n // Log success if multiple attempts were needed\n this.debugLogger.logConnectionSuccess('shared', result.attempts, result.totalTimeMs);\n\n return result.result;\n }\n\n /**\n * Get schema name for a tenant\n */\n getSchemaName(tenantId: string): string {\n return this.config.isolation.schemaNameTemplate(tenantId);\n }\n\n /**\n * Check if a pool exists for a tenant\n */\n hasPool(tenantId: string): boolean {\n const schemaName = this.config.isolation.schemaNameTemplate(tenantId);\n return this.pools.has(schemaName);\n }\n\n /**\n * Get count of active pools\n */\n getPoolCount(): number {\n return this.pools.size;\n }\n\n /**\n * Get all active tenant IDs\n */\n getActiveTenantIds(): string[] {\n return Array.from(this.tenantIdBySchema.values());\n }\n\n /**\n * Get the retry configuration\n */\n getRetryConfig(): Required<RetryConfig> {\n return { ...this.retryConfig };\n }\n\n /**\n * Pre-warm pools for specified tenants to reduce cold start latency\n *\n * Uses automatic retry with exponential backoff for connection failures.\n */\n async warmup(tenantIds: string[], options: WarmupOptions = {}): Promise<WarmupResult> {\n this.ensureNotDisposed();\n\n const startTime = Date.now();\n const { concurrency = 10, ping = true, onProgress } = options;\n const results: TenantWarmupResult[] = [];\n\n // Process in batches\n for (let i = 0; i < tenantIds.length; i += concurrency) {\n const batch = tenantIds.slice(i, i + concurrency);\n\n const batchResults = await Promise.all(\n batch.map(async (tenantId) => {\n const tenantStart = Date.now();\n onProgress?.(tenantId, 'starting');\n\n try {\n const alreadyWarm = this.hasPool(tenantId);\n\n // Use getDbAsync which includes retry logic and ping validation\n if (ping) {\n await this.getDbAsync(tenantId);\n } else {\n // For backward compatibility: sync version without ping\n this.getDb(tenantId);\n }\n\n const durationMs = Date.now() - tenantStart;\n onProgress?.(tenantId, 'completed');\n\n // Log warmup\n this.debugLogger.logWarmup(tenantId, true, durationMs, alreadyWarm);\n\n return {\n tenantId,\n success: true,\n alreadyWarm,\n durationMs,\n };\n } catch (error) {\n const durationMs = Date.now() - tenantStart;\n onProgress?.(tenantId, 'failed');\n\n // Log warmup failure\n this.debugLogger.logWarmup(tenantId, false, durationMs, false);\n\n return {\n tenantId,\n success: false,\n alreadyWarm: false,\n durationMs,\n error: (error as Error).message,\n };\n }\n })\n );\n\n results.push(...batchResults);\n }\n\n return {\n total: results.length,\n succeeded: results.filter((r) => r.success).length,\n failed: results.filter((r) => !r.success).length,\n alreadyWarm: results.filter((r) => r.alreadyWarm).length,\n durationMs: Date.now() - startTime,\n details: results,\n };\n }\n\n /**\n * Manually evict a tenant pool\n */\n async evictPool(tenantId: string, reason: string = 'manual'): Promise<void> {\n const schemaName = this.config.isolation.schemaNameTemplate(tenantId);\n const entry = this.pools.get(schemaName);\n\n if (entry) {\n // Log eviction\n this.debugLogger.logPoolEvicted(tenantId, schemaName, reason);\n\n this.pools.delete(schemaName);\n this.tenantIdBySchema.delete(schemaName);\n await this.closePool(entry.pool, tenantId);\n }\n }\n\n /**\n * Start automatic cleanup of idle pools\n */\n startCleanup(): void {\n if (this.cleanupInterval) return;\n\n const poolTtlMs = this.config.isolation.poolTtlMs ?? defaults.poolTtlMs;\n const cleanupIntervalMs = defaults.cleanupIntervalMs;\n\n this.cleanupInterval = setInterval(() => {\n void this.cleanupIdlePools(poolTtlMs);\n }, cleanupIntervalMs);\n\n // Don't prevent process exit\n this.cleanupInterval.unref();\n }\n\n /**\n * Stop automatic cleanup\n */\n stopCleanup(): void {\n if (this.cleanupInterval) {\n clearInterval(this.cleanupInterval);\n this.cleanupInterval = null;\n }\n }\n\n /**\n * Dispose all pools and cleanup resources\n */\n async dispose(): Promise<void> {\n if (this.disposed) return;\n\n this.disposed = true;\n this.stopCleanup();\n\n // Close all tenant pools\n const closePromises: Promise<void>[] = [];\n\n for (const [schemaName, entry] of this.pools.entries()) {\n const tenantId = this.tenantIdBySchema.get(schemaName);\n closePromises.push(this.closePool(entry.pool, tenantId ?? schemaName));\n }\n\n this.pools.clear();\n this.tenantIdBySchema.clear();\n\n // Close shared pool\n if (this.sharedPool) {\n closePromises.push(this.closePool(this.sharedPool, 'shared'));\n this.sharedPool = null;\n this.sharedDb = null;\n }\n\n await Promise.all(closePromises);\n }\n\n /**\n * Create a new pool entry for a tenant\n */\n private createPoolEntry(tenantId: string, schemaName: string): PoolEntry<TTenantSchema> {\n const pool = new Pool({\n connectionString: this.config.connection.url,\n ...defaults.poolConfig,\n ...this.config.connection.poolConfig,\n options: `-c search_path=${schemaName},public`,\n });\n\n pool.on('error', async (err) => {\n // Log pool error\n this.debugLogger.logPoolError(tenantId, err);\n\n void this.config.hooks?.onError?.(tenantId, err);\n await this.evictPool(tenantId, 'error');\n });\n\n const db = drizzle(pool, {\n schema: this.config.schemas.tenant,\n }) as TenantDb<TTenantSchema>;\n\n return {\n db,\n pool,\n lastAccess: Date.now(),\n schemaName,\n };\n }\n\n /**\n * Dispose a pool entry (called by LRU cache)\n */\n private disposePoolEntry(entry: PoolEntry<TTenantSchema>, schemaName: string): void {\n const tenantId = this.tenantIdBySchema.get(schemaName);\n this.tenantIdBySchema.delete(schemaName);\n\n // Log pool eviction\n if (tenantId) {\n this.debugLogger.logPoolEvicted(tenantId, schemaName, 'lru_eviction');\n }\n\n void this.closePool(entry.pool, tenantId ?? schemaName).then(() => {\n if (tenantId) {\n void this.config.hooks?.onPoolEvicted?.(tenantId);\n }\n });\n }\n\n /**\n * Close a pool gracefully\n */\n private async closePool(pool: Pool, identifier: string): Promise<void> {\n try {\n await pool.end();\n } catch (error) {\n void this.config.hooks?.onError?.(identifier, error as Error);\n }\n }\n\n /**\n * Cleanup pools that have been idle for too long\n */\n private async cleanupIdlePools(poolTtlMs: number): Promise<void> {\n const now = Date.now();\n const toEvict: string[] = [];\n\n for (const [schemaName, entry] of this.pools.entries()) {\n if (now - entry.lastAccess > poolTtlMs) {\n toEvict.push(schemaName);\n }\n }\n\n for (const schemaName of toEvict) {\n const tenantId = this.tenantIdBySchema.get(schemaName);\n if (tenantId) {\n await this.evictPool(tenantId, 'ttl_expired');\n }\n }\n }\n\n /**\n * Ensure the manager hasn't been disposed\n */\n private ensureNotDisposed(): void {\n if (this.disposed) {\n throw new Error('[drizzle-multitenant] TenantManager has been disposed');\n }\n }\n}\n","import { PoolManager } from './pool.js';\nimport type { Config, TenantManager, TenantDb, SharedDb, WarmupOptions, WarmupResult, RetryConfig } from './types.js';\n\n/**\n * Create a tenant manager instance\n *\n * @example\n * ```typescript\n * import { createTenantManager, defineConfig } from 'drizzle-multitenant';\n *\n * const config = defineConfig({\n * connection: { url: process.env.DATABASE_URL! },\n * isolation: {\n * strategy: 'schema',\n * schemaNameTemplate: (id) => `tenant_${id}`,\n * },\n * schemas: { tenant: tenantSchema },\n * });\n *\n * const tenants = createTenantManager(config);\n *\n * // Get database for a specific tenant\n * const db = tenants.getDb('tenant-uuid');\n * const users = await db.select().from(schema.users);\n *\n * // Get shared database\n * const sharedDb = tenants.getSharedDb();\n * const plans = await sharedDb.select().from(sharedSchema.plans);\n * ```\n */\nexport function createTenantManager<\n TTenantSchema extends Record<string, unknown>,\n TSharedSchema extends Record<string, unknown> = Record<string, unknown>,\n>(config: Config<TTenantSchema, TSharedSchema>): TenantManager<TTenantSchema, TSharedSchema> {\n const poolManager = new PoolManager(config);\n\n // Start automatic cleanup\n poolManager.startCleanup();\n\n return {\n getDb(tenantId: string): TenantDb<TTenantSchema> {\n return poolManager.getDb(tenantId);\n },\n\n async getDbAsync(tenantId: string): Promise<TenantDb<TTenantSchema>> {\n return poolManager.getDbAsync(tenantId);\n },\n\n getSharedDb(): SharedDb<TSharedSchema> {\n return poolManager.getSharedDb();\n },\n\n async getSharedDbAsync(): Promise<SharedDb<TSharedSchema>> {\n return poolManager.getSharedDbAsync();\n },\n\n getSchemaName(tenantId: string): string {\n return poolManager.getSchemaName(tenantId);\n },\n\n hasPool(tenantId: string): boolean {\n return poolManager.hasPool(tenantId);\n },\n\n getPoolCount(): number {\n return poolManager.getPoolCount();\n },\n\n getActiveTenantIds(): string[] {\n return poolManager.getActiveTenantIds();\n },\n\n getRetryConfig(): Required<RetryConfig> {\n return poolManager.getRetryConfig();\n },\n\n async evictPool(tenantId: string): Promise<void> {\n await poolManager.evictPool(tenantId);\n },\n\n async warmup(tenantIds: string[], options?: WarmupOptions): Promise<WarmupResult> {\n return poolManager.warmup(tenantIds, options);\n },\n\n async dispose(): Promise<void> {\n await poolManager.dispose();\n },\n };\n}\n","import { AsyncLocalStorage } from 'node:async_hooks';\nimport type { TenantManager, TenantDb, SharedDb } from './types.js';\n\n/**\n * Base tenant context data\n */\nexport interface BaseTenantContext {\n tenantId: string;\n}\n\n/**\n * Tenant context with optional custom data\n */\nexport type TenantContextData<TCustom extends Record<string, unknown> = Record<string, unknown>> =\n BaseTenantContext & TCustom;\n\n/**\n * Tenant context API\n */\nexport interface TenantContext<\n TTenantSchema extends Record<string, unknown>,\n TSharedSchema extends Record<string, unknown>,\n TCustom extends Record<string, unknown> = Record<string, unknown>,\n> {\n /**\n * Run a callback with tenant context\n */\n runWithTenant<T>(\n context: TenantContextData<TCustom>,\n callback: () => T | Promise<T>\n ): T | Promise<T>;\n\n /**\n * Get current tenant context (throws if not in context)\n */\n getTenant(): TenantContextData<TCustom>;\n\n /**\n * Get current tenant context or undefined\n */\n getTenantOrNull(): TenantContextData<TCustom> | undefined;\n\n /**\n * Get current tenant ID (throws if not in context)\n */\n getTenantId(): string;\n\n /**\n * Get database for current tenant (throws if not in context)\n */\n getTenantDb(): TenantDb<TTenantSchema>;\n\n /**\n * Get shared database\n */\n getSharedDb(): SharedDb<TSharedSchema>;\n\n /**\n * Check if currently running within a tenant context\n */\n isInTenantContext(): boolean;\n}\n\n/**\n * Create a tenant context with AsyncLocalStorage\n *\n * @example\n * ```typescript\n * import { createTenantContext, createTenantManager } from 'drizzle-multitenant';\n *\n * const manager = createTenantManager(config);\n *\n * const {\n * runWithTenant,\n * getTenant,\n * getTenantDb,\n * getSharedDb,\n * } = createTenantContext(manager);\n *\n * // Use in request handler\n * app.get('/users', async (req, res) => {\n * const tenantId = req.headers['x-tenant-id'];\n *\n * await runWithTenant({ tenantId }, async () => {\n * const db = getTenantDb();\n * const users = await db.select().from(schema.users);\n * res.json(users);\n * });\n * });\n * ```\n */\nexport function createTenantContext<\n TTenantSchema extends Record<string, unknown>,\n TSharedSchema extends Record<string, unknown> = Record<string, unknown>,\n TCustom extends Record<string, unknown> = Record<string, unknown>,\n>(\n manager: TenantManager<TTenantSchema, TSharedSchema>\n): TenantContext<TTenantSchema, TSharedSchema, TCustom> {\n const storage = new AsyncLocalStorage<TenantContextData<TCustom>>();\n\n function getTenantOrNull(): TenantContextData<TCustom> | undefined {\n return storage.getStore();\n }\n\n function getTenant(): TenantContextData<TCustom> {\n const context = getTenantOrNull();\n if (!context) {\n throw new Error(\n '[drizzle-multitenant] No tenant context found. ' +\n 'Make sure you are calling this within runWithTenant().'\n );\n }\n return context;\n }\n\n function getTenantId(): string {\n return getTenant().tenantId;\n }\n\n function getTenantDb(): TenantDb<TTenantSchema> {\n const tenantId = getTenantId();\n return manager.getDb(tenantId);\n }\n\n function getSharedDb(): SharedDb<TSharedSchema> {\n return manager.getSharedDb();\n }\n\n function isInTenantContext(): boolean {\n return getTenantOrNull() !== undefined;\n }\n\n function runWithTenant<T>(\n context: TenantContextData<TCustom>,\n callback: () => T | Promise<T>\n ): T | Promise<T> {\n if (!context.tenantId) {\n throw new Error('[drizzle-multitenant] tenantId is required in context');\n }\n return storage.run(context, callback);\n }\n\n return {\n runWithTenant,\n getTenant,\n getTenantOrNull,\n getTenantId,\n getTenantDb,\n getSharedDb,\n isInTenantContext,\n };\n}\n","import type { Pool } from 'pg';\n\n/**\n * Table format for tracking migrations\n * - \"name\": drizzle-multitenant native (filename-based)\n * - \"hash\": SHA-256 hash with timestamp\n * - \"drizzle-kit\": Exact drizzle-kit format (hash + bigint timestamp)\n */\nexport type TableFormat = 'name' | 'hash' | 'drizzle-kit';\n\n/**\n * Detected table format information\n */\nexport interface DetectedFormat {\n /** The detected format type */\n format: TableFormat;\n /** The table name */\n tableName: string;\n /** Column configuration */\n columns: {\n /** Column used for identifying migrations */\n identifier: 'name' | 'hash';\n /** Column used for timestamp */\n timestamp: 'applied_at' | 'created_at';\n /** Data type of timestamp column */\n timestampType: 'timestamp' | 'bigint';\n };\n}\n\n/**\n * Default format configuration for new tables\n */\nexport const DEFAULT_FORMAT: DetectedFormat = {\n format: 'name',\n tableName: '__drizzle_migrations',\n columns: {\n identifier: 'name',\n timestamp: 'applied_at',\n timestampType: 'timestamp',\n },\n};\n\n/**\n * drizzle-kit format configuration\n */\nexport const DRIZZLE_KIT_FORMAT: DetectedFormat = {\n format: 'drizzle-kit',\n tableName: '__drizzle_migrations',\n columns: {\n identifier: 'hash',\n timestamp: 'created_at',\n timestampType: 'bigint',\n },\n};\n\ninterface ColumnInfo {\n column_name: string;\n data_type: string;\n}\n\n/**\n * Detect the format of an existing migrations table\n *\n * @param pool - Database connection pool\n * @param schemaName - Schema to check\n * @param tableName - Migrations table name\n * @returns Detected format or null if table doesn't exist\n */\nexport async function detectTableFormat(\n pool: Pool,\n schemaName: string,\n tableName: string\n): Promise<DetectedFormat | null> {\n // Check if table exists\n const tableExists = await pool.query<{ exists: boolean }>(\n `SELECT EXISTS (\n SELECT 1 FROM information_schema.tables\n WHERE table_schema = $1 AND table_name = $2\n ) as exists`,\n [schemaName, tableName]\n );\n\n if (!tableExists.rows[0]?.exists) {\n return null;\n }\n\n // Get column information\n const columnsResult = await pool.query<ColumnInfo>(\n `SELECT column_name, data_type\n FROM information_schema.columns\n WHERE table_schema = $1 AND table_name = $2`,\n [schemaName, tableName]\n );\n\n const columnMap = new Map<string, string>(\n columnsResult.rows.map((r) => [r.column_name, r.data_type])\n );\n\n // Detect format based on columns\n if (columnMap.has('name')) {\n // drizzle-multitenant native format\n return {\n format: 'name',\n tableName,\n columns: {\n identifier: 'name',\n timestamp: columnMap.has('applied_at') ? 'applied_at' : 'created_at',\n timestampType: 'timestamp',\n },\n };\n }\n\n if (columnMap.has('hash')) {\n const createdAtType = columnMap.get('created_at');\n\n // drizzle-kit uses bigint for created_at\n if (createdAtType === 'bigint') {\n return {\n format: 'drizzle-kit',\n tableName,\n columns: {\n identifier: 'hash',\n timestamp: 'created_at',\n timestampType: 'bigint',\n },\n };\n }\n\n // Custom hash-based format with regular timestamp\n return {\n format: 'hash',\n tableName,\n columns: {\n identifier: 'hash',\n timestamp: 'created_at',\n timestampType: 'timestamp',\n },\n };\n }\n\n // Unknown format - return null to trigger error handling\n return null;\n}\n\n/**\n * Get the format configuration for a specific format type\n */\nexport function getFormatConfig(\n format: TableFormat,\n tableName: string = '__drizzle_migrations'\n): DetectedFormat {\n switch (format) {\n case 'name':\n return {\n format: 'name',\n tableName,\n columns: {\n identifier: 'name',\n timestamp: 'applied_at',\n timestampType: 'timestamp',\n },\n };\n case 'hash':\n return {\n format: 'hash',\n tableName,\n columns: {\n identifier: 'hash',\n timestamp: 'created_at',\n timestampType: 'timestamp',\n },\n };\n case 'drizzle-kit':\n return {\n format: 'drizzle-kit',\n tableName,\n columns: {\n identifier: 'hash',\n timestamp: 'created_at',\n timestampType: 'bigint',\n },\n };\n }\n}\n","import { readdir, readFile } from 'node:fs/promises';\nimport { join, basename } from 'node:path';\nimport { createHash } from 'node:crypto';\nimport { Pool } from 'pg';\nimport type { Config } from '../types.js';\nimport type {\n MigratorConfig,\n MigrationFile,\n MigrateOptions,\n TenantMigrationResult,\n MigrationResults,\n TenantMigrationStatus,\n AppliedMigration,\n CreateTenantOptions,\n DropTenantOptions,\n TenantSyncStatus,\n SyncStatus,\n TenantSyncResult,\n SyncResults,\n SyncOptions,\n} from './types.js';\nimport { detectTableFormat, getFormatConfig, type DetectedFormat, type TableFormat } from './table-format.js';\n\nconst DEFAULT_MIGRATIONS_TABLE = '__drizzle_migrations';\n\n/**\n * Parallel migration engine for multi-tenant applications\n */\nexport class Migrator<\n TTenantSchema extends Record<string, unknown>,\n TSharedSchema extends Record<string, unknown>,\n> {\n private readonly migrationsTable: string;\n\n constructor(\n private readonly tenantConfig: Config<TTenantSchema, TSharedSchema>,\n private readonly migratorConfig: MigratorConfig\n ) {\n this.migrationsTable = migratorConfig.migrationsTable ?? DEFAULT_MIGRATIONS_TABLE;\n }\n\n /**\n * Migrate all tenants in parallel\n */\n async migrateAll(options: MigrateOptions = {}): Promise<MigrationResults> {\n const {\n concurrency = 10,\n onProgress,\n onError,\n dryRun = false,\n } = options;\n\n const tenantIds = await this.migratorConfig.tenantDiscovery();\n const migrations = await this.loadMigrations();\n\n const results: TenantMigrationResult[] = [];\n let aborted = false;\n\n // Process tenants in batches\n for (let i = 0; i < tenantIds.length && !aborted; i += concurrency) {\n const batch = tenantIds.slice(i, i + concurrency);\n\n const batchResults = await Promise.all(\n batch.map(async (tenantId) => {\n if (aborted) {\n return this.createSkippedResult(tenantId);\n }\n\n try {\n onProgress?.(tenantId, 'starting');\n const result = await this.migrateTenant(tenantId, migrations, { dryRun, onProgress });\n onProgress?.(tenantId, result.success ? 'completed' : 'failed');\n return result;\n } catch (error) {\n onProgress?.(tenantId, 'failed');\n const action = onError?.(tenantId, error as Error);\n if (action === 'abort') {\n aborted = true;\n }\n return this.createErrorResult(tenantId, error as Error);\n }\n })\n );\n\n results.push(...batchResults);\n }\n\n // Mark remaining tenants as skipped if aborted\n if (aborted) {\n const remaining = tenantIds.slice(results.length);\n for (const tenantId of remaining) {\n results.push(this.createSkippedResult(tenantId));\n }\n }\n\n return this.aggregateResults(results);\n }\n\n /**\n * Migrate a single tenant\n */\n async migrateTenant(\n tenantId: string,\n migrations?: MigrationFile[],\n options: { dryRun?: boolean; onProgress?: MigrateOptions['onProgress'] } = {}\n ): Promise<TenantMigrationResult> {\n const startTime = Date.now();\n const schemaName = this.tenantConfig.isolation.schemaNameTemplate(tenantId);\n const appliedMigrations: string[] = [];\n\n const pool = await this.createPool(schemaName);\n\n try {\n await this.migratorConfig.hooks?.beforeTenant?.(tenantId);\n\n // Detect or determine the format before creating table\n const format = await this.getOrDetectFormat(pool, schemaName);\n\n // Ensure migrations table exists with correct format\n await this.ensureMigrationsTable(pool, schemaName, format);\n\n // Load migrations if not provided\n const allMigrations = migrations ?? await this.loadMigrations();\n\n // Get applied migrations using format-aware query\n const applied = await this.getAppliedMigrations(pool, schemaName, format);\n const appliedSet = new Set(applied.map((m) => m.identifier));\n\n // Filter pending migrations using format-aware comparison\n const pending = allMigrations.filter(\n (m) => !this.isMigrationApplied(m, appliedSet, format)\n );\n\n if (options.dryRun) {\n return {\n tenantId,\n schemaName,\n success: true,\n appliedMigrations: pending.map((m) => m.name),\n durationMs: Date.now() - startTime,\n format: format.format,\n };\n }\n\n // Apply pending migrations\n for (const migration of pending) {\n const migrationStart = Date.now();\n options.onProgress?.(tenantId, 'migrating', migration.name);\n\n await this.migratorConfig.hooks?.beforeMigration?.(tenantId, migration.name);\n await this.applyMigration(pool, schemaName, migration, format);\n await this.migratorConfig.hooks?.afterMigration?.(\n tenantId,\n migration.name,\n Date.now() - migrationStart\n );\n\n appliedMigrations.push(migration.name);\n }\n\n const result: TenantMigrationResult = {\n tenantId,\n schemaName,\n success: true,\n appliedMigrations,\n durationMs: Date.now() - startTime,\n format: format.format,\n };\n\n await this.migratorConfig.hooks?.afterTenant?.(tenantId, result);\n\n return result;\n } catch (error) {\n const result: TenantMigrationResult = {\n tenantId,\n schemaName,\n success: false,\n appliedMigrations,\n error: (error as Error).message,\n durationMs: Date.now() - startTime,\n };\n\n await this.migratorConfig.hooks?.afterTenant?.(tenantId, result);\n\n return result;\n } finally {\n await pool.end();\n }\n }\n\n /**\n * Migrate specific tenants\n */\n async migrateTenants(tenantIds: string[], options: MigrateOptions = {}): Promise<MigrationResults> {\n const migrations = await this.loadMigrations();\n const results: TenantMigrationResult[] = [];\n\n const { concurrency = 10, onProgress, onError } = options;\n\n for (let i = 0; i < tenantIds.length; i += concurrency) {\n const batch = tenantIds.slice(i, i + concurrency);\n\n const batchResults = await Promise.all(\n batch.map(async (tenantId) => {\n try {\n onProgress?.(tenantId, 'starting');\n const result = await this.migrateTenant(tenantId, migrations, { dryRun: options.dryRun ?? false, onProgress });\n onProgress?.(tenantId, result.success ? 'completed' : 'failed');\n return result;\n } catch (error) {\n onProgress?.(tenantId, 'failed');\n onError?.(tenantId, error as Error);\n return this.createErrorResult(tenantId, error as Error);\n }\n })\n );\n\n results.push(...batchResults);\n }\n\n return this.aggregateResults(results);\n }\n\n /**\n * Get migration status for all tenants\n */\n async getStatus(): Promise<TenantMigrationStatus[]> {\n const tenantIds = await this.migratorConfig.tenantDiscovery();\n const migrations = await this.loadMigrations();\n const statuses: TenantMigrationStatus[] = [];\n\n for (const tenantId of tenantIds) {\n statuses.push(await this.getTenantStatus(tenantId, migrations));\n }\n\n return statuses;\n }\n\n /**\n * Get migration status for a specific tenant\n */\n async getTenantStatus(tenantId: string, migrations?: MigrationFile[]): Promise<TenantMigrationStatus> {\n const schemaName = this.tenantConfig.isolation.schemaNameTemplate(tenantId);\n const pool = await this.createPool(schemaName);\n\n try {\n const allMigrations = migrations ?? await this.loadMigrations();\n\n // Check if migrations table exists\n const tableExists = await this.migrationsTableExists(pool, schemaName);\n if (!tableExists) {\n return {\n tenantId,\n schemaName,\n appliedCount: 0,\n pendingCount: allMigrations.length,\n pendingMigrations: allMigrations.map((m) => m.name),\n status: allMigrations.length > 0 ? 'behind' : 'ok',\n format: null, // New tenant, no table yet\n };\n }\n\n // Detect the table format\n const format = await this.getOrDetectFormat(pool, schemaName);\n\n const applied = await this.getAppliedMigrations(pool, schemaName, format);\n const appliedSet = new Set(applied.map((m) => m.identifier));\n\n // Use format-aware comparison\n const pending = allMigrations.filter(\n (m) => !this.isMigrationApplied(m, appliedSet, format)\n );\n\n return {\n tenantId,\n schemaName,\n appliedCount: applied.length,\n pendingCount: pending.length,\n pendingMigrations: pending.map((m) => m.name),\n status: pending.length > 0 ? 'behind' : 'ok',\n format: format.format,\n };\n } catch (error) {\n return {\n tenantId,\n schemaName,\n appliedCount: 0,\n pendingCount: 0,\n pendingMigrations: [],\n status: 'error',\n error: (error as Error).message,\n format: null,\n };\n } finally {\n await pool.end();\n }\n }\n\n /**\n * Create a new tenant schema and optionally apply migrations\n */\n async createTenant(tenantId: string, options: CreateTenantOptions = {}): Promise<void> {\n const { migrate = true } = options;\n const schemaName = this.tenantConfig.isolation.schemaNameTemplate(tenantId);\n\n const pool = new Pool({\n connectionString: this.tenantConfig.connection.url,\n ...this.tenantConfig.connection.poolConfig,\n });\n\n try {\n // Create schema\n await pool.query(`CREATE SCHEMA IF NOT EXISTS \"${schemaName}\"`);\n\n if (migrate) {\n // Apply all migrations\n await this.migrateTenant(tenantId);\n }\n } finally {\n await pool.end();\n }\n }\n\n /**\n * Drop a tenant schema\n */\n async dropTenant(tenantId: string, options: DropTenantOptions = {}): Promise<void> {\n const { cascade = true } = options;\n const schemaName = this.tenantConfig.isolation.schemaNameTemplate(tenantId);\n\n const pool = new Pool({\n connectionString: this.tenantConfig.connection.url,\n ...this.tenantConfig.connection.poolConfig,\n });\n\n try {\n const cascadeSql = cascade ? 'CASCADE' : 'RESTRICT';\n await pool.query(`DROP SCHEMA IF EXISTS \"${schemaName}\" ${cascadeSql}`);\n } finally {\n await pool.end();\n }\n }\n\n /**\n * Check if a tenant schema exists\n */\n async tenantExists(tenantId: string): Promise<boolean> {\n const schemaName = this.tenantConfig.isolation.schemaNameTemplate(tenantId);\n\n const pool = new Pool({\n connectionString: this.tenantConfig.connection.url,\n ...this.tenantConfig.connection.poolConfig,\n });\n\n try {\n const result = await pool.query(\n `SELECT 1 FROM information_schema.schemata WHERE schema_name = $1`,\n [schemaName]\n );\n return result.rowCount !== null && result.rowCount > 0;\n } finally {\n await pool.end();\n }\n }\n\n /**\n * Mark migrations as applied without executing SQL\n * Useful for syncing tracking state with already-applied migrations\n */\n async markAsApplied(\n tenantId: string,\n options: { onProgress?: MigrateOptions['onProgress'] } = {}\n ): Promise<TenantMigrationResult> {\n const startTime = Date.now();\n const schemaName = this.tenantConfig.isolation.schemaNameTemplate(tenantId);\n const markedMigrations: string[] = [];\n\n const pool = await this.createPool(schemaName);\n\n try {\n await this.migratorConfig.hooks?.beforeTenant?.(tenantId);\n\n // Detect or determine the format before creating table\n const format = await this.getOrDetectFormat(pool, schemaName);\n\n // Ensure migrations table exists with correct format\n await this.ensureMigrationsTable(pool, schemaName, format);\n\n // Load all migrations\n const allMigrations = await this.loadMigrations();\n\n // Get applied migrations\n const applied = await this.getAppliedMigrations(pool, schemaName, format);\n const appliedSet = new Set(applied.map((m) => m.identifier));\n\n // Filter pending migrations\n const pending = allMigrations.filter(\n (m) => !this.isMigrationApplied(m, appliedSet, format)\n );\n\n // Mark each pending migration as applied (without executing SQL)\n for (const migration of pending) {\n const migrationStart = Date.now();\n options.onProgress?.(tenantId, 'migrating', migration.name);\n\n await this.migratorConfig.hooks?.beforeMigration?.(tenantId, migration.name);\n await this.recordMigration(pool, schemaName, migration, format);\n await this.migratorConfig.hooks?.afterMigration?.(\n tenantId,\n migration.name,\n Date.now() - migrationStart\n );\n\n markedMigrations.push(migration.name);\n }\n\n const result: TenantMigrationResult = {\n tenantId,\n schemaName,\n success: true,\n appliedMigrations: markedMigrations,\n durationMs: Date.now() - startTime,\n format: format.format,\n };\n\n await this.migratorConfig.hooks?.afterTenant?.(tenantId, result);\n\n return result;\n } catch (error) {\n const result: TenantMigrationResult = {\n tenantId,\n schemaName,\n success: false,\n appliedMigrations: markedMigrations,\n error: (error as Error).message,\n durationMs: Date.now() - startTime,\n };\n\n await this.migratorConfig.hooks?.afterTenant?.(tenantId, result);\n\n return result;\n } finally {\n await pool.end();\n }\n }\n\n /**\n * Mark migrations as applied for all tenants without executing SQL\n * Useful for syncing tracking state with already-applied migrations\n */\n async markAllAsApplied(options: MigrateOptions = {}): Promise<MigrationResults> {\n const {\n concurrency = 10,\n onProgress,\n onError,\n } = options;\n\n const tenantIds = await this.migratorConfig.tenantDiscovery();\n const results: TenantMigrationResult[] = [];\n let aborted = false;\n\n // Process tenants in batches\n for (let i = 0; i < tenantIds.length && !aborted; i += concurrency) {\n const batch = tenantIds.slice(i, i + concurrency);\n\n const batchResults = await Promise.all(\n batch.map(async (tenantId) => {\n if (aborted) {\n return this.createSkippedResult(tenantId);\n }\n\n try {\n onProgress?.(tenantId, 'starting');\n const result = await this.markAsApplied(tenantId, { onProgress });\n onProgress?.(tenantId, result.success ? 'completed' : 'failed');\n return result;\n } catch (error) {\n onProgress?.(tenantId, 'failed');\n const action = onError?.(tenantId, error as Error);\n if (action === 'abort') {\n aborted = true;\n }\n return this.createErrorResult(tenantId, error as Error);\n }\n })\n );\n\n results.push(...batchResults);\n }\n\n // Mark remaining tenants as skipped if aborted\n if (aborted) {\n const remaining = tenantIds.slice(results.length);\n for (const tenantId of remaining) {\n results.push(this.createSkippedResult(tenantId));\n }\n }\n\n return this.aggregateResults(results);\n }\n\n /**\n * Get sync status for all tenants\n * Detects divergences between migrations on disk and tracking in database\n */\n async getSyncStatus(): Promise<SyncStatus> {\n const tenantIds = await this.migratorConfig.tenantDiscovery();\n const migrations = await this.loadMigrations();\n const statuses: TenantSyncStatus[] = [];\n\n for (const tenantId of tenantIds) {\n statuses.push(await this.getTenantSyncStatus(tenantId, migrations));\n }\n\n return {\n total: statuses.length,\n inSync: statuses.filter((s) => s.inSync && !s.error).length,\n outOfSync: statuses.filter((s) => !s.inSync && !s.error).length,\n error: statuses.filter((s) => !!s.error).length,\n details: statuses,\n };\n }\n\n /**\n * Get sync status for a specific tenant\n */\n async getTenantSyncStatus(tenantId: string, migrations?: MigrationFile[]): Promise<TenantSyncStatus> {\n const schemaName = this.tenantConfig.isolation.schemaNameTemplate(tenantId);\n const pool = await this.createPool(schemaName);\n\n try {\n const allMigrations = migrations ?? await this.loadMigrations();\n const migrationNames = new Set(allMigrations.map((m) => m.name));\n const migrationHashes = new Set(allMigrations.map((m) => m.hash));\n\n // Check if migrations table exists\n const tableExists = await this.migrationsTableExists(pool, schemaName);\n if (!tableExists) {\n return {\n tenantId,\n schemaName,\n missing: allMigrations.map((m) => m.name),\n orphans: [],\n inSync: allMigrations.length === 0,\n format: null,\n };\n }\n\n // Detect the table format\n const format = await this.getOrDetectFormat(pool, schemaName);\n const applied = await this.getAppliedMigrations(pool, schemaName, format);\n\n // Find missing migrations (in disk but not in database)\n const appliedIdentifiers = new Set(applied.map((m) => m.identifier));\n const missing = allMigrations\n .filter((m) => !this.isMigrationApplied(m, appliedIdentifiers, format))\n .map((m) => m.name);\n\n // Find orphan records (in database but not in disk)\n const orphans = applied\n .filter((m) => {\n if (format.columns.identifier === 'name') {\n return !migrationNames.has(m.identifier);\n }\n // For hash-based formats, check both hash and name\n return !migrationHashes.has(m.identifier) && !migrationNames.has(m.identifier);\n })\n .map((m) => m.identifier);\n\n return {\n tenantId,\n schemaName,\n missing,\n orphans,\n inSync: missing.length === 0 && orphans.length === 0,\n format: format.format,\n };\n } catch (error) {\n return {\n tenantId,\n schemaName,\n missing: [],\n orphans: [],\n inSync: false,\n format: null,\n error: (error as Error).message,\n };\n } finally {\n await pool.end();\n }\n }\n\n /**\n * Mark missing migrations as applied for a tenant\n */\n async markMissing(tenantId: string): Promise<TenantSyncResult> {\n const startTime = Date.now();\n const schemaName = this.tenantConfig.isolation.schemaNameTemplate(tenantId);\n const markedMigrations: string[] = [];\n\n const pool = await this.createPool(schemaName);\n\n try {\n const syncStatus = await this.getTenantSyncStatus(tenantId);\n\n if (syncStatus.error) {\n return {\n tenantId,\n schemaName,\n success: false,\n markedMigrations: [],\n removedOrphans: [],\n error: syncStatus.error,\n durationMs: Date.now() - startTime,\n };\n }\n\n if (syncStatus.missing.length === 0) {\n return {\n tenantId,\n schemaName,\n success: true,\n markedMigrations: [],\n removedOrphans: [],\n durationMs: Date.now() - startTime,\n };\n }\n\n const format = await this.getOrDetectFormat(pool, schemaName);\n await this.ensureMigrationsTable(pool, schemaName, format);\n\n const allMigrations = await this.loadMigrations();\n const missingSet = new Set(syncStatus.missing);\n\n for (const migration of allMigrations) {\n if (missingSet.has(migration.name)) {\n await this.recordMigration(pool, schemaName, migration, format);\n markedMigrations.push(migration.name);\n }\n }\n\n return {\n tenantId,\n schemaName,\n success: true,\n markedMigrations,\n removedOrphans: [],\n durationMs: Date.now() - startTime,\n };\n } catch (error) {\n return {\n tenantId,\n schemaName,\n success: false,\n markedMigrations,\n removedOrphans: [],\n error: (error as Error).message,\n durationMs: Date.now() - startTime,\n };\n } finally {\n await pool.end();\n }\n }\n\n /**\n * Mark missing migrations as applied for all tenants\n */\n async markAllMissing(options: SyncOptions = {}): Promise<SyncResults> {\n const { concurrency = 10, onProgress, onError } = options;\n\n const tenantIds = await this.migratorConfig.tenantDiscovery();\n const results: TenantSyncResult[] = [];\n let aborted = false;\n\n for (let i = 0; i < tenantIds.length && !aborted; i += concurrency) {\n const batch = tenantIds.slice(i, i + concurrency);\n\n const batchResults = await Promise.all(\n batch.map(async (tenantId) => {\n if (aborted) {\n return this.createSkippedSyncResult(tenantId);\n }\n\n try {\n onProgress?.(tenantId, 'starting');\n const result = await this.markMissing(tenantId);\n onProgress?.(tenantId, result.success ? 'completed' : 'failed');\n return result;\n } catch (error) {\n onProgress?.(tenantId, 'failed');\n const action = onError?.(tenantId, error as Error);\n if (action === 'abort') {\n aborted = true;\n }\n return this.createErrorSyncResult(tenantId, error as Error);\n }\n })\n );\n\n results.push(...batchResults);\n }\n\n return this.aggregateSyncResults(results);\n }\n\n /**\n * Remove orphan migration records for a tenant\n */\n async cleanOrphans(tenantId: string): Promise<TenantSyncResult> {\n const startTime = Date.now();\n const schemaName = this.tenantConfig.isolation.schemaNameTemplate(tenantId);\n const removedOrphans: string[] = [];\n\n const pool = await this.createPool(schemaName);\n\n try {\n const syncStatus = await this.getTenantSyncStatus(tenantId);\n\n if (syncStatus.error) {\n return {\n tenantId,\n schemaName,\n success: false,\n markedMigrations: [],\n removedOrphans: [],\n error: syncStatus.error,\n durationMs: Date.now() - startTime,\n };\n }\n\n if (syncStatus.orphans.length === 0) {\n return {\n tenantId,\n schemaName,\n success: true,\n markedMigrations: [],\n removedOrphans: [],\n durationMs: Date.now() - startTime,\n };\n }\n\n const format = await this.getOrDetectFormat(pool, schemaName);\n const identifierColumn = format.columns.identifier;\n\n for (const orphan of syncStatus.orphans) {\n await pool.query(\n `DELETE FROM \"${schemaName}\".\"${format.tableName}\" WHERE \"${identifierColumn}\" = $1`,\n [orphan]\n );\n removedOrphans.push(orphan);\n }\n\n return {\n tenantId,\n schemaName,\n success: true,\n markedMigrations: [],\n removedOrphans,\n durationMs: Date.now() - startTime,\n };\n } catch (error) {\n return {\n tenantId,\n schemaName,\n success: false,\n markedMigrations: [],\n removedOrphans,\n error: (error as Error).message,\n durationMs: Date.now() - startTime,\n };\n } finally {\n await pool.end();\n }\n }\n\n /**\n * Remove orphan migration records for all tenants\n */\n async cleanAllOrphans(options: SyncOptions = {}): Promise<SyncResults> {\n const { concurrency = 10, onProgress, onError } = options;\n\n const tenantIds = await this.migratorConfig.tenantDiscovery();\n const results: TenantSyncResult[] = [];\n let aborted = false;\n\n for (let i = 0; i < tenantIds.length && !aborted; i += concurrency) {\n const batch = tenantIds.slice(i, i + concurrency);\n\n const batchResults = await Promise.all(\n batch.map(async (tenantId) => {\n if (aborted) {\n return this.createSkippedSyncResult(tenantId);\n }\n\n try {\n onProgress?.(tenantId, 'starting');\n const result = await this.cleanOrphans(tenantId);\n onProgress?.(tenantId, result.success ? 'completed' : 'failed');\n return result;\n } catch (error) {\n onProgress?.(tenantId, 'failed');\n const action = onError?.(tenantId, error as Error);\n if (action === 'abort') {\n aborted = true;\n }\n return this.createErrorSyncResult(tenantId, error as Error);\n }\n })\n );\n\n results.push(...batchResults);\n }\n\n return this.aggregateSyncResults(results);\n }\n\n /**\n * Load migration files from the migrations folder\n */\n private async loadMigrations(): Promise<MigrationFile[]> {\n const files = await readdir(this.migratorConfig.migrationsFolder);\n\n const migrations: MigrationFile[] = [];\n\n for (const file of files) {\n if (!file.endsWith('.sql')) continue;\n\n const filePath = join(this.migratorConfig.migrationsFolder, file);\n const content = await readFile(filePath, 'utf-8');\n\n // Extract timestamp from filename (e.g., 0001_migration_name.sql)\n const match = file.match(/^(\\d+)_/);\n const timestamp = match?.[1] ? parseInt(match[1], 10) : 0;\n\n // Compute SHA-256 hash for drizzle-kit compatibility\n const hash = createHash('sha256').update(content).digest('hex');\n\n migrations.push({\n name: basename(file, '.sql'),\n path: filePath,\n sql: content,\n timestamp,\n hash,\n });\n }\n\n // Sort by timestamp\n return migrations.sort((a, b) => a.timestamp - b.timestamp);\n }\n\n /**\n * Create a pool for a specific schema\n */\n private async createPool(schemaName: string): Promise<Pool> {\n return new Pool({\n connectionString: this.tenantConfig.connection.url,\n ...this.tenantConfig.connection.poolConfig,\n options: `-c search_path=\"${schemaName}\",public`,\n });\n }\n\n /**\n * Ensure migrations table exists with the correct format\n */\n private async ensureMigrationsTable(\n pool: Pool,\n schemaName: string,\n format: DetectedFormat\n ): Promise<void> {\n const { identifier, timestamp, timestampType } = format.columns;\n\n // Build column definitions based on format\n const identifierCol = identifier === 'name'\n ? 'name VARCHAR(255) NOT NULL UNIQUE'\n : 'hash TEXT NOT NULL';\n\n const timestampCol = timestampType === 'bigint'\n ? `${timestamp} BIGINT NOT NULL`\n : `${timestamp} TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP`;\n\n await pool.query(`\n CREATE TABLE IF NOT EXISTS \"${schemaName}\".\"${format.tableName}\" (\n id SERIAL PRIMARY KEY,\n ${identifierCol},\n ${timestampCol}\n )\n `);\n }\n\n /**\n * Check if migrations table exists\n */\n private async migrationsTableExists(pool: Pool, schemaName: string): Promise<boolean> {\n const result = await pool.query(\n `SELECT 1 FROM information_schema.tables\n WHERE table_schema = $1 AND table_name = $2`,\n [schemaName, this.migrationsTable]\n );\n return result.rowCount !== null && result.rowCount > 0;\n }\n\n /**\n * Get applied migrations for a schema\n */\n private async getAppliedMigrations(\n pool: Pool,\n schemaName: string,\n format: DetectedFormat\n ): Promise<AppliedMigration[]> {\n const identifierColumn = format.columns.identifier;\n const timestampColumn = format.columns.timestamp;\n\n const result = await pool.query<{ id: number; identifier: string; applied_at: string | number }>(\n `SELECT id, \"${identifierColumn}\" as identifier, \"${timestampColumn}\" as applied_at\n FROM \"${schemaName}\".\"${format.tableName}\"\n ORDER BY id`\n );\n\n return result.rows.map((row) => {\n // Convert timestamp based on format\n const appliedAt = format.columns.timestampType === 'bigint'\n ? new Date(Number(row.applied_at))\n : new Date(row.applied_at);\n\n return {\n id: row.id,\n identifier: row.identifier,\n // Set name or hash based on format\n ...(format.columns.identifier === 'name'\n ? { name: row.identifier }\n : { hash: row.identifier }),\n appliedAt,\n };\n });\n }\n\n /**\n * Check if a migration has been applied\n */\n private isMigrationApplied(\n migration: MigrationFile,\n appliedIdentifiers: Set<string>,\n format: DetectedFormat\n ): boolean {\n if (format.columns.identifier === 'name') {\n return appliedIdentifiers.has(migration.name);\n }\n\n // Hash-based: check both hash AND name for backwards compatibility\n // This allows migration from name-based to hash-based tracking\n return appliedIdentifiers.has(migration.hash) || appliedIdentifiers.has(migration.name);\n }\n\n /**\n * Get or detect the format for a schema\n * Returns the configured format or auto-detects from existing table\n */\n private async getOrDetectFormat(\n pool: Pool,\n schemaName: string\n ): Promise<DetectedFormat> {\n const configuredFormat = this.migratorConfig.tableFormat ?? 'auto';\n\n // If not auto, return the configured format\n if (configuredFormat !== 'auto') {\n return getFormatConfig(configuredFormat, this.migrationsTable);\n }\n\n // Auto-detect from existing table\n const detected = await detectTableFormat(pool, schemaName, this.migrationsTable);\n\n if (detected) {\n return detected;\n }\n\n // No table exists, use default format\n const defaultFormat: TableFormat = this.migratorConfig.defaultFormat ?? 'name';\n return getFormatConfig(defaultFormat, this.migrationsTable);\n }\n\n /**\n * Apply a migration to a schema\n */\n private async applyMigration(\n pool: Pool,\n schemaName: string,\n migration: MigrationFile,\n format: DetectedFormat\n ): Promise<void> {\n const client = await pool.connect();\n\n try {\n await client.query('BEGIN');\n\n // Execute migration SQL\n await client.query(migration.sql);\n\n // Record migration using format-aware insert\n const { identifier, timestamp, timestampType } = format.columns;\n const identifierValue = identifier === 'name' ? migration.name : migration.hash;\n const timestampValue = timestampType === 'bigint' ? Date.now() : new Date();\n\n await client.query(\n `INSERT INTO \"${schemaName}\".\"${format.tableName}\" (\"${identifier}\", \"${timestamp}\") VALUES ($1, $2)`,\n [identifierValue, timestampValue]\n );\n\n await client.query('COMMIT');\n } catch (error) {\n await client.query('ROLLBACK');\n throw error;\n } finally {\n client.release();\n }\n }\n\n /**\n * Record a migration as applied without executing SQL\n * Used by markAsApplied to sync tracking state\n */\n private async recordMigration(\n pool: Pool,\n schemaName: string,\n migration: MigrationFile,\n format: DetectedFormat\n ): Promise<void> {\n const { identifier, timestamp, timestampType } = format.columns;\n const identifierValue = identifier === 'name' ? migration.name : migration.hash;\n const timestampValue = timestampType === 'bigint' ? Date.now() : new Date();\n\n await pool.query(\n `INSERT INTO \"${schemaName}\".\"${format.tableName}\" (\"${identifier}\", \"${timestamp}\") VALUES ($1, $2)`,\n [identifierValue, timestampValue]\n );\n }\n\n /**\n * Create a skipped result\n */\n private createSkippedResult(tenantId: string): TenantMigrationResult {\n return {\n tenantId,\n schemaName: this.tenantConfig.isolation.schemaNameTemplate(tenantId),\n success: false,\n appliedMigrations: [],\n error: 'Skipped due to abort',\n durationMs: 0,\n };\n }\n\n /**\n * Create an error result\n */\n private createErrorResult(tenantId: string, error: Error): TenantMigrationResult {\n return {\n tenantId,\n schemaName: this.tenantConfig.isolation.schemaNameTemplate(tenantId),\n success: false,\n appliedMigrations: [],\n error: error.message,\n durationMs: 0,\n };\n }\n\n /**\n * Aggregate migration results\n */\n private aggregateResults(results: TenantMigrationResult[]): MigrationResults {\n return {\n total: results.length,\n succeeded: results.filter((r) => r.success).length,\n failed: results.filter((r) => !r.success && r.error !== 'Skipped due to abort').length,\n skipped: results.filter((r) => r.error === 'Skipped due to abort').length,\n details: results,\n };\n }\n\n /**\n * Create a skipped sync result\n */\n private createSkippedSyncResult(tenantId: string): TenantSyncResult {\n return {\n tenantId,\n schemaName: this.tenantConfig.isolation.schemaNameTemplate(tenantId),\n success: false,\n markedMigrations: [],\n removedOrphans: [],\n error: 'Skipped due to abort',\n durationMs: 0,\n };\n }\n\n /**\n * Create an error sync result\n */\n private createErrorSyncResult(tenantId: string, error: Error): TenantSyncResult {\n return {\n tenantId,\n schemaName: this.tenantConfig.isolation.schemaNameTemplate(tenantId),\n success: false,\n markedMigrations: [],\n removedOrphans: [],\n error: error.message,\n durationMs: 0,\n };\n }\n\n /**\n * Aggregate sync results\n */\n private aggregateSyncResults(results: TenantSyncResult[]): SyncResults {\n return {\n total: results.length,\n succeeded: results.filter((r) => r.success).length,\n failed: results.filter((r) => !r.success).length,\n details: results,\n };\n }\n}\n\n/**\n * Create a migrator instance\n */\nexport function createMigrator<\n TTenantSchema extends Record<string, unknown>,\n TSharedSchema extends Record<string, unknown>,\n>(\n tenantConfig: Config<TTenantSchema, TSharedSchema>,\n migratorConfig: MigratorConfig\n): Migrator<TTenantSchema, TSharedSchema> {\n return new Migrator(tenantConfig, migratorConfig);\n}\n","import { sql, getTableName } from 'drizzle-orm';\nimport type { NodePgDatabase } from 'drizzle-orm/node-postgres';\nimport type { SQL, Table, Column } from 'drizzle-orm';\nimport type {\n CrossSchemaContext,\n SchemaSource,\n JoinType,\n JoinCondition,\n SharedLookupConfig,\n CrossSchemaRawOptions,\n} from './types.js';\n\n/**\n * Cross-schema query builder for joining tenant and shared data\n *\n * @example\n * ```typescript\n * const query = createCrossSchemaQuery({\n * tenantDb: tenants.getDb('tenant-uuid'),\n * sharedDb: tenants.getSharedDb(),\n * });\n *\n * const results = await query\n * .from('tenant', orders)\n * .leftJoin('shared', subscriptionPlans, eq(orders.planId, subscriptionPlans.id))\n * .select({\n * orderId: orders.id,\n * planName: subscriptionPlans.name,\n * })\n * .execute();\n * ```\n */\nexport class CrossSchemaQueryBuilder<\n TTenantSchema extends Record<string, unknown> = Record<string, unknown>,\n TSharedSchema extends Record<string, unknown> = Record<string, unknown>,\n> {\n private fromTable: { table: Table; source: SchemaSource; schemaName: string } | null = null;\n private joins: Array<{\n table: Table;\n source: SchemaSource;\n schemaName: string;\n condition: JoinCondition;\n type: JoinType;\n }> = [];\n private selectFields: Record<string, Column> = {};\n private whereCondition: SQL<unknown> | null = null;\n private orderByFields: SQL<unknown>[] = [];\n private limitValue: number | null = null;\n private offsetValue: number | null = null;\n\n constructor(private readonly context: CrossSchemaContext<TTenantSchema, TSharedSchema>) {}\n\n /**\n * Set the main table to query from\n */\n from<T extends Table>(source: SchemaSource, table: T): this {\n const schemaName = this.getSchemaName(source);\n this.fromTable = { table, source, schemaName };\n return this;\n }\n\n /**\n * Add an inner join\n */\n innerJoin<T extends Table>(source: SchemaSource, table: T, condition: JoinCondition): this {\n return this.addJoin(source, table, condition, 'inner');\n }\n\n /**\n * Add a left join\n */\n leftJoin<T extends Table>(source: SchemaSource, table: T, condition: JoinCondition): this {\n return this.addJoin(source, table, condition, 'left');\n }\n\n /**\n * Add a right join\n */\n rightJoin<T extends Table>(source: SchemaSource, table: T, condition: JoinCondition): this {\n return this.addJoin(source, table, condition, 'right');\n }\n\n /**\n * Add a full outer join\n */\n fullJoin<T extends Table>(source: SchemaSource, table: T, condition: JoinCondition): this {\n return this.addJoin(source, table, condition, 'full');\n }\n\n /**\n * Select specific fields\n */\n select<T extends Record<string, Column>>(fields: T): this {\n this.selectFields = fields;\n return this;\n }\n\n /**\n * Add a where condition\n */\n where(condition: SQL<unknown>): this {\n this.whereCondition = condition;\n return this;\n }\n\n /**\n * Add order by\n */\n orderBy(...fields: SQL<unknown>[]): this {\n this.orderByFields = fields;\n return this;\n }\n\n /**\n * Set limit\n */\n limit(value: number): this {\n this.limitValue = value;\n return this;\n }\n\n /**\n * Set offset\n */\n offset(value: number): this {\n this.offsetValue = value;\n return this;\n }\n\n /**\n * Execute the query and return typed results\n */\n async execute<TResult = Record<string, unknown>>(): Promise<TResult[]> {\n if (!this.fromTable) {\n throw new Error('[drizzle-multitenant] No table specified. Use .from() first.');\n }\n\n const sqlQuery = this.buildSql();\n\n // Use the tenant db to execute (it has access to both schemas via search_path)\n const result = await this.context.tenantDb.execute(sqlQuery);\n\n return result.rows as TResult[];\n }\n\n /**\n * Build the SQL query\n */\n private buildSql(): SQL<unknown> {\n if (!this.fromTable) {\n throw new Error('[drizzle-multitenant] No table specified');\n }\n\n const parts: SQL<unknown>[] = [];\n\n // SELECT clause\n const selectParts = Object.entries(this.selectFields).map(([alias, column]) => {\n const columnName = column.name;\n return sql`${sql.raw(`\"${columnName}\"`)} as ${sql.raw(`\"${alias}\"`)}`;\n });\n\n if (selectParts.length === 0) {\n parts.push(sql`SELECT *`);\n } else {\n parts.push(sql`SELECT ${sql.join(selectParts, sql`, `)}`);\n }\n\n // FROM clause\n const fromTableRef = this.getFullTableName(this.fromTable.schemaName, this.fromTable.table);\n parts.push(sql` FROM ${sql.raw(fromTableRef)}`);\n\n // JOIN clauses\n for (const join of this.joins) {\n const joinTableRef = this.getFullTableName(join.schemaName, join.table);\n const joinType = this.getJoinKeyword(join.type);\n parts.push(sql` ${sql.raw(joinType)} ${sql.raw(joinTableRef)} ON ${join.condition}`);\n }\n\n // WHERE clause\n if (this.whereCondition) {\n parts.push(sql` WHERE ${this.whereCondition}`);\n }\n\n // ORDER BY clause\n if (this.orderByFields.length > 0) {\n parts.push(sql` ORDER BY ${sql.join(this.orderByFields, sql`, `)}`);\n }\n\n // LIMIT clause\n if (this.limitValue !== null) {\n parts.push(sql` LIMIT ${sql.raw(this.limitValue.toString())}`);\n }\n\n // OFFSET clause\n if (this.offsetValue !== null) {\n parts.push(sql` OFFSET ${sql.raw(this.offsetValue.toString())}`);\n }\n\n return sql.join(parts, sql``);\n }\n\n /**\n * Add a join to the query\n */\n private addJoin<T extends Table>(\n source: SchemaSource,\n table: T,\n condition: JoinCondition,\n type: JoinType\n ): this {\n const schemaName = this.getSchemaName(source);\n this.joins.push({ table, source, schemaName, condition, type });\n return this;\n }\n\n /**\n * Get schema name for a source\n */\n private getSchemaName(source: SchemaSource): string {\n if (source === 'tenant') {\n return this.context.tenantSchema ?? 'tenant';\n }\n return this.context.sharedSchema ?? 'public';\n }\n\n /**\n * Get fully qualified table name\n */\n private getFullTableName(schemaName: string, table: Table): string {\n const tableName = getTableName(table);\n return `\"${schemaName}\".\"${tableName}\"`;\n }\n\n /**\n * Get SQL keyword for join type\n */\n private getJoinKeyword(type: JoinType): string {\n switch (type) {\n case 'inner':\n return 'INNER JOIN';\n case 'left':\n return 'LEFT JOIN';\n case 'right':\n return 'RIGHT JOIN';\n case 'full':\n return 'FULL OUTER JOIN';\n }\n }\n}\n\n/**\n * Create a cross-schema query builder\n */\nexport function createCrossSchemaQuery<\n TTenantSchema extends Record<string, unknown> = Record<string, unknown>,\n TSharedSchema extends Record<string, unknown> = Record<string, unknown>,\n>(\n context: CrossSchemaContext<TTenantSchema, TSharedSchema>\n): CrossSchemaQueryBuilder<TTenantSchema, TSharedSchema> {\n return new CrossSchemaQueryBuilder(context);\n}\n\n/**\n * Helper for common pattern: tenant table with shared lookup\n *\n * @example\n * ```typescript\n * const ordersWithPlans = await withSharedLookup({\n * tenantDb,\n * sharedDb,\n * tenantTable: orders,\n * sharedTable: subscriptionPlans,\n * foreignKey: 'planId',\n * sharedFields: ['name', 'features', 'price'],\n * });\n * ```\n */\nexport async function withSharedLookup<\n TTenantTable extends Table,\n TSharedTable extends Table,\n TSharedFields extends keyof TSharedTable['_']['columns'],\n>(config: SharedLookupConfig<TTenantTable, TSharedTable, TSharedFields>): Promise<Array<Record<string, unknown>>> {\n const {\n tenantDb,\n tenantTable,\n sharedTable,\n foreignKey,\n sharedKey = 'id' as keyof TSharedTable['_']['columns'],\n sharedFields,\n where: whereCondition,\n } = config;\n\n // Get table names using Drizzle's utility\n const tenantTableName = getTableName(tenantTable);\n const sharedTableName = getTableName(sharedTable);\n\n // Build field list for shared table\n const sharedFieldList = sharedFields\n .map((field) => `s.\"${String(field)}\"`)\n .join(', ');\n\n // Build the query\n const queryParts = [\n `SELECT t.*, ${sharedFieldList}`,\n `FROM \"${tenantTableName}\" t`,\n `LEFT JOIN \"public\".\"${sharedTableName}\" s ON t.\"${String(foreignKey)}\" = s.\"${String(sharedKey)}\"`,\n ];\n\n if (whereCondition) {\n queryParts.push('WHERE');\n // We'll need to use raw SQL for the where condition\n }\n\n const sqlQuery = sql.raw(queryParts.join(' '));\n\n const result = await tenantDb.execute(sqlQuery);\n\n return result.rows as Array<Record<string, unknown>>;\n}\n\n/**\n * Execute raw cross-schema SQL with type safety\n *\n * @example\n * ```typescript\n * const result = await crossSchemaRaw<{ userName: string; planName: string }>({\n * tenantSchema: 'tenant_abc123',\n * sharedSchema: 'public',\n * sql: `\n * SELECT u.name as \"userName\", p.name as \"planName\"\n * FROM $tenant.users u\n * JOIN $shared.plans p ON u.plan_id = p.id\n * `,\n * });\n * ```\n */\nexport async function crossSchemaRaw<TResult = Record<string, unknown>>(\n db: NodePgDatabase<Record<string, unknown>>,\n options: CrossSchemaRawOptions\n): Promise<TResult[]> {\n const { tenantSchema, sharedSchema, sql: rawSql } = options;\n\n // Replace $tenant and $shared placeholders\n const processedSql = rawSql\n .replace(/\\$tenant\\./g, `\"${tenantSchema}\".`)\n .replace(/\\$shared\\./g, `\"${sharedSchema}\".`);\n\n const query = sql.raw(processedSql);\n\n const result = await db.execute(query);\n\n return result.rows as TResult[];\n}\n\n/**\n * Create a typed cross-schema query using SQL template\n *\n * @example\n * ```typescript\n * const users = await crossSchemaSelect(tenantDb, {\n * tenantSchema: 'tenant_abc',\n * sharedSchema: 'public',\n * select: {\n * id: users.id,\n * name: users.name,\n * planName: plans.name,\n * },\n * from: { table: users, schema: 'tenant' },\n * joins: [\n * { table: plans, schema: 'shared', on: eq(users.planId, plans.id), type: 'left' },\n * ],\n * });\n * ```\n */\nexport function buildCrossSchemaSelect<T extends Record<string, Column>>(\n fields: T,\n tenantSchema: string,\n _sharedSchema: string\n): { columns: string[]; getSchema: () => string } {\n const columns = Object.entries(fields).map(([alias, column]) => {\n const columnName = column.name;\n return `\"${columnName}\" as \"${alias}\"`;\n });\n\n const getSchema = (): string => {\n // This would need more context to determine which schema a column belongs to\n // For now, return tenant schema as default\n return tenantSchema;\n };\n\n return { columns, getSchema };\n}\n","import { sql, getTableName } from 'drizzle-orm';\nimport type { NodePgDatabase } from 'drizzle-orm/node-postgres';\nimport type { SQL, Column, Table } from 'drizzle-orm';\nimport type {\n JoinCondition,\n JoinType,\n WithSharedConfig,\n WithSharedOptions,\n InferSelectResult,\n} from './types.js';\n\n/**\n * Extract tables from a Drizzle schema object\n */\nfunction extractTablesFromSchema(schema: Record<string, unknown>): Set<Table> {\n const tables = new Set<Table>();\n\n for (const value of Object.values(schema)) {\n if (value && typeof value === 'object' && '_' in value) {\n const branded = value as { _?: { brand?: string } };\n if (branded._?.brand === 'Table') {\n tables.add(value as Table);\n }\n }\n }\n\n return tables;\n}\n\n/**\n * Check if a table belongs to the shared schema\n */\nfunction isSharedTable(table: Table, sharedTables: Set<Table>): boolean {\n return sharedTables.has(table);\n}\n\n/**\n * Simplified cross-schema query builder with automatic schema detection\n *\n * @example\n * ```typescript\n * const result = await withShared(tenantDb, sharedDb, { tenant: tenantSchema, shared: sharedSchema })\n * .from(pedidos)\n * .leftJoin(workflowSteps, eq(pedidos.workflowStepId, workflowSteps.id))\n * .select({ pedidoId: pedidos.id, workflowNome: workflowSteps.nome })\n * .execute();\n * ```\n */\nexport class WithSharedQueryBuilder<\n TTenantSchema extends Record<string, unknown> = Record<string, unknown>,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n _TSharedSchema extends Record<string, unknown> = Record<string, unknown>,\n> {\n private fromTable: {\n table: Table;\n isShared: boolean;\n schemaName: string;\n } | null = null;\n\n private joins: Array<{\n table: Table;\n isShared: boolean;\n schemaName: string;\n condition: JoinCondition;\n type: JoinType;\n }> = [];\n\n private selectFields: Record<string, Column> = {};\n private whereCondition: SQL<unknown> | null = null;\n private orderByFields: SQL<unknown>[] = [];\n private limitValue: number | null = null;\n private offsetValue: number | null = null;\n\n constructor(\n private readonly tenantDb: NodePgDatabase<TTenantSchema>,\n private readonly sharedTables: Set<Table>,\n private readonly tenantSchemaName: string,\n private readonly sharedSchemaName: string = 'public'\n ) {}\n\n /**\n * Set the main table to query from\n * Automatically detects if it's a tenant or shared table\n */\n from<T extends Table>(table: T): this {\n const isShared = isSharedTable(table, this.sharedTables);\n this.fromTable = {\n table,\n isShared,\n schemaName: isShared ? this.sharedSchemaName : this.tenantSchemaName,\n };\n return this;\n }\n\n /**\n * Add a left join with automatic schema detection\n */\n leftJoin<T extends Table>(table: T, condition: JoinCondition): this {\n return this.addJoin(table, condition, 'left');\n }\n\n /**\n * Add an inner join with automatic schema detection\n */\n innerJoin<T extends Table>(table: T, condition: JoinCondition): this {\n return this.addJoin(table, condition, 'inner');\n }\n\n /**\n * Add a right join with automatic schema detection\n */\n rightJoin<T extends Table>(table: T, condition: JoinCondition): this {\n return this.addJoin(table, condition, 'right');\n }\n\n /**\n * Add a full outer join with automatic schema detection\n */\n fullJoin<T extends Table>(table: T, condition: JoinCondition): this {\n return this.addJoin(table, condition, 'full');\n }\n\n /**\n * Select specific fields\n */\n select<T extends Record<string, Column>>(fields: T): this {\n this.selectFields = fields;\n return this;\n }\n\n /**\n * Add a WHERE condition\n */\n where(condition: SQL<unknown>): this {\n this.whereCondition = condition;\n return this;\n }\n\n /**\n * Add ORDER BY\n */\n orderBy(...fields: SQL<unknown>[]): this {\n this.orderByFields = fields;\n return this;\n }\n\n /**\n * Set LIMIT\n */\n limit(value: number): this {\n this.limitValue = value;\n return this;\n }\n\n /**\n * Set OFFSET\n */\n offset(value: number): this {\n this.offsetValue = value;\n return this;\n }\n\n /**\n * Execute the query and return typed results\n */\n async execute<TResult extends Record<string, unknown> = InferSelectResult<typeof this.selectFields>>(): Promise<TResult[]> {\n if (!this.fromTable) {\n throw new Error('[drizzle-multitenant] No table specified. Use .from() first.');\n }\n\n const sqlQuery = this.buildSql();\n const result = await this.tenantDb.execute(sqlQuery);\n\n return result.rows as TResult[];\n }\n\n /**\n * Add a join to the query\n */\n private addJoin<T extends Table>(\n table: T,\n condition: JoinCondition,\n type: JoinType\n ): this {\n const isShared = isSharedTable(table, this.sharedTables);\n this.joins.push({\n table,\n isShared,\n schemaName: isShared ? this.sharedSchemaName : this.tenantSchemaName,\n condition,\n type,\n });\n return this;\n }\n\n /**\n * Build the SQL query\n */\n private buildSql(): SQL<unknown> {\n if (!this.fromTable) {\n throw new Error('[drizzle-multitenant] No table specified');\n }\n\n const parts: SQL<unknown>[] = [];\n\n // SELECT clause\n const selectParts = Object.entries(this.selectFields).map(([alias, column]) => {\n const columnName = column.name;\n // Try to get table name from column\n const tableName = this.getTableAliasForColumn(column);\n if (tableName) {\n return sql`${sql.raw(`\"${tableName}\".\"${columnName}\"`)} as ${sql.raw(`\"${alias}\"`)}`;\n }\n return sql`${sql.raw(`\"${columnName}\"`)} as ${sql.raw(`\"${alias}\"`)}`;\n });\n\n if (selectParts.length === 0) {\n parts.push(sql`SELECT *`);\n } else {\n parts.push(sql`SELECT ${sql.join(selectParts, sql`, `)}`);\n }\n\n // FROM clause with alias\n const fromTableName = getTableName(this.fromTable.table);\n const fromTableRef = `\"${this.fromTable.schemaName}\".\"${fromTableName}\"`;\n parts.push(sql` FROM ${sql.raw(fromTableRef)} \"${sql.raw(fromTableName)}\"`);\n\n // JOIN clauses with aliases\n for (const join of this.joins) {\n const joinTableName = getTableName(join.table);\n const joinTableRef = `\"${join.schemaName}\".\"${joinTableName}\"`;\n const joinKeyword = this.getJoinKeyword(join.type);\n parts.push(\n sql` ${sql.raw(joinKeyword)} ${sql.raw(joinTableRef)} \"${sql.raw(joinTableName)}\" ON ${join.condition}`\n );\n }\n\n // WHERE clause\n if (this.whereCondition) {\n parts.push(sql` WHERE ${this.whereCondition}`);\n }\n\n // ORDER BY clause\n if (this.orderByFields.length > 0) {\n parts.push(sql` ORDER BY ${sql.join(this.orderByFields, sql`, `)}`);\n }\n\n // LIMIT clause\n if (this.limitValue !== null) {\n parts.push(sql` LIMIT ${sql.raw(this.limitValue.toString())}`);\n }\n\n // OFFSET clause\n if (this.offsetValue !== null) {\n parts.push(sql` OFFSET ${sql.raw(this.offsetValue.toString())}`);\n }\n\n return sql.join(parts, sql``);\n }\n\n /**\n * Get table alias for a column (used in SELECT)\n */\n private getTableAliasForColumn(column: Column): string | null {\n // Drizzle columns have a reference to their table\n const columnTable = (column as unknown as { table?: Table }).table;\n if (columnTable) {\n return getTableName(columnTable);\n }\n return null;\n }\n\n /**\n * Get SQL keyword for join type\n */\n private getJoinKeyword(type: JoinType): string {\n switch (type) {\n case 'inner':\n return 'INNER JOIN';\n case 'left':\n return 'LEFT JOIN';\n case 'right':\n return 'RIGHT JOIN';\n case 'full':\n return 'FULL OUTER JOIN';\n }\n }\n}\n\n/**\n * Create a simplified cross-schema query builder with automatic schema detection\n *\n * This helper automatically detects whether a table belongs to the tenant schema\n * or the shared schema based on the schema configuration provided.\n *\n * @param tenantDb - The tenant database instance\n * @param sharedDb - The shared database instance (unused but kept for API symmetry)\n * @param schemas - Object containing tenant and shared schema definitions\n * @param options - Optional configuration for schema names\n * @returns A query builder with automatic schema detection\n *\n * @example\n * ```typescript\n * // Define your schemas\n * const tenantSchema = { pedidos, clientes };\n * const sharedSchema = { workflowSteps, plans };\n *\n * // Use withShared for cross-schema queries\n * const result = await withShared(\n * tenantDb,\n * sharedDb,\n * { tenant: tenantSchema, shared: sharedSchema }\n * )\n * .from(pedidos) // Auto-detected as tenant table\n * .leftJoin(workflowSteps, // Auto-detected as shared table\n * eq(pedidos.workflowStepId, workflowSteps.id)\n * )\n * .select({\n * pedidoId: pedidos.id,\n * workflowNome: workflowSteps.nome,\n * })\n * .where(eq(pedidos.status, 'active'))\n * .orderBy(desc(pedidos.createdAt))\n * .limit(10)\n * .execute();\n * ```\n */\nexport function withShared<\n TTenantSchema extends Record<string, unknown>,\n TSharedSchema extends Record<string, unknown>,\n>(\n tenantDb: NodePgDatabase<TTenantSchema>,\n _sharedDb: NodePgDatabase<TSharedSchema>,\n schemas: WithSharedConfig<TTenantSchema, TSharedSchema>,\n options?: WithSharedOptions\n): WithSharedQueryBuilder<TTenantSchema, TSharedSchema> {\n const sharedTables = extractTablesFromSchema(schemas.shared);\n\n return new WithSharedQueryBuilder(\n tenantDb,\n sharedTables,\n options?.tenantSchema ?? 'tenant',\n options?.sharedSchema ?? 'public'\n );\n}\n"]}