logquill 0.3.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/levels.ts","../src/core/records.ts","../src/core/formatter.ts","../src/core/plugin.ts","../src/plugins/context-plugin.ts","../src/plugins/redact-plugin.ts","../src/plugins/pii-redact-plugin.ts","../src/plugins/sampling-plugin.ts","../src/transports/transport.ts","../src/transports/console-transport.ts","../src/transports/beacon-transport.ts","../src/core/context-browser.ts","../src/core/dispatch-queue.ts","../src/core/span-browser.ts","../src/core/logger.ts"],"names":["Level"],"mappings":";AACO,IAAK,KAAA,qBAAAA,MAAAA,KAAL;AAEL,EAAAA,MAAAA,CAAAA,MAAAA,CAAA,WAAQ,CAAA,CAAA,GAAR,OAAA;AAEA,EAAAA,MAAAA,CAAAA,MAAAA,CAAA,WAAQ,EAAA,CAAA,GAAR,OAAA;AAEA,EAAAA,MAAAA,CAAAA,MAAAA,CAAA,UAAO,EAAA,CAAA,GAAP,MAAA;AAEA,EAAAA,MAAAA,CAAAA,MAAAA,CAAA,UAAO,EAAA,CAAA,GAAP,MAAA;AAEA,EAAAA,MAAAA,CAAAA,MAAAA,CAAA,WAAQ,EAAA,CAAA,GAAR,OAAA;AAEA,EAAAA,MAAAA,CAAAA,MAAAA,CAAA,WAAQ,EAAA,CAAA,GAAR,OAAA;AAZU,EAAA,OAAAA,MAAAA;AAAA,CAAA,EAAA,KAAA,IAAA,EAAA;AAeZ,IAAM,aAAA,GAAiD;AAAA,EACrD,KAAA,EAAO,CAAA;AAAA,EACP,KAAA,EAAO,EAAA;AAAA,EACP,IAAA,EAAM,EAAA;AAAA,EACN,IAAA,EAAM,EAAA;AAAA,EACN,KAAA,EAAO,EAAA;AAAA,EACP,KAAA,EAAO,EAAA;AACT,CAAA;AAMO,SAAS,UAAU,KAAA,EAAsB;AAC9C,EAAA,OAAO,MAAM,KAAK,CAAA;AACpB;AAGO,SAAS,WAAW,KAAA,EAA0B;AACnD,EAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,IAAA,MAAM,MAAA,GAAS,aAAA,CAAc,KAAA,CAAM,WAAA,EAAa,CAAA;AAChD,IAAA,IAAI,WAAW,MAAA,EAAW;AACxB,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,mBAAA,EAAsB,KAAK,CAAA,CAAE,CAAA;AAAA,IAC/C;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,IAAI,KAAA,CAAM,KAAK,CAAA,KAAM,MAAA,EAAW;AAC9B,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,mBAAA,EAAsB,MAAA,CAAO,KAAK,CAAC,CAAA,CAAE,CAAA;AAAA,EACvD;AACA,EAAA,OAAO,KAAA;AACT;;;AC7BO,SAAS,YAAA,GAAuB;AACrC,EAAA,OAAA,iBAAO,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAChC;AAGO,SAAS,aAAa,MAAA,EAKf;AACZ,EAAA,OAAO;AAAA,IACL,WAAW,YAAA,EAAa;AAAA,IACxB,KAAA,EAAO,SAAA,CAAU,MAAA,CAAO,KAAK,CAAA;AAAA,IAC7B,QAAQ,MAAA,CAAO,MAAA;AAAA,IACf,SAAS,MAAA,CAAO,OAAA;AAAA,IAChB,MAAM,MAAA,CAAO;AAAA,GACf;AACF;;;AC1BO,IAAM,gBAAN,MAAyC;AAAA;AAAA,EAE9C,OAAO,MAAA,EAA2B;AAChC,IAAA,OAAO,IAAA,CAAK,UAAU,MAAM,CAAA;AAAA,EAC9B;AACF;;;ACcO,IAAM,iBAAN,MAAuC;AAAA,EAC3B,IAAA;AAAA,EAEjB,YAAY,IAAA,EAAsB;AAChC,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AAAA,EACd;AAAA,EAEA,UAAU,MAAA,EAAqC;AAC7C,IAAA,OAAO,IAAA,CAAK,KAAK,MAAM,CAAA;AAAA,EACzB;AACF;;;AC/BO,IAAM,gBAAN,MAAsC;AAAA;AAAA,EAElC,OAAA;AAAA,EAET,YAAY,OAAA,EAAkC;AAC5C,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA;AAAA,EACjB;AAAA,EAEA,UAAU,MAAA,EAA8B;AACtC,IAAA,OAAO,EAAE,GAAG,MAAA,EAAQ,IAAA,EAAM,EAAE,GAAG,IAAA,CAAK,OAAA,EAAS,GAAG,MAAA,CAAO,IAAA,EAAK,EAAE;AAAA,EAChE;AACF;;;ACdO,IAAM,wBAA2C,CAAC,UAAA,EAAY,OAAA,EAAS,QAAA,EAAU,WAAW,eAAe;AAW3G,IAAM,eAAN,MAAqC;AAAA,EACzB,IAAA;AAAA;AAAA,EAER,WAAA;AAAA,EAET,WAAA,CAAY,OAAA,GAA+B,EAAC,EAAG;AAC7C,IAAA,IAAA,CAAK,IAAA,GAAO,IAAI,GAAA,CAAA,CAAK,OAAA,CAAQ,IAAA,IAAQ,qBAAA,EAAuB,GAAA,CAAI,CAAC,GAAA,KAAQ,GAAA,CAAI,WAAA,EAAa,CAAC,CAAA;AAC3F,IAAA,IAAA,CAAK,WAAA,GAAc,QAAQ,WAAA,IAAe,KAAA;AAAA,EAC5C;AAAA,EAEA,UAAU,MAAA,EAA8B;AACtC,IAAA,MAAM,OAAgC,EAAC;AACvC,IAAA,KAAA,MAAW,CAAC,KAAK,KAAK,CAAA,IAAK,OAAO,OAAA,CAAQ,MAAA,CAAO,IAAI,CAAA,EAAG;AACtD,MAAA,IAAA,CAAK,GAAG,CAAA,GAAI,IAAA,CAAK,IAAA,CAAK,GAAA,CAAI,IAAI,WAAA,EAAa,CAAA,GAAI,IAAA,CAAK,WAAA,GAAc,KAAA;AAAA,IACpE;AACA,IAAA,OAAO,EAAE,GAAG,MAAA,EAAQ,IAAA,EAAK;AAAA,EAC3B;AACF;;;ACvBO,IAAM,oBAAA,GAAyD;AAAA,EACpE,KAAA,EAAO,qDAAA;AAAA,EACP,GAAA,EAAK,wBAAA;AAAA,EACL,UAAA,EAAY,yBAAA;AAAA,EACZ,KAAA,EAAO;AACT;AAEA,IAAM,SAAA,GAAY,EAAA;AA8BX,IAAM,kBAAN,MAAwC;AAAA;AAAA,EAEpC,QAAA;AAAA;AAAA,EAEA,WAAA;AAAA,EAET,WAAA,CAAY,OAAA,GAAkC,EAAC,EAAG;AAChD,IAAA,IAAA,CAAK,QAAA,GAAW,QAAQ,QAAA,IAAY,oBAAA;AACpC,IAAA,IAAA,CAAK,WAAA,GAAc,QAAQ,WAAA,IAAe,KAAA;AAAA,EAC5C;AAAA,EAEA,UAAU,MAAA,EAA8B;AACtC,IAAA,OAAO,EAAE,GAAG,MAAA,EAAQ,IAAA,EAAM,IAAA,CAAK,WAAA,CAAY,MAAA,CAAO,IAAA,kBAAM,IAAI,GAAA,EAAI,EAAG,CAAC,CAAA,EAA6B;AAAA,EACnG;AAAA,EAEQ,WAAA,CAAY,KAAA,EAAgB,IAAA,EAA4B,KAAA,EAAwB;AACtF,IAAA,IAAI,QAAQ,SAAA,EAAW;AACrB,MAAA,OAAO,KAAA;AAAA,IACT;AACA,IAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,MAAA,OAAO,IAAA,CAAK,WAAW,KAAK,CAAA;AAAA,IAC9B;AACA,IAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AACxB,MAAA,IAAI,IAAA,CAAK,GAAA,CAAI,KAAK,CAAA,EAAG;AACnB,QAAA,OAAO,KAAA;AAAA,MACT;AACA,MAAA,MAAM,WAAW,IAAI,GAAA,CAAI,IAAI,CAAA,CAAE,IAAI,KAAK,CAAA;AACxC,MAAA,OAAO,KAAA,CAAM,GAAA,CAAI,CAAC,KAAA,KAAU,IAAA,CAAK,YAAY,KAAA,EAAO,QAAA,EAAU,KAAA,GAAQ,CAAC,CAAC,CAAA;AAAA,IAC1E;AACA,IAAA,IAAI,KAAA,KAAU,IAAA,IAAQ,OAAO,KAAA,KAAU,QAAA,EAAU;AAC/C,MAAA,IAAI,IAAA,CAAK,GAAA,CAAI,KAAK,CAAA,EAAG;AACnB,QAAA,OAAO,KAAA;AAAA,MACT;AACA,MAAA,MAAM,WAAW,IAAI,GAAA,CAAI,IAAI,CAAA,CAAE,IAAI,KAAK,CAAA;AACxC,MAAA,MAAM,SAAkC,EAAC;AACzC,MAAA,KAAA,MAAW,CAAC,GAAA,EAAK,UAAU,KAAK,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA,EAAG;AACrD,QAAA,MAAA,CAAO,GAAG,CAAA,GAAI,IAAA,CAAK,YAAY,UAAA,EAAY,QAAA,EAAU,QAAQ,CAAC,CAAA;AAAA,MAChE;AACA,MAAA,OAAO,MAAA;AAAA,IACT;AACA,IAAA,OAAO,KAAA;AAAA,EACT;AAAA,EAEQ,WAAW,IAAA,EAAsB;AACvC,IAAA,IAAI,QAAA,GAAW,IAAA;AACf,IAAA,KAAA,MAAW,OAAA,IAAW,MAAA,CAAO,MAAA,CAAO,IAAA,CAAK,QAAQ,CAAA,EAAG;AAKlD,MAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,MAAA,GAAS,OAAA,GAAU,IAAI,MAAA,CAAO,OAAA,CAAQ,MAAA,EAAQ,CAAA,EAAG,OAAA,CAAQ,KAAK,CAAA,CAAA,CAAG,CAAA;AACxF,MAAA,QAAA,GAAW,QAAA,CAAS,OAAA,CAAQ,MAAA,EAAQ,IAAA,CAAK,WAAW,CAAA;AAAA,IACtD;AACA,IAAA,OAAO,QAAA;AAAA,EACT;AACF;;;AClDO,IAAM,iBAAN,MAAuC;AAAA;AAAA,EAEnC,IAAA;AAAA;AAAA,EAEA,QAAA;AAAA;AAAA,EAEA,SAAA;AAAA;AAAA,EAEA,UAAA;AAAA;AAAA,EAEA,kBAAA;AAAA;AAAA,EAEA,SAAA;AAAA,EACQ,GAAA;AAAA,EACA,MAAA,uBAAa,GAAA,EAA0B;AAAA,EAChD,aAAA,GAAgB,CAAA;AAAA,EACP,QAAA,uBAAe,GAAA,EAAa;AAAA,EAE7C,WAAA,CAAY,IAAA,EAAc,OAAA,GAAiC,EAAC,EAAG;AAC7D,IAAA,IAAI,IAAA,GAAO,CAAA,IAAK,IAAA,GAAO,CAAA,EAAG;AACxB,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,kCAAA,EAAqC,MAAA,CAAO,IAAI,CAAC,CAAA,CAAE,CAAA;AAAA,IACrE;AACA,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AACZ,IAAA,IAAA,CAAK,GAAA,GAAM,OAAA,CAAQ,GAAA,IAAO,IAAA,CAAK,MAAA;AAC/B,IAAA,IAAA,CAAK,QAAA,GAAW,QAAQ,QAAA,IAAY,SAAA;AACpC,IAAA,IAAA,CAAK,SAAA,GAAY,UAAA,CAAW,OAAA,CAAQ,SAAA,IAAA,EAAA,aAAwB;AAC5D,IAAA,IAAA,CAAK,aAAa,OAAA,CAAQ,UAAA;AAC1B,IAAA,IAAA,CAAK,kBAAA,GAAqB,QAAQ,kBAAA,IAAsB,GAAA;AACxD,IAAA,IAAA,CAAK,SAAA,GAAY,QAAQ,SAAA,IAAa,GAAA;AAAA,EACxC;AAAA,EAEA,UAAU,MAAA,EAAqC;AAC7C,IAAA,MAAM,aAAa,IAAA,CAAK,UAAA;AACxB,IAAA,IAAI,eAAe,MAAA,EAAW;AAC5B,MAAA,OAAO,IAAA,CAAK,GAAA,EAAI,GAAI,IAAA,CAAK,OAAO,MAAA,GAAS,IAAA;AAAA,IAC3C;AAEA,IAAA,MAAM,OAAA,GAAU,MAAA,CAAO,IAAA,CAAK,IAAA,CAAK,QAAQ,CAAA;AAEzC,IAAA,IAAI,YAAY,MAAA,IAAa,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,OAAO,CAAA,EAAG;AACvD,MAAA,OAAO,MAAA;AAAA,IACT;AAEA,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,GAAA,EAAI,GAAI,IAAA,CAAK,IAAA;AAC/B,IAAA,MAAM,mBAAA,GAAsB,UAAA,CAAW,MAAA,CAAO,KAAK,KAAK,IAAA,CAAK,SAAA;AAE7D,IAAA,IAAI,OAAA,KAAY,UAAa,mBAAA,EAAqB;AAChD,MAAA,IAAA,CAAK,OAAA,CAAQ,SAAS,UAAU,CAAA;AAChC,MAAA,OAAO,MAAA;AAAA,IACT;AAEA,IAAA,IAAI,IAAA,EAAM;AACR,MAAA,OAAO,MAAA;AAAA,IACT;AAEA,IAAA,IAAI,YAAY,MAAA,EAAW;AACzB,MAAA,IAAA,CAAK,YAAA,CAAa,SAAS,MAAM,CAAA;AAAA,IACnC;AAEA,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EAEQ,OAAA,CAAQ,SAAkB,UAAA,EAA+B;AAC/D,IAAA,IAAA,CAAK,QAAA,CAAS,IAAI,OAAO,CAAA;AACzB,IAAA,MAAM,WAAW,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,OAAO,KAAK,EAAC;AAC9C,IAAA,IAAA,CAAK,MAAA,CAAO,OAAO,OAAO,CAAA;AAC1B,IAAA,IAAA,CAAK,iBAAiB,QAAA,CAAS,MAAA;AAC/B,IAAA,KAAA,MAAW,kBAAkB,QAAA,EAAU;AACrC,MAAA,KAAA,MAAW,aAAa,UAAA,EAAY;AAClC,QAAA,SAAA,CAAU,KAAA,CAAM,SAAA,CAAU,MAAA,CAAO,cAAc,GAAG,cAAc,CAAA;AAAA,MAClE;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,YAAA,CAAa,SAAkB,MAAA,EAAyB;AAC9D,IAAA,IAAI,OAAA,GAAU,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,OAAO,CAAA;AACrC,IAAA,IAAI,OAAA,EAAS;AAEX,MAAA,IAAA,CAAK,MAAA,CAAO,OAAO,OAAO,CAAA;AAC1B,MAAA,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,OAAA,EAAS,OAAO,CAAA;AAAA,IAClC,CAAA,MAAO;AACL,MAAA,IAAI,IAAA,CAAK,MAAA,CAAO,IAAA,IAAQ,IAAA,CAAK,SAAA,EAAW;AACtC,QAAA,IAAA,CAAK,gBAAA,EAAiB;AAAA,MACxB;AACA,MAAA,OAAA,GAAU,EAAC;AACX,MAAA,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,OAAA,EAAS,OAAO,CAAA;AAAA,IAClC;AAEA,IAAA,OAAA,CAAQ,KAAK,MAAM,CAAA;AACnB,IAAA,IAAA,CAAK,aAAA,IAAiB,CAAA;AAEtB,IAAA,OAAO,KAAK,aAAA,GAAgB,IAAA,CAAK,sBAAsB,IAAA,CAAK,MAAA,CAAO,OAAO,CAAA,EAAG;AAC3E,MAAA,IAAA,CAAK,gBAAA,EAAiB;AAAA,IACxB;AAAA,EACF;AAAA,EAEQ,gBAAA,GAAyB;AAC/B,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,MAAA,CAAO,OAAA,GAAU,IAAA,EAAK;AAC1C,IAAA,IAAI,OAAO,IAAA,EAAM;AACf,MAAA;AAAA,IACF;AACA,IAAA,MAAM,CAAC,SAAA,EAAW,aAAa,CAAA,GAAI,MAAA,CAAO,KAAA;AAC1C,IAAA,IAAA,CAAK,MAAA,CAAO,OAAO,SAAS,CAAA;AAC5B,IAAA,IAAA,CAAK,iBAAiB,aAAA,CAAc,MAAA;AAAA,EACtC;AACF;;;ACrJO,IAAe,YAAf,MAAyB;AAAA;AAAA,EAE9B,SAAA;AAAA,EAEA,WAAA,CAAY,SAAA,GAAuB,IAAI,aAAA,EAAc,EAAG;AACtD,IAAA,IAAA,CAAK,SAAA,GAAY,SAAA;AAAA,EACnB;AAAA;AAAA,EAGA,OAAO,MAAA,EAA2B;AAChC,IAAA,OAAO,IAAA,CAAK,SAAA,CAAU,MAAA,CAAO,MAAM,CAAA;AAAA,EACrC;AAAA;AAAA,EAMA,KAAA,GAAc;AAAA,EAAC;AACjB;AASO,SAAS,SAAS,SAAA,EAAmE;AAC1F,EAAA,OAAO,OAAQ,UAA0C,KAAA,KAAU,UAAA;AACrE;AAGO,IAAM,mBAAA,GAAN,cAAkC,SAAA,CAAU;AAAA;AAAA,EAExC,YAAsB,EAAC;AAAA;AAAA,EAEvB,UAAuB,EAAC;AAAA;AAAA,EAEjC,MAAA,GAAS,KAAA;AAAA,EAET,KAAA,CAAM,WAAmB,MAAA,EAAyB;AAChD,IAAA,IAAA,CAAK,SAAA,CAAU,KAAK,SAAS,CAAA;AAC7B,IAAA,IAAA,CAAK,OAAA,CAAQ,KAAK,MAAM,CAAA;AAAA,EAC1B;AAAA,EAES,KAAA,GAAc;AACrB,IAAA,IAAA,CAAK,MAAA,GAAS,IAAA;AAAA,EAChB;AACF;;;AClDA,IAAM,MAAA,GAA0C;AAAA,EAC9C,iBAAe,UAAA;AAAA;AAAA,EACf,kBAAe,UAAA;AAAA;AAAA,EACf,iBAAc,UAAA;AAAA;AAAA,EACd,iBAAc,UAAA;AAAA;AAAA,EACd,kBAAe,UAAA;AAAA;AAAA,EACf,kBAAe;AAAA;AACjB,CAAA;AACA,IAAM,KAAA,GAAQ,SAAA;AAoBd,SAAS,eAAA,GAA2B;AAElC,EAAA,MAAM,GAAA,GAAqC,OAAO,OAAA,KAAY,WAAA,GAAc,SAAY,OAAA,CAAQ,GAAA;AAChG,EAAA,OAAO,KAAK,QAAA,KAAa,MAAA;AAC3B;AAOO,IAAM,gBAAA,GAAN,cAA+B,SAAA,CAAU;AAAA;AAAA,EAE9C,QAAA;AAAA,EACiB,GAAA;AAAA,EAEjB,WAAA,CAAY,OAAA,GAAmC,EAAC,EAAG;AACjD,IAAA,KAAA,CAAM,QAAQ,SAAS,CAAA;AACvB,IAAA,IAAA,CAAK,QAAA,GAAW,OAAA,CAAQ,QAAA,IAAY,eAAA,EAAgB;AACpD,IAAA,IAAA,CAAK,GAAA,GAAM,QAAQ,OAAA,IAAW,OAAA;AAAA,EAChC;AAAA;AAAA,EAGA,KAAA,CAAM,WAAmB,MAAA,EAAyB;AAChD,IAAA,MAAM,KAAA,GAAQ,UAAA,CAAW,MAAA,CAAO,KAAK,CAAA;AACrC,IAAA,MAAM,OAAO,IAAA,CAAK,QAAA,GAAW,KAAK,UAAA,CAAW,SAAA,EAAW,KAAK,CAAA,GAAI,SAAA;AACjE,IAAA,IAAI,KAAA,IAAA,EAAA,cAAsB;AACxB,MAAA,IAAA,CAAK,GAAA,CAAI,MAAM,IAAI,CAAA;AAAA,IACrB,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,GAAA,CAAI,IAAI,IAAI,CAAA;AAAA,IACnB;AAAA,EACF;AAAA,EAEQ,UAAA,CAAW,WAAmB,KAAA,EAAsB;AAC1D,IAAA,OAAO,GAAG,MAAA,CAAO,KAAK,CAAC,CAAA,EAAG,SAAS,GAAG,KAAK,CAAA,CAAA;AAAA,EAC7C;AACF;;;ACtDA,SAAS,mBAAA,CAAoB,KAAa,KAAA,EAAgC;AACxE,EAAA,MAAM,IAAA,GAAO,KAAA,CAAM,IAAA,CAAK,IAAI,CAAA;AAI5B,EAAA,MAAM,GAAA,GAAM,OAAO,SAAA,KAAc,WAAA,GAAc,MAAA,GAAa,SAAA;AAC5D,EAAA,IAAI,GAAA,IAAO,OAAO,GAAA,CAAI,UAAA,KAAe,UAAA,EAAY;AAC/C,IAAA,GAAA,CAAI,UAAA,CAAW,KAAK,IAAI,CAAA;AACxB,IAAA;AAAA,EACF;AAKA,EAAA,KAAK,KAAA,CAAM,GAAA,EAAK,EAAE,MAAA,EAAQ,MAAA,EAAQ,IAAA,EAAM,SAAA,EAAW,IAAA,EAAM,CAAA,CAAE,KAAA,CAAM,CAAC,KAAA,KAAmB;AAGnF,IAAA,OAAA,CAAQ,KAAA,CAAM,6CAA6C,KAAK,CAAA;AAAA,EAClE,CAAC,CAAA;AACH;AAmBO,IAAM,eAAA,GAAN,cAA8B,SAAA,CAAU;AAAA;AAAA,EAEpC,GAAA;AAAA;AAAA,EAEA,SAAA;AAAA,EACQ,MAAA;AAAA,EACT,QAAkB,EAAC;AAAA,EAE3B,WAAA,CAAY,GAAA,EAAa,OAAA,GAAkC,EAAC,EAAG;AAC7D,IAAA,KAAA,CAAM,QAAQ,SAAS,CAAA;AACvB,IAAA,IAAA,CAAK,GAAA,GAAM,GAAA;AACX,IAAA,IAAA,CAAK,SAAA,GAAY,QAAQ,SAAA,IAAa,EAAA;AACtC,IAAA,IAAA,CAAK,MAAA,GAAS,QAAQ,MAAA,IAAU,mBAAA;AAAA,EAClC;AAAA;AAAA,EAGA,MAAM,SAAA,EAAyB;AAC7B,IAAA,IAAA,CAAK,KAAA,CAAM,KAAK,SAAS,CAAA;AACzB,IAAA,IAAI,IAAA,CAAK,KAAA,CAAM,MAAA,IAAU,IAAA,CAAK,SAAA,EAAW;AACvC,MAAA,IAAA,CAAK,KAAA,EAAM;AAAA,IACb;AAAA,EACF;AAAA;AAAA,EAGA,KAAA,GAAc;AACZ,IAAA,IAAI,IAAA,CAAK,KAAA,CAAM,MAAA,KAAW,CAAA,EAAG;AAC3B,MAAA;AAAA,IACF;AACA,IAAA,MAAM,QAAQ,IAAA,CAAK,KAAA;AACnB,IAAA,IAAA,CAAK,QAAQ,EAAC;AAEd,IAAA,IAAI;AACF,MAAA,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,GAAA,EAAK,KAAK,CAAA;AAAA,IAC7B,SAAS,KAAA,EAAO;AACd,MAAA,OAAA,CAAQ,KAAA,CAAM,6CAA6C,KAAK,CAAA;AAAA,IAClE;AAAA,EACF;AAAA,EAES,KAAA,GAAc;AACrB,IAAA,IAAA,CAAK,KAAA,EAAM;AAAA,EACb;AACF;;;AC/EA,IAAM,eAA0C,EAAC;AAG1C,SAAS,cAAA,GAA0C;AACxD,EAAA,OAAO,YAAA,CAAa,YAAA,CAAa,MAAA,GAAS,CAAC,KAAK,EAAC;AACnD;;;ACcA,SAAS,UAAU,KAAA,EAAqD;AACtE,EAAA,OAAO,OAAO,KAAA,KAAU,QAAA,IAAY,OAAO,MAAM,IAAA,KAAS,UAAA;AAC5D;AAEA,SAAS,iBAAiB,GAAA,EAAuB;AAI/C,EAAA,IAAI,OAAO,iBAAiB,UAAA,EAAY;AACtC,IAAA,YAAA,CAAa,GAAG,CAAA;AAAA,EAClB,CAAA,MAAO;AACL,IAAA,cAAA,CAAe,GAAG,CAAA;AAAA,EACpB;AACF;AAEA,SAAS,aAAA,CAAc,OAAe,MAAA,EAAkC;AACtE,EAAA,OAAA,CAAQ,IAAA;AAAA,IACN,CAAA,uBAAA,EAA0B,MAAA,CAAO,KAAK,CAAC,mEAA8D,MAAM,CAAA,qBAAA;AAAA,GAC7G;AACF;AASO,IAAM,gBAAN,MAAoB;AAAA;AAAA,EAEhB,OAAA;AAAA;AAAA,EAEA,MAAA;AAAA,EACQ,MAAA;AAAA,EACA,cAAA;AAAA,EAEA,QAAgB,EAAC;AAAA,EAC1B,QAAA,GAAW,KAAA;AAAA,EACX,SAAA,GAAY,KAAA;AAAA,EACZ,cAA8B,EAAC;AAAA,EAC/B,mBAAA,GAAsB,CAAA;AAAA,EACtB,UAAA,GAAa,CAAA;AAAA,EAErB,WAAA,CAAY,OAAA,GAAgC,EAAC,EAAG;AAC9C,IAAA,IAAA,CAAK,OAAA,GAAU,QAAQ,OAAA,IAAW,GAAA;AAClC,IAAA,IAAA,CAAK,MAAA,GAAS,QAAQ,MAAA,IAAU,YAAA;AAChC,IAAA,IAAA,CAAK,MAAA,GAAS,QAAQ,MAAA,IAAU,aAAA;AAChC,IAAA,IAAA,CAAK,cAAA,GAAiB,QAAQ,cAAA,IAAkB,GAAA;AAAA,EAClD;AAAA;AAAA,EAGA,IAAI,IAAA,GAAe;AACjB,IAAA,OAAO,KAAK,KAAA,CAAM,MAAA;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,QAAQ,IAAA,EAAkB;AACxB,IAAA,IAAI,IAAA,CAAK,KAAA,CAAM,MAAA,GAAS,IAAA,CAAK,OAAA,EAAS;AACpC,MAAA,IAAA,CAAK,KAAA,CAAM,KAAK,IAAI,CAAA;AACpB,MAAA,IAAA,CAAK,QAAA,EAAS;AACd,MAAA;AAAA,IACF;AAEA,IAAA,QAAQ,KAAK,MAAA;AAAQ,MACnB,KAAK,YAAA;AACH,QAAA,IAAA,CAAK,UAAA,EAAW;AAChB,QAAA;AAAA,MACF,KAAK,OAAA;AACH,QAAA,IAAA,CAAK,UAAU,IAAI,CAAA;AACnB,QAAA;AAAA,MACF,KAAK,YAAA;AAAA,MACL;AACE,QAAA,IAAA,CAAK,MAAM,KAAA,EAAM;AACjB,QAAA,IAAA,CAAK,UAAA,EAAW;AAChB,QAAA,IAAA,CAAK,KAAA,CAAM,KAAK,IAAI,CAAA;AACpB,QAAA,IAAA,CAAK,QAAA,EAAS;AACd,QAAA;AAAA;AACJ,EACF;AAAA;AAAA,EAGA,MAAM,KAAA,GAAuB;AAC3B,IAAA,IAAI,KAAK,KAAA,CAAM,MAAA,KAAW,CAAA,IAAK,CAAC,KAAK,QAAA,EAAU;AAC7C,MAAA;AAAA,IACF;AACA,IAAA,MAAM,IAAI,OAAA,CAAc,CAAC,OAAA,KAAY;AACnC,MAAA,IAAA,CAAK,WAAA,CAAY,KAAK,OAAO,CAAA;AAC7B,MAAA,IAAA,CAAK,QAAA,EAAS;AAAA,IAChB,CAAC,CAAA;AAAA,EACH;AAAA,EAEQ,UAAA,GAAmB;AACzB,IAAA,IAAA,CAAK,mBAAA,IAAuB,CAAA;AAC5B,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,IAAA,IAAI,GAAA,GAAM,IAAA,CAAK,UAAA,IAAc,IAAA,CAAK,cAAA,EAAgB;AAChD,MAAA,MAAM,QAAQ,IAAA,CAAK,mBAAA;AACnB,MAAA,IAAA,CAAK,mBAAA,GAAsB,CAAA;AAC3B,MAAA,IAAA,CAAK,UAAA,GAAa,GAAA;AAClB,MAAA,IAAI;AACF,QAAA,IAAA,CAAK,MAAA,CAAO,KAAA,EAAO,IAAA,CAAK,MAAM,CAAA;AAAA,MAChC,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,UAAU,IAAA,EAAkB;AAClC,IAAA,IAAI;AACF,MAAA,MAAM,SAAS,IAAA,EAAK;AACpB,MAAA,IAAI,SAAA,CAAU,MAAM,CAAA,EAAG;AACrB,QAAA,MAAA,CAAO,KAAA,CAAM,CAAC,KAAA,KAAmB;AAC/B,UAAA,OAAA,CAAQ,KAAA,CAAM,wCAAwC,KAAK,CAAA;AAAA,QAC7D,CAAC,CAAA;AAAA,MACH;AAAA,IACF,SAAS,KAAA,EAAO;AACd,MAAA,OAAA,CAAQ,KAAA,CAAM,wCAAwC,KAAK,CAAA;AAAA,IAC7D;AAAA,EACF;AAAA,EAEQ,QAAA,GAAiB;AACvB,IAAA,IAAI,KAAK,SAAA,EAAW;AAClB,MAAA;AAAA,IACF;AACA,IAAA,IAAA,CAAK,SAAA,GAAY,IAAA;AACjB,IAAA,gBAAA,CAAiB,MAAM;AACrB,MAAA,IAAA,CAAK,SAAA,GAAY,KAAA;AACjB,MAAA,KAAK,KAAK,QAAA,EAAS;AAAA,IACrB,CAAC,CAAA;AAAA,EACH;AAAA,EAEA,MAAc,QAAA,GAA0B;AACtC,IAAA,IAAI,KAAK,QAAA,EAAU;AACjB,MAAA;AAAA,IACF;AACA,IAAA,IAAA,CAAK,QAAA,GAAW,IAAA;AAChB,IAAA,IAAI;AACF,MAAA,OAAO,IAAA,CAAK,KAAA,CAAM,MAAA,GAAS,CAAA,EAAG;AAC5B,QAAA,MAAM,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,KAAA,EAAM;AAC9B,QAAA,IAAI,CAAC,IAAA,EAAM;AACT,UAAA;AAAA,QACF;AACA,QAAA,IAAI;AACF,UAAA,MAAM,IAAA,EAAK;AAAA,QACb,SAAS,KAAA,EAAO;AACd,UAAA,OAAA,CAAQ,KAAA,CAAM,uCAAuC,KAAK,CAAA;AAAA,QAC5D;AAAA,MACF;AAAA,IACF,CAAA,SAAE;AACA,MAAA,IAAA,CAAK,QAAA,GAAW,KAAA;AAChB,MAAA,MAAM,UAAU,IAAA,CAAK,WAAA;AACrB,MAAA,IAAA,CAAK,cAAc,EAAC;AACpB,MAAA,KAAA,MAAW,WAAW,OAAA,EAAS;AAC7B,QAAA,OAAA,EAAQ;AAAA,MACV;AAAA,IACF;AAAA,EACF;AACF,CAAA;;;ACnLA,IAAM,YAAsB,EAAC;AAGtB,SAAS,aAAA,GAAoC;AAClD,EAAA,OAAO,SAAA,CAAU,SAAA,CAAU,MAAA,GAAS,CAAC,CAAA;AACvC;AAGO,SAAS,SAAA,GAAoB;AAClC,EAAA,MAAM,KAAA,GAAQ,IAAI,UAAA,CAAW,CAAC,CAAA;AAC9B,EAAA,MAAA,CAAO,gBAAgB,KAAK,CAAA;AAC5B,EAAA,OAAO,KAAA,CAAM,IAAA,CAAK,KAAA,EAAO,CAAC,SAAS,IAAA,CAAK,QAAA,CAAS,EAAE,CAAA,CAAE,SAAS,CAAA,EAAG,GAAG,CAAC,CAAA,CAAE,KAAK,EAAE,CAAA;AAChF;AAEO,SAAS,SAAA,CAAa,QAAgB,EAAA,EAAgB;AAC3D,EAAA,SAAA,CAAU,KAAK,MAAM,CAAA;AACrB,EAAA,IAAI,MAAA;AACJ,EAAA,IAAI;AACF,IAAA,MAAA,GAAS,EAAA,EAAG;AAAA,EACd,SAAS,KAAA,EAAO;AACd,IAAA,SAAA,CAAU,GAAA,EAAI;AACd,IAAA,MAAM,KAAA;AAAA,EACR;AACA,EAAA,IAAI,kBAAkB,OAAA,EAAS;AAK7B,IAAA,OAAO,MAAA,CAAO,OAAA,CAAQ,MAAM,SAAA,CAAU,KAAK,CAAA;AAAA,EAC7C;AACA,EAAA,SAAA,CAAU,GAAA,EAAI;AACd,EAAA,OAAO,MAAA;AACT;;;AC/BA,SAAS,gBAAgB,KAAA,EAAwB;AAC/C,EAAA,IAAI,iBAAiB,KAAA,EAAO;AAC1B,IAAA,OAAO,CAAA,EAAG,KAAA,CAAM,IAAI,CAAA,EAAA,EAAK,MAAM,OAAO,CAAA,CAAA;AAAA,EACxC;AACA,EAAA,OAAO,OAAO,KAAK,CAAA;AACrB;AASA,SAAS,iBAAiB,IAAA,EAAwD;AAChF,EAAA,MAAM,MAAM,IAAA,CAAK,GAAA;AACjB,EAAA,IAAI,EAAE,eAAe,KAAA,CAAA,EAAQ;AAC3B,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,MAAM,IAAA,GAAO,EAAE,GAAG,IAAA,EAAK;AACvB,EAAA,OAAO,IAAA,CAAK,GAAA;AACZ,EAAA,IAAA,CAAK,KAAA,GAAQ,IAAI,KAAA,IAAS,CAAA,EAAG,IAAI,IAAI,CAAA,EAAA,EAAK,IAAI,OAAO,CAAA,CAAA;AACrD,EAAA,OAAO,IAAA;AACT;AAuBO,IAAM,MAAA,GAAN,MAAM,OAAA,CAAO;AAAA;AAAA,EAET,IAAA;AAAA;AAAA,EAEA,UAAA;AAAA;AAAA,EAEA,OAAA;AAAA,EACD,YAAA;AAAA,EACS,QAAA;AAAA,EACT,aAAA;AAAA,EAER,WAAA,CAAY,IAAA,EAAc,OAAA,GAAyB,EAAC,EAAG;AACrD,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AACZ,IAAA,IAAA,CAAK,YAAA,GAAe,UAAA,CAAW,OAAA,CAAQ,KAAA,IAAA,EAAA,YAAmB;AAC1D,IAAA,IAAA,CAAK,UAAA,GAAa,QAAQ,UAAA,GAAa,CAAC,GAAG,OAAA,CAAQ,UAAU,IAAI,EAAC;AAClE,IAAA,IAAA,CAAK,UAAU,EAAC;AAChB,IAAA,KAAA,MAAW,MAAA,IAAU,OAAA,CAAQ,OAAA,IAAW,EAAC,EAAG;AAC1C,MAAA,IAAA,CAAK,IAAI,MAAM,CAAA;AAAA,IACjB;AACA,IAAA,IAAA,CAAK,QAAA,GAAW,QAAQ,IAAA,GAAO,EAAE,GAAG,OAAA,CAAQ,IAAA,KAAS,EAAC;AACtD,IAAA,IAAA,CAAK,aAAA,GAAgB,IAAI,aAAA,CAAc,OAAA,CAAQ,KAAK,CAAA;AAAA,EACtD;AAAA;AAAA,EAGA,IAAI,KAAA,GAAe;AACjB,IAAA,OAAO,IAAA,CAAK,YAAA;AAAA,EACd;AAAA;AAAA,EAGA,SAAS,KAAA,EAAyB;AAChC,IAAA,IAAA,CAAK,YAAA,GAAe,WAAW,KAAK,CAAA;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,IAAI,MAAA,EAAuC;AACzC,IAAA,IAAA,CAAK,OAAA,CAAQ,KAAK,OAAO,MAAA,KAAW,aAAa,IAAI,cAAA,CAAe,MAAM,CAAA,GAAI,MAAM,CAAA;AACpF,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA,EAGA,IAAI,SAAA,GAAoB;AACtB,IAAA,OAAO,KAAK,aAAA,CAAc,IAAA;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,KAAA,GAAuB;AAC3B,IAAA,MAAM,IAAA,CAAK,cAAc,KAAA,EAAM;AAAA,EACjC;AAAA;AAAA,EAGA,MAAM,KAAA,GAAuB;AAC3B,IAAA,MAAM,KAAK,KAAA,EAAM;AACjB,IAAA,KAAA,MAAW,SAAA,IAAa,KAAK,UAAA,EAAY;AACvC,MAAA,SAAA,CAAU,KAAA,EAAM;AAAA,IAClB;AAAA,EACF;AAAA;AAAA,EAGA,KAAA,CAAM,IAAA,EAAc,IAAA,GAAgC,EAAC,EAAW;AAC9D,IAAA,MAAM,KAAA,GAAQ,IAAI,OAAA,CAAO,CAAA,EAAG,KAAK,IAAI,CAAA,CAAA,EAAI,IAAI,CAAA,CAAA,EAAI;AAAA,MAC/C,OAAO,IAAA,CAAK,YAAA;AAAA,MACZ,YAAY,IAAA,CAAK,UAAA;AAAA,MACjB,SAAS,IAAA,CAAK,OAAA;AAAA,MACd,MAAM,EAAE,GAAG,IAAA,CAAK,QAAA,EAAU,GAAG,IAAA;AAAK,KACnC,CAAA;AACD,IAAA,KAAA,CAAM,gBAAgB,IAAA,CAAK,aAAA;AAC3B,IAAA,OAAO,KAAA;AAAA,EACT;AAAA,EAEQ,WAAA,CAAY,MAAA,EAAgB,KAAA,EAAgB,MAAA,EAAyB;AAE3E,IAAA,IAAI;AACF,MAAA,MAAA,CAAO,OAAA,GAAU,OAAO,MAAM,CAAA;AAAA,IAChC,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEQ,QAAA,CAAS,KAAA,EAAc,OAAA,EAAiB,IAAA,EAAiD;AAC/F,IAAA,IAAI,KAAA,GAAQ,KAAK,YAAA,EAAc;AAC7B,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,IAAI,SAAS,YAAA,CAAa;AAAA,MACxB,KAAA;AAAA,MACA,QAAQ,IAAA,CAAK,IAAA;AAAA,MACb,OAAA;AAAA,MACA,IAAA,EAAM,EAAE,GAAG,IAAA,CAAK,QAAA,EAAU,GAAG,cAAA,EAAe,EAAG,GAAG,gBAAA,CAAiB,IAAI,CAAA;AAAE,KAC1E,CAAA;AAED,IAAA,MAAM,eAAe,aAAA,EAAc;AACnC,IAAA,IAAI,iBAAiB,MAAA,EAAW;AAC9B,MAAA,MAAA,CAAO,KAAK,YAAA,KAAiB,YAAA;AAAA,IAC/B;AAEA,IAAA,KAAA,MAAW,MAAA,IAAU,KAAK,OAAA,EAAS;AACjC,MAAA,IAAI,MAAA;AACJ,MAAA,IAAI;AACF,QAAA,MAAA,GAAS,MAAA,CAAO,SAAA,GAAY,MAAA,CAAO,SAAA,CAAU,MAAM,CAAA,GAAI,MAAA;AAAA,MACzD,SAAS,KAAA,EAAO;AACd,QAAA,IAAA,CAAK,WAAA,CAAY,MAAA,EAAQ,KAAA,EAAO,MAAM,CAAA;AACtC,QAAA;AAAA,MACF;AACA,MAAA,IAAI,WAAW,IAAA,EAAM;AACnB,QAAA,OAAO,IAAA;AAAA,MACT;AACA,MAAA,MAAA,GAAS,MAAA;AAAA,IACX;AAMA,IAAA,IAAA,CAAK,aAAA,CAAc,QAAQ,MAAM;AAC/B,MAAA,IAAA,CAAK,eAAe,MAAM,CAAA;AAAA,IAC5B,CAAC,CAAA;AAED,IAAA,OAAO,MAAA;AAAA,EACT;AAAA,EAEQ,eAAe,MAAA,EAAyB;AAC9C,IAAA,KAAA,MAAW,SAAA,IAAa,KAAK,UAAA,EAAY;AACvC,MAAA,IAAI;AACF,QAAA,SAAA,CAAU,KAAA,CAAM,SAAA,CAAU,MAAA,CAAO,MAAM,GAAG,MAAM,CAAA;AAAA,MAClD,SAAS,KAAA,EAAO;AAGd,QAAA,OAAA,CAAQ,MAAM,CAAA,EAAG,SAAA,CAAU,WAAA,CAAY,IAAI,kCAAkC,KAAK,CAAA;AAAA,MACpF;AAAA,IACF;AAEA,IAAA,KAAA,MAAW,MAAA,IAAU,KAAK,OAAA,EAAS;AACjC,MAAA,IAAI;AACF,QAAA,MAAA,CAAO,WAAW,MAAM,CAAA;AAAA,MAC1B,SAAS,KAAA,EAAO;AACd,QAAA,IAAA,CAAK,WAAA,CAAY,MAAA,EAAQ,KAAA,EAAO,MAAM,CAAA;AAAA,MACxC;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,KAAA,CAAM,OAAA,EAAiB,IAAA,GAAgC,EAAC,EAAqB;AAC3E,IAAA,OAAO,IAAA,CAAK,QAAA,CAAA,CAAA,cAAsB,OAAA,EAAS,IAAI,CAAA;AAAA,EACjD;AAAA;AAAA,EAGA,KAAA,CAAM,OAAA,EAAiB,IAAA,GAAgC,EAAC,EAAqB;AAC3E,IAAA,OAAO,IAAA,CAAK,QAAA,CAAA,EAAA,cAAsB,OAAA,EAAS,IAAI,CAAA;AAAA,EACjD;AAAA;AAAA,EAGA,IAAA,CAAK,OAAA,EAAiB,IAAA,GAAgC,EAAC,EAAqB;AAC1E,IAAA,OAAO,IAAA,CAAK,QAAA,CAAA,EAAA,aAAqB,OAAA,EAAS,IAAI,CAAA;AAAA,EAChD;AAAA;AAAA,EAGA,IAAA,CAAK,OAAA,EAAiB,IAAA,GAAgC,EAAC,EAAqB;AAC1E,IAAA,OAAO,IAAA,CAAK,QAAA,CAAA,EAAA,aAAqB,OAAA,EAAS,IAAI,CAAA;AAAA,EAChD;AAAA;AAAA,EAGA,KAAA,CAAM,OAAA,EAAiB,IAAA,GAAgC,EAAC,EAAqB;AAC3E,IAAA,OAAO,IAAA,CAAK,QAAA,CAAA,EAAA,cAAsB,OAAA,EAAS,IAAI,CAAA;AAAA,EACjD;AAAA;AAAA,EAGA,KAAA,CAAM,OAAA,EAAiB,IAAA,GAAgC,EAAC,EAAqB;AAC3E,IAAA,OAAO,IAAA,CAAK,QAAA,CAAA,EAAA,cAAsB,OAAA,EAAS,IAAI,CAAA;AAAA,EACjD;AAAA;AAAA,EAGA,OAAA,CAAQ,OAAA,EAAiB,IAAA,GAAgC,EAAC,EAAqB;AAC7E,IAAA,OAAO,IAAA,CAAK,wBAAqB,OAAA,EAAS,EAAE,MAAM,SAAA,EAAW,GAAG,MAAM,CAAA;AAAA,EACxE;AAAA;AAAA,EAGA,MAAA,CAAO,OAAA,EAAiB,IAAA,GAAgC,EAAC,EAAqB;AAC5E,IAAA,OAAO,IAAA,CAAK,wBAAqB,OAAA,EAAS,EAAE,MAAM,QAAA,EAAU,GAAG,MAAM,CAAA;AAAA,EACvE;AAAA;AAAA,EAGA,WAAA,CAAY,OAAA,EAAiB,IAAA,GAAgC,EAAC,EAAqB;AACjF,IAAA,OAAO,IAAA,CAAK,wBAAqB,OAAA,EAAS,EAAE,MAAM,aAAA,EAAe,GAAG,MAAM,CAAA;AAAA,EAC5E;AAAA;AAAA,EAGA,QAAA,CAAS,OAAA,EAAiB,IAAA,GAAgC,EAAC,EAAqB;AAC9E,IAAA,OAAO,IAAA,CAAK,wBAAqB,OAAA,EAAS,EAAE,MAAM,UAAA,EAAY,GAAG,MAAM,CAAA;AAAA,EACzE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBA,MAAM,IAAA,CAAQ,IAAA,EAAc,EAAA,EAA0B,OAAA,GAAuB,EAAC,EAAe;AAC3F,IAAA,MAAM,EAAE,MAAA,EAAQ,cAAA,EAAgB,cAAc,oBAAA,EAAsB,GAAG,MAAK,GAAI,OAAA;AAChF,IAAA,MAAM,MAAA,GAAS,kBAAkB,SAAA,EAAU;AAC3C,IAAA,MAAM,KAAA,GAAQ,YAAY,GAAA,EAAI;AAE9B,IAAA,IAAI;AACF,MAAA,MAAM,SAAS,MAAM,SAAA,CAAU,MAAA,EAAQ,MAAM,IAAI,CAAA;AACjD,MAAA,IAAA,CAAK,UAAA,CAAW,MAAM,MAAA,EAAQ,oBAAA,EAAsB,YAAY,GAAA,EAAI,GAAI,OAAO,IAAI,CAAA;AACnF,MAAA,OAAO,MAAA;AAAA,IACT,SAAS,KAAA,EAAO;AACd,MAAA,IAAA,CAAK,UAAA,CAAW,MAAM,MAAA,EAAQ,oBAAA,EAAsB,YAAY,GAAA,EAAI,GAAI,KAAA,EAAO,IAAA,EAAM,KAAK,CAAA;AAC1F,MAAA,MAAM,KAAA;AAAA,IACR;AAAA,EACF;AAAA,EAEQ,WACN,IAAA,EACA,MAAA,EACA,oBAAA,EACA,UAAA,EACA,MACA,KAAA,EACM;AACN,IAAA,MAAM,QAAA,GAAoC;AAAA,MACxC,MAAA;AAAA,MACA,UAAA,EAAY,IAAA,CAAK,KAAA,CAAM,UAAA,GAAa,GAAI,CAAA,GAAI,GAAA;AAAA,MAC5C,GAAG;AAAA,KACL;AACA,IAAA,IAAI,yBAAyB,MAAA,EAAW;AACtC,MAAA,QAAA,CAAS,YAAA,GAAe,oBAAA;AAAA,IAC1B;AACA,IAAA,QAAA,CAAS,IAAA,KAAS,MAAA;AAClB,IAAA,IAAI,UAAU,MAAA,EAAW;AACvB,MAAA,QAAA,CAAS,KAAA,GAAQ,gBAAgB,KAAK,CAAA;AAAA,IACxC;AACA,IAAA,IAAA,CAAK,QAAA,CAAS,KAAA,KAAU,MAAA,GAAA,EAAA,eAAA,EAAA,aAAsC,IAAA,EAAM,QAAQ,CAAA;AAAA,EAC9E;AACF","file":"browser.mjs","sourcesContent":["/** Log levels, shared by name and numeric weight with the logquill-python contract. */\nexport enum Level {\n /** Finest-grained diagnostic detail. */\n TRACE = 5,\n /** Diagnostic detail useful in development. */\n DEBUG = 10,\n /** Notable events during normal operation. */\n INFO = 20,\n /** Something unexpected, but not (yet) an error. */\n WARN = 30,\n /** An error that didn't necessarily stop the operation. */\n ERROR = 40,\n /** An error that precedes an unrecoverable failure. */\n FATAL = 50,\n}\n\nconst NAME_TO_LEVEL: Readonly<Record<string, Level>> = {\n TRACE: Level.TRACE,\n DEBUG: Level.DEBUG,\n INFO: Level.INFO,\n WARN: Level.WARN,\n ERROR: Level.ERROR,\n FATAL: Level.FATAL,\n};\n\n/** A level given as a `Level`, a level name (any case), or its numeric weight. */\nexport type LevelInput = Level | number | string;\n\n/** The level's name, e.g. `levelName(Level.INFO) === \"INFO\"`. */\nexport function levelName(level: Level): string {\n return Level[level];\n}\n\n/** Normalize a level given as a `Level`, level name, or numeric weight. Throws if unknown. */\nexport function parseLevel(level: LevelInput): Level {\n if (typeof level === \"string\") {\n const parsed = NAME_TO_LEVEL[level.toUpperCase()];\n if (parsed === undefined) {\n throw new Error(`Unknown log level: ${level}`);\n }\n return parsed;\n }\n if (Level[level] === undefined) {\n throw new Error(`Unknown log level: ${String(level)}`);\n }\n return level;\n}\n","import { levelName, type Level } from \"./levels.js\";\n\n/** The cross-language record shape shared with logquill-python. */\nexport interface LogRecord {\n /** ISO8601 UTC timestamp with millisecond precision. */\n timestamp: string;\n /** Level name, e.g. `\"INFO\"`. */\n level: string;\n /** Name of the `Logger` that created this record. */\n logger: string;\n /** The log message. */\n message: string;\n /** Structured payload — always present, even if empty. */\n meta: Record<string, unknown>;\n}\n\n/** ISO8601 UTC timestamp with millisecond precision, matching Python's `utc_timestamp()`. */\nexport function utcTimestamp(): string {\n return new Date().toISOString();\n}\n\n/** Builds a `LogRecord` with the current UTC timestamp. Used internally by `Logger`; exported for transports/plugins that need to construct a record directly. */\nexport function createRecord(params: {\n level: Level;\n logger: string;\n message: string;\n meta: Record<string, unknown>;\n}): LogRecord {\n return {\n timestamp: utcTimestamp(),\n level: levelName(params.level),\n logger: params.logger,\n message: params.message,\n meta: params.meta,\n };\n}\n","import type { LogRecord } from \"./records.js\";\n\n/** `format(record) -> string`, per the transport contract shared with logquill-python. */\nexport interface Formatter {\n /** Turns a `LogRecord` into the string a `Transport` writes. */\n format(record: LogRecord): string;\n}\n\n/** Serializes a record to the canonical JSON line shape. */\nexport class JSONFormatter implements Formatter {\n /** Returns `JSON.stringify(record)`. */\n format(record: LogRecord): string {\n return JSON.stringify(record);\n }\n}\n","import type { LogRecord } from \"./records.js\";\n\n/**\n * The plugin pipeline hooks, matching the Python hook names: `beforeLog`,\n * `afterLog`, `onError`. All hooks are optional — implement only what you need.\n * A hook that throws cannot crash logging: the pipeline catches it, routes it\n * to `onError`, and moves on.\n */\nexport interface Plugin {\n /** Return a (possibly modified) record, or `null` to drop it. */\n beforeLog?(record: LogRecord): LogRecord | null;\n /** Called after the record has been dispatched to every transport. */\n afterLog?(record: LogRecord): void;\n /** Called when one of this plugin's own hooks throws. */\n onError?(error: unknown, record: LogRecord): void;\n}\n\n/** A plain `beforeLog`-style function, as accepted by `Logger.use()` in place of a `Plugin`. */\nexport type MiddlewareFunc = (record: LogRecord) => LogRecord | null;\n\n/**\n * Wraps a plain `beforeLog`-style function as a `Plugin`. `Logger.use()`\n * builds one of these automatically when given a function instead of a\n * `Plugin` — Express/Koa-style middleware ergonomics, without needing to\n * read the `Plugin` interface first. There's no `next()` chaining: the\n * pipeline already calls hooks in sequence, so this is sugar for a\n * single-method `Plugin`, not a new execution model.\n */\nexport class FunctionPlugin implements Plugin {\n private readonly func: MiddlewareFunc;\n\n constructor(func: MiddlewareFunc) {\n this.func = func;\n }\n\n beforeLog(record: LogRecord): LogRecord | null {\n return this.func(record);\n }\n}\n","import type { Plugin } from \"../core/plugin.js\";\nimport type { LogRecord } from \"../core/records.js\";\n\n/**\n * Injects fixed key/value pairs into every record's `meta`.\n * A value already present in a record's own `meta` wins over the fixed context.\n */\nexport class ContextPlugin implements Plugin {\n /** Fixed key/value pairs merged into every record's `meta`. */\n readonly context: Record<string, unknown>;\n\n constructor(context: Record<string, unknown>) {\n this.context = context;\n }\n\n beforeLog(record: LogRecord): LogRecord {\n return { ...record, meta: { ...this.context, ...record.meta } };\n }\n}\n","import type { Plugin } from \"../core/plugin.js\";\nimport type { LogRecord } from \"../core/records.js\";\n\n/** `meta` keys (case-insensitive) `RedactPlugin` replaces by default. */\nexport const DEFAULT_REDACTED_KEYS: readonly string[] = [\"password\", \"token\", \"secret\", \"api_key\", \"authorization\"];\n\n/** Options for {@link RedactPlugin}. */\nexport interface RedactPluginOptions {\n /** Keys (case-insensitive) to redact. Default `DEFAULT_REDACTED_KEYS`. */\n keys?: readonly string[];\n /** Placeholder a matched value is replaced with. Default `\"***\"`. */\n replacement?: string;\n}\n\n/** Replaces sensitive `meta` values, matched by key (case-insensitive), with a placeholder. */\nexport class RedactPlugin implements Plugin {\n private readonly keys: ReadonlySet<string>;\n /** Placeholder a matched value is replaced with. */\n readonly replacement: string;\n\n constructor(options: RedactPluginOptions = {}) {\n this.keys = new Set((options.keys ?? DEFAULT_REDACTED_KEYS).map((key) => key.toLowerCase()));\n this.replacement = options.replacement ?? \"***\";\n }\n\n beforeLog(record: LogRecord): LogRecord {\n const meta: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(record.meta)) {\n meta[key] = this.keys.has(key.toLowerCase()) ? this.replacement : value;\n }\n return { ...record, meta };\n }\n}\n","import type { Plugin } from \"../core/plugin.js\";\nimport type { LogRecord } from \"../core/records.js\";\n\n/**\n * Syntactic (not semantic) patterns — matched on shape, so both false\n * positives (a random 9-digit number) and false negatives (anything that\n * doesn't look like these shapes) are expected. Override via `patterns`\n * for anything stricter.\n */\nexport const DEFAULT_PII_PATTERNS: Readonly<Record<string, RegExp>> = {\n email: /\\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}\\b/g,\n ssn: /\\b\\d{3}-\\d{2}-\\d{4}\\b/g,\n creditCard: /\\b(?:\\d[ -]?){13,16}\\b/g,\n phone: /\\b(?:\\+?1[-.\\s]?)?\\(?\\d{3}\\)?[-.\\s]?\\d{3}[-.\\s]?\\d{4}\\b/g,\n};\n\nconst MAX_DEPTH = 50;\n\n/** Options for {@link PIIRedactPlugin}. */\nexport interface PIIRedactPluginOptions {\n /** Named patterns to scan for. Default `DEFAULT_PII_PATTERNS`. */\n patterns?: Readonly<Record<string, RegExp>>;\n /** Placeholder a matched substring is replaced with. Default `\"***\"`. */\n replacement?: string;\n}\n\n/**\n * Regex-based PII redaction over `meta` **values**, not just keys.\n *\n * Complements `RedactPlugin`, which redacts by exact key match —\n * `PIIRedactPlugin` scans string values (recursively through nested\n * objects/arrays) for emails, SSNs, credit-card numbers, and phone\n * numbers, and redacts matches wherever they appear, regardless of which\n * key holds them (a `notes` field containing a stray SSN is still caught).\n *\n * Detection is pattern-based: fast and dependency-free, but it matches on\n * syntactic shape, not meaning — a random 9-digit number can false-positive\n * as an SSN, and anything that doesn't fit these shapes (a name, a street\n * address) is a false negative. Pass your own `patterns` to extend or\n * replace the defaults.\n *\n * Recursion into nested `meta` structures is depth- and cycle-bounded, so a\n * circular reference or a pathologically deep structure can't hang or\n * crash the caller — it's left unredacted past the bound rather than\n * throwing.\n */\nexport class PIIRedactPlugin implements Plugin {\n /** Named patterns scanned for in every string `meta` value. */\n readonly patterns: Readonly<Record<string, RegExp>>;\n /** Placeholder a matched substring is replaced with. */\n readonly replacement: string;\n\n constructor(options: PIIRedactPluginOptions = {}) {\n this.patterns = options.patterns ?? DEFAULT_PII_PATTERNS;\n this.replacement = options.replacement ?? \"***\";\n }\n\n beforeLog(record: LogRecord): LogRecord {\n return { ...record, meta: this.redactValue(record.meta, new Set(), 0) as Record<string, unknown> };\n }\n\n private redactValue(value: unknown, seen: ReadonlySet<unknown>, depth: number): unknown {\n if (depth > MAX_DEPTH) {\n return value;\n }\n if (typeof value === \"string\") {\n return this.redactText(value);\n }\n if (Array.isArray(value)) {\n if (seen.has(value)) {\n return value; // circular reference — leave as-is rather than recurse forever\n }\n const nextSeen = new Set(seen).add(value);\n return value.map((entry) => this.redactValue(entry, nextSeen, depth + 1));\n }\n if (value !== null && typeof value === \"object\") {\n if (seen.has(value)) {\n return value;\n }\n const nextSeen = new Set(seen).add(value);\n const result: Record<string, unknown> = {};\n for (const [key, entryValue] of Object.entries(value)) {\n result[key] = this.redactValue(entryValue, nextSeen, depth + 1);\n }\n return result;\n }\n return value;\n }\n\n private redactText(text: string): string {\n let redacted = text;\n for (const pattern of Object.values(this.patterns)) {\n // Custom patterns aren't guaranteed to carry the \"g\" flag, but every\n // occurrence must be replaced (matching Python's `pattern.sub`) —\n // reconstruct with \"g\" added rather than silently stopping at the\n // first match.\n const global = pattern.global ? pattern : new RegExp(pattern.source, `${pattern.flags}g`);\n redacted = redacted.replace(global, this.replacement);\n }\n return redacted;\n }\n}\n","import { Level, parseLevel, type LevelInput } from \"../core/levels.js\";\nimport type { Plugin } from \"../core/plugin.js\";\nimport type { LogRecord } from \"../core/records.js\";\nimport type { Transport } from \"../transports/transport.js\";\n\n/** Options for {@link SamplingPlugin}. */\nexport interface SamplingPluginOptions {\n /** Source of randomness for the rate check. Defaults to `Math.random`; override with a seeded/fake generator for deterministic tests. */\n rng?: () => number;\n /** `meta` key holding the trace/run id used to group buffered records. Default `\"traceId\"`. */\n traceKey?: string;\n /** A record at or above this level elevates its whole trace. Default `Level.ERROR`. */\n elevateAt?: LevelInput;\n /** Enables tail-based elevation, writing straight to these transports on elevation. Omit to disable and get plain rate-based sampling. */\n transports?: Transport[];\n /** Total buffered records allowed across every trace before the oldest trace is evicted. Default 1000. */\n maxBufferedRecords?: number;\n /** Distinct trace ids held at once before the oldest is evicted. Default 200. */\n maxTraces?: number;\n}\n\n/**\n * Keeps roughly `rate` of records (0.0-1.0), dropping the rest.\n *\n * With `transports` set, sampling becomes tail-based per trace: a record\n * that would otherwise be dropped is buffered under its `meta[traceKey]`\n * value instead of discarded outright. If any later record sharing that\n * trace id reaches `elevateAt` or above, the whole trace is \"elevated\" —\n * every buffered record for that trace id is flushed straight to\n * `transports`, and every subsequent record for that trace id ships\n * unconditionally. This is what lets a sampled-out request still produce a\n * complete trace once it turns out to matter (it errored).\n *\n * Flushing writes buffered records directly to `transports` — pass the\n * same array given to the `Logger`. This bypasses `beforeLog`/`afterLog`/\n * `onError` for any plugin *after* `SamplingPlugin` in the pipeline (the\n * plugins before it already ran, since that's how the buffered record was\n * built); put `SamplingPlugin` last if that matters for your pipeline.\n *\n * Without `transports`, tail-based elevation is inactive and this behaves\n * exactly like plain rate-based sampling (the original behavior) — a\n * record without `meta[traceKey]` is also just rate-sampled, since there's\n * no trace to buffer it under.\n *\n * Buffering is bounded: at most `maxBufferedRecords` records total and\n * `maxTraces` distinct trace ids are held at once. Once either limit is\n * hit, the oldest buffered trace is evicted (and its records are lost, not\n * flushed) — a deliberate bounded-memory trade-off, not a bug: an\n * unbounded per-trace buffer would let a single pathologically long-lived\n * or high-cardinality trace grow memory without limit.\n */\nexport class SamplingPlugin implements Plugin {\n /** Fraction of non-elevated records kept, in `[0, 1]`. */\n readonly rate: number;\n /** `meta` key holding the trace/run id used to group buffered records. */\n readonly traceKey: string;\n /** A record at or above this level elevates its whole trace. */\n readonly elevateAt: Level;\n /** Transports buffered records are flushed straight to on elevation; `undefined` disables tail-based elevation. */\n readonly transports: Transport[] | undefined;\n /** Total buffered records allowed across every trace before the oldest trace is evicted. */\n readonly maxBufferedRecords: number;\n /** Distinct trace ids held at once before the oldest is evicted. */\n readonly maxTraces: number;\n private readonly rng: () => number;\n private readonly buffer = new Map<unknown, LogRecord[]>();\n private bufferedCount = 0;\n private readonly elevated = new Set<unknown>();\n\n constructor(rate: number, options: SamplingPluginOptions = {}) {\n if (rate < 0 || rate > 1) {\n throw new Error(`rate must be between 0 and 1, got ${String(rate)}`);\n }\n this.rate = rate;\n this.rng = options.rng ?? Math.random;\n this.traceKey = options.traceKey ?? \"traceId\";\n this.elevateAt = parseLevel(options.elevateAt ?? Level.ERROR);\n this.transports = options.transports;\n this.maxBufferedRecords = options.maxBufferedRecords ?? 1000;\n this.maxTraces = options.maxTraces ?? 200;\n }\n\n beforeLog(record: LogRecord): LogRecord | null {\n const transports = this.transports;\n if (transports === undefined) {\n return this.rng() < this.rate ? record : null;\n }\n\n const traceId = record.meta[this.traceKey];\n\n if (traceId !== undefined && this.elevated.has(traceId)) {\n return record;\n }\n\n const keep = this.rng() < this.rate;\n const reachedElevateLevel = parseLevel(record.level) >= this.elevateAt;\n\n if (traceId !== undefined && reachedElevateLevel) {\n this.elevate(traceId, transports);\n return record;\n }\n\n if (keep) {\n return record;\n }\n\n if (traceId !== undefined) {\n this.bufferRecord(traceId, record);\n }\n\n return null;\n }\n\n private elevate(traceId: unknown, transports: Transport[]): void {\n this.elevated.add(traceId);\n const buffered = this.buffer.get(traceId) ?? [];\n this.buffer.delete(traceId);\n this.bufferedCount -= buffered.length;\n for (const bufferedRecord of buffered) {\n for (const transport of transports) {\n transport.write(transport.format(bufferedRecord), bufferedRecord);\n }\n }\n }\n\n private bufferRecord(traceId: unknown, record: LogRecord): void {\n let records = this.buffer.get(traceId);\n if (records) {\n // move to the end, marking this trace as most-recently-touched\n this.buffer.delete(traceId);\n this.buffer.set(traceId, records);\n } else {\n if (this.buffer.size >= this.maxTraces) {\n this.evictOldestTrace();\n }\n records = [];\n this.buffer.set(traceId, records);\n }\n\n records.push(record);\n this.bufferedCount += 1;\n\n while (this.bufferedCount > this.maxBufferedRecords && this.buffer.size > 0) {\n this.evictOldestTrace();\n }\n }\n\n private evictOldestTrace(): void {\n const oldest = this.buffer.entries().next();\n if (oldest.done) {\n return;\n }\n const [oldestKey, oldestRecords] = oldest.value;\n this.buffer.delete(oldestKey);\n this.bufferedCount -= oldestRecords.length;\n }\n}\n","import { JSONFormatter, type Formatter } from \"../core/formatter.js\";\nimport type { LogRecord } from \"../core/records.js\";\n\n/**\n * Sink for log records, per the cross-language transport contract:\n * `format(record) -> string`, `write(formatted, record)`, `close()` on shutdown.\n */\nexport abstract class Transport {\n /** Turns a `LogRecord` into the string this transport actually writes. Defaults to `JSONFormatter`. */\n formatter: Formatter;\n\n constructor(formatter: Formatter = new JSONFormatter()) {\n this.formatter = formatter;\n }\n\n /** Formats `record` via `this.formatter`. Called once per record before `write()`. */\n format(record: LogRecord): string {\n return this.formatter.format(record);\n }\n\n /** Sends the already-formatted record to this transport's sink. */\n abstract write(formatted: string, record: LogRecord): void;\n\n /** Flush/release resources on shutdown. No-op unless a transport overrides it. */\n close(): void {}\n}\n\n/** Duck-typed: a transport (typically a `BatchingTransport`) whose `flush()` sends its current buffer now, without closing. */\nexport interface FlushableTransport {\n /** Sends the current buffer now, even if it hasn't reached its own flush threshold. */\n flush(): void | Promise<void>;\n}\n\n/** Type guard for {@link FlushableTransport} — true for any transport (e.g. every `BatchingTransport`) that exposes a `flush()` method. */\nexport function hasFlush(transport: Transport): transport is Transport & FlushableTransport {\n return typeof (transport as Partial<FlushableTransport>).flush === \"function\";\n}\n\n/** In-memory transport for tests: collects every (formatted, record) pair written to it. */\nexport class CollectingTransport extends Transport {\n /** Every formatted string passed to `write()`, in call order. */\n readonly formatted: string[] = [];\n /** Every raw `LogRecord` passed to `write()`, in call order. */\n readonly records: LogRecord[] = [];\n /** Set once `close()` has been called. */\n closed = false;\n\n write(formatted: string, record: LogRecord): void {\n this.formatted.push(formatted);\n this.records.push(record);\n }\n\n override close(): void {\n this.closed = true;\n }\n}\n","import type { Formatter } from \"../core/formatter.js\";\nimport { Level, parseLevel } from \"../core/levels.js\";\nimport type { LogRecord } from \"../core/records.js\";\nimport { Transport } from \"./transport.js\";\n\nconst COLORS: Readonly<Record<Level, string>> = {\n [Level.TRACE]: \"\\x1b[90m\", // gray\n [Level.DEBUG]: \"\\x1b[36m\", // cyan\n [Level.INFO]: \"\\x1b[32m\", // green\n [Level.WARN]: \"\\x1b[33m\", // yellow\n [Level.ERROR]: \"\\x1b[31m\", // red\n [Level.FATAL]: \"\\x1b[35m\", // magenta\n};\nconst RESET = \"\\x1b[0m\";\n\n/** The subset of `console` this transport needs — swap in a fake for tests. */\nexport interface ConsoleLike {\n /** Writes one already-formatted line, e.g. for a TRACE–WARN record. */\n log(message: string): void;\n /** Writes one already-formatted line, e.g. for an ERROR/FATAL record. */\n error(message: string): void;\n}\n\n/** Options for {@link ConsoleTransport}. */\nexport interface ConsoleTransportOptions {\n /** Turns a `LogRecord` into the string this transport writes. Defaults to `JSONFormatter`. */\n formatter?: Formatter;\n /** Wrap each line in an ANSI color escape for its level. Defaults to `true` unless the `NO_COLOR` env var is set. */\n colorize?: boolean;\n /** Sink to write through instead of the global `console` — swap in a fake for tests. */\n console?: ConsoleLike;\n}\n\nfunction defaultColorize(): boolean {\n // Isomorphic guard: `process` doesn't exist in a browser bundle.\n const env: NodeJS.ProcessEnv | undefined = typeof process === \"undefined\" ? undefined : process.env;\n return env?.NO_COLOR === undefined;\n}\n\n/**\n * Writes to `console.log`, routing ERROR/FATAL to `console.error`, colorized by\n * level. Uses the global `console` rather than Node's `process.stdout`/`stderr`\n * so this transport works unmodified in a browser bundle.\n */\nexport class ConsoleTransport extends Transport {\n /** Whether each line is wrapped in an ANSI color escape for its level. */\n colorize: boolean;\n private readonly out: ConsoleLike;\n\n constructor(options: ConsoleTransportOptions = {}) {\n super(options.formatter);\n this.colorize = options.colorize ?? defaultColorize();\n this.out = options.console ?? console;\n }\n\n /** Writes `formatted` via `console.log`, or `console.error` for ERROR/FATAL records. */\n write(formatted: string, record: LogRecord): void {\n const level = parseLevel(record.level);\n const line = this.colorize ? this.applyColor(formatted, level) : formatted;\n if (level >= Level.ERROR) {\n this.out.error(line);\n } else {\n this.out.log(line);\n }\n }\n\n private applyColor(formatted: string, level: Level): string {\n return `${COLORS[level]}${formatted}${RESET}`;\n }\n}\n","import type { Formatter } from \"../core/formatter.js\";\nimport { Transport } from \"./transport.js\";\n\n/** Sends one batch of formatted lines to `url`. Swap in a fake for tests. */\nexport type BeaconSender = (url: string, batch: readonly string[]) => void;\n\n/**\n * `@types/node`'s `Navigator` doesn't declare `sendBeacon` (it's DOM-only,\n * and this project has no DOM lib), so it's cast to this local shape at the\n * one call site that needs it.\n */\ninterface BeaconNavigator {\n sendBeacon(url: string, data: string): boolean;\n}\n\nfunction defaultBeaconSender(url: string, batch: readonly string[]): void {\n const body = batch.join(\"\\n\");\n // Isomorphic guard: `navigator` doesn't exist at runtime before Node 21,\n // and its presence there is limited (no `sendBeacon`) — same pattern as\n // ConsoleTransport's `typeof process === \"undefined\"` guard.\n const nav = typeof navigator === \"undefined\" ? undefined : (navigator as unknown as BeaconNavigator);\n if (nav && typeof nav.sendBeacon === \"function\") {\n nav.sendBeacon(url, body);\n return;\n }\n // Fallback for environments without `navigator.sendBeacon` (a worker, an\n // older browser, or this transport running under Node): `fetch` with\n // `keepalive` so the request can still complete after the page/caller\n // that queued it goes away, matching `sendBeacon`'s fire-and-forget contract.\n void fetch(url, { method: \"POST\", body, keepalive: true }).catch((error: unknown) => {\n // write()/close() are non-blocking by contract, so a send failure can't\n // propagate to the caller — report it the same way HTTPTransport does.\n console.error(\"BeaconTransport: failed to send log batch\", error);\n });\n}\n\n/** Options for {@link BeaconTransport}. */\nexport interface BeaconTransportOptions {\n /** Turns a `LogRecord` into the string this transport writes. Defaults to `JSONFormatter`. */\n formatter?: Formatter;\n /** Flush once the buffer holds this many lines. Default 20 — kept low since `sendBeacon` payloads are capped. */\n batchSize?: number;\n /** Delivers one batch. Defaults to `sendBeacon` with a `fetch(..., { keepalive: true })` fallback; override for a fake or a different backend. */\n sender?: BeaconSender;\n}\n\n/**\n * Batches formatted records and sends them via `navigator.sendBeacon`,\n * falling back to a `keepalive` `fetch` where `sendBeacon` isn't available.\n * Meant for the browser: unlike `HTTPTransport`, a beacon send can complete\n * even after the page that queued it starts unloading. Keep `batchSize`\n * small — `sendBeacon` payloads are capped (64KB in most browsers).\n */\nexport class BeaconTransport extends Transport {\n /** Endpoint each batch is sent to. */\n readonly url: string;\n /** Buffer is flushed once it holds this many lines. */\n readonly batchSize: number;\n private readonly sender: BeaconSender;\n private batch: string[] = [];\n\n constructor(url: string, options: BeaconTransportOptions = {}) {\n super(options.formatter);\n this.url = url;\n this.batchSize = options.batchSize ?? 20;\n this.sender = options.sender ?? defaultBeaconSender;\n }\n\n /** Buffers the formatted line, flushing the batch once `batchSize` is reached. */\n write(formatted: string): void {\n this.batch.push(formatted);\n if (this.batch.length >= this.batchSize) {\n this.flush();\n }\n }\n\n /** Send the current batch now, even if it hasn't reached `batchSize`. */\n flush(): void {\n if (this.batch.length === 0) {\n return;\n }\n const batch = this.batch;\n this.batch = [];\n\n try {\n this.sender(this.url, batch);\n } catch (error) {\n console.error(\"BeaconTransport: failed to send log batch\", error);\n }\n }\n\n override close(): void {\n this.flush();\n }\n}\n","/**\n * Browser-safe stand-in for `context.ts`, swapped in only when bundling the\n * `logquill/browser` entry (see the `\"#context\"` subpath import in\n * package.json's `imports` map) so that entry never pulls in\n * `node:async_hooks`. Browsers have no equivalent of `AsyncLocalStorage`,\n * so nesting is tracked with a plain stack of merged contexts instead:\n * correct for one in-flight `bindContext()` block at a time — including\n * across an internal `await`, since the frame is only popped once `fn`'s\n * returned promise settles — but, unlike the Node build, two\n * `bindContext()` blocks on the same stack running concurrently across an\n * `await` can still interleave and see each other's values, since both\n * frames sit on one shared stack with no way to tell which is \"current\"\n * independent of call order. Same documented trade-off as\n * `core/span-browser.ts`.\n */\nconst contextStack: Record<string, unknown>[] = [];\n\n/** The merged key/value pairs bound by every `bindContext()` block currently active, or `{}` outside any block. */\nexport function currentContext(): Record<string, unknown> {\n return contextStack[contextStack.length - 1] ?? {};\n}\n\nexport function bindContext<T>(values: Record<string, unknown>, fn: () => T): T {\n contextStack.push({ ...currentContext(), ...values });\n let result: T;\n try {\n result = fn();\n } catch (error) {\n contextStack.pop();\n throw error;\n }\n if (result instanceof Promise) {\n // Defer the pop until fn's returned promise settles, so a log call made\n // after an internal `await` still sees this block's context — a plain\n // synchronous `finally` would pop the frame the moment fn returns its\n // (still-pending) promise, before any of its post-`await` code runs.\n return result.finally(() => contextStack.pop()) as T;\n }\n contextStack.pop();\n return result;\n}\n","/** How a full queue behaves when another task arrives. */\nexport type BackpressurePolicy = \"dropOldest\" | \"dropNewest\" | \"block\";\n\n/** Options for the {@link DispatchQueue} constructor. */\nexport interface DispatchQueueOptions {\n /** Maximum number of pending tasks the queue holds at once. Default 10_000. */\n maxSize?: number;\n /**\n * What happens when `enqueue()` is called while the queue is already at\n * `maxSize`:\n * - `\"dropOldest\"` (default) — evict the longest-waiting task (it never\n * runs) and enqueue the new one. Favors recent records.\n * - `\"dropNewest\"` — discard the incoming task; everything already queued\n * is left alone. Favors records already in flight.\n * - `\"block\"` — run the task synchronously, right now, on the caller's\n * stack instead of queueing it. Nothing is ever dropped, at the cost of\n * the caller (e.g. `logger.info()`) taking as long as the write itself —\n * real backpressure rather than a silent drop.\n */\n policy?: BackpressurePolicy;\n /**\n * Called at most once per `warnIntervalMs` (default 5000) when the queue\n * drops tasks, with the number dropped since the last call — a\n * rate-limited way to surface sustained overload without flooding the\n * caller's own logs with one warning per drop. Defaults to `console.warn`.\n */\n onDrop?: (droppedSinceLastWarning: number, policy: BackpressurePolicy) => void;\n /** Minimum gap between `onDrop` calls. Default 5000ms. */\n warnIntervalMs?: number;\n}\n\n/** A unit of deferred work queued via `DispatchQueue.enqueue()`. */\nexport type Task = () => void | Promise<void>;\n\nfunction isPromise(value: void | Promise<void>): value is Promise<void> {\n return typeof value === \"object\" && typeof value.then === \"function\";\n}\n\nfunction defaultScheduler(run: () => void): void {\n // Node has setImmediate (a real macrotask, letting the current call stack\n // — and any synchronous work queued right after it — finish first); a\n // browser bundle falls back to a microtask.\n if (typeof setImmediate === \"function\") {\n setImmediate(run);\n } else {\n queueMicrotask(run);\n }\n}\n\nfunction defaultOnDrop(count: number, policy: BackpressurePolicy): void {\n console.warn(\n `DispatchQueue: dropped ${String(count)} record(s) — queue exceeded its configured size under the \"${policy}\" backpressure policy`,\n );\n}\n\n/**\n * A bounded, in-order queue of pending write tasks, drained outside the\n * caller's own call stack (`setImmediate`/microtask) so `Logger` methods can\n * return before the I/O they triggered actually runs. Backed by an explicit\n * size cap and backpressure policy — see `DispatchQueueOptions` — so a\n * sustained burst can never grow memory unboundedly.\n */\nexport class DispatchQueue {\n /** Maximum number of pending tasks held at once, as configured via `DispatchQueueOptions`. */\n readonly maxSize: number;\n /** Backpressure policy applied once `maxSize` is reached, as configured via `DispatchQueueOptions`. */\n readonly policy: BackpressurePolicy;\n private readonly onDrop: (count: number, policy: BackpressurePolicy) => void;\n private readonly warnIntervalMs: number;\n\n private readonly tasks: Task[] = [];\n private draining = false;\n private scheduled = false;\n private idleWaiters: (() => void)[] = [];\n private droppedSinceWarning = 0;\n private lastWarnAt = 0;\n\n constructor(options: DispatchQueueOptions = {}) {\n this.maxSize = options.maxSize ?? 10_000;\n this.policy = options.policy ?? \"dropOldest\";\n this.onDrop = options.onDrop ?? defaultOnDrop;\n this.warnIntervalMs = options.warnIntervalMs ?? 5000;\n }\n\n /** Number of tasks currently waiting to run. Bounded by `maxSize`. */\n get size(): number {\n return this.tasks.length;\n }\n\n /**\n * Queue `task` to run outside the current call stack, applying the\n * configured backpressure policy if the queue is already full. Under\n * `\"block\"`, `task` may run synchronously before this call returns.\n */\n enqueue(task: Task): void {\n if (this.tasks.length < this.maxSize) {\n this.tasks.push(task);\n this.schedule();\n return;\n }\n\n switch (this.policy) {\n case \"dropNewest\":\n this.recordDrop();\n return;\n case \"block\":\n this.runInline(task);\n return;\n case \"dropOldest\":\n default:\n this.tasks.shift();\n this.recordDrop();\n this.tasks.push(task);\n this.schedule();\n return;\n }\n }\n\n /** Resolves once every task queued so far has run. Safe to call when idle. */\n async flush(): Promise<void> {\n if (this.tasks.length === 0 && !this.draining) {\n return;\n }\n await new Promise<void>((resolve) => {\n this.idleWaiters.push(resolve);\n this.schedule();\n });\n }\n\n private recordDrop(): void {\n this.droppedSinceWarning += 1;\n const now = Date.now();\n if (now - this.lastWarnAt >= this.warnIntervalMs) {\n const count = this.droppedSinceWarning;\n this.droppedSinceWarning = 0;\n this.lastWarnAt = now;\n try {\n this.onDrop(count, this.policy);\n } catch {\n /* a broken onDrop callback must not crash logging */\n }\n }\n }\n\n private runInline(task: Task): void {\n try {\n const result = task();\n if (isPromise(result)) {\n result.catch((error: unknown) => {\n console.error(\"DispatchQueue: a blocked task failed\", error);\n });\n }\n } catch (error) {\n console.error(\"DispatchQueue: a blocked task failed\", error);\n }\n }\n\n private schedule(): void {\n if (this.scheduled) {\n return;\n }\n this.scheduled = true;\n defaultScheduler(() => {\n this.scheduled = false;\n void this.drainAll();\n });\n }\n\n private async drainAll(): Promise<void> {\n if (this.draining) {\n return;\n }\n this.draining = true;\n try {\n while (this.tasks.length > 0) {\n const task = this.tasks.shift();\n if (!task) {\n continue;\n }\n try {\n await task();\n } catch (error) {\n console.error(\"DispatchQueue: a queued task failed\", error);\n }\n }\n } finally {\n this.draining = false;\n const waiters = this.idleWaiters;\n this.idleWaiters = [];\n for (const resolve of waiters) {\n resolve();\n }\n }\n }\n}\n","/**\n * Browser-safe stand-in for `span.ts`, swapped in only when bundling the\n * `logquill/browser` entry (see the `alias` in tsup.config.ts) so that entry\n * never pulls in `node:async_hooks`/`node:crypto`. Browsers have no\n * equivalent of `AsyncLocalStorage`, so nesting is tracked with a plain\n * stack instead: correct for one span open at a time — including across an\n * internal `await`, since the frame is only popped once `fn`'s returned\n * promise settles — but, unlike the Node build, two spans on the same\n * `Logger` running concurrently across an `await` can still interleave and\n * stamp the wrong `parentSpanId`, since both sit on one shared stack with\n * no way to tell which is \"current\" independent of call order. Documented\n * trade-off, not an oversight: `test/core/tracing.test.ts`'s\n * concurrent-span guarantee is a Node-only guarantee, exercised only\n * through `src/index.ts`.\n */\nconst spanStack: string[] = [];\n\n/** The innermost span active on this stack, or `undefined` outside any span. */\nexport function currentSpanId(): string | undefined {\n return spanStack[spanStack.length - 1];\n}\n\n/** A 16-hex-char id, matching the shape of `span.ts`'s Node id and an OTel span id. */\nexport function newSpanId(): string {\n const bytes = new Uint8Array(8);\n crypto.getRandomValues(bytes);\n return Array.from(bytes, (byte) => byte.toString(16).padStart(2, \"0\")).join(\"\");\n}\n\nexport function runInSpan<T>(spanId: string, fn: () => T): T {\n spanStack.push(spanId);\n let result: T;\n try {\n result = fn();\n } catch (error) {\n spanStack.pop();\n throw error;\n }\n if (result instanceof Promise) {\n // Defer the pop until fn's returned promise settles, so a log call made\n // after an internal `await` still sees this span as current — a plain\n // synchronous `finally` would pop it the moment fn returns its\n // (still-pending) promise, before any of its post-`await` code runs.\n return result.finally(() => spanStack.pop()) as T;\n }\n spanStack.pop();\n return result;\n}\n","import { currentContext } from \"#context\";\nimport { DispatchQueue, type DispatchQueueOptions } from \"./dispatch-queue.js\";\nimport { Level, parseLevel, type LevelInput } from \"./levels.js\";\nimport { FunctionPlugin, type MiddlewareFunc, type Plugin } from \"./plugin.js\";\nimport { createRecord, type LogRecord } from \"./records.js\";\nimport { currentSpanId, newSpanId, runInSpan } from \"#span\";\nimport type { Transport } from \"../transports/transport.js\";\n\n/** Options for `Logger.span()`. Any extra keys become the span's own `meta`. */\nexport interface SpanOptions extends Record<string, unknown> {\n /** Adopt an id handed in from elsewhere (e.g. a framework's own run id) instead of generating one. */\n spanId?: string;\n /** Adopt a parent id explicitly, overriding auto-nesting from an enclosing `span()` block. */\n parentSpanId?: string;\n}\n\nfunction formatSpanError(error: unknown): string {\n if (error instanceof Error) {\n return `${error.name}: ${error.message}`;\n }\n return String(error);\n}\n\n/**\n * If `meta.err` is an `Error`, replaces it with a formatted `meta.stack`\n * (the JS analogue of `logquill-python`'s `exc_info` kwarg, which pops\n * `exc_info` and populates `meta[\"stack\"]` the same way). Left as-is\n * otherwise — a non-`Error` `meta.err` is passed through unchanged rather\n * than rejected, so a call site can't crash logging by getting this wrong.\n */\nfunction withStackFromErr(meta: Record<string, unknown>): Record<string, unknown> {\n const err = meta.err;\n if (!(err instanceof Error)) {\n return meta;\n }\n const next = { ...meta };\n delete next.err;\n next.stack = err.stack ?? `${err.name}: ${err.message}`;\n return next;\n}\n\n/** Options for the {@link Logger} constructor. */\nexport interface LoggerOptions {\n /** Minimum level that reaches a transport; records below it are dropped before any plugin runs. Default `INFO`. */\n level?: LevelInput;\n /** Sinks every record that passes the level filter and plugin pipeline is written to. */\n transports?: Transport[];\n /** Registered via `.use()` in order — a plain function is wrapped as an anonymous `Plugin`. */\n plugins?: (Plugin | MiddlewareFunc)[];\n /** Merged into every record's `meta`, before a call-site `meta` value (which always wins on collision). */\n meta?: Record<string, unknown>;\n /** Bounds and backpressure policy for the internal async dispatch queue. See `DispatchQueueOptions`. */\n queue?: DispatchQueueOptions;\n}\n\n/**\n * The core logger: leveled, structured logging over a pluggable transport\n * and plugin pipeline. Every log call returns the finished `LogRecord` (or\n * `null` if it was filtered by level or dropped by a plugin) synchronously —\n * the actual transport writes are dispatched onto an internal queue so the\n * call returns before any I/O runs; see `flush()`/`close()`.\n */\nexport class Logger {\n /** This logger's name, as passed to the constructor (or derived via `.child()`). Appears on every record as `logger`. */\n readonly name: string;\n /** Every transport a written record is sent to. */\n readonly transports: Transport[];\n /** Every plugin registered via `.use()`, in registration order. */\n readonly plugins: Plugin[];\n private currentLevel: Level;\n private readonly baseMeta: Record<string, unknown>;\n private dispatchQueue: DispatchQueue;\n\n constructor(name: string, options: LoggerOptions = {}) {\n this.name = name;\n this.currentLevel = parseLevel(options.level ?? Level.INFO);\n this.transports = options.transports ? [...options.transports] : [];\n this.plugins = [];\n for (const plugin of options.plugins ?? []) {\n this.use(plugin);\n }\n this.baseMeta = options.meta ? { ...options.meta } : {};\n this.dispatchQueue = new DispatchQueue(options.queue);\n }\n\n /** This logger's current minimum level — records below it are filtered before any plugin runs. */\n get level(): Level {\n return this.currentLevel;\n }\n\n /** Changes the minimum level records must meet to reach a transport. Accepts a `Level`, its numeric weight, or its name. */\n setLevel(level: LevelInput): void {\n this.currentLevel = parseLevel(level);\n }\n\n /**\n * Register a plugin, or a plain `beforeLog`-style function. A function is\n * wrapped internally as an anonymous `Plugin` (`FunctionPlugin`) — the\n * same middleware ergonomics as Express/Koa, without needing to read the\n * `Plugin` interface first. Returns `this` so calls can be chained.\n */\n use(plugin: Plugin | MiddlewareFunc): this {\n this.plugins.push(typeof plugin === \"function\" ? new FunctionPlugin(plugin) : plugin);\n return this;\n }\n\n /** Number of dispatched records not yet written to their transports. Bounded by the `queue` option. */\n get queueSize(): number {\n return this.dispatchQueue.size;\n }\n\n /**\n * Waits for every record dispatched so far to reach its transports'\n * `write()` (and any plugin `afterLog` hooks). Note this does *not* force\n * a batching transport (SQL, a queue, `HTTPTransport`, ...) to send a\n * batch still under its own `maxRecords`/`maxBytes` threshold early — it\n * only guarantees the record has been handed to that transport, the same\n * contract `write()` always had. Before a process may pause or exit\n * (a serverless freeze, a shutdown signal), prefer `withLambda`/\n * `installShutdownHandlers`, which additionally force every batching\n * transport to send its current buffer regardless of threshold.\n */\n async flush(): Promise<void> {\n await this.dispatchQueue.flush();\n }\n\n /** Flush every pending record, then close every attached transport. Call once, on shutdown. */\n async close(): Promise<void> {\n await this.flush();\n for (const transport of this.transports) {\n transport.close();\n }\n }\n\n /** A logger scoped under this one, inheriting its level, transports, plugins, and dispatch queue. */\n child(name: string, meta: Record<string, unknown> = {}): Logger {\n const child = new Logger(`${this.name}.${name}`, {\n level: this.currentLevel,\n transports: this.transports,\n plugins: this.plugins,\n meta: { ...this.baseMeta, ...meta },\n });\n child.dispatchQueue = this.dispatchQueue;\n return child;\n }\n\n private notifyError(plugin: Plugin, error: unknown, record: LogRecord): void {\n // a broken error handler must not crash logging either\n try {\n plugin.onError?.(error, record);\n } catch {\n /* swallowed */\n }\n }\n\n private dispatch(level: Level, message: string, meta: Record<string, unknown>): LogRecord | null {\n if (level < this.currentLevel) {\n return null;\n }\n\n let record = createRecord({\n level,\n logger: this.name,\n message,\n meta: { ...this.baseMeta, ...currentContext(), ...withStackFromErr(meta) },\n });\n\n const parentSpanId = currentSpanId();\n if (parentSpanId !== undefined) {\n record.meta.parentSpanId ??= parentSpanId;\n }\n\n for (const plugin of this.plugins) {\n let result: LogRecord | null;\n try {\n result = plugin.beforeLog ? plugin.beforeLog(record) : record;\n } catch (error) {\n this.notifyError(plugin, error, record);\n continue;\n }\n if (result === null) {\n return null;\n }\n record = result;\n }\n\n // The write itself (I/O) and afterLog are deferred onto the dispatch\n // queue so this call returns before either runs — see DispatchQueue.\n // They're bundled into one task to preserve the existing contract that\n // afterLog fires only once the record has reached every transport.\n this.dispatchQueue.enqueue(() => {\n this.writeAndNotify(record);\n });\n\n return record;\n }\n\n private writeAndNotify(record: LogRecord): void {\n for (const transport of this.transports) {\n try {\n transport.write(transport.format(record), record);\n } catch (error) {\n // a transport that can't format or write this particular record\n // (e.g. a circular reference in `meta`) must not crash the caller\n console.error(`${transport.constructor.name}: failed to write a log record`, error);\n }\n }\n\n for (const plugin of this.plugins) {\n try {\n plugin.afterLog?.(record);\n } catch (error) {\n this.notifyError(plugin, error, record);\n }\n }\n }\n\n /** Logs at `TRACE` — the lowest level, for fine-grained diagnostic detail. Returns the record, or `null` if filtered/dropped. */\n trace(message: string, meta: Record<string, unknown> = {}): LogRecord | null {\n return this.dispatch(Level.TRACE, message, meta);\n }\n\n /** Logs at `DEBUG`. Returns the record, or `null` if filtered/dropped. */\n debug(message: string, meta: Record<string, unknown> = {}): LogRecord | null {\n return this.dispatch(Level.DEBUG, message, meta);\n }\n\n /** Logs at `INFO`. Returns the record, or `null` if filtered/dropped. */\n info(message: string, meta: Record<string, unknown> = {}): LogRecord | null {\n return this.dispatch(Level.INFO, message, meta);\n }\n\n /** Logs at `WARN`. Returns the record, or `null` if filtered/dropped. */\n warn(message: string, meta: Record<string, unknown> = {}): LogRecord | null {\n return this.dispatch(Level.WARN, message, meta);\n }\n\n /** Logs at `ERROR`. Returns the record, or `null` if filtered/dropped. */\n error(message: string, meta: Record<string, unknown> = {}): LogRecord | null {\n return this.dispatch(Level.ERROR, message, meta);\n }\n\n /** Logs at `FATAL` — the highest level, for errors that precede an unrecoverable failure. Returns the record, or `null` if filtered/dropped. */\n fatal(message: string, meta: Record<string, unknown> = {}): LogRecord | null {\n return this.dispatch(Level.FATAL, message, meta);\n }\n\n /** `.info()` tagged `meta.kind = \"thought\"` — an agent's internal reasoning step, for harness/agentic tracing. */\n thought(message: string, meta: Record<string, unknown> = {}): LogRecord | null {\n return this.dispatch(Level.INFO, message, { kind: \"thought\", ...meta });\n }\n\n /** `.info()` tagged `meta.kind = \"action\"` — an agent taking an action (a tool call, an LLM request), for harness/agentic tracing. */\n action(message: string, meta: Record<string, unknown> = {}): LogRecord | null {\n return this.dispatch(Level.INFO, message, { kind: \"action\", ...meta });\n }\n\n /** `.info()` tagged `meta.kind = \"observation\"` — the result an agent observed from an action, for harness/agentic tracing. */\n observation(message: string, meta: Record<string, unknown> = {}): LogRecord | null {\n return this.dispatch(Level.INFO, message, { kind: \"observation\", ...meta });\n }\n\n /** `.info()` tagged `meta.kind = \"decision\"` — an agent's concluding decision for a step or run, for harness/agentic tracing. */\n decision(message: string, meta: Record<string, unknown> = {}): LogRecord | null {\n return this.dispatch(Level.INFO, message, { kind: \"decision\", ...meta });\n }\n\n /**\n * `await logger.span(\"callLlm\", async () => {...})` — runs `fn`, and on\n * settling (success or throw) emits one record for the span itself\n * carrying `meta.spanId` and `meta.durationMs`. Every record logged\n * inside `fn` — through any method, and through any further `await` —\n * is automatically stamped with `meta.parentSpanId` pointing at this\n * span, so nested/sub-agent calls reconstruct their exact nesting when\n * sorted by `spanId`/`parentSpanId`.\n *\n * Still emits its record — at `ERROR`, with `meta.error` set — if `fn`\n * throws; the error itself propagates unchanged to the caller.\n *\n * `spanId`/`parentSpanId` normally auto-generate/auto-nest; pass them in\n * `options` to adopt an id handed in from elsewhere (e.g. a framework\n * adapter translating an id it already received).\n */\n async span<T>(name: string, fn: () => T | Promise<T>, options: SpanOptions = {}): Promise<T> {\n const { spanId: explicitSpanId, parentSpanId: explicitParentSpanId, ...meta } = options;\n const spanId = explicitSpanId ?? newSpanId();\n const start = performance.now();\n\n try {\n const result = await runInSpan(spanId, () => fn());\n this.finishSpan(name, spanId, explicitParentSpanId, performance.now() - start, meta);\n return result;\n } catch (error) {\n this.finishSpan(name, spanId, explicitParentSpanId, performance.now() - start, meta, error);\n throw error;\n }\n }\n\n private finishSpan(\n name: string,\n spanId: string,\n explicitParentSpanId: string | undefined,\n durationMs: number,\n meta: Record<string, unknown>,\n error?: unknown,\n ): void {\n const fullMeta: Record<string, unknown> = {\n spanId,\n durationMs: Math.round(durationMs * 1000) / 1000,\n ...meta,\n };\n if (explicitParentSpanId !== undefined) {\n fullMeta.parentSpanId = explicitParentSpanId;\n }\n fullMeta.kind ??= \"span\";\n if (error !== undefined) {\n fullMeta.error = formatSpanError(error);\n }\n this.dispatch(error !== undefined ? Level.ERROR : Level.INFO, name, fullMeta);\n }\n}\n"]}