@dimah-s3/server 1.1.1 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/create-s3-endpoint.d.ts +3 -1
- package/dist/api/create-s3-endpoint.d.ts.map +1 -1
- package/dist/api/index.js +9 -0
- package/dist/api/index.js.map +1 -1
- package/dist/api/routes/confirm.d.ts.map +1 -1
- package/dist/api/routes/delete.d.ts.map +1 -1
- package/dist/api/routes/download.d.ts.map +1 -1
- package/dist/api/routes/file.d.ts.map +1 -1
- package/dist/api/routes/multipart/abort.d.ts.map +1 -1
- package/dist/api/routes/multipart/complete.d.ts.map +1 -1
- package/dist/api/routes/multipart/init.d.ts.map +1 -1
- package/dist/api/routes/multipart/list-parts.d.ts.map +1 -1
- package/dist/api/routes/multipart/part.d.ts.map +1 -1
- package/dist/api/routes/upload.d.ts.map +1 -1
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -1
- package/dist/plugins.js +9 -0
- package/dist/plugins.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/helpers/request.ts","../src/helpers/best-effort.ts","../src/errors.ts","../src/helpers/is-aws-not-found.ts","../src/helpers/expires.ts","../src/helpers/logger.ts","../src/helpers/hooks.ts","../src/helpers/previous-key.ts","../src/helpers/resolve-target.ts","../src/route.ts","../src/helpers/features.ts","../src/helpers/constraints.ts","../src/helpers/resolve-route.ts","../src/helpers/head-object.ts","../src/helpers/list-parts.ts","../src/helpers/finalize-confirmed.ts","../src/put.ts","../src/api/create-s3-middleware.ts","../src/api/create-s3-endpoint.ts","../src/api/routes/confirm.ts","../src/api/routes/delete.ts","../src/api/routes/delete-batch.ts","../src/api/routes/download.ts","../src/api/routes/catalog.ts","../src/api/routes/file.ts","../src/api/routes/multipart/abort.ts","../src/api/routes/multipart/complete.ts","../src/api/routes/multipart/init.ts","../src/api/routes/multipart/list-parts.ts","../src/api/routes/multipart/part.ts","../src/api/routes/upload.ts","../src/api/routes/index.ts","../src/plugin/chain-hooks.ts","../src/plugin/hook-registry.ts","../src/plugin/types.ts","../src/plugin/apply-plugins.ts","../src/plugin/define-plugin.ts","../src/api/bind-endpoints.ts","../src/api/router.ts","../src/dimah-s3.ts","../src/types/config.ts"],"names":["route","isAPIError","DimahS3Error","upload","download","DeleteObjectCommand","S3_API_ROUTES","isDimahS3Error","GetObjectCommand","buildContentDisposition","AbortMultipartUploadCommand","getSignedUrl","url","PutObjectCommand","S3_ERROR_CODES"],"mappings":";;;;;;;;;;AACO,SAAS,mBAAmB,OAAA,EAAgC;AACjE,EAAA,OAAO,IAAI,OAAA,CAAQ,uBAAA,EAAyB,EAAE,SAAS,CAAA;AACzD;ACIA,eAAsB,sBAAA,CACpB,MAAA,EACA,MAAA,EACA,GAAA,EACe;AACf,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,CAAO,IAAA,CAAK,IAAI,mBAAA,CAAoB,EAAE,QAAQ,MAAA,EAAQ,GAAA,EAAK,GAAA,EAAK,CAAC,CAAA;AAAA,EACzE,CAAA,CAAA,MAAQ;AAAA,EAER;AACF;AAGA,eAAsB,wBAAA,CACpB,MAAA,EACA,MAAA,EACA,GAAA,EACA,QAAA,EACe;AACf,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,CAAO,IAAA;AAAA,MACX,IAAI,2BAAA,CAA4B;AAAA,QAC9B,MAAA,EAAQ,MAAA;AAAA,QACR,GAAA,EAAK,GAAA;AAAA,QACL,QAAA,EAAU;AAAA,OACX;AAAA,KACH;AAAA,EACF,CAAA,CAAA,MAAQ;AAAA,EAER;AACF;ACnBO,IAAM,MAAA,GAAS;AAAA,EACpB,UAAU,MAAM,YAAA,CAAa,IAAA,CAAK,WAAA,EAAa,eAAe,SAAS,CAAA;AAAA,EAEvE,cAAc,MACZ,YAAA,CAAa,IAAA,CAAK,cAAA,EAAgB,eAAe,YAAY,CAAA;AAAA,EAE/D,WAAW,MAAM,YAAA,CAAa,IAAA,CAAK,WAAA,EAAa,eAAe,SAAS,CAAA;AAAA,EAExE,UAAU,MAAM,YAAA,CAAa,IAAA,CAAK,UAAA,EAAY,eAAe,QAAQ,CAAA;AAAA,EAErE,eAAe,MACb,YAAA,CAAa,IAAA,CAAK,uBAAA,EAAyB,eAAe,cAAc,CAAA;AAAA,EAE1E,gBAAgB,MACd,YAAA,CAAa,IAAA,CAAK,WAAA,EAAa,eAAe,gBAAgB,CAAA;AAAA,EAEhE,eAAA,EAAiB,CAAC,OAAA,KAChB,YAAA,CAAa,KAAK,WAAA,EAAa;AAAA,IAC7B,IAAA,EAAM,eAAe,gBAAA,CAAiB,IAAA;AAAA,IACtC,OAAA,EAAS,cAAA,CAAe,gBAAA,CAAiB,OAAA,CAAQ,UAAA;AAAA,MAC/C,WAAA;AAAA,MACA;AAAA,KACF;AAAA,IACA,MAAA,EAAQ,EAAE,OAAA;AAAQ,GACnB,CAAA;AAAA,EAEH,YAAY,MACV,YAAA,CAAa,IAAA,CAAK,aAAA,EAAe,eAAe,WAAW,CAAA;AAAA,EAE7D,YAAA,EAAc,CAACA,MAAAA,KACb,YAAA,CAAa,KAAK,WAAA,EAAa;AAAA,IAC7B,IAAA,EAAM,eAAe,aAAA,CAAc,IAAA;AAAA,IACnC,OAAA,EAAS,eAAe,aAAA,CAAc,OAAA;AAAA,IACtC,MAAA,EAAQ,EAAE,KAAA,EAAAA,MAAAA;AAAM,GACjB,CAAA;AAAA,EAEH,oBAAoB,CAAC,QAAA,EAAkB,WAAA,KACrC,YAAA,CAAa,KAAK,aAAA,EAAe;AAAA,IAC/B,IAAA,EAAM,eAAe,qBAAA,CAAsB,IAAA;AAAA,IAC3C,OAAA,EAAS,eAAe,qBAAA,CAAsB,OAAA;AAAA,IAC9C,MAAA,EAAQ;AAAA,MACN,QAAA;AAAA,MACA,GAAI,WAAA,GAAc,EAAE,WAAA,KAAgB;AAAC;AACvC,GACD,CAAA;AAAA,EAEH,cAAA,EAAgB,CAAC,IAAA,KACf,YAAA,CAAa,KAAK,aAAA,EAAe;AAAA,IAC/B,IAAA,EAAM,eAAe,gBAAA,CAAiB,IAAA;AAAA,IACtC,OAAA,EAAS,cAAA,CAAe,gBAAA,CAAiB,OAAA,CAAQ,UAAA;AAAA,MAC/C,QAAA;AAAA,MACA;AAAA,KACF;AAAA,IACA,MAAA,EAAQ,EAAE,IAAA;AAAK,GAChB,CAAA;AAAA,EAEH,oBAAA,EAAsB,CAAC,UAAA,KACrB,YAAA,CAAa,KAAK,aAAA,EAAe;AAAA,IAC/B,IAAA,EAAM,eAAe,sBAAA,CAAuB,IAAA;AAAA,IAC5C,OAAA,EAAS,cAAA,CAAe,sBAAA,CAAuB,OAAA,CAAQ,UAAA;AAAA,MACrD,cAAA;AAAA,MACA,OAAO,UAAU;AAAA,KACnB;AAAA,IACA,MAAA,EAAQ,EAAE,UAAA;AAAW,GACtB,CAAA;AAAA,EAEH,eAAA,EAAiB,CACf,OAAA,GAAkB,cAAA,CAAe,kBAAkB,OAAA,KAEnD,YAAA,CAAa,KAAK,mBAAA,EAAqB;AAAA,IACrC,GAAG,cAAA,CAAe,iBAAA;AAAA,IAClB;AAAA,GACD,CAAA;AAAA,EAEH,aAAA,EAAe,CAAC,OAAA,GAAkB,cAAA,CAAe,eAAe,OAAA,KAC9D,YAAA,CAAa,KAAK,mBAAA,EAAqB;AAAA,IACrC,GAAG,cAAA,CAAe,cAAA;AAAA,IAClB;AAAA,GACD,CAAA;AAAA,EAEH,eAAA,EAAiB,CAAC,OAAA,KAChB,YAAA,CAAa,KAAK,aAAA,EAAe;AAAA,IAC/B,IAAA,EAAM,eAAe,gBAAA,CAAiB,IAAA;AAAA,IACtC;AAAA,GACD;AACL;;;ACpGO,SAAS,cAAc,GAAA,EAAuB;AACnD,EAAA,MAAM,CAAA,GAAI,GAAA;AAKV,EAAA,OACE,CAAA,EAAG,SAAS,WAAA,IACZ,CAAA,EAAG,SAAS,UAAA,IACZ,CAAA,EAAG,SAAS,cAAA,IACZ,CAAA,EAAG,SAAS,WAAA,IACZ,CAAA,EAAG,SAAS,UAAA,IACZ,CAAA,EAAG,SAAS,cAAA,IACZ,CAAA,EAAG,WAAW,cAAA,KAAmB,GAAA;AAErC;AAGA,eAAsB,qBACpB,IAAA,EACY;AACZ,EAAA,IAAI;AACF,IAAA,OAAO,MAAM,IAAA,EAAK;AAAA,EACpB,SAAS,GAAA,EAAc;AACrB,IAAA,IAAI,aAAA,CAAc,GAAG,CAAA,EAAG,MAAM,OAAO,cAAA,EAAe;AACpD,IAAA,MAAM,GAAA;AAAA,EACR;AACF;ACxBO,SAAS,kBAAA,CACd,KAAA,EACA,YAAA,GAAuB,iBAAA,EACf;AACR,EAAA,MAAM,CAAA,GAAI,OAAO,KAAK,CAAA;AACtB,EAAA,MAAM,OAAA,GACJ,MAAA,CAAO,QAAA,CAAS,CAAC,CAAA,IAAK,IAAI,CAAA,GAAI,IAAA,CAAK,KAAA,CAAM,CAAC,CAAA,GAAI,qBAAA;AAChD,EAAA,MAAM,GAAA,GACJ,MAAA,CAAO,QAAA,CAAS,YAAY,CAAA,IAAK,eAAe,CAAA,GAC5C,IAAA,CAAK,KAAA,CAAM,YAAY,CAAA,GACvB,iBAAA;AACN,EAAA,OAAO,IAAA,CAAK,GAAA,CAAI,OAAA,EAAS,GAAG,CAAA;AAC9B;;;AChBO,IAAM,aAAA,GAA+B;AAAA,EAC1C,KAAA,EAAO,CAAC,OAAA,EAAA,GAAY,IAAA,KAAS;AAC3B,IAAA,OAAA,CAAQ,KAAA,CAAM,YAAA,EAAc,OAAA,EAAS,GAAG,IAAI,CAAA;AAAA,EAC9C,CAAA;AAAA,EACA,IAAA,EAAM,CAAC,OAAA,EAAA,GAAY,IAAA,KAAS;AAC1B,IAAA,OAAA,CAAQ,IAAA,CAAK,YAAA,EAAc,OAAA,EAAS,GAAG,IAAI,CAAA;AAAA,EAC7C;AACF,CAAA;AAEO,SAAS,cACd,MAAA,EACe;AACf,EAAA,IAAI,MAAA,KAAW,KAAA,EAAO,OAAO,EAAC;AAC9B,EAAA,IAAI,CAAC,QAAQ,OAAO,aAAA;AACpB,EAAA,OAAO,MAAA;AACT;;;ACPA,SAAS,cAAc,GAAA,EAAqB;AAC1C,EAAA,IAAIC,UAAAA,CAAW,GAAG,CAAA,EAAG,MAAM,GAAA;AAC3B,EAAA,IAAI,GAAA,YAAe,KAAA,IAAS,GAAA,CAAI,OAAA,CAAQ,MAAK,EAAG;AAC9C,IAAA,MAAM,IAAIC,aAAa,WAAA,EAAa;AAAA,MAClC,SAAS,GAAA,CAAI,OAAA;AAAA,MACb,KAAA,EAAO;AAAA,KACR,CAAA;AAAA,EACH;AACA,EAAA,MAAM,OAAO,SAAA,EAAU;AACzB;AAOA,eAAsB,OAAA,CACpB,MACA,OAAA,EACe;AACf,EAAA,IAAI,CAAC,IAAA,EAAM;AACX,EAAA,IAAI;AACF,IAAA,MAAM,KAAK,OAAO,CAAA;AAAA,EACpB,SAAS,GAAA,EAAK;AACZ,IAAA,aAAA,CAAc,GAAG,CAAA;AAAA,EACnB;AACF;AAMA,eAAsB,aAAA,CACpB,MACA,OAAA,EACkC;AAClC,EAAA,IAAI,CAAC,IAAA,EAAM;AACX,EAAA,IAAI;AACF,IAAA,OAAO,MAAM,KAAK,OAAO,CAAA;AAAA,EAC3B,SAAS,GAAA,EAAK;AACZ,IAAA,aAAA,CAAc,GAAG,CAAA;AAAA,EACnB;AACF;AAMA,eAAsB,gBAAA,CACpB,IAAA,EACA,OAAA,EACA,MAAA,EACe;AACf,EAAA,IAAI,CAAC,IAAA,EAAM;AACX,EAAA,IAAI;AACF,IAAA,MAAM,KAAK,OAAO,CAAA;AAAA,EACpB,SAAS,GAAA,EAAK;AACZ,IAAA,IAAID,UAAAA,CAAW,GAAG,CAAA,EAAG,MAAM,GAAA;AAC3B,IAAA,aAAA,CAAc,MAAA,EAAQ,MAAM,CAAA,CAAE,KAAA,GAAQ,yBAAyB,GAAG,CAAA;AAClE,IAAA,MAAA,EAAQ,UAAU,GAAA,EAAK,EAAE,OAAA,EAAS,OAAA,CAAQ,SAAS,CAAA;AACnD,IAAA,MAAM,OAAO,aAAA,EAAc;AAAA,EAC7B;AACF;;;ACvEO,IAAM,uBAAA,GAA0B,oBAAA;AAEhC,SAAS,qBACd,QAAA,EACwB;AACxB,EAAA,IAAI,CAAC,QAAA,EAAU,OAAO,EAAC;AACvB,EAAA,MAAM,EAAE,CAAC,uBAAuB,GAAG,KAAA,EAAO,GAAG,MAAK,GAAI,QAAA;AACtD,EAAA,OAAO,IAAA;AACT;AAEO,SAAS,wBACd,QAAA,EACoB;AACpB,EAAA,MAAM,KAAA,GAAQ,QAAA,GAAW,uBAAuB,CAAA,EAAG,IAAA,EAAK;AACxD,EAAA,OAAO,KAAA,IAAS,MAAA;AAClB;;;ACkBO,SAAS,oBAAoB,GAAA,EAAqB;AACvD,EAAA,MAAM,UAAA,GAAa,mBAAmB,GAAG,CAAA;AACzC,EAAA,IAAI,CAAC,UAAA,EAAY,MAAM,MAAA,CAAO,UAAA,EAAW;AACzC,EAAA,OAAO,UAAA;AACT;AAEA,SAAS,WAAA,CAAY,QAAgB,GAAA,EAAqB;AACxD,EAAA,MAAM,CAAA,GAAI,oBAAoB,MAAM,CAAA;AACpC,EAAA,MAAM,CAAA,GAAI,oBAAoB,GAAG,CAAA;AACjC,EAAA,IAAI,EAAE,UAAA,CAAW,CAAA,EAAG,CAAC,CAAA,CAAA,CAAG,GAAG,OAAO,CAAA;AAClC,EAAA,IAAI,CAAA,KAAM,CAAA,EAAG,MAAM,MAAA,CAAO,UAAA,EAAW;AACrC,EAAA,OAAO,CAAA,EAAG,CAAC,CAAA,CAAA,EAAI,CAAC,CAAA,CAAA;AAClB;AAGO,SAAS,kBAAA,CACd,WACA,GAAA,EACQ;AACR,EAAA,MAAM,IAAA,GAAO,oBAAoB,GAAG,CAAA;AACpC,EAAA,IAAI,SAAA,KAAc,OAAO,OAAO,IAAA;AAChC,EAAA,OAAO,WAAA,CAAY,WAAW,IAAI,CAAA;AACpC;AAGO,SAAS,eAAA,CACd,KACA,SAAA,EACQ;AACR,EAAA,MAAM,IAAA,GAAO,oBAAoB,GAAG,CAAA;AACpC,EAAA,IAAI,SAAA,KAAc,OAAO,OAAO,IAAA;AAChC,EAAA,MAAM,IAAA,GAAO,oBAAoB,SAAS,CAAA;AAC1C,EAAA,IAAI,KAAK,UAAA,CAAW,CAAA,EAAG,IAAI,CAAA,CAAA,CAAG,GAAG,OAAO,IAAA;AACxC,EAAA,MAAM,OAAO,UAAA,EAAW;AAC1B;AAMA,SAAS,kBAAkB,QAAA,EAA0B;AACnD,EAAA,MAAM,SAAA,GAAY,iBAAiB,QAAQ,CAAA;AAC3C,EAAA,MAAM,IAAA,GAAO,SAAA,CACV,KAAA,CAAM,GAAG,CAAA,CACT,MAAA,CAAO,CAAC,IAAA,KAAS,IAAA,CAAK,MAAA,GAAS,CAAC,CAAA,CAChC,GAAG,EAAE,CAAA;AACR,EAAA,IAAI,CAAC,IAAA,IAAQ,IAAA,KAAS,GAAA,IAAO,IAAA,KAAS,MAAM,OAAO,MAAA;AACnD,EAAA,OAAO,IAAA;AACT;AAGO,SAAS,iBAAA,CACd,QACA,QAAA,EACQ;AACR,EAAA,MAAM,IAAA,GAAO,GAAG,MAAA,CAAO,UAAA,EAAY,CAAA,CAAA,EAAI,iBAAA,CAAkB,QAAQ,CAAC,CAAA,CAAA;AAClE,EAAA,IAAI,MAAA,KAAW,KAAA,EAAO,OAAO,mBAAA,CAAoB,IAAI,CAAA;AACrD,EAAA,OAAO,WAAA,CAAY,QAAQ,IAAI,CAAA;AACjC;AAEA,SAAS,UAAA,CACP,MACAD,MAAAA,EACuB;AACvB,EAAA,OAAO,IAAA,EAAM,GAAA,IAAOA,MAAAA,CAAM,MAAA,CAAO,GAAA,IAAO,SAAA;AAC1C;AAEA,eAAsB,mBAAA,CACpBA,QACA,OAAA,EACyB;AACzB,EAAA,MAAM,SAASA,MAAAA,CAAM,MAAA;AACrB,EAAA,MAAM,aAAA,GAAqC;AAAA,IACzC,GAAG,OAAA;AAAA,IACH,MAAA;AAAA,IACA,WAAWA,MAAAA,CAAM;AAAA,GACnB;AACA,EAAA,MAAM,OACH,MAAM,aAAA,CAAcA,OAAM,MAAA,CAAO,MAAA,EAAQ,aAAa,CAAA,IAAM,MAAA;AAC/D,EAAA,MAAM,GAAA,GAAM,MAAM,GAAA,GACd,kBAAA,CAAmBA,OAAM,SAAA,EAAW,IAAA,CAAK,GAAG,CAAA,GAC5C,iBAAA;AAAA,IACE,MAAM,MAAA,IAAU,IAAA,IAAQ,IAAA,CAAK,MAAA,KAAW,KACpC,kBAAA,CAAmBA,MAAAA,CAAM,SAAA,EAAW,IAAA,CAAK,MAAM,CAAA,GAC/CA,MAAAA,CAAM,SAAA,KAAc,KAAA,GAClB,QACAA,MAAAA,CAAM,SAAA;AAAA,IACZ,QAAQ,IAAA,CAAK;AAAA,GACf;AACJ,EAAA,MAAM,QAAA,GAAW,EAAE,GAAG,IAAA,EAAM,QAAA,EAAS;AACrC,EAAA,IAAI,MAAM,WAAA,EAAa;AACrB,IAAA,QAAA,CAAS,uBAAuB,CAAA,GAAI,kBAAA;AAAA,MAClCA,MAAAA,CAAM,SAAA;AAAA,MACN,IAAA,CAAK;AAAA,KACP;AAAA,EACF;AACA,EAAA,OAAO;AAAA,IACL,GAAA;AAAA,IACA,MAAA;AAAA,IACA,QAAA,EAAU,OAAO,IAAA,CAAK,QAAQ,EAAE,MAAA,GAAS,CAAA,GAAI,WAAW,IAAA,EAAM,QAAA;AAAA,IAC9D,GAAA,EAAK,UAAA,CAAW,IAAA,EAAMA,MAAK;AAAA,GAC7B;AACF;AAEO,SAAS,mBAAA,CACdA,QACA,GAAA,EACiC;AACjC,EAAA,OAAO;AAAA,IACL,GAAA,EAAK,eAAA,CAAgB,GAAA,EAAKA,MAAAA,CAAM,SAAS,CAAA;AAAA,IACzC,QAAQA,MAAAA,CAAM;AAAA,GAChB;AACF;ACtIO,SAAS,MAA0C,MAAA,EAAc;AACtE,EAAA,OAAO,MAAA;AACT;AAEO,SAAS,gBAAgB,IAAA,EAAoB;AAClD,EAAA,IAAI,CAAC,kBAAA,CAAmB,IAAA,CAAK,IAAI,CAAA,EAAG;AAClC,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,kBAAkB,IAAI,CAAA,yFAAA;AAAA,KACxB;AAAA,EACF;AACF;;;ACNO,SAAS,UACd,OAAA,EACkC;AAClC,EAAA,OAAO,OAAA,CAAQ,OAAA;AACjB;AAEA,SAAS,gBAAA,CACP,MACA,KAAA,EACgB;AAChB,EAAA,IAAI,KAAA,KAAU,OAAO,OAAO,KAAA;AAC5B,EAAA,MAAM,UAAA,GAAa,kBAAA,CAAmB,KAAA,IAAS,IAAI,CAAA;AACnD,EAAA,IAAI,CAAC,UAAA,EAAY;AACf,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,kBAAkB,IAAI,CAAA,8CAAA;AAAA,KACxB;AAAA,EACF;AACA,EAAA,OAAO,UAAA;AACT;AAOO,SAAS,WAAA,CACd,KAAA,EACA,SAAA,GAAY,KAAA,EACH;AACT,EAAA,IAAI,KAAA,KAAU,OAAO,OAAO,KAAA;AAC5B,EAAA,IAAI,KAAA,KAAU,QAAW,OAAO,SAAA;AAChC,EAAA,IAAI,KAAA,KAAU,MAAM,OAAO,IAAA;AAC3B,EAAA,IAAI,SAAA,IAAa,KAAA,IAAS,OAAO,KAAA,CAAM,YAAY,SAAA,EAAW;AAC5D,IAAA,OAAO,KAAA,CAAM,OAAA;AAAA,EACf;AACA,EAAA,OAAO,IAAA;AACT;AAGO,SAAS,gBAAA,CACd,KAAA,EACA,SAAA,GAAY,KAAA,EACQ;AACpB,EAAA,IAAI,KAAA,KAAU,KAAA,EAAO,OAAO,EAAE,SAAS,KAAA,EAAM;AAC7C,EAAA,IAAI,UAAU,MAAA,EAAW;AACvB,IAAA,IAAI,CAAC,SAAA,EAAW,OAAO,EAAE,SAAS,KAAA,EAAM;AACxC,IAAA,OAAO,EAAE,SAAS,IAAA,EAAK;AAAA,EACzB;AACA,EAAA,IAAI,KAAA,KAAU,IAAA,EAAM,OAAO,EAAE,SAAS,IAAA,EAAK;AAC3C,EAAA,OAAO,EAAE,GAAG,KAAA,EAAO,OAAA,EAAS,IAAA,EAAK;AACnC;AAEA,SAAS,iBAAiB,OAAA,EAAqD;AAC7E,EAAA,MAAM,GAAA,uBAAU,GAAA,EAAY;AAC5B,EAAA,IAAI,CAAC,SAAS,OAAO,GAAA;AACrB,EAAA,KAAA,MAAW,CAAC,EAAA,EAAI,OAAO,KAAK,MAAA,CAAO,OAAA,CAAQ,OAAO,CAAA,EAAG;AACnD,IAAA,IAAI,OAAA,KAAY,KAAA,EAAO,GAAA,CAAI,GAAA,CAAI,EAAE,CAAA;AAAA,EACnC;AACA,EAAA,OAAO,GAAA;AACT;AAEA,SAAS,YAAYG,OAAAA,EAGnB;AACA,EAAA,IAAIA,OAAAA,KAAW,MAAA,IAAa,OAAOA,OAAAA,KAAW,SAAA,EAAW;AACvD,IAAA,OAAO,EAAE,MAAA,EAAAA,OAAAA,EAAQ,SAAA,EAAW,MAAA,EAAU;AAAA,EACxC;AACA,EAAA,MAAM,EAAE,SAAA,EAAW,GAAG,IAAA,EAAK,GAAIA,OAAAA;AAC/B,EAAA,OAAO,EAAE,MAAA,EAAQ,IAAA,EAAM,SAAA,EAAU;AACnC;AAEO,SAAS,cAAA,CACd,IAAA,EACAH,MAAAA,EACA,QAAA,EACe;AACf,EAAA,eAAA,CAAgB,IAAI,CAAA;AAEpB,EAAA,MAAM,MAAA,GAASA,MAAAA,CAAM,MAAA,IAAU,QAAA,CAAS,MAAA;AACxC,EAAA,MAAM,MAAA,GAASA,MAAAA,CAAM,MAAA,IAAU,QAAA,CAAS,MAAA;AACxC,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,kBAAkB,IAAI,CAAA,2CAAA;AAAA,KACxB;AAAA,EACF;AACA,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,kBAAkB,IAAI,CAAA,2CAAA;AAAA,KACxB;AAAA,EACF;AAEA,EAAA,MAAM,EAAE,MAAA,EAAQ,WAAA,EAAa,SAAA,EAAW,gBAAe,GAAI,WAAA;AAAA,IACzDA,MAAAA,CAAM;AAAA,GACR;AACA,EAAA,MAAMG,OAAAA,GAAS,iBAAiB,WAAW,CAAA;AAC3C,EAAA,MAAMC,SAAAA,GAAW,gBAAA,CAAiCJ,MAAAA,CAAM,QAAQ,CAAA;AAChE,EAAA,MAAM,aAAA,GAAgB,gBAAA,CAA+BA,MAAAA,CAAM,MAAM,CAAA;AACjE,EAAA,MAAM,SAAA,GAAY,iBAAkC,cAAc,CAAA;AAElE,EAAA,IAAI,CAACG,QAAO,OAAA,IAAW,CAACC,UAAS,OAAA,IAAW,CAAC,cAAc,OAAA,EAAS;AAClE,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,kBAAkB,IAAI,CAAA,sCAAA;AAAA,KACxB;AAAA,EACF;AAEA,EAAA,MAAM,cAAA,GAAuCD,OAAAA,CAAO,OAAA,GAChD,EAAE,GAAGA,OAAAA,EAAQ,SAAA,EAAU,GACvB,EAAE,SAAS,KAAA,EAAO,SAAA,EAAW,EAAE,OAAA,EAAS,OAAM,EAAE;AAEpD,EAAA,IAAI,eAAe,OAAA,EAAS;AAC1B,IAAA,MAAM,cAAc,cAAA,CAAe,WAAA;AACnC,IAAA,IACE,WAAA,IAAe,SACd,CAAC,MAAA,CAAO,SAAS,WAAW,CAAA,IAAK,eAAe,CAAA,CAAA,EACjD;AACA,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,kBAAkB,IAAI,CAAA,yCAAA;AAAA,OACxB;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,IAAA;AAAA,IACA,MAAA;AAAA,IACA,MAAA;AAAA,IACA,SAAA,EAAW,gBAAA,CAAiB,IAAA,EAAMH,MAAAA,CAAM,SAAS,CAAA;AAAA,IACjD,OAAOA,MAAAA,CAAM,KAAA;AAAA,IACb,gBAAA,EAAkB,gBAAA,CAAiBA,MAAAA,CAAM,OAAO,CAAA;AAAA,IAChD,MAAA,EAAQ,cAAA;AAAA,IACR,QAAA,EAAAI,SAAAA;AAAA,IACA,MAAA,EAAQ;AAAA,GACV;AACF;AAEO,SAAS,gBACd,MAAA,EAC+B;AAC/B,EAAA,MAAM,OAAA,GAAU,MAAA,CAAO,OAAA,CAAQ,MAAA,CAAO,MAAM,CAAA;AAC5C,EAAA,IAAI,OAAA,CAAQ,WAAW,CAAA,EAAG;AACxB,IAAA,MAAM,IAAI,MAAM,0CAA0C,CAAA;AAAA,EAC5D;AACA,EAAA,MAAM,SAAwC,EAAC;AAC/C,EAAA,KAAA,MAAW,CAAC,IAAA,EAAMJ,MAAK,CAAA,IAAK,OAAA,EAAS;AACnC,IAAA,MAAA,CAAO,IAAI,CAAA,GAAI,cAAA,CAAe,IAAA,EAAMA,QAAO,MAAM,CAAA;AAAA,EACnD;AACA,EAAA,yBAAA,CAA0B,MAAM,CAAA;AAChC,EAAA,OAAO,MAAA;AACT;AAEA,SAAS,eAAA,CAAgB,GAAW,CAAA,EAAoB;AACtD,EAAA,OAAO,CAAA,KAAM,CAAA,IAAK,CAAA,CAAE,UAAA,CAAW,CAAA,EAAG,CAAC,CAAA,CAAA,CAAG,CAAA,IAAK,CAAA,CAAE,UAAA,CAAW,CAAA,EAAG,CAAC,CAAA,CAAA,CAAG,CAAA;AACjE;AAGA,SAAS,0BACP,MAAA,EACM;AACN,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA,CAAE,MAAA;AAAA,IACnC,CAAC,KAAA,KACC,KAAA,CAAM,CAAC,EAAE,SAAA,KAAc;AAAA,GAC3B;AACA,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,KAAA,CAAM,QAAQ,CAAA,EAAA,EAAK;AACrC,IAAA,KAAA,IAAS,IAAI,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,KAAA,CAAM,QAAQ,CAAA,EAAA,EAAK;AACzC,MAAA,MAAM,CAAC,KAAA,EAAO,MAAM,CAAA,GAAI,MAAM,CAAC,CAAA;AAC/B,MAAA,MAAM,CAAC,KAAA,EAAO,MAAM,CAAA,GAAI,MAAM,CAAC,CAAA;AAC/B,MAAA,IAAI,eAAA,CAAgB,MAAA,CAAO,SAAA,EAAW,MAAA,CAAO,SAAS,CAAA,EAAG;AACvD,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,CAAA,iBAAA,EAAoB,KAAK,CAAA,OAAA,EAAU,KAAK,yCAAyC,MAAA,CAAO,SAAS,CAAA,OAAA,EAAU,MAAA,CAAO,SAAS,CAAA,GAAA;AAAA,SAC7H;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;ACrLO,SAAS,uBAAA,CACd,aACA,IAAA,EACM;AACN,EAAA,IAAI,OAAO,WAAA,KAAgB,QAAA,IAAY,IAAA,GAAO,WAAA,EAAa;AACzD,IAAA,MAAM,OAAO,eAAA,EAAgB;AAAA,EAC/B;AACF;AAEO,SAAS,yBAAA,CACd,aACA,KAAA,EACM;AACN,EAAA,IACE,WAAA,EAAa,SAAA,EAAW,MAAA,IACxB,CAAC,gBAAA,CAAiB,KAAA,CAAM,QAAA,EAAU,KAAA,CAAM,WAAA,EAAa,WAAA,CAAY,SAAS,CAAA,EAC1E;AACA,IAAA,MAAM,MAAA,CAAO,kBAAA,CAAmB,KAAA,CAAM,QAAA,EAAU,MAAM,WAAW,CAAA;AAAA,EACnE;AACA,EAAA,uBAAA,CAAwB,WAAA,EAAa,WAAA,EAAa,KAAA,CAAM,QAAQ,CAAA;AAClE;AAEO,SAAS,yBAAA,CACd,aACA,KAAA,EACM;AACN,EAAA,uBAAA,CAAwB,WAAA,EAAa,WAAA,EAAa,KAAA,CAAM,aAAa,CAAA;AACrE,EAAA,MAAM,IAAA,GAAO,MAAM,QAAA,IAAY,EAAA;AAC/B,EAAA,IACE,WAAA,EAAa,SAAA,EAAW,MAAA,IACxB,CAAC,gBAAA,CAAiB,MAAM,KAAA,CAAM,WAAA,EAAa,WAAA,CAAY,SAAS,CAAA,EAChE;AACA,IAAA,MAAM,MAAA,CAAO,kBAAA,CAAmB,IAAA,IAAQ,SAAA,EAAW,MAAM,WAAW,CAAA;AAAA,EACtE;AACF;;;ACLO,SAAS,gBAAA,CACd,QACA,IAAA,EACe;AACf,EAAA,MAAMA,MAAAA,GAAQ,MAAA,CAAO,MAAA,CAAO,IAAI,CAAA;AAChC,EAAA,IAAI,CAACA,MAAAA,EAAO;AACV,IAAA,MAAM,MAAA,CAAO,aAAa,IAAI,CAAA;AAAA,EAChC;AACA,EAAA,OAAOA,MAAAA;AACT;AAEA,SAAS,gBAAA,CACPA,QACA,OAAA,EACS;AACT,EAAA,IAAI,OAAA,KAAY,WAAA,EAAa,OAAOA,MAAAA,CAAM,OAAO,SAAA,CAAU,OAAA;AAC3D,EAAA,OAAOA,MAAAA,CAAM,OAAO,CAAA,CAAE,OAAA;AACxB;AAGO,SAAS,oBAAA,CACdA,QACA,OAAA,EACiC;AACjC,EAAA,IAAI,CAAC,gBAAA,CAAiBA,MAAAA,EAAO,OAAO,CAAA,EAAG;AACrC,IAAA,MAAM,MAAA,CAAO,gBAAgB,OAAO,CAAA;AAAA,EACtC;AACF;AAGA,eAAsB,SAAA,CACpB,MAAA,EACA,IAAA,EACA,OAAA,EACA,OAAA,EACyB;AACzB,EAAA,MAAMA,MAAAA,GAAQ,gBAAA,CAAiB,MAAA,EAAQ,IAAI,CAAA;AAC3C,EAAA,oBAAA,CAAqBA,QAAO,OAAO,CAAA;AACnC,EAAA,MAAM,OAAA,CAAQA,OAAM,KAAA,EAAO,EAAE,SAAS,KAAA,EAAOA,MAAAA,CAAM,MAAM,CAAA;AACzD,EAAA,OAAOA,MAAAA;AACT;AAEO,SAAS,mBAAA,CACd,OAAA,EACAA,MAAAA,EACA,GAAA,EACqB;AACrB,EAAA,OAAO,EAAE,SAAS,KAAA,EAAOA,MAAAA,CAAM,MAAM,GAAA,EAAK,MAAA,EAAQA,OAAM,MAAA,EAAO;AACjE;AAMA,eAAsB,gBAAA,CACpB,MAAA,EACA,KAAA,EACA,OAAA,EACA,OAAA,EACgC;AAChC,EAAA,MAAMA,SAAQ,MAAM,SAAA,CAAU,QAAQ,KAAA,CAAM,KAAA,EAAO,SAAS,OAAO,CAAA;AACnE,EAAA,MAAM,QAAA,GAAW,IAAA,CAAK,KAAA,CAAM,KAAA,CAAM,QAAQ,CAAA;AAC1C,EAAA,MAAM,WAAW,KAAA,CAAM,QAAA;AACvB,EAAA,yBAAA,CAA0BA,OAAM,MAAA,EAAQ;AAAA,IACtC,QAAA;AAAA,IACA,QAAA;AAAA,IACA,aAAa,KAAA,CAAM;AAAA,GACpB,CAAA;AACD,EAAA,MAAM,MAAA,GAAS,MAAM,mBAAA,CAAoBA,MAAAA,EAAO;AAAA,IAC9C,OAAA;AAAA,IACA,OAAOA,MAAAA,CAAM,IAAA;AAAA,IACb,IAAA,EAAM;AAAA,MACJ,IAAA,EAAM,QAAA;AAAA,MACN,IAAA,EAAM,QAAA;AAAA,MACN,MAAM,KAAA,CAAM;AAAA,KACd;AAAA,IACA,gBAAgB,KAAA,CAAM;AAAA,GACvB,CAAA;AACD,EAAA,OAAO;AAAA,IACL,KAAA,EAAAA,MAAAA;AAAA,IACA,GAAG,MAAA;AAAA,IACH,MAAA,EAAQ,mBAAA,CAAoB,OAAA,EAASA,MAAAA,EAAO,OAAO,GAAG;AAAA,GACxD;AACF;AAGA,eAAsB,gBAAA,CACpB,MAAA,EACA,KAAA,EACA,OAAA,EACA,OAAA,EAC0B;AAC1B,EAAA,MAAMA,SAAQ,MAAM,SAAA,CAAU,QAAQ,KAAA,CAAM,KAAA,EAAO,SAAS,OAAO,CAAA;AACnE,EAAA,MAAM,MAAA,GAAS,mBAAA,CAAoBA,MAAAA,EAAO,KAAA,CAAM,GAAG,CAAA;AACnD,EAAA,OAAO;AAAA,IACL,KAAA,EAAAA,MAAAA;AAAA,IACA,GAAG,MAAA;AAAA,IACH,MAAA,EAAQ,mBAAA,CAAoB,OAAA,EAASA,MAAAA,EAAO,OAAO,GAAG;AAAA,GACxD;AACF;AC/HA,eAAsB,oBAAA,CACpB,MAAA,EACA,MAAA,EACA,GAAA,EACkC;AAClC,EAAA,OAAO,oBAAA;AAAA,IAAqB,MAC1B,MAAA,CAAO,IAAA,CAAK,IAAI,iBAAA,CAAkB,EAAE,MAAA,EAAQ,MAAA,EAAQ,GAAA,EAAK,GAAA,EAAK,CAAC;AAAA,GACjE;AACF;AAMA,eAAsB,gCAAA,CACpB,MAAA,EACA,MAAA,EACA,GAAA,EACkC;AAClC,EAAA,MAAM,OAAO,MACX,oBAAA;AAAA,IAAqB,MACnB,MAAA,CAAO,IAAA,CAAK,IAAI,iBAAA,CAAkB,EAAE,MAAA,EAAQ,MAAA,EAAQ,GAAA,EAAK,GAAA,EAAK,CAAC;AAAA,GACjE;AAEF,EAAA,IAAI,IAAA,GAAO,MAAM,IAAA,EAAK;AACtB,EAAA,KAAA,IACM,OAAA,GAAU,GACd,OAAA,GAAU,CAAA,IAAK,OAAO,IAAA,CAAK,aAAA,KAAkB,UAC7C,OAAA,EAAA,EACA;AACA,IAAA,MAAM,IAAI,QAAQ,CAAC,CAAA,KAAM,WAAW,CAAA,EAAG,GAAA,GAAM,CAAA,IAAK,OAAO,CAAC,CAAA;AAC1D,IAAA,IAAA,GAAO,MAAM,IAAA,EAAK;AAAA,EACpB;AACA,EAAA,OAAO,IAAA;AACT;AAGO,SAAS,qBAAqB,IAAA,EAAuC;AAC1E,EAAA,IAAI,OAAO,IAAA,CAAK,aAAA,KAAkB,QAAA,EAAU;AAC1C,IAAA,MAAM,OAAO,aAAA,EAAc;AAAA,EAC7B;AACA,EAAA,OAAO,IAAA,CAAK,aAAA;AACd;AC1CA,eAAsB,YAAA,CACpB,QACA,KAAA,EACiB;AACjB,EAAA,MAAM,QAAgB,EAAC;AACvB,EAAA,IAAI,gBAAA;AACJ,EAAA,IAAI,WAAA,GAAc,IAAA;AAElB,EAAA,OAAO,WAAA,EAAa;AAClB,IAAA,MAAM,WAAmC,MAAM,oBAAA;AAAA,MAAqB,MAClE,MAAA,CAAO,IAAA;AAAA,QACL,IAAI,gBAAA,CAAiB;AAAA,UACnB,QAAQ,KAAA,CAAM,MAAA;AAAA,UACd,KAAK,KAAA,CAAM,GAAA;AAAA,UACX,UAAU,KAAA,CAAM,QAAA;AAAA,UAChB,GAAI,gBAAA,GAAmB,EAAE,gBAAA,EAAkB,gBAAA,KAAqB;AAAC,SAClE;AAAA;AACH,KACF;AACA,IAAA,KAAA,CAAM,IAAA,CAAK,GAAI,QAAA,CAAS,KAAA,IAAS,EAAG,CAAA;AACpC,IAAA,WAAA,GAAc,SAAS,WAAA,KAAgB,IAAA;AACvC,IAAA,gBAAA,GAAmB,WAAA,GAAc,SAAS,oBAAA,GAAuB,MAAA;AAAA,EACnE;AAEA,EAAA,OAAO,KAAA;AACT;AAGO,SAAS,mBAAA,CACd,OACA,iBAAA,EACQ;AACR,EAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,IACE,iBAAA,KAAsB,MAAA,IACtB,IAAA,CAAK,UAAA,KAAe,iBAAA,EACpB;AACA,MAAA;AAAA,IACF;AACA,IAAA,KAAA,IAAS,KAAK,IAAA,IAAQ,CAAA;AAAA,EACxB;AACA,EAAA,OAAO,KAAA;AACT;AClBA,eAAsB,uBAAA,CACpB,MAAA,EACA,MAAA,EACA,GAAA,EACA,KAAA,EACkC;AAClC,EAAA,MAAM,EAAE,QAAQ,KAAA,EAAAA,MAAAA,EAAO,QAAQ,IAAA,EAAM,QAAA,EAAU,KAAI,GAAI,KAAA;AACvD,EAAA,MAAM,aAAA,GAAgB,qBAAqB,IAAI,CAAA;AAC/C,EAAA,MAAM,QAAA,GAAW,qBAAA,CAAsB,IAAA,CAAK,kBAAA,EAAoB,GAAG,CAAA;AACnE,EAAA,MAAM,WAAA,GAAc,IAAA,CAAK,QAAA,IAAY,EAAC;AAEtC,EAAA,IAAI;AACF,IAAA,yBAAA,CAA0BA,OAAM,MAAA,EAAQ;AAAA,MACtC,QAAA;AAAA,MACA,aAAa,IAAA,CAAK,WAAA;AAAA,MAClB;AAAA,KACD,CAAA;AAAA,EACH,SAAS,GAAA,EAAK;AACZ,IAAA,MAAM,sBAAA,CAAuB,MAAA,EAAQ,MAAA,EAAQ,GAAG,CAAA;AAChD,IAAA,MAAM,GAAA;AAAA,EACR;AAEA,EAAA,MAAM,QAAA,GAAW,qBAAqB,WAAW,CAAA;AACjD,EAAA,MAAM,OAAA,GAAoC;AAAA,IACxC,GAAG,MAAA;AAAA,IACH,aAAa,IAAA,CAAK,WAAA;AAAA,IAClB,aAAA;AAAA,IACA,IAAA,EAAM,IAAA,CAAK,IAAA,EAAM,OAAA,CAAQ,MAAM,EAAE,CAAA;AAAA,IACjC,QAAA;AAAA,IACA,GAAA;AAAA,IACA,QAAA;AAAA,IACA,WAAW,IAAA,CAAK,SAAA;AAAA,IAChB,YAAA,EAAc,IAAA,CAAK,YAAA,EAAc,WAAA,EAAY;AAAA,IAC7C;AAAA,GACF;AAEA,EAAA,IAAI;AACF,IAAA,MAAM,gBAAA,CAAiBA,MAAAA,CAAM,MAAA,CAAO,WAAA,EAAa,SAAS,MAAM,CAAA;AAAA,EAClE,SAAS,GAAA,EAAK;AACZ,IAAA,MAAM,sBAAA,CAAuB,MAAA,EAAQ,MAAA,EAAQ,GAAG,CAAA;AAChD,IAAA,MAAM,GAAA;AAAA,EACR;AAEA,EAAA,MAAM,WAAA,GAAc,wBAAwB,WAAW,CAAA;AACvD,EAAA,IAAI,WAAA,IAAe,gBAAgB,GAAA,EAAK;AACtC,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,GAAO,eAAA,CAAgB,WAAA,EAAaA,MAAAA,CAAM,SAAS,CAAA;AACzD,MAAA,MAAM,sBAAA,CAAuB,MAAA,EAAQ,MAAA,EAAQ,IAAI,CAAA;AAAA,IACnD,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,GAAA;AAAA,IACA,MAAA;AAAA,IACA,aAAa,OAAA,CAAQ,WAAA;AAAA,IACrB,eAAe,OAAA,CAAQ,aAAA;AAAA,IACvB,MAAM,OAAA,CAAQ,IAAA;AAAA,IACd,QAAA,EAAU,OAAA,CAAQ,QAAA,IAAY,EAAC;AAAA,IAC/B,GAAA;AAAA,IACA,QAAA;AAAA,IACA,WAAW,OAAA,CAAQ,SAAA;AAAA,IACnB,cAAc,OAAA,CAAQ;AAAA,GACxB;AACF;;;AC/EA,SAAS,QAAQ,IAAA,EAA0C;AACzD,EAAA,IAAI,OAAO,SAAS,QAAA,EAAU,OAAO,IAAI,WAAA,EAAY,CAAE,OAAO,IAAI,CAAA;AAClE,EAAA,IAAI,IAAA,YAAgB,WAAA,EAAa,OAAO,IAAI,WAAW,IAAI,CAAA;AAC3D,EAAA,OAAO,IAAA;AACT;AAKA,eAAsB,SAAA,CACpB,QACA,KAAA,EACkC;AAClC,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,KAAA,CAAM,IAAI,CAAA;AAC/B,EAAA,MAAM,OAAA,GAAU,kBAAA,CAAmB,KAAA,CAAM,OAAO,CAAA;AAChD,EAAA,MAAM,OAAA,CAAQ,MAAA,CAAO,KAAA,EAAO,EAAE,SAAS,CAAA;AACvC,EAAA,MAAM,WAAW,IAAA,CAAK,UAAA;AACtB,EAAA,MAAM,EAAE,OAAAA,MAAAA,EAAO,GAAA,EAAK,QAAQ,QAAA,EAAU,GAAA,EAAK,MAAA,EAAO,GAAI,MAAM,gBAAA;AAAA,IAC1D,MAAA;AAAA,IACA;AAAA,MACE,OAAO,KAAA,CAAM,KAAA;AAAA,MACb,UAAU,KAAA,CAAM,QAAA;AAAA,MAChB,QAAA;AAAA,MACA,aAAa,KAAA,CAAM,WAAA;AAAA,MACnB,UAAU,KAAA,CAAM;AAAA,KAClB;AAAA,IACA,OAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAA,MAAM,OAAA,CAAQA,MAAAA,CAAM,MAAA,CAAO,KAAA,EAAO;AAAA,IAChC,GAAG,MAAA;AAAA,IACH,IAAA,EAAM;AAAA,MACJ,MAAM,KAAA,CAAM,QAAA;AAAA,MACZ,IAAA,EAAM,QAAA;AAAA,MACN,MAAM,KAAA,CAAM;AAAA,KACd;AAAA,IACA,QAAA;AAAA,IACA,gBAAgB,KAAA,CAAM,QAAA;AAAA,IACtB,GAAA;AAAA,IACA,OAAA,EAASA,OAAM,MAAA,CAAO;AAAA,GACvB,CAAA;AAED,EAAA,MAAMA,OAAM,MAAA,CAAO,IAAA;AAAA,IACjB,IAAI,gBAAA,CAAiB;AAAA,MACnB,MAAA,EAAQ,MAAA;AAAA,MACR,GAAA,EAAK,GAAA;AAAA,MACL,IAAA,EAAM,IAAA;AAAA,MACN,aAAa,KAAA,CAAM,WAAA;AAAA,MACnB,aAAA,EAAe,QAAA;AAAA,MACf,QAAA,EAAU,QAAA;AAAA,MACV,GAAA,EAAK;AAAA,KACN;AAAA,GACH;AAEA,EAAA,MAAM,OAAO,MAAM,oBAAA,CAAqBA,MAAAA,CAAM,MAAA,EAAQ,QAAQ,GAAG,CAAA;AACjE,EAAA,OAAO,uBAAA,CAAwBA,MAAAA,CAAM,MAAA,EAAQ,MAAA,EAAQ,GAAA,EAAK;AAAA,IACxD,MAAA;AAAA,IACA,KAAA,EAAAA,MAAAA;AAAA,IACA,MAAA;AAAA,IACA,IAAA;AAAA,IACA;AAAA,GACD,CAAA;AACH;AC3EO,IAAM,mBAAA,GAAsB,gBAAA,CAAiB,OAAO,GAAA,KAAQ;AACjE,EAAA,MAAM,WAAW,GAAA,CAAI,OAAA;AACrB,EAAA,IAAI,CAAC,UAAU,MAAA,EAAQ;AACrB,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AAEA,EAAA,MAAM,UACJ,GAAA,CAAI,OAAA,IACJ,SAAS,OAAA,IACT,kBAAA,CAAmB,IAAI,OAAkC,CAAA;AAE3D,EAAA,MAAM,QAAQ,QAAA,CAAS,MAAA,CAAO,KAAA,EAAO,EAAE,SAAS,CAAA;AAEhD,EAAA,OAAO;AAAA,IACL,QAAQ,QAAA,CAAS,MAAA;AAAA,IACjB;AAAA,GACF;AACF,CAAC,CAAA;AAMM,IAAM,kBAAA,GAAqB,iBAAiB,MAAA,CAAO;AAAA,EACxD,GAAA,EAAK,CAAC,mBAAmB;AAC3B,CAAC;;;AC/BD,IAAM,yBAAA,GAA4B,eAAe,MAAA,CAAO;AAAA,EACtD,GAAA,EAAK,CAAC,mBAAmB;AAC3B,CAAC,CAAA;AAED,SAAS,iBAA4C,OAAA,EAAe;AAClE,EAAA,OAAO;AAAA,IACL,GAAG,OAAA;AAAA,IACH,mBACE,OAAA,CAAQ,iBAAA,KACP,CAAC,EAAE,SAAQ,KAA2B;AACrC,MAAA,MAAM,MAAA,CAAO,gBAAgB,OAAO,CAAA;AAAA,IACtC,CAAA;AAAA,GACJ;AACF;AAoBO,IAAM,gBAAA,IAAsC,CACjD,aAAA,EACA,gBAAA,EACA,YAAA,KACG;AACH,EAAA,IAAI,OAAO,kBAAkB,QAAA,EAAU;AACrC,IAAA,OAAO,yBAAA;AAAA,MACL,aAAA;AAAA,MACA,iBAAiB,gBAAmC,CAAA;AAAA,MACpD;AAAA,KACF;AAAA,EACF;AACA,EAAA,OAAO,yBAAA;AAAA,IACL,iBAAiB,aAAa,CAAA;AAAA,IAC9B;AAAA,GACF;AACF,CAAA;;;AC3CA,eAAe,aAAA,CACb,MAAA,EACA,KAAA,EACA,OAAA,EACA;AACA,EAAA,MAAM,EAAE,KAAA,EAAAA,MAAAA,EAAO,KAAK,MAAA,EAAQ,MAAA,KAAW,MAAM,gBAAA;AAAA,IAC3C,MAAA;AAAA,IACA,KAAA;AAAA,IACA,OAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAA,MAAM,OAAA,CAAQA,MAAAA,CAAM,MAAA,CAAO,YAAA,EAAc;AAAA,IACvC,GAAG,MAAA;AAAA,IACH,OAAA,EAASA,OAAM,MAAA,CAAO;AAAA,GACvB,CAAA;AAED,EAAA,MAAM,OAAO,MAAM,oBAAA,CAAqBA,MAAAA,CAAM,MAAA,EAAQ,QAAQ,GAAG,CAAA;AACjE,EAAA,OAAO,uBAAA,CAAwBA,MAAAA,CAAM,MAAA,EAAQ,MAAA,EAAQ,GAAA,EAAK;AAAA,IACxD,MAAA;AAAA,IACA,KAAA,EAAAA,MAAAA;AAAA,IACA,MAAA;AAAA,IACA,IAAA;AAAA,IACA,GAAA,EAAKA,OAAM,MAAA,CAAO;AAAA,GACnB,CAAA;AACH;AAEO,IAAM,OAAA,GAAU,gBAAA;AAAA,EACrB,aAAA,CAAc,aAAA;AAAA,EACd,EAAE,MAAA,EAAQ,MAAA,EAAQ,IAAA,EAAM,iBAAA,EAAkB;AAAA,EAC1C,OAAO,GAAA,KAAQ;AACb,IAAA,OAAO,aAAA,CAAc,IAAI,OAAA,CAAQ,MAAA,EAAQ,IAAI,IAAA,EAAM,GAAA,CAAI,QAAQ,OAAO,CAAA;AAAA,EACxE;AACF,CAAA;AC5BA,eAAe,YAAA,CACb,MAAA,EACA,KAAA,EACA,OAAA,EACyB;AACzB,EAAA,MAAM,EAAE,KAAA,EAAAA,MAAAA,EAAO,KAAK,MAAA,EAAQ,MAAA,KAAW,MAAM,gBAAA;AAAA,IAC3C,MAAA;AAAA,IACA,KAAA;AAAA,IACA,OAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAA,MAAM,OAAA,CAAQA,MAAAA,CAAM,MAAA,CAAO,KAAA,EAAO,MAAM,CAAA;AAExC,EAAA,MAAM,oBAAA,CAAqBA,MAAAA,CAAM,MAAA,EAAQ,MAAA,EAAQ,GAAG,CAAA;AAEpD,EAAA,MAAMA,OAAM,MAAA,CAAO,IAAA;AAAA,IACjB,IAAIK,mBAAAA,CAAoB,EAAE,QAAQ,MAAA,EAAQ,GAAA,EAAK,KAAK;AAAA,GACtD;AAEA,EAAA,MAAM,gBAAA,CAAiBL,MAAAA,CAAM,MAAA,CAAO,SAAA,EAAW,QAAQ,MAAM,CAAA;AAE7D,EAAA,OAAO,EAAE,OAAA,EAAS,IAAA,EAAM,MAAA,EAAQ,GAAA,EAAI;AACtC;AAEO,IAAM,YAAA,GAAe,gBAAA;AAAA,EAC1BM,aAAAA,CAAc,MAAA;AAAA,EACd,EAAE,MAAA,EAAQ,QAAA,EAAU,KAAA,EAAO,iBAAA,EAAkB;AAAA,EAC7C,OAAO,GAAA,KAAQ;AACb,IAAA,OAAO,YAAA,CAAa,IAAI,OAAA,CAAQ,MAAA,EAAQ,IAAI,KAAA,EAAO,GAAA,CAAI,QAAQ,OAAO,CAAA;AAAA,EACxE;AACF,CAAA;AC9BA,eAAe,SAAA,CACb,MAAA,EACA,SAAA,EACA,GAAA,EACA,OAAA,EACe;AACf,EAAA,MAAM,EAAE,KAAA,EAAAN,MAAAA,EAAO,MAAA,EAAQ,MAAA,KAAW,MAAM,gBAAA;AAAA,IACtC,MAAA;AAAA,IACA,EAAE,KAAA,EAAO,SAAA,EAAW,GAAA,EAAI;AAAA,IACxB,OAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAA,MAAM,OAAA,CAAQA,MAAAA,CAAM,MAAA,CAAO,KAAA,EAAO,MAAM,CAAA;AACxC,EAAA,MAAM,oBAAA,CAAqBA,MAAAA,CAAM,MAAA,EAAQ,MAAA,EAAQ,OAAO,GAAG,CAAA;AAC3D,EAAA,MAAMA,OAAM,MAAA,CAAO,IAAA;AAAA,IACjB,IAAIK,oBAAoB,EAAE,MAAA,EAAQ,QAAQ,GAAA,EAAK,MAAA,CAAO,KAAK;AAAA,GAC7D;AACA,EAAA,MAAM,gBAAA,CAAiBL,MAAAA,CAAM,MAAA,CAAO,SAAA,EAAW,QAAQ,MAAM,CAAA;AAC/D;AAEO,IAAM,WAAA,GAAc,gBAAA;AAAA,EACzBM,aAAAA,CAAc,WAAA;AAAA,EACd,EAAE,MAAA,EAAQ,MAAA,EAAQ,IAAA,EAAM,qBAAA,EAAsB;AAAA,EAC9C,OAAO,GAAA,KAAsC;AAC3C,IAAA,MAAM,MAAA,GAAS,IAAI,OAAA,CAAQ,MAAA;AAC3B,IAAA,MAAM,OAAA,GAAU,IAAI,OAAA,CAAQ,OAAA;AAC5B,IAAA,MAAM,UAA0C,EAAC;AAEjD,IAAA,KAAA,MAAW,GAAA,IAAO,GAAA,CAAI,IAAA,CAAK,IAAA,EAAM;AAC/B,MAAA,IAAI;AACF,QAAA,MAAM,UAAU,MAAA,EAAQ,GAAA,CAAI,IAAA,CAAK,KAAA,EAAO,KAAK,OAAO,CAAA;AACpD,QAAA,OAAA,CAAQ,IAAA,CAAK,EAAE,GAAA,EAAK,OAAA,EAAS,MAAM,CAAA;AAAA,MACrC,SAAS,GAAA,EAAK;AACZ,QAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,UACX,GAAA;AAAA,UACA,OAAA,EAAS,KAAA;AAAA,UACT,OAAOC,cAAAA,CAAe,GAAG,CAAA,GACrB,EAAE,MAAM,GAAA,CAAI,IAAA,IAAQ,gBAAA,EAAkB,OAAA,EAAS,IAAI,OAAA,EAAQ,GAC3D,EAAE,IAAA,EAAM,gBAAA,EAAkB,SAAS,uBAAA;AAAwB,SAChE,CAAA;AAAA,MACH;AAAA,IACF;AAEA,IAAA,OAAO,EAAE,OAAA,EAAQ;AAAA,EACnB;AACF,CAAA;AC5CA,SAAS,OAAA,CACP,OAAA,EACA,QAAA,EACA,KAAA,EAMQ;AACR,EAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,OAAA,CAAQ,GAAG,CAAA;AAC/B,EAAA,MAAM,MAAA,GAAS,SAAS,QAAA,CAAS,GAAG,IAAI,QAAA,CAAS,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA,GAAI,QAAA;AAChE,EAAA,GAAA,CAAI,QAAA,GAAW,CAAA,EAAG,MAAM,CAAA,EAAGD,cAAc,IAAI,CAAA,CAAA;AAC7C,EAAA,GAAA,CAAI,MAAA,GAAS,EAAA;AACb,EAAA,GAAA,CAAI,YAAA,CAAa,GAAA,CAAI,OAAA,EAAS,KAAA,CAAM,KAAK,CAAA;AACzC,EAAA,GAAA,CAAI,YAAA,CAAa,GAAA,CAAI,KAAA,EAAO,KAAA,CAAM,GAAG,CAAA;AACrC,EAAA,IAAI,MAAM,QAAA,EAAU,GAAA,CAAI,aAAa,GAAA,CAAI,UAAA,EAAY,MAAM,QAAQ,CAAA;AACnE,EAAA,IAAI,MAAM,WAAA,EAAa,GAAA,CAAI,aAAa,GAAA,CAAI,aAAA,EAAe,MAAM,WAAW,CAAA;AAC5E,EAAA,OAAO,IAAI,QAAA,EAAS;AACtB;AAEA,eAAe,cAAA,CACb,MAAA,EACA,KAAA,EACA,OAAA,EACkC;AAClC,EAAA,MAAM,EAAE,KAAA,EAAAN,MAAAA,EAAO,KAAK,MAAA,EAAQ,MAAA,KAAW,MAAM,gBAAA;AAAA,IAC3C,MAAA;AAAA,IACA,KAAA;AAAA,IACA,OAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAA,MAAM,QAAA,GAAW,MAAMA,MAAAA,CAAM,QAAA,CAAS,OAAA,GAAU;AAAA,IAC9C,GAAG,MAAA;AAAA,IACH,UAAU,KAAA,CAAM,QAAA;AAAA,IAChB,WAAA,EAAa,KAAA,CAAM,WAAA,IAAeA,MAAAA,CAAM,QAAA,CAAS;AAAA,GAClD,CAAA;AAED,EAAA,MAAM,QAAA,GAAW,QAAA,EAAU,QAAA,IAAY,KAAA,CAAM,QAAA;AAC7C,EAAA,MAAM,cACJ,QAAA,EAAU,WAAA,IACV,MAAM,WAAA,IACNA,MAAAA,CAAM,SAAS,WAAA,IACf,YAAA;AACF,EAAA,MAAM,SAAA,GAAY,kBAAA;AAAA,IAChB,QAAA,EAAU,SAAA,IAAaA,MAAAA,CAAM,QAAA,CAAS,SAAA;AAAA,IACtC,MAAA,CAAO;AAAA,GACT;AAEA,EAAA,MAAM,OAAA,CAAQA,MAAAA,CAAM,QAAA,CAAS,KAAA,EAAO;AAAA,IAClC,GAAG,MAAA;AAAA,IACH,QAAA;AAAA,IACA;AAAA,GACD,CAAA;AAED,EAAA,MAAM,oBAAA,CAAqBA,MAAAA,CAAM,MAAA,EAAQ,MAAA,EAAQ,GAAG,CAAA;AAEpD,EAAA,MAAM,IAAA,GAAOA,MAAAA,CAAM,QAAA,CAAS,IAAA,IAAQ,SAAA;AACpC,EAAA,MAAM,kBAAA,GAAqB,QAAA,GACvB,uBAAA,CAAwB,QAAA,EAAU,WAAW,CAAA,GAC7C,WAAA;AAEJ,EAAA,MAAM,MACJ,IAAA,KAAS,OAAA,GACL,QAAQ,OAAA,EAAS,MAAA,CAAO,YAAY,SAAA,EAAW;AAAA,IAC7C,OAAO,KAAA,CAAM,KAAA;AAAA,IACb,GAAA;AAAA,IACA,QAAA;AAAA,IACA;AAAA,GACD,IACD,MAAM,YAAA;AAAA,IACJA,MAAAA,CAAM,MAAA;AAAA,IACN,IAAI,gBAAA,CAAiB;AAAA,MACnB,MAAA,EAAQ,MAAA;AAAA,MACR,GAAA,EAAK,GAAA;AAAA,MACL,0BAAA,EAA4B;AAAA,KAC7B,CAAA;AAAA,IACD,EAAE,SAAA;AAAU,GACd;AAEN,EAAA,MAAM,gBAAA;AAAA,IACJA,OAAM,QAAA,CAAS,WAAA;AAAA,IACf;AAAA,MACE,GAAG,MAAA;AAAA,MACH,QAAA;AAAA,MACA,GAAA;AAAA,MACA,SAAA,EAAW,IAAA,KAAS,OAAA,GAAU,CAAA,GAAI;AAAA,KACpC;AAAA,IACA;AAAA,GACF;AAEA,EAAA,OAAO;AAAA,IACL,MAAA;AAAA,IACA,GAAA;AAAA,IACA,GAAA;AAAA,IACA,SAAA,EAAW,IAAA,KAAS,OAAA,GAAU,CAAA,GAAI,SAAA;AAAA,IAClC,IAAA;AAAA,IACA;AAAA,GACF;AACF;AAEO,IAAM,QAAA,GAAW,gBAAA;AAAA,EACtBM,aAAAA,CAAc,QAAA;AAAA,EACd,EAAE,MAAA,EAAQ,KAAA,EAAO,KAAA,EAAO,mBAAA,EAAoB;AAAA,EAC5C,OAAO,GAAA,KAAQ;AACb,IAAA,OAAO,cAAA,CAAe,IAAI,OAAA,CAAQ,MAAA,EAAQ,IAAI,KAAA,EAAO,GAAA,CAAI,QAAQ,OAAO,CAAA;AAAA,EAC1E;AACF,CAAA;ACrHA,SAAS,cACPH,OAAAA,EAC6B;AAC7B,EAAA,IAAI,CAAC,SAAA,CAAUA,OAAM,GAAG,OAAO,EAAE,SAAS,KAAA,EAAM;AAChD,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,IAAA;AAAA,IACT,WAAWA,OAAAA,CAAO,SAAA;AAAA,IAClB,aAAaA,OAAAA,CAAO,WAAA;AAAA,IACpB,SAAA,EAAW,SAAA,CAAUA,OAAAA,CAAO,SAAS,CAAA;AAAA,IACrC,GAAIA,OAAAA,CAAO,QAAA,GAAW,EAAE,QAAA,EAAU,IAAA,KAAS,EAAC;AAAA,IAC5C,GAAIA,QAAO,OAAA,GAAU,EAAE,SAASA,OAAAA,CAAO,OAAA,KAAY;AAAC,GACtD;AACF;AAEA,SAAS,gBACPC,SAAAA,EAC+B;AAC/B,EAAA,IAAI,CAAC,SAAA,CAAUA,SAAQ,GAAG,OAAO,EAAE,SAAS,KAAA,EAAM;AAClD,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,IAAA;AAAA,IACT,GAAIA,UAAS,WAAA,GAAc,EAAE,aAAaA,SAAAA,CAAS,WAAA,KAAgB,EAAC;AAAA,IACpE,GAAIA,UAAS,IAAA,GAAO,EAAE,MAAMA,SAAAA,CAAS,IAAA,KAAS;AAAC,GACjD;AACF;AAEO,SAAS,kBACd,MAAA,EACsB;AACtB,EAAA,MAAM,SAAyC,EAAC;AAChD,EAAA,KAAA,MAAW,CAAC,MAAMJ,MAAK,CAAA,IAAK,OAAO,OAAA,CAAQ,MAAA,CAAO,MAAM,CAAA,EAAG;AACzD,IAAA,MAAA,CAAO,IAAI,CAAA,GAAI;AAAA,MACb,MAAA,EAAQ,aAAA,CAAcA,MAAAA,CAAM,MAAM,CAAA;AAAA,MAClC,QAAA,EAAU,eAAA,CAAgBA,MAAAA,CAAM,QAAQ,CAAA;AAAA,MACxC,MAAA,EAAQ,SAAA,CAAUA,MAAAA,CAAM,MAAM,CAAA,GAAI,EAAE,OAAA,EAAS,IAAA,EAAK,GAAI,EAAE,OAAA,EAAS,KAAA;AAAM,KACzE;AAAA,EACF;AACA,EAAA,OAAO,EAAE,MAAA,EAAO;AAClB;AAEO,IAAM,OAAA,GAAU,gBAAA;AAAA,EACrBM,aAAAA,CAAc,OAAA;AAAA,EACd,EAAE,QAAQ,KAAA,EAAM;AAAA,EAChB,OAAO,GAAA,KAAuC;AAC5C,IAAA,OAAO,iBAAA,CAAkB,GAAA,CAAI,OAAA,CAAQ,MAAM,CAAA;AAAA,EAC7C;AACF,CAAA;ACrCA,eAAe,UAAA,CACb,MAAA,EACA,KAAA,EACA,OAAA,EACmB;AACnB,EAAA,MAAM,EAAE,KAAA,EAAAN,MAAAA,EAAO,KAAK,MAAA,EAAQ,MAAA,KAAW,MAAM,gBAAA;AAAA,IAC3C,MAAA;AAAA,IACA,KAAA;AAAA,IACA,OAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAA,MAAM,QAAA,GAAW,MAAMA,MAAAA,CAAM,QAAA,CAAS,OAAA,GAAU;AAAA,IAC9C,GAAG,MAAA;AAAA,IACH,UAAU,KAAA,CAAM,QAAA;AAAA,IAChB,WAAA,EAAa,KAAA,CAAM,WAAA,IAAeA,MAAAA,CAAM,QAAA,CAAS;AAAA,GAClD,CAAA;AACD,EAAA,MAAM,QAAA,GAAW,QAAA,EAAU,QAAA,IAAY,KAAA,CAAM,QAAA;AAC7C,EAAA,MAAM,cACJ,QAAA,EAAU,WAAA,IACV,MAAM,WAAA,IACNA,MAAAA,CAAM,SAAS,WAAA,IACf,YAAA;AAEF,EAAA,MAAM,OAAA,CAAQA,MAAAA,CAAM,QAAA,CAAS,KAAA,EAAO;AAAA,IAClC,GAAG,MAAA;AAAA,IACH,QAAA;AAAA,IACA;AAAA,GACD,CAAA;AAED,EAAA,MAAM,oBAAA,CAAqBA,MAAAA,CAAM,MAAA,EAAQ,MAAA,EAAQ,GAAG,CAAA;AAEpD,EAAA,MAAM,SAAS,MAAM,oBAAA;AAAA,IAAqB,MACxCA,OAAM,MAAA,CAAO,IAAA;AAAA,MACX,IAAIQ,gBAAAA,CAAiB;AAAA,QACnB,MAAA,EAAQ,MAAA;AAAA,QACR,GAAA,EAAK,GAAA;AAAA,QACL,4BAA4B,QAAA,GACxBC,uBAAAA,CAAwB,UAAU,WAAW,CAAA,GAC7C,GAAG,WAAW,CAAA;AAAA,OACnB;AAAA;AACH,GACF;AAEA,EAAA,MAAM,OAAO,MAAA,CAAO,IAAA;AACpB,EAAA,IAAI,CAAC,IAAA,EAAM,MAAM,MAAA,CAAO,cAAA,EAAe;AAEvC,EAAA,MAAM,MAAA,GACJ,0BAA0B,IAAA,IAC1B,OAAO,KAAK,oBAAA,KAAyB,UAAA,GACjC,IAAA,CAAK,oBAAA,EAAqB,GACzB,IAAA;AAEP,EAAA,MAAM,OAAA,GAAU,IAAI,OAAA,EAAQ;AAC5B,EAAA,OAAA,CAAQ,GAAA,CAAI,cAAA,EAAgB,MAAA,CAAO,WAAA,IAAe,0BAA0B,CAAA;AAC5E,EAAA,OAAA,CAAQ,GAAA;AAAA,IACN,qBAAA;AAAA,IACA,WACIA,uBAAAA,CAAwB,QAAA,EAAU,WAAW,CAAA,GAC7C,GAAG,WAAW,CAAA;AAAA,GACpB;AACA,EAAA,IAAI,OAAO,MAAA,CAAO,aAAA,KAAkB,QAAA,EAAU;AAC5C,IAAA,OAAA,CAAQ,GAAA,CAAI,gBAAA,EAAkB,MAAA,CAAO,MAAA,CAAO,aAAa,CAAC,CAAA;AAAA,EAC5D;AAEA,EAAA,OAAO,IAAI,QAAA,CAAS,MAAA,EAAQ,EAAE,SAAS,CAAA;AACzC;AAEO,IAAM,IAAA,GAAO,gBAAA;AAAA,EAClBH,aAAAA,CAAc,IAAA;AAAA,EACd,EAAE,MAAA,EAAQ,KAAA,EAAO,KAAA,EAAO,eAAA,EAAgB;AAAA,EACxC,OAAO,GAAA,KAAQ;AACb,IAAA,OAAO,UAAA,CAAW,IAAI,OAAA,CAAQ,MAAA,EAAQ,IAAI,KAAA,EAAO,GAAA,CAAI,QAAQ,OAAO,CAAA;AAAA,EACtE;AACF,CAAA;AC5EA,eAAe,WAAA,CACb,MAAA,EACA,KAAA,EACA,OAAA,EACiC;AACjC,EAAA,MAAM,EAAE,KAAA,EAAAN,MAAAA,EAAO,KAAK,MAAA,EAAQ,MAAA,KAAW,MAAM,gBAAA;AAAA,IAC3C,MAAA;AAAA,IACA,KAAA;AAAA,IACA,OAAA;AAAA,IACA;AAAA,GACF;AACA,EAAA,MAAM,WAAW,KAAA,CAAM,QAAA;AAEvB,EAAA,MAAM,OAAA,CAAQA,MAAAA,CAAM,MAAA,CAAO,SAAA,CAAU,KAAA,EAAO;AAAA,IAC1C,GAAG,MAAA;AAAA,IACH,QAAA;AAAA,IACA,MAAA,EAAQ;AAAA,GACT,CAAA;AAED,EAAA,MAAM,oBAAA;AAAA,IAAqB,MACzBA,OAAM,MAAA,CAAO,IAAA;AAAA,MACX,IAAIU,2BAAAA,CAA4B;AAAA,QAC9B,MAAA,EAAQ,MAAA;AAAA,QACR,GAAA,EAAK,GAAA;AAAA,QACL,QAAA,EAAU;AAAA,OACX;AAAA;AACH,GACF;AAEA,EAAA,MAAM,gBAAA;AAAA,IACJV,MAAAA,CAAM,OAAO,SAAA,CAAU,OAAA;AAAA,IACvB;AAAA,MACE,GAAG,MAAA;AAAA,MACH;AAAA,KACF;AAAA,IACA;AAAA,GACF;AAEA,EAAA,OAAO,EAAE,MAAA,EAAQ,GAAA,EAAK,QAAA,EAAU,SAAS,IAAA,EAAK;AAChD;AAEO,IAAM,cAAA,GAAiB,gBAAA;AAAA,EAC5BM,aAAAA,CAAc,cAAA;AAAA,EACd,EAAE,MAAA,EAAQ,MAAA,EAAQ,IAAA,EAAM,wBAAA,EAAyB;AAAA,EACjD,OAAO,GAAA,KAAQ;AACb,IAAA,OAAO,WAAA,CAAY,IAAI,OAAA,CAAQ,MAAA,EAAQ,IAAI,IAAA,EAAM,GAAA,CAAI,QAAQ,OAAO,CAAA;AAAA,EACtE;AACF,CAAA;ACvCA,eAAe,cAAA,CACb,MAAA,EACA,KAAA,EACA,OAAA,EACoC;AACpC,EAAA,MAAM,EAAE,KAAA,EAAAN,MAAAA,EAAO,KAAK,MAAA,EAAQ,MAAA,KAAW,MAAM,gBAAA;AAAA,IAC3C,MAAA;AAAA,IACA,KAAA;AAAA,IACA,OAAA;AAAA,IACA;AAAA,GACF;AACA,EAAA,MAAM,WAAW,KAAA,CAAM,QAAA;AACvB,EAAA,MAAM,KAAA,GAAQ;AAAA,IACZ,GAAG,IAAI,GAAA,CAAI,KAAA,CAAM,KAAA,CAAM,GAAA,CAAI,CAAC,EAAE,UAAA,EAAW,KAAM,UAAU,CAAC;AAAA,IAC1D,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,IAAI,CAAC,CAAA;AACtB,EAAA,MAAM,WAAW,KAAA,CAAM,GAAA,CAAI,CAAC,UAAA,MAAgB,EAAE,YAAW,CAAE,CAAA;AAE3D,EAAA,MAAM,OAAA,CAAQA,MAAAA,CAAM,MAAA,CAAO,SAAA,CAAU,KAAA,EAAO;AAAA,IAC1C,GAAG,MAAA;AAAA,IACH,QAAA;AAAA,IACA,MAAA,EAAQ;AAAA,GACT,CAAA;AACD,EAAA,MAAM,OAAA,CAAQA,MAAAA,CAAM,MAAA,CAAO,YAAA,EAAc;AAAA,IACvC,GAAG,MAAA;AAAA,IACH,QAAA;AAAA,IACA,KAAA,EAAO,QAAA;AAAA,IACP,OAAA,EAASA,OAAM,MAAA,CAAO;AAAA,GACvB,CAAA;AAED,EAAA,MAAM,WAAA,GAAc,MAAM,YAAA,CAAaA,MAAAA,CAAM,MAAA,EAAQ;AAAA,IACnD,MAAA;AAAA,IACA,GAAA;AAAA,IACA;AAAA,GACD,CAAA;AAED,EAAA,IAAI,cAAA,GAAiB,CAAA;AACrB,EAAA,MAAM,aAAA,GAAgB,KAAA,CAAM,GAAA,CAAI,CAAC,UAAA,KAAe;AAC9C,IAAA,MAAM,QAAQ,WAAA,CAAY,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,eAAe,UAAU,CAAA;AACjE,IAAA,IAAI,CAAC,OAAO,IAAA,EAAM;AAChB,MAAA,MAAM,MAAA,CAAO,qBAAqB,UAAU,CAAA;AAAA,IAC9C;AACA,IAAA,cAAA,IAAkB,MAAM,IAAA,IAAQ,CAAA;AAChC,IAAA,OAAO,EAAE,UAAA,EAAY,UAAA,EAAY,IAAA,EAAM,MAAM,IAAA,EAAK;AAAA,EACpD,CAAC,CAAA;AAED,EAAA,IAAI;AACF,IAAA,uBAAA,CAAwBA,MAAAA,CAAM,MAAA,CAAO,WAAA,EAAa,cAAc,CAAA;AAAA,EAClE,SAAS,GAAA,EAAK;AACZ,IAAA,MAAM,wBAAA,CAAyBA,MAAAA,CAAM,MAAA,EAAQ,MAAA,EAAQ,KAAK,QAAQ,CAAA;AAClE,IAAA,MAAM,GAAA;AAAA,EACR;AAEA,EAAA,MAAM,iBACJ,MAAM,oBAAA;AAAA,IAAqB,MACzBA,OAAM,MAAA,CAAO,IAAA;AAAA,MACX,IAAI,8BAAA,CAA+B;AAAA,QACjC,MAAA,EAAQ,MAAA;AAAA,QACR,GAAA,EAAK,GAAA;AAAA,QACL,QAAA,EAAU,QAAA;AAAA,QACV,eAAA,EAAiB,EAAE,KAAA,EAAO,aAAA;AAAc,OACzC;AAAA;AACH,GACF;AAEF,EAAA,MAAM,OAAO,MAAM,gCAAA;AAAA,IACjBA,MAAAA,CAAM,MAAA;AAAA,IACN,MAAA;AAAA,IACA;AAAA,GACF;AACA,EAAA,MAAM,YAAY,MAAM,uBAAA,CAAwBA,MAAAA,CAAM,MAAA,EAAQ,QAAQ,GAAA,EAAK;AAAA,IACzE,MAAA;AAAA,IACA,KAAA,EAAAA,MAAAA;AAAA,IACA,MAAA;AAAA,IACA,IAAA,EAAM;AAAA,MACJ,GAAG,IAAA;AAAA,MACH,IAAA,EAAM,IAAA,CAAK,IAAA,IAAQ,cAAA,CAAe;AAAA,KACpC;AAAA,IACA,QAAA;AAAA,IACA,GAAA,EAAKA,OAAM,MAAA,CAAO;AAAA,GACnB,CAAA;AAED,EAAA,OAAO,EAAE,GAAG,SAAA,EAAW,QAAA,EAAS;AAClC;AAEO,IAAM,iBAAA,GAAoB,gBAAA;AAAA,EAC/BM,aAAAA,CAAc,iBAAA;AAAA,EACd,EAAE,MAAA,EAAQ,MAAA,EAAQ,IAAA,EAAM,2BAAA,EAA4B;AAAA,EACpD,OAAO,GAAA,KAAQ;AACb,IAAA,OAAO,cAAA,CAAe,IAAI,OAAA,CAAQ,MAAA,EAAQ,IAAI,IAAA,EAAM,GAAA,CAAI,QAAQ,OAAO,CAAA;AAAA,EACzE;AACF,CAAA;AClGA,eAAe,mBAAA,CACb,MAAA,EACA,KAAA,EACA,OAAA,EACgC;AAChC,EAAA,MAAM,QAAA,GAAW,IAAA,CAAK,KAAA,CAAM,KAAA,CAAM,QAAQ,CAAA;AAC1C,EAAA,MAAM,WAAW,KAAA,CAAM,QAAA;AACvB,EAAA,MAAM,EAAE,OAAAN,MAAAA,EAAO,GAAA,EAAK,QAAQ,QAAA,EAAU,GAAA,EAAK,MAAA,EAAO,GAAI,MAAM,gBAAA;AAAA,IAC1D,MAAA;AAAA,IACA;AAAA,MACE,OAAO,KAAA,CAAM,KAAA;AAAA,MACb,QAAA;AAAA,MACA,QAAA;AAAA,MACA,aAAa,KAAA,CAAM,WAAA;AAAA,MACnB,UAAU,KAAA,CAAM;AAAA,KAClB;AAAA,IACA,OAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAA,MAAM,OAAA,CAAQA,MAAAA,CAAM,MAAA,CAAO,KAAA,EAAO;AAAA,IAChC,GAAG,MAAA;AAAA,IACH,IAAA,EAAM;AAAA,MACJ,IAAA,EAAM,QAAA;AAAA,MACN,IAAA,EAAM,QAAA;AAAA,MACN,MAAM,KAAA,CAAM;AAAA,KACd;AAAA,IACA,QAAA;AAAA,IACA,gBAAgB,KAAA,CAAM,QAAA;AAAA,IACtB,GAAA;AAAA,IACA,OAAA,EAASA,OAAM,MAAA,CAAO;AAAA,GACvB,CAAA;AAED,EAAA,MAAM,EAAE,QAAA,EAAS,GAAK,MAAMA,OAAM,MAAA,CAAO,IAAA;AAAA,IACvC,IAAI,4BAAA,CAA6B;AAAA,MAC/B,MAAA,EAAQ,MAAA;AAAA,MACR,GAAA,EAAK,GAAA;AAAA,MACL,aAAa,KAAA,CAAM,WAAA;AAAA,MACnB,kBAAA,EAAoBS,wBAAwB,QAAQ,CAAA;AAAA,MACpD,QAAA,EAAU,QAAA;AAAA,MACV,GAAA,EAAK;AAAA,KACN;AAAA,GACH;AAEA,EAAA,IAAI,CAAC,QAAA,EAAU;AACb,IAAA,MAAM,OAAO,aAAA,EAAc;AAAA,EAC7B;AAEA,EAAA,MAAM,gBAAA;AAAA,IACJT,MAAAA,CAAM,OAAO,SAAA,CAAU,MAAA;AAAA,IACvB;AAAA,MACE,GAAG,MAAA;AAAA,MACH,QAAA,EAAU,QAAA;AAAA,MACV,IAAA,EAAM;AAAA,QACJ,IAAA,EAAM,QAAA;AAAA,QACN,IAAA,EAAM,QAAA;AAAA,QACN,MAAM,KAAA,CAAM;AAAA,OACd;AAAA,MACA,QAAA;AAAA,MACA,gBAAgB,KAAA,CAAM,QAAA;AAAA,MACtB,GAAA;AAAA,MACA,OAAA,EAASA,OAAM,MAAA,CAAO;AAAA,KACxB;AAAA,IACA;AAAA,GACF;AAEA,EAAA,OAAO,EAAE,MAAA,EAAQ,GAAA,EAAK,QAAA,EAAU,QAAA,EAAS;AAC3C;AAEO,IAAM,aAAA,GAAgB,gBAAA;AAAA,EAC3BM,aAAAA,CAAc,aAAA;AAAA,EACd,EAAE,MAAA,EAAQ,MAAA,EAAQ,IAAA,EAAM,uBAAA,EAAwB;AAAA,EAChD,OAAO,GAAA,KAAQ;AACb,IAAA,MAAM,SAAS,MAAM,mBAAA;AAAA,MACnB,IAAI,OAAA,CAAQ,MAAA;AAAA,MACZ,GAAA,CAAI,IAAA;AAAA,MACJ,IAAI,OAAA,CAAQ;AAAA,KACd;AACA,IAAA,GAAA,CAAI,UAAU,GAAG,CAAA;AACjB,IAAA,OAAO,MAAA;AAAA,EACT;AACF,CAAA;AClFA,eAAe,eAAA,CACb,MAAA,EACA,KAAA,EACA,OAAA,EACqC;AACrC,EAAA,MAAM,EAAE,KAAA,EAAAN,MAAAA,EAAO,KAAK,MAAA,EAAQ,MAAA,KAAW,MAAM,gBAAA;AAAA,IAC3C,MAAA;AAAA,IACA,KAAA;AAAA,IACA,OAAA;AAAA,IACA;AAAA,GACF;AACA,EAAA,MAAM,WAAW,KAAA,CAAM,QAAA;AAEvB,EAAA,MAAM,OAAA,CAAQA,MAAAA,CAAM,MAAA,CAAO,SAAA,CAAU,KAAA,EAAO;AAAA,IAC1C,GAAG,MAAA;AAAA,IACH,QAAA;AAAA,IACA,MAAA,EAAQ;AAAA,GACT,CAAA;AAED,EAAA,MAAM,MAAA,GAAS,MAAM,YAAA,CAAaA,MAAAA,CAAM,QAAQ,EAAE,MAAA,EAAQ,GAAA,EAAK,QAAA,EAAU,CAAA;AAEzE,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,OAAA,CAAQ,CAAC,CAAA,KAAM;AAClC,IAAA,IAAI,EAAE,UAAA,IAAc,IAAA,IAAQ,EAAE,UAAA,GAAa,CAAA,SAAU,EAAC;AACtD,IAAA,OAAO;AAAA,MACL;AAAA,QACE,YAAY,CAAA,CAAE,UAAA;AAAA,QACd,IAAA,EAAM,EAAE,IAAA,IAAQ,CAAA;AAAA,QAChB,OAAO,CAAA,CAAE,IAAA,IAAQ,EAAA,EAAI,OAAA,CAAQ,MAAM,EAAE;AAAA;AACvC,KACF;AAAA,EACF,CAAC,CAAA;AAED,EAAA,MAAM,gBAAA;AAAA,IACJA,MAAAA,CAAM,OAAO,SAAA,CAAU,MAAA;AAAA,IACvB;AAAA,MACE,GAAG,MAAA;AAAA,MACH,QAAA;AAAA,MACA;AAAA,KACF;AAAA,IACA;AAAA,GACF;AAEA,EAAA,OAAO,EAAE,KAAA,EAAM;AACjB;AAEO,IAAM,kBAAA,GAAqB,gBAAA;AAAA,EAChCM,aAAAA,CAAc,kBAAA;AAAA,EACd,EAAE,MAAA,EAAQ,KAAA,EAAO,KAAA,EAAO,6BAAA,EAA8B;AAAA,EACtD,OAAO,GAAA,KAAQ;AACb,IAAA,OAAO,eAAA,CAAgB,IAAI,OAAA,CAAQ,MAAA,EAAQ,IAAI,KAAA,EAAO,GAAA,CAAI,QAAQ,OAAO,CAAA;AAAA,EAC3E;AACF,CAAA;AC/CA,eAAe,cAAA,CACb,MAAA,EACA,KAAA,EACA,OAAA,EACgC;AAChC,EAAA,MAAM,EAAE,KAAA,EAAAN,MAAAA,EAAO,KAAK,MAAA,EAAQ,MAAA,KAAW,MAAM,gBAAA;AAAA,IAC3C,MAAA;AAAA,IACA,KAAA;AAAA,IACA,OAAA;AAAA,IACA;AAAA,GACF;AACA,EAAA,MAAM,WAAW,KAAA,CAAM,QAAA;AACvB,EAAA,MAAM,aAAa,KAAA,CAAM,UAAA;AACzB,EAAA,MAAM,SAAA,GAAY,kBAAA;AAAA,IAChBA,OAAM,MAAA,CAAO,SAAA;AAAA,IACb,MAAA,CAAO;AAAA,GACT;AACA,EAAA,MAAM,QAAA,GAAW,IAAA,CAAK,KAAA,CAAM,KAAA,CAAM,QAAQ,CAAA;AAE1C,EAAA,MAAM,OAAA,CAAQA,MAAAA,CAAM,MAAA,CAAO,SAAA,CAAU,KAAA,EAAO;AAAA,IAC1C,GAAG,MAAA;AAAA,IACH,QAAA;AAAA,IACA,MAAA,EAAQ,MAAA;AAAA,IACR,UAAA;AAAA,IACA;AAAA,GACD,CAAA;AAED,EAAA,MAAM,WAAA,GAAcA,OAAM,MAAA,CAAO,WAAA;AACjC,EAAA,uBAAA,CAAwB,aAAa,QAAQ,CAAA;AAC7C,EAAA,IAAI,OAAO,gBAAgB,QAAA,EAAU;AACnC,IAAA,MAAM,MAAA,GAAS,MAAM,YAAA,CAAaA,MAAAA,CAAM,QAAQ,EAAE,MAAA,EAAQ,GAAA,EAAK,QAAA,EAAU,CAAA;AACzE,IAAA,uBAAA;AAAA,MACE,WAAA;AAAA,MACA,mBAAA,CAAoB,MAAA,EAAQ,UAAU,CAAA,GAAI;AAAA,KAC5C;AAAA,EACF;AAEA,EAAA,MAAM,MAAM,MAAMW,YAAAA;AAAA,IAChBX,MAAAA,CAAM,MAAA;AAAA,IACN,IAAI,iBAAA,CAAkB;AAAA,MACpB,MAAA,EAAQ,MAAA;AAAA,MACR,GAAA,EAAK,GAAA;AAAA,MACL,QAAA,EAAU,QAAA;AAAA,MACV,UAAA,EAAY,UAAA;AAAA,MACZ,aAAA,EAAe;AAAA,KAChB,CAAA;AAAA,IACD;AAAA,MACE,SAAA;AAAA,MACA,eAAA,kBAAiB,IAAI,GAAA,CAAI,CAAC,gBAAgB,CAAC;AAAA;AAC7C,GACF;AAEA,EAAA,OAAO;AAAA,IACL,GAAA;AAAA,IACA,UAAA;AAAA,IACA,QAAA;AAAA,IACA,MAAA;AAAA,IACA,SAAA;AAAA,IACA;AAAA,GACF;AACF;AAEO,IAAM,aAAA,GAAgB,gBAAA;AAAA,EAC3BM,aAAAA,CAAc,aAAA;AAAA,EACd,EAAE,MAAA,EAAQ,MAAA,EAAQ,IAAA,EAAM,2BAAA,EAA4B;AAAA,EACpD,OAAO,GAAA,KAAQ;AACb,IAAA,OAAO,cAAA,CAAe,IAAI,OAAA,CAAQ,MAAA,EAAQ,IAAI,IAAA,EAAM,GAAA,CAAI,QAAQ,OAAO,CAAA;AAAA,EACzE;AACF,CAAA;AClEA,SAAS,mBACP,QAAA,EACwB;AACxB,EAAA,IAAI,CAAC,QAAA,EAAU,OAAO,EAAC;AACvB,EAAA,MAAM,SAAiC,EAAC;AACxC,EAAA,KAAA,MAAW,CAAC,CAAA,EAAG,CAAC,KAAK,MAAA,CAAO,OAAA,CAAQ,QAAQ,CAAA,EAAG;AAC7C,IAAA,MAAA,CAAO,CAAA,WAAA,EAAc,CAAC,CAAA,CAAE,CAAA,GAAI,CAAA;AAAA,EAC9B;AACA,EAAA,OAAO,MAAA;AACT;AAEA,eAAe,YAAA,CACb,MAAA,EACA,KAAA,EACA,OAAA,EACgC;AAChC,EAAA,MAAM,QAAA,GAAW,IAAA,CAAK,KAAA,CAAM,KAAA,CAAM,QAAQ,CAAA;AAC1C,EAAA,MAAM,WAAW,KAAA,CAAM,QAAA;AACvB,EAAA,MAAM,EAAE,OAAAN,MAAAA,EAAO,GAAA,EAAK,QAAQ,QAAA,EAAU,GAAA,EAAK,MAAA,EAAO,GAAI,MAAM,gBAAA;AAAA,IAC1D,MAAA;AAAA,IACA;AAAA,MACE,OAAO,KAAA,CAAM,KAAA;AAAA,MACb,QAAA;AAAA,MACA,QAAA;AAAA,MACA,aAAa,KAAA,CAAM,WAAA;AAAA,MACnB,UAAU,KAAA,CAAM;AAAA,KAClB;AAAA,IACA,OAAA;AAAA,IACA;AAAA,GACF;AACA,EAAA,MAAM,MAAA,GAASA,MAAAA,CAAM,MAAA,CAAO,MAAA,IAAU,MAAA;AACtC,EAAA,IAAIA,MAAAA,CAAM,MAAA,CAAO,QAAA,IAAY,CAAC,MAAM,QAAA,EAAU;AAC5C,IAAA,MAAM,MAAA,CAAO,gBAAgB,qCAAqC,CAAA;AAAA,EACpE;AACA,EAAA,IAAI,MAAA,KAAW,MAAA,IAAU,QAAA,GAAW,wBAAA,EAA0B;AAC5D,IAAA,MAAM,MAAA,CAAO,eAAA;AAAA,MACX,8BAA8B,wBAAwB,CAAA,8DAAA;AAAA,KACxD;AAAA,EACF;AAEA,EAAA,MAAM,SAAA,GAAY,kBAAA;AAAA,IAChBA,OAAM,MAAA,CAAO,SAAA;AAAA,IACb,MAAA,CAAO;AAAA,GACT;AACA,EAAA,MAAM,WAAA,GAAc,MAAM,WAAA,IAAe,0BAAA;AACzC,EAAA,MAAM,OAAA,GAAU;AAAA,IACd,GAAG,MAAA;AAAA,IACH,IAAA,EAAM;AAAA,MACJ,IAAA,EAAM,QAAA;AAAA,MACN,IAAA,EAAM,QAAA;AAAA,MACN,MAAM,KAAA,CAAM;AAAA,KACd;AAAA,IACA,QAAA;AAAA,IACA,gBAAgB,KAAA,CAAM,QAAA;AAAA,IACtB,GAAA;AAAA,IACA,OAAA,EAASA,OAAM,MAAA,CAAO;AAAA,GACxB;AAEA,EAAA,MAAM,OAAA,CAAQA,MAAAA,CAAM,MAAA,CAAO,KAAA,EAAO,OAAO,CAAA;AAEzC,EAAA,IAAI,WAAW,KAAA,EAAO;AACpB,IAAA,MAAM,UAAA,GAAqC;AAAA,MACzC,cAAA,EAAgB,WAAA;AAAA,MAChB,GAAG,mBAAmB,QAAQ,CAAA;AAAA,MAC9B,qBAAA,EAAuBS,wBAAwB,QAAQ,CAAA;AAAA,MACvD,GAAI,MAAM,QAAA,GAAW,EAAE,yBAAyB,KAAA,CAAM,QAAA,KAAa;AAAC,KACtE;AAEA,IAAA,MAAMG,OAAM,MAAMD,YAAAA;AAAA,MAChBX,MAAAA,CAAM,MAAA;AAAA,MACN,IAAIa,gBAAAA,CAAiB;AAAA,QACnB,MAAA,EAAQ,MAAA;AAAA,QACR,GAAA,EAAK,GAAA;AAAA,QACL,WAAA,EAAa,WAAA;AAAA,QACb,GAAA,EAAK,GAAA;AAAA,QACL,QAAA,EAAU,QAAA;AAAA,QACV,kBAAA,EAAoBJ,wBAAwB,QAAQ,CAAA;AAAA,QACpD,aAAA,EAAe,QAAA;AAAA,QACf,GAAI,KAAA,CAAM,QAAA,GACN,EAAE,cAAA,EAAgB,MAAM,QAAA,EAAU,iBAAA,EAAmB,QAAA,EAAS,GAC9D;AAAC,OACN,CAAA;AAAA,MACD;AAAA,QACE,SAAA;AAAA,QACA,eAAA,sBAAqB,GAAA,CAAI;AAAA,UACvB,gBAAA;AAAA,UACA,GAAI,KAAA,CAAM,QAAA,GAAW,CAAC,uBAAuB,IAAI;AAAC,SACnD;AAAA;AACH,KACF;AAEA,IAAA,MAAM,gBAAA;AAAA,MACJT,OAAM,MAAA,CAAO,WAAA;AAAA,MACb;AAAA,QACE,GAAG,OAAA;AAAA,QACH,GAAA,EAAAY,IAAAA;AAAA,QACA;AAAA,OACF;AAAA,MACA;AAAA,KACF;AAEA,IAAA,OAAO;AAAA,MACL,MAAA;AAAA,MACA,GAAA;AAAA,MACA,GAAA,EAAAA,IAAAA;AAAA,MACA,OAAA,EAAS,UAAA;AAAA,MACT,SAAA;AAAA,MACA,MAAA,EAAQ;AAAA,KACV;AAAA,EACF;AAEA,EAAA,MAAM,MAAA,GAAiC;AAAA,IACrC,GAAA;AAAA,IACA,cAAA,EAAgB,WAAA;AAAA,IAChB,qBAAA,EAAuBH,wBAAwB,QAAQ,CAAA;AAAA,IACvD,GAAG,mBAAmB,QAAQ,CAAA;AAAA,IAC9B,GAAI,MAAM,QAAA,GAAW,EAAE,yBAAyB,KAAA,CAAM,QAAA,KAAa;AAAC,GACtE;AAEA,EAAA,MAAM,EAAE,GAAA,EAAK,MAAA,EAAQ,YAAA,KAAiB,MAAM,mBAAA;AAAA,IAC1CT,MAAAA,CAAM,MAAA;AAAA,IACN;AAAA,MACE,MAAA,EAAQ,MAAA;AAAA,MACR,GAAA,EAAK,GAAA;AAAA,MACL,YAAY,CAAC,CAAC,sBAAA,EAAwB,QAAA,EAAU,QAAQ,CAAC,CAAA;AAAA,MACzD,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS;AAAA;AACX,GACF;AAEA,EAAA,MAAM,gBAAA;AAAA,IACJA,OAAM,MAAA,CAAO,WAAA;AAAA,IACb;AAAA,MACE,GAAG,OAAA;AAAA,MACH,GAAA;AAAA,MACA;AAAA,KACF;AAAA,IACA;AAAA,GACF;AAEA,EAAA,OAAO;AAAA,IACL,MAAA;AAAA,IACA,GAAA;AAAA,IACA,GAAA;AAAA,IACA,MAAA,EAAQ,YAAA;AAAA,IACR,SAAA;AAAA,IACA,MAAA,EAAQ;AAAA,GACV;AACF;AAEO,IAAM,MAAA,GAAS,gBAAA;AAAA,EACpBM,aAAAA,CAAc,MAAA;AAAA,EACd,EAAE,MAAA,EAAQ,MAAA,EAAQ,IAAA,EAAM,gBAAA,EAAiB;AAAA,EACzC,OAAO,GAAA,KAAQ;AACb,IAAA,OAAO,YAAA,CAAa,IAAI,OAAA,CAAQ,MAAA,EAAQ,IAAI,IAAA,EAAM,GAAA,CAAI,QAAQ,OAAO,CAAA;AAAA,EACvE;AACF,CAAA;;;AClKO,IAAM,aAAA,GAAgB;AAAA,EAC3B,MAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA;AAAA,EACA,IAAA;AAAA,EACA,MAAA,EAAQ,YAAA;AAAA,EACR,WAAA;AAAA,EACA,aAAA;AAAA,EACA,aAAA;AAAA,EACA,kBAAA;AAAA,EACA,iBAAA;AAAA,EACA;AACF,CAAA;AAIO,IAAM,sBAAsB,MAAA,CAAO,IAAA;AAAA,EACxC;AACF,CAAA;;;ACjBO,SAAS,cACX,KAAA,EACkC;AACrC,EAAA,OAAO,OAAO,OAAA,KAAY;AACxB,IAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,MAAA,IAAI,IAAA,EAAM,MAAM,IAAA,CAAK,OAAO,CAAA;AAAA,IAC9B;AAAA,EACF,CAAA;AACF;;;ACZO,IAAM,iBAAA,GAAoB;AAAA,EAC/B,MAAA,EAAQ,CAAC,OAAA,EAAS,aAAA,EAAe,gBAAgB,aAAa,CAAA;AAAA,EAC9D,QAAA,EAAU,CAAC,OAAA,EAAS,aAAa,CAAA;AAAA,EACjC,MAAA,EAAQ,CAAC,OAAA,EAAS,WAAW;AAC/B,CAAA;AASO,IAAM,mBAAA,GAAsB;AAAA,EACjC,QAAA;AAAA,EACA,OAAA;AAAA,EACA,SAAA;AAAA,EACA;AACF,CAAA;AAGO,IAAM,2BAAA,GAA8B;AAAA,EACzC,MAAA,EAAQ,CAAC,aAAA,EAAe,aAAa,CAAA;AAAA,EACrC,QAAA,EAAU,CAAC,aAAa,CAAA;AAAA,EACxB,MAAA,EAAQ,CAAC,WAAW;AACtB,CAAA;AAEO,IAAM,6BAAA,GAAgC;AAAA,EAC3C,QAAA;AAAA,EACA,SAAA;AAAA,EACA;AACF,CAAA;;;AC2EO,IAAM,mBAAA,GAAsB;AAAA,EACjC,SAAA;AAAA,EACA,KAAA;AAAA,EACA,SAAA;AAAA,EACA,WAAA;AAAA,EACA,cAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA;AAAA,EACA,UAAA;AAAA,EACA,SAAA;AAAA,EACA,MAAA;AAAA,EACA,QAAA;AAAA,EACA,aAAA;AAAA,EACA,KAAA;AAAA,EACA;AACF,CAAA;;;AC5GA,SAAS,cAAA,CACP,WAAA,EACA,QAAA,EACA,KAAA,GAAwC,eAAA,EACpB;AACpB,EAAA,MAAM,WACJ,KAAA,KAAU,YAAA,GACN,CAAC,QAAA,EAAU,GAAG,WAAW,CAAA,GACzB,CAAC,GAAG,aAAa,QAAQ,CAAA,EAC7B,OAAO,CAAC,CAAA,KAAgC,KAAK,IAAI,CAAA;AACnD,EAAA,IAAI,OAAA,CAAQ,MAAA,KAAW,CAAA,EAAG,OAAO,MAAA;AACjC,EAAA,IAAI,OAAA,CAAQ,MAAA,KAAW,CAAA,EAAG,OAAO,QAAQ,CAAC,CAAA;AAC1C,EAAA,OAAO,UAAA,CAAW,GAAG,OAAO,CAAA;AAC9B;AAEA,SAAS,UAAA,CACP,MACA,OAAA,EACA,WAAA,EACA,MACA,aAAA,mBAAqC,IAAI,KAAI,EAC1C;AACH,EAAA,MAAM,MAAA,GAAkB,EAAE,GAAI,WAAA,EAAwB;AACtD,EAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,IAAA,MAAM,IAAA,GAAO,cAAA;AAAA,MACX,OAAA,CAAQ,IAAI,CAAC,MAAA,KAAW,KAAK,MAAM,CAAA,GAAI,GAAG,CAAC,CAAA;AAAA,MAC1C,YAAwB,GAAG,CAAA;AAAA,MAC5B,aAAA,CAAc,GAAA,CAAI,GAAG,CAAA,GAAI,YAAA,GAAe;AAAA,KAC1C;AACA,IAAA,IAAI,IAAA,KAAS,MAAA,EAAW,MAAA,CAAO,GAAG,CAAA,GAAI,IAAA;AAAA,EACxC;AACA,EAAA,OAAO,MAAA;AACT;AAEA,SAAS,iBAAA,CACPN,QACA,OAAA,EACe;AACf,EAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,MAAA,CAAO,CAAC,CAAA,KAAM,CAACA,MAAAA,CAAM,gBAAA,CAAiB,GAAA,CAAI,CAAA,CAAE,EAAE,CAAC,CAAA;AAEtE,EAAA,MAAMG,OAAAA,GAAS,SAAA,CAAUH,MAAAA,CAAM,MAAM,CAAA,GACjC;AAAA,IACE,GAAG,UAAA;AAAA,MACD,iBAAA,CAAkB,MAAA;AAAA,MAClB,MAAA;AAAA,MACAA,MAAAA,CAAM,MAAA;AAAA,MACN,CAAC,CAAA,KAAM,CAAA,CAAE,KAAA,EAAO,MAAA;AAAA,MAChB,IAAI,GAAA,CAAI,2BAAA,CAA4B,MAAM;AAAA,KAC5C;AAAA,IACA,SAAA,EAAW,SAAA,CAAUA,MAAAA,CAAM,MAAA,CAAO,SAAS,CAAA,GACvC,UAAA;AAAA,MACE,mBAAA;AAAA,MACA,MAAA;AAAA,MACAA,OAAM,MAAA,CAAO,SAAA;AAAA,MACb,CAAC,CAAA,KAAM,CAAA,CAAE,KAAA,EAAO,MAAA,EAAQ,SAAA;AAAA,MACxB,IAAI,IAAI,6BAA6B;AAAA,KACvC,GACAA,OAAM,MAAA,CAAO;AAAA,MAEnBA,MAAAA,CAAM,MAAA;AAEV,EAAA,OAAO;AAAA,IACL,GAAGA,MAAAA;AAAA,IACH,MAAA,EAAAG,OAAAA;AAAA,IACA,QAAA,EAAU,SAAA,CAAUH,MAAAA,CAAM,QAAQ,CAAA,GAC9B,UAAA;AAAA,MACE,iBAAA,CAAkB,QAAA;AAAA,MAClB,MAAA;AAAA,MACAA,MAAAA,CAAM,QAAA;AAAA,MACN,CAAC,CAAA,KAAM,CAAA,CAAE,KAAA,EAAO,QAAA;AAAA,MAChB,IAAI,GAAA,CAAI,2BAAA,CAA4B,QAAQ;AAAA,QAE9CA,MAAAA,CAAM,QAAA;AAAA,IACV,MAAA,EAAQ,SAAA,CAAUA,MAAAA,CAAM,MAAM,CAAA,GAC1B,UAAA;AAAA,MACE,iBAAA,CAAkB,MAAA;AAAA,MAClB,MAAA;AAAA,MACAA,MAAAA,CAAM,MAAA;AAAA,MACN,CAAC,CAAA,KAAM,CAAA,CAAE,KAAA,EAAO,MAAA;AAAA,MAChB,IAAI,GAAA,CAAI,2BAAA,CAA4B,MAAM;AAAA,QAE5CA,MAAAA,CAAM;AAAA,GACZ;AACF;AAYO,SAAS,aAGd,MAAA,EAA4D;AAC5D,EAAA,MAAM,OAAA,GAAU,MAAA,CAAO,OAAA,IAAW,EAAC;AACnC,EAAA,MAAM,IAAA,uBAAW,GAAA,EAAY;AAC7B,EAAA,MAAM,IAAA,uBAAW,GAAA,EAA2B;AAC5C,EAAA,MAAM,UAAU,EAAC;AACjB,EAAA,MAAM,SAAA,GAAY,CAAC,EAAA,KAAe,IAAA,CAAK,IAAI,EAAE,CAAA;AAE7C,EAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,IAAA,IAAK,mBAAA,CAA0C,QAAA,CAAS,MAAA,CAAO,EAAE,CAAA,EAAG;AAClE,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,WAAA,EAAc,OAAO,EAAE,CAAA,6DAAA;AAAA,OACzB;AAAA,IACF;AACA,IAAA,IAAI,IAAA,CAAK,GAAA,CAAI,MAAA,CAAO,EAAE,CAAA,EAAG;AACvB,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,8BAAA,EAAiC,OAAO,EAAE,CAAA,iCAAA;AAAA,OAC5C;AAAA,IACF;AACA,IAAA,IAAA,CAAK,GAAA,CAAI,OAAO,EAAE,CAAA;AAClB,IAAA,IAAA,CAAK,GAAA,CAAI,MAAA,CAAO,EAAA,EAAI,MAAM,CAAA;AAAA,EAC5B;AAEA,EAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,IAAA,KAAA,MAAW,GAAA,IAAO,MAAA,CAAO,SAAA,IAAa,EAAC,EAAG;AACxC,MAAA,IAAI,CAAC,IAAA,CAAK,GAAA,CAAI,GAAG,CAAA,EAAG;AAClB,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,CAAA,QAAA,EAAW,MAAA,CAAO,EAAE,CAAA,cAAA,EAAiB,GAAG,CAAA,2BAAA;AAAA,SAC1C;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,EAAA,MAAM,QAAA,uBAAe,GAAA,EAAY;AACjC,EAAA,MAAM,OAAA,uBAAc,GAAA,EAAY;AAChC,EAAA,SAAS,KAAA,CAAM,IAAY,KAAA,EAAiB;AAC1C,IAAA,IAAI,OAAA,CAAQ,GAAA,CAAI,EAAE,CAAA,EAAG;AACrB,IAAA,IAAI,QAAA,CAAS,GAAA,CAAI,EAAE,CAAA,EAAG;AACpB,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,qCAAA,EAAwC,CAAC,GAAG,KAAA,EAAO,EAAE,CAAA,CAAE,IAAA,CAAK,MAAM,CAAC,CAAA,CAAA;AAAA,OACrE;AAAA,IACF;AACA,IAAA,QAAA,CAAS,IAAI,EAAE,CAAA;AACf,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,GAAA,CAAI,EAAE,CAAA;AAC1B,IAAA,KAAA,MAAW,GAAA,IAAO,MAAA,EAAQ,SAAA,IAAa,EAAC,EAAG;AACzC,MAAA,KAAA,CAAM,GAAA,EAAK,CAAC,GAAG,KAAA,EAAO,EAAE,CAAC,CAAA;AAAA,IAC3B;AACA,IAAA,QAAA,CAAS,OAAO,EAAE,CAAA;AAClB,IAAA,OAAA,CAAQ,IAAI,EAAE,CAAA;AAAA,EAChB;AACA,EAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,IAAA,KAAA,CAAM,MAAA,CAAO,EAAA,EAAI,EAAE,CAAA;AAAA,EACrB;AAEA,EAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,IAAA,IAAI,MAAA,CAAO,YAAY,MAAA,EAAW;AAChC,MAAC,OAAA,CAAoC,MAAA,CAAO,EAAE,CAAA,GAAI,MAAA,CAAO,OAAA;AAAA,IAC3D;AAAA,EACF;AAEA,EAAA,MAAM,qBAAqB,IAAI,GAAA,CAAY,MAAA,CAAO,MAAA,CAAOM,aAAa,CAAC,CAAA;AACvE,EAAA,MAAM,gCAAgB,IAAI,GAAA,CAAY,CAAC,GAAG,mBAAA,EAAqB,WAAW,CAAC,CAAA;AAC3E,EAAA,MAAM,gBAAA,uBAAuB,GAAA,EAAY;AACzC,EAAA,MAAM,YAAsC,EAAC;AAE7C,EAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,IAAA,KAAA,MAAW,CAAC,IAAA,EAAM,QAAQ,CAAA,IAAK,MAAA,CAAO,QAAQ,MAAA,CAAO,SAAA,IAAa,EAAE,CAAA,EAAG;AACrE,MAAA,IAAI,aAAA,CAAc,GAAA,CAAI,IAAI,CAAA,IAAK,QAAQ,SAAA,EAAW;AAChD,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,CAAA,QAAA,EAAW,MAAA,CAAO,EAAE,CAAA,YAAA,EAAe,IAAI,CAAA,qCAAA;AAAA,SACzC;AAAA,MACF;AACA,MAAA,MAAM,OAAO,QAAA,CAAS,IAAA;AACtB,MAAA,IAAI,OAAO,IAAA,KAAS,QAAA,IAAY,CAAC,IAAA,CAAK,UAAA,CAAW,GAAG,CAAA,EAAG;AACrD,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,CAAA,QAAA,EAAW,MAAA,CAAO,EAAE,CAAA,YAAA,EAAe,IAAI,CAAA,2BAAA;AAAA,SACzC;AAAA,MACF;AACA,MAAA,IAAI,kBAAA,CAAmB,GAAA,CAAI,IAAI,CAAA,EAAG;AAChC,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,CAAA,QAAA,EAAW,MAAA,CAAO,EAAE,CAAA,YAAA,EAAe,IAAI,CAAA,6BAAA;AAAA,SACzC;AAAA,MACF;AACA,MAAA,MAAM,OAAA,GAAU,KAAA,CAAM,OAAA,CAAQ,QAAA,CAAS,OAAA,CAAQ,MAAM,CAAA,GACjD,QAAA,CAAS,OAAA,CAAQ,MAAA,GACjB,CAAC,QAAA,CAAS,QAAQ,MAAM,CAAA;AAC5B,MAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,QAAA,MAAM,QAAA,GAAW,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI,IAAI,CAAA,CAAA;AAClC,QAAA,IAAI,gBAAA,CAAiB,GAAA,CAAI,QAAQ,CAAA,EAAG;AAClC,UAAA,MAAM,IAAI,KAAA,CAAM,CAAA,0BAAA,EAA6B,QAAQ,CAAA,CAAA,CAAG,CAAA;AAAA,QAC1D;AACA,QAAA,gBAAA,CAAiB,IAAI,QAAQ,CAAA;AAAA,MAC/B;AACA,MAAA,SAAA,CAAU,IAAI,CAAA,GAAI,QAAA;AAAA,IACpB;AAAA,EACF;AAEA,EAAA,MAAM,EAAE,OAAA,EAAS,KAAA,EAAO,GAAG,MAAK,GAAI,MAAA;AACpC,EAAA,MAAM,UAAA,GAAa,gBAAgB,IAAI,CAAA;AAEvC,EAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,IAAA,MAAA,CAAO,IAAA,GAAO,EAAE,MAAA,EAAQ,IAAA,EAAM,WAAW,CAAA;AAAA,EAC3C;AACA,EAAA,MAAM,SAAwC,EAAC;AAC/C,EAAA,KAAA,MAAW,CAAC,IAAA,EAAMN,MAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,UAAU,CAAA,EAAG;AACtD,IAAA,MAAA,CAAO,IAAI,CAAA,GAAI,iBAAA,CAAkBA,MAAAA,EAAO,OAAO,CAAA;AAAA,EACjD;AAEA,EAAA,MAAM,KAAA,GAAQ,cAAA;AAAA,IACZ,QAAQ,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,OAAO,KAAe,CAAA;AAAA,IAC3C,IAAA,CAAK;AAAA,GACP;AAEA,EAAA,MAAM,MAAA,GAAgC;AAAA,IACpC,GAAG,IAAA;AAAA,IACH,MAAA;AAAA,IACA,GAAI,KAAA,KAAU,MAAA,GAAY,EAAE,KAAA,KAAU;AAAC,GACzC;AAEA,EAAA,OAAO;AAAA,IACL,MAAA,EAAQ,MAAA;AAAA,IACR,OAAA;AAAA,IACA,SAAA;AAAA,IACA;AAAA,GACF;AACF;;;ACjPO,SAAS,aAKd,MAAA,EACyC;AACzC,EAAA,OAAO,MAAA;AACT;;;ACPO,SAAS,aAAA,CACd,WACA,OAAA,EACG;AACH,EAAA,MAAM,MAAM,EAAC;AAEb,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,QAAQ,KAAK,MAAA,CAAO,OAAA,CAAQ,SAAS,CAAA,EAAG;AACvD,IAAA,MAAM,KAAA,IAAS,OAAO,KAAA,GAAiC,EAAC,KAAM;AAC5D,MAAA,MAAM,UAAU,KAAA,CAAM,OAAA;AACtB,MAAA,MAAM,OAAA,GACH,KAAA,CAAM,OAAA,IAAmC,kBAAA,CAAmB,OAAO,CAAA;AACtE,MAAA,OAAO,QAAA,CAAS;AAAA,QACd,GAAG,KAAA;AAAA,QACH,OAAA,EAAS,WAAW,OAAA,CAAQ,OAAA;AAAA,QAC5B,OAAA;AAAA,QACA;AAAA,OACD,CAAA;AAAA,IACH,CAAA,CAAA;AAEA,IAAA,KAAA,CAAM,OAAO,QAAA,CAAS,IAAA;AACtB,IAAA,KAAA,CAAM,UAAU,QAAA,CAAS,OAAA;AACzB,IAAA,GAAA,CAAI,GAAc,CAAA,GAAI,KAAA;AAAA,EACxB;AAEA,EAAA,OAAO,GAAA;AACT;;;ACtBA,IAAM,aAAA,uBAAoB,GAAA,CAAI;AAAA,EAC5B,WAAA;AAAA,EACA,cAAA;AAAA,EACA,YAAA;AAAA,EACA,WAAA;AAAA,EACA;AACF,CAAC,CAAA;AAMD,SAAS,eAAA,CAAgB,OAAgB,MAAA,EAAsC;AAC7E,EAAA,IAAIC,UAAAA,CAAW,KAAK,CAAA,EAAG;AAEvB,EAAA,MAAM,OAAQ,KAAA,EAA6B,IAAA;AAC3C,EAAA,MAAM,MAAA,GAAS,aAAA,CAAc,MAAA,EAAQ,MAAM,CAAA;AAC3C,EAAA,IAAI,OAAO,IAAA,KAAS,QAAA,IAAY,aAAA,CAAc,GAAA,CAAI,IAAI,CAAA,EAAG;AACvD,IAAA,MAAM,UAAA,GAAa,MAAA,CAAO,cAAA,CAAe,IAAI,CAAA;AAC7C,IAAA,MAAA,CAAO,KAAA,GAAQ,UAAA,CAAW,OAAA,EAAS,KAAK,CAAA;AACxC,IAAA,MAAA,EAAQ,OAAA,GAAU,KAAA,EAAO,EAAE,CAAA;AAC3B,IAAA,MAAM,UAAA;AAAA,EACR;AAEA,EAAA,MAAA,CAAO,KAAA,GAAQ,iBAAiB,KAAA,GAAQ,KAAA,CAAM,UAAU,MAAA,CAAO,KAAK,GAAG,KAAK,CAAA;AAC5E,EAAA,MAAA,EAAQ,OAAA,GAAU,KAAA,EAAO,EAAE,CAAA;AAC3B,EAAA,MAAM,OAAO,aAAA,EAAc;AAC7B;AAMA,SAAS,uBACP,OAAA,EACyC;AACzC,EAAA,OAAO,OAAO,OAAA,KAAY;AACxB,IAAA,MAAM,QAAA,GAAW,MAAM,OAAA,CAAQ,OAAO,CAAA;AACtC,IAAA,IAAI,QAAA,CAAS,MAAA,KAAW,GAAA,EAAK,OAAO,QAAA;AACpC,IAAA,MAAM,WAAA,GAAc,QAAA,CAAS,OAAA,CAAQ,GAAA,CAAI,cAAc,CAAA,IAAK,EAAA;AAC5D,IAAA,IAAI,WAAA,CAAY,QAAA,CAAS,kBAAkB,CAAA,EAAG,OAAO,QAAA;AACrD,IAAA,OAAO,UAAA,CAAW,MAAA,CAAO,QAAA,EAAU,CAAA;AAAA,EACrC,CAAA;AACF;AAMO,SAAS,cAAA,CACd,WACA,GAAA,EACA;AACA,EAAA,MAAM,QAAA,GAAW,sBAAA;AAAA,IACf,GAAA,CAAI,OAAO,QAAA,IAAY;AAAA,GACzB;AAEA,EAAA,MAAM,MAAA,GAAS,aAAa,SAAA,EAAW;AAAA,IACrC,QAAA;AAAA,IACA,aAAA,EAAe,EAAE,MAAA,EAAQ,GAAA,CAAI,MAAA,EAAO;AAAA,IACpC,OAAA,EAAS,EAAE,QAAA,EAAU,IAAA,EAAK;AAAA,IAC1B,SAAS,CAAC,KAAA,KAAU,eAAA,CAAgB,KAAA,EAAO,IAAI,MAAM;AAAA,GACtD,CAAA;AAED,EAAA,OAAO;AAAA,IACL,SAAA,EAAW,cAAc,MAAA,CAAO,SAAA,EAAW,EAAE,MAAA,EAAQ,GAAA,CAAI,QAAQ,CAAA;AAAA,IACjE,OAAA,EAAS,sBAAA,CAAuB,MAAA,CAAO,OAAO;AAAA,GAChD;AACF;;;ACYO,SAAS,QAOd,MAAA,EACoC;AACpC,EAAA,MAAM;AAAA,IACJ,MAAA,EAAQ,QAAA;AAAA,IACR,OAAA;AAAA,IACA,SAAA;AAAA,IACA,SAAA,EAAW;AAAA,GACb,GAAI,aAAa,MAAM,CAAA;AAEvB,EAAA,MAAM,SAAA,GAAY,EAAE,GAAG,aAAA,EAAe,GAAG,eAAA,EAAgB;AACzD,EAAA,MAAM,SAAS,cAAA,CAAe,SAAA,EAAW,EAAE,MAAA,EAAQ,UAAU,CAAA;AAC7D,EAAA,MAAM,QAAQ,MAAA,CAAO,SAAA;AAErB,EAAA,MAAM,GAAA,GAAM;AAAA,IACV,GAAG,KAAA;AAAA,IACH,YAAY,KAAA,CAAM,WAAA;AAAA,IAClB,SAAA,EAAW;AAAA,MACT,MAAM,KAAA,CAAM,aAAA;AAAA,MACZ,UAAU,KAAA,CAAM,aAAA;AAAA,MAChB,WAAW,KAAA,CAAM,kBAAA;AAAA,MACjB,UAAU,KAAA,CAAM,iBAAA;AAAA,MAChB,OAAO,KAAA,CAAM;AAAA;AACf,GACF;AAEA,EAAA,OAAO;AAAA,IACL,SAAS,MAAA,CAAO,OAAA;AAAA,IAChB,GAAA;AAAA,IACA,OAAA;AAAA,IACA,SAAA;AAAA,IACA,YAAA,EAAca,cAAAA;AAAA,IACd,QAAQ,EAAC;AAAA,IACT,GAAA,EAAK,CAAC,KAAA,KAAU,SAAA,CAAU,UAAU,KAAK,CAAA;AAAA,IACzC,GAAG;AAAA,GACL;AACF;;;AC3GO,IAAM,cAAA,GAAiB,CAAC,QAAA,EAAU,UAAA,EAAY,QAAQ;AAOtD,IAAM,gBAAA,GAAmB,CAAC,GAAG,cAAA,EAAgB,WAAW","file":"index.js","sourcesContent":["/** Build a synthetic Request for server-side `api` calls. */\nexport function requestFromHeaders(headers?: HeadersInit): Request {\n return new Request(\"http://dimah-s3.local\", { headers });\n}\n","import {\n AbortMultipartUploadCommand,\n DeleteObjectCommand,\n type S3Client,\n} from \"@aws-sdk/client-s3\";\n\n/** Best-effort DeleteObject after a failed constraint check. */\nexport async function deleteObjectBestEffort(\n client: S3Client,\n bucket: string,\n key: string,\n): Promise<void> {\n try {\n await client.send(new DeleteObjectCommand({ Bucket: bucket, Key: key }));\n } catch {\n // Best-effort cleanup.\n }\n}\n\n/** Best-effort AbortMultipartUpload before assembly or after a failed complete. */\nexport async function abortMultipartBestEffort(\n client: S3Client,\n bucket: string,\n key: string,\n uploadId: string,\n): Promise<void> {\n try {\n await client.send(\n new AbortMultipartUploadCommand({\n Bucket: bucket,\n Key: key,\n UploadId: uploadId,\n }),\n );\n } catch {\n // Best-effort cleanup.\n }\n}\n","import {\n DimahS3Error,\n S3_ERROR_CODES,\n isAPIError,\n isDimahS3Error,\n isS3ErrorCode,\n} from \"@dimah-s3/core\";\nimport type { RouteOperation } from \"@/types/config\";\n\nexport {\n DimahS3Error,\n S3_ERROR_CODES,\n isAPIError,\n isDimahS3Error,\n isS3ErrorCode,\n};\n\n/** English API errors with stable codes for client-side localization. */\nexport const errors = {\n notFound: () => DimahS3Error.from(\"NOT_FOUND\", S3_ERROR_CODES.NOT_FOUND),\n\n unauthorized: () =>\n DimahS3Error.from(\"UNAUTHORIZED\", S3_ERROR_CODES.UNAUTHORIZED),\n\n forbidden: () => DimahS3Error.from(\"FORBIDDEN\", S3_ERROR_CODES.FORBIDDEN),\n\n conflict: () => DimahS3Error.from(\"CONFLICT\", S3_ERROR_CODES.CONFLICT),\n\n internalError: () =>\n DimahS3Error.from(\"INTERNAL_SERVER_ERROR\", S3_ERROR_CODES.INTERNAL_ERROR),\n\n objectNotFound: () =>\n DimahS3Error.from(\"NOT_FOUND\", S3_ERROR_CODES.OBJECT_NOT_FOUND),\n\n featureDisabled: (feature: RouteOperation) =>\n DimahS3Error.from(\"NOT_FOUND\", {\n code: S3_ERROR_CODES.FEATURE_DISABLED.code,\n message: S3_ERROR_CODES.FEATURE_DISABLED.message.replaceAll(\n \"{feature}\",\n feature,\n ),\n params: { feature },\n }),\n\n invalidKey: () =>\n DimahS3Error.from(\"BAD_REQUEST\", S3_ERROR_CODES.INVALID_KEY),\n\n unknownRoute: (route: string) =>\n DimahS3Error.from(\"NOT_FOUND\", {\n code: S3_ERROR_CODES.UNKNOWN_ROUTE.code,\n message: S3_ERROR_CODES.UNKNOWN_ROUTE.message,\n params: { route },\n }),\n\n fileTypeNotAllowed: (fileName: string, contentType?: string) =>\n DimahS3Error.from(\"BAD_REQUEST\", {\n code: S3_ERROR_CODES.FILE_TYPE_NOT_ALLOWED.code,\n message: S3_ERROR_CODES.FILE_TYPE_NOT_ALLOWED.message,\n params: {\n fileName,\n ...(contentType ? { contentType } : {}),\n },\n }),\n\n s3NetworkError: (code: string) =>\n DimahS3Error.from(\"BAD_GATEWAY\", {\n code: S3_ERROR_CODES.S3_NETWORK_ERROR.code,\n message: S3_ERROR_CODES.S3_NETWORK_ERROR.message.replaceAll(\n \"{code}\",\n code,\n ),\n params: { code },\n }),\n\n multipartPartMissing: (partNumber: number) =>\n DimahS3Error.from(\"BAD_REQUEST\", {\n code: S3_ERROR_CODES.MULTIPART_PART_MISSING.code,\n message: S3_ERROR_CODES.MULTIPART_PART_MISSING.message.replaceAll(\n \"{partNumber}\",\n String(partNumber),\n ),\n params: { partNumber },\n }),\n\n payloadTooLarge: (\n message: string = S3_ERROR_CODES.PAYLOAD_TOO_LARGE.message,\n ) =>\n DimahS3Error.from(\"PAYLOAD_TOO_LARGE\", {\n ...S3_ERROR_CODES.PAYLOAD_TOO_LARGE,\n message,\n }),\n\n quotaExceeded: (message: string = S3_ERROR_CODES.QUOTA_EXCEEDED.message) =>\n DimahS3Error.from(\"PAYLOAD_TOO_LARGE\", {\n ...S3_ERROR_CODES.QUOTA_EXCEEDED,\n message,\n }),\n\n validationError: (message: string) =>\n DimahS3Error.from(\"BAD_REQUEST\", {\n code: S3_ERROR_CODES.VALIDATION_ERROR.code,\n message,\n }),\n} as const;\n\nexport type ServerErrors = typeof errors;\n","import { errors } from \"@/errors\";\n\n/** True when an AWS SDK throw means the object or multipart upload does not exist. */\nexport function isAwsNotFound(err: unknown): boolean {\n const e = err as {\n name?: string;\n Code?: string;\n $metadata?: { httpStatusCode?: number };\n };\n return (\n e?.name === \"NoSuchKey\" ||\n e?.name === \"NotFound\" ||\n e?.name === \"NoSuchUpload\" ||\n e?.Code === \"NoSuchKey\" ||\n e?.Code === \"NotFound\" ||\n e?.Code === \"NoSuchUpload\" ||\n e?.$metadata?.httpStatusCode === 404\n );\n}\n\n/** Run an AWS call and map not-found errors to `OBJECT_NOT_FOUND`. */\nexport async function sendOrObjectNotFound<T>(\n send: () => Promise<T>,\n): Promise<T> {\n try {\n return await send();\n } catch (err: unknown) {\n if (isAwsNotFound(err)) throw errors.objectNotFound();\n throw err;\n }\n}\n","import { S3_DEFAULT_EXPIRES_IN, S3_MAX_EXPIRES_IN } from \"@dimah-s3/core\";\n\n/**\n * Coerce an upload/download `expiresIn` to a positive integer, then clamp\n * to {@link maxExpiresIn} (SigV4 max by default).\n */\nexport function normalizeExpiresIn(\n value: unknown,\n maxExpiresIn: number = S3_MAX_EXPIRES_IN,\n): number {\n const n = Number(value);\n const expires =\n Number.isFinite(n) && n > 0 ? Math.floor(n) : S3_DEFAULT_EXPIRES_IN;\n const max =\n Number.isFinite(maxExpiresIn) && maxExpiresIn > 0\n ? Math.floor(maxExpiresIn)\n : S3_MAX_EXPIRES_IN;\n return Math.min(expires, max);\n}\n","import type { DimahS3Logger } from \"@/types\";\n\nexport const defaultLogger: DimahS3Logger = {\n error: (message, ...args) => {\n console.error(\"[dimah-s3]\", message, ...args);\n },\n warn: (message, ...args) => {\n console.warn(\"[dimah-s3]\", message, ...args);\n },\n};\n\nexport function resolveLogger(\n logger: DimahS3Logger | false | undefined,\n): DimahS3Logger {\n if (logger === false) return {};\n if (!logger) return defaultLogger;\n return logger;\n}\n","import { DimahS3Error, isAPIError } from \"@dimah-s3/core\";\nimport { errors } from \"@/errors\";\nimport { resolveLogger } from \"@/helpers/logger\";\nimport type {\n ResolvedDimahS3Config,\n UploadConfig,\n UploadObjectContext,\n UploadObjectInfo,\n} from \"@/types\";\n\nfunction mapGuardError(err: unknown): never {\n if (isAPIError(err)) throw err;\n if (err instanceof Error && err.message.trim()) {\n throw new DimahS3Error(\"FORBIDDEN\", {\n message: err.message,\n cause: err,\n });\n }\n throw errors.forbidden();\n}\n\n/**\n * Run a guard hook. {@link isAPIError} values are preserved; plain Errors keep\n * their English message without a library `code` so client\n * `useFormatDimahError` does not replace them with a generic mapped string.\n */\nexport async function runHook<T extends { request: Request }>(\n hook: ((context: T) => Promise<void> | void) | undefined,\n context: T,\n): Promise<void> {\n if (!hook) return;\n try {\n await hook(context);\n } catch (err) {\n mapGuardError(err);\n }\n}\n\n/**\n * Run `upload.object`. Same rejection mapping as {@link runHook}\n * (plain `Error` → 403) so auth throws in `object` match `guard`.\n */\nexport async function runObjectHook(\n hook: UploadConfig[\"object\"],\n context: UploadObjectContext,\n): Promise<UploadObjectInfo | void> {\n if (!hook) return;\n try {\n return await hook(context);\n } catch (err) {\n mapGuardError(err);\n }\n}\n\n/**\n * Run a lifecycle `on*` hook. Failures become {@link errors.internalError}\n * (or preserve an existing APIError).\n */\nexport async function runLifecycleHook<T extends { request: Request }>(\n hook: ((context: T) => Promise<void> | void) | undefined,\n context: T,\n config?: Pick<ResolvedDimahS3Config, \"logger\" | \"onError\">,\n): Promise<void> {\n if (!hook) return;\n try {\n await hook(context);\n } catch (err) {\n if (isAPIError(err)) throw err;\n resolveLogger(config?.logger).error?.(\"lifecycle hook failed\", err);\n config?.onError?.(err, { request: context.request });\n throw errors.internalError();\n }\n}\n","/** S3 user-metadata key for `upload.object().previousKey`. */\nexport const DIMAH_PREVIOUS_KEY_META = \"dimah-previous-key\";\n\nexport function stripPreviousKeyMeta(\n metadata: Record<string, string> | undefined,\n): Record<string, string> {\n if (!metadata) return {};\n const { [DIMAH_PREVIOUS_KEY_META]: _omit, ...rest } = metadata;\n return rest;\n}\n\nexport function previousKeyFromMetadata(\n metadata: Record<string, string> | undefined,\n): string | undefined {\n const value = metadata?.[DIMAH_PREVIOUS_KEY_META]?.trim();\n return value || undefined;\n}\n","import {\n normalizeObjectKey,\n sanitizeFileName,\n type S3ObjectAcl,\n} from \"@dimah-s3/core\";\nimport { errors } from \"@/errors\";\nimport { DIMAH_PREVIOUS_KEY_META } from \"@/helpers/previous-key\";\nimport { runObjectHook } from \"@/helpers/hooks\";\nimport type {\n OpenedRoute,\n ResolvedRoute,\n UploadObjectContext,\n UploadObjectInfo,\n} from \"@/types\";\n\nexport type ResolvedObject = {\n key: string;\n bucket: string;\n metadata?: Record<string, string>;\n acl: S3ObjectAcl;\n};\n\ntype RouteKeyPrefix = ResolvedRoute[\"keyPrefix\"];\n\n/**\n * Strip leading/trailing slashes and reject `.` / `..` / empty segments,\n * NUL, and backslashes. Returns `null` when the key is unsafe.\n */\nexport { normalizeObjectKey };\n\n/**\n * Normalize an object key: strip leading slashes, reject `.` / `..` segments,\n * NUL, and backslashes.\n */\nexport function assertSafeObjectKey(key: string): string {\n const normalized = normalizeObjectKey(key);\n if (!normalized) throw errors.invalidKey();\n return normalized;\n}\n\nfunction applyPrefix(prefix: string, key: string): string {\n const p = assertSafeObjectKey(prefix);\n const k = assertSafeObjectKey(key);\n if (k.startsWith(`${p}/`)) return k;\n if (k === p) throw errors.invalidKey();\n return `${p}/${k}`;\n}\n\n/** Nest `key` under `keyPrefix`. `false` leaves a safe key unchanged. */\nexport function nestKeyUnderPrefix(\n keyPrefix: RouteKeyPrefix,\n key: string,\n): string {\n const safe = assertSafeObjectKey(key);\n if (keyPrefix === false) return safe;\n return applyPrefix(keyPrefix, safe);\n}\n\n/** Confirm / download / delete / multipart follow-ups: stored key + namespace. */\nexport function assertStoredKey(\n key: string,\n keyPrefix: RouteKeyPrefix,\n): string {\n const safe = assertSafeObjectKey(key);\n if (keyPrefix === false) return safe;\n const root = assertSafeObjectKey(keyPrefix);\n if (safe.startsWith(`${root}/`)) return safe;\n throw errors.invalidKey();\n}\n\n/**\n * Leaf name for a generated object key. Path segments (`../`, `/`) must\n * not become extra key folders or fail {@link assertSafeObjectKey}.\n */\nfunction objectKeyFileName(fileName: string): string {\n const sanitized = sanitizeFileName(fileName);\n const leaf = sanitized\n .split(\"/\")\n .filter((part) => part.length > 0)\n .at(-1);\n if (!leaf || leaf === \".\" || leaf === \"..\") return \"file\";\n return leaf;\n}\n\n/** `{folder}/{uuid}/{sanitizedName}` — omit `folder` (`false`) for `{uuid}/{name}`. */\nexport function generateObjectKey(\n folder: string | false,\n fileName: string,\n): string {\n const leaf = `${crypto.randomUUID()}/${objectKeyFileName(fileName)}`;\n if (folder === false) return assertSafeObjectKey(leaf);\n return applyPrefix(folder, leaf);\n}\n\nfunction resolveAcl(\n info: UploadObjectInfo | void,\n route: OpenedRoute<\"upload\" | \"multipart\">,\n): ResolvedObject[\"acl\"] {\n return info?.acl ?? route.upload.acl ?? \"private\";\n}\n\nexport async function resolveUploadTarget(\n route: OpenedRoute<\"upload\" | \"multipart\">,\n context: Omit<UploadObjectContext, \"bucket\" | \"keyPrefix\">,\n): Promise<ResolvedObject> {\n const bucket = route.bucket;\n const objectContext: UploadObjectContext = {\n ...context,\n bucket,\n keyPrefix: route.keyPrefix,\n };\n const info =\n (await runObjectHook(route.upload.object, objectContext)) ?? undefined;\n const key = info?.key\n ? nestKeyUnderPrefix(route.keyPrefix, info.key)\n : generateObjectKey(\n info?.folder != null && info.folder !== \"\"\n ? nestKeyUnderPrefix(route.keyPrefix, info.folder)\n : route.keyPrefix === false\n ? false\n : route.keyPrefix,\n context.file.name,\n );\n const metadata = { ...info?.metadata };\n if (info?.previousKey) {\n metadata[DIMAH_PREVIOUS_KEY_META] = nestKeyUnderPrefix(\n route.keyPrefix,\n info.previousKey,\n );\n }\n return {\n key,\n bucket,\n metadata: Object.keys(metadata).length > 0 ? metadata : info?.metadata,\n acl: resolveAcl(info, route),\n };\n}\n\nexport function resolveStoredTarget(\n route: ResolvedRoute,\n key: string,\n): { key: string; bucket: string } {\n return {\n key: assertStoredKey(key, route.keyPrefix),\n bucket: route.bucket,\n };\n}\n","import { ROUTE_NAME_PATTERN } from \"@dimah-s3/core\";\nimport type { DimahS3RouteConfig } from \"@/types/config\";\n\n/**\n * Identity helper so route configs infer as a distinct policy object.\n *\n * ```ts\n * routes: {\n * uploads: route({ upload: { fileTypes: [\"image/*\"] } }),\n * }\n * ```\n */\nexport function route<const T extends DimahS3RouteConfig>(config: T): T {\n return config;\n}\n\nexport function assertRouteName(name: string): void {\n if (!ROUTE_NAME_PATTERN.test(name)) {\n throw new Error(\n `dimahS3 route \"${name}\" is invalid. Use a letter followed by up to 63 letters, digits, underscores, or hyphens.`,\n );\n }\n}\n","import type {\n DeleteConfig,\n DimahS3Config,\n DimahS3RouteConfig,\n DownloadConfig,\n EnabledFeature,\n FeatureToggle,\n MultipartConfig,\n ResolvedFeature,\n ResolvedRoute,\n ResolvedUploadConfig,\n UploadConfig,\n} from \"@/types\";\nimport { normalizeObjectKey } from \"@/helpers/resolve-target\";\nimport { assertRouteName } from \"@/route\";\n\nexport function isEnabled<T extends { enabled: boolean }>(\n feature: T,\n): feature is T & { enabled: true } {\n return feature.enabled;\n}\n\nfunction resolveKeyPrefix(\n name: string,\n value: DimahS3RouteConfig[\"keyPrefix\"],\n): string | false {\n if (value === false) return false;\n const normalized = normalizeObjectKey(value ?? name);\n if (!normalized) {\n throw new Error(\n `dimahS3 route \"${name}\": keyPrefix is not a valid object-key prefix.`,\n );\n }\n return normalized;\n}\n\n/**\n * `true` / options → on; `false` → off.\n * `undefined` uses {@link defaultOn} (false unless passed).\n * Resolved `{ enabled }` objects (after `normalizeFeature`) use that flag.\n */\nexport function isFeatureOn<T extends object>(\n value: FeatureToggle<T> | ResolvedFeature<T> | undefined,\n defaultOn = false,\n): boolean {\n if (value === false) return false;\n if (value === undefined) return defaultOn;\n if (value === true) return true;\n if (\"enabled\" in value && typeof value.enabled === \"boolean\") {\n return value.enabled;\n }\n return true;\n}\n\n/** `true` / options → enabled; omit / `false` → disabled. */\nexport function normalizeFeature<T extends object>(\n value: FeatureToggle<T> | undefined,\n defaultOn = false,\n): ResolvedFeature<T> {\n if (value === false) return { enabled: false };\n if (value === undefined) {\n if (!defaultOn) return { enabled: false };\n return { enabled: true } as EnabledFeature<T>;\n }\n if (value === true) return { enabled: true } as EnabledFeature<T>;\n return { ...value, enabled: true };\n}\n\nfunction skippedPluginIds(plugins: DimahS3RouteConfig[\"plugins\"]): Set<string> {\n const ids = new Set<string>();\n if (!plugins) return ids;\n for (const [id, enabled] of Object.entries(plugins)) {\n if (enabled === false) ids.add(id);\n }\n return ids;\n}\n\nfunction splitUpload(upload: DimahS3RouteConfig[\"upload\"]): {\n upload: FeatureToggle<Omit<UploadConfig, \"multipart\">> | undefined;\n multipart: FeatureToggle<MultipartConfig> | undefined;\n} {\n if (upload === undefined || typeof upload === \"boolean\") {\n return { upload, multipart: undefined };\n }\n const { multipart, ...rest } = upload;\n return { upload: rest, multipart };\n}\n\nexport function normalizeRoute(\n name: string,\n route: DimahS3RouteConfig,\n instance: Pick<DimahS3Config, \"client\" | \"bucket\">,\n): ResolvedRoute {\n assertRouteName(name);\n\n const client = route.client ?? instance.client;\n const bucket = route.bucket ?? instance.bucket;\n if (!client) {\n throw new Error(\n `dimahS3 route \"${name}\": set client on the route or on dimahS3().`,\n );\n }\n if (!bucket) {\n throw new Error(\n `dimahS3 route \"${name}\": set bucket on the route or on dimahS3().`,\n );\n }\n\n const { upload: uploadInput, multipart: multipartInput } = splitUpload(\n route.upload,\n );\n const upload = normalizeFeature(uploadInput);\n const download = normalizeFeature<DownloadConfig>(route.download);\n const deleteFeature = normalizeFeature<DeleteConfig>(route.delete);\n const multipart = normalizeFeature<MultipartConfig>(multipartInput);\n\n if (!upload.enabled && !download.enabled && !deleteFeature.enabled) {\n throw new Error(\n `dimahS3 route \"${name}\": enable upload, download, or delete.`,\n );\n }\n\n const resolvedUpload: ResolvedUploadConfig = upload.enabled\n ? { ...upload, multipart }\n : { enabled: false, multipart: { enabled: false } };\n\n if (resolvedUpload.enabled) {\n const maxFileSize = resolvedUpload.maxFileSize;\n if (\n maxFileSize != null &&\n (!Number.isFinite(maxFileSize) || maxFileSize <= 0)\n ) {\n throw new Error(\n `dimahS3 route \"${name}\": maxFileSize must be a positive number.`,\n );\n }\n }\n\n return {\n name,\n client,\n bucket,\n keyPrefix: resolveKeyPrefix(name, route.keyPrefix),\n guard: route.guard,\n skippedPluginIds: skippedPluginIds(route.plugins),\n upload: resolvedUpload,\n download,\n delete: deleteFeature,\n };\n}\n\nexport function normalizeRoutes(\n config: DimahS3Config,\n): Record<string, ResolvedRoute> {\n const entries = Object.entries(config.routes);\n if (entries.length === 0) {\n throw new Error(\"dimahS3: at least one route is required.\");\n }\n const routes: Record<string, ResolvedRoute> = {};\n for (const [name, route] of entries) {\n routes[name] = normalizeRoute(name, route, config);\n }\n assertDistinctKeyPrefixes(routes);\n return routes;\n}\n\nfunction prefixesOverlap(a: string, b: string): boolean {\n return a === b || a.startsWith(`${b}/`) || b.startsWith(`${a}/`);\n}\n\n/** Nested or identical `keyPrefix` values would let one route access another's keys. */\nfunction assertDistinctKeyPrefixes(\n routes: Record<string, ResolvedRoute>,\n): void {\n const named = Object.entries(routes).filter(\n (entry): entry is [string, ResolvedRoute & { keyPrefix: string }] =>\n entry[1].keyPrefix !== false,\n );\n for (let i = 0; i < named.length; i++) {\n for (let j = i + 1; j < named.length; j++) {\n const [nameA, routeA] = named[i];\n const [nameB, routeB] = named[j];\n if (prefixesOverlap(routeA.keyPrefix, routeB.keyPrefix)) {\n throw new Error(\n `dimahS3: routes \"${nameA}\" and \"${nameB}\" have overlapping keyPrefix values (\"${routeA.keyPrefix}\" and \"${routeB.keyPrefix}\").`,\n );\n }\n }\n }\n}\n","import { matchesFileTypes } from \"@dimah-s3/core\";\nimport { errors } from \"@/errors\";\nimport type { UploadConfig } from \"@/types\";\n\n/** File limits from `upload` (`fileTypes` / `maxFileSize`). */\nexport type FileConstraints = Pick<UploadConfig, \"fileTypes\" | \"maxFileSize\">;\n\n/** Reject when `size` is over the route cap. No-op when `maxFileSize` is unset. */\nexport function assertWithinMaxFileSize(\n maxFileSize: number | undefined,\n size: number,\n): void {\n if (typeof maxFileSize === \"number\" && size > maxFileSize) {\n throw errors.payloadTooLarge();\n }\n}\n\nexport function assertDeclaredConstraints(\n constraints: FileConstraints | undefined,\n input: { fileName: string; fileSize: number; contentType?: string },\n): void {\n if (\n constraints?.fileTypes?.length &&\n !matchesFileTypes(input.fileName, input.contentType, constraints.fileTypes)\n ) {\n throw errors.fileTypeNotAllowed(input.fileName, input.contentType);\n }\n assertWithinMaxFileSize(constraints?.maxFileSize, input.fileSize);\n}\n\nexport function assertVerifiedConstraints(\n constraints: FileConstraints | undefined,\n input: { fileName?: string; contentType?: string; contentLength: number },\n): void {\n assertWithinMaxFileSize(constraints?.maxFileSize, input.contentLength);\n const name = input.fileName ?? \"\";\n if (\n constraints?.fileTypes?.length &&\n !matchesFileTypes(name, input.contentType, constraints.fileTypes)\n ) {\n throw errors.fileTypeNotAllowed(name || \"unknown\", input.contentType);\n }\n}\n","import type { S3ObjectAcl } from \"@dimah-s3/core\";\nimport { errors } from \"@/errors\";\nimport { assertDeclaredConstraints } from \"@/helpers/constraints\";\nimport { runHook } from \"@/helpers/hooks\";\nimport {\n resolveStoredTarget,\n resolveUploadTarget,\n} from \"@/helpers/resolve-target\";\nimport type {\n OpenedRoute,\n ResolvedDimahS3Config,\n ResolvedRoute,\n RouteOperation,\n StoredObjectContext,\n} from \"@/types\";\n\nexport type OpenedTarget<F extends RouteOperation> = {\n route: OpenedRoute<F>;\n key: string;\n bucket: string;\n stored: StoredObjectContext;\n};\n\nexport type OpenedUploadTarget<F extends \"upload\" | \"multipart\"> =\n OpenedTarget<F> & {\n metadata?: Record<string, string>;\n acl: S3ObjectAcl;\n };\n\nexport type OpenUploadInput = {\n route: string;\n fileName: string;\n fileSize: number;\n contentType?: string;\n metadata?: Record<string, string>;\n};\n\nexport function getResolvedRoute(\n config: ResolvedDimahS3Config,\n name: string,\n): ResolvedRoute {\n const route = config.routes[name];\n if (!route) {\n throw errors.unknownRoute(name);\n }\n return route;\n}\n\nfunction featureIsEnabled(\n route: ResolvedRoute,\n feature: RouteOperation,\n): boolean {\n if (feature === \"multipart\") return route.upload.multipart.enabled;\n return route[feature].enabled;\n}\n\n/** Disabled features respond 404 (`FEATURE_DISABLED`) from both HTTP and `s3.api`. */\nexport function assertFeatureEnabled<F extends RouteOperation>(\n route: ResolvedRoute,\n feature: F,\n): asserts route is OpenedRoute<F> {\n if (!featureIsEnabled(route, feature)) {\n throw errors.featureDisabled(feature);\n }\n}\n\n/** Lookup the named route, reject a disabled feature, run the route `guard`. */\nexport async function openRoute<F extends RouteOperation>(\n config: ResolvedDimahS3Config,\n name: string,\n request: Request,\n feature: F,\n): Promise<OpenedRoute<F>> {\n const route = getResolvedRoute(config, name);\n assertFeatureEnabled(route, feature);\n await runHook(route.guard, { request, route: route.name });\n return route;\n}\n\nexport function storedObjectContext(\n request: Request,\n route: Pick<ResolvedRoute, \"name\" | \"bucket\">,\n key: string,\n): StoredObjectContext {\n return { request, route: route.name, key, bucket: route.bucket };\n}\n\n/**\n * {@link openRoute} plus file constraints and server-owned key generation.\n * Used by upload presign and multipart init.\n */\nexport async function openUploadTarget<F extends \"upload\" | \"multipart\">(\n config: ResolvedDimahS3Config,\n input: OpenUploadInput,\n request: Request,\n feature: F,\n): Promise<OpenedUploadTarget<F>> {\n const route = await openRoute(config, input.route, request, feature);\n const fileSize = Math.floor(input.fileSize);\n const fileName = input.fileName;\n assertDeclaredConstraints(route.upload, {\n fileName,\n fileSize,\n contentType: input.contentType,\n });\n const target = await resolveUploadTarget(route, {\n request,\n route: route.name,\n file: {\n name: fileName,\n size: fileSize,\n type: input.contentType,\n },\n clientMetadata: input.metadata,\n });\n return {\n route,\n ...target,\n stored: storedObjectContext(request, route, target.key),\n };\n}\n\n/** {@link openRoute} plus the stored-key namespace check. */\nexport async function openStoredTarget<F extends RouteOperation>(\n config: ResolvedDimahS3Config,\n input: { route: string; key: string },\n request: Request,\n feature: F,\n): Promise<OpenedTarget<F>> {\n const route = await openRoute(config, input.route, request, feature);\n const target = resolveStoredTarget(route, input.key);\n return {\n route,\n ...target,\n stored: storedObjectContext(request, route, target.key),\n };\n}\n","import {\n HeadObjectCommand,\n type HeadObjectCommandOutput,\n type S3Client,\n} from \"@aws-sdk/client-s3\";\nimport { errors } from \"@/errors\";\nimport { sendOrObjectNotFound } from \"./is-aws-not-found\";\n\n/** HeadObject, mapping AWS not-found to `OBJECT_NOT_FOUND`. */\nexport async function headObjectOrNotFound(\n client: S3Client,\n bucket: string,\n key: string,\n): Promise<HeadObjectCommandOutput> {\n return sendOrObjectNotFound(() =>\n client.send(new HeadObjectCommand({ Bucket: bucket, Key: key })),\n );\n}\n\n/**\n * HeadObject after CompleteMultipartUpload. Some providers briefly omit\n * `ContentLength`; retry a few times with exponential backoff.\n */\nexport async function headObjectAfterMultipartComplete(\n client: S3Client,\n bucket: string,\n key: string,\n): Promise<HeadObjectCommandOutput> {\n const send = (): Promise<HeadObjectCommandOutput> =>\n sendOrObjectNotFound(() =>\n client.send(new HeadObjectCommand({ Bucket: bucket, Key: key })),\n );\n\n let head = await send();\n for (\n let attempt = 0;\n attempt < 4 && typeof head.ContentLength !== \"number\";\n attempt++\n ) {\n await new Promise((r) => setTimeout(r, 250 * 2 ** attempt));\n head = await send();\n }\n return head;\n}\n\n/** Verified size from HeadObject — never invent `0` when S3 omits it. */\nexport function requireContentLength(head: HeadObjectCommandOutput): number {\n if (typeof head.ContentLength !== \"number\") {\n throw errors.internalError();\n }\n return head.ContentLength;\n}\n","import {\n ListPartsCommand,\n type ListPartsCommandOutput,\n type Part,\n type S3Client,\n} from \"@aws-sdk/client-s3\";\nimport { sendOrObjectNotFound } from \"./is-aws-not-found\";\n\n/** Page through ListParts until S3 reports no more parts. */\nexport async function listAllParts(\n client: S3Client,\n input: { bucket: string; key: string; uploadId: string },\n): Promise<Part[]> {\n const parts: Part[] = [];\n let partNumberMarker: string | undefined;\n let isTruncated = true;\n\n while (isTruncated) {\n const response: ListPartsCommandOutput = await sendOrObjectNotFound(() =>\n client.send(\n new ListPartsCommand({\n Bucket: input.bucket,\n Key: input.key,\n UploadId: input.uploadId,\n ...(partNumberMarker ? { PartNumberMarker: partNumberMarker } : {}),\n }),\n ),\n );\n parts.push(...(response.Parts ?? []));\n isTruncated = response.IsTruncated === true;\n partNumberMarker = isTruncated ? response.NextPartNumberMarker : undefined;\n }\n\n return parts;\n}\n\n/** Sum `Size` on listed parts. Pass `excludePartNumber` when replacing a part. */\nexport function listedPartsByteSize(\n parts: readonly { PartNumber?: number; Size?: number }[],\n excludePartNumber?: number,\n): number {\n let total = 0;\n for (const part of parts) {\n if (\n excludePartNumber !== undefined &&\n part.PartNumber === excludePartNumber\n ) {\n continue;\n }\n total += part.Size ?? 0;\n }\n return total;\n}\n","import type { ConfirmedObjectResponse, S3ObjectAcl } from \"@dimah-s3/core\";\nimport { resolveStoredFileName } from \"@dimah-s3/core\";\nimport type { HeadObjectCommandOutput, S3Client } from \"@aws-sdk/client-s3\";\nimport { assertVerifiedConstraints } from \"@/helpers/constraints\";\nimport { deleteObjectBestEffort } from \"@/helpers/best-effort\";\nimport { requireContentLength } from \"@/helpers/head-object\";\nimport { runLifecycleHook } from \"@/helpers/hooks\";\nimport { assertStoredKey } from \"@/helpers/resolve-target\";\nimport {\n previousKeyFromMetadata,\n stripPreviousKeyMeta,\n} from \"@/helpers/previous-key\";\nimport type {\n OpenedRoute,\n ResolvedDimahS3Config,\n StoredObjectContext,\n UploadOnConfirmedContext,\n} from \"@/types\";\n\nexport type FinalizeConfirmedInput = {\n config: ResolvedDimahS3Config;\n route: OpenedRoute<\"upload\" | \"multipart\">;\n stored: StoredObjectContext;\n head: HeadObjectCommandOutput;\n uploadId?: string;\n /** ACL from the upload policy, not GetObjectAcl. */\n acl?: S3ObjectAcl;\n};\n\n/**\n * HeadObject constraints, `onConfirmed`, then compensating `DeleteObject`\n * (and `previousKey` cleanup) so a thrown lifecycle hook cannot leave an\n * orphan object.\n */\nexport async function finalizeConfirmedObject(\n client: S3Client,\n bucket: string,\n key: string,\n input: FinalizeConfirmedInput,\n): Promise<ConfirmedObjectResponse> {\n const { config, route, stored, head, uploadId, acl } = input;\n const contentLength = requireContentLength(head);\n const fileName = resolveStoredFileName(head.ContentDisposition, key);\n const rawMetadata = head.Metadata ?? {};\n\n try {\n assertVerifiedConstraints(route.upload, {\n fileName,\n contentType: head.ContentType,\n contentLength,\n });\n } catch (err) {\n await deleteObjectBestEffort(client, bucket, key);\n throw err;\n }\n\n const metadata = stripPreviousKeyMeta(rawMetadata);\n const context: UploadOnConfirmedContext = {\n ...stored,\n contentType: head.ContentType,\n contentLength,\n eTag: head.ETag?.replace(/\"/g, \"\"),\n metadata,\n acl,\n fileName,\n versionId: head.VersionId,\n lastModified: head.LastModified?.toISOString(),\n uploadId,\n };\n\n try {\n await runLifecycleHook(route.upload.onConfirmed, context, config);\n } catch (err) {\n await deleteObjectBestEffort(client, bucket, key);\n throw err;\n }\n\n const previousKey = previousKeyFromMetadata(rawMetadata);\n if (previousKey && previousKey !== key) {\n try {\n const safe = assertStoredKey(previousKey, route.keyPrefix);\n await deleteObjectBestEffort(client, bucket, safe);\n } catch {\n // Invalid previousKey — skip.\n }\n }\n\n return {\n key,\n bucket,\n contentType: context.contentType,\n contentLength: context.contentLength,\n eTag: context.eTag,\n metadata: context.metadata ?? {},\n acl,\n fileName,\n versionId: context.versionId,\n lastModified: context.lastModified,\n };\n}\n","import { PutObjectCommand } from \"@aws-sdk/client-s3\";\nimport type { ConfirmedObjectResponse, S3RouteName } from \"@dimah-s3/core\";\nimport { requestFromHeaders } from \"@/helpers/request\";\nimport {\n finalizeConfirmedObject,\n headObjectOrNotFound,\n openUploadTarget,\n runHook,\n} from \"@/helpers\";\nimport type { ResolvedDimahS3Config } from \"@/types\";\n\nexport type PutObjectInput = {\n route: S3RouteName;\n fileName: string;\n contentType?: string;\n body: Uint8Array | ArrayBuffer | string;\n metadata?: Record<string, string>;\n headers?: HeadersInit;\n};\n\nfunction toBytes(body: PutObjectInput[\"body\"]): Uint8Array {\n if (typeof body === \"string\") return new TextEncoder().encode(body);\n if (body instanceof ArrayBuffer) return new Uint8Array(body);\n return body;\n}\n\n/**\n * Server-side upload through the same route policy as presign + confirm.\n */\nexport async function putObject(\n config: ResolvedDimahS3Config,\n input: PutObjectInput,\n): Promise<ConfirmedObjectResponse> {\n const body = toBytes(input.body);\n const request = requestFromHeaders(input.headers);\n await runHook(config.guard, { request });\n const fileSize = body.byteLength;\n const { route, key, bucket, metadata, acl, stored } = await openUploadTarget(\n config,\n {\n route: input.route,\n fileName: input.fileName,\n fileSize,\n contentType: input.contentType,\n metadata: input.metadata,\n },\n request,\n \"upload\",\n );\n\n await runHook(route.upload.guard, {\n ...stored,\n file: {\n name: input.fileName,\n size: fileSize,\n type: input.contentType,\n },\n metadata,\n clientMetadata: input.metadata,\n acl,\n replace: route.upload.replace,\n });\n\n await route.client.send(\n new PutObjectCommand({\n Bucket: bucket,\n Key: key,\n Body: body,\n ContentType: input.contentType,\n ContentLength: fileSize,\n Metadata: metadata,\n ACL: acl,\n }),\n );\n\n const head = await headObjectOrNotFound(route.client, bucket, key);\n return finalizeConfirmedObject(route.client, bucket, key, {\n config,\n route,\n stored,\n head,\n acl,\n });\n}\n","import { createMiddleware } from \"better-call\";\nimport { requestFromHeaders, runHook } from \"@/helpers\";\nimport type { S3EndpointContext } from \"./context\";\n\n/**\n * Injects `config` / `request` and runs the global `guard`.\n * Used by {@link createS3Endpoint} so HTTP and `s3.api` share the same path.\n */\nexport const s3ContextMiddleware = createMiddleware(async (ctx) => {\n const injected = ctx.context as Partial<S3EndpointContext> | undefined;\n if (!injected?.config) {\n throw new Error(\n \"createS3Endpoint requires dimahS3 router context. Call endpoints through dimahS3().api or the HTTP handler.\",\n );\n }\n\n const request =\n ctx.request ??\n injected.request ??\n requestFromHeaders(ctx.headers as HeadersInit | undefined);\n\n await runHook(injected.config.guard, { request });\n\n return {\n config: injected.config,\n request,\n } satisfies S3EndpointContext;\n});\n\n/**\n * Middleware factory with dimah-s3 context already applied — same idea as\n * Better Auth `createAuthMiddleware`.\n */\nexport const createS3Middleware = createMiddleware.create({\n use: [s3ContextMiddleware],\n});\n","import { createEndpoint, type EndpointOptions } from \"better-call\";\nimport { errors } from \"@/errors\";\nimport { s3ContextMiddleware } from \"./create-s3-middleware\";\n\nconst createEndpointWithContext = createEndpoint.create({\n use: [s3ContextMiddleware],\n});\n\nfunction withS3Validation<O extends EndpointOptions>(options: O): O {\n return {\n ...options,\n onValidationError:\n options.onValidationError ??\n (({ message }: { message: string }) => {\n throw errors.validationError(message);\n }),\n };\n}\n\ntype CreateS3Endpoint = typeof createEndpointWithContext;\n\n/**\n * Typed endpoint for dimah-s3 plugins and core routes.\n *\n * Paths are absolute under `basePath` (e.g. `/db/objects`). Context\n * (`config`, `request`) is injected by the router / `s3.api`.\n * Zod failures throw `DimahS3Error` (`VALIDATION_ERROR`) via\n * better-call `onValidationError`.\n *\n * ```ts\n * endpoints: {\n * recent: createS3Endpoint(\"/audit/recent\", { method: \"GET\" }, async (ctx) => {\n * return { events: [] };\n * }),\n * }\n * ```\n */\nexport const createS3Endpoint: CreateS3Endpoint = ((\n pathOrOptions: string | EndpointOptions,\n optionsOrHandler: EndpointOptions | ((...args: never[]) => unknown),\n maybeHandler?: (...args: never[]) => unknown,\n) => {\n if (typeof pathOrOptions === \"string\") {\n return createEndpointWithContext(\n pathOrOptions,\n withS3Validation(optionsOrHandler as EndpointOptions),\n maybeHandler as never,\n );\n }\n return createEndpointWithContext(\n withS3Validation(pathOrOptions),\n optionsOrHandler as never,\n );\n}) as unknown as CreateS3Endpoint;\n","import { confirmBodySchema, S3_API_ROUTES } from \"@dimah-s3/core\";\nimport {\n finalizeConfirmedObject,\n headObjectOrNotFound,\n openStoredTarget,\n runHook,\n} from \"@/helpers\";\nimport type { ResolvedDimahS3Config } from \"@/types\";\nimport { createS3Endpoint } from \"@/api/create-s3-endpoint\";\n\nasync function handleConfirm(\n config: ResolvedDimahS3Config,\n input: typeof confirmBodySchema._output,\n request: Request,\n) {\n const { route, key, bucket, stored } = await openStoredTarget(\n config,\n input,\n request,\n \"upload\",\n );\n\n await runHook(route.upload.confirmGuard, {\n ...stored,\n replace: route.upload.replace,\n });\n\n const head = await headObjectOrNotFound(route.client, bucket, key);\n return finalizeConfirmedObject(route.client, bucket, key, {\n config,\n route,\n stored,\n head,\n acl: route.upload.acl,\n });\n}\n\nexport const confirm = createS3Endpoint(\n S3_API_ROUTES.uploadConfirm,\n { method: \"POST\", body: confirmBodySchema },\n async (ctx) => {\n return handleConfirm(ctx.context.config, ctx.body, ctx.context.request);\n },\n);\n","import { DeleteObjectCommand } from \"@aws-sdk/client-s3\";\nimport {\n deleteQuerySchema,\n S3_API_ROUTES,\n type DeleteResponse,\n} from \"@dimah-s3/core\";\nimport {\n headObjectOrNotFound,\n openStoredTarget,\n runHook,\n runLifecycleHook,\n} from \"@/helpers\";\nimport type { ResolvedDimahS3Config } from \"@/types\";\nimport { createS3Endpoint } from \"@/api/create-s3-endpoint\";\n\nasync function handleDelete(\n config: ResolvedDimahS3Config,\n input: typeof deleteQuerySchema._output,\n request: Request,\n): Promise<DeleteResponse> {\n const { route, key, bucket, stored } = await openStoredTarget(\n config,\n input,\n request,\n \"delete\",\n );\n\n await runHook(route.delete.guard, stored);\n\n await headObjectOrNotFound(route.client, bucket, key);\n\n await route.client.send(\n new DeleteObjectCommand({ Bucket: bucket, Key: key }),\n );\n\n await runLifecycleHook(route.delete.onDeleted, stored, config);\n\n return { success: true, bucket, key };\n}\n\nexport const deleteObject = createS3Endpoint(\n S3_API_ROUTES.delete,\n { method: \"DELETE\", query: deleteQuerySchema },\n async (ctx) => {\n return handleDelete(ctx.context.config, ctx.query, ctx.context.request);\n },\n);\n","import { DeleteObjectCommand } from \"@aws-sdk/client-s3\";\nimport {\n deleteBatchBodySchema,\n isDimahS3Error,\n S3_API_ROUTES,\n type DeleteBatchResponse,\n} from \"@dimah-s3/core\";\nimport {\n headObjectOrNotFound,\n openStoredTarget,\n runHook,\n runLifecycleHook,\n} from \"@/helpers\";\nimport type { ResolvedDimahS3Config } from \"@/types\";\nimport { createS3Endpoint } from \"@/api/create-s3-endpoint\";\n\nasync function deleteOne(\n config: ResolvedDimahS3Config,\n routeName: string,\n key: string,\n request: Request,\n): Promise<void> {\n const { route, bucket, stored } = await openStoredTarget(\n config,\n { route: routeName, key },\n request,\n \"delete\",\n );\n\n await runHook(route.delete.guard, stored);\n await headObjectOrNotFound(route.client, bucket, stored.key);\n await route.client.send(\n new DeleteObjectCommand({ Bucket: bucket, Key: stored.key }),\n );\n await runLifecycleHook(route.delete.onDeleted, stored, config);\n}\n\nexport const deleteBatch = createS3Endpoint(\n S3_API_ROUTES.deleteBatch,\n { method: \"POST\", body: deleteBatchBodySchema },\n async (ctx): Promise<DeleteBatchResponse> => {\n const config = ctx.context.config;\n const request = ctx.context.request;\n const results: DeleteBatchResponse[\"results\"] = [];\n\n for (const key of ctx.body.keys) {\n try {\n await deleteOne(config, ctx.body.route, key, request);\n results.push({ key, success: true });\n } catch (err) {\n results.push({\n key,\n success: false,\n error: isDimahS3Error(err)\n ? { code: err.code ?? \"INTERNAL_ERROR\", message: err.message }\n : { code: \"INTERNAL_ERROR\", message: \"Internal server error\" },\n });\n }\n }\n\n return { results };\n },\n);\n","import { GetObjectCommand } from \"@aws-sdk/client-s3\";\nimport { getSignedUrl } from \"@aws-sdk/s3-request-presigner\";\nimport {\n buildContentDisposition,\n downloadQuerySchema,\n S3_API_ROUTES,\n type DownloadPresignResponse,\n} from \"@dimah-s3/core\";\nimport {\n headObjectOrNotFound,\n normalizeExpiresIn,\n openStoredTarget,\n runHook,\n runLifecycleHook,\n} from \"@/helpers\";\nimport type { ResolvedDimahS3Config } from \"@/types\";\nimport { createS3Endpoint } from \"@/api/create-s3-endpoint\";\n\nfunction fileUrl(\n request: Request,\n basePath: string,\n query: {\n route: string;\n key: string;\n fileName?: string;\n disposition?: string;\n },\n): string {\n const url = new URL(request.url);\n const prefix = basePath.endsWith(\"/\") ? basePath.slice(0, -1) : basePath;\n url.pathname = `${prefix}${S3_API_ROUTES.file}`;\n url.search = \"\";\n url.searchParams.set(\"route\", query.route);\n url.searchParams.set(\"key\", query.key);\n if (query.fileName) url.searchParams.set(\"fileName\", query.fileName);\n if (query.disposition) url.searchParams.set(\"disposition\", query.disposition);\n return url.toString();\n}\n\nasync function handleDownload(\n config: ResolvedDimahS3Config,\n input: typeof downloadQuerySchema._output,\n request: Request,\n): Promise<DownloadPresignResponse> {\n const { route, key, bucket, stored } = await openStoredTarget(\n config,\n input,\n request,\n \"download\",\n );\n\n const resolved = await route.download.resolve?.({\n ...stored,\n fileName: input.fileName,\n disposition: input.disposition ?? route.download.disposition,\n });\n\n const fileName = resolved?.fileName ?? input.fileName;\n const disposition =\n resolved?.disposition ??\n input.disposition ??\n route.download.disposition ??\n \"attachment\";\n const expiresIn = normalizeExpiresIn(\n resolved?.expiresIn ?? route.download.expiresIn,\n config.maxExpiresIn,\n );\n\n await runHook(route.download.guard, {\n ...stored,\n fileName,\n disposition,\n });\n\n await headObjectOrNotFound(route.client, bucket, key);\n\n const mode = route.download.mode ?? \"presign\";\n const contentDisposition = fileName\n ? buildContentDisposition(fileName, disposition)\n : disposition;\n\n const url =\n mode === \"proxy\"\n ? fileUrl(request, config.basePath ?? \"/api/s3\", {\n route: input.route,\n key,\n fileName,\n disposition,\n })\n : await getSignedUrl(\n route.client,\n new GetObjectCommand({\n Bucket: bucket,\n Key: key,\n ResponseContentDisposition: contentDisposition,\n }),\n { expiresIn },\n );\n\n await runLifecycleHook(\n route.download.onPresigned,\n {\n ...stored,\n fileName,\n url,\n expiresIn: mode === \"proxy\" ? 0 : expiresIn,\n },\n config,\n );\n\n return {\n bucket,\n key,\n url,\n expiresIn: mode === \"proxy\" ? 0 : expiresIn,\n mode,\n disposition,\n };\n}\n\nexport const download = createS3Endpoint(\n S3_API_ROUTES.download,\n { method: \"GET\", query: downloadQuerySchema },\n async (ctx) => {\n return handleDownload(ctx.context.config, ctx.query, ctx.context.request);\n },\n);\n","import {\n S3_API_ROUTES,\n type RouteCatalogEntry,\n type RouteCatalogResponse,\n} from \"@dimah-s3/core\";\nimport { isEnabled } from \"@/helpers/features\";\nimport type { ResolvedDimahS3Config } from \"@/types\";\nimport { createS3Endpoint } from \"@/api/create-s3-endpoint\";\n\nfunction catalogUpload(\n upload: ResolvedDimahS3Config[\"routes\"][string][\"upload\"],\n): RouteCatalogEntry[\"upload\"] {\n if (!isEnabled(upload)) return { enabled: false };\n return {\n enabled: true,\n fileTypes: upload.fileTypes,\n maxFileSize: upload.maxFileSize,\n multipart: isEnabled(upload.multipart),\n ...(upload.checksum ? { checksum: true } : {}),\n ...(upload.replace ? { replace: upload.replace } : {}),\n };\n}\n\nfunction catalogDownload(\n download: ResolvedDimahS3Config[\"routes\"][string][\"download\"],\n): RouteCatalogEntry[\"download\"] {\n if (!isEnabled(download)) return { enabled: false };\n return {\n enabled: true,\n ...(download.disposition ? { disposition: download.disposition } : {}),\n ...(download.mode ? { mode: download.mode } : {}),\n };\n}\n\nexport function buildRouteCatalog(\n config: ResolvedDimahS3Config,\n): RouteCatalogResponse {\n const routes: RouteCatalogResponse[\"routes\"] = {};\n for (const [name, route] of Object.entries(config.routes)) {\n routes[name] = {\n upload: catalogUpload(route.upload),\n download: catalogDownload(route.download),\n delete: isEnabled(route.delete) ? { enabled: true } : { enabled: false },\n };\n }\n return { routes };\n}\n\nexport const catalog = createS3Endpoint(\n S3_API_ROUTES.catalog,\n { method: \"GET\" },\n async (ctx): Promise<RouteCatalogResponse> => {\n return buildRouteCatalog(ctx.context.config);\n },\n);\n","import { GetObjectCommand } from \"@aws-sdk/client-s3\";\nimport {\n buildContentDisposition,\n fileQuerySchema,\n resolveStoredFileName,\n S3_API_ROUTES,\n} from \"@dimah-s3/core\";\nimport { errors } from \"@/errors\";\nimport {\n headObjectOrNotFound,\n openStoredTarget,\n runHook,\n sendOrObjectNotFound,\n} from \"@/helpers\";\nimport type { ResolvedDimahS3Config } from \"@/types\";\nimport { createS3Endpoint } from \"@/api/create-s3-endpoint\";\n\nasync function handleFile(\n config: ResolvedDimahS3Config,\n input: typeof fileQuerySchema._output,\n request: Request,\n): Promise<Response> {\n const { route, key, bucket, stored } = await openStoredTarget(\n config,\n input,\n request,\n \"download\",\n );\n\n const resolved = await route.download.resolve?.({\n ...stored,\n fileName: input.fileName,\n disposition: input.disposition ?? route.download.disposition,\n });\n const fileName = resolved?.fileName ?? input.fileName;\n const disposition =\n resolved?.disposition ??\n input.disposition ??\n route.download.disposition ??\n \"attachment\";\n\n await runHook(route.download.guard, {\n ...stored,\n fileName,\n disposition,\n });\n\n await headObjectOrNotFound(route.client, bucket, key);\n\n const result = await sendOrObjectNotFound(() =>\n route.client.send(\n new GetObjectCommand({\n Bucket: bucket,\n Key: key,\n ResponseContentDisposition: fileName\n ? buildContentDisposition(fileName, disposition)\n : `${disposition}`,\n }),\n ),\n );\n\n const body = result.Body;\n if (!body) throw errors.objectNotFound();\n\n const stream =\n \"transformToWebStream\" in body &&\n typeof body.transformToWebStream === \"function\"\n ? body.transformToWebStream()\n : (body as ReadableStream<Uint8Array>);\n\n const headers = new Headers();\n headers.set(\"Content-Type\", result.ContentType ?? \"application/octet-stream\");\n headers.set(\n \"Content-Disposition\",\n fileName\n ? buildContentDisposition(fileName, disposition)\n : `${disposition}`,\n );\n if (typeof result.ContentLength === \"number\") {\n headers.set(\"Content-Length\", String(result.ContentLength));\n }\n\n return new Response(stream, { headers });\n}\n\nexport const file = createS3Endpoint(\n S3_API_ROUTES.file,\n { method: \"GET\", query: fileQuerySchema },\n async (ctx) => {\n return handleFile(ctx.context.config, ctx.query, ctx.context.request);\n },\n);\n\nexport { resolveStoredFileName };\n","import { AbortMultipartUploadCommand } from \"@aws-sdk/client-s3\";\nimport {\n multipartAbortBodySchema,\n S3_API_ROUTES,\n type MultipartAbortResponse,\n} from \"@dimah-s3/core\";\nimport {\n openStoredTarget,\n runHook,\n runLifecycleHook,\n sendOrObjectNotFound,\n} from \"@/helpers\";\nimport type { ResolvedDimahS3Config } from \"@/types\";\nimport { createS3Endpoint } from \"@/api/create-s3-endpoint\";\n\nasync function handleAbort(\n config: ResolvedDimahS3Config,\n input: typeof multipartAbortBodySchema._output,\n request: Request,\n): Promise<MultipartAbortResponse> {\n const { route, key, bucket, stored } = await openStoredTarget(\n config,\n input,\n request,\n \"multipart\",\n );\n const uploadId = input.uploadId;\n\n await runHook(route.upload.multipart.guard, {\n ...stored,\n uploadId,\n action: \"abort\",\n });\n\n await sendOrObjectNotFound(() =>\n route.client.send(\n new AbortMultipartUploadCommand({\n Bucket: bucket,\n Key: key,\n UploadId: uploadId,\n }),\n ),\n );\n\n await runLifecycleHook(\n route.upload.multipart.onAbort,\n {\n ...stored,\n uploadId,\n },\n config,\n );\n\n return { bucket, key, uploadId, aborted: true };\n}\n\nexport const multipartAbort = createS3Endpoint(\n S3_API_ROUTES.multipartAbort,\n { method: \"POST\", body: multipartAbortBodySchema },\n async (ctx) => {\n return handleAbort(ctx.context.config, ctx.body, ctx.context.request);\n },\n);\n","import {\n CompleteMultipartUploadCommand,\n type CompleteMultipartUploadCommandOutput,\n} from \"@aws-sdk/client-s3\";\nimport {\n multipartCompleteBodySchema,\n S3_API_ROUTES,\n type MultipartCompleteResponse,\n} from \"@dimah-s3/core\";\nimport { errors } from \"@/errors\";\nimport {\n abortMultipartBestEffort,\n assertWithinMaxFileSize,\n finalizeConfirmedObject,\n headObjectAfterMultipartComplete,\n listAllParts,\n openStoredTarget,\n runHook,\n sendOrObjectNotFound,\n} from \"@/helpers\";\nimport type { ResolvedDimahS3Config } from \"@/types\";\nimport { createS3Endpoint } from \"@/api/create-s3-endpoint\";\n\nasync function handleComplete(\n config: ResolvedDimahS3Config,\n input: typeof multipartCompleteBodySchema._output,\n request: Request,\n): Promise<MultipartCompleteResponse> {\n const { route, key, bucket, stored } = await openStoredTarget(\n config,\n input,\n request,\n \"multipart\",\n );\n const uploadId = input.uploadId;\n const parts = [\n ...new Set(input.parts.map(({ partNumber }) => partNumber)),\n ].sort((a, b) => a - b);\n const partRefs = parts.map((partNumber) => ({ partNumber }));\n\n await runHook(route.upload.multipart.guard, {\n ...stored,\n uploadId,\n action: \"complete\",\n });\n await runHook(route.upload.confirmGuard, {\n ...stored,\n uploadId,\n parts: partRefs,\n replace: route.upload.replace,\n });\n\n const listedParts = await listAllParts(route.client, {\n bucket,\n key,\n uploadId,\n });\n\n let assembledBytes = 0;\n const completeParts = parts.map((partNumber) => {\n const found = listedParts.find((p) => p.PartNumber === partNumber);\n if (!found?.ETag) {\n throw errors.multipartPartMissing(partNumber);\n }\n assembledBytes += found.Size ?? 0;\n return { PartNumber: partNumber, ETag: found.ETag };\n });\n\n try {\n assertWithinMaxFileSize(route.upload.maxFileSize, assembledBytes);\n } catch (err) {\n await abortMultipartBestEffort(route.client, bucket, key, uploadId);\n throw err;\n }\n\n const completeResult: CompleteMultipartUploadCommandOutput =\n await sendOrObjectNotFound(() =>\n route.client.send(\n new CompleteMultipartUploadCommand({\n Bucket: bucket,\n Key: key,\n UploadId: uploadId,\n MultipartUpload: { Parts: completeParts },\n }),\n ),\n );\n\n const head = await headObjectAfterMultipartComplete(\n route.client,\n bucket,\n key,\n );\n const confirmed = await finalizeConfirmedObject(route.client, bucket, key, {\n config,\n route,\n stored,\n head: {\n ...head,\n ETag: head.ETag ?? completeResult.ETag,\n },\n uploadId,\n acl: route.upload.acl,\n });\n\n return { ...confirmed, uploadId };\n}\n\nexport const multipartComplete = createS3Endpoint(\n S3_API_ROUTES.multipartComplete,\n { method: \"POST\", body: multipartCompleteBodySchema },\n async (ctx) => {\n return handleComplete(ctx.context.config, ctx.body, ctx.context.request);\n },\n);\n","import {\n CreateMultipartUploadCommand,\n type CreateMultipartUploadCommandOutput,\n} from \"@aws-sdk/client-s3\";\nimport {\n buildContentDisposition,\n multipartInitBodySchema,\n S3_API_ROUTES,\n type MultipartInitResponse,\n} from \"@dimah-s3/core\";\nimport { errors } from \"@/errors\";\nimport { openUploadTarget, runHook, runLifecycleHook } from \"@/helpers\";\nimport type { ResolvedDimahS3Config } from \"@/types\";\nimport { createS3Endpoint } from \"@/api/create-s3-endpoint\";\n\nasync function handleMultipartInit(\n config: ResolvedDimahS3Config,\n input: typeof multipartInitBodySchema._output,\n request: Request,\n): Promise<MultipartInitResponse> {\n const fileSize = Math.floor(input.fileSize);\n const fileName = input.fileName;\n const { route, key, bucket, metadata, acl, stored } = await openUploadTarget(\n config,\n {\n route: input.route,\n fileName,\n fileSize,\n contentType: input.contentType,\n metadata: input.metadata,\n },\n request,\n \"multipart\",\n );\n\n await runHook(route.upload.guard, {\n ...stored,\n file: {\n name: fileName,\n size: fileSize,\n type: input.contentType,\n },\n metadata,\n clientMetadata: input.metadata,\n acl,\n replace: route.upload.replace,\n });\n\n const { UploadId } = (await route.client.send(\n new CreateMultipartUploadCommand({\n Bucket: bucket,\n Key: key,\n ContentType: input.contentType,\n ContentDisposition: buildContentDisposition(fileName),\n Metadata: metadata,\n ACL: acl,\n }),\n )) as CreateMultipartUploadCommandOutput;\n\n if (!UploadId) {\n throw errors.internalError();\n }\n\n await runLifecycleHook(\n route.upload.multipart.onInit,\n {\n ...stored,\n uploadId: UploadId,\n file: {\n name: fileName,\n size: fileSize,\n type: input.contentType,\n },\n metadata,\n clientMetadata: input.metadata,\n acl,\n replace: route.upload.replace,\n },\n config,\n );\n\n return { bucket, key, uploadId: UploadId };\n}\n\nexport const multipartInit = createS3Endpoint(\n S3_API_ROUTES.multipartInit,\n { method: \"POST\", body: multipartInitBodySchema },\n async (ctx) => {\n const result = await handleMultipartInit(\n ctx.context.config,\n ctx.body,\n ctx.context.request,\n );\n ctx.setStatus(201);\n return result;\n },\n);\n","import {\n multipartListPartsQuerySchema,\n S3_API_ROUTES,\n type MultipartListPartsResponse,\n} from \"@dimah-s3/core\";\nimport {\n listAllParts,\n openStoredTarget,\n runHook,\n runLifecycleHook,\n} from \"@/helpers\";\nimport type { ResolvedDimahS3Config } from \"@/types\";\nimport { createS3Endpoint } from \"@/api/create-s3-endpoint\";\n\nasync function handleListParts(\n config: ResolvedDimahS3Config,\n input: typeof multipartListPartsQuerySchema._output,\n request: Request,\n): Promise<MultipartListPartsResponse> {\n const { route, key, bucket, stored } = await openStoredTarget(\n config,\n input,\n request,\n \"multipart\",\n );\n const uploadId = input.uploadId;\n\n await runHook(route.upload.multipart.guard, {\n ...stored,\n uploadId,\n action: \"list\",\n });\n\n const listed = await listAllParts(route.client, { bucket, key, uploadId });\n\n const parts = listed.flatMap((p) => {\n if (p.PartNumber == null || p.PartNumber < 1) return [];\n return [\n {\n partNumber: p.PartNumber,\n size: p.Size ?? 0,\n eTag: (p.ETag ?? \"\").replace(/\"/g, \"\"),\n },\n ];\n });\n\n await runLifecycleHook(\n route.upload.multipart.onList,\n {\n ...stored,\n uploadId,\n parts,\n },\n config,\n );\n\n return { parts };\n}\n\nexport const multipartListParts = createS3Endpoint(\n S3_API_ROUTES.multipartListParts,\n { method: \"GET\", query: multipartListPartsQuerySchema },\n async (ctx) => {\n return handleListParts(ctx.context.config, ctx.query, ctx.context.request);\n },\n);\n","import { UploadPartCommand } from \"@aws-sdk/client-s3\";\nimport { getSignedUrl } from \"@aws-sdk/s3-request-presigner\";\nimport {\n multipartSignPartBodySchema,\n S3_API_ROUTES,\n type MultipartPartResponse,\n} from \"@dimah-s3/core\";\nimport {\n assertWithinMaxFileSize,\n listAllParts,\n listedPartsByteSize,\n normalizeExpiresIn,\n openStoredTarget,\n runHook,\n} from \"@/helpers\";\nimport type { ResolvedDimahS3Config } from \"@/types\";\nimport { createS3Endpoint } from \"@/api/create-s3-endpoint\";\n\nasync function handleSignPart(\n config: ResolvedDimahS3Config,\n input: typeof multipartSignPartBodySchema._output,\n request: Request,\n): Promise<MultipartPartResponse> {\n const { route, key, bucket, stored } = await openStoredTarget(\n config,\n input,\n request,\n \"multipart\",\n );\n const uploadId = input.uploadId;\n const partNumber = input.partNumber;\n const expiresIn = normalizeExpiresIn(\n route.upload.expiresIn,\n config.maxExpiresIn,\n );\n const partSize = Math.floor(input.partSize);\n\n await runHook(route.upload.multipart.guard, {\n ...stored,\n uploadId,\n action: \"part\",\n partNumber,\n partSize,\n });\n\n const maxFileSize = route.upload.maxFileSize;\n assertWithinMaxFileSize(maxFileSize, partSize);\n if (typeof maxFileSize === \"number\") {\n const listed = await listAllParts(route.client, { bucket, key, uploadId });\n assertWithinMaxFileSize(\n maxFileSize,\n listedPartsByteSize(listed, partNumber) + partSize,\n );\n }\n\n const url = await getSignedUrl(\n route.client,\n new UploadPartCommand({\n Bucket: bucket,\n Key: key,\n UploadId: uploadId,\n PartNumber: partNumber,\n ContentLength: partSize,\n }),\n {\n expiresIn,\n signableHeaders: new Set([\"content-length\"]),\n },\n );\n\n return {\n url,\n partNumber,\n uploadId,\n bucket,\n expiresIn,\n partSize,\n };\n}\n\nexport const multipartPart = createS3Endpoint(\n S3_API_ROUTES.multipartPart,\n { method: \"POST\", body: multipartSignPartBodySchema },\n async (ctx) => {\n return handleSignPart(ctx.context.config, ctx.body, ctx.context.request);\n },\n);\n","import { createPresignedPost } from \"@aws-sdk/s3-presigned-post\";\nimport { getSignedUrl } from \"@aws-sdk/s3-request-presigner\";\nimport { PutObjectCommand } from \"@aws-sdk/client-s3\";\nimport {\n buildContentDisposition,\n S3_API_ROUTES,\n S3_MAX_POST_OBJECT_BYTES,\n uploadBodySchema,\n type UploadPresignResponse,\n} from \"@dimah-s3/core\";\nimport { errors } from \"@/errors\";\nimport {\n normalizeExpiresIn,\n openUploadTarget,\n runHook,\n runLifecycleHook,\n} from \"@/helpers\";\nimport type { ResolvedDimahS3Config } from \"@/types\";\nimport { createS3Endpoint } from \"@/api/create-s3-endpoint\";\n\nfunction objectUserMetadata(\n metadata: Record<string, string> | undefined,\n): Record<string, string> {\n if (!metadata) return {};\n const fields: Record<string, string> = {};\n for (const [k, v] of Object.entries(metadata)) {\n fields[`x-amz-meta-${k}`] = v;\n }\n return fields;\n}\n\nasync function handleUpload(\n config: ResolvedDimahS3Config,\n input: typeof uploadBodySchema._output,\n request: Request,\n): Promise<UploadPresignResponse> {\n const fileSize = Math.floor(input.fileSize);\n const fileName = input.fileName;\n const { route, key, bucket, metadata, acl, stored } = await openUploadTarget(\n config,\n {\n route: input.route,\n fileName,\n fileSize,\n contentType: input.contentType,\n metadata: input.metadata,\n },\n request,\n \"upload\",\n );\n const method = route.upload.method ?? \"POST\";\n if (route.upload.checksum && !input.checksum) {\n throw errors.validationError(\"Checksum is required for this route\");\n }\n if (method === \"POST\" && fileSize > S3_MAX_POST_OBJECT_BYTES) {\n throw errors.payloadTooLarge(\n `POST uploads cannot exceed ${S3_MAX_POST_OBJECT_BYTES} bytes. Enable upload.multipart or set upload.method to \"PUT\".`,\n );\n }\n\n const expiresIn = normalizeExpiresIn(\n route.upload.expiresIn,\n config.maxExpiresIn,\n );\n const contentType = input.contentType ?? \"application/octet-stream\";\n const hookCtx = {\n ...stored,\n file: {\n name: fileName,\n size: fileSize,\n type: input.contentType,\n },\n metadata,\n clientMetadata: input.metadata,\n acl,\n replace: route.upload.replace,\n };\n\n await runHook(route.upload.guard, hookCtx);\n\n if (method === \"PUT\") {\n const putHeaders: Record<string, string> = {\n \"Content-Type\": contentType,\n ...objectUserMetadata(metadata),\n \"Content-Disposition\": buildContentDisposition(fileName),\n ...(input.checksum ? { \"x-amz-checksum-sha256\": input.checksum } : {}),\n };\n\n const url = await getSignedUrl(\n route.client,\n new PutObjectCommand({\n Bucket: bucket,\n Key: key,\n ContentType: contentType,\n ACL: acl,\n Metadata: metadata,\n ContentDisposition: buildContentDisposition(fileName),\n ContentLength: fileSize,\n ...(input.checksum\n ? { ChecksumSHA256: input.checksum, ChecksumAlgorithm: \"SHA256\" }\n : {}),\n }),\n {\n expiresIn,\n signableHeaders: new Set([\n \"content-length\",\n ...(input.checksum ? [\"x-amz-checksum-sha256\"] : []),\n ]),\n },\n );\n\n await runLifecycleHook(\n route.upload.onPresigned,\n {\n ...hookCtx,\n url,\n expiresIn,\n },\n config,\n );\n\n return {\n bucket,\n key,\n url,\n headers: putHeaders,\n expiresIn,\n method: \"PUT\",\n };\n }\n\n const fields: Record<string, string> = {\n acl,\n \"Content-Type\": contentType,\n \"Content-Disposition\": buildContentDisposition(fileName),\n ...objectUserMetadata(metadata),\n ...(input.checksum ? { \"x-amz-checksum-sha256\": input.checksum } : {}),\n };\n\n const { url, fields: signedFields } = await createPresignedPost(\n route.client,\n {\n Bucket: bucket,\n Key: key,\n Conditions: [[\"content-length-range\", fileSize, fileSize]],\n Fields: fields,\n Expires: expiresIn,\n },\n );\n\n await runLifecycleHook(\n route.upload.onPresigned,\n {\n ...hookCtx,\n url,\n expiresIn,\n },\n config,\n );\n\n return {\n bucket,\n key,\n url,\n fields: signedFields,\n expiresIn,\n method: \"POST\",\n };\n}\n\nexport const upload = createS3Endpoint(\n S3_API_ROUTES.upload,\n { method: \"POST\", body: uploadBodySchema },\n async (ctx) => {\n return handleUpload(ctx.context.config, ctx.body, ctx.context.request);\n },\n);\n","import { confirm } from \"./confirm\";\nimport { deleteObject } from \"./delete\";\nimport { deleteBatch } from \"./delete-batch\";\nimport { download } from \"./download\";\nimport { catalog } from \"./catalog\";\nimport { file } from \"./file\";\nimport { multipartAbort } from \"./multipart/abort\";\nimport { multipartComplete } from \"./multipart/complete\";\nimport { multipartInit } from \"./multipart/init\";\nimport { multipartListParts } from \"./multipart/list-parts\";\nimport { multipartPart } from \"./multipart/part\";\nimport { upload } from \"./upload\";\n\n/** Core better-call endpoints — keys become `s3.api.*`. */\nexport const coreEndpoints = {\n upload,\n confirm,\n download,\n catalog,\n file,\n delete: deleteObject,\n deleteBatch,\n multipartInit,\n multipartPart,\n multipartListParts,\n multipartComplete,\n multipartAbort,\n};\n\nexport type CoreEndpoints = typeof coreEndpoints;\n\nexport const CORE_ENDPOINT_NAMES = Object.keys(\n coreEndpoints,\n) as (keyof CoreEndpoints)[];\n","type Hook<Context> = (context: Context) => Promise<void> | void;\n\n/**\n * Compose hooks into one that awaits each in order.\n *\n * Used by {@link dimahS3} when merging plugin + user hooks, and by consumers\n * to stack extras (quota, audit) beside plugin hooks:\n *\n * ```ts\n * upload: {\n * guard: chainHooks(myQuotaGuard, myAuditGuard),\n * }\n * ```\n *\n * `undefined` entries are skipped, so optional hooks compose cleanly.\n */\nexport function chainHooks<Context>(\n ...hooks: (Hook<Context> | undefined)[]\n): (context: Context) => Promise<void> {\n return async (context) => {\n for (const hook of hooks) {\n if (hook) await hook(context);\n }\n };\n}\n","import type {\n DeleteConfig,\n DownloadConfig,\n MultipartConfig,\n RouteFeature,\n UploadConfig,\n} from \"@/types/config\";\n\n/**\n * Hook keys a plugin may contribute per route feature.\n * {@link applyPlugins} merges these ahead of user config hooks.\n */\nexport const FEATURE_HOOK_KEYS = {\n upload: [\"guard\", \"onPresigned\", \"confirmGuard\", \"onConfirmed\"],\n download: [\"guard\", \"onPresigned\"],\n delete: [\"guard\", \"onDeleted\"],\n} as const satisfies {\n [K in RouteFeature]: readonly (keyof (K extends \"upload\"\n ? UploadConfig\n : K extends \"download\"\n ? DownloadConfig\n : DeleteConfig))[];\n};\n\n/** Nested under `upload.multipart` — init/complete share upload hooks. */\nexport const MULTIPART_HOOK_KEYS = [\n \"onInit\",\n \"guard\",\n \"onAbort\",\n \"onList\",\n] as const satisfies readonly (keyof MultipartConfig)[];\n\n/** Lifecycle `on*` keys — merged user-first, plugins last (persist last). */\nexport const LIFECYCLE_FEATURE_HOOK_KEYS = {\n upload: [\"onPresigned\", \"onConfirmed\"],\n download: [\"onPresigned\"],\n delete: [\"onDeleted\"],\n} as const;\n\nexport const LIFECYCLE_MULTIPART_HOOK_KEYS = [\n \"onInit\",\n \"onAbort\",\n \"onList\",\n] as const;\n\nexport type FeatureHookKeyMap = typeof FEATURE_HOOK_KEYS;\nexport type MultipartHookKey = (typeof MULTIPART_HOOK_KEYS)[number];\n","import type { Endpoint } from \"better-call\";\nimport type {\n DeleteConfig,\n DownloadConfig,\n MultipartConfig,\n UploadConfig,\n DimahS3Config,\n ResolvedDimahS3Config,\n} from \"@/types/config\";\nimport type { FeatureHookKeyMap, MultipartHookKey } from \"./hook-registry\";\n\ntype HookFields<T, K extends keyof T> = Pick<T, K>;\n\n/**\n * Hook fields a plugin may contribute. Scalars like `method` /\n * `object` / `acl` stay user-owned on the route `upload` feature.\n * Keys come from {@link FEATURE_HOOK_KEYS} / {@link MULTIPART_HOOK_KEYS}.\n */\nexport type DimahS3PluginHooks = {\n guard?: DimahS3Config[\"guard\"];\n upload?: HookFields<UploadConfig, FeatureHookKeyMap[\"upload\"][number]> & {\n multipart?: HookFields<MultipartConfig, MultipartHookKey>;\n };\n download?: HookFields<DownloadConfig, FeatureHookKeyMap[\"download\"][number]>;\n delete?: HookFields<DeleteConfig, FeatureHookKeyMap[\"delete\"][number]>;\n};\n\n/**\n * Environment passed to {@link DimahS3Plugin.init}.\n * Config is pre-merge (user config only) — use `isFeatureOn` for\n * feature-flag checks. Routes are already validated before `init` runs.\n */\nexport type PluginInitEnv = {\n /** User config before plugin hooks are merged — read-only. */\n config: Readonly<DimahS3Config>;\n /** Lookup another registered plugin by id. */\n getPlugin: (id: string) => DimahS3Plugin | undefined;\n};\n\n/**\n * Server plugin contract. Feature packages (e.g. `@dimah-s3/db`) return\n * these from factories like `db()` / `definePlugin()`.\n *\n * @typeParam Id — unique plugin id; becomes the key on `s3.context` and the\n * flattened instance (`s3[id]`).\n * @typeParam TContext — exposed on `s3.context[id]` and `s3[id]` after\n * `dimahS3()`.\n * @typeParam TEndpoints — better-call endpoints merged onto `s3.api`.\n */\nexport type DimahS3Plugin<\n Id extends string = string,\n TContext extends Record<string, unknown> = Record<string, unknown>,\n TEndpoints extends Record<string, Endpoint> = Record<string, Endpoint>,\n> = {\n /** Unique id — duplicate ids throw at init. */\n id: Id;\n /**\n * Other plugin ids that must be registered. Validated when `dimahS3()`\n * runs — missing deps throw with a clear message.\n * Merge order remains plugins-array order (not topological).\n */\n dependsOn?: readonly string[];\n /**\n * Runs once after the context map is built and before hooks are merged.\n * Synchronous so `dimahS3()` stays a sync factory — validate options /\n * required feature flags here.\n */\n init?: (env: PluginInitEnv) => void;\n /** Lifecycle / guard hooks merged ahead of user config hooks. */\n hooks?: DimahS3PluginHooks;\n /**\n * Extra HTTP routes on the shared handler. Use {@link createS3Endpoint}.\n * Paths are absolute under `basePath` (e.g. `/db/objects`).\n */\n endpoints?: TEndpoints;\n /** Opaque context keyed by `id` on the dimahS3 instance. */\n context?: TContext;\n};\n\nexport type AppliedPlugins<\n C extends Record<string, unknown> = Record<string, unknown>,\n E extends Record<string, Endpoint> = Record<string, Endpoint>,\n> = {\n /** Config with plugin hooks chained ahead of user hooks. */\n config: ResolvedDimahS3Config;\n /** Plugin contexts keyed by plugin id. */\n context: C;\n getPlugin: (id: string) => DimahS3Plugin | undefined;\n /** Plugin HTTP endpoints merged onto `s3.api` and the router. */\n endpoints: E;\n};\n\n/** Map plugin ids → their `context` types. */\nexport type PluginContextMap<P extends readonly DimahS3Plugin[]> = {\n [K in P[number] as K[\"id\"]]: K extends DimahS3Plugin<string, infer Ctx>\n ? Ctx\n : never;\n};\n\n/** Map plugin endpoint names → better-call endpoints. */\nexport type PluginEndpointMap<P extends readonly DimahS3Plugin[]> =\n P extends readonly []\n ? Record<string, never>\n : UnionToIntersection<\n P[number] extends { endpoints?: infer E }\n ? E extends Record<string, Endpoint>\n ? E\n : Record<string, never>\n : Record<string, never>\n >;\n\ntype UnionToIntersection<U> = (\n U extends unknown ? (k: U) => void : never\n) extends (k: infer I) => void\n ? I\n : Record<string, never>;\n\n/** Keys reserved on the dimahS3 instance — plugins may not use these as ids. */\nexport const RESERVED_PLUGIN_IDS = [\n \"handler\",\n \"api\",\n \"context\",\n \"getPlugin\",\n \"$ERROR_CODES\",\n \"$Infer\",\n \"upload\",\n \"confirm\",\n \"download\",\n \"catalog\",\n \"file\",\n \"delete\",\n \"deleteBatch\",\n \"put\",\n \"multipart\",\n] as const;\n\nexport type ReservedPluginId = (typeof RESERVED_PLUGIN_IDS)[number];\n","import { S3_API_ROUTES } from \"@dimah-s3/core\";\nimport type { Endpoint } from \"better-call\";\nimport { CORE_ENDPOINT_NAMES } from \"@/api/routes\";\nimport { isEnabled, normalizeRoutes } from \"@/helpers/features\";\nimport type {\n DimahS3Config,\n ResolvedDimahS3Config,\n ResolvedRoute,\n} from \"@/types\";\nimport { chainHooks } from \"./chain-hooks\";\nimport {\n FEATURE_HOOK_KEYS,\n MULTIPART_HOOK_KEYS,\n LIFECYCLE_FEATURE_HOOK_KEYS,\n LIFECYCLE_MULTIPART_HOOK_KEYS,\n} from \"./hook-registry\";\nimport {\n RESERVED_PLUGIN_IDS,\n type AppliedPlugins,\n type DimahS3Plugin,\n type PluginContextMap,\n} from \"./types\";\n\ntype HookFn = ((context: never) => Promise<void> | void) | undefined;\ntype HookBag = Record<string, HookFn>;\n\nfunction mergeHookField(\n pluginHooks: HookFn[],\n userHook: HookFn,\n order: \"plugins-first\" | \"user-first\" = \"plugins-first\",\n): HookFn | undefined {\n const present = (\n order === \"user-first\"\n ? [userHook, ...pluginHooks]\n : [...pluginHooks, userHook]\n ).filter((h): h is NonNullable<HookFn> => h != null);\n if (present.length === 0) return undefined;\n if (present.length === 1) return present[0];\n return chainHooks(...present) as HookFn;\n}\n\nfunction mergeHooks<T extends object>(\n keys: readonly string[],\n plugins: readonly DimahS3Plugin[],\n userFeature: T,\n pick: (plugin: DimahS3Plugin) => HookBag | undefined,\n lifecycleKeys: ReadonlySet<string> = new Set(),\n): T {\n const merged: HookBag = { ...(userFeature as HookBag) };\n for (const key of keys) {\n const next = mergeHookField(\n plugins.map((plugin) => pick(plugin)?.[key]),\n (userFeature as HookBag)[key],\n lifecycleKeys.has(key) ? \"user-first\" : \"plugins-first\",\n );\n if (next !== undefined) merged[key] = next;\n }\n return merged as T;\n}\n\nfunction applyHooksToRoute(\n route: ResolvedRoute,\n plugins: readonly DimahS3Plugin[],\n): ResolvedRoute {\n const active = plugins.filter((p) => !route.skippedPluginIds.has(p.id));\n\n const upload = isEnabled(route.upload)\n ? {\n ...mergeHooks(\n FEATURE_HOOK_KEYS.upload,\n active,\n route.upload,\n (p) => p.hooks?.upload as HookBag | undefined,\n new Set(LIFECYCLE_FEATURE_HOOK_KEYS.upload),\n ),\n multipart: isEnabled(route.upload.multipart)\n ? mergeHooks(\n MULTIPART_HOOK_KEYS,\n active,\n route.upload.multipart,\n (p) => p.hooks?.upload?.multipart as HookBag | undefined,\n new Set(LIFECYCLE_MULTIPART_HOOK_KEYS),\n )\n : route.upload.multipart,\n }\n : route.upload;\n\n return {\n ...route,\n upload,\n download: isEnabled(route.download)\n ? mergeHooks(\n FEATURE_HOOK_KEYS.download,\n active,\n route.download,\n (p) => p.hooks?.download as HookBag | undefined,\n new Set(LIFECYCLE_FEATURE_HOOK_KEYS.download),\n )\n : route.download,\n delete: isEnabled(route.delete)\n ? mergeHooks(\n FEATURE_HOOK_KEYS.delete,\n active,\n route.delete,\n (p) => p.hooks?.delete as HookBag | undefined,\n new Set(LIFECYCLE_FEATURE_HOOK_KEYS.delete),\n )\n : route.delete,\n };\n}\n\n/**\n * Validate plugins, build context map, collect endpoints, validate routes,\n * run `init`, and merge hooks into each route.\n *\n * Guard / `*Guard` hooks: plugins first (array order), then user.\n * Lifecycle `on*` hooks: user first, then plugins, so `db().markActive`\n * runs last and confirm rollback can still `DeleteObject`.\n *\n * Hooks are not merged onto a feature that is off for that route.\n */\nexport function applyPlugins<\n const P extends readonly DimahS3Plugin[],\n C extends Record<string, unknown> = PluginContextMap<P>,\n>(config: DimahS3Config & { plugins?: P }): AppliedPlugins<C> {\n const plugins = config.plugins ?? [];\n const seen = new Set<string>();\n const byId = new Map<string, DimahS3Plugin>();\n const context = {} as C;\n const getPlugin = (id: string) => byId.get(id);\n\n for (const plugin of plugins) {\n if ((RESERVED_PLUGIN_IDS as readonly string[]).includes(plugin.id)) {\n throw new Error(\n `Plugin id \"${plugin.id}\" is reserved on the dimahS3 instance. Choose a different id.`,\n );\n }\n if (seen.has(plugin.id)) {\n throw new Error(\n `Duplicate dimah-s3 plugin id \"${plugin.id}\". Each plugin id must be unique.`,\n );\n }\n seen.add(plugin.id);\n byId.set(plugin.id, plugin);\n }\n\n for (const plugin of plugins) {\n for (const dep of plugin.dependsOn ?? []) {\n if (!seen.has(dep)) {\n throw new Error(\n `Plugin \"${plugin.id}\" depends on \"${dep}\", which is not registered.`,\n );\n }\n }\n }\n\n const visiting = new Set<string>();\n const visited = new Set<string>();\n function visit(id: string, stack: string[]) {\n if (visited.has(id)) return;\n if (visiting.has(id)) {\n throw new Error(\n `Circular plugin dependency detected: ${[...stack, id].join(\" -> \")}.`,\n );\n }\n visiting.add(id);\n const plugin = byId.get(id);\n for (const dep of plugin?.dependsOn ?? []) {\n visit(dep, [...stack, id]);\n }\n visiting.delete(id);\n visited.add(id);\n }\n for (const plugin of plugins) {\n visit(plugin.id, []);\n }\n\n for (const plugin of plugins) {\n if (plugin.context !== undefined) {\n (context as Record<string, unknown>)[plugin.id] = plugin.context;\n }\n }\n\n const reservedRoutePaths = new Set<string>(Object.values(S3_API_ROUTES));\n const reservedNames = new Set<string>([...CORE_ENDPOINT_NAMES, \"multipart\"]);\n const seenEndpointKeys = new Set<string>();\n const endpoints: Record<string, Endpoint> = {};\n\n for (const plugin of plugins) {\n for (const [name, endpoint] of Object.entries(plugin.endpoints ?? {})) {\n if (reservedNames.has(name) || name in endpoints) {\n throw new Error(\n `Plugin \"${plugin.id}\" endpoint \"${name}\" collides with an existing endpoint.`,\n );\n }\n const path = endpoint.path;\n if (typeof path !== \"string\" || !path.startsWith(\"/\")) {\n throw new Error(\n `Plugin \"${plugin.id}\" endpoint \"${name}\" path must start with \"/\".`,\n );\n }\n if (reservedRoutePaths.has(path)) {\n throw new Error(\n `Plugin \"${plugin.id}\" endpoint \"${name}\" collides with a core route.`,\n );\n }\n const methods = Array.isArray(endpoint.options.method)\n ? endpoint.options.method\n : [endpoint.options.method];\n for (const method of methods) {\n const routeKey = `${method} ${path}`;\n if (seenEndpointKeys.has(routeKey)) {\n throw new Error(`Duplicate plugin endpoint ${routeKey}.`);\n }\n seenEndpointKeys.add(routeKey);\n }\n endpoints[name] = endpoint;\n }\n }\n\n const { plugins: _omit, ...rest } = config;\n const normalized = normalizeRoutes(rest);\n\n for (const plugin of plugins) {\n plugin.init?.({ config: rest, getPlugin });\n }\n const routes: Record<string, ResolvedRoute> = {};\n for (const [name, route] of Object.entries(normalized)) {\n routes[name] = applyHooksToRoute(route, plugins);\n }\n\n const guard = mergeHookField(\n plugins.map((p) => p.hooks?.guard as HookFn),\n rest.guard as HookFn,\n ) as ResolvedDimahS3Config[\"guard\"];\n\n const merged: ResolvedDimahS3Config = {\n ...rest,\n routes,\n ...(guard !== undefined ? { guard } : {}),\n };\n\n return {\n config: merged,\n context,\n getPlugin,\n endpoints,\n };\n}\n","import type { Endpoint } from \"better-call\";\nimport type { DimahS3Plugin } from \"./types\";\n\n/**\n * Identity helper that preserves literal `id`, context, and endpoint types\n * for {@link dimahS3} inference (`s3.context[id]` / `s3.api`).\n */\nexport function definePlugin<\n Id extends string,\n TContext extends Record<string, unknown> = Record<string, unknown>,\n TEndpoints extends Record<string, Endpoint> = Record<string, Endpoint>,\n>(\n plugin: DimahS3Plugin<Id, TContext, TEndpoints>,\n): DimahS3Plugin<Id, TContext, TEndpoints> {\n return plugin;\n}\n","import { type Endpoint } from \"better-call\";\nimport type { S3EndpointContext } from \"./context\";\nimport { requestFromHeaders } from \"@/helpers\";\n\n/**\n * Wrap better-call endpoints so `s3.api.upload({ body, headers })` injects\n * `routerContext` the same way HTTP `createRouter` does.\n */\nexport function bindEndpoints<E extends Record<string, Endpoint>>(\n endpoints: E,\n context: Pick<S3EndpointContext, \"config\">,\n): E {\n const api = {} as E;\n\n for (const [key, endpoint] of Object.entries(endpoints)) {\n const bound = (async (input: Record<string, unknown> = {}) => {\n const headers = input.headers as HeadersInit | undefined;\n const request =\n (input.request as Request | undefined) ?? requestFromHeaders(headers);\n return endpoint({\n ...input,\n headers: headers ?? request.headers,\n request,\n context,\n });\n }) as typeof endpoint;\n\n bound.path = endpoint.path;\n bound.options = endpoint.options;\n api[key as keyof E] = bound as E[keyof E];\n }\n\n return api;\n}\n","import { createRouter, toResponse, type Endpoint } from \"better-call\";\nimport {\n isAPIError,\n normalizeS3ApiBasePath,\n S3_API_BASE_PATH,\n} from \"@dimah-s3/core\";\nimport { errors } from \"@/errors\";\nimport { resolveLogger } from \"@/helpers/logger\";\nimport { bindEndpoints } from \"./bind-endpoints\";\nimport type { ResolvedDimahS3Config } from \"@/types\";\n\nconst NETWORK_CODES = new Set([\n \"EAI_AGAIN\",\n \"ECONNREFUSED\",\n \"ECONNRESET\",\n \"ETIMEDOUT\",\n \"ENOTFOUND\",\n]);\n\n/**\n * better-call `onError`: APIError (including DimahS3Error) serializes\n * natively. Unknown throws become INTERNAL_ERROR / S3_NETWORK_ERROR.\n */\nfunction onS3RouterError(error: unknown, config?: ResolvedDimahS3Config): void {\n if (isAPIError(error)) return;\n\n const code = (error as { code?: string })?.code;\n const logger = resolveLogger(config?.logger);\n if (typeof code === \"string\" && NETWORK_CODES.has(code)) {\n const networkErr = errors.s3NetworkError(code);\n logger.error?.(networkErr.message, error);\n config?.onError?.(error, {});\n throw networkErr;\n }\n\n logger.error?.(error instanceof Error ? error.message : String(error), error);\n config?.onError?.(error, {});\n throw errors.internalError();\n}\n\n/**\n * Unmatched routes never hit `onError` — better-call returns an empty 404.\n * Re-serialize those as DimahS3Error JSON. JSON 404s from endpoints pass through.\n */\nfunction withUnmatchedRouteJson(\n handler: (request: Request) => Promise<Response>,\n): (request: Request) => Promise<Response> {\n return async (request) => {\n const response = await handler(request);\n if (response.status !== 404) return response;\n const contentType = response.headers.get(\"content-type\") ?? \"\";\n if (contentType.includes(\"application/json\")) return response;\n return toResponse(errors.notFound());\n };\n}\n\n/**\n * Internal better-call router with dimah-s3 context, OpenAPI off, and native\n * APIError JSON. Not part of the public package surface.\n */\nexport function createS3Router<E extends Record<string, Endpoint>>(\n endpoints: E,\n env: { config: ResolvedDimahS3Config },\n) {\n const basePath = normalizeS3ApiBasePath(\n env.config.basePath ?? S3_API_BASE_PATH,\n );\n\n const router = createRouter(endpoints, {\n basePath,\n routerContext: { config: env.config },\n openapi: { disabled: true },\n onError: (error) => onS3RouterError(error, env.config),\n });\n\n return {\n endpoints: bindEndpoints(router.endpoints, { config: env.config }),\n handler: withUnmatchedRouteJson(router.handler),\n };\n}\n","import { S3_ERROR_CODES } from \"@dimah-s3/core\";\nimport { putObject, type PutObjectInput } from \"./put\";\nimport {\n applyPlugins,\n type DimahS3Plugin,\n type PluginContextMap,\n type PluginEndpointMap,\n} from \"./plugin\";\nimport { coreEndpoints, type CoreEndpoints } from \"./api/routes\";\nimport { createS3Router } from \"./api/router\";\nimport type { DimahS3Config, DimahS3RouteConfig } from \"./types\";\n\nexport type MultipartAliasApi = {\n init: CoreEndpoints[\"multipartInit\"];\n signPart: CoreEndpoints[\"multipartPart\"];\n listParts: CoreEndpoints[\"multipartListParts\"];\n complete: CoreEndpoints[\"multipartComplete\"];\n abort: CoreEndpoints[\"multipartAbort\"];\n};\n\nexport type DimahS3Api<P extends readonly DimahS3Plugin[] = []> =\n CoreEndpoints & {\n multipart: MultipartAliasApi;\n deleteMany: CoreEndpoints[\"deleteBatch\"];\n } & PluginEndpointMap<P>;\n\nexport type DimahS3<\n P extends readonly DimahS3Plugin[] = [],\n C extends Record<string, unknown> = PluginContextMap<P>,\n R extends Record<string, DimahS3RouteConfig> = Record<\n string,\n DimahS3RouteConfig\n >,\n> = {\n /** Framework-agnostic HTTP handler (`Request` → `Response`). */\n handler: (request: Request) => Promise<Response>;\n /**\n * better-call endpoints — invoke as functions from Server Actions / RSC.\n *\n * ```ts\n * await s3.api.download({ query: { route, key }, headers: await headers() });\n * await s3.api.multipart.init({ body: { route, fileName, fileSize } });\n * ```\n */\n api: DimahS3Api<P>;\n /** Plugin contexts keyed by plugin id. */\n context: C;\n /** Lookup a registered plugin by id. */\n getPlugin: {\n <Id extends P[number][\"id\"]>(\n id: Id,\n ): Extract<P[number], { id: Id }> | undefined;\n (id: string): DimahS3Plugin | undefined;\n };\n $ERROR_CODES: typeof S3_ERROR_CODES;\n $Infer: {\n api: DimahS3Api<P>;\n context: C;\n routes: keyof R & string;\n };\n /**\n * Server-side upload through the same route policy as presign + confirm.\n */\n put: (\n input: PutObjectInput,\n ) => Promise<import(\"@dimah-s3/core\").ConfirmedObjectResponse>;\n} & C;\n\n/**\n * Create a dimah-s3 server instance.\n *\n * Plugin contexts are available on `s3.context[id]` and flattened onto the\n * instance itself (`s3.db` when the `db` plugin is registered, etc.).\n *\n * @example\n * ```ts\n * export const awsS3 = new S3Client({ ... });\n * export const s3 = dimahS3({\n * client: awsS3,\n * bucket: \"my-bucket\",\n * routes: {\n * uploads: route({ upload: { fileTypes: [\"image/*\"] } }),\n * invoices: route({ download: true }),\n * },\n * });\n *\n * export const { GET, POST, PUT, PATCH, DELETE } = toNextJsHandler(s3);\n *\n * await s3.api.download({ query: { route: \"invoices\", key }, headers: await headers() });\n * ```\n */\nexport function dimahS3<\n const P extends readonly DimahS3Plugin[] = [],\n const R extends Record<string, DimahS3RouteConfig> = Record<\n string,\n DimahS3RouteConfig\n >,\n>(\n config: DimahS3Config & { plugins?: P; routes: R },\n): DimahS3<P, PluginContextMap<P>, R> {\n const {\n config: resolved,\n context,\n getPlugin,\n endpoints: pluginEndpoints,\n } = applyPlugins(config);\n\n const endpoints = { ...coreEndpoints, ...pluginEndpoints };\n const router = createS3Router(endpoints, { config: resolved });\n const bound = router.endpoints as CoreEndpoints & PluginEndpointMap<P>;\n\n const api = {\n ...bound,\n deleteMany: bound.deleteBatch,\n multipart: {\n init: bound.multipartInit,\n signPart: bound.multipartPart,\n listParts: bound.multipartListParts,\n complete: bound.multipartComplete,\n abort: bound.multipartAbort,\n },\n } as DimahS3<P, PluginContextMap<P>, R>[\"api\"];\n\n return {\n handler: router.handler,\n api,\n context,\n getPlugin,\n $ERROR_CODES: S3_ERROR_CODES,\n $Infer: {} as DimahS3<P, PluginContextMap<P>, R>[\"$Infer\"],\n put: (input) => putObject(resolved, input),\n ...context,\n } as DimahS3<P, PluginContextMap<P>, R>;\n}\n","import type { S3Client } from \"@aws-sdk/client-s3\";\nimport type { S3ObjectAcl, UploadPresignMethod } from \"@dimah-s3/core\";\nimport type {\n DeleteGuardContext,\n DeleteOnDeletedContext,\n DownloadGuardContext,\n DownloadOnPresignedContext,\n DownloadResolveInfo,\n GuardContext,\n MultipartGuardContext,\n MultipartOnAbortContext,\n MultipartOnInitContext,\n MultipartOnListContext,\n RouteGuardContext,\n UploadConfirmGuardContext,\n UploadGuardContext,\n UploadObjectContext,\n UploadObjectInfo,\n UploadOnConfirmedContext,\n UploadOnPresignedContext,\n} from \"./hook-contexts\";\nimport type { DimahS3Plugin } from \"@/plugin/types\";\n\nexport type { UploadObjectContext, UploadObjectInfo, DownloadResolveInfo };\n\n/** The three nested features on a named route. */\nexport const ROUTE_FEATURES = [\"upload\", \"download\", \"delete\"] as const;\nexport type RouteFeature = (typeof ROUTE_FEATURES)[number];\n\n/**\n * Endpoint operations. Multipart is nested under upload — it is not a\n * fourth route feature.\n */\nexport const ROUTE_OPERATIONS = [...ROUTE_FEATURES, \"multipart\"] as const;\nexport type RouteOperation = (typeof ROUTE_OPERATIONS)[number];\n\n/** `true` or an options object enables the feature; omit or `false` disables it. */\nexport type FeatureToggle<T> = boolean | T;\n\n/** Optional structured logger on {@link DimahS3Config}. */\nexport type DimahS3Logger = {\n debug?: (message: string, ...args: unknown[]) => void;\n info?: (message: string, ...args: unknown[]) => void;\n warn?: (message: string, ...args: unknown[]) => void;\n error?: (message: string, ...args: unknown[]) => void;\n};\n\nexport type DisabledFeature = { enabled: false };\nexport type EnabledFeature<T extends object> = T & { enabled: true };\nexport type ResolvedFeature<T extends object> =\n EnabledFeature<T> | DisabledFeature;\n\n/**\n * Multipart-only hooks. Init shares `upload.guard` / `onInit`. Complete\n * runs `guard` (`action: \"complete\"`) then `upload.confirmGuard` /\n * `upload.onConfirmed`.\n */\nexport type MultipartConfig = {\n /** After `CreateMultipartUpload` — persist `uploadId` for resume. */\n onInit?: (context: MultipartOnInitContext) => Promise<void> | void;\n /** Authorize part, list, abort, and complete. Branch on `action` if needed. */\n guard?: (context: MultipartGuardContext) => Promise<void> | void;\n onAbort?: (context: MultipartOnAbortContext) => Promise<void> | void;\n onList?: (context: MultipartOnListContext) => Promise<void> | void;\n};\n\n/** Upload feature: constraints, object identity, and lifecycle hooks. */\nexport type UploadConfig = {\n /** HTML `accept` tokens (`image/*`, `.pdf`, `application/pdf`). */\n fileTypes?: string[];\n /**\n * Max declared size, signed part size, listed multipart total, and\n * HeadObject size in bytes.\n */\n maxFileSize?: number;\n /**\n * Server-owned object identity. Return `folder` for a directory under\n * the route `keyPrefix`, `key` for the rest of the key (also nested\n * under `keyPrefix`), plus optional S3 `metadata` and `acl`.\n * Runs on upload / multipart init only. Default key is\n * `{keyPrefix}/{uuid}/{name}` (`keyPrefix` defaults to the route name).\n * `keyPrefix: false` generates `{uuid}/{name}` and skips the follow-up\n * namespace check.\n */\n object?: (\n context: UploadObjectContext,\n ) => UploadObjectInfo | void | Promise<UploadObjectInfo | void>;\n /**\n * Server-forced ACL when `object` does not return one.\n * @default \"private\"\n */\n acl?: S3ObjectAcl;\n /** Presign verb. Use `\"PUT\"` on R2 (no Presigned POST). @default \"POST\" */\n method?: UploadPresignMethod;\n /** Presign TTL in seconds. Clamped by instance `maxExpiresIn`. */\n expiresIn?: number;\n /**\n * Require a SHA-256 `checksum` on the presign body and lock it into the\n * signed PUT/POST.\n */\n checksum?: boolean;\n /**\n * Overwrite an existing object at the resolved key without flipping a\n * `db()` row from `active` to `pending` during the new upload.\n */\n replace?: \"overwrite\";\n /** Presign and multipart init. */\n guard?: (context: UploadGuardContext) => Promise<void> | void;\n /** After a single-shot URL is signed. Multipart uses `multipart.onInit`. */\n onPresigned?: (context: UploadOnPresignedContext) => Promise<void> | void;\n /** Confirm and multipart complete. */\n confirmGuard?: (context: UploadConfirmGuardContext) => Promise<void> | void;\n /** After HeadObject on confirm and multipart complete. */\n onConfirmed?: (context: UploadOnConfirmedContext) => Promise<void> | void;\n /** Opt-in multipart. Default off. */\n multipart?: FeatureToggle<MultipartConfig>;\n};\n\n/** Download feature. A config object (or `true`) enables the feature. */\nexport type DownloadConfig = {\n /**\n * Presign TTL in seconds. Defaults to `S3_DEFAULT_EXPIRES_IN` (600).\n * Independent of {@link UploadConfig.expiresIn}.\n */\n expiresIn?: number;\n /**\n * Default Content-Disposition. @default \"attachment\"\n */\n disposition?: \"inline\" | \"attachment\";\n /**\n * `\"presign\"` (default) returns an S3 URL. `\"proxy\"` returns a\n * same-origin `/file` URL that streams through the server.\n */\n mode?: \"presign\" | \"proxy\";\n /**\n * Per-request download options. Return values override route defaults.\n * The client `disposition` / `fileName` query is a fallback.\n */\n resolve?: (\n context: DownloadGuardContext,\n ) => DownloadResolveInfo | void | Promise<DownloadResolveInfo | void>;\n guard?: (context: DownloadGuardContext) => Promise<void> | void;\n onPresigned?: (context: DownloadOnPresignedContext) => Promise<void> | void;\n};\n\n/** Delete feature. A config object (or `true`) enables the feature. */\nexport type DeleteConfig = {\n guard?: (context: DeleteGuardContext) => Promise<void> | void;\n onDeleted?: (context: DeleteOnDeletedContext) => Promise<void> | void;\n};\n\n/**\n * Named file route — a mini {@link DimahS3Config} under `routes`.\n * Upload, download, delete, and `upload.multipart` are off until set.\n * Prefer one feature per route; combine only when those callers share\n * the key namespace.\n */\nexport type DimahS3RouteConfig = {\n /** Override the instance S3 client for this route. */\n client?: S3Client;\n /** Override the instance bucket for this route. */\n bucket?: string;\n /**\n * Object-key namespace. Generated keys and follow-up ops (confirm,\n * download, delete, multipart) must stay under it.\n * Defaults to the route name. `false` disables the bound.\n */\n keyPrefix?: string | false;\n /** Runs before every operation on this route. */\n guard?: (context: RouteGuardContext) => Promise<void> | void;\n /**\n * Opt out of instance plugins by id (`{ db: false }`).\n * Hooks from opted-out plugins are not merged onto this route.\n */\n plugins?: { readonly [pluginId: string]: false };\n upload?: FeatureToggle<UploadConfig>;\n download?: FeatureToggle<DownloadConfig>;\n delete?: FeatureToggle<DeleteConfig>;\n};\n\n/**\n * Options for {@link dimahS3}.\n *\n * @example\n * ```ts\n * export const s3 = dimahS3({\n * client: awsS3,\n * bucket: \"my-bucket\",\n * routes: {\n * uploads: route({\n * upload: { fileTypes: [\"image/*\"], multipart: true },\n * }),\n * },\n * });\n * ```\n */\nexport type DimahS3Config = {\n /**\n * Default AWS SDK v3 `S3Client`. Required unless every route sets\n * {@link DimahS3RouteConfig.client}.\n */\n client?: S3Client;\n /**\n * Default bucket. Required unless every route sets\n * {@link DimahS3RouteConfig.bucket}.\n */\n bucket?: string;\n /**\n * API path prefix for the HTTP `handler`.\n * Must match `createS3Client({ basePath })` on the client.\n * @default \"/api/s3\"\n */\n basePath?: string;\n /**\n * Upper bound for `upload.expiresIn` and `download.expiresIn` (seconds).\n * The protocol maximum is 7 days (604800).\n * @default 604800\n */\n maxExpiresIn?: number;\n /**\n * Structured logs for lifecycle failures and unmatched router errors.\n * `false` silences the default `console.error`.\n */\n logger?: DimahS3Logger | false;\n /** Called after an unexpected throw is mapped to `INTERNAL_ERROR`. */\n onError?: (error: unknown, context: { request?: Request }) => void;\n /** Runs before every operation, before route lookup. Throw to reject. */\n guard?: (context: GuardContext) => Promise<void> | void;\n /**\n * Optional server plugins (e.g. `db()` from `@dimah-s3/db`).\n * Plugin hooks merge onto each route unless the route opts out.\n */\n plugins?: readonly DimahS3Plugin[];\n /** Named file routes. At least one is required. */\n routes: Record<string, DimahS3RouteConfig>;\n};\n\ntype UploadFields = Omit<UploadConfig, \"multipart\">;\n\nexport type EnabledUploadConfig = EnabledFeature<UploadFields> & {\n multipart: ResolvedFeature<MultipartConfig>;\n};\n\nexport type ResolvedUploadConfig =\n EnabledUploadConfig | (DisabledFeature & { multipart: DisabledFeature });\n\n/** One named route after {@link dimahS3} normalizes toggles and plugin hooks. */\nexport type ResolvedRoute = {\n name: string;\n client: S3Client;\n bucket: string;\n /** `false` means follow-up keys are not namespace-checked. */\n keyPrefix: string | false;\n guard?: DimahS3RouteConfig[\"guard\"];\n skippedPluginIds: ReadonlySet<string>;\n upload: ResolvedUploadConfig;\n download: ResolvedFeature<DownloadConfig>;\n delete: ResolvedFeature<DeleteConfig>;\n};\n\n/**\n * A {@link ResolvedRoute} after the named operation has been asserted on.\n * `route.upload.fileTypes` is typed as present only after opening `\"upload\"`.\n */\nexport type OpenedRoute<F extends RouteOperation> = F extends \"multipart\"\n ? ResolvedRoute & {\n upload: EnabledUploadConfig & {\n multipart: EnabledFeature<MultipartConfig>;\n };\n }\n : F extends \"upload\"\n ? ResolvedRoute & { upload: EnabledUploadConfig }\n : F extends \"download\"\n ? ResolvedRoute & { download: EnabledFeature<DownloadConfig> }\n : F extends \"delete\"\n ? ResolvedRoute & { delete: EnabledFeature<DeleteConfig> }\n : never;\n\n/** Instance config after {@link dimahS3} normalizes routes and plugins. */\nexport type ResolvedDimahS3Config = Omit<\n DimahS3Config,\n \"routes\" | \"plugins\"\n> & {\n routes: Record<string, ResolvedRoute>;\n};\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/helpers/request.ts","../src/helpers/best-effort.ts","../src/errors.ts","../src/helpers/is-aws-not-found.ts","../src/helpers/expires.ts","../src/helpers/logger.ts","../src/helpers/hooks.ts","../src/helpers/previous-key.ts","../src/helpers/resolve-target.ts","../src/route.ts","../src/helpers/features.ts","../src/helpers/constraints.ts","../src/helpers/resolve-route.ts","../src/helpers/head-object.ts","../src/helpers/list-parts.ts","../src/helpers/finalize-confirmed.ts","../src/put.ts","../src/api/create-s3-middleware.ts","../src/api/create-s3-endpoint.ts","../src/api/routes/confirm.ts","../src/api/routes/delete.ts","../src/api/routes/delete-batch.ts","../src/api/routes/download.ts","../src/api/routes/catalog.ts","../src/api/routes/file.ts","../src/api/routes/multipart/abort.ts","../src/api/routes/multipart/complete.ts","../src/api/routes/multipart/init.ts","../src/api/routes/multipart/list-parts.ts","../src/api/routes/multipart/part.ts","../src/api/routes/upload.ts","../src/api/routes/index.ts","../src/plugin/chain-hooks.ts","../src/plugin/hook-registry.ts","../src/plugin/types.ts","../src/plugin/apply-plugins.ts","../src/plugin/define-plugin.ts","../src/api/bind-endpoints.ts","../src/api/router.ts","../src/dimah-s3.ts","../src/types/config.ts"],"names":["route","isAPIError","DimahS3Error","upload","download","DeleteObjectCommand","S3_API_ROUTES","isDimahS3Error","GetObjectCommand","buildContentDisposition","AbortMultipartUploadCommand","getSignedUrl","url","PutObjectCommand","S3_ERROR_CODES"],"mappings":";;;;;;;;;;;AACO,SAAS,mBAAmB,OAAA,EAAgC;AACjE,EAAA,OAAO,IAAI,OAAA,CAAQ,uBAAA,EAAyB,EAAE,SAAS,CAAA;AACzD;ACIA,eAAsB,sBAAA,CACpB,MAAA,EACA,MAAA,EACA,GAAA,EACe;AACf,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,CAAO,IAAA,CAAK,IAAI,mBAAA,CAAoB,EAAE,QAAQ,MAAA,EAAQ,GAAA,EAAK,GAAA,EAAK,CAAC,CAAA;AAAA,EACzE,CAAA,CAAA,MAAQ;AAAA,EAER;AACF;AAGA,eAAsB,wBAAA,CACpB,MAAA,EACA,MAAA,EACA,GAAA,EACA,QAAA,EACe;AACf,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,CAAO,IAAA;AAAA,MACX,IAAI,2BAAA,CAA4B;AAAA,QAC9B,MAAA,EAAQ,MAAA;AAAA,QACR,GAAA,EAAK,GAAA;AAAA,QACL,QAAA,EAAU;AAAA,OACX;AAAA,KACH;AAAA,EACF,CAAA,CAAA,MAAQ;AAAA,EAER;AACF;ACnBO,IAAM,MAAA,GAAS;AAAA,EACpB,UAAU,MAAM,YAAA,CAAa,IAAA,CAAK,WAAA,EAAa,eAAe,SAAS,CAAA;AAAA,EAEvE,cAAc,MACZ,YAAA,CAAa,IAAA,CAAK,cAAA,EAAgB,eAAe,YAAY,CAAA;AAAA,EAE/D,WAAW,MAAM,YAAA,CAAa,IAAA,CAAK,WAAA,EAAa,eAAe,SAAS,CAAA;AAAA,EAExE,UAAU,MAAM,YAAA,CAAa,IAAA,CAAK,UAAA,EAAY,eAAe,QAAQ,CAAA;AAAA,EAErE,eAAe,MACb,YAAA,CAAa,IAAA,CAAK,uBAAA,EAAyB,eAAe,cAAc,CAAA;AAAA,EAE1E,gBAAgB,MACd,YAAA,CAAa,IAAA,CAAK,WAAA,EAAa,eAAe,gBAAgB,CAAA;AAAA,EAEhE,eAAA,EAAiB,CAAC,OAAA,KAChB,YAAA,CAAa,KAAK,WAAA,EAAa;AAAA,IAC7B,IAAA,EAAM,eAAe,gBAAA,CAAiB,IAAA;AAAA,IACtC,OAAA,EAAS,cAAA,CAAe,gBAAA,CAAiB,OAAA,CAAQ,UAAA;AAAA,MAC/C,WAAA;AAAA,MACA;AAAA,KACF;AAAA,IACA,MAAA,EAAQ,EAAE,OAAA;AAAQ,GACnB,CAAA;AAAA,EAEH,YAAY,MACV,YAAA,CAAa,IAAA,CAAK,aAAA,EAAe,eAAe,WAAW,CAAA;AAAA,EAE7D,YAAA,EAAc,CAACA,MAAAA,KACb,YAAA,CAAa,KAAK,WAAA,EAAa;AAAA,IAC7B,IAAA,EAAM,eAAe,aAAA,CAAc,IAAA;AAAA,IACnC,OAAA,EAAS,eAAe,aAAA,CAAc,OAAA;AAAA,IACtC,MAAA,EAAQ,EAAE,KAAA,EAAAA,MAAAA;AAAM,GACjB,CAAA;AAAA,EAEH,oBAAoB,CAAC,QAAA,EAAkB,WAAA,KACrC,YAAA,CAAa,KAAK,aAAA,EAAe;AAAA,IAC/B,IAAA,EAAM,eAAe,qBAAA,CAAsB,IAAA;AAAA,IAC3C,OAAA,EAAS,eAAe,qBAAA,CAAsB,OAAA;AAAA,IAC9C,MAAA,EAAQ;AAAA,MACN,QAAA;AAAA,MACA,GAAI,WAAA,GAAc,EAAE,WAAA,KAAgB;AAAC;AACvC,GACD,CAAA;AAAA,EAEH,cAAA,EAAgB,CAAC,IAAA,KACf,YAAA,CAAa,KAAK,aAAA,EAAe;AAAA,IAC/B,IAAA,EAAM,eAAe,gBAAA,CAAiB,IAAA;AAAA,IACtC,OAAA,EAAS,cAAA,CAAe,gBAAA,CAAiB,OAAA,CAAQ,UAAA;AAAA,MAC/C,QAAA;AAAA,MACA;AAAA,KACF;AAAA,IACA,MAAA,EAAQ,EAAE,IAAA;AAAK,GAChB,CAAA;AAAA,EAEH,oBAAA,EAAsB,CAAC,UAAA,KACrB,YAAA,CAAa,KAAK,aAAA,EAAe;AAAA,IAC/B,IAAA,EAAM,eAAe,sBAAA,CAAuB,IAAA;AAAA,IAC5C,OAAA,EAAS,cAAA,CAAe,sBAAA,CAAuB,OAAA,CAAQ,UAAA;AAAA,MACrD,cAAA;AAAA,MACA,OAAO,UAAU;AAAA,KACnB;AAAA,IACA,MAAA,EAAQ,EAAE,UAAA;AAAW,GACtB,CAAA;AAAA,EAEH,eAAA,EAAiB,CACf,OAAA,GAAkB,cAAA,CAAe,kBAAkB,OAAA,KAEnD,YAAA,CAAa,KAAK,mBAAA,EAAqB;AAAA,IACrC,GAAG,cAAA,CAAe,iBAAA;AAAA,IAClB;AAAA,GACD,CAAA;AAAA,EAEH,aAAA,EAAe,CAAC,OAAA,GAAkB,cAAA,CAAe,eAAe,OAAA,KAC9D,YAAA,CAAa,KAAK,mBAAA,EAAqB;AAAA,IACrC,GAAG,cAAA,CAAe,cAAA;AAAA,IAClB;AAAA,GACD,CAAA;AAAA,EAEH,eAAA,EAAiB,CAAC,OAAA,KAChB,YAAA,CAAa,KAAK,aAAA,EAAe;AAAA,IAC/B,IAAA,EAAM,eAAe,gBAAA,CAAiB,IAAA;AAAA,IACtC;AAAA,GACD;AACL;;;ACpGO,SAAS,cAAc,GAAA,EAAuB;AACnD,EAAA,MAAM,CAAA,GAAI,GAAA;AAKV,EAAA,OACE,CAAA,EAAG,SAAS,WAAA,IACZ,CAAA,EAAG,SAAS,UAAA,IACZ,CAAA,EAAG,SAAS,cAAA,IACZ,CAAA,EAAG,SAAS,WAAA,IACZ,CAAA,EAAG,SAAS,UAAA,IACZ,CAAA,EAAG,SAAS,cAAA,IACZ,CAAA,EAAG,WAAW,cAAA,KAAmB,GAAA;AAErC;AAGA,eAAsB,qBACpB,IAAA,EACY;AACZ,EAAA,IAAI;AACF,IAAA,OAAO,MAAM,IAAA,EAAK;AAAA,EACpB,SAAS,GAAA,EAAc;AACrB,IAAA,IAAI,aAAA,CAAc,GAAG,CAAA,EAAG,MAAM,OAAO,cAAA,EAAe;AACpD,IAAA,MAAM,GAAA;AAAA,EACR;AACF;ACxBO,SAAS,kBAAA,CACd,KAAA,EACA,YAAA,GAAuB,iBAAA,EACf;AACR,EAAA,MAAM,CAAA,GAAI,OAAO,KAAK,CAAA;AACtB,EAAA,MAAM,OAAA,GACJ,MAAA,CAAO,QAAA,CAAS,CAAC,CAAA,IAAK,IAAI,CAAA,GAAI,IAAA,CAAK,KAAA,CAAM,CAAC,CAAA,GAAI,qBAAA;AAChD,EAAA,MAAM,GAAA,GACJ,MAAA,CAAO,QAAA,CAAS,YAAY,CAAA,IAAK,eAAe,CAAA,GAC5C,IAAA,CAAK,KAAA,CAAM,YAAY,CAAA,GACvB,iBAAA;AACN,EAAA,OAAO,IAAA,CAAK,GAAA,CAAI,OAAA,EAAS,GAAG,CAAA;AAC9B;;;AChBO,IAAM,aAAA,GAA+B;AAAA,EAC1C,KAAA,EAAO,CAAC,OAAA,EAAA,GAAY,IAAA,KAAS;AAC3B,IAAA,OAAA,CAAQ,KAAA,CAAM,YAAA,EAAc,OAAA,EAAS,GAAG,IAAI,CAAA;AAAA,EAC9C,CAAA;AAAA,EACA,IAAA,EAAM,CAAC,OAAA,EAAA,GAAY,IAAA,KAAS;AAC1B,IAAA,OAAA,CAAQ,IAAA,CAAK,YAAA,EAAc,OAAA,EAAS,GAAG,IAAI,CAAA;AAAA,EAC7C;AACF,CAAA;AAEO,SAAS,cACd,MAAA,EACe;AACf,EAAA,IAAI,MAAA,KAAW,KAAA,EAAO,OAAO,EAAC;AAC9B,EAAA,IAAI,CAAC,QAAQ,OAAO,aAAA;AACpB,EAAA,OAAO,MAAA;AACT;;;ACPA,SAAS,cAAc,GAAA,EAAqB;AAC1C,EAAA,IAAIC,UAAAA,CAAW,GAAG,CAAA,EAAG,MAAM,GAAA;AAC3B,EAAA,IAAI,GAAA,YAAe,KAAA,IAAS,GAAA,CAAI,OAAA,CAAQ,MAAK,EAAG;AAC9C,IAAA,MAAM,IAAIC,aAAa,WAAA,EAAa;AAAA,MAClC,SAAS,GAAA,CAAI,OAAA;AAAA,MACb,KAAA,EAAO;AAAA,KACR,CAAA;AAAA,EACH;AACA,EAAA,MAAM,OAAO,SAAA,EAAU;AACzB;AAOA,eAAsB,OAAA,CACpB,MACA,OAAA,EACe;AACf,EAAA,IAAI,CAAC,IAAA,EAAM;AACX,EAAA,IAAI;AACF,IAAA,MAAM,KAAK,OAAO,CAAA;AAAA,EACpB,SAAS,GAAA,EAAK;AACZ,IAAA,aAAA,CAAc,GAAG,CAAA;AAAA,EACnB;AACF;AAMA,eAAsB,aAAA,CACpB,MACA,OAAA,EACkC;AAClC,EAAA,IAAI,CAAC,IAAA,EAAM;AACX,EAAA,IAAI;AACF,IAAA,OAAO,MAAM,KAAK,OAAO,CAAA;AAAA,EAC3B,SAAS,GAAA,EAAK;AACZ,IAAA,aAAA,CAAc,GAAG,CAAA;AAAA,EACnB;AACF;AAMA,eAAsB,gBAAA,CACpB,IAAA,EACA,OAAA,EACA,MAAA,EACe;AACf,EAAA,IAAI,CAAC,IAAA,EAAM;AACX,EAAA,IAAI;AACF,IAAA,MAAM,KAAK,OAAO,CAAA;AAAA,EACpB,SAAS,GAAA,EAAK;AACZ,IAAA,IAAID,UAAAA,CAAW,GAAG,CAAA,EAAG,MAAM,GAAA;AAC3B,IAAA,aAAA,CAAc,MAAA,EAAQ,MAAM,CAAA,CAAE,KAAA,GAAQ,yBAAyB,GAAG,CAAA;AAClE,IAAA,MAAA,EAAQ,UAAU,GAAA,EAAK,EAAE,OAAA,EAAS,OAAA,CAAQ,SAAS,CAAA;AACnD,IAAA,MAAM,OAAO,aAAA,EAAc;AAAA,EAC7B;AACF;;;ACvEO,IAAM,uBAAA,GAA0B,oBAAA;AAEhC,SAAS,qBACd,QAAA,EACwB;AACxB,EAAA,IAAI,CAAC,QAAA,EAAU,OAAO,EAAC;AACvB,EAAA,MAAM,EAAE,CAAC,uBAAuB,GAAG,KAAA,EAAO,GAAG,MAAK,GAAI,QAAA;AACtD,EAAA,OAAO,IAAA;AACT;AAEO,SAAS,wBACd,QAAA,EACoB;AACpB,EAAA,MAAM,KAAA,GAAQ,QAAA,GAAW,uBAAuB,CAAA,EAAG,IAAA,EAAK;AACxD,EAAA,OAAO,KAAA,IAAS,MAAA;AAClB;;;ACkBO,SAAS,oBAAoB,GAAA,EAAqB;AACvD,EAAA,MAAM,UAAA,GAAa,mBAAmB,GAAG,CAAA;AACzC,EAAA,IAAI,CAAC,UAAA,EAAY,MAAM,MAAA,CAAO,UAAA,EAAW;AACzC,EAAA,OAAO,UAAA;AACT;AAEA,SAAS,WAAA,CAAY,QAAgB,GAAA,EAAqB;AACxD,EAAA,MAAM,CAAA,GAAI,oBAAoB,MAAM,CAAA;AACpC,EAAA,MAAM,CAAA,GAAI,oBAAoB,GAAG,CAAA;AACjC,EAAA,IAAI,EAAE,UAAA,CAAW,CAAA,EAAG,CAAC,CAAA,CAAA,CAAG,GAAG,OAAO,CAAA;AAClC,EAAA,IAAI,CAAA,KAAM,CAAA,EAAG,MAAM,MAAA,CAAO,UAAA,EAAW;AACrC,EAAA,OAAO,CAAA,EAAG,CAAC,CAAA,CAAA,EAAI,CAAC,CAAA,CAAA;AAClB;AAGO,SAAS,kBAAA,CACd,WACA,GAAA,EACQ;AACR,EAAA,MAAM,IAAA,GAAO,oBAAoB,GAAG,CAAA;AACpC,EAAA,IAAI,SAAA,KAAc,OAAO,OAAO,IAAA;AAChC,EAAA,OAAO,WAAA,CAAY,WAAW,IAAI,CAAA;AACpC;AAGO,SAAS,eAAA,CACd,KACA,SAAA,EACQ;AACR,EAAA,MAAM,IAAA,GAAO,oBAAoB,GAAG,CAAA;AACpC,EAAA,IAAI,SAAA,KAAc,OAAO,OAAO,IAAA;AAChC,EAAA,MAAM,IAAA,GAAO,oBAAoB,SAAS,CAAA;AAC1C,EAAA,IAAI,KAAK,UAAA,CAAW,CAAA,EAAG,IAAI,CAAA,CAAA,CAAG,GAAG,OAAO,IAAA;AACxC,EAAA,MAAM,OAAO,UAAA,EAAW;AAC1B;AAMA,SAAS,kBAAkB,QAAA,EAA0B;AACnD,EAAA,MAAM,SAAA,GAAY,iBAAiB,QAAQ,CAAA;AAC3C,EAAA,MAAM,IAAA,GAAO,SAAA,CACV,KAAA,CAAM,GAAG,CAAA,CACT,MAAA,CAAO,CAAC,IAAA,KAAS,IAAA,CAAK,MAAA,GAAS,CAAC,CAAA,CAChC,GAAG,EAAE,CAAA;AACR,EAAA,IAAI,CAAC,IAAA,IAAQ,IAAA,KAAS,GAAA,IAAO,IAAA,KAAS,MAAM,OAAO,MAAA;AACnD,EAAA,OAAO,IAAA;AACT;AAGO,SAAS,iBAAA,CACd,QACA,QAAA,EACQ;AACR,EAAA,MAAM,IAAA,GAAO,GAAG,MAAA,CAAO,UAAA,EAAY,CAAA,CAAA,EAAI,iBAAA,CAAkB,QAAQ,CAAC,CAAA,CAAA;AAClE,EAAA,IAAI,MAAA,KAAW,KAAA,EAAO,OAAO,mBAAA,CAAoB,IAAI,CAAA;AACrD,EAAA,OAAO,WAAA,CAAY,QAAQ,IAAI,CAAA;AACjC;AAEA,SAAS,UAAA,CACP,MACAD,MAAAA,EACuB;AACvB,EAAA,OAAO,IAAA,EAAM,GAAA,IAAOA,MAAAA,CAAM,MAAA,CAAO,GAAA,IAAO,SAAA;AAC1C;AAEA,eAAsB,mBAAA,CACpBA,QACA,OAAA,EACyB;AACzB,EAAA,MAAM,SAASA,MAAAA,CAAM,MAAA;AACrB,EAAA,MAAM,aAAA,GAAqC;AAAA,IACzC,GAAG,OAAA;AAAA,IACH,MAAA;AAAA,IACA,WAAWA,MAAAA,CAAM;AAAA,GACnB;AACA,EAAA,MAAM,OACH,MAAM,aAAA,CAAcA,OAAM,MAAA,CAAO,MAAA,EAAQ,aAAa,CAAA,IAAM,MAAA;AAC/D,EAAA,MAAM,GAAA,GAAM,MAAM,GAAA,GACd,kBAAA,CAAmBA,OAAM,SAAA,EAAW,IAAA,CAAK,GAAG,CAAA,GAC5C,iBAAA;AAAA,IACE,MAAM,MAAA,IAAU,IAAA,IAAQ,IAAA,CAAK,MAAA,KAAW,KACpC,kBAAA,CAAmBA,MAAAA,CAAM,SAAA,EAAW,IAAA,CAAK,MAAM,CAAA,GAC/CA,MAAAA,CAAM,SAAA,KAAc,KAAA,GAClB,QACAA,MAAAA,CAAM,SAAA;AAAA,IACZ,QAAQ,IAAA,CAAK;AAAA,GACf;AACJ,EAAA,MAAM,QAAA,GAAW,EAAE,GAAG,IAAA,EAAM,QAAA,EAAS;AACrC,EAAA,IAAI,MAAM,WAAA,EAAa;AACrB,IAAA,QAAA,CAAS,uBAAuB,CAAA,GAAI,kBAAA;AAAA,MAClCA,MAAAA,CAAM,SAAA;AAAA,MACN,IAAA,CAAK;AAAA,KACP;AAAA,EACF;AACA,EAAA,OAAO;AAAA,IACL,GAAA;AAAA,IACA,MAAA;AAAA,IACA,QAAA,EAAU,OAAO,IAAA,CAAK,QAAQ,EAAE,MAAA,GAAS,CAAA,GAAI,WAAW,IAAA,EAAM,QAAA;AAAA,IAC9D,GAAA,EAAK,UAAA,CAAW,IAAA,EAAMA,MAAK;AAAA,GAC7B;AACF;AAEO,SAAS,mBAAA,CACdA,QACA,GAAA,EACiC;AACjC,EAAA,OAAO;AAAA,IACL,GAAA,EAAK,eAAA,CAAgB,GAAA,EAAKA,MAAAA,CAAM,SAAS,CAAA;AAAA,IACzC,QAAQA,MAAAA,CAAM;AAAA,GAChB;AACF;ACtIO,SAAS,MAA0C,MAAA,EAAc;AACtE,EAAA,OAAO,MAAA;AACT;AAEO,SAAS,gBAAgB,IAAA,EAAoB;AAClD,EAAA,IAAI,CAAC,kBAAA,CAAmB,IAAA,CAAK,IAAI,CAAA,EAAG;AAClC,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,kBAAkB,IAAI,CAAA,yFAAA;AAAA,KACxB;AAAA,EACF;AACF;;;ACNO,SAAS,UACd,OAAA,EACkC;AAClC,EAAA,OAAO,OAAA,CAAQ,OAAA;AACjB;AAEA,SAAS,gBAAA,CACP,MACA,KAAA,EACgB;AAChB,EAAA,IAAI,KAAA,KAAU,OAAO,OAAO,KAAA;AAC5B,EAAA,MAAM,UAAA,GAAa,kBAAA,CAAmB,KAAA,IAAS,IAAI,CAAA;AACnD,EAAA,IAAI,CAAC,UAAA,EAAY;AACf,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,kBAAkB,IAAI,CAAA,8CAAA;AAAA,KACxB;AAAA,EACF;AACA,EAAA,OAAO,UAAA;AACT;AAOO,SAAS,WAAA,CACd,KAAA,EACA,SAAA,GAAY,KAAA,EACH;AACT,EAAA,IAAI,KAAA,KAAU,OAAO,OAAO,KAAA;AAC5B,EAAA,IAAI,KAAA,KAAU,QAAW,OAAO,SAAA;AAChC,EAAA,IAAI,KAAA,KAAU,MAAM,OAAO,IAAA;AAC3B,EAAA,IAAI,SAAA,IAAa,KAAA,IAAS,OAAO,KAAA,CAAM,YAAY,SAAA,EAAW;AAC5D,IAAA,OAAO,KAAA,CAAM,OAAA;AAAA,EACf;AACA,EAAA,OAAO,IAAA;AACT;AAGO,SAAS,gBAAA,CACd,KAAA,EACA,SAAA,GAAY,KAAA,EACQ;AACpB,EAAA,IAAI,KAAA,KAAU,KAAA,EAAO,OAAO,EAAE,SAAS,KAAA,EAAM;AAC7C,EAAA,IAAI,UAAU,MAAA,EAAW;AACvB,IAAA,IAAI,CAAC,SAAA,EAAW,OAAO,EAAE,SAAS,KAAA,EAAM;AACxC,IAAA,OAAO,EAAE,SAAS,IAAA,EAAK;AAAA,EACzB;AACA,EAAA,IAAI,KAAA,KAAU,IAAA,EAAM,OAAO,EAAE,SAAS,IAAA,EAAK;AAC3C,EAAA,OAAO,EAAE,GAAG,KAAA,EAAO,OAAA,EAAS,IAAA,EAAK;AACnC;AAEA,SAAS,iBAAiB,OAAA,EAAqD;AAC7E,EAAA,MAAM,GAAA,uBAAU,GAAA,EAAY;AAC5B,EAAA,IAAI,CAAC,SAAS,OAAO,GAAA;AACrB,EAAA,KAAA,MAAW,CAAC,EAAA,EAAI,OAAO,KAAK,MAAA,CAAO,OAAA,CAAQ,OAAO,CAAA,EAAG;AACnD,IAAA,IAAI,OAAA,KAAY,KAAA,EAAO,GAAA,CAAI,GAAA,CAAI,EAAE,CAAA;AAAA,EACnC;AACA,EAAA,OAAO,GAAA;AACT;AAEA,SAAS,YAAYG,OAAAA,EAGnB;AACA,EAAA,IAAIA,OAAAA,KAAW,MAAA,IAAa,OAAOA,OAAAA,KAAW,SAAA,EAAW;AACvD,IAAA,OAAO,EAAE,MAAA,EAAAA,OAAAA,EAAQ,SAAA,EAAW,MAAA,EAAU;AAAA,EACxC;AACA,EAAA,MAAM,EAAE,SAAA,EAAW,GAAG,IAAA,EAAK,GAAIA,OAAAA;AAC/B,EAAA,OAAO,EAAE,MAAA,EAAQ,IAAA,EAAM,SAAA,EAAU;AACnC;AAEO,SAAS,cAAA,CACd,IAAA,EACAH,MAAAA,EACA,QAAA,EACe;AACf,EAAA,eAAA,CAAgB,IAAI,CAAA;AAEpB,EAAA,MAAM,MAAA,GAASA,MAAAA,CAAM,MAAA,IAAU,QAAA,CAAS,MAAA;AACxC,EAAA,MAAM,MAAA,GAASA,MAAAA,CAAM,MAAA,IAAU,QAAA,CAAS,MAAA;AACxC,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,kBAAkB,IAAI,CAAA,2CAAA;AAAA,KACxB;AAAA,EACF;AACA,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,kBAAkB,IAAI,CAAA,2CAAA;AAAA,KACxB;AAAA,EACF;AAEA,EAAA,MAAM,EAAE,MAAA,EAAQ,WAAA,EAAa,SAAA,EAAW,gBAAe,GAAI,WAAA;AAAA,IACzDA,MAAAA,CAAM;AAAA,GACR;AACA,EAAA,MAAMG,OAAAA,GAAS,iBAAiB,WAAW,CAAA;AAC3C,EAAA,MAAMC,SAAAA,GAAW,gBAAA,CAAiCJ,MAAAA,CAAM,QAAQ,CAAA;AAChE,EAAA,MAAM,aAAA,GAAgB,gBAAA,CAA+BA,MAAAA,CAAM,MAAM,CAAA;AACjE,EAAA,MAAM,SAAA,GAAY,iBAAkC,cAAc,CAAA;AAElE,EAAA,IAAI,CAACG,QAAO,OAAA,IAAW,CAACC,UAAS,OAAA,IAAW,CAAC,cAAc,OAAA,EAAS;AAClE,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,kBAAkB,IAAI,CAAA,sCAAA;AAAA,KACxB;AAAA,EACF;AAEA,EAAA,MAAM,cAAA,GAAuCD,OAAAA,CAAO,OAAA,GAChD,EAAE,GAAGA,OAAAA,EAAQ,SAAA,EAAU,GACvB,EAAE,SAAS,KAAA,EAAO,SAAA,EAAW,EAAE,OAAA,EAAS,OAAM,EAAE;AAEpD,EAAA,IAAI,eAAe,OAAA,EAAS;AAC1B,IAAA,MAAM,cAAc,cAAA,CAAe,WAAA;AACnC,IAAA,IACE,WAAA,IAAe,SACd,CAAC,MAAA,CAAO,SAAS,WAAW,CAAA,IAAK,eAAe,CAAA,CAAA,EACjD;AACA,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,kBAAkB,IAAI,CAAA,yCAAA;AAAA,OACxB;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,IAAA;AAAA,IACA,MAAA;AAAA,IACA,MAAA;AAAA,IACA,SAAA,EAAW,gBAAA,CAAiB,IAAA,EAAMH,MAAAA,CAAM,SAAS,CAAA;AAAA,IACjD,OAAOA,MAAAA,CAAM,KAAA;AAAA,IACb,gBAAA,EAAkB,gBAAA,CAAiBA,MAAAA,CAAM,OAAO,CAAA;AAAA,IAChD,MAAA,EAAQ,cAAA;AAAA,IACR,QAAA,EAAAI,SAAAA;AAAA,IACA,MAAA,EAAQ;AAAA,GACV;AACF;AAEO,SAAS,gBACd,MAAA,EAC+B;AAC/B,EAAA,MAAM,OAAA,GAAU,MAAA,CAAO,OAAA,CAAQ,MAAA,CAAO,MAAM,CAAA;AAC5C,EAAA,IAAI,OAAA,CAAQ,WAAW,CAAA,EAAG;AACxB,IAAA,MAAM,IAAI,MAAM,0CAA0C,CAAA;AAAA,EAC5D;AACA,EAAA,MAAM,SAAwC,EAAC;AAC/C,EAAA,KAAA,MAAW,CAAC,IAAA,EAAMJ,MAAK,CAAA,IAAK,OAAA,EAAS;AACnC,IAAA,MAAA,CAAO,IAAI,CAAA,GAAI,cAAA,CAAe,IAAA,EAAMA,QAAO,MAAM,CAAA;AAAA,EACnD;AACA,EAAA,yBAAA,CAA0B,MAAM,CAAA;AAChC,EAAA,OAAO,MAAA;AACT;AAEA,SAAS,eAAA,CAAgB,GAAW,CAAA,EAAoB;AACtD,EAAA,OAAO,CAAA,KAAM,CAAA,IAAK,CAAA,CAAE,UAAA,CAAW,CAAA,EAAG,CAAC,CAAA,CAAA,CAAG,CAAA,IAAK,CAAA,CAAE,UAAA,CAAW,CAAA,EAAG,CAAC,CAAA,CAAA,CAAG,CAAA;AACjE;AAGA,SAAS,0BACP,MAAA,EACM;AACN,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA,CAAE,MAAA;AAAA,IACnC,CAAC,KAAA,KACC,KAAA,CAAM,CAAC,EAAE,SAAA,KAAc;AAAA,GAC3B;AACA,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,KAAA,CAAM,QAAQ,CAAA,EAAA,EAAK;AACrC,IAAA,KAAA,IAAS,IAAI,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,KAAA,CAAM,QAAQ,CAAA,EAAA,EAAK;AACzC,MAAA,MAAM,CAAC,KAAA,EAAO,MAAM,CAAA,GAAI,MAAM,CAAC,CAAA;AAC/B,MAAA,MAAM,CAAC,KAAA,EAAO,MAAM,CAAA,GAAI,MAAM,CAAC,CAAA;AAC/B,MAAA,IAAI,eAAA,CAAgB,MAAA,CAAO,SAAA,EAAW,MAAA,CAAO,SAAS,CAAA,EAAG;AACvD,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,CAAA,iBAAA,EAAoB,KAAK,CAAA,OAAA,EAAU,KAAK,yCAAyC,MAAA,CAAO,SAAS,CAAA,OAAA,EAAU,MAAA,CAAO,SAAS,CAAA,GAAA;AAAA,SAC7H;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;ACrLO,SAAS,uBAAA,CACd,aACA,IAAA,EACM;AACN,EAAA,IAAI,OAAO,WAAA,KAAgB,QAAA,IAAY,IAAA,GAAO,WAAA,EAAa;AACzD,IAAA,MAAM,OAAO,eAAA,EAAgB;AAAA,EAC/B;AACF;AAEO,SAAS,yBAAA,CACd,aACA,KAAA,EACM;AACN,EAAA,IACE,WAAA,EAAa,SAAA,EAAW,MAAA,IACxB,CAAC,gBAAA,CAAiB,KAAA,CAAM,QAAA,EAAU,KAAA,CAAM,WAAA,EAAa,WAAA,CAAY,SAAS,CAAA,EAC1E;AACA,IAAA,MAAM,MAAA,CAAO,kBAAA,CAAmB,KAAA,CAAM,QAAA,EAAU,MAAM,WAAW,CAAA;AAAA,EACnE;AACA,EAAA,uBAAA,CAAwB,WAAA,EAAa,WAAA,EAAa,KAAA,CAAM,QAAQ,CAAA;AAClE;AAEO,SAAS,yBAAA,CACd,aACA,KAAA,EACM;AACN,EAAA,uBAAA,CAAwB,WAAA,EAAa,WAAA,EAAa,KAAA,CAAM,aAAa,CAAA;AACrE,EAAA,MAAM,IAAA,GAAO,MAAM,QAAA,IAAY,EAAA;AAC/B,EAAA,IACE,WAAA,EAAa,SAAA,EAAW,MAAA,IACxB,CAAC,gBAAA,CAAiB,MAAM,KAAA,CAAM,WAAA,EAAa,WAAA,CAAY,SAAS,CAAA,EAChE;AACA,IAAA,MAAM,MAAA,CAAO,kBAAA,CAAmB,IAAA,IAAQ,SAAA,EAAW,MAAM,WAAW,CAAA;AAAA,EACtE;AACF;;;ACLO,SAAS,gBAAA,CACd,QACA,IAAA,EACe;AACf,EAAA,MAAMA,MAAAA,GAAQ,MAAA,CAAO,MAAA,CAAO,IAAI,CAAA;AAChC,EAAA,IAAI,CAACA,MAAAA,EAAO;AACV,IAAA,MAAM,MAAA,CAAO,aAAa,IAAI,CAAA;AAAA,EAChC;AACA,EAAA,OAAOA,MAAAA;AACT;AAEA,SAAS,gBAAA,CACPA,QACA,OAAA,EACS;AACT,EAAA,IAAI,OAAA,KAAY,WAAA,EAAa,OAAOA,MAAAA,CAAM,OAAO,SAAA,CAAU,OAAA;AAC3D,EAAA,OAAOA,MAAAA,CAAM,OAAO,CAAA,CAAE,OAAA;AACxB;AAGO,SAAS,oBAAA,CACdA,QACA,OAAA,EACiC;AACjC,EAAA,IAAI,CAAC,gBAAA,CAAiBA,MAAAA,EAAO,OAAO,CAAA,EAAG;AACrC,IAAA,MAAM,MAAA,CAAO,gBAAgB,OAAO,CAAA;AAAA,EACtC;AACF;AAGA,eAAsB,SAAA,CACpB,MAAA,EACA,IAAA,EACA,OAAA,EACA,OAAA,EACyB;AACzB,EAAA,MAAMA,MAAAA,GAAQ,gBAAA,CAAiB,MAAA,EAAQ,IAAI,CAAA;AAC3C,EAAA,oBAAA,CAAqBA,QAAO,OAAO,CAAA;AACnC,EAAA,MAAM,OAAA,CAAQA,OAAM,KAAA,EAAO,EAAE,SAAS,KAAA,EAAOA,MAAAA,CAAM,MAAM,CAAA;AACzD,EAAA,OAAOA,MAAAA;AACT;AAEO,SAAS,mBAAA,CACd,OAAA,EACAA,MAAAA,EACA,GAAA,EACqB;AACrB,EAAA,OAAO,EAAE,SAAS,KAAA,EAAOA,MAAAA,CAAM,MAAM,GAAA,EAAK,MAAA,EAAQA,OAAM,MAAA,EAAO;AACjE;AAMA,eAAsB,gBAAA,CACpB,MAAA,EACA,KAAA,EACA,OAAA,EACA,OAAA,EACgC;AAChC,EAAA,MAAMA,SAAQ,MAAM,SAAA,CAAU,QAAQ,KAAA,CAAM,KAAA,EAAO,SAAS,OAAO,CAAA;AACnE,EAAA,MAAM,QAAA,GAAW,IAAA,CAAK,KAAA,CAAM,KAAA,CAAM,QAAQ,CAAA;AAC1C,EAAA,MAAM,WAAW,KAAA,CAAM,QAAA;AACvB,EAAA,yBAAA,CAA0BA,OAAM,MAAA,EAAQ;AAAA,IACtC,QAAA;AAAA,IACA,QAAA;AAAA,IACA,aAAa,KAAA,CAAM;AAAA,GACpB,CAAA;AACD,EAAA,MAAM,MAAA,GAAS,MAAM,mBAAA,CAAoBA,MAAAA,EAAO;AAAA,IAC9C,OAAA;AAAA,IACA,OAAOA,MAAAA,CAAM,IAAA;AAAA,IACb,IAAA,EAAM;AAAA,MACJ,IAAA,EAAM,QAAA;AAAA,MACN,IAAA,EAAM,QAAA;AAAA,MACN,MAAM,KAAA,CAAM;AAAA,KACd;AAAA,IACA,gBAAgB,KAAA,CAAM;AAAA,GACvB,CAAA;AACD,EAAA,OAAO;AAAA,IACL,KAAA,EAAAA,MAAAA;AAAA,IACA,GAAG,MAAA;AAAA,IACH,MAAA,EAAQ,mBAAA,CAAoB,OAAA,EAASA,MAAAA,EAAO,OAAO,GAAG;AAAA,GACxD;AACF;AAGA,eAAsB,gBAAA,CACpB,MAAA,EACA,KAAA,EACA,OAAA,EACA,OAAA,EAC0B;AAC1B,EAAA,MAAMA,SAAQ,MAAM,SAAA,CAAU,QAAQ,KAAA,CAAM,KAAA,EAAO,SAAS,OAAO,CAAA;AACnE,EAAA,MAAM,MAAA,GAAS,mBAAA,CAAoBA,MAAAA,EAAO,KAAA,CAAM,GAAG,CAAA;AACnD,EAAA,OAAO;AAAA,IACL,KAAA,EAAAA,MAAAA;AAAA,IACA,GAAG,MAAA;AAAA,IACH,MAAA,EAAQ,mBAAA,CAAoB,OAAA,EAASA,MAAAA,EAAO,OAAO,GAAG;AAAA,GACxD;AACF;AC/HA,eAAsB,oBAAA,CACpB,MAAA,EACA,MAAA,EACA,GAAA,EACkC;AAClC,EAAA,OAAO,oBAAA;AAAA,IAAqB,MAC1B,MAAA,CAAO,IAAA,CAAK,IAAI,iBAAA,CAAkB,EAAE,MAAA,EAAQ,MAAA,EAAQ,GAAA,EAAK,GAAA,EAAK,CAAC;AAAA,GACjE;AACF;AAMA,eAAsB,gCAAA,CACpB,MAAA,EACA,MAAA,EACA,GAAA,EACkC;AAClC,EAAA,MAAM,OAAO,MACX,oBAAA;AAAA,IAAqB,MACnB,MAAA,CAAO,IAAA,CAAK,IAAI,iBAAA,CAAkB,EAAE,MAAA,EAAQ,MAAA,EAAQ,GAAA,EAAK,GAAA,EAAK,CAAC;AAAA,GACjE;AAEF,EAAA,IAAI,IAAA,GAAO,MAAM,IAAA,EAAK;AACtB,EAAA,KAAA,IACM,OAAA,GAAU,GACd,OAAA,GAAU,CAAA,IAAK,OAAO,IAAA,CAAK,aAAA,KAAkB,UAC7C,OAAA,EAAA,EACA;AACA,IAAA,MAAM,IAAI,QAAQ,CAAC,CAAA,KAAM,WAAW,CAAA,EAAG,GAAA,GAAM,CAAA,IAAK,OAAO,CAAC,CAAA;AAC1D,IAAA,IAAA,GAAO,MAAM,IAAA,EAAK;AAAA,EACpB;AACA,EAAA,OAAO,IAAA;AACT;AAGO,SAAS,qBAAqB,IAAA,EAAuC;AAC1E,EAAA,IAAI,OAAO,IAAA,CAAK,aAAA,KAAkB,QAAA,EAAU;AAC1C,IAAA,MAAM,OAAO,aAAA,EAAc;AAAA,EAC7B;AACA,EAAA,OAAO,IAAA,CAAK,aAAA;AACd;AC1CA,eAAsB,YAAA,CACpB,QACA,KAAA,EACiB;AACjB,EAAA,MAAM,QAAgB,EAAC;AACvB,EAAA,IAAI,gBAAA;AACJ,EAAA,IAAI,WAAA,GAAc,IAAA;AAElB,EAAA,OAAO,WAAA,EAAa;AAClB,IAAA,MAAM,WAAmC,MAAM,oBAAA;AAAA,MAAqB,MAClE,MAAA,CAAO,IAAA;AAAA,QACL,IAAI,gBAAA,CAAiB;AAAA,UACnB,QAAQ,KAAA,CAAM,MAAA;AAAA,UACd,KAAK,KAAA,CAAM,GAAA;AAAA,UACX,UAAU,KAAA,CAAM,QAAA;AAAA,UAChB,GAAI,gBAAA,GAAmB,EAAE,gBAAA,EAAkB,gBAAA,KAAqB;AAAC,SAClE;AAAA;AACH,KACF;AACA,IAAA,KAAA,CAAM,IAAA,CAAK,GAAI,QAAA,CAAS,KAAA,IAAS,EAAG,CAAA;AACpC,IAAA,WAAA,GAAc,SAAS,WAAA,KAAgB,IAAA;AACvC,IAAA,gBAAA,GAAmB,WAAA,GAAc,SAAS,oBAAA,GAAuB,MAAA;AAAA,EACnE;AAEA,EAAA,OAAO,KAAA;AACT;AAGO,SAAS,mBAAA,CACd,OACA,iBAAA,EACQ;AACR,EAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,IACE,iBAAA,KAAsB,MAAA,IACtB,IAAA,CAAK,UAAA,KAAe,iBAAA,EACpB;AACA,MAAA;AAAA,IACF;AACA,IAAA,KAAA,IAAS,KAAK,IAAA,IAAQ,CAAA;AAAA,EACxB;AACA,EAAA,OAAO,KAAA;AACT;AClBA,eAAsB,uBAAA,CACpB,MAAA,EACA,MAAA,EACA,GAAA,EACA,KAAA,EACkC;AAClC,EAAA,MAAM,EAAE,QAAQ,KAAA,EAAAA,MAAAA,EAAO,QAAQ,IAAA,EAAM,QAAA,EAAU,KAAI,GAAI,KAAA;AACvD,EAAA,MAAM,aAAA,GAAgB,qBAAqB,IAAI,CAAA;AAC/C,EAAA,MAAM,QAAA,GAAW,qBAAA,CAAsB,IAAA,CAAK,kBAAA,EAAoB,GAAG,CAAA;AACnE,EAAA,MAAM,WAAA,GAAc,IAAA,CAAK,QAAA,IAAY,EAAC;AAEtC,EAAA,IAAI;AACF,IAAA,yBAAA,CAA0BA,OAAM,MAAA,EAAQ;AAAA,MACtC,QAAA;AAAA,MACA,aAAa,IAAA,CAAK,WAAA;AAAA,MAClB;AAAA,KACD,CAAA;AAAA,EACH,SAAS,GAAA,EAAK;AACZ,IAAA,MAAM,sBAAA,CAAuB,MAAA,EAAQ,MAAA,EAAQ,GAAG,CAAA;AAChD,IAAA,MAAM,GAAA;AAAA,EACR;AAEA,EAAA,MAAM,QAAA,GAAW,qBAAqB,WAAW,CAAA;AACjD,EAAA,MAAM,OAAA,GAAoC;AAAA,IACxC,GAAG,MAAA;AAAA,IACH,aAAa,IAAA,CAAK,WAAA;AAAA,IAClB,aAAA;AAAA,IACA,IAAA,EAAM,IAAA,CAAK,IAAA,EAAM,OAAA,CAAQ,MAAM,EAAE,CAAA;AAAA,IACjC,QAAA;AAAA,IACA,GAAA;AAAA,IACA,QAAA;AAAA,IACA,WAAW,IAAA,CAAK,SAAA;AAAA,IAChB,YAAA,EAAc,IAAA,CAAK,YAAA,EAAc,WAAA,EAAY;AAAA,IAC7C;AAAA,GACF;AAEA,EAAA,IAAI;AACF,IAAA,MAAM,gBAAA,CAAiBA,MAAAA,CAAM,MAAA,CAAO,WAAA,EAAa,SAAS,MAAM,CAAA;AAAA,EAClE,SAAS,GAAA,EAAK;AACZ,IAAA,MAAM,sBAAA,CAAuB,MAAA,EAAQ,MAAA,EAAQ,GAAG,CAAA;AAChD,IAAA,MAAM,GAAA;AAAA,EACR;AAEA,EAAA,MAAM,WAAA,GAAc,wBAAwB,WAAW,CAAA;AACvD,EAAA,IAAI,WAAA,IAAe,gBAAgB,GAAA,EAAK;AACtC,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,GAAO,eAAA,CAAgB,WAAA,EAAaA,MAAAA,CAAM,SAAS,CAAA;AACzD,MAAA,MAAM,sBAAA,CAAuB,MAAA,EAAQ,MAAA,EAAQ,IAAI,CAAA;AAAA,IACnD,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,GAAA;AAAA,IACA,MAAA;AAAA,IACA,aAAa,OAAA,CAAQ,WAAA;AAAA,IACrB,eAAe,OAAA,CAAQ,aAAA;AAAA,IACvB,MAAM,OAAA,CAAQ,IAAA;AAAA,IACd,QAAA,EAAU,OAAA,CAAQ,QAAA,IAAY,EAAC;AAAA,IAC/B,GAAA;AAAA,IACA,QAAA;AAAA,IACA,WAAW,OAAA,CAAQ,SAAA;AAAA,IACnB,cAAc,OAAA,CAAQ;AAAA,GACxB;AACF;;;AC/EA,SAAS,QAAQ,IAAA,EAA0C;AACzD,EAAA,IAAI,OAAO,SAAS,QAAA,EAAU,OAAO,IAAI,WAAA,EAAY,CAAE,OAAO,IAAI,CAAA;AAClE,EAAA,IAAI,IAAA,YAAgB,WAAA,EAAa,OAAO,IAAI,WAAW,IAAI,CAAA;AAC3D,EAAA,OAAO,IAAA;AACT;AAKA,eAAsB,SAAA,CACpB,QACA,KAAA,EACkC;AAClC,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,KAAA,CAAM,IAAI,CAAA;AAC/B,EAAA,MAAM,OAAA,GAAU,kBAAA,CAAmB,KAAA,CAAM,OAAO,CAAA;AAChD,EAAA,MAAM,OAAA,CAAQ,MAAA,CAAO,KAAA,EAAO,EAAE,SAAS,CAAA;AACvC,EAAA,MAAM,WAAW,IAAA,CAAK,UAAA;AACtB,EAAA,MAAM,EAAE,OAAAA,MAAAA,EAAO,GAAA,EAAK,QAAQ,QAAA,EAAU,GAAA,EAAK,MAAA,EAAO,GAAI,MAAM,gBAAA;AAAA,IAC1D,MAAA;AAAA,IACA;AAAA,MACE,OAAO,KAAA,CAAM,KAAA;AAAA,MACb,UAAU,KAAA,CAAM,QAAA;AAAA,MAChB,QAAA;AAAA,MACA,aAAa,KAAA,CAAM,WAAA;AAAA,MACnB,UAAU,KAAA,CAAM;AAAA,KAClB;AAAA,IACA,OAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAA,MAAM,OAAA,CAAQA,MAAAA,CAAM,MAAA,CAAO,KAAA,EAAO;AAAA,IAChC,GAAG,MAAA;AAAA,IACH,IAAA,EAAM;AAAA,MACJ,MAAM,KAAA,CAAM,QAAA;AAAA,MACZ,IAAA,EAAM,QAAA;AAAA,MACN,MAAM,KAAA,CAAM;AAAA,KACd;AAAA,IACA,QAAA;AAAA,IACA,gBAAgB,KAAA,CAAM,QAAA;AAAA,IACtB,GAAA;AAAA,IACA,OAAA,EAASA,OAAM,MAAA,CAAO;AAAA,GACvB,CAAA;AAED,EAAA,MAAMA,OAAM,MAAA,CAAO,IAAA;AAAA,IACjB,IAAI,gBAAA,CAAiB;AAAA,MACnB,MAAA,EAAQ,MAAA;AAAA,MACR,GAAA,EAAK,GAAA;AAAA,MACL,IAAA,EAAM,IAAA;AAAA,MACN,aAAa,KAAA,CAAM,WAAA;AAAA,MACnB,aAAA,EAAe,QAAA;AAAA,MACf,QAAA,EAAU,QAAA;AAAA,MACV,GAAA,EAAK;AAAA,KACN;AAAA,GACH;AAEA,EAAA,MAAM,OAAO,MAAM,oBAAA,CAAqBA,MAAAA,CAAM,MAAA,EAAQ,QAAQ,GAAG,CAAA;AACjE,EAAA,OAAO,uBAAA,CAAwBA,MAAAA,CAAM,MAAA,EAAQ,MAAA,EAAQ,GAAA,EAAK;AAAA,IACxD,MAAA;AAAA,IACA,KAAA,EAAAA,MAAAA;AAAA,IACA,MAAA;AAAA,IACA,IAAA;AAAA,IACA;AAAA,GACD,CAAA;AACH;AC3EO,IAAM,mBAAA,GAAsB,gBAAA,CAAiB,OAAO,GAAA,KAAQ;AACjE,EAAA,MAAM,WAAW,GAAA,CAAI,OAAA;AACrB,EAAA,IAAI,CAAC,UAAU,MAAA,EAAQ;AACrB,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AAEA,EAAA,MAAM,UACJ,GAAA,CAAI,OAAA,IACJ,SAAS,OAAA,IACT,kBAAA,CAAmB,IAAI,OAAkC,CAAA;AAE3D,EAAA,MAAM,QAAQ,QAAA,CAAS,MAAA,CAAO,KAAA,EAAO,EAAE,SAAS,CAAA;AAEhD,EAAA,OAAO;AAAA,IACL,QAAQ,QAAA,CAAS,MAAA;AAAA,IACjB;AAAA,GACF;AACF,CAAC,CAAA;AAMM,IAAM,kBAAA,GAAqB,iBAAiB,MAAA,CAAO;AAAA,EACxD,GAAA,EAAK,CAAC,mBAAmB;AAC3B,CAAC;;;AC9BD,IAAM,yBAAA,GAA4B,eAAe,MAAA,CAAO;AAAA,EACtD,GAAA,EAAK,CAAC,mBAAmB;AAC3B,CAAC,CAAA;AAED,SAAS,aAAgB,MAAA,EAAc;AACrC,EAAA,IAAI,WAAW,IAAA,IAAQ,OAAO,MAAA,KAAW,QAAA,IAAY,UAAU,MAAA,EAAQ;AACrE,IAAA,OAAS,UAAQ,MAA8B,CAAA;AAAA,EACjD;AACA,EAAA,OAAO,MAAA;AACT;AAEA,SAAS,iBAA4C,OAAA,EAAe;AAClE,EAAA,OAAO;AAAA,IACL,GAAG,OAAA;AAAA,IACH,GAAI,OAAA,CAAQ,IAAA,KAAS,MAAA,GAAY,EAAE,IAAA,EAAM,YAAA,CAAa,OAAA,CAAQ,IAAI,CAAA,EAAE,GAAI,EAAC;AAAA,IACzE,GAAI,OAAA,CAAQ,KAAA,KAAU,MAAA,GAClB,EAAE,KAAA,EAAO,YAAA,CAAa,OAAA,CAAQ,KAAK,CAAA,EAAE,GACrC,EAAC;AAAA,IACL,mBACE,OAAA,CAAQ,iBAAA,KACP,CAAC,EAAE,SAAQ,KAA2B;AACrC,MAAA,MAAM,MAAA,CAAO,gBAAgB,OAAO,CAAA;AAAA,IACtC,CAAA;AAAA,GACJ;AACF;AAsBO,IAAM,gBAAA,IAAsC,CACjD,aAAA,EACA,gBAAA,EACA,YAAA,KACG;AACH,EAAA,IAAI,OAAO,kBAAkB,QAAA,EAAU;AACrC,IAAA,OAAO,yBAAA;AAAA,MACL,aAAA;AAAA,MACA,iBAAiB,gBAAmC,CAAA;AAAA,MACpD;AAAA,KACF;AAAA,EACF;AACA,EAAA,OAAO,yBAAA;AAAA,IACL,iBAAiB,aAAa,CAAA;AAAA,IAC9B;AAAA,GACF;AACF,CAAA;;;ACxDA,eAAe,aAAA,CACb,MAAA,EACA,KAAA,EACA,OAAA,EACA;AACA,EAAA,MAAM,EAAE,KAAA,EAAAA,MAAAA,EAAO,KAAK,MAAA,EAAQ,MAAA,KAAW,MAAM,gBAAA;AAAA,IAC3C,MAAA;AAAA,IACA,KAAA;AAAA,IACA,OAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAA,MAAM,OAAA,CAAQA,MAAAA,CAAM,MAAA,CAAO,YAAA,EAAc;AAAA,IACvC,GAAG,MAAA;AAAA,IACH,OAAA,EAASA,OAAM,MAAA,CAAO;AAAA,GACvB,CAAA;AAED,EAAA,MAAM,OAAO,MAAM,oBAAA,CAAqBA,MAAAA,CAAM,MAAA,EAAQ,QAAQ,GAAG,CAAA;AACjE,EAAA,OAAO,uBAAA,CAAwBA,MAAAA,CAAM,MAAA,EAAQ,MAAA,EAAQ,GAAA,EAAK;AAAA,IACxD,MAAA;AAAA,IACA,KAAA,EAAAA,MAAAA;AAAA,IACA,MAAA;AAAA,IACA,IAAA;AAAA,IACA,GAAA,EAAKA,OAAM,MAAA,CAAO;AAAA,GACnB,CAAA;AACH;AAEO,IAAM,OAAA,GAAU,gBAAA;AAAA,EACrB,aAAA,CAAc,aAAA;AAAA,EACd,EAAE,MAAA,EAAQ,MAAA,EAAQ,IAAA,EAAM,iBAAA,EAAkB;AAAA,EAC1C,OAAO,GAAA,KAAQ;AACb,IAAA,OAAO,aAAA,CAAc,IAAI,OAAA,CAAQ,MAAA,EAAQ,IAAI,IAAA,EAAM,GAAA,CAAI,QAAQ,OAAO,CAAA;AAAA,EACxE;AACF,CAAA;AC5BA,eAAe,YAAA,CACb,MAAA,EACA,KAAA,EACA,OAAA,EACyB;AACzB,EAAA,MAAM,EAAE,KAAA,EAAAA,MAAAA,EAAO,KAAK,MAAA,EAAQ,MAAA,KAAW,MAAM,gBAAA;AAAA,IAC3C,MAAA;AAAA,IACA,KAAA;AAAA,IACA,OAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAA,MAAM,OAAA,CAAQA,MAAAA,CAAM,MAAA,CAAO,KAAA,EAAO,MAAM,CAAA;AAExC,EAAA,MAAM,oBAAA,CAAqBA,MAAAA,CAAM,MAAA,EAAQ,MAAA,EAAQ,GAAG,CAAA;AAEpD,EAAA,MAAMA,OAAM,MAAA,CAAO,IAAA;AAAA,IACjB,IAAIK,mBAAAA,CAAoB,EAAE,QAAQ,MAAA,EAAQ,GAAA,EAAK,KAAK;AAAA,GACtD;AAEA,EAAA,MAAM,gBAAA,CAAiBL,MAAAA,CAAM,MAAA,CAAO,SAAA,EAAW,QAAQ,MAAM,CAAA;AAE7D,EAAA,OAAO,EAAE,OAAA,EAAS,IAAA,EAAM,MAAA,EAAQ,GAAA,EAAI;AACtC;AAEO,IAAM,YAAA,GAAe,gBAAA;AAAA,EAC1BM,aAAAA,CAAc,MAAA;AAAA,EACd,EAAE,MAAA,EAAQ,QAAA,EAAU,KAAA,EAAO,iBAAA,EAAkB;AAAA,EAC7C,OAAO,GAAA,KAAQ;AACb,IAAA,OAAO,YAAA,CAAa,IAAI,OAAA,CAAQ,MAAA,EAAQ,IAAI,KAAA,EAAO,GAAA,CAAI,QAAQ,OAAO,CAAA;AAAA,EACxE;AACF,CAAA;AC/BA,eAAe,SAAA,CACb,MAAA,EACA,SAAA,EACA,GAAA,EACA,OAAA,EACe;AACf,EAAA,MAAM,EAAE,KAAA,EAAAN,MAAAA,EAAO,MAAA,EAAQ,MAAA,KAAW,MAAM,gBAAA;AAAA,IACtC,MAAA;AAAA,IACA,EAAE,KAAA,EAAO,SAAA,EAAW,GAAA,EAAI;AAAA,IACxB,OAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAA,MAAM,OAAA,CAAQA,MAAAA,CAAM,MAAA,CAAO,KAAA,EAAO,MAAM,CAAA;AACxC,EAAA,MAAM,oBAAA,CAAqBA,MAAAA,CAAM,MAAA,EAAQ,MAAA,EAAQ,OAAO,GAAG,CAAA;AAC3D,EAAA,MAAMA,OAAM,MAAA,CAAO,IAAA;AAAA,IACjB,IAAIK,oBAAoB,EAAE,MAAA,EAAQ,QAAQ,GAAA,EAAK,MAAA,CAAO,KAAK;AAAA,GAC7D;AACA,EAAA,MAAM,gBAAA,CAAiBL,MAAAA,CAAM,MAAA,CAAO,SAAA,EAAW,QAAQ,MAAM,CAAA;AAC/D;AAEO,IAAM,WAAA,GAAc,gBAAA;AAAA,EACzBM,aAAAA,CAAc,WAAA;AAAA,EACd,EAAE,MAAA,EAAQ,MAAA,EAAQ,IAAA,EAAM,qBAAA,EAAsB;AAAA,EAC9C,OAAO,GAAA,KAAsC;AAC3C,IAAA,MAAM,MAAA,GAAS,IAAI,OAAA,CAAQ,MAAA;AAC3B,IAAA,MAAM,OAAA,GAAU,IAAI,OAAA,CAAQ,OAAA;AAC5B,IAAA,MAAM,UAA0C,EAAC;AAEjD,IAAA,KAAA,MAAW,GAAA,IAAO,GAAA,CAAI,IAAA,CAAK,IAAA,EAAM;AAC/B,MAAA,IAAI;AACF,QAAA,MAAM,UAAU,MAAA,EAAQ,GAAA,CAAI,IAAA,CAAK,KAAA,EAAO,KAAK,OAAO,CAAA;AACpD,QAAA,OAAA,CAAQ,IAAA,CAAK,EAAE,GAAA,EAAK,OAAA,EAAS,MAAM,CAAA;AAAA,MACrC,SAAS,GAAA,EAAK;AACZ,QAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,UACX,GAAA;AAAA,UACA,OAAA,EAAS,KAAA;AAAA,UACT,OAAOC,cAAAA,CAAe,GAAG,CAAA,GACrB,EAAE,MAAM,GAAA,CAAI,IAAA,IAAQ,gBAAA,EAAkB,OAAA,EAAS,IAAI,OAAA,EAAQ,GAC3D,EAAE,IAAA,EAAM,gBAAA,EAAkB,SAAS,uBAAA;AAAwB,SAChE,CAAA;AAAA,MACH;AAAA,IACF;AAEA,IAAA,OAAO,EAAE,OAAA,EAAQ;AAAA,EACnB;AACF,CAAA;AC3CA,SAAS,OAAA,CACP,OAAA,EACA,QAAA,EACA,KAAA,EAMQ;AACR,EAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,OAAA,CAAQ,GAAG,CAAA;AAC/B,EAAA,MAAM,MAAA,GAAS,SAAS,QAAA,CAAS,GAAG,IAAI,QAAA,CAAS,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA,GAAI,QAAA;AAChE,EAAA,GAAA,CAAI,QAAA,GAAW,CAAA,EAAG,MAAM,CAAA,EAAGD,cAAc,IAAI,CAAA,CAAA;AAC7C,EAAA,GAAA,CAAI,MAAA,GAAS,EAAA;AACb,EAAA,GAAA,CAAI,YAAA,CAAa,GAAA,CAAI,OAAA,EAAS,KAAA,CAAM,KAAK,CAAA;AACzC,EAAA,GAAA,CAAI,YAAA,CAAa,GAAA,CAAI,KAAA,EAAO,KAAA,CAAM,GAAG,CAAA;AACrC,EAAA,IAAI,MAAM,QAAA,EAAU,GAAA,CAAI,aAAa,GAAA,CAAI,UAAA,EAAY,MAAM,QAAQ,CAAA;AACnE,EAAA,IAAI,MAAM,WAAA,EAAa,GAAA,CAAI,aAAa,GAAA,CAAI,aAAA,EAAe,MAAM,WAAW,CAAA;AAC5E,EAAA,OAAO,IAAI,QAAA,EAAS;AACtB;AAEA,eAAe,cAAA,CACb,MAAA,EACA,KAAA,EACA,OAAA,EACkC;AAClC,EAAA,MAAM,EAAE,KAAA,EAAAN,MAAAA,EAAO,KAAK,MAAA,EAAQ,MAAA,KAAW,MAAM,gBAAA;AAAA,IAC3C,MAAA;AAAA,IACA,KAAA;AAAA,IACA,OAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAA,MAAM,QAAA,GAAW,MAAMA,MAAAA,CAAM,QAAA,CAAS,OAAA,GAAU;AAAA,IAC9C,GAAG,MAAA;AAAA,IACH,UAAU,KAAA,CAAM,QAAA;AAAA,IAChB,WAAA,EAAa,KAAA,CAAM,WAAA,IAAeA,MAAAA,CAAM,QAAA,CAAS;AAAA,GAClD,CAAA;AAED,EAAA,MAAM,QAAA,GAAW,QAAA,EAAU,QAAA,IAAY,KAAA,CAAM,QAAA;AAC7C,EAAA,MAAM,cACJ,QAAA,EAAU,WAAA,IACV,MAAM,WAAA,IACNA,MAAAA,CAAM,SAAS,WAAA,IACf,YAAA;AACF,EAAA,MAAM,SAAA,GAAY,kBAAA;AAAA,IAChB,QAAA,EAAU,SAAA,IAAaA,MAAAA,CAAM,QAAA,CAAS,SAAA;AAAA,IACtC,MAAA,CAAO;AAAA,GACT;AAEA,EAAA,MAAM,OAAA,CAAQA,MAAAA,CAAM,QAAA,CAAS,KAAA,EAAO;AAAA,IAClC,GAAG,MAAA;AAAA,IACH,QAAA;AAAA,IACA;AAAA,GACD,CAAA;AAED,EAAA,MAAM,oBAAA,CAAqBA,MAAAA,CAAM,MAAA,EAAQ,MAAA,EAAQ,GAAG,CAAA;AAEpD,EAAA,MAAM,IAAA,GAAOA,MAAAA,CAAM,QAAA,CAAS,IAAA,IAAQ,SAAA;AACpC,EAAA,MAAM,kBAAA,GAAqB,QAAA,GACvB,uBAAA,CAAwB,QAAA,EAAU,WAAW,CAAA,GAC7C,WAAA;AAEJ,EAAA,MAAM,MACJ,IAAA,KAAS,OAAA,GACL,QAAQ,OAAA,EAAS,MAAA,CAAO,YAAY,SAAA,EAAW;AAAA,IAC7C,OAAO,KAAA,CAAM,KAAA;AAAA,IACb,GAAA;AAAA,IACA,QAAA;AAAA,IACA;AAAA,GACD,IACD,MAAM,YAAA;AAAA,IACJA,MAAAA,CAAM,MAAA;AAAA,IACN,IAAI,gBAAA,CAAiB;AAAA,MACnB,MAAA,EAAQ,MAAA;AAAA,MACR,GAAA,EAAK,GAAA;AAAA,MACL,0BAAA,EAA4B;AAAA,KAC7B,CAAA;AAAA,IACD,EAAE,SAAA;AAAU,GACd;AAEN,EAAA,MAAM,gBAAA;AAAA,IACJA,OAAM,QAAA,CAAS,WAAA;AAAA,IACf;AAAA,MACE,GAAG,MAAA;AAAA,MACH,QAAA;AAAA,MACA,GAAA;AAAA,MACA,SAAA,EAAW,IAAA,KAAS,OAAA,GAAU,CAAA,GAAI;AAAA,KACpC;AAAA,IACA;AAAA,GACF;AAEA,EAAA,OAAO;AAAA,IACL,MAAA;AAAA,IACA,GAAA;AAAA,IACA,GAAA;AAAA,IACA,SAAA,EAAW,IAAA,KAAS,OAAA,GAAU,CAAA,GAAI,SAAA;AAAA,IAClC,IAAA;AAAA,IACA;AAAA,GACF;AACF;AAEO,IAAM,QAAA,GAAW,gBAAA;AAAA,EACtBM,aAAAA,CAAc,QAAA;AAAA,EACd,EAAE,MAAA,EAAQ,KAAA,EAAO,KAAA,EAAO,mBAAA,EAAoB;AAAA,EAC5C,OAAO,GAAA,KAAQ;AACb,IAAA,OAAO,cAAA,CAAe,IAAI,OAAA,CAAQ,MAAA,EAAQ,IAAI,KAAA,EAAO,GAAA,CAAI,QAAQ,OAAO,CAAA;AAAA,EAC1E;AACF,CAAA;ACtHA,SAAS,cACPH,OAAAA,EAC6B;AAC7B,EAAA,IAAI,CAAC,SAAA,CAAUA,OAAM,GAAG,OAAO,EAAE,SAAS,KAAA,EAAM;AAChD,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,IAAA;AAAA,IACT,WAAWA,OAAAA,CAAO,SAAA;AAAA,IAClB,aAAaA,OAAAA,CAAO,WAAA;AAAA,IACpB,SAAA,EAAW,SAAA,CAAUA,OAAAA,CAAO,SAAS,CAAA;AAAA,IACrC,GAAIA,OAAAA,CAAO,QAAA,GAAW,EAAE,QAAA,EAAU,IAAA,KAAS,EAAC;AAAA,IAC5C,GAAIA,QAAO,OAAA,GAAU,EAAE,SAASA,OAAAA,CAAO,OAAA,KAAY;AAAC,GACtD;AACF;AAEA,SAAS,gBACPC,SAAAA,EAC+B;AAC/B,EAAA,IAAI,CAAC,SAAA,CAAUA,SAAQ,GAAG,OAAO,EAAE,SAAS,KAAA,EAAM;AAClD,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,IAAA;AAAA,IACT,GAAIA,UAAS,WAAA,GAAc,EAAE,aAAaA,SAAAA,CAAS,WAAA,KAAgB,EAAC;AAAA,IACpE,GAAIA,UAAS,IAAA,GAAO,EAAE,MAAMA,SAAAA,CAAS,IAAA,KAAS;AAAC,GACjD;AACF;AAEO,SAAS,kBACd,MAAA,EACsB;AACtB,EAAA,MAAM,SAAyC,EAAC;AAChD,EAAA,KAAA,MAAW,CAAC,MAAMJ,MAAK,CAAA,IAAK,OAAO,OAAA,CAAQ,MAAA,CAAO,MAAM,CAAA,EAAG;AACzD,IAAA,MAAA,CAAO,IAAI,CAAA,GAAI;AAAA,MACb,MAAA,EAAQ,aAAA,CAAcA,MAAAA,CAAM,MAAM,CAAA;AAAA,MAClC,QAAA,EAAU,eAAA,CAAgBA,MAAAA,CAAM,QAAQ,CAAA;AAAA,MACxC,MAAA,EAAQ,SAAA,CAAUA,MAAAA,CAAM,MAAM,CAAA,GAAI,EAAE,OAAA,EAAS,IAAA,EAAK,GAAI,EAAE,OAAA,EAAS,KAAA;AAAM,KACzE;AAAA,EACF;AACA,EAAA,OAAO,EAAE,MAAA,EAAO;AAClB;AAEO,IAAM,OAAA,GAAU,gBAAA;AAAA,EACrBM,aAAAA,CAAc,OAAA;AAAA,EACd,EAAE,QAAQ,KAAA,EAAM;AAAA,EAChB,OAAO,GAAA,KAAuC;AAC5C,IAAA,OAAO,iBAAA,CAAkB,GAAA,CAAI,OAAA,CAAQ,MAAM,CAAA;AAAA,EAC7C;AACF,CAAA;ACpCA,eAAe,UAAA,CACb,MAAA,EACA,KAAA,EACA,OAAA,EACmB;AACnB,EAAA,MAAM,EAAE,KAAA,EAAAN,MAAAA,EAAO,KAAK,MAAA,EAAQ,MAAA,KAAW,MAAM,gBAAA;AAAA,IAC3C,MAAA;AAAA,IACA,KAAA;AAAA,IACA,OAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAA,MAAM,QAAA,GAAW,MAAMA,MAAAA,CAAM,QAAA,CAAS,OAAA,GAAU;AAAA,IAC9C,GAAG,MAAA;AAAA,IACH,UAAU,KAAA,CAAM,QAAA;AAAA,IAChB,WAAA,EAAa,KAAA,CAAM,WAAA,IAAeA,MAAAA,CAAM,QAAA,CAAS;AAAA,GAClD,CAAA;AACD,EAAA,MAAM,QAAA,GAAW,QAAA,EAAU,QAAA,IAAY,KAAA,CAAM,QAAA;AAC7C,EAAA,MAAM,cACJ,QAAA,EAAU,WAAA,IACV,MAAM,WAAA,IACNA,MAAAA,CAAM,SAAS,WAAA,IACf,YAAA;AAEF,EAAA,MAAM,OAAA,CAAQA,MAAAA,CAAM,QAAA,CAAS,KAAA,EAAO;AAAA,IAClC,GAAG,MAAA;AAAA,IACH,QAAA;AAAA,IACA;AAAA,GACD,CAAA;AAED,EAAA,MAAM,oBAAA,CAAqBA,MAAAA,CAAM,MAAA,EAAQ,MAAA,EAAQ,GAAG,CAAA;AAEpD,EAAA,MAAM,SAAS,MAAM,oBAAA;AAAA,IAAqB,MACxCA,OAAM,MAAA,CAAO,IAAA;AAAA,MACX,IAAIQ,gBAAAA,CAAiB;AAAA,QACnB,MAAA,EAAQ,MAAA;AAAA,QACR,GAAA,EAAK,GAAA;AAAA,QACL,4BAA4B,QAAA,GACxBC,uBAAAA,CAAwB,UAAU,WAAW,CAAA,GAC7C,GAAG,WAAW,CAAA;AAAA,OACnB;AAAA;AACH,GACF;AAEA,EAAA,MAAM,OAAO,MAAA,CAAO,IAAA;AACpB,EAAA,IAAI,CAAC,IAAA,EAAM,MAAM,MAAA,CAAO,cAAA,EAAe;AAEvC,EAAA,MAAM,MAAA,GACJ,0BAA0B,IAAA,IAC1B,OAAO,KAAK,oBAAA,KAAyB,UAAA,GACjC,IAAA,CAAK,oBAAA,EAAqB,GACzB,IAAA;AAEP,EAAA,MAAM,OAAA,GAAU,IAAI,OAAA,EAAQ;AAC5B,EAAA,OAAA,CAAQ,GAAA,CAAI,cAAA,EAAgB,MAAA,CAAO,WAAA,IAAe,0BAA0B,CAAA;AAC5E,EAAA,OAAA,CAAQ,GAAA;AAAA,IACN,qBAAA;AAAA,IACA,WACIA,uBAAAA,CAAwB,QAAA,EAAU,WAAW,CAAA,GAC7C,GAAG,WAAW,CAAA;AAAA,GACpB;AACA,EAAA,IAAI,OAAO,MAAA,CAAO,aAAA,KAAkB,QAAA,EAAU;AAC5C,IAAA,OAAA,CAAQ,GAAA,CAAI,gBAAA,EAAkB,MAAA,CAAO,MAAA,CAAO,aAAa,CAAC,CAAA;AAAA,EAC5D;AAEA,EAAA,OAAO,IAAI,QAAA,CAAS,MAAA,EAAQ,EAAE,SAAS,CAAA;AACzC;AAEO,IAAM,IAAA,GAAO,gBAAA;AAAA,EAClBH,aAAAA,CAAc,IAAA;AAAA,EACd,EAAE,MAAA,EAAQ,KAAA,EAAO,KAAA,EAAO,eAAA,EAAgB;AAAA,EACxC,OAAO,GAAA,KAAQ;AACb,IAAA,OAAO,UAAA,CAAW,IAAI,OAAA,CAAQ,MAAA,EAAQ,IAAI,KAAA,EAAO,GAAA,CAAI,QAAQ,OAAO,CAAA;AAAA,EACtE;AACF,CAAA;AC5EA,eAAe,WAAA,CACb,MAAA,EACA,KAAA,EACA,OAAA,EACiC;AACjC,EAAA,MAAM,EAAE,KAAA,EAAAN,MAAAA,EAAO,KAAK,MAAA,EAAQ,MAAA,KAAW,MAAM,gBAAA;AAAA,IAC3C,MAAA;AAAA,IACA,KAAA;AAAA,IACA,OAAA;AAAA,IACA;AAAA,GACF;AACA,EAAA,MAAM,WAAW,KAAA,CAAM,QAAA;AAEvB,EAAA,MAAM,OAAA,CAAQA,MAAAA,CAAM,MAAA,CAAO,SAAA,CAAU,KAAA,EAAO;AAAA,IAC1C,GAAG,MAAA;AAAA,IACH,QAAA;AAAA,IACA,MAAA,EAAQ;AAAA,GACT,CAAA;AAED,EAAA,MAAM,oBAAA;AAAA,IAAqB,MACzBA,OAAM,MAAA,CAAO,IAAA;AAAA,MACX,IAAIU,2BAAAA,CAA4B;AAAA,QAC9B,MAAA,EAAQ,MAAA;AAAA,QACR,GAAA,EAAK,GAAA;AAAA,QACL,QAAA,EAAU;AAAA,OACX;AAAA;AACH,GACF;AAEA,EAAA,MAAM,gBAAA;AAAA,IACJV,MAAAA,CAAM,OAAO,SAAA,CAAU,OAAA;AAAA,IACvB;AAAA,MACE,GAAG,MAAA;AAAA,MACH;AAAA,KACF;AAAA,IACA;AAAA,GACF;AAEA,EAAA,OAAO,EAAE,MAAA,EAAQ,GAAA,EAAK,QAAA,EAAU,SAAS,IAAA,EAAK;AAChD;AAEO,IAAM,cAAA,GAAiB,gBAAA;AAAA,EAC5BM,aAAAA,CAAc,cAAA;AAAA,EACd,EAAE,MAAA,EAAQ,MAAA,EAAQ,IAAA,EAAM,wBAAA,EAAyB;AAAA,EACjD,OAAO,GAAA,KAAQ;AACb,IAAA,OAAO,WAAA,CAAY,IAAI,OAAA,CAAQ,MAAA,EAAQ,IAAI,IAAA,EAAM,GAAA,CAAI,QAAQ,OAAO,CAAA;AAAA,EACtE;AACF,CAAA;ACvCA,eAAe,cAAA,CACb,MAAA,EACA,KAAA,EACA,OAAA,EACoC;AACpC,EAAA,MAAM,EAAE,KAAA,EAAAN,MAAAA,EAAO,KAAK,MAAA,EAAQ,MAAA,KAAW,MAAM,gBAAA;AAAA,IAC3C,MAAA;AAAA,IACA,KAAA;AAAA,IACA,OAAA;AAAA,IACA;AAAA,GACF;AACA,EAAA,MAAM,WAAW,KAAA,CAAM,QAAA;AACvB,EAAA,MAAM,KAAA,GAAQ;AAAA,IACZ,GAAG,IAAI,GAAA,CAAI,KAAA,CAAM,KAAA,CAAM,GAAA,CAAI,CAAC,EAAE,UAAA,EAAW,KAAM,UAAU,CAAC;AAAA,IAC1D,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,IAAI,CAAC,CAAA;AACtB,EAAA,MAAM,WAAW,KAAA,CAAM,GAAA,CAAI,CAAC,UAAA,MAAgB,EAAE,YAAW,CAAE,CAAA;AAE3D,EAAA,MAAM,OAAA,CAAQA,MAAAA,CAAM,MAAA,CAAO,SAAA,CAAU,KAAA,EAAO;AAAA,IAC1C,GAAG,MAAA;AAAA,IACH,QAAA;AAAA,IACA,MAAA,EAAQ;AAAA,GACT,CAAA;AACD,EAAA,MAAM,OAAA,CAAQA,MAAAA,CAAM,MAAA,CAAO,YAAA,EAAc;AAAA,IACvC,GAAG,MAAA;AAAA,IACH,QAAA;AAAA,IACA,KAAA,EAAO,QAAA;AAAA,IACP,OAAA,EAASA,OAAM,MAAA,CAAO;AAAA,GACvB,CAAA;AAED,EAAA,MAAM,WAAA,GAAc,MAAM,YAAA,CAAaA,MAAAA,CAAM,MAAA,EAAQ;AAAA,IACnD,MAAA;AAAA,IACA,GAAA;AAAA,IACA;AAAA,GACD,CAAA;AAED,EAAA,IAAI,cAAA,GAAiB,CAAA;AACrB,EAAA,MAAM,aAAA,GAAgB,KAAA,CAAM,GAAA,CAAI,CAAC,UAAA,KAAe;AAC9C,IAAA,MAAM,QAAQ,WAAA,CAAY,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,eAAe,UAAU,CAAA;AACjE,IAAA,IAAI,CAAC,OAAO,IAAA,EAAM;AAChB,MAAA,MAAM,MAAA,CAAO,qBAAqB,UAAU,CAAA;AAAA,IAC9C;AACA,IAAA,cAAA,IAAkB,MAAM,IAAA,IAAQ,CAAA;AAChC,IAAA,OAAO,EAAE,UAAA,EAAY,UAAA,EAAY,IAAA,EAAM,MAAM,IAAA,EAAK;AAAA,EACpD,CAAC,CAAA;AAED,EAAA,IAAI;AACF,IAAA,uBAAA,CAAwBA,MAAAA,CAAM,MAAA,CAAO,WAAA,EAAa,cAAc,CAAA;AAAA,EAClE,SAAS,GAAA,EAAK;AACZ,IAAA,MAAM,wBAAA,CAAyBA,MAAAA,CAAM,MAAA,EAAQ,MAAA,EAAQ,KAAK,QAAQ,CAAA;AAClE,IAAA,MAAM,GAAA;AAAA,EACR;AAEA,EAAA,MAAM,iBACJ,MAAM,oBAAA;AAAA,IAAqB,MACzBA,OAAM,MAAA,CAAO,IAAA;AAAA,MACX,IAAI,8BAAA,CAA+B;AAAA,QACjC,MAAA,EAAQ,MAAA;AAAA,QACR,GAAA,EAAK,GAAA;AAAA,QACL,QAAA,EAAU,QAAA;AAAA,QACV,eAAA,EAAiB,EAAE,KAAA,EAAO,aAAA;AAAc,OACzC;AAAA;AACH,GACF;AAEF,EAAA,MAAM,OAAO,MAAM,gCAAA;AAAA,IACjBA,MAAAA,CAAM,MAAA;AAAA,IACN,MAAA;AAAA,IACA;AAAA,GACF;AACA,EAAA,MAAM,YAAY,MAAM,uBAAA,CAAwBA,MAAAA,CAAM,MAAA,EAAQ,QAAQ,GAAA,EAAK;AAAA,IACzE,MAAA;AAAA,IACA,KAAA,EAAAA,MAAAA;AAAA,IACA,MAAA;AAAA,IACA,IAAA,EAAM;AAAA,MACJ,GAAG,IAAA;AAAA,MACH,IAAA,EAAM,IAAA,CAAK,IAAA,IAAQ,cAAA,CAAe;AAAA,KACpC;AAAA,IACA,QAAA;AAAA,IACA,GAAA,EAAKA,OAAM,MAAA,CAAO;AAAA,GACnB,CAAA;AAED,EAAA,OAAO,EAAE,GAAG,SAAA,EAAW,QAAA,EAAS;AAClC;AAEO,IAAM,iBAAA,GAAoB,gBAAA;AAAA,EAC/BM,aAAAA,CAAc,iBAAA;AAAA,EACd,EAAE,MAAA,EAAQ,MAAA,EAAQ,IAAA,EAAM,2BAAA,EAA4B;AAAA,EACpD,OAAO,GAAA,KAAQ;AACb,IAAA,OAAO,cAAA,CAAe,IAAI,OAAA,CAAQ,MAAA,EAAQ,IAAI,IAAA,EAAM,GAAA,CAAI,QAAQ,OAAO,CAAA;AAAA,EACzE;AACF,CAAA;AClGA,eAAe,mBAAA,CACb,MAAA,EACA,KAAA,EACA,OAAA,EACgC;AAChC,EAAA,MAAM,QAAA,GAAW,IAAA,CAAK,KAAA,CAAM,KAAA,CAAM,QAAQ,CAAA;AAC1C,EAAA,MAAM,WAAW,KAAA,CAAM,QAAA;AACvB,EAAA,MAAM,EAAE,OAAAN,MAAAA,EAAO,GAAA,EAAK,QAAQ,QAAA,EAAU,GAAA,EAAK,MAAA,EAAO,GAAI,MAAM,gBAAA;AAAA,IAC1D,MAAA;AAAA,IACA;AAAA,MACE,OAAO,KAAA,CAAM,KAAA;AAAA,MACb,QAAA;AAAA,MACA,QAAA;AAAA,MACA,aAAa,KAAA,CAAM,WAAA;AAAA,MACnB,UAAU,KAAA,CAAM;AAAA,KAClB;AAAA,IACA,OAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAA,MAAM,OAAA,CAAQA,MAAAA,CAAM,MAAA,CAAO,KAAA,EAAO;AAAA,IAChC,GAAG,MAAA;AAAA,IACH,IAAA,EAAM;AAAA,MACJ,IAAA,EAAM,QAAA;AAAA,MACN,IAAA,EAAM,QAAA;AAAA,MACN,MAAM,KAAA,CAAM;AAAA,KACd;AAAA,IACA,QAAA;AAAA,IACA,gBAAgB,KAAA,CAAM,QAAA;AAAA,IACtB,GAAA;AAAA,IACA,OAAA,EAASA,OAAM,MAAA,CAAO;AAAA,GACvB,CAAA;AAED,EAAA,MAAM,EAAE,QAAA,EAAS,GAAK,MAAMA,OAAM,MAAA,CAAO,IAAA;AAAA,IACvC,IAAI,4BAAA,CAA6B;AAAA,MAC/B,MAAA,EAAQ,MAAA;AAAA,MACR,GAAA,EAAK,GAAA;AAAA,MACL,aAAa,KAAA,CAAM,WAAA;AAAA,MACnB,kBAAA,EAAoBS,wBAAwB,QAAQ,CAAA;AAAA,MACpD,QAAA,EAAU,QAAA;AAAA,MACV,GAAA,EAAK;AAAA,KACN;AAAA,GACH;AAEA,EAAA,IAAI,CAAC,QAAA,EAAU;AACb,IAAA,MAAM,OAAO,aAAA,EAAc;AAAA,EAC7B;AAEA,EAAA,MAAM,gBAAA;AAAA,IACJT,MAAAA,CAAM,OAAO,SAAA,CAAU,MAAA;AAAA,IACvB;AAAA,MACE,GAAG,MAAA;AAAA,MACH,QAAA,EAAU,QAAA;AAAA,MACV,IAAA,EAAM;AAAA,QACJ,IAAA,EAAM,QAAA;AAAA,QACN,IAAA,EAAM,QAAA;AAAA,QACN,MAAM,KAAA,CAAM;AAAA,OACd;AAAA,MACA,QAAA;AAAA,MACA,gBAAgB,KAAA,CAAM,QAAA;AAAA,MACtB,GAAA;AAAA,MACA,OAAA,EAASA,OAAM,MAAA,CAAO;AAAA,KACxB;AAAA,IACA;AAAA,GACF;AAEA,EAAA,OAAO,EAAE,MAAA,EAAQ,GAAA,EAAK,QAAA,EAAU,QAAA,EAAS;AAC3C;AAEO,IAAM,aAAA,GAAgB,gBAAA;AAAA,EAC3BM,aAAAA,CAAc,aAAA;AAAA,EACd,EAAE,MAAA,EAAQ,MAAA,EAAQ,IAAA,EAAM,uBAAA,EAAwB;AAAA,EAChD,OAAO,GAAA,KAAQ;AACb,IAAA,MAAM,SAAS,MAAM,mBAAA;AAAA,MACnB,IAAI,OAAA,CAAQ,MAAA;AAAA,MACZ,GAAA,CAAI,IAAA;AAAA,MACJ,IAAI,OAAA,CAAQ;AAAA,KACd;AACA,IAAA,GAAA,CAAI,UAAU,GAAG,CAAA;AACjB,IAAA,OAAO,MAAA;AAAA,EACT;AACF,CAAA;AClFA,eAAe,eAAA,CACb,MAAA,EACA,KAAA,EACA,OAAA,EACqC;AACrC,EAAA,MAAM,EAAE,KAAA,EAAAN,MAAAA,EAAO,KAAK,MAAA,EAAQ,MAAA,KAAW,MAAM,gBAAA;AAAA,IAC3C,MAAA;AAAA,IACA,KAAA;AAAA,IACA,OAAA;AAAA,IACA;AAAA,GACF;AACA,EAAA,MAAM,WAAW,KAAA,CAAM,QAAA;AAEvB,EAAA,MAAM,OAAA,CAAQA,MAAAA,CAAM,MAAA,CAAO,SAAA,CAAU,KAAA,EAAO;AAAA,IAC1C,GAAG,MAAA;AAAA,IACH,QAAA;AAAA,IACA,MAAA,EAAQ;AAAA,GACT,CAAA;AAED,EAAA,MAAM,MAAA,GAAS,MAAM,YAAA,CAAaA,MAAAA,CAAM,QAAQ,EAAE,MAAA,EAAQ,GAAA,EAAK,QAAA,EAAU,CAAA;AAEzE,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,OAAA,CAAQ,CAAC,CAAA,KAAM;AAClC,IAAA,IAAI,EAAE,UAAA,IAAc,IAAA,IAAQ,EAAE,UAAA,GAAa,CAAA,SAAU,EAAC;AACtD,IAAA,OAAO;AAAA,MACL;AAAA,QACE,YAAY,CAAA,CAAE,UAAA;AAAA,QACd,IAAA,EAAM,EAAE,IAAA,IAAQ,CAAA;AAAA,QAChB,OAAO,CAAA,CAAE,IAAA,IAAQ,EAAA,EAAI,OAAA,CAAQ,MAAM,EAAE;AAAA;AACvC,KACF;AAAA,EACF,CAAC,CAAA;AAED,EAAA,MAAM,gBAAA;AAAA,IACJA,MAAAA,CAAM,OAAO,SAAA,CAAU,MAAA;AAAA,IACvB;AAAA,MACE,GAAG,MAAA;AAAA,MACH,QAAA;AAAA,MACA;AAAA,KACF;AAAA,IACA;AAAA,GACF;AAEA,EAAA,OAAO,EAAE,KAAA,EAAM;AACjB;AAEO,IAAM,kBAAA,GAAqB,gBAAA;AAAA,EAChCM,aAAAA,CAAc,kBAAA;AAAA,EACd,EAAE,MAAA,EAAQ,KAAA,EAAO,KAAA,EAAO,6BAAA,EAA8B;AAAA,EACtD,OAAO,GAAA,KAAQ;AACb,IAAA,OAAO,eAAA,CAAgB,IAAI,OAAA,CAAQ,MAAA,EAAQ,IAAI,KAAA,EAAO,GAAA,CAAI,QAAQ,OAAO,CAAA;AAAA,EAC3E;AACF,CAAA;AC/CA,eAAe,cAAA,CACb,MAAA,EACA,KAAA,EACA,OAAA,EACgC;AAChC,EAAA,MAAM,EAAE,KAAA,EAAAN,MAAAA,EAAO,KAAK,MAAA,EAAQ,MAAA,KAAW,MAAM,gBAAA;AAAA,IAC3C,MAAA;AAAA,IACA,KAAA;AAAA,IACA,OAAA;AAAA,IACA;AAAA,GACF;AACA,EAAA,MAAM,WAAW,KAAA,CAAM,QAAA;AACvB,EAAA,MAAM,aAAa,KAAA,CAAM,UAAA;AACzB,EAAA,MAAM,SAAA,GAAY,kBAAA;AAAA,IAChBA,OAAM,MAAA,CAAO,SAAA;AAAA,IACb,MAAA,CAAO;AAAA,GACT;AACA,EAAA,MAAM,QAAA,GAAW,IAAA,CAAK,KAAA,CAAM,KAAA,CAAM,QAAQ,CAAA;AAE1C,EAAA,MAAM,OAAA,CAAQA,MAAAA,CAAM,MAAA,CAAO,SAAA,CAAU,KAAA,EAAO;AAAA,IAC1C,GAAG,MAAA;AAAA,IACH,QAAA;AAAA,IACA,MAAA,EAAQ,MAAA;AAAA,IACR,UAAA;AAAA,IACA;AAAA,GACD,CAAA;AAED,EAAA,MAAM,WAAA,GAAcA,OAAM,MAAA,CAAO,WAAA;AACjC,EAAA,uBAAA,CAAwB,aAAa,QAAQ,CAAA;AAC7C,EAAA,IAAI,OAAO,gBAAgB,QAAA,EAAU;AACnC,IAAA,MAAM,MAAA,GAAS,MAAM,YAAA,CAAaA,MAAAA,CAAM,QAAQ,EAAE,MAAA,EAAQ,GAAA,EAAK,QAAA,EAAU,CAAA;AACzE,IAAA,uBAAA;AAAA,MACE,WAAA;AAAA,MACA,mBAAA,CAAoB,MAAA,EAAQ,UAAU,CAAA,GAAI;AAAA,KAC5C;AAAA,EACF;AAEA,EAAA,MAAM,MAAM,MAAMW,YAAAA;AAAA,IAChBX,MAAAA,CAAM,MAAA;AAAA,IACN,IAAI,iBAAA,CAAkB;AAAA,MACpB,MAAA,EAAQ,MAAA;AAAA,MACR,GAAA,EAAK,GAAA;AAAA,MACL,QAAA,EAAU,QAAA;AAAA,MACV,UAAA,EAAY,UAAA;AAAA,MACZ,aAAA,EAAe;AAAA,KAChB,CAAA;AAAA,IACD;AAAA,MACE,SAAA;AAAA,MACA,eAAA,kBAAiB,IAAI,GAAA,CAAI,CAAC,gBAAgB,CAAC;AAAA;AAC7C,GACF;AAEA,EAAA,OAAO;AAAA,IACL,GAAA;AAAA,IACA,UAAA;AAAA,IACA,QAAA;AAAA,IACA,MAAA;AAAA,IACA,SAAA;AAAA,IACA;AAAA,GACF;AACF;AAEO,IAAM,aAAA,GAAgB,gBAAA;AAAA,EAC3BM,aAAAA,CAAc,aAAA;AAAA,EACd,EAAE,MAAA,EAAQ,MAAA,EAAQ,IAAA,EAAM,2BAAA,EAA4B;AAAA,EACpD,OAAO,GAAA,KAAQ;AACb,IAAA,OAAO,cAAA,CAAe,IAAI,OAAA,CAAQ,MAAA,EAAQ,IAAI,IAAA,EAAM,GAAA,CAAI,QAAQ,OAAO,CAAA;AAAA,EACzE;AACF,CAAA;AClEA,SAAS,mBACP,QAAA,EACwB;AACxB,EAAA,IAAI,CAAC,QAAA,EAAU,OAAO,EAAC;AACvB,EAAA,MAAM,SAAiC,EAAC;AACxC,EAAA,KAAA,MAAW,CAAC,CAAA,EAAG,CAAC,KAAK,MAAA,CAAO,OAAA,CAAQ,QAAQ,CAAA,EAAG;AAC7C,IAAA,MAAA,CAAO,CAAA,WAAA,EAAc,CAAC,CAAA,CAAE,CAAA,GAAI,CAAA;AAAA,EAC9B;AACA,EAAA,OAAO,MAAA;AACT;AAEA,eAAe,YAAA,CACb,MAAA,EACA,KAAA,EACA,OAAA,EACgC;AAChC,EAAA,MAAM,QAAA,GAAW,IAAA,CAAK,KAAA,CAAM,KAAA,CAAM,QAAQ,CAAA;AAC1C,EAAA,MAAM,WAAW,KAAA,CAAM,QAAA;AACvB,EAAA,MAAM,EAAE,OAAAN,MAAAA,EAAO,GAAA,EAAK,QAAQ,QAAA,EAAU,GAAA,EAAK,MAAA,EAAO,GAAI,MAAM,gBAAA;AAAA,IAC1D,MAAA;AAAA,IACA;AAAA,MACE,OAAO,KAAA,CAAM,KAAA;AAAA,MACb,QAAA;AAAA,MACA,QAAA;AAAA,MACA,aAAa,KAAA,CAAM,WAAA;AAAA,MACnB,UAAU,KAAA,CAAM;AAAA,KAClB;AAAA,IACA,OAAA;AAAA,IACA;AAAA,GACF;AACA,EAAA,MAAM,MAAA,GAASA,MAAAA,CAAM,MAAA,CAAO,MAAA,IAAU,MAAA;AACtC,EAAA,IAAIA,MAAAA,CAAM,MAAA,CAAO,QAAA,IAAY,CAAC,MAAM,QAAA,EAAU;AAC5C,IAAA,MAAM,MAAA,CAAO,gBAAgB,qCAAqC,CAAA;AAAA,EACpE;AACA,EAAA,IAAI,MAAA,KAAW,MAAA,IAAU,QAAA,GAAW,wBAAA,EAA0B;AAC5D,IAAA,MAAM,MAAA,CAAO,eAAA;AAAA,MACX,8BAA8B,wBAAwB,CAAA,8DAAA;AAAA,KACxD;AAAA,EACF;AAEA,EAAA,MAAM,SAAA,GAAY,kBAAA;AAAA,IAChBA,OAAM,MAAA,CAAO,SAAA;AAAA,IACb,MAAA,CAAO;AAAA,GACT;AACA,EAAA,MAAM,WAAA,GAAc,MAAM,WAAA,IAAe,0BAAA;AACzC,EAAA,MAAM,OAAA,GAAU;AAAA,IACd,GAAG,MAAA;AAAA,IACH,IAAA,EAAM;AAAA,MACJ,IAAA,EAAM,QAAA;AAAA,MACN,IAAA,EAAM,QAAA;AAAA,MACN,MAAM,KAAA,CAAM;AAAA,KACd;AAAA,IACA,QAAA;AAAA,IACA,gBAAgB,KAAA,CAAM,QAAA;AAAA,IACtB,GAAA;AAAA,IACA,OAAA,EAASA,OAAM,MAAA,CAAO;AAAA,GACxB;AAEA,EAAA,MAAM,OAAA,CAAQA,MAAAA,CAAM,MAAA,CAAO,KAAA,EAAO,OAAO,CAAA;AAEzC,EAAA,IAAI,WAAW,KAAA,EAAO;AACpB,IAAA,MAAM,UAAA,GAAqC;AAAA,MACzC,cAAA,EAAgB,WAAA;AAAA,MAChB,GAAG,mBAAmB,QAAQ,CAAA;AAAA,MAC9B,qBAAA,EAAuBS,wBAAwB,QAAQ,CAAA;AAAA,MACvD,GAAI,MAAM,QAAA,GAAW,EAAE,yBAAyB,KAAA,CAAM,QAAA,KAAa;AAAC,KACtE;AAEA,IAAA,MAAMG,OAAM,MAAMD,YAAAA;AAAA,MAChBX,MAAAA,CAAM,MAAA;AAAA,MACN,IAAIa,gBAAAA,CAAiB;AAAA,QACnB,MAAA,EAAQ,MAAA;AAAA,QACR,GAAA,EAAK,GAAA;AAAA,QACL,WAAA,EAAa,WAAA;AAAA,QACb,GAAA,EAAK,GAAA;AAAA,QACL,QAAA,EAAU,QAAA;AAAA,QACV,kBAAA,EAAoBJ,wBAAwB,QAAQ,CAAA;AAAA,QACpD,aAAA,EAAe,QAAA;AAAA,QACf,GAAI,KAAA,CAAM,QAAA,GACN,EAAE,cAAA,EAAgB,MAAM,QAAA,EAAU,iBAAA,EAAmB,QAAA,EAAS,GAC9D;AAAC,OACN,CAAA;AAAA,MACD;AAAA,QACE,SAAA;AAAA,QACA,eAAA,sBAAqB,GAAA,CAAI;AAAA,UACvB,gBAAA;AAAA,UACA,GAAI,KAAA,CAAM,QAAA,GAAW,CAAC,uBAAuB,IAAI;AAAC,SACnD;AAAA;AACH,KACF;AAEA,IAAA,MAAM,gBAAA;AAAA,MACJT,OAAM,MAAA,CAAO,WAAA;AAAA,MACb;AAAA,QACE,GAAG,OAAA;AAAA,QACH,GAAA,EAAAY,IAAAA;AAAA,QACA;AAAA,OACF;AAAA,MACA;AAAA,KACF;AAEA,IAAA,OAAO;AAAA,MACL,MAAA;AAAA,MACA,GAAA;AAAA,MACA,GAAA,EAAAA,IAAAA;AAAA,MACA,OAAA,EAAS,UAAA;AAAA,MACT,SAAA;AAAA,MACA,MAAA,EAAQ;AAAA,KACV;AAAA,EACF;AAEA,EAAA,MAAM,MAAA,GAAiC;AAAA,IACrC,GAAA;AAAA,IACA,cAAA,EAAgB,WAAA;AAAA,IAChB,qBAAA,EAAuBH,wBAAwB,QAAQ,CAAA;AAAA,IACvD,GAAG,mBAAmB,QAAQ,CAAA;AAAA,IAC9B,GAAI,MAAM,QAAA,GAAW,EAAE,yBAAyB,KAAA,CAAM,QAAA,KAAa;AAAC,GACtE;AAEA,EAAA,MAAM,EAAE,GAAA,EAAK,MAAA,EAAQ,YAAA,KAAiB,MAAM,mBAAA;AAAA,IAC1CT,MAAAA,CAAM,MAAA;AAAA,IACN;AAAA,MACE,MAAA,EAAQ,MAAA;AAAA,MACR,GAAA,EAAK,GAAA;AAAA,MACL,YAAY,CAAC,CAAC,sBAAA,EAAwB,QAAA,EAAU,QAAQ,CAAC,CAAA;AAAA,MACzD,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS;AAAA;AACX,GACF;AAEA,EAAA,MAAM,gBAAA;AAAA,IACJA,OAAM,MAAA,CAAO,WAAA;AAAA,IACb;AAAA,MACE,GAAG,OAAA;AAAA,MACH,GAAA;AAAA,MACA;AAAA,KACF;AAAA,IACA;AAAA,GACF;AAEA,EAAA,OAAO;AAAA,IACL,MAAA;AAAA,IACA,GAAA;AAAA,IACA,GAAA;AAAA,IACA,MAAA,EAAQ,YAAA;AAAA,IACR,SAAA;AAAA,IACA,MAAA,EAAQ;AAAA,GACV;AACF;AAEO,IAAM,MAAA,GAAS,gBAAA;AAAA,EACpBM,aAAAA,CAAc,MAAA;AAAA,EACd,EAAE,MAAA,EAAQ,MAAA,EAAQ,IAAA,EAAM,gBAAA,EAAiB;AAAA,EACzC,OAAO,GAAA,KAAQ;AACb,IAAA,OAAO,YAAA,CAAa,IAAI,OAAA,CAAQ,MAAA,EAAQ,IAAI,IAAA,EAAM,GAAA,CAAI,QAAQ,OAAO,CAAA;AAAA,EACvE;AACF,CAAA;;;ACnKO,IAAM,aAAA,GAAgB;AAAA,EAC3B,MAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA;AAAA,EACA,IAAA;AAAA,EACA,MAAA,EAAQ,YAAA;AAAA,EACR,WAAA;AAAA,EACA,aAAA;AAAA,EACA,aAAA;AAAA,EACA,kBAAA;AAAA,EACA,iBAAA;AAAA,EACA;AACF,CAAA;AAIO,IAAM,sBAAsB,MAAA,CAAO,IAAA;AAAA,EACxC;AACF,CAAA;;;ACjBO,SAAS,cACX,KAAA,EACkC;AACrC,EAAA,OAAO,OAAO,OAAA,KAAY;AACxB,IAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,MAAA,IAAI,IAAA,EAAM,MAAM,IAAA,CAAK,OAAO,CAAA;AAAA,IAC9B;AAAA,EACF,CAAA;AACF;;;ACZO,IAAM,iBAAA,GAAoB;AAAA,EAC/B,MAAA,EAAQ,CAAC,OAAA,EAAS,aAAA,EAAe,gBAAgB,aAAa,CAAA;AAAA,EAC9D,QAAA,EAAU,CAAC,OAAA,EAAS,aAAa,CAAA;AAAA,EACjC,MAAA,EAAQ,CAAC,OAAA,EAAS,WAAW;AAC/B,CAAA;AASO,IAAM,mBAAA,GAAsB;AAAA,EACjC,QAAA;AAAA,EACA,OAAA;AAAA,EACA,SAAA;AAAA,EACA;AACF,CAAA;AAGO,IAAM,2BAAA,GAA8B;AAAA,EACzC,MAAA,EAAQ,CAAC,aAAA,EAAe,aAAa,CAAA;AAAA,EACrC,QAAA,EAAU,CAAC,aAAa,CAAA;AAAA,EACxB,MAAA,EAAQ,CAAC,WAAW;AACtB,CAAA;AAEO,IAAM,6BAAA,GAAgC;AAAA,EAC3C,QAAA;AAAA,EACA,SAAA;AAAA,EACA;AACF,CAAA;;;AC2EO,IAAM,mBAAA,GAAsB;AAAA,EACjC,SAAA;AAAA,EACA,KAAA;AAAA,EACA,SAAA;AAAA,EACA,WAAA;AAAA,EACA,cAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA;AAAA,EACA,UAAA;AAAA,EACA,SAAA;AAAA,EACA,MAAA;AAAA,EACA,QAAA;AAAA,EACA,aAAA;AAAA,EACA,KAAA;AAAA,EACA;AACF,CAAA;;;AC5GA,SAAS,cAAA,CACP,WAAA,EACA,QAAA,EACA,KAAA,GAAwC,eAAA,EACpB;AACpB,EAAA,MAAM,WACJ,KAAA,KAAU,YAAA,GACN,CAAC,QAAA,EAAU,GAAG,WAAW,CAAA,GACzB,CAAC,GAAG,aAAa,QAAQ,CAAA,EAC7B,OAAO,CAAC,CAAA,KAAgC,KAAK,IAAI,CAAA;AACnD,EAAA,IAAI,OAAA,CAAQ,MAAA,KAAW,CAAA,EAAG,OAAO,MAAA;AACjC,EAAA,IAAI,OAAA,CAAQ,MAAA,KAAW,CAAA,EAAG,OAAO,QAAQ,CAAC,CAAA;AAC1C,EAAA,OAAO,UAAA,CAAW,GAAG,OAAO,CAAA;AAC9B;AAEA,SAAS,UAAA,CACP,MACA,OAAA,EACA,WAAA,EACA,MACA,aAAA,mBAAqC,IAAI,KAAI,EAC1C;AACH,EAAA,MAAM,MAAA,GAAkB,EAAE,GAAI,WAAA,EAAwB;AACtD,EAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,IAAA,MAAM,IAAA,GAAO,cAAA;AAAA,MACX,OAAA,CAAQ,IAAI,CAAC,MAAA,KAAW,KAAK,MAAM,CAAA,GAAI,GAAG,CAAC,CAAA;AAAA,MAC1C,YAAwB,GAAG,CAAA;AAAA,MAC5B,aAAA,CAAc,GAAA,CAAI,GAAG,CAAA,GAAI,YAAA,GAAe;AAAA,KAC1C;AACA,IAAA,IAAI,IAAA,KAAS,MAAA,EAAW,MAAA,CAAO,GAAG,CAAA,GAAI,IAAA;AAAA,EACxC;AACA,EAAA,OAAO,MAAA;AACT;AAEA,SAAS,iBAAA,CACPN,QACA,OAAA,EACe;AACf,EAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,MAAA,CAAO,CAAC,CAAA,KAAM,CAACA,MAAAA,CAAM,gBAAA,CAAiB,GAAA,CAAI,CAAA,CAAE,EAAE,CAAC,CAAA;AAEtE,EAAA,MAAMG,OAAAA,GAAS,SAAA,CAAUH,MAAAA,CAAM,MAAM,CAAA,GACjC;AAAA,IACE,GAAG,UAAA;AAAA,MACD,iBAAA,CAAkB,MAAA;AAAA,MAClB,MAAA;AAAA,MACAA,MAAAA,CAAM,MAAA;AAAA,MACN,CAAC,CAAA,KAAM,CAAA,CAAE,KAAA,EAAO,MAAA;AAAA,MAChB,IAAI,GAAA,CAAI,2BAAA,CAA4B,MAAM;AAAA,KAC5C;AAAA,IACA,SAAA,EAAW,SAAA,CAAUA,MAAAA,CAAM,MAAA,CAAO,SAAS,CAAA,GACvC,UAAA;AAAA,MACE,mBAAA;AAAA,MACA,MAAA;AAAA,MACAA,OAAM,MAAA,CAAO,SAAA;AAAA,MACb,CAAC,CAAA,KAAM,CAAA,CAAE,KAAA,EAAO,MAAA,EAAQ,SAAA;AAAA,MACxB,IAAI,IAAI,6BAA6B;AAAA,KACvC,GACAA,OAAM,MAAA,CAAO;AAAA,MAEnBA,MAAAA,CAAM,MAAA;AAEV,EAAA,OAAO;AAAA,IACL,GAAGA,MAAAA;AAAA,IACH,MAAA,EAAAG,OAAAA;AAAA,IACA,QAAA,EAAU,SAAA,CAAUH,MAAAA,CAAM,QAAQ,CAAA,GAC9B,UAAA;AAAA,MACE,iBAAA,CAAkB,QAAA;AAAA,MAClB,MAAA;AAAA,MACAA,MAAAA,CAAM,QAAA;AAAA,MACN,CAAC,CAAA,KAAM,CAAA,CAAE,KAAA,EAAO,QAAA;AAAA,MAChB,IAAI,GAAA,CAAI,2BAAA,CAA4B,QAAQ;AAAA,QAE9CA,MAAAA,CAAM,QAAA;AAAA,IACV,MAAA,EAAQ,SAAA,CAAUA,MAAAA,CAAM,MAAM,CAAA,GAC1B,UAAA;AAAA,MACE,iBAAA,CAAkB,MAAA;AAAA,MAClB,MAAA;AAAA,MACAA,MAAAA,CAAM,MAAA;AAAA,MACN,CAAC,CAAA,KAAM,CAAA,CAAE,KAAA,EAAO,MAAA;AAAA,MAChB,IAAI,GAAA,CAAI,2BAAA,CAA4B,MAAM;AAAA,QAE5CA,MAAAA,CAAM;AAAA,GACZ;AACF;AAYO,SAAS,aAGd,MAAA,EAA4D;AAC5D,EAAA,MAAM,OAAA,GAAU,MAAA,CAAO,OAAA,IAAW,EAAC;AACnC,EAAA,MAAM,IAAA,uBAAW,GAAA,EAAY;AAC7B,EAAA,MAAM,IAAA,uBAAW,GAAA,EAA2B;AAC5C,EAAA,MAAM,UAAU,EAAC;AACjB,EAAA,MAAM,SAAA,GAAY,CAAC,EAAA,KAAe,IAAA,CAAK,IAAI,EAAE,CAAA;AAE7C,EAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,IAAA,IAAK,mBAAA,CAA0C,QAAA,CAAS,MAAA,CAAO,EAAE,CAAA,EAAG;AAClE,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,WAAA,EAAc,OAAO,EAAE,CAAA,6DAAA;AAAA,OACzB;AAAA,IACF;AACA,IAAA,IAAI,IAAA,CAAK,GAAA,CAAI,MAAA,CAAO,EAAE,CAAA,EAAG;AACvB,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,8BAAA,EAAiC,OAAO,EAAE,CAAA,iCAAA;AAAA,OAC5C;AAAA,IACF;AACA,IAAA,IAAA,CAAK,GAAA,CAAI,OAAO,EAAE,CAAA;AAClB,IAAA,IAAA,CAAK,GAAA,CAAI,MAAA,CAAO,EAAA,EAAI,MAAM,CAAA;AAAA,EAC5B;AAEA,EAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,IAAA,KAAA,MAAW,GAAA,IAAO,MAAA,CAAO,SAAA,IAAa,EAAC,EAAG;AACxC,MAAA,IAAI,CAAC,IAAA,CAAK,GAAA,CAAI,GAAG,CAAA,EAAG;AAClB,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,CAAA,QAAA,EAAW,MAAA,CAAO,EAAE,CAAA,cAAA,EAAiB,GAAG,CAAA,2BAAA;AAAA,SAC1C;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,EAAA,MAAM,QAAA,uBAAe,GAAA,EAAY;AACjC,EAAA,MAAM,OAAA,uBAAc,GAAA,EAAY;AAChC,EAAA,SAAS,KAAA,CAAM,IAAY,KAAA,EAAiB;AAC1C,IAAA,IAAI,OAAA,CAAQ,GAAA,CAAI,EAAE,CAAA,EAAG;AACrB,IAAA,IAAI,QAAA,CAAS,GAAA,CAAI,EAAE,CAAA,EAAG;AACpB,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,qCAAA,EAAwC,CAAC,GAAG,KAAA,EAAO,EAAE,CAAA,CAAE,IAAA,CAAK,MAAM,CAAC,CAAA,CAAA;AAAA,OACrE;AAAA,IACF;AACA,IAAA,QAAA,CAAS,IAAI,EAAE,CAAA;AACf,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,GAAA,CAAI,EAAE,CAAA;AAC1B,IAAA,KAAA,MAAW,GAAA,IAAO,MAAA,EAAQ,SAAA,IAAa,EAAC,EAAG;AACzC,MAAA,KAAA,CAAM,GAAA,EAAK,CAAC,GAAG,KAAA,EAAO,EAAE,CAAC,CAAA;AAAA,IAC3B;AACA,IAAA,QAAA,CAAS,OAAO,EAAE,CAAA;AAClB,IAAA,OAAA,CAAQ,IAAI,EAAE,CAAA;AAAA,EAChB;AACA,EAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,IAAA,KAAA,CAAM,MAAA,CAAO,EAAA,EAAI,EAAE,CAAA;AAAA,EACrB;AAEA,EAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,IAAA,IAAI,MAAA,CAAO,YAAY,MAAA,EAAW;AAChC,MAAC,OAAA,CAAoC,MAAA,CAAO,EAAE,CAAA,GAAI,MAAA,CAAO,OAAA;AAAA,IAC3D;AAAA,EACF;AAEA,EAAA,MAAM,qBAAqB,IAAI,GAAA,CAAY,MAAA,CAAO,MAAA,CAAOM,aAAa,CAAC,CAAA;AACvE,EAAA,MAAM,gCAAgB,IAAI,GAAA,CAAY,CAAC,GAAG,mBAAA,EAAqB,WAAW,CAAC,CAAA;AAC3E,EAAA,MAAM,gBAAA,uBAAuB,GAAA,EAAY;AACzC,EAAA,MAAM,YAAsC,EAAC;AAE7C,EAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,IAAA,KAAA,MAAW,CAAC,IAAA,EAAM,QAAQ,CAAA,IAAK,MAAA,CAAO,QAAQ,MAAA,CAAO,SAAA,IAAa,EAAE,CAAA,EAAG;AACrE,MAAA,IAAI,aAAA,CAAc,GAAA,CAAI,IAAI,CAAA,IAAK,QAAQ,SAAA,EAAW;AAChD,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,CAAA,QAAA,EAAW,MAAA,CAAO,EAAE,CAAA,YAAA,EAAe,IAAI,CAAA,qCAAA;AAAA,SACzC;AAAA,MACF;AACA,MAAA,MAAM,OAAO,QAAA,CAAS,IAAA;AACtB,MAAA,IAAI,OAAO,IAAA,KAAS,QAAA,IAAY,CAAC,IAAA,CAAK,UAAA,CAAW,GAAG,CAAA,EAAG;AACrD,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,CAAA,QAAA,EAAW,MAAA,CAAO,EAAE,CAAA,YAAA,EAAe,IAAI,CAAA,2BAAA;AAAA,SACzC;AAAA,MACF;AACA,MAAA,IAAI,kBAAA,CAAmB,GAAA,CAAI,IAAI,CAAA,EAAG;AAChC,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,CAAA,QAAA,EAAW,MAAA,CAAO,EAAE,CAAA,YAAA,EAAe,IAAI,CAAA,6BAAA;AAAA,SACzC;AAAA,MACF;AACA,MAAA,MAAM,OAAA,GAAU,KAAA,CAAM,OAAA,CAAQ,QAAA,CAAS,OAAA,CAAQ,MAAM,CAAA,GACjD,QAAA,CAAS,OAAA,CAAQ,MAAA,GACjB,CAAC,QAAA,CAAS,QAAQ,MAAM,CAAA;AAC5B,MAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,QAAA,MAAM,QAAA,GAAW,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI,IAAI,CAAA,CAAA;AAClC,QAAA,IAAI,gBAAA,CAAiB,GAAA,CAAI,QAAQ,CAAA,EAAG;AAClC,UAAA,MAAM,IAAI,KAAA,CAAM,CAAA,0BAAA,EAA6B,QAAQ,CAAA,CAAA,CAAG,CAAA;AAAA,QAC1D;AACA,QAAA,gBAAA,CAAiB,IAAI,QAAQ,CAAA;AAAA,MAC/B;AACA,MAAA,SAAA,CAAU,IAAI,CAAA,GAAI,QAAA;AAAA,IACpB;AAAA,EACF;AAEA,EAAA,MAAM,EAAE,OAAA,EAAS,KAAA,EAAO,GAAG,MAAK,GAAI,MAAA;AACpC,EAAA,MAAM,UAAA,GAAa,gBAAgB,IAAI,CAAA;AAEvC,EAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,IAAA,MAAA,CAAO,IAAA,GAAO,EAAE,MAAA,EAAQ,IAAA,EAAM,WAAW,CAAA;AAAA,EAC3C;AACA,EAAA,MAAM,SAAwC,EAAC;AAC/C,EAAA,KAAA,MAAW,CAAC,IAAA,EAAMN,MAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,UAAU,CAAA,EAAG;AACtD,IAAA,MAAA,CAAO,IAAI,CAAA,GAAI,iBAAA,CAAkBA,MAAAA,EAAO,OAAO,CAAA;AAAA,EACjD;AAEA,EAAA,MAAM,KAAA,GAAQ,cAAA;AAAA,IACZ,QAAQ,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,OAAO,KAAe,CAAA;AAAA,IAC3C,IAAA,CAAK;AAAA,GACP;AAEA,EAAA,MAAM,MAAA,GAAgC;AAAA,IACpC,GAAG,IAAA;AAAA,IACH,MAAA;AAAA,IACA,GAAI,KAAA,KAAU,MAAA,GAAY,EAAE,KAAA,KAAU;AAAC,GACzC;AAEA,EAAA,OAAO;AAAA,IACL,MAAA,EAAQ,MAAA;AAAA,IACR,OAAA;AAAA,IACA,SAAA;AAAA,IACA;AAAA,GACF;AACF;;;ACjPO,SAAS,aAKd,MAAA,EACyC;AACzC,EAAA,OAAO,MAAA;AACT;;;ACPO,SAAS,aAAA,CACd,WACA,OAAA,EACG;AACH,EAAA,MAAM,MAAM,EAAC;AAEb,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,QAAQ,KAAK,MAAA,CAAO,OAAA,CAAQ,SAAS,CAAA,EAAG;AACvD,IAAA,MAAM,KAAA,IAAS,OAAO,KAAA,GAAiC,EAAC,KAAM;AAC5D,MAAA,MAAM,UAAU,KAAA,CAAM,OAAA;AACtB,MAAA,MAAM,OAAA,GACH,KAAA,CAAM,OAAA,IAAmC,kBAAA,CAAmB,OAAO,CAAA;AACtE,MAAA,OAAO,QAAA,CAAS;AAAA,QACd,GAAG,KAAA;AAAA,QACH,OAAA,EAAS,WAAW,OAAA,CAAQ,OAAA;AAAA,QAC5B,OAAA;AAAA,QACA;AAAA,OACD,CAAA;AAAA,IACH,CAAA,CAAA;AAEA,IAAA,KAAA,CAAM,OAAO,QAAA,CAAS,IAAA;AACtB,IAAA,KAAA,CAAM,UAAU,QAAA,CAAS,OAAA;AACzB,IAAA,GAAA,CAAI,GAAc,CAAA,GAAI,KAAA;AAAA,EACxB;AAEA,EAAA,OAAO,GAAA;AACT;;;ACtBA,IAAM,aAAA,uBAAoB,GAAA,CAAI;AAAA,EAC5B,WAAA;AAAA,EACA,cAAA;AAAA,EACA,YAAA;AAAA,EACA,WAAA;AAAA,EACA;AACF,CAAC,CAAA;AAMD,SAAS,eAAA,CAAgB,OAAgB,MAAA,EAAsC;AAC7E,EAAA,IAAIC,UAAAA,CAAW,KAAK,CAAA,EAAG;AAEvB,EAAA,MAAM,OAAQ,KAAA,EAA6B,IAAA;AAC3C,EAAA,MAAM,MAAA,GAAS,aAAA,CAAc,MAAA,EAAQ,MAAM,CAAA;AAC3C,EAAA,IAAI,OAAO,IAAA,KAAS,QAAA,IAAY,aAAA,CAAc,GAAA,CAAI,IAAI,CAAA,EAAG;AACvD,IAAA,MAAM,UAAA,GAAa,MAAA,CAAO,cAAA,CAAe,IAAI,CAAA;AAC7C,IAAA,MAAA,CAAO,KAAA,GAAQ,UAAA,CAAW,OAAA,EAAS,KAAK,CAAA;AACxC,IAAA,MAAA,EAAQ,OAAA,GAAU,KAAA,EAAO,EAAE,CAAA;AAC3B,IAAA,MAAM,UAAA;AAAA,EACR;AAEA,EAAA,MAAA,CAAO,KAAA,GAAQ,iBAAiB,KAAA,GAAQ,KAAA,CAAM,UAAU,MAAA,CAAO,KAAK,GAAG,KAAK,CAAA;AAC5E,EAAA,MAAA,EAAQ,OAAA,GAAU,KAAA,EAAO,EAAE,CAAA;AAC3B,EAAA,MAAM,OAAO,aAAA,EAAc;AAC7B;AAMA,SAAS,uBACP,OAAA,EACyC;AACzC,EAAA,OAAO,OAAO,OAAA,KAAY;AACxB,IAAA,MAAM,QAAA,GAAW,MAAM,OAAA,CAAQ,OAAO,CAAA;AACtC,IAAA,IAAI,QAAA,CAAS,MAAA,KAAW,GAAA,EAAK,OAAO,QAAA;AACpC,IAAA,MAAM,WAAA,GAAc,QAAA,CAAS,OAAA,CAAQ,GAAA,CAAI,cAAc,CAAA,IAAK,EAAA;AAC5D,IAAA,IAAI,WAAA,CAAY,QAAA,CAAS,kBAAkB,CAAA,EAAG,OAAO,QAAA;AACrD,IAAA,OAAO,UAAA,CAAW,MAAA,CAAO,QAAA,EAAU,CAAA;AAAA,EACrC,CAAA;AACF;AAMO,SAAS,cAAA,CACd,WACA,GAAA,EACA;AACA,EAAA,MAAM,QAAA,GAAW,sBAAA;AAAA,IACf,GAAA,CAAI,OAAO,QAAA,IAAY;AAAA,GACzB;AAEA,EAAA,MAAM,MAAA,GAAS,aAAa,SAAA,EAAW;AAAA,IACrC,QAAA;AAAA,IACA,aAAA,EAAe,EAAE,MAAA,EAAQ,GAAA,CAAI,MAAA,EAAO;AAAA,IACpC,OAAA,EAAS,EAAE,QAAA,EAAU,IAAA,EAAK;AAAA,IAC1B,SAAS,CAAC,KAAA,KAAU,eAAA,CAAgB,KAAA,EAAO,IAAI,MAAM;AAAA,GACtD,CAAA;AAED,EAAA,OAAO;AAAA,IACL,SAAA,EAAW,cAAc,MAAA,CAAO,SAAA,EAAW,EAAE,MAAA,EAAQ,GAAA,CAAI,QAAQ,CAAA;AAAA,IACjE,OAAA,EAAS,sBAAA,CAAuB,MAAA,CAAO,OAAO;AAAA,GAChD;AACF;;;ACYO,SAAS,QAOd,MAAA,EACoC;AACpC,EAAA,MAAM;AAAA,IACJ,MAAA,EAAQ,QAAA;AAAA,IACR,OAAA;AAAA,IACA,SAAA;AAAA,IACA,SAAA,EAAW;AAAA,GACb,GAAI,aAAa,MAAM,CAAA;AAEvB,EAAA,MAAM,SAAA,GAAY,EAAE,GAAG,aAAA,EAAe,GAAG,eAAA,EAAgB;AACzD,EAAA,MAAM,SAAS,cAAA,CAAe,SAAA,EAAW,EAAE,MAAA,EAAQ,UAAU,CAAA;AAC7D,EAAA,MAAM,QAAQ,MAAA,CAAO,SAAA;AAErB,EAAA,MAAM,GAAA,GAAM;AAAA,IACV,GAAG,KAAA;AAAA,IACH,YAAY,KAAA,CAAM,WAAA;AAAA,IAClB,SAAA,EAAW;AAAA,MACT,MAAM,KAAA,CAAM,aAAA;AAAA,MACZ,UAAU,KAAA,CAAM,aAAA;AAAA,MAChB,WAAW,KAAA,CAAM,kBAAA;AAAA,MACjB,UAAU,KAAA,CAAM,iBAAA;AAAA,MAChB,OAAO,KAAA,CAAM;AAAA;AACf,GACF;AAEA,EAAA,OAAO;AAAA,IACL,SAAS,MAAA,CAAO,OAAA;AAAA,IAChB,GAAA;AAAA,IACA,OAAA;AAAA,IACA,SAAA;AAAA,IACA,YAAA,EAAca,cAAAA;AAAA,IACd,QAAQ,EAAC;AAAA,IACT,GAAA,EAAK,CAAC,KAAA,KAAU,SAAA,CAAU,UAAU,KAAK,CAAA;AAAA,IACzC,GAAG;AAAA,GACL;AACF;;;AC3GO,IAAM,cAAA,GAAiB,CAAC,QAAA,EAAU,UAAA,EAAY,QAAQ;AAOtD,IAAM,gBAAA,GAAmB,CAAC,GAAG,cAAA,EAAgB,WAAW","file":"index.js","sourcesContent":["/** Build a synthetic Request for server-side `api` calls. */\nexport function requestFromHeaders(headers?: HeadersInit): Request {\n return new Request(\"http://dimah-s3.local\", { headers });\n}\n","import {\n AbortMultipartUploadCommand,\n DeleteObjectCommand,\n type S3Client,\n} from \"@aws-sdk/client-s3\";\n\n/** Best-effort DeleteObject after a failed constraint check. */\nexport async function deleteObjectBestEffort(\n client: S3Client,\n bucket: string,\n key: string,\n): Promise<void> {\n try {\n await client.send(new DeleteObjectCommand({ Bucket: bucket, Key: key }));\n } catch {\n // Best-effort cleanup.\n }\n}\n\n/** Best-effort AbortMultipartUpload before assembly or after a failed complete. */\nexport async function abortMultipartBestEffort(\n client: S3Client,\n bucket: string,\n key: string,\n uploadId: string,\n): Promise<void> {\n try {\n await client.send(\n new AbortMultipartUploadCommand({\n Bucket: bucket,\n Key: key,\n UploadId: uploadId,\n }),\n );\n } catch {\n // Best-effort cleanup.\n }\n}\n","import {\n DimahS3Error,\n S3_ERROR_CODES,\n isAPIError,\n isDimahS3Error,\n isS3ErrorCode,\n} from \"@dimah-s3/core\";\nimport type { RouteOperation } from \"@/types/config\";\n\nexport {\n DimahS3Error,\n S3_ERROR_CODES,\n isAPIError,\n isDimahS3Error,\n isS3ErrorCode,\n};\n\n/** English API errors with stable codes for client-side localization. */\nexport const errors = {\n notFound: () => DimahS3Error.from(\"NOT_FOUND\", S3_ERROR_CODES.NOT_FOUND),\n\n unauthorized: () =>\n DimahS3Error.from(\"UNAUTHORIZED\", S3_ERROR_CODES.UNAUTHORIZED),\n\n forbidden: () => DimahS3Error.from(\"FORBIDDEN\", S3_ERROR_CODES.FORBIDDEN),\n\n conflict: () => DimahS3Error.from(\"CONFLICT\", S3_ERROR_CODES.CONFLICT),\n\n internalError: () =>\n DimahS3Error.from(\"INTERNAL_SERVER_ERROR\", S3_ERROR_CODES.INTERNAL_ERROR),\n\n objectNotFound: () =>\n DimahS3Error.from(\"NOT_FOUND\", S3_ERROR_CODES.OBJECT_NOT_FOUND),\n\n featureDisabled: (feature: RouteOperation) =>\n DimahS3Error.from(\"NOT_FOUND\", {\n code: S3_ERROR_CODES.FEATURE_DISABLED.code,\n message: S3_ERROR_CODES.FEATURE_DISABLED.message.replaceAll(\n \"{feature}\",\n feature,\n ),\n params: { feature },\n }),\n\n invalidKey: () =>\n DimahS3Error.from(\"BAD_REQUEST\", S3_ERROR_CODES.INVALID_KEY),\n\n unknownRoute: (route: string) =>\n DimahS3Error.from(\"NOT_FOUND\", {\n code: S3_ERROR_CODES.UNKNOWN_ROUTE.code,\n message: S3_ERROR_CODES.UNKNOWN_ROUTE.message,\n params: { route },\n }),\n\n fileTypeNotAllowed: (fileName: string, contentType?: string) =>\n DimahS3Error.from(\"BAD_REQUEST\", {\n code: S3_ERROR_CODES.FILE_TYPE_NOT_ALLOWED.code,\n message: S3_ERROR_CODES.FILE_TYPE_NOT_ALLOWED.message,\n params: {\n fileName,\n ...(contentType ? { contentType } : {}),\n },\n }),\n\n s3NetworkError: (code: string) =>\n DimahS3Error.from(\"BAD_GATEWAY\", {\n code: S3_ERROR_CODES.S3_NETWORK_ERROR.code,\n message: S3_ERROR_CODES.S3_NETWORK_ERROR.message.replaceAll(\n \"{code}\",\n code,\n ),\n params: { code },\n }),\n\n multipartPartMissing: (partNumber: number) =>\n DimahS3Error.from(\"BAD_REQUEST\", {\n code: S3_ERROR_CODES.MULTIPART_PART_MISSING.code,\n message: S3_ERROR_CODES.MULTIPART_PART_MISSING.message.replaceAll(\n \"{partNumber}\",\n String(partNumber),\n ),\n params: { partNumber },\n }),\n\n payloadTooLarge: (\n message: string = S3_ERROR_CODES.PAYLOAD_TOO_LARGE.message,\n ) =>\n DimahS3Error.from(\"PAYLOAD_TOO_LARGE\", {\n ...S3_ERROR_CODES.PAYLOAD_TOO_LARGE,\n message,\n }),\n\n quotaExceeded: (message: string = S3_ERROR_CODES.QUOTA_EXCEEDED.message) =>\n DimahS3Error.from(\"PAYLOAD_TOO_LARGE\", {\n ...S3_ERROR_CODES.QUOTA_EXCEEDED,\n message,\n }),\n\n validationError: (message: string) =>\n DimahS3Error.from(\"BAD_REQUEST\", {\n code: S3_ERROR_CODES.VALIDATION_ERROR.code,\n message,\n }),\n} as const;\n\nexport type ServerErrors = typeof errors;\n","import { errors } from \"@/errors\";\n\n/** True when an AWS SDK throw means the object or multipart upload does not exist. */\nexport function isAwsNotFound(err: unknown): boolean {\n const e = err as {\n name?: string;\n Code?: string;\n $metadata?: { httpStatusCode?: number };\n };\n return (\n e?.name === \"NoSuchKey\" ||\n e?.name === \"NotFound\" ||\n e?.name === \"NoSuchUpload\" ||\n e?.Code === \"NoSuchKey\" ||\n e?.Code === \"NotFound\" ||\n e?.Code === \"NoSuchUpload\" ||\n e?.$metadata?.httpStatusCode === 404\n );\n}\n\n/** Run an AWS call and map not-found errors to `OBJECT_NOT_FOUND`. */\nexport async function sendOrObjectNotFound<T>(\n send: () => Promise<T>,\n): Promise<T> {\n try {\n return await send();\n } catch (err: unknown) {\n if (isAwsNotFound(err)) throw errors.objectNotFound();\n throw err;\n }\n}\n","import { S3_DEFAULT_EXPIRES_IN, S3_MAX_EXPIRES_IN } from \"@dimah-s3/core\";\n\n/**\n * Coerce an upload/download `expiresIn` to a positive integer, then clamp\n * to {@link maxExpiresIn} (SigV4 max by default).\n */\nexport function normalizeExpiresIn(\n value: unknown,\n maxExpiresIn: number = S3_MAX_EXPIRES_IN,\n): number {\n const n = Number(value);\n const expires =\n Number.isFinite(n) && n > 0 ? Math.floor(n) : S3_DEFAULT_EXPIRES_IN;\n const max =\n Number.isFinite(maxExpiresIn) && maxExpiresIn > 0\n ? Math.floor(maxExpiresIn)\n : S3_MAX_EXPIRES_IN;\n return Math.min(expires, max);\n}\n","import type { DimahS3Logger } from \"@/types\";\n\nexport const defaultLogger: DimahS3Logger = {\n error: (message, ...args) => {\n console.error(\"[dimah-s3]\", message, ...args);\n },\n warn: (message, ...args) => {\n console.warn(\"[dimah-s3]\", message, ...args);\n },\n};\n\nexport function resolveLogger(\n logger: DimahS3Logger | false | undefined,\n): DimahS3Logger {\n if (logger === false) return {};\n if (!logger) return defaultLogger;\n return logger;\n}\n","import { DimahS3Error, isAPIError } from \"@dimah-s3/core\";\nimport { errors } from \"@/errors\";\nimport { resolveLogger } from \"@/helpers/logger\";\nimport type {\n ResolvedDimahS3Config,\n UploadConfig,\n UploadObjectContext,\n UploadObjectInfo,\n} from \"@/types\";\n\nfunction mapGuardError(err: unknown): never {\n if (isAPIError(err)) throw err;\n if (err instanceof Error && err.message.trim()) {\n throw new DimahS3Error(\"FORBIDDEN\", {\n message: err.message,\n cause: err,\n });\n }\n throw errors.forbidden();\n}\n\n/**\n * Run a guard hook. {@link isAPIError} values are preserved; plain Errors keep\n * their English message without a library `code` so client\n * `useFormatDimahError` does not replace them with a generic mapped string.\n */\nexport async function runHook<T extends { request: Request }>(\n hook: ((context: T) => Promise<void> | void) | undefined,\n context: T,\n): Promise<void> {\n if (!hook) return;\n try {\n await hook(context);\n } catch (err) {\n mapGuardError(err);\n }\n}\n\n/**\n * Run `upload.object`. Same rejection mapping as {@link runHook}\n * (plain `Error` → 403) so auth throws in `object` match `guard`.\n */\nexport async function runObjectHook(\n hook: UploadConfig[\"object\"],\n context: UploadObjectContext,\n): Promise<UploadObjectInfo | void> {\n if (!hook) return;\n try {\n return await hook(context);\n } catch (err) {\n mapGuardError(err);\n }\n}\n\n/**\n * Run a lifecycle `on*` hook. Failures become {@link errors.internalError}\n * (or preserve an existing APIError).\n */\nexport async function runLifecycleHook<T extends { request: Request }>(\n hook: ((context: T) => Promise<void> | void) | undefined,\n context: T,\n config?: Pick<ResolvedDimahS3Config, \"logger\" | \"onError\">,\n): Promise<void> {\n if (!hook) return;\n try {\n await hook(context);\n } catch (err) {\n if (isAPIError(err)) throw err;\n resolveLogger(config?.logger).error?.(\"lifecycle hook failed\", err);\n config?.onError?.(err, { request: context.request });\n throw errors.internalError();\n }\n}\n","/** S3 user-metadata key for `upload.object().previousKey`. */\nexport const DIMAH_PREVIOUS_KEY_META = \"dimah-previous-key\";\n\nexport function stripPreviousKeyMeta(\n metadata: Record<string, string> | undefined,\n): Record<string, string> {\n if (!metadata) return {};\n const { [DIMAH_PREVIOUS_KEY_META]: _omit, ...rest } = metadata;\n return rest;\n}\n\nexport function previousKeyFromMetadata(\n metadata: Record<string, string> | undefined,\n): string | undefined {\n const value = metadata?.[DIMAH_PREVIOUS_KEY_META]?.trim();\n return value || undefined;\n}\n","import {\n normalizeObjectKey,\n sanitizeFileName,\n type S3ObjectAcl,\n} from \"@dimah-s3/core\";\nimport { errors } from \"@/errors\";\nimport { DIMAH_PREVIOUS_KEY_META } from \"@/helpers/previous-key\";\nimport { runObjectHook } from \"@/helpers/hooks\";\nimport type {\n OpenedRoute,\n ResolvedRoute,\n UploadObjectContext,\n UploadObjectInfo,\n} from \"@/types\";\n\nexport type ResolvedObject = {\n key: string;\n bucket: string;\n metadata?: Record<string, string>;\n acl: S3ObjectAcl;\n};\n\ntype RouteKeyPrefix = ResolvedRoute[\"keyPrefix\"];\n\n/**\n * Strip leading/trailing slashes and reject `.` / `..` / empty segments,\n * NUL, and backslashes. Returns `null` when the key is unsafe.\n */\nexport { normalizeObjectKey };\n\n/**\n * Normalize an object key: strip leading slashes, reject `.` / `..` segments,\n * NUL, and backslashes.\n */\nexport function assertSafeObjectKey(key: string): string {\n const normalized = normalizeObjectKey(key);\n if (!normalized) throw errors.invalidKey();\n return normalized;\n}\n\nfunction applyPrefix(prefix: string, key: string): string {\n const p = assertSafeObjectKey(prefix);\n const k = assertSafeObjectKey(key);\n if (k.startsWith(`${p}/`)) return k;\n if (k === p) throw errors.invalidKey();\n return `${p}/${k}`;\n}\n\n/** Nest `key` under `keyPrefix`. `false` leaves a safe key unchanged. */\nexport function nestKeyUnderPrefix(\n keyPrefix: RouteKeyPrefix,\n key: string,\n): string {\n const safe = assertSafeObjectKey(key);\n if (keyPrefix === false) return safe;\n return applyPrefix(keyPrefix, safe);\n}\n\n/** Confirm / download / delete / multipart follow-ups: stored key + namespace. */\nexport function assertStoredKey(\n key: string,\n keyPrefix: RouteKeyPrefix,\n): string {\n const safe = assertSafeObjectKey(key);\n if (keyPrefix === false) return safe;\n const root = assertSafeObjectKey(keyPrefix);\n if (safe.startsWith(`${root}/`)) return safe;\n throw errors.invalidKey();\n}\n\n/**\n * Leaf name for a generated object key. Path segments (`../`, `/`) must\n * not become extra key folders or fail {@link assertSafeObjectKey}.\n */\nfunction objectKeyFileName(fileName: string): string {\n const sanitized = sanitizeFileName(fileName);\n const leaf = sanitized\n .split(\"/\")\n .filter((part) => part.length > 0)\n .at(-1);\n if (!leaf || leaf === \".\" || leaf === \"..\") return \"file\";\n return leaf;\n}\n\n/** `{folder}/{uuid}/{sanitizedName}` — omit `folder` (`false`) for `{uuid}/{name}`. */\nexport function generateObjectKey(\n folder: string | false,\n fileName: string,\n): string {\n const leaf = `${crypto.randomUUID()}/${objectKeyFileName(fileName)}`;\n if (folder === false) return assertSafeObjectKey(leaf);\n return applyPrefix(folder, leaf);\n}\n\nfunction resolveAcl(\n info: UploadObjectInfo | void,\n route: OpenedRoute<\"upload\" | \"multipart\">,\n): ResolvedObject[\"acl\"] {\n return info?.acl ?? route.upload.acl ?? \"private\";\n}\n\nexport async function resolveUploadTarget(\n route: OpenedRoute<\"upload\" | \"multipart\">,\n context: Omit<UploadObjectContext, \"bucket\" | \"keyPrefix\">,\n): Promise<ResolvedObject> {\n const bucket = route.bucket;\n const objectContext: UploadObjectContext = {\n ...context,\n bucket,\n keyPrefix: route.keyPrefix,\n };\n const info =\n (await runObjectHook(route.upload.object, objectContext)) ?? undefined;\n const key = info?.key\n ? nestKeyUnderPrefix(route.keyPrefix, info.key)\n : generateObjectKey(\n info?.folder != null && info.folder !== \"\"\n ? nestKeyUnderPrefix(route.keyPrefix, info.folder)\n : route.keyPrefix === false\n ? false\n : route.keyPrefix,\n context.file.name,\n );\n const metadata = { ...info?.metadata };\n if (info?.previousKey) {\n metadata[DIMAH_PREVIOUS_KEY_META] = nestKeyUnderPrefix(\n route.keyPrefix,\n info.previousKey,\n );\n }\n return {\n key,\n bucket,\n metadata: Object.keys(metadata).length > 0 ? metadata : info?.metadata,\n acl: resolveAcl(info, route),\n };\n}\n\nexport function resolveStoredTarget(\n route: ResolvedRoute,\n key: string,\n): { key: string; bucket: string } {\n return {\n key: assertStoredKey(key, route.keyPrefix),\n bucket: route.bucket,\n };\n}\n","import { ROUTE_NAME_PATTERN } from \"@dimah-s3/core\";\nimport type { DimahS3RouteConfig } from \"@/types/config\";\n\n/**\n * Identity helper so route configs infer as a distinct policy object.\n *\n * ```ts\n * routes: {\n * uploads: route({ upload: { fileTypes: [\"image/*\"] } }),\n * }\n * ```\n */\nexport function route<const T extends DimahS3RouteConfig>(config: T): T {\n return config;\n}\n\nexport function assertRouteName(name: string): void {\n if (!ROUTE_NAME_PATTERN.test(name)) {\n throw new Error(\n `dimahS3 route \"${name}\" is invalid. Use a letter followed by up to 63 letters, digits, underscores, or hyphens.`,\n );\n }\n}\n","import type {\n DeleteConfig,\n DimahS3Config,\n DimahS3RouteConfig,\n DownloadConfig,\n EnabledFeature,\n FeatureToggle,\n MultipartConfig,\n ResolvedFeature,\n ResolvedRoute,\n ResolvedUploadConfig,\n UploadConfig,\n} from \"@/types\";\nimport { normalizeObjectKey } from \"@/helpers/resolve-target\";\nimport { assertRouteName } from \"@/route\";\n\nexport function isEnabled<T extends { enabled: boolean }>(\n feature: T,\n): feature is T & { enabled: true } {\n return feature.enabled;\n}\n\nfunction resolveKeyPrefix(\n name: string,\n value: DimahS3RouteConfig[\"keyPrefix\"],\n): string | false {\n if (value === false) return false;\n const normalized = normalizeObjectKey(value ?? name);\n if (!normalized) {\n throw new Error(\n `dimahS3 route \"${name}\": keyPrefix is not a valid object-key prefix.`,\n );\n }\n return normalized;\n}\n\n/**\n * `true` / options → on; `false` → off.\n * `undefined` uses {@link defaultOn} (false unless passed).\n * Resolved `{ enabled }` objects (after `normalizeFeature`) use that flag.\n */\nexport function isFeatureOn<T extends object>(\n value: FeatureToggle<T> | ResolvedFeature<T> | undefined,\n defaultOn = false,\n): boolean {\n if (value === false) return false;\n if (value === undefined) return defaultOn;\n if (value === true) return true;\n if (\"enabled\" in value && typeof value.enabled === \"boolean\") {\n return value.enabled;\n }\n return true;\n}\n\n/** `true` / options → enabled; omit / `false` → disabled. */\nexport function normalizeFeature<T extends object>(\n value: FeatureToggle<T> | undefined,\n defaultOn = false,\n): ResolvedFeature<T> {\n if (value === false) return { enabled: false };\n if (value === undefined) {\n if (!defaultOn) return { enabled: false };\n return { enabled: true } as EnabledFeature<T>;\n }\n if (value === true) return { enabled: true } as EnabledFeature<T>;\n return { ...value, enabled: true };\n}\n\nfunction skippedPluginIds(plugins: DimahS3RouteConfig[\"plugins\"]): Set<string> {\n const ids = new Set<string>();\n if (!plugins) return ids;\n for (const [id, enabled] of Object.entries(plugins)) {\n if (enabled === false) ids.add(id);\n }\n return ids;\n}\n\nfunction splitUpload(upload: DimahS3RouteConfig[\"upload\"]): {\n upload: FeatureToggle<Omit<UploadConfig, \"multipart\">> | undefined;\n multipart: FeatureToggle<MultipartConfig> | undefined;\n} {\n if (upload === undefined || typeof upload === \"boolean\") {\n return { upload, multipart: undefined };\n }\n const { multipart, ...rest } = upload;\n return { upload: rest, multipart };\n}\n\nexport function normalizeRoute(\n name: string,\n route: DimahS3RouteConfig,\n instance: Pick<DimahS3Config, \"client\" | \"bucket\">,\n): ResolvedRoute {\n assertRouteName(name);\n\n const client = route.client ?? instance.client;\n const bucket = route.bucket ?? instance.bucket;\n if (!client) {\n throw new Error(\n `dimahS3 route \"${name}\": set client on the route or on dimahS3().`,\n );\n }\n if (!bucket) {\n throw new Error(\n `dimahS3 route \"${name}\": set bucket on the route or on dimahS3().`,\n );\n }\n\n const { upload: uploadInput, multipart: multipartInput } = splitUpload(\n route.upload,\n );\n const upload = normalizeFeature(uploadInput);\n const download = normalizeFeature<DownloadConfig>(route.download);\n const deleteFeature = normalizeFeature<DeleteConfig>(route.delete);\n const multipart = normalizeFeature<MultipartConfig>(multipartInput);\n\n if (!upload.enabled && !download.enabled && !deleteFeature.enabled) {\n throw new Error(\n `dimahS3 route \"${name}\": enable upload, download, or delete.`,\n );\n }\n\n const resolvedUpload: ResolvedUploadConfig = upload.enabled\n ? { ...upload, multipart }\n : { enabled: false, multipart: { enabled: false } };\n\n if (resolvedUpload.enabled) {\n const maxFileSize = resolvedUpload.maxFileSize;\n if (\n maxFileSize != null &&\n (!Number.isFinite(maxFileSize) || maxFileSize <= 0)\n ) {\n throw new Error(\n `dimahS3 route \"${name}\": maxFileSize must be a positive number.`,\n );\n }\n }\n\n return {\n name,\n client,\n bucket,\n keyPrefix: resolveKeyPrefix(name, route.keyPrefix),\n guard: route.guard,\n skippedPluginIds: skippedPluginIds(route.plugins),\n upload: resolvedUpload,\n download,\n delete: deleteFeature,\n };\n}\n\nexport function normalizeRoutes(\n config: DimahS3Config,\n): Record<string, ResolvedRoute> {\n const entries = Object.entries(config.routes);\n if (entries.length === 0) {\n throw new Error(\"dimahS3: at least one route is required.\");\n }\n const routes: Record<string, ResolvedRoute> = {};\n for (const [name, route] of entries) {\n routes[name] = normalizeRoute(name, route, config);\n }\n assertDistinctKeyPrefixes(routes);\n return routes;\n}\n\nfunction prefixesOverlap(a: string, b: string): boolean {\n return a === b || a.startsWith(`${b}/`) || b.startsWith(`${a}/`);\n}\n\n/** Nested or identical `keyPrefix` values would let one route access another's keys. */\nfunction assertDistinctKeyPrefixes(\n routes: Record<string, ResolvedRoute>,\n): void {\n const named = Object.entries(routes).filter(\n (entry): entry is [string, ResolvedRoute & { keyPrefix: string }] =>\n entry[1].keyPrefix !== false,\n );\n for (let i = 0; i < named.length; i++) {\n for (let j = i + 1; j < named.length; j++) {\n const [nameA, routeA] = named[i];\n const [nameB, routeB] = named[j];\n if (prefixesOverlap(routeA.keyPrefix, routeB.keyPrefix)) {\n throw new Error(\n `dimahS3: routes \"${nameA}\" and \"${nameB}\" have overlapping keyPrefix values (\"${routeA.keyPrefix}\" and \"${routeB.keyPrefix}\").`,\n );\n }\n }\n }\n}\n","import { matchesFileTypes } from \"@dimah-s3/core\";\nimport { errors } from \"@/errors\";\nimport type { UploadConfig } from \"@/types\";\n\n/** File limits from `upload` (`fileTypes` / `maxFileSize`). */\nexport type FileConstraints = Pick<UploadConfig, \"fileTypes\" | \"maxFileSize\">;\n\n/** Reject when `size` is over the route cap. No-op when `maxFileSize` is unset. */\nexport function assertWithinMaxFileSize(\n maxFileSize: number | undefined,\n size: number,\n): void {\n if (typeof maxFileSize === \"number\" && size > maxFileSize) {\n throw errors.payloadTooLarge();\n }\n}\n\nexport function assertDeclaredConstraints(\n constraints: FileConstraints | undefined,\n input: { fileName: string; fileSize: number; contentType?: string },\n): void {\n if (\n constraints?.fileTypes?.length &&\n !matchesFileTypes(input.fileName, input.contentType, constraints.fileTypes)\n ) {\n throw errors.fileTypeNotAllowed(input.fileName, input.contentType);\n }\n assertWithinMaxFileSize(constraints?.maxFileSize, input.fileSize);\n}\n\nexport function assertVerifiedConstraints(\n constraints: FileConstraints | undefined,\n input: { fileName?: string; contentType?: string; contentLength: number },\n): void {\n assertWithinMaxFileSize(constraints?.maxFileSize, input.contentLength);\n const name = input.fileName ?? \"\";\n if (\n constraints?.fileTypes?.length &&\n !matchesFileTypes(name, input.contentType, constraints.fileTypes)\n ) {\n throw errors.fileTypeNotAllowed(name || \"unknown\", input.contentType);\n }\n}\n","import type { S3ObjectAcl } from \"@dimah-s3/core\";\nimport { errors } from \"@/errors\";\nimport { assertDeclaredConstraints } from \"@/helpers/constraints\";\nimport { runHook } from \"@/helpers/hooks\";\nimport {\n resolveStoredTarget,\n resolveUploadTarget,\n} from \"@/helpers/resolve-target\";\nimport type {\n OpenedRoute,\n ResolvedDimahS3Config,\n ResolvedRoute,\n RouteOperation,\n StoredObjectContext,\n} from \"@/types\";\n\nexport type OpenedTarget<F extends RouteOperation> = {\n route: OpenedRoute<F>;\n key: string;\n bucket: string;\n stored: StoredObjectContext;\n};\n\nexport type OpenedUploadTarget<F extends \"upload\" | \"multipart\"> =\n OpenedTarget<F> & {\n metadata?: Record<string, string>;\n acl: S3ObjectAcl;\n };\n\nexport type OpenUploadInput = {\n route: string;\n fileName: string;\n fileSize: number;\n contentType?: string;\n metadata?: Record<string, string>;\n};\n\nexport function getResolvedRoute(\n config: ResolvedDimahS3Config,\n name: string,\n): ResolvedRoute {\n const route = config.routes[name];\n if (!route) {\n throw errors.unknownRoute(name);\n }\n return route;\n}\n\nfunction featureIsEnabled(\n route: ResolvedRoute,\n feature: RouteOperation,\n): boolean {\n if (feature === \"multipart\") return route.upload.multipart.enabled;\n return route[feature].enabled;\n}\n\n/** Disabled features respond 404 (`FEATURE_DISABLED`) from both HTTP and `s3.api`. */\nexport function assertFeatureEnabled<F extends RouteOperation>(\n route: ResolvedRoute,\n feature: F,\n): asserts route is OpenedRoute<F> {\n if (!featureIsEnabled(route, feature)) {\n throw errors.featureDisabled(feature);\n }\n}\n\n/** Lookup the named route, reject a disabled feature, run the route `guard`. */\nexport async function openRoute<F extends RouteOperation>(\n config: ResolvedDimahS3Config,\n name: string,\n request: Request,\n feature: F,\n): Promise<OpenedRoute<F>> {\n const route = getResolvedRoute(config, name);\n assertFeatureEnabled(route, feature);\n await runHook(route.guard, { request, route: route.name });\n return route;\n}\n\nexport function storedObjectContext(\n request: Request,\n route: Pick<ResolvedRoute, \"name\" | \"bucket\">,\n key: string,\n): StoredObjectContext {\n return { request, route: route.name, key, bucket: route.bucket };\n}\n\n/**\n * {@link openRoute} plus file constraints and server-owned key generation.\n * Used by upload presign and multipart init.\n */\nexport async function openUploadTarget<F extends \"upload\" | \"multipart\">(\n config: ResolvedDimahS3Config,\n input: OpenUploadInput,\n request: Request,\n feature: F,\n): Promise<OpenedUploadTarget<F>> {\n const route = await openRoute(config, input.route, request, feature);\n const fileSize = Math.floor(input.fileSize);\n const fileName = input.fileName;\n assertDeclaredConstraints(route.upload, {\n fileName,\n fileSize,\n contentType: input.contentType,\n });\n const target = await resolveUploadTarget(route, {\n request,\n route: route.name,\n file: {\n name: fileName,\n size: fileSize,\n type: input.contentType,\n },\n clientMetadata: input.metadata,\n });\n return {\n route,\n ...target,\n stored: storedObjectContext(request, route, target.key),\n };\n}\n\n/** {@link openRoute} plus the stored-key namespace check. */\nexport async function openStoredTarget<F extends RouteOperation>(\n config: ResolvedDimahS3Config,\n input: { route: string; key: string },\n request: Request,\n feature: F,\n): Promise<OpenedTarget<F>> {\n const route = await openRoute(config, input.route, request, feature);\n const target = resolveStoredTarget(route, input.key);\n return {\n route,\n ...target,\n stored: storedObjectContext(request, route, target.key),\n };\n}\n","import {\n HeadObjectCommand,\n type HeadObjectCommandOutput,\n type S3Client,\n} from \"@aws-sdk/client-s3\";\nimport { errors } from \"@/errors\";\nimport { sendOrObjectNotFound } from \"./is-aws-not-found\";\n\n/** HeadObject, mapping AWS not-found to `OBJECT_NOT_FOUND`. */\nexport async function headObjectOrNotFound(\n client: S3Client,\n bucket: string,\n key: string,\n): Promise<HeadObjectCommandOutput> {\n return sendOrObjectNotFound(() =>\n client.send(new HeadObjectCommand({ Bucket: bucket, Key: key })),\n );\n}\n\n/**\n * HeadObject after CompleteMultipartUpload. Some providers briefly omit\n * `ContentLength`; retry a few times with exponential backoff.\n */\nexport async function headObjectAfterMultipartComplete(\n client: S3Client,\n bucket: string,\n key: string,\n): Promise<HeadObjectCommandOutput> {\n const send = (): Promise<HeadObjectCommandOutput> =>\n sendOrObjectNotFound(() =>\n client.send(new HeadObjectCommand({ Bucket: bucket, Key: key })),\n );\n\n let head = await send();\n for (\n let attempt = 0;\n attempt < 4 && typeof head.ContentLength !== \"number\";\n attempt++\n ) {\n await new Promise((r) => setTimeout(r, 250 * 2 ** attempt));\n head = await send();\n }\n return head;\n}\n\n/** Verified size from HeadObject — never invent `0` when S3 omits it. */\nexport function requireContentLength(head: HeadObjectCommandOutput): number {\n if (typeof head.ContentLength !== \"number\") {\n throw errors.internalError();\n }\n return head.ContentLength;\n}\n","import {\n ListPartsCommand,\n type ListPartsCommandOutput,\n type Part,\n type S3Client,\n} from \"@aws-sdk/client-s3\";\nimport { sendOrObjectNotFound } from \"./is-aws-not-found\";\n\n/** Page through ListParts until S3 reports no more parts. */\nexport async function listAllParts(\n client: S3Client,\n input: { bucket: string; key: string; uploadId: string },\n): Promise<Part[]> {\n const parts: Part[] = [];\n let partNumberMarker: string | undefined;\n let isTruncated = true;\n\n while (isTruncated) {\n const response: ListPartsCommandOutput = await sendOrObjectNotFound(() =>\n client.send(\n new ListPartsCommand({\n Bucket: input.bucket,\n Key: input.key,\n UploadId: input.uploadId,\n ...(partNumberMarker ? { PartNumberMarker: partNumberMarker } : {}),\n }),\n ),\n );\n parts.push(...(response.Parts ?? []));\n isTruncated = response.IsTruncated === true;\n partNumberMarker = isTruncated ? response.NextPartNumberMarker : undefined;\n }\n\n return parts;\n}\n\n/** Sum `Size` on listed parts. Pass `excludePartNumber` when replacing a part. */\nexport function listedPartsByteSize(\n parts: readonly { PartNumber?: number; Size?: number }[],\n excludePartNumber?: number,\n): number {\n let total = 0;\n for (const part of parts) {\n if (\n excludePartNumber !== undefined &&\n part.PartNumber === excludePartNumber\n ) {\n continue;\n }\n total += part.Size ?? 0;\n }\n return total;\n}\n","import type { ConfirmedObjectResponse, S3ObjectAcl } from \"@dimah-s3/core\";\nimport { resolveStoredFileName } from \"@dimah-s3/core\";\nimport type { HeadObjectCommandOutput, S3Client } from \"@aws-sdk/client-s3\";\nimport { assertVerifiedConstraints } from \"@/helpers/constraints\";\nimport { deleteObjectBestEffort } from \"@/helpers/best-effort\";\nimport { requireContentLength } from \"@/helpers/head-object\";\nimport { runLifecycleHook } from \"@/helpers/hooks\";\nimport { assertStoredKey } from \"@/helpers/resolve-target\";\nimport {\n previousKeyFromMetadata,\n stripPreviousKeyMeta,\n} from \"@/helpers/previous-key\";\nimport type {\n OpenedRoute,\n ResolvedDimahS3Config,\n StoredObjectContext,\n UploadOnConfirmedContext,\n} from \"@/types\";\n\nexport type FinalizeConfirmedInput = {\n config: ResolvedDimahS3Config;\n route: OpenedRoute<\"upload\" | \"multipart\">;\n stored: StoredObjectContext;\n head: HeadObjectCommandOutput;\n uploadId?: string;\n /** ACL from the upload policy, not GetObjectAcl. */\n acl?: S3ObjectAcl;\n};\n\n/**\n * HeadObject constraints, `onConfirmed`, then compensating `DeleteObject`\n * (and `previousKey` cleanup) so a thrown lifecycle hook cannot leave an\n * orphan object.\n */\nexport async function finalizeConfirmedObject(\n client: S3Client,\n bucket: string,\n key: string,\n input: FinalizeConfirmedInput,\n): Promise<ConfirmedObjectResponse> {\n const { config, route, stored, head, uploadId, acl } = input;\n const contentLength = requireContentLength(head);\n const fileName = resolveStoredFileName(head.ContentDisposition, key);\n const rawMetadata = head.Metadata ?? {};\n\n try {\n assertVerifiedConstraints(route.upload, {\n fileName,\n contentType: head.ContentType,\n contentLength,\n });\n } catch (err) {\n await deleteObjectBestEffort(client, bucket, key);\n throw err;\n }\n\n const metadata = stripPreviousKeyMeta(rawMetadata);\n const context: UploadOnConfirmedContext = {\n ...stored,\n contentType: head.ContentType,\n contentLength,\n eTag: head.ETag?.replace(/\"/g, \"\"),\n metadata,\n acl,\n fileName,\n versionId: head.VersionId,\n lastModified: head.LastModified?.toISOString(),\n uploadId,\n };\n\n try {\n await runLifecycleHook(route.upload.onConfirmed, context, config);\n } catch (err) {\n await deleteObjectBestEffort(client, bucket, key);\n throw err;\n }\n\n const previousKey = previousKeyFromMetadata(rawMetadata);\n if (previousKey && previousKey !== key) {\n try {\n const safe = assertStoredKey(previousKey, route.keyPrefix);\n await deleteObjectBestEffort(client, bucket, safe);\n } catch {\n // Invalid previousKey — skip.\n }\n }\n\n return {\n key,\n bucket,\n contentType: context.contentType,\n contentLength: context.contentLength,\n eTag: context.eTag,\n metadata: context.metadata ?? {},\n acl,\n fileName,\n versionId: context.versionId,\n lastModified: context.lastModified,\n };\n}\n","import { PutObjectCommand } from \"@aws-sdk/client-s3\";\nimport type { ConfirmedObjectResponse, S3RouteName } from \"@dimah-s3/core\";\nimport { requestFromHeaders } from \"@/helpers/request\";\nimport {\n finalizeConfirmedObject,\n headObjectOrNotFound,\n openUploadTarget,\n runHook,\n} from \"@/helpers\";\nimport type { ResolvedDimahS3Config } from \"@/types\";\n\nexport type PutObjectInput = {\n route: S3RouteName;\n fileName: string;\n contentType?: string;\n body: Uint8Array | ArrayBuffer | string;\n metadata?: Record<string, string>;\n headers?: HeadersInit;\n};\n\nfunction toBytes(body: PutObjectInput[\"body\"]): Uint8Array {\n if (typeof body === \"string\") return new TextEncoder().encode(body);\n if (body instanceof ArrayBuffer) return new Uint8Array(body);\n return body;\n}\n\n/**\n * Server-side upload through the same route policy as presign + confirm.\n */\nexport async function putObject(\n config: ResolvedDimahS3Config,\n input: PutObjectInput,\n): Promise<ConfirmedObjectResponse> {\n const body = toBytes(input.body);\n const request = requestFromHeaders(input.headers);\n await runHook(config.guard, { request });\n const fileSize = body.byteLength;\n const { route, key, bucket, metadata, acl, stored } = await openUploadTarget(\n config,\n {\n route: input.route,\n fileName: input.fileName,\n fileSize,\n contentType: input.contentType,\n metadata: input.metadata,\n },\n request,\n \"upload\",\n );\n\n await runHook(route.upload.guard, {\n ...stored,\n file: {\n name: input.fileName,\n size: fileSize,\n type: input.contentType,\n },\n metadata,\n clientMetadata: input.metadata,\n acl,\n replace: route.upload.replace,\n });\n\n await route.client.send(\n new PutObjectCommand({\n Bucket: bucket,\n Key: key,\n Body: body,\n ContentType: input.contentType,\n ContentLength: fileSize,\n Metadata: metadata,\n ACL: acl,\n }),\n );\n\n const head = await headObjectOrNotFound(route.client, bucket, key);\n return finalizeConfirmedObject(route.client, bucket, key, {\n config,\n route,\n stored,\n head,\n acl,\n });\n}\n","import { createMiddleware } from \"better-call\";\nimport { requestFromHeaders, runHook } from \"@/helpers\";\nimport type { S3EndpointContext } from \"./context\";\n\n/**\n * Injects `config` / `request` and runs the global `guard`.\n * Used by {@link createS3Endpoint} so HTTP and `s3.api` share the same path.\n */\nexport const s3ContextMiddleware = createMiddleware(async (ctx) => {\n const injected = ctx.context as Partial<S3EndpointContext> | undefined;\n if (!injected?.config) {\n throw new Error(\n \"createS3Endpoint requires dimahS3 router context. Call endpoints through dimahS3().api or the HTTP handler.\",\n );\n }\n\n const request =\n ctx.request ??\n injected.request ??\n requestFromHeaders(ctx.headers as HeadersInit | undefined);\n\n await runHook(injected.config.guard, { request });\n\n return {\n config: injected.config,\n request,\n } satisfies S3EndpointContext;\n});\n\n/**\n * Middleware factory with dimah-s3 context already applied — same idea as\n * Better Auth `createAuthMiddleware`.\n */\nexport const createS3Middleware = createMiddleware.create({\n use: [s3ContextMiddleware],\n});\n","import { createEndpoint, type EndpointOptions } from \"better-call\";\nimport * as z from \"zod\";\nimport { errors } from \"@/errors\";\nimport { s3ContextMiddleware } from \"./create-s3-middleware\";\n\nconst createEndpointWithContext = createEndpoint.create({\n use: [s3ContextMiddleware],\n});\n\nfunction compileIfZod<T>(schema: T): T {\n if (schema !== null && typeof schema === \"object\" && \"_zod\" in schema) {\n return z.compile(schema as unknown as z.ZodType) as T;\n }\n return schema;\n}\n\nfunction withS3Validation<O extends EndpointOptions>(options: O): O {\n return {\n ...options,\n ...(options.body !== undefined ? { body: compileIfZod(options.body) } : {}),\n ...(options.query !== undefined\n ? { query: compileIfZod(options.query) }\n : {}),\n onValidationError:\n options.onValidationError ??\n (({ message }: { message: string }) => {\n throw errors.validationError(message);\n }),\n };\n}\n\ntype CreateS3Endpoint = typeof createEndpointWithContext;\n\n/**\n * Typed endpoint for dimah-s3 plugins and core routes.\n *\n * Paths are absolute under `basePath` (e.g. `/db/objects`). Context\n * (`config`, `request`) is injected by the router / `s3.api`.\n * Zod failures throw `DimahS3Error` (`VALIDATION_ERROR`) via\n * better-call `onValidationError`. Zod `body` / `query` schemas are\n * compiled with `z.compile()` (Zod 4.5) so valid requests skip the\n * interpreter; unsupported schemas fall back to the runtime parser.\n *\n * ```ts\n * endpoints: {\n * recent: createS3Endpoint(\"/audit/recent\", { method: \"GET\" }, async (ctx) => {\n * return { events: [] };\n * }),\n * }\n * ```\n */\nexport const createS3Endpoint: CreateS3Endpoint = ((\n pathOrOptions: string | EndpointOptions,\n optionsOrHandler: EndpointOptions | ((...args: never[]) => unknown),\n maybeHandler?: (...args: never[]) => unknown,\n) => {\n if (typeof pathOrOptions === \"string\") {\n return createEndpointWithContext(\n pathOrOptions,\n withS3Validation(optionsOrHandler as EndpointOptions),\n maybeHandler as never,\n );\n }\n return createEndpointWithContext(\n withS3Validation(pathOrOptions),\n optionsOrHandler as never,\n );\n}) as unknown as CreateS3Endpoint;\n","import { confirmBodySchema, S3_API_ROUTES } from \"@dimah-s3/core\";\nimport type * as z from \"zod\";\nimport {\n finalizeConfirmedObject,\n headObjectOrNotFound,\n openStoredTarget,\n runHook,\n} from \"@/helpers\";\nimport type { ResolvedDimahS3Config } from \"@/types\";\nimport { createS3Endpoint } from \"@/api/create-s3-endpoint\";\n\nasync function handleConfirm(\n config: ResolvedDimahS3Config,\n input: z.output<typeof confirmBodySchema>,\n request: Request,\n) {\n const { route, key, bucket, stored } = await openStoredTarget(\n config,\n input,\n request,\n \"upload\",\n );\n\n await runHook(route.upload.confirmGuard, {\n ...stored,\n replace: route.upload.replace,\n });\n\n const head = await headObjectOrNotFound(route.client, bucket, key);\n return finalizeConfirmedObject(route.client, bucket, key, {\n config,\n route,\n stored,\n head,\n acl: route.upload.acl,\n });\n}\n\nexport const confirm = createS3Endpoint(\n S3_API_ROUTES.uploadConfirm,\n { method: \"POST\", body: confirmBodySchema },\n async (ctx) => {\n return handleConfirm(ctx.context.config, ctx.body, ctx.context.request);\n },\n);\n","import { DeleteObjectCommand } from \"@aws-sdk/client-s3\";\nimport {\n deleteQuerySchema,\n S3_API_ROUTES,\n type DeleteResponse,\n} from \"@dimah-s3/core\";\nimport type * as z from \"zod\";\nimport {\n headObjectOrNotFound,\n openStoredTarget,\n runHook,\n runLifecycleHook,\n} from \"@/helpers\";\nimport type { ResolvedDimahS3Config } from \"@/types\";\nimport { createS3Endpoint } from \"@/api/create-s3-endpoint\";\n\nasync function handleDelete(\n config: ResolvedDimahS3Config,\n input: z.output<typeof deleteQuerySchema>,\n request: Request,\n): Promise<DeleteResponse> {\n const { route, key, bucket, stored } = await openStoredTarget(\n config,\n input,\n request,\n \"delete\",\n );\n\n await runHook(route.delete.guard, stored);\n\n await headObjectOrNotFound(route.client, bucket, key);\n\n await route.client.send(\n new DeleteObjectCommand({ Bucket: bucket, Key: key }),\n );\n\n await runLifecycleHook(route.delete.onDeleted, stored, config);\n\n return { success: true, bucket, key };\n}\n\nexport const deleteObject = createS3Endpoint(\n S3_API_ROUTES.delete,\n { method: \"DELETE\", query: deleteQuerySchema },\n async (ctx) => {\n return handleDelete(ctx.context.config, ctx.query, ctx.context.request);\n },\n);\n","import { DeleteObjectCommand } from \"@aws-sdk/client-s3\";\nimport {\n deleteBatchBodySchema,\n isDimahS3Error,\n S3_API_ROUTES,\n type DeleteBatchResponse,\n} from \"@dimah-s3/core\";\nimport {\n headObjectOrNotFound,\n openStoredTarget,\n runHook,\n runLifecycleHook,\n} from \"@/helpers\";\nimport type { ResolvedDimahS3Config } from \"@/types\";\nimport { createS3Endpoint } from \"@/api/create-s3-endpoint\";\n\nasync function deleteOne(\n config: ResolvedDimahS3Config,\n routeName: string,\n key: string,\n request: Request,\n): Promise<void> {\n const { route, bucket, stored } = await openStoredTarget(\n config,\n { route: routeName, key },\n request,\n \"delete\",\n );\n\n await runHook(route.delete.guard, stored);\n await headObjectOrNotFound(route.client, bucket, stored.key);\n await route.client.send(\n new DeleteObjectCommand({ Bucket: bucket, Key: stored.key }),\n );\n await runLifecycleHook(route.delete.onDeleted, stored, config);\n}\n\nexport const deleteBatch = createS3Endpoint(\n S3_API_ROUTES.deleteBatch,\n { method: \"POST\", body: deleteBatchBodySchema },\n async (ctx): Promise<DeleteBatchResponse> => {\n const config = ctx.context.config;\n const request = ctx.context.request;\n const results: DeleteBatchResponse[\"results\"] = [];\n\n for (const key of ctx.body.keys) {\n try {\n await deleteOne(config, ctx.body.route, key, request);\n results.push({ key, success: true });\n } catch (err) {\n results.push({\n key,\n success: false,\n error: isDimahS3Error(err)\n ? { code: err.code ?? \"INTERNAL_ERROR\", message: err.message }\n : { code: \"INTERNAL_ERROR\", message: \"Internal server error\" },\n });\n }\n }\n\n return { results };\n },\n);\n","import { GetObjectCommand } from \"@aws-sdk/client-s3\";\nimport { getSignedUrl } from \"@aws-sdk/s3-request-presigner\";\nimport {\n buildContentDisposition,\n downloadQuerySchema,\n S3_API_ROUTES,\n type DownloadPresignResponse,\n} from \"@dimah-s3/core\";\nimport type * as z from \"zod\";\nimport {\n headObjectOrNotFound,\n normalizeExpiresIn,\n openStoredTarget,\n runHook,\n runLifecycleHook,\n} from \"@/helpers\";\nimport type { ResolvedDimahS3Config } from \"@/types\";\nimport { createS3Endpoint } from \"@/api/create-s3-endpoint\";\n\nfunction fileUrl(\n request: Request,\n basePath: string,\n query: {\n route: string;\n key: string;\n fileName?: string;\n disposition?: string;\n },\n): string {\n const url = new URL(request.url);\n const prefix = basePath.endsWith(\"/\") ? basePath.slice(0, -1) : basePath;\n url.pathname = `${prefix}${S3_API_ROUTES.file}`;\n url.search = \"\";\n url.searchParams.set(\"route\", query.route);\n url.searchParams.set(\"key\", query.key);\n if (query.fileName) url.searchParams.set(\"fileName\", query.fileName);\n if (query.disposition) url.searchParams.set(\"disposition\", query.disposition);\n return url.toString();\n}\n\nasync function handleDownload(\n config: ResolvedDimahS3Config,\n input: z.output<typeof downloadQuerySchema>,\n request: Request,\n): Promise<DownloadPresignResponse> {\n const { route, key, bucket, stored } = await openStoredTarget(\n config,\n input,\n request,\n \"download\",\n );\n\n const resolved = await route.download.resolve?.({\n ...stored,\n fileName: input.fileName,\n disposition: input.disposition ?? route.download.disposition,\n });\n\n const fileName = resolved?.fileName ?? input.fileName;\n const disposition =\n resolved?.disposition ??\n input.disposition ??\n route.download.disposition ??\n \"attachment\";\n const expiresIn = normalizeExpiresIn(\n resolved?.expiresIn ?? route.download.expiresIn,\n config.maxExpiresIn,\n );\n\n await runHook(route.download.guard, {\n ...stored,\n fileName,\n disposition,\n });\n\n await headObjectOrNotFound(route.client, bucket, key);\n\n const mode = route.download.mode ?? \"presign\";\n const contentDisposition = fileName\n ? buildContentDisposition(fileName, disposition)\n : disposition;\n\n const url =\n mode === \"proxy\"\n ? fileUrl(request, config.basePath ?? \"/api/s3\", {\n route: input.route,\n key,\n fileName,\n disposition,\n })\n : await getSignedUrl(\n route.client,\n new GetObjectCommand({\n Bucket: bucket,\n Key: key,\n ResponseContentDisposition: contentDisposition,\n }),\n { expiresIn },\n );\n\n await runLifecycleHook(\n route.download.onPresigned,\n {\n ...stored,\n fileName,\n url,\n expiresIn: mode === \"proxy\" ? 0 : expiresIn,\n },\n config,\n );\n\n return {\n bucket,\n key,\n url,\n expiresIn: mode === \"proxy\" ? 0 : expiresIn,\n mode,\n disposition,\n };\n}\n\nexport const download = createS3Endpoint(\n S3_API_ROUTES.download,\n { method: \"GET\", query: downloadQuerySchema },\n async (ctx) => {\n return handleDownload(ctx.context.config, ctx.query, ctx.context.request);\n },\n);\n","import {\n S3_API_ROUTES,\n type RouteCatalogEntry,\n type RouteCatalogResponse,\n} from \"@dimah-s3/core\";\nimport { isEnabled } from \"@/helpers/features\";\nimport type { ResolvedDimahS3Config } from \"@/types\";\nimport { createS3Endpoint } from \"@/api/create-s3-endpoint\";\n\nfunction catalogUpload(\n upload: ResolvedDimahS3Config[\"routes\"][string][\"upload\"],\n): RouteCatalogEntry[\"upload\"] {\n if (!isEnabled(upload)) return { enabled: false };\n return {\n enabled: true,\n fileTypes: upload.fileTypes,\n maxFileSize: upload.maxFileSize,\n multipart: isEnabled(upload.multipart),\n ...(upload.checksum ? { checksum: true } : {}),\n ...(upload.replace ? { replace: upload.replace } : {}),\n };\n}\n\nfunction catalogDownload(\n download: ResolvedDimahS3Config[\"routes\"][string][\"download\"],\n): RouteCatalogEntry[\"download\"] {\n if (!isEnabled(download)) return { enabled: false };\n return {\n enabled: true,\n ...(download.disposition ? { disposition: download.disposition } : {}),\n ...(download.mode ? { mode: download.mode } : {}),\n };\n}\n\nexport function buildRouteCatalog(\n config: ResolvedDimahS3Config,\n): RouteCatalogResponse {\n const routes: RouteCatalogResponse[\"routes\"] = {};\n for (const [name, route] of Object.entries(config.routes)) {\n routes[name] = {\n upload: catalogUpload(route.upload),\n download: catalogDownload(route.download),\n delete: isEnabled(route.delete) ? { enabled: true } : { enabled: false },\n };\n }\n return { routes };\n}\n\nexport const catalog = createS3Endpoint(\n S3_API_ROUTES.catalog,\n { method: \"GET\" },\n async (ctx): Promise<RouteCatalogResponse> => {\n return buildRouteCatalog(ctx.context.config);\n },\n);\n","import { GetObjectCommand } from \"@aws-sdk/client-s3\";\nimport {\n buildContentDisposition,\n fileQuerySchema,\n resolveStoredFileName,\n S3_API_ROUTES,\n} from \"@dimah-s3/core\";\nimport type * as z from \"zod\";\nimport { errors } from \"@/errors\";\nimport {\n headObjectOrNotFound,\n openStoredTarget,\n runHook,\n sendOrObjectNotFound,\n} from \"@/helpers\";\nimport type { ResolvedDimahS3Config } from \"@/types\";\nimport { createS3Endpoint } from \"@/api/create-s3-endpoint\";\n\nasync function handleFile(\n config: ResolvedDimahS3Config,\n input: z.output<typeof fileQuerySchema>,\n request: Request,\n): Promise<Response> {\n const { route, key, bucket, stored } = await openStoredTarget(\n config,\n input,\n request,\n \"download\",\n );\n\n const resolved = await route.download.resolve?.({\n ...stored,\n fileName: input.fileName,\n disposition: input.disposition ?? route.download.disposition,\n });\n const fileName = resolved?.fileName ?? input.fileName;\n const disposition =\n resolved?.disposition ??\n input.disposition ??\n route.download.disposition ??\n \"attachment\";\n\n await runHook(route.download.guard, {\n ...stored,\n fileName,\n disposition,\n });\n\n await headObjectOrNotFound(route.client, bucket, key);\n\n const result = await sendOrObjectNotFound(() =>\n route.client.send(\n new GetObjectCommand({\n Bucket: bucket,\n Key: key,\n ResponseContentDisposition: fileName\n ? buildContentDisposition(fileName, disposition)\n : `${disposition}`,\n }),\n ),\n );\n\n const body = result.Body;\n if (!body) throw errors.objectNotFound();\n\n const stream =\n \"transformToWebStream\" in body &&\n typeof body.transformToWebStream === \"function\"\n ? body.transformToWebStream()\n : (body as ReadableStream<Uint8Array>);\n\n const headers = new Headers();\n headers.set(\"Content-Type\", result.ContentType ?? \"application/octet-stream\");\n headers.set(\n \"Content-Disposition\",\n fileName\n ? buildContentDisposition(fileName, disposition)\n : `${disposition}`,\n );\n if (typeof result.ContentLength === \"number\") {\n headers.set(\"Content-Length\", String(result.ContentLength));\n }\n\n return new Response(stream, { headers });\n}\n\nexport const file = createS3Endpoint(\n S3_API_ROUTES.file,\n { method: \"GET\", query: fileQuerySchema },\n async (ctx) => {\n return handleFile(ctx.context.config, ctx.query, ctx.context.request);\n },\n);\n\nexport { resolveStoredFileName };\n","import { AbortMultipartUploadCommand } from \"@aws-sdk/client-s3\";\nimport {\n multipartAbortBodySchema,\n S3_API_ROUTES,\n type MultipartAbortResponse,\n} from \"@dimah-s3/core\";\nimport type * as z from \"zod\";\nimport {\n openStoredTarget,\n runHook,\n runLifecycleHook,\n sendOrObjectNotFound,\n} from \"@/helpers\";\nimport type { ResolvedDimahS3Config } from \"@/types\";\nimport { createS3Endpoint } from \"@/api/create-s3-endpoint\";\n\nasync function handleAbort(\n config: ResolvedDimahS3Config,\n input: z.output<typeof multipartAbortBodySchema>,\n request: Request,\n): Promise<MultipartAbortResponse> {\n const { route, key, bucket, stored } = await openStoredTarget(\n config,\n input,\n request,\n \"multipart\",\n );\n const uploadId = input.uploadId;\n\n await runHook(route.upload.multipart.guard, {\n ...stored,\n uploadId,\n action: \"abort\",\n });\n\n await sendOrObjectNotFound(() =>\n route.client.send(\n new AbortMultipartUploadCommand({\n Bucket: bucket,\n Key: key,\n UploadId: uploadId,\n }),\n ),\n );\n\n await runLifecycleHook(\n route.upload.multipart.onAbort,\n {\n ...stored,\n uploadId,\n },\n config,\n );\n\n return { bucket, key, uploadId, aborted: true };\n}\n\nexport const multipartAbort = createS3Endpoint(\n S3_API_ROUTES.multipartAbort,\n { method: \"POST\", body: multipartAbortBodySchema },\n async (ctx) => {\n return handleAbort(ctx.context.config, ctx.body, ctx.context.request);\n },\n);\n","import {\n CompleteMultipartUploadCommand,\n type CompleteMultipartUploadCommandOutput,\n} from \"@aws-sdk/client-s3\";\nimport {\n multipartCompleteBodySchema,\n S3_API_ROUTES,\n type MultipartCompleteResponse,\n} from \"@dimah-s3/core\";\nimport type * as z from \"zod\";\nimport { errors } from \"@/errors\";\nimport {\n abortMultipartBestEffort,\n assertWithinMaxFileSize,\n finalizeConfirmedObject,\n headObjectAfterMultipartComplete,\n listAllParts,\n openStoredTarget,\n runHook,\n sendOrObjectNotFound,\n} from \"@/helpers\";\nimport type { ResolvedDimahS3Config } from \"@/types\";\nimport { createS3Endpoint } from \"@/api/create-s3-endpoint\";\n\nasync function handleComplete(\n config: ResolvedDimahS3Config,\n input: z.output<typeof multipartCompleteBodySchema>,\n request: Request,\n): Promise<MultipartCompleteResponse> {\n const { route, key, bucket, stored } = await openStoredTarget(\n config,\n input,\n request,\n \"multipart\",\n );\n const uploadId = input.uploadId;\n const parts = [\n ...new Set(input.parts.map(({ partNumber }) => partNumber)),\n ].sort((a, b) => a - b);\n const partRefs = parts.map((partNumber) => ({ partNumber }));\n\n await runHook(route.upload.multipart.guard, {\n ...stored,\n uploadId,\n action: \"complete\",\n });\n await runHook(route.upload.confirmGuard, {\n ...stored,\n uploadId,\n parts: partRefs,\n replace: route.upload.replace,\n });\n\n const listedParts = await listAllParts(route.client, {\n bucket,\n key,\n uploadId,\n });\n\n let assembledBytes = 0;\n const completeParts = parts.map((partNumber) => {\n const found = listedParts.find((p) => p.PartNumber === partNumber);\n if (!found?.ETag) {\n throw errors.multipartPartMissing(partNumber);\n }\n assembledBytes += found.Size ?? 0;\n return { PartNumber: partNumber, ETag: found.ETag };\n });\n\n try {\n assertWithinMaxFileSize(route.upload.maxFileSize, assembledBytes);\n } catch (err) {\n await abortMultipartBestEffort(route.client, bucket, key, uploadId);\n throw err;\n }\n\n const completeResult: CompleteMultipartUploadCommandOutput =\n await sendOrObjectNotFound(() =>\n route.client.send(\n new CompleteMultipartUploadCommand({\n Bucket: bucket,\n Key: key,\n UploadId: uploadId,\n MultipartUpload: { Parts: completeParts },\n }),\n ),\n );\n\n const head = await headObjectAfterMultipartComplete(\n route.client,\n bucket,\n key,\n );\n const confirmed = await finalizeConfirmedObject(route.client, bucket, key, {\n config,\n route,\n stored,\n head: {\n ...head,\n ETag: head.ETag ?? completeResult.ETag,\n },\n uploadId,\n acl: route.upload.acl,\n });\n\n return { ...confirmed, uploadId };\n}\n\nexport const multipartComplete = createS3Endpoint(\n S3_API_ROUTES.multipartComplete,\n { method: \"POST\", body: multipartCompleteBodySchema },\n async (ctx) => {\n return handleComplete(ctx.context.config, ctx.body, ctx.context.request);\n },\n);\n","import {\n CreateMultipartUploadCommand,\n type CreateMultipartUploadCommandOutput,\n} from \"@aws-sdk/client-s3\";\nimport {\n buildContentDisposition,\n multipartInitBodySchema,\n S3_API_ROUTES,\n type MultipartInitResponse,\n} from \"@dimah-s3/core\";\nimport type * as z from \"zod\";\nimport { errors } from \"@/errors\";\nimport { openUploadTarget, runHook, runLifecycleHook } from \"@/helpers\";\nimport type { ResolvedDimahS3Config } from \"@/types\";\nimport { createS3Endpoint } from \"@/api/create-s3-endpoint\";\n\nasync function handleMultipartInit(\n config: ResolvedDimahS3Config,\n input: z.output<typeof multipartInitBodySchema>,\n request: Request,\n): Promise<MultipartInitResponse> {\n const fileSize = Math.floor(input.fileSize);\n const fileName = input.fileName;\n const { route, key, bucket, metadata, acl, stored } = await openUploadTarget(\n config,\n {\n route: input.route,\n fileName,\n fileSize,\n contentType: input.contentType,\n metadata: input.metadata,\n },\n request,\n \"multipart\",\n );\n\n await runHook(route.upload.guard, {\n ...stored,\n file: {\n name: fileName,\n size: fileSize,\n type: input.contentType,\n },\n metadata,\n clientMetadata: input.metadata,\n acl,\n replace: route.upload.replace,\n });\n\n const { UploadId } = (await route.client.send(\n new CreateMultipartUploadCommand({\n Bucket: bucket,\n Key: key,\n ContentType: input.contentType,\n ContentDisposition: buildContentDisposition(fileName),\n Metadata: metadata,\n ACL: acl,\n }),\n )) as CreateMultipartUploadCommandOutput;\n\n if (!UploadId) {\n throw errors.internalError();\n }\n\n await runLifecycleHook(\n route.upload.multipart.onInit,\n {\n ...stored,\n uploadId: UploadId,\n file: {\n name: fileName,\n size: fileSize,\n type: input.contentType,\n },\n metadata,\n clientMetadata: input.metadata,\n acl,\n replace: route.upload.replace,\n },\n config,\n );\n\n return { bucket, key, uploadId: UploadId };\n}\n\nexport const multipartInit = createS3Endpoint(\n S3_API_ROUTES.multipartInit,\n { method: \"POST\", body: multipartInitBodySchema },\n async (ctx) => {\n const result = await handleMultipartInit(\n ctx.context.config,\n ctx.body,\n ctx.context.request,\n );\n ctx.setStatus(201);\n return result;\n },\n);\n","import {\n multipartListPartsQuerySchema,\n S3_API_ROUTES,\n type MultipartListPartsResponse,\n} from \"@dimah-s3/core\";\nimport type * as z from \"zod\";\nimport {\n listAllParts,\n openStoredTarget,\n runHook,\n runLifecycleHook,\n} from \"@/helpers\";\nimport type { ResolvedDimahS3Config } from \"@/types\";\nimport { createS3Endpoint } from \"@/api/create-s3-endpoint\";\n\nasync function handleListParts(\n config: ResolvedDimahS3Config,\n input: z.output<typeof multipartListPartsQuerySchema>,\n request: Request,\n): Promise<MultipartListPartsResponse> {\n const { route, key, bucket, stored } = await openStoredTarget(\n config,\n input,\n request,\n \"multipart\",\n );\n const uploadId = input.uploadId;\n\n await runHook(route.upload.multipart.guard, {\n ...stored,\n uploadId,\n action: \"list\",\n });\n\n const listed = await listAllParts(route.client, { bucket, key, uploadId });\n\n const parts = listed.flatMap((p) => {\n if (p.PartNumber == null || p.PartNumber < 1) return [];\n return [\n {\n partNumber: p.PartNumber,\n size: p.Size ?? 0,\n eTag: (p.ETag ?? \"\").replace(/\"/g, \"\"),\n },\n ];\n });\n\n await runLifecycleHook(\n route.upload.multipart.onList,\n {\n ...stored,\n uploadId,\n parts,\n },\n config,\n );\n\n return { parts };\n}\n\nexport const multipartListParts = createS3Endpoint(\n S3_API_ROUTES.multipartListParts,\n { method: \"GET\", query: multipartListPartsQuerySchema },\n async (ctx) => {\n return handleListParts(ctx.context.config, ctx.query, ctx.context.request);\n },\n);\n","import { UploadPartCommand } from \"@aws-sdk/client-s3\";\nimport { getSignedUrl } from \"@aws-sdk/s3-request-presigner\";\nimport {\n multipartSignPartBodySchema,\n S3_API_ROUTES,\n type MultipartPartResponse,\n} from \"@dimah-s3/core\";\nimport type * as z from \"zod\";\nimport {\n assertWithinMaxFileSize,\n listAllParts,\n listedPartsByteSize,\n normalizeExpiresIn,\n openStoredTarget,\n runHook,\n} from \"@/helpers\";\nimport type { ResolvedDimahS3Config } from \"@/types\";\nimport { createS3Endpoint } from \"@/api/create-s3-endpoint\";\n\nasync function handleSignPart(\n config: ResolvedDimahS3Config,\n input: z.output<typeof multipartSignPartBodySchema>,\n request: Request,\n): Promise<MultipartPartResponse> {\n const { route, key, bucket, stored } = await openStoredTarget(\n config,\n input,\n request,\n \"multipart\",\n );\n const uploadId = input.uploadId;\n const partNumber = input.partNumber;\n const expiresIn = normalizeExpiresIn(\n route.upload.expiresIn,\n config.maxExpiresIn,\n );\n const partSize = Math.floor(input.partSize);\n\n await runHook(route.upload.multipart.guard, {\n ...stored,\n uploadId,\n action: \"part\",\n partNumber,\n partSize,\n });\n\n const maxFileSize = route.upload.maxFileSize;\n assertWithinMaxFileSize(maxFileSize, partSize);\n if (typeof maxFileSize === \"number\") {\n const listed = await listAllParts(route.client, { bucket, key, uploadId });\n assertWithinMaxFileSize(\n maxFileSize,\n listedPartsByteSize(listed, partNumber) + partSize,\n );\n }\n\n const url = await getSignedUrl(\n route.client,\n new UploadPartCommand({\n Bucket: bucket,\n Key: key,\n UploadId: uploadId,\n PartNumber: partNumber,\n ContentLength: partSize,\n }),\n {\n expiresIn,\n signableHeaders: new Set([\"content-length\"]),\n },\n );\n\n return {\n url,\n partNumber,\n uploadId,\n bucket,\n expiresIn,\n partSize,\n };\n}\n\nexport const multipartPart = createS3Endpoint(\n S3_API_ROUTES.multipartPart,\n { method: \"POST\", body: multipartSignPartBodySchema },\n async (ctx) => {\n return handleSignPart(ctx.context.config, ctx.body, ctx.context.request);\n },\n);\n","import { createPresignedPost } from \"@aws-sdk/s3-presigned-post\";\nimport { getSignedUrl } from \"@aws-sdk/s3-request-presigner\";\nimport { PutObjectCommand } from \"@aws-sdk/client-s3\";\nimport {\n buildContentDisposition,\n S3_API_ROUTES,\n S3_MAX_POST_OBJECT_BYTES,\n uploadBodySchema,\n type UploadPresignResponse,\n} from \"@dimah-s3/core\";\nimport type * as z from \"zod\";\nimport { errors } from \"@/errors\";\nimport {\n normalizeExpiresIn,\n openUploadTarget,\n runHook,\n runLifecycleHook,\n} from \"@/helpers\";\nimport type { ResolvedDimahS3Config } from \"@/types\";\nimport { createS3Endpoint } from \"@/api/create-s3-endpoint\";\n\nfunction objectUserMetadata(\n metadata: Record<string, string> | undefined,\n): Record<string, string> {\n if (!metadata) return {};\n const fields: Record<string, string> = {};\n for (const [k, v] of Object.entries(metadata)) {\n fields[`x-amz-meta-${k}`] = v;\n }\n return fields;\n}\n\nasync function handleUpload(\n config: ResolvedDimahS3Config,\n input: z.output<typeof uploadBodySchema>,\n request: Request,\n): Promise<UploadPresignResponse> {\n const fileSize = Math.floor(input.fileSize);\n const fileName = input.fileName;\n const { route, key, bucket, metadata, acl, stored } = await openUploadTarget(\n config,\n {\n route: input.route,\n fileName,\n fileSize,\n contentType: input.contentType,\n metadata: input.metadata,\n },\n request,\n \"upload\",\n );\n const method = route.upload.method ?? \"POST\";\n if (route.upload.checksum && !input.checksum) {\n throw errors.validationError(\"Checksum is required for this route\");\n }\n if (method === \"POST\" && fileSize > S3_MAX_POST_OBJECT_BYTES) {\n throw errors.payloadTooLarge(\n `POST uploads cannot exceed ${S3_MAX_POST_OBJECT_BYTES} bytes. Enable upload.multipart or set upload.method to \"PUT\".`,\n );\n }\n\n const expiresIn = normalizeExpiresIn(\n route.upload.expiresIn,\n config.maxExpiresIn,\n );\n const contentType = input.contentType ?? \"application/octet-stream\";\n const hookCtx = {\n ...stored,\n file: {\n name: fileName,\n size: fileSize,\n type: input.contentType,\n },\n metadata,\n clientMetadata: input.metadata,\n acl,\n replace: route.upload.replace,\n };\n\n await runHook(route.upload.guard, hookCtx);\n\n if (method === \"PUT\") {\n const putHeaders: Record<string, string> = {\n \"Content-Type\": contentType,\n ...objectUserMetadata(metadata),\n \"Content-Disposition\": buildContentDisposition(fileName),\n ...(input.checksum ? { \"x-amz-checksum-sha256\": input.checksum } : {}),\n };\n\n const url = await getSignedUrl(\n route.client,\n new PutObjectCommand({\n Bucket: bucket,\n Key: key,\n ContentType: contentType,\n ACL: acl,\n Metadata: metadata,\n ContentDisposition: buildContentDisposition(fileName),\n ContentLength: fileSize,\n ...(input.checksum\n ? { ChecksumSHA256: input.checksum, ChecksumAlgorithm: \"SHA256\" }\n : {}),\n }),\n {\n expiresIn,\n signableHeaders: new Set([\n \"content-length\",\n ...(input.checksum ? [\"x-amz-checksum-sha256\"] : []),\n ]),\n },\n );\n\n await runLifecycleHook(\n route.upload.onPresigned,\n {\n ...hookCtx,\n url,\n expiresIn,\n },\n config,\n );\n\n return {\n bucket,\n key,\n url,\n headers: putHeaders,\n expiresIn,\n method: \"PUT\",\n };\n }\n\n const fields: Record<string, string> = {\n acl,\n \"Content-Type\": contentType,\n \"Content-Disposition\": buildContentDisposition(fileName),\n ...objectUserMetadata(metadata),\n ...(input.checksum ? { \"x-amz-checksum-sha256\": input.checksum } : {}),\n };\n\n const { url, fields: signedFields } = await createPresignedPost(\n route.client,\n {\n Bucket: bucket,\n Key: key,\n Conditions: [[\"content-length-range\", fileSize, fileSize]],\n Fields: fields,\n Expires: expiresIn,\n },\n );\n\n await runLifecycleHook(\n route.upload.onPresigned,\n {\n ...hookCtx,\n url,\n expiresIn,\n },\n config,\n );\n\n return {\n bucket,\n key,\n url,\n fields: signedFields,\n expiresIn,\n method: \"POST\",\n };\n}\n\nexport const upload = createS3Endpoint(\n S3_API_ROUTES.upload,\n { method: \"POST\", body: uploadBodySchema },\n async (ctx) => {\n return handleUpload(ctx.context.config, ctx.body, ctx.context.request);\n },\n);\n","import { confirm } from \"./confirm\";\nimport { deleteObject } from \"./delete\";\nimport { deleteBatch } from \"./delete-batch\";\nimport { download } from \"./download\";\nimport { catalog } from \"./catalog\";\nimport { file } from \"./file\";\nimport { multipartAbort } from \"./multipart/abort\";\nimport { multipartComplete } from \"./multipart/complete\";\nimport { multipartInit } from \"./multipart/init\";\nimport { multipartListParts } from \"./multipart/list-parts\";\nimport { multipartPart } from \"./multipart/part\";\nimport { upload } from \"./upload\";\n\n/** Core better-call endpoints — keys become `s3.api.*`. */\nexport const coreEndpoints = {\n upload,\n confirm,\n download,\n catalog,\n file,\n delete: deleteObject,\n deleteBatch,\n multipartInit,\n multipartPart,\n multipartListParts,\n multipartComplete,\n multipartAbort,\n};\n\nexport type CoreEndpoints = typeof coreEndpoints;\n\nexport const CORE_ENDPOINT_NAMES = Object.keys(\n coreEndpoints,\n) as (keyof CoreEndpoints)[];\n","type Hook<Context> = (context: Context) => Promise<void> | void;\n\n/**\n * Compose hooks into one that awaits each in order.\n *\n * Used by {@link dimahS3} when merging plugin + user hooks, and by consumers\n * to stack extras (quota, audit) beside plugin hooks:\n *\n * ```ts\n * upload: {\n * guard: chainHooks(myQuotaGuard, myAuditGuard),\n * }\n * ```\n *\n * `undefined` entries are skipped, so optional hooks compose cleanly.\n */\nexport function chainHooks<Context>(\n ...hooks: (Hook<Context> | undefined)[]\n): (context: Context) => Promise<void> {\n return async (context) => {\n for (const hook of hooks) {\n if (hook) await hook(context);\n }\n };\n}\n","import type {\n DeleteConfig,\n DownloadConfig,\n MultipartConfig,\n RouteFeature,\n UploadConfig,\n} from \"@/types/config\";\n\n/**\n * Hook keys a plugin may contribute per route feature.\n * {@link applyPlugins} merges these ahead of user config hooks.\n */\nexport const FEATURE_HOOK_KEYS = {\n upload: [\"guard\", \"onPresigned\", \"confirmGuard\", \"onConfirmed\"],\n download: [\"guard\", \"onPresigned\"],\n delete: [\"guard\", \"onDeleted\"],\n} as const satisfies {\n [K in RouteFeature]: readonly (keyof (K extends \"upload\"\n ? UploadConfig\n : K extends \"download\"\n ? DownloadConfig\n : DeleteConfig))[];\n};\n\n/** Nested under `upload.multipart` — init/complete share upload hooks. */\nexport const MULTIPART_HOOK_KEYS = [\n \"onInit\",\n \"guard\",\n \"onAbort\",\n \"onList\",\n] as const satisfies readonly (keyof MultipartConfig)[];\n\n/** Lifecycle `on*` keys — merged user-first, plugins last (persist last). */\nexport const LIFECYCLE_FEATURE_HOOK_KEYS = {\n upload: [\"onPresigned\", \"onConfirmed\"],\n download: [\"onPresigned\"],\n delete: [\"onDeleted\"],\n} as const;\n\nexport const LIFECYCLE_MULTIPART_HOOK_KEYS = [\n \"onInit\",\n \"onAbort\",\n \"onList\",\n] as const;\n\nexport type FeatureHookKeyMap = typeof FEATURE_HOOK_KEYS;\nexport type MultipartHookKey = (typeof MULTIPART_HOOK_KEYS)[number];\n","import type { Endpoint } from \"better-call\";\nimport type {\n DeleteConfig,\n DownloadConfig,\n MultipartConfig,\n UploadConfig,\n DimahS3Config,\n ResolvedDimahS3Config,\n} from \"@/types/config\";\nimport type { FeatureHookKeyMap, MultipartHookKey } from \"./hook-registry\";\n\ntype HookFields<T, K extends keyof T> = Pick<T, K>;\n\n/**\n * Hook fields a plugin may contribute. Scalars like `method` /\n * `object` / `acl` stay user-owned on the route `upload` feature.\n * Keys come from {@link FEATURE_HOOK_KEYS} / {@link MULTIPART_HOOK_KEYS}.\n */\nexport type DimahS3PluginHooks = {\n guard?: DimahS3Config[\"guard\"];\n upload?: HookFields<UploadConfig, FeatureHookKeyMap[\"upload\"][number]> & {\n multipart?: HookFields<MultipartConfig, MultipartHookKey>;\n };\n download?: HookFields<DownloadConfig, FeatureHookKeyMap[\"download\"][number]>;\n delete?: HookFields<DeleteConfig, FeatureHookKeyMap[\"delete\"][number]>;\n};\n\n/**\n * Environment passed to {@link DimahS3Plugin.init}.\n * Config is pre-merge (user config only) — use `isFeatureOn` for\n * feature-flag checks. Routes are already validated before `init` runs.\n */\nexport type PluginInitEnv = {\n /** User config before plugin hooks are merged — read-only. */\n config: Readonly<DimahS3Config>;\n /** Lookup another registered plugin by id. */\n getPlugin: (id: string) => DimahS3Plugin | undefined;\n};\n\n/**\n * Server plugin contract. Feature packages (e.g. `@dimah-s3/db`) return\n * these from factories like `db()` / `definePlugin()`.\n *\n * @typeParam Id — unique plugin id; becomes the key on `s3.context` and the\n * flattened instance (`s3[id]`).\n * @typeParam TContext — exposed on `s3.context[id]` and `s3[id]` after\n * `dimahS3()`.\n * @typeParam TEndpoints — better-call endpoints merged onto `s3.api`.\n */\nexport type DimahS3Plugin<\n Id extends string = string,\n TContext extends Record<string, unknown> = Record<string, unknown>,\n TEndpoints extends Record<string, Endpoint> = Record<string, Endpoint>,\n> = {\n /** Unique id — duplicate ids throw at init. */\n id: Id;\n /**\n * Other plugin ids that must be registered. Validated when `dimahS3()`\n * runs — missing deps throw with a clear message.\n * Merge order remains plugins-array order (not topological).\n */\n dependsOn?: readonly string[];\n /**\n * Runs once after the context map is built and before hooks are merged.\n * Synchronous so `dimahS3()` stays a sync factory — validate options /\n * required feature flags here.\n */\n init?: (env: PluginInitEnv) => void;\n /** Lifecycle / guard hooks merged ahead of user config hooks. */\n hooks?: DimahS3PluginHooks;\n /**\n * Extra HTTP routes on the shared handler. Use {@link createS3Endpoint}.\n * Paths are absolute under `basePath` (e.g. `/db/objects`).\n */\n endpoints?: TEndpoints;\n /** Opaque context keyed by `id` on the dimahS3 instance. */\n context?: TContext;\n};\n\nexport type AppliedPlugins<\n C extends Record<string, unknown> = Record<string, unknown>,\n E extends Record<string, Endpoint> = Record<string, Endpoint>,\n> = {\n /** Config with plugin hooks chained ahead of user hooks. */\n config: ResolvedDimahS3Config;\n /** Plugin contexts keyed by plugin id. */\n context: C;\n getPlugin: (id: string) => DimahS3Plugin | undefined;\n /** Plugin HTTP endpoints merged onto `s3.api` and the router. */\n endpoints: E;\n};\n\n/** Map plugin ids → their `context` types. */\nexport type PluginContextMap<P extends readonly DimahS3Plugin[]> = {\n [K in P[number] as K[\"id\"]]: K extends DimahS3Plugin<string, infer Ctx>\n ? Ctx\n : never;\n};\n\n/** Map plugin endpoint names → better-call endpoints. */\nexport type PluginEndpointMap<P extends readonly DimahS3Plugin[]> =\n P extends readonly []\n ? Record<string, never>\n : UnionToIntersection<\n P[number] extends { endpoints?: infer E }\n ? E extends Record<string, Endpoint>\n ? E\n : Record<string, never>\n : Record<string, never>\n >;\n\ntype UnionToIntersection<U> = (\n U extends unknown ? (k: U) => void : never\n) extends (k: infer I) => void\n ? I\n : Record<string, never>;\n\n/** Keys reserved on the dimahS3 instance — plugins may not use these as ids. */\nexport const RESERVED_PLUGIN_IDS = [\n \"handler\",\n \"api\",\n \"context\",\n \"getPlugin\",\n \"$ERROR_CODES\",\n \"$Infer\",\n \"upload\",\n \"confirm\",\n \"download\",\n \"catalog\",\n \"file\",\n \"delete\",\n \"deleteBatch\",\n \"put\",\n \"multipart\",\n] as const;\n\nexport type ReservedPluginId = (typeof RESERVED_PLUGIN_IDS)[number];\n","import { S3_API_ROUTES } from \"@dimah-s3/core\";\nimport type { Endpoint } from \"better-call\";\nimport { CORE_ENDPOINT_NAMES } from \"@/api/routes\";\nimport { isEnabled, normalizeRoutes } from \"@/helpers/features\";\nimport type {\n DimahS3Config,\n ResolvedDimahS3Config,\n ResolvedRoute,\n} from \"@/types\";\nimport { chainHooks } from \"./chain-hooks\";\nimport {\n FEATURE_HOOK_KEYS,\n MULTIPART_HOOK_KEYS,\n LIFECYCLE_FEATURE_HOOK_KEYS,\n LIFECYCLE_MULTIPART_HOOK_KEYS,\n} from \"./hook-registry\";\nimport {\n RESERVED_PLUGIN_IDS,\n type AppliedPlugins,\n type DimahS3Plugin,\n type PluginContextMap,\n} from \"./types\";\n\ntype HookFn = ((context: never) => Promise<void> | void) | undefined;\ntype HookBag = Record<string, HookFn>;\n\nfunction mergeHookField(\n pluginHooks: HookFn[],\n userHook: HookFn,\n order: \"plugins-first\" | \"user-first\" = \"plugins-first\",\n): HookFn | undefined {\n const present = (\n order === \"user-first\"\n ? [userHook, ...pluginHooks]\n : [...pluginHooks, userHook]\n ).filter((h): h is NonNullable<HookFn> => h != null);\n if (present.length === 0) return undefined;\n if (present.length === 1) return present[0];\n return chainHooks(...present) as HookFn;\n}\n\nfunction mergeHooks<T extends object>(\n keys: readonly string[],\n plugins: readonly DimahS3Plugin[],\n userFeature: T,\n pick: (plugin: DimahS3Plugin) => HookBag | undefined,\n lifecycleKeys: ReadonlySet<string> = new Set(),\n): T {\n const merged: HookBag = { ...(userFeature as HookBag) };\n for (const key of keys) {\n const next = mergeHookField(\n plugins.map((plugin) => pick(plugin)?.[key]),\n (userFeature as HookBag)[key],\n lifecycleKeys.has(key) ? \"user-first\" : \"plugins-first\",\n );\n if (next !== undefined) merged[key] = next;\n }\n return merged as T;\n}\n\nfunction applyHooksToRoute(\n route: ResolvedRoute,\n plugins: readonly DimahS3Plugin[],\n): ResolvedRoute {\n const active = plugins.filter((p) => !route.skippedPluginIds.has(p.id));\n\n const upload = isEnabled(route.upload)\n ? {\n ...mergeHooks(\n FEATURE_HOOK_KEYS.upload,\n active,\n route.upload,\n (p) => p.hooks?.upload as HookBag | undefined,\n new Set(LIFECYCLE_FEATURE_HOOK_KEYS.upload),\n ),\n multipart: isEnabled(route.upload.multipart)\n ? mergeHooks(\n MULTIPART_HOOK_KEYS,\n active,\n route.upload.multipart,\n (p) => p.hooks?.upload?.multipart as HookBag | undefined,\n new Set(LIFECYCLE_MULTIPART_HOOK_KEYS),\n )\n : route.upload.multipart,\n }\n : route.upload;\n\n return {\n ...route,\n upload,\n download: isEnabled(route.download)\n ? mergeHooks(\n FEATURE_HOOK_KEYS.download,\n active,\n route.download,\n (p) => p.hooks?.download as HookBag | undefined,\n new Set(LIFECYCLE_FEATURE_HOOK_KEYS.download),\n )\n : route.download,\n delete: isEnabled(route.delete)\n ? mergeHooks(\n FEATURE_HOOK_KEYS.delete,\n active,\n route.delete,\n (p) => p.hooks?.delete as HookBag | undefined,\n new Set(LIFECYCLE_FEATURE_HOOK_KEYS.delete),\n )\n : route.delete,\n };\n}\n\n/**\n * Validate plugins, build context map, collect endpoints, validate routes,\n * run `init`, and merge hooks into each route.\n *\n * Guard / `*Guard` hooks: plugins first (array order), then user.\n * Lifecycle `on*` hooks: user first, then plugins, so `db().markActive`\n * runs last and confirm rollback can still `DeleteObject`.\n *\n * Hooks are not merged onto a feature that is off for that route.\n */\nexport function applyPlugins<\n const P extends readonly DimahS3Plugin[],\n C extends Record<string, unknown> = PluginContextMap<P>,\n>(config: DimahS3Config & { plugins?: P }): AppliedPlugins<C> {\n const plugins = config.plugins ?? [];\n const seen = new Set<string>();\n const byId = new Map<string, DimahS3Plugin>();\n const context = {} as C;\n const getPlugin = (id: string) => byId.get(id);\n\n for (const plugin of plugins) {\n if ((RESERVED_PLUGIN_IDS as readonly string[]).includes(plugin.id)) {\n throw new Error(\n `Plugin id \"${plugin.id}\" is reserved on the dimahS3 instance. Choose a different id.`,\n );\n }\n if (seen.has(plugin.id)) {\n throw new Error(\n `Duplicate dimah-s3 plugin id \"${plugin.id}\". Each plugin id must be unique.`,\n );\n }\n seen.add(plugin.id);\n byId.set(plugin.id, plugin);\n }\n\n for (const plugin of plugins) {\n for (const dep of plugin.dependsOn ?? []) {\n if (!seen.has(dep)) {\n throw new Error(\n `Plugin \"${plugin.id}\" depends on \"${dep}\", which is not registered.`,\n );\n }\n }\n }\n\n const visiting = new Set<string>();\n const visited = new Set<string>();\n function visit(id: string, stack: string[]) {\n if (visited.has(id)) return;\n if (visiting.has(id)) {\n throw new Error(\n `Circular plugin dependency detected: ${[...stack, id].join(\" -> \")}.`,\n );\n }\n visiting.add(id);\n const plugin = byId.get(id);\n for (const dep of plugin?.dependsOn ?? []) {\n visit(dep, [...stack, id]);\n }\n visiting.delete(id);\n visited.add(id);\n }\n for (const plugin of plugins) {\n visit(plugin.id, []);\n }\n\n for (const plugin of plugins) {\n if (plugin.context !== undefined) {\n (context as Record<string, unknown>)[plugin.id] = plugin.context;\n }\n }\n\n const reservedRoutePaths = new Set<string>(Object.values(S3_API_ROUTES));\n const reservedNames = new Set<string>([...CORE_ENDPOINT_NAMES, \"multipart\"]);\n const seenEndpointKeys = new Set<string>();\n const endpoints: Record<string, Endpoint> = {};\n\n for (const plugin of plugins) {\n for (const [name, endpoint] of Object.entries(plugin.endpoints ?? {})) {\n if (reservedNames.has(name) || name in endpoints) {\n throw new Error(\n `Plugin \"${plugin.id}\" endpoint \"${name}\" collides with an existing endpoint.`,\n );\n }\n const path = endpoint.path;\n if (typeof path !== \"string\" || !path.startsWith(\"/\")) {\n throw new Error(\n `Plugin \"${plugin.id}\" endpoint \"${name}\" path must start with \"/\".`,\n );\n }\n if (reservedRoutePaths.has(path)) {\n throw new Error(\n `Plugin \"${plugin.id}\" endpoint \"${name}\" collides with a core route.`,\n );\n }\n const methods = Array.isArray(endpoint.options.method)\n ? endpoint.options.method\n : [endpoint.options.method];\n for (const method of methods) {\n const routeKey = `${method} ${path}`;\n if (seenEndpointKeys.has(routeKey)) {\n throw new Error(`Duplicate plugin endpoint ${routeKey}.`);\n }\n seenEndpointKeys.add(routeKey);\n }\n endpoints[name] = endpoint;\n }\n }\n\n const { plugins: _omit, ...rest } = config;\n const normalized = normalizeRoutes(rest);\n\n for (const plugin of plugins) {\n plugin.init?.({ config: rest, getPlugin });\n }\n const routes: Record<string, ResolvedRoute> = {};\n for (const [name, route] of Object.entries(normalized)) {\n routes[name] = applyHooksToRoute(route, plugins);\n }\n\n const guard = mergeHookField(\n plugins.map((p) => p.hooks?.guard as HookFn),\n rest.guard as HookFn,\n ) as ResolvedDimahS3Config[\"guard\"];\n\n const merged: ResolvedDimahS3Config = {\n ...rest,\n routes,\n ...(guard !== undefined ? { guard } : {}),\n };\n\n return {\n config: merged,\n context,\n getPlugin,\n endpoints,\n };\n}\n","import type { Endpoint } from \"better-call\";\nimport type { DimahS3Plugin } from \"./types\";\n\n/**\n * Identity helper that preserves literal `id`, context, and endpoint types\n * for {@link dimahS3} inference (`s3.context[id]` / `s3.api`).\n */\nexport function definePlugin<\n Id extends string,\n TContext extends Record<string, unknown> = Record<string, unknown>,\n TEndpoints extends Record<string, Endpoint> = Record<string, Endpoint>,\n>(\n plugin: DimahS3Plugin<Id, TContext, TEndpoints>,\n): DimahS3Plugin<Id, TContext, TEndpoints> {\n return plugin;\n}\n","import { type Endpoint } from \"better-call\";\nimport type { S3EndpointContext } from \"./context\";\nimport { requestFromHeaders } from \"@/helpers\";\n\n/**\n * Wrap better-call endpoints so `s3.api.upload({ body, headers })` injects\n * `routerContext` the same way HTTP `createRouter` does.\n */\nexport function bindEndpoints<E extends Record<string, Endpoint>>(\n endpoints: E,\n context: Pick<S3EndpointContext, \"config\">,\n): E {\n const api = {} as E;\n\n for (const [key, endpoint] of Object.entries(endpoints)) {\n const bound = (async (input: Record<string, unknown> = {}) => {\n const headers = input.headers as HeadersInit | undefined;\n const request =\n (input.request as Request | undefined) ?? requestFromHeaders(headers);\n return endpoint({\n ...input,\n headers: headers ?? request.headers,\n request,\n context,\n });\n }) as typeof endpoint;\n\n bound.path = endpoint.path;\n bound.options = endpoint.options;\n api[key as keyof E] = bound as E[keyof E];\n }\n\n return api;\n}\n","import { createRouter, toResponse, type Endpoint } from \"better-call\";\nimport {\n isAPIError,\n normalizeS3ApiBasePath,\n S3_API_BASE_PATH,\n} from \"@dimah-s3/core\";\nimport { errors } from \"@/errors\";\nimport { resolveLogger } from \"@/helpers/logger\";\nimport { bindEndpoints } from \"./bind-endpoints\";\nimport type { ResolvedDimahS3Config } from \"@/types\";\n\nconst NETWORK_CODES = new Set([\n \"EAI_AGAIN\",\n \"ECONNREFUSED\",\n \"ECONNRESET\",\n \"ETIMEDOUT\",\n \"ENOTFOUND\",\n]);\n\n/**\n * better-call `onError`: APIError (including DimahS3Error) serializes\n * natively. Unknown throws become INTERNAL_ERROR / S3_NETWORK_ERROR.\n */\nfunction onS3RouterError(error: unknown, config?: ResolvedDimahS3Config): void {\n if (isAPIError(error)) return;\n\n const code = (error as { code?: string })?.code;\n const logger = resolveLogger(config?.logger);\n if (typeof code === \"string\" && NETWORK_CODES.has(code)) {\n const networkErr = errors.s3NetworkError(code);\n logger.error?.(networkErr.message, error);\n config?.onError?.(error, {});\n throw networkErr;\n }\n\n logger.error?.(error instanceof Error ? error.message : String(error), error);\n config?.onError?.(error, {});\n throw errors.internalError();\n}\n\n/**\n * Unmatched routes never hit `onError` — better-call returns an empty 404.\n * Re-serialize those as DimahS3Error JSON. JSON 404s from endpoints pass through.\n */\nfunction withUnmatchedRouteJson(\n handler: (request: Request) => Promise<Response>,\n): (request: Request) => Promise<Response> {\n return async (request) => {\n const response = await handler(request);\n if (response.status !== 404) return response;\n const contentType = response.headers.get(\"content-type\") ?? \"\";\n if (contentType.includes(\"application/json\")) return response;\n return toResponse(errors.notFound());\n };\n}\n\n/**\n * Internal better-call router with dimah-s3 context, OpenAPI off, and native\n * APIError JSON. Not part of the public package surface.\n */\nexport function createS3Router<E extends Record<string, Endpoint>>(\n endpoints: E,\n env: { config: ResolvedDimahS3Config },\n) {\n const basePath = normalizeS3ApiBasePath(\n env.config.basePath ?? S3_API_BASE_PATH,\n );\n\n const router = createRouter(endpoints, {\n basePath,\n routerContext: { config: env.config },\n openapi: { disabled: true },\n onError: (error) => onS3RouterError(error, env.config),\n });\n\n return {\n endpoints: bindEndpoints(router.endpoints, { config: env.config }),\n handler: withUnmatchedRouteJson(router.handler),\n };\n}\n","import { S3_ERROR_CODES } from \"@dimah-s3/core\";\nimport { putObject, type PutObjectInput } from \"./put\";\nimport {\n applyPlugins,\n type DimahS3Plugin,\n type PluginContextMap,\n type PluginEndpointMap,\n} from \"./plugin\";\nimport { coreEndpoints, type CoreEndpoints } from \"./api/routes\";\nimport { createS3Router } from \"./api/router\";\nimport type { DimahS3Config, DimahS3RouteConfig } from \"./types\";\n\nexport type MultipartAliasApi = {\n init: CoreEndpoints[\"multipartInit\"];\n signPart: CoreEndpoints[\"multipartPart\"];\n listParts: CoreEndpoints[\"multipartListParts\"];\n complete: CoreEndpoints[\"multipartComplete\"];\n abort: CoreEndpoints[\"multipartAbort\"];\n};\n\nexport type DimahS3Api<P extends readonly DimahS3Plugin[] = []> =\n CoreEndpoints & {\n multipart: MultipartAliasApi;\n deleteMany: CoreEndpoints[\"deleteBatch\"];\n } & PluginEndpointMap<P>;\n\nexport type DimahS3<\n P extends readonly DimahS3Plugin[] = [],\n C extends Record<string, unknown> = PluginContextMap<P>,\n R extends Record<string, DimahS3RouteConfig> = Record<\n string,\n DimahS3RouteConfig\n >,\n> = {\n /** Framework-agnostic HTTP handler (`Request` → `Response`). */\n handler: (request: Request) => Promise<Response>;\n /**\n * better-call endpoints — invoke as functions from Server Actions / RSC.\n *\n * ```ts\n * await s3.api.download({ query: { route, key }, headers: await headers() });\n * await s3.api.multipart.init({ body: { route, fileName, fileSize } });\n * ```\n */\n api: DimahS3Api<P>;\n /** Plugin contexts keyed by plugin id. */\n context: C;\n /** Lookup a registered plugin by id. */\n getPlugin: {\n <Id extends P[number][\"id\"]>(\n id: Id,\n ): Extract<P[number], { id: Id }> | undefined;\n (id: string): DimahS3Plugin | undefined;\n };\n $ERROR_CODES: typeof S3_ERROR_CODES;\n $Infer: {\n api: DimahS3Api<P>;\n context: C;\n routes: keyof R & string;\n };\n /**\n * Server-side upload through the same route policy as presign + confirm.\n */\n put: (\n input: PutObjectInput,\n ) => Promise<import(\"@dimah-s3/core\").ConfirmedObjectResponse>;\n} & C;\n\n/**\n * Create a dimah-s3 server instance.\n *\n * Plugin contexts are available on `s3.context[id]` and flattened onto the\n * instance itself (`s3.db` when the `db` plugin is registered, etc.).\n *\n * @example\n * ```ts\n * export const awsS3 = new S3Client({ ... });\n * export const s3 = dimahS3({\n * client: awsS3,\n * bucket: \"my-bucket\",\n * routes: {\n * uploads: route({ upload: { fileTypes: [\"image/*\"] } }),\n * invoices: route({ download: true }),\n * },\n * });\n *\n * export const { GET, POST, PUT, PATCH, DELETE } = toNextJsHandler(s3);\n *\n * await s3.api.download({ query: { route: \"invoices\", key }, headers: await headers() });\n * ```\n */\nexport function dimahS3<\n const P extends readonly DimahS3Plugin[] = [],\n const R extends Record<string, DimahS3RouteConfig> = Record<\n string,\n DimahS3RouteConfig\n >,\n>(\n config: DimahS3Config & { plugins?: P; routes: R },\n): DimahS3<P, PluginContextMap<P>, R> {\n const {\n config: resolved,\n context,\n getPlugin,\n endpoints: pluginEndpoints,\n } = applyPlugins(config);\n\n const endpoints = { ...coreEndpoints, ...pluginEndpoints };\n const router = createS3Router(endpoints, { config: resolved });\n const bound = router.endpoints as CoreEndpoints & PluginEndpointMap<P>;\n\n const api = {\n ...bound,\n deleteMany: bound.deleteBatch,\n multipart: {\n init: bound.multipartInit,\n signPart: bound.multipartPart,\n listParts: bound.multipartListParts,\n complete: bound.multipartComplete,\n abort: bound.multipartAbort,\n },\n } as DimahS3<P, PluginContextMap<P>, R>[\"api\"];\n\n return {\n handler: router.handler,\n api,\n context,\n getPlugin,\n $ERROR_CODES: S3_ERROR_CODES,\n $Infer: {} as DimahS3<P, PluginContextMap<P>, R>[\"$Infer\"],\n put: (input) => putObject(resolved, input),\n ...context,\n } as DimahS3<P, PluginContextMap<P>, R>;\n}\n","import type { S3Client } from \"@aws-sdk/client-s3\";\nimport type { S3ObjectAcl, UploadPresignMethod } from \"@dimah-s3/core\";\nimport type {\n DeleteGuardContext,\n DeleteOnDeletedContext,\n DownloadGuardContext,\n DownloadOnPresignedContext,\n DownloadResolveInfo,\n GuardContext,\n MultipartGuardContext,\n MultipartOnAbortContext,\n MultipartOnInitContext,\n MultipartOnListContext,\n RouteGuardContext,\n UploadConfirmGuardContext,\n UploadGuardContext,\n UploadObjectContext,\n UploadObjectInfo,\n UploadOnConfirmedContext,\n UploadOnPresignedContext,\n} from \"./hook-contexts\";\nimport type { DimahS3Plugin } from \"@/plugin/types\";\n\nexport type { UploadObjectContext, UploadObjectInfo, DownloadResolveInfo };\n\n/** The three nested features on a named route. */\nexport const ROUTE_FEATURES = [\"upload\", \"download\", \"delete\"] as const;\nexport type RouteFeature = (typeof ROUTE_FEATURES)[number];\n\n/**\n * Endpoint operations. Multipart is nested under upload — it is not a\n * fourth route feature.\n */\nexport const ROUTE_OPERATIONS = [...ROUTE_FEATURES, \"multipart\"] as const;\nexport type RouteOperation = (typeof ROUTE_OPERATIONS)[number];\n\n/** `true` or an options object enables the feature; omit or `false` disables it. */\nexport type FeatureToggle<T> = boolean | T;\n\n/** Optional structured logger on {@link DimahS3Config}. */\nexport type DimahS3Logger = {\n debug?: (message: string, ...args: unknown[]) => void;\n info?: (message: string, ...args: unknown[]) => void;\n warn?: (message: string, ...args: unknown[]) => void;\n error?: (message: string, ...args: unknown[]) => void;\n};\n\nexport type DisabledFeature = { enabled: false };\nexport type EnabledFeature<T extends object> = T & { enabled: true };\nexport type ResolvedFeature<T extends object> =\n EnabledFeature<T> | DisabledFeature;\n\n/**\n * Multipart-only hooks. Init shares `upload.guard` / `onInit`. Complete\n * runs `guard` (`action: \"complete\"`) then `upload.confirmGuard` /\n * `upload.onConfirmed`.\n */\nexport type MultipartConfig = {\n /** After `CreateMultipartUpload` — persist `uploadId` for resume. */\n onInit?: (context: MultipartOnInitContext) => Promise<void> | void;\n /** Authorize part, list, abort, and complete. Branch on `action` if needed. */\n guard?: (context: MultipartGuardContext) => Promise<void> | void;\n onAbort?: (context: MultipartOnAbortContext) => Promise<void> | void;\n onList?: (context: MultipartOnListContext) => Promise<void> | void;\n};\n\n/** Upload feature: constraints, object identity, and lifecycle hooks. */\nexport type UploadConfig = {\n /** HTML `accept` tokens (`image/*`, `.pdf`, `application/pdf`). */\n fileTypes?: string[];\n /**\n * Max declared size, signed part size, listed multipart total, and\n * HeadObject size in bytes.\n */\n maxFileSize?: number;\n /**\n * Server-owned object identity. Return `folder` for a directory under\n * the route `keyPrefix`, `key` for the rest of the key (also nested\n * under `keyPrefix`), plus optional S3 `metadata` and `acl`.\n * Runs on upload / multipart init only. Default key is\n * `{keyPrefix}/{uuid}/{name}` (`keyPrefix` defaults to the route name).\n * `keyPrefix: false` generates `{uuid}/{name}` and skips the follow-up\n * namespace check.\n */\n object?: (\n context: UploadObjectContext,\n ) => UploadObjectInfo | void | Promise<UploadObjectInfo | void>;\n /**\n * Server-forced ACL when `object` does not return one.\n * @default \"private\"\n */\n acl?: S3ObjectAcl;\n /** Presign verb. Use `\"PUT\"` on R2 (no Presigned POST). @default \"POST\" */\n method?: UploadPresignMethod;\n /** Presign TTL in seconds. Clamped by instance `maxExpiresIn`. */\n expiresIn?: number;\n /**\n * Require a SHA-256 `checksum` on the presign body and lock it into the\n * signed PUT/POST.\n */\n checksum?: boolean;\n /**\n * Overwrite an existing object at the resolved key without flipping a\n * `db()` row from `active` to `pending` during the new upload.\n */\n replace?: \"overwrite\";\n /** Presign and multipart init. */\n guard?: (context: UploadGuardContext) => Promise<void> | void;\n /** After a single-shot URL is signed. Multipart uses `multipart.onInit`. */\n onPresigned?: (context: UploadOnPresignedContext) => Promise<void> | void;\n /** Confirm and multipart complete. */\n confirmGuard?: (context: UploadConfirmGuardContext) => Promise<void> | void;\n /** After HeadObject on confirm and multipart complete. */\n onConfirmed?: (context: UploadOnConfirmedContext) => Promise<void> | void;\n /** Opt-in multipart. Default off. */\n multipart?: FeatureToggle<MultipartConfig>;\n};\n\n/** Download feature. A config object (or `true`) enables the feature. */\nexport type DownloadConfig = {\n /**\n * Presign TTL in seconds. Defaults to `S3_DEFAULT_EXPIRES_IN` (600).\n * Independent of {@link UploadConfig.expiresIn}.\n */\n expiresIn?: number;\n /**\n * Default Content-Disposition. @default \"attachment\"\n */\n disposition?: \"inline\" | \"attachment\";\n /**\n * `\"presign\"` (default) returns an S3 URL. `\"proxy\"` returns a\n * same-origin `/file` URL that streams through the server.\n */\n mode?: \"presign\" | \"proxy\";\n /**\n * Per-request download options. Return values override route defaults.\n * The client `disposition` / `fileName` query is a fallback.\n */\n resolve?: (\n context: DownloadGuardContext,\n ) => DownloadResolveInfo | void | Promise<DownloadResolveInfo | void>;\n guard?: (context: DownloadGuardContext) => Promise<void> | void;\n onPresigned?: (context: DownloadOnPresignedContext) => Promise<void> | void;\n};\n\n/** Delete feature. A config object (or `true`) enables the feature. */\nexport type DeleteConfig = {\n guard?: (context: DeleteGuardContext) => Promise<void> | void;\n onDeleted?: (context: DeleteOnDeletedContext) => Promise<void> | void;\n};\n\n/**\n * Named file route — a mini {@link DimahS3Config} under `routes`.\n * Upload, download, delete, and `upload.multipart` are off until set.\n * Prefer one feature per route; combine only when those callers share\n * the key namespace.\n */\nexport type DimahS3RouteConfig = {\n /** Override the instance S3 client for this route. */\n client?: S3Client;\n /** Override the instance bucket for this route. */\n bucket?: string;\n /**\n * Object-key namespace. Generated keys and follow-up ops (confirm,\n * download, delete, multipart) must stay under it.\n * Defaults to the route name. `false` disables the bound.\n */\n keyPrefix?: string | false;\n /** Runs before every operation on this route. */\n guard?: (context: RouteGuardContext) => Promise<void> | void;\n /**\n * Opt out of instance plugins by id (`{ db: false }`).\n * Hooks from opted-out plugins are not merged onto this route.\n */\n plugins?: { readonly [pluginId: string]: false };\n upload?: FeatureToggle<UploadConfig>;\n download?: FeatureToggle<DownloadConfig>;\n delete?: FeatureToggle<DeleteConfig>;\n};\n\n/**\n * Options for {@link dimahS3}.\n *\n * @example\n * ```ts\n * export const s3 = dimahS3({\n * client: awsS3,\n * bucket: \"my-bucket\",\n * routes: {\n * uploads: route({\n * upload: { fileTypes: [\"image/*\"], multipart: true },\n * }),\n * },\n * });\n * ```\n */\nexport type DimahS3Config = {\n /**\n * Default AWS SDK v3 `S3Client`. Required unless every route sets\n * {@link DimahS3RouteConfig.client}.\n */\n client?: S3Client;\n /**\n * Default bucket. Required unless every route sets\n * {@link DimahS3RouteConfig.bucket}.\n */\n bucket?: string;\n /**\n * API path prefix for the HTTP `handler`.\n * Must match `createS3Client({ basePath })` on the client.\n * @default \"/api/s3\"\n */\n basePath?: string;\n /**\n * Upper bound for `upload.expiresIn` and `download.expiresIn` (seconds).\n * The protocol maximum is 7 days (604800).\n * @default 604800\n */\n maxExpiresIn?: number;\n /**\n * Structured logs for lifecycle failures and unmatched router errors.\n * `false` silences the default `console.error`.\n */\n logger?: DimahS3Logger | false;\n /** Called after an unexpected throw is mapped to `INTERNAL_ERROR`. */\n onError?: (error: unknown, context: { request?: Request }) => void;\n /** Runs before every operation, before route lookup. Throw to reject. */\n guard?: (context: GuardContext) => Promise<void> | void;\n /**\n * Optional server plugins (e.g. `db()` from `@dimah-s3/db`).\n * Plugin hooks merge onto each route unless the route opts out.\n */\n plugins?: readonly DimahS3Plugin[];\n /** Named file routes. At least one is required. */\n routes: Record<string, DimahS3RouteConfig>;\n};\n\ntype UploadFields = Omit<UploadConfig, \"multipart\">;\n\nexport type EnabledUploadConfig = EnabledFeature<UploadFields> & {\n multipart: ResolvedFeature<MultipartConfig>;\n};\n\nexport type ResolvedUploadConfig =\n EnabledUploadConfig | (DisabledFeature & { multipart: DisabledFeature });\n\n/** One named route after {@link dimahS3} normalizes toggles and plugin hooks. */\nexport type ResolvedRoute = {\n name: string;\n client: S3Client;\n bucket: string;\n /** `false` means follow-up keys are not namespace-checked. */\n keyPrefix: string | false;\n guard?: DimahS3RouteConfig[\"guard\"];\n skippedPluginIds: ReadonlySet<string>;\n upload: ResolvedUploadConfig;\n download: ResolvedFeature<DownloadConfig>;\n delete: ResolvedFeature<DeleteConfig>;\n};\n\n/**\n * A {@link ResolvedRoute} after the named operation has been asserted on.\n * `route.upload.fileTypes` is typed as present only after opening `\"upload\"`.\n */\nexport type OpenedRoute<F extends RouteOperation> = F extends \"multipart\"\n ? ResolvedRoute & {\n upload: EnabledUploadConfig & {\n multipart: EnabledFeature<MultipartConfig>;\n };\n }\n : F extends \"upload\"\n ? ResolvedRoute & { upload: EnabledUploadConfig }\n : F extends \"download\"\n ? ResolvedRoute & { download: EnabledFeature<DownloadConfig> }\n : F extends \"delete\"\n ? ResolvedRoute & { delete: EnabledFeature<DeleteConfig> }\n : never;\n\n/** Instance config after {@link dimahS3} normalizes routes and plugins. */\nexport type ResolvedDimahS3Config = Omit<\n DimahS3Config,\n \"routes\" | \"plugins\"\n> & {\n routes: Record<string, ResolvedRoute>;\n};\n"]}
|