{"version":3,"sources":["../src/errors.ts","../src/utils/auth.ts","../src/utils/cors.ts","../src/utils/logging.ts","../src/utils/rate-limit.ts","../src/utils/validate.ts"],"names":["RouteComposeError","message","code","statusCode","UnauthorizedError","ForbiddenError","RateLimitError","retryAfter","headers","ValidationError","details","BadRequestError","NotFoundError","defaultErrorHandler","error","withAuth","options","verify","onUnauthorized","handler","context","user","enrichedContext","withOptionalAuth","DEFAULT_METHODS","DEFAULT_HEADERS","withCors","origin","methods","allowedHeaders","exposedHeaders","credentials","maxAge","requestOrigin","allowedOrigin","corsHeaders","response","newHeaders","key","value","defaultLogger","data","headersToObject","result","logByLevel","level","logger","withLogging","includeBody","includeResponse","startTime","requestId","requestData","clonedRequest","duration","responseData","clonedResponse","withTiming","store","cleanupStore","now","defaultKeyGenerator","withRateLimit","limit","window","keyGenerator","onRateLimited","windowMs","entry","remaining","reset","createRateLimiter","customStore","withValidation","schema","source","formatError","url","formatZodError","issues","formatted","issue","path","withMultiValidation","schemas","validated","errors"],"mappings":"aAGO,IAAMA,CAAAA,CAAN,cAAgC,KAAM,CACzC,YACIC,CAAAA,CACgBC,CAAAA,CACAC,EAAqB,GAAA,CACvC,CACE,MAAMF,CAAO,CAAA,CAHG,UAAAC,CAAAA,CACA,IAAA,CAAA,UAAA,CAAAC,EAGhB,IAAA,CAAK,IAAA,CAAO,oBAChB,CAKA,UAAA,EAAuB,CACnB,OAAO,QAAA,CAAS,KACZ,CACI,KAAA,CAAO,CACH,IAAA,CAAM,IAAA,CAAK,KACX,OAAA,CAAS,IAAA,CAAK,OAClB,CACJ,CAAA,CACA,CAAE,MAAA,CAAQ,IAAA,CAAK,UAAW,CAC9B,CACJ,CACJ,CAAA,CAKaC,CAAAA,CAAN,cAAgCJ,CAAkB,CACrD,WAAA,CAAYC,EAAU,cAAA,CAAgB,CAClC,MAAMA,CAAAA,CAAS,cAAA,CAAgB,GAAG,CAAA,CAClC,IAAA,CAAK,KAAO,oBAChB,CACJ,EAKaI,CAAAA,CAAN,cAA6BL,CAAkB,CAClD,WAAA,CAAYC,EAAU,WAAA,CAAa,CAC/B,MAAMA,CAAAA,CAAS,WAAA,CAAa,GAAG,CAAA,CAC/B,IAAA,CAAK,KAAO,iBAChB,CACJ,EAKaK,CAAAA,CAAN,cAA6BN,CAAkB,CAClD,WAAA,CACIC,EAAU,mBAAA,CACMM,CAAAA,CAClB,CACE,KAAA,CAAMN,CAAAA,CAAS,cAAA,CAAgB,GAAG,CAAA,CAFlB,IAAA,CAAA,UAAA,CAAAM,EAGhB,IAAA,CAAK,IAAA,CAAO,iBAChB,CAES,UAAA,EAAuB,CAC5B,IAAMC,CAAAA,CAAuB,EAAC,CAC9B,OAAI,KAAK,UAAA,GAAe,MAAA,GACpBA,EAAQ,aAAa,CAAA,CAAI,OAAO,IAAA,CAAK,UAAU,GAE5C,QAAA,CAAS,IAAA,CACZ,CACI,KAAA,CAAO,CACH,KAAM,IAAA,CAAK,IAAA,CACX,QAAS,IAAA,CAAK,OAClB,CACJ,CAAA,CACA,CAAE,OAAQ,IAAA,CAAK,UAAA,CAAY,QAAAA,CAAQ,CACvC,CACJ,CACJ,CAAA,CAKaC,CAAAA,CAAN,cAA8BT,CAAkB,CACnD,YACIC,CAAAA,CAAU,mBAAA,CACMS,EAClB,CACE,KAAA,CAAMT,EAAS,kBAAA,CAAoB,GAAG,EAFtB,IAAA,CAAA,OAAA,CAAAS,CAAAA,CAGhB,KAAK,IAAA,CAAO,kBAChB,CAES,UAAA,EAAuB,CAC5B,OAAO,QAAA,CAAS,IAAA,CACZ,CACI,KAAA,CAAO,CACH,IAAA,CAAM,KAAK,IAAA,CACX,OAAA,CAAS,KAAK,OAAA,CACd,OAAA,CAAS,KAAK,OAClB,CACJ,EACA,CAAE,MAAA,CAAQ,KAAK,UAAW,CAC9B,CACJ,CACJ,CAAA,CAKaC,EAAN,cAA8BX,CAAkB,CACnD,WAAA,CAAYC,CAAAA,CAAU,aAAA,CAAe,CACjC,KAAA,CAAMA,CAAAA,CAAS,cAAe,GAAG,CAAA,CACjC,KAAK,IAAA,CAAO,kBAChB,CACJ,CAAA,CAKaW,CAAAA,CAAN,cAA4BZ,CAAkB,CACjD,YAAYC,CAAAA,CAAU,WAAA,CAAa,CAC/B,KAAA,CAAMA,CAAAA,CAAS,YAAa,GAAG,CAAA,CAC/B,KAAK,IAAA,CAAO,gBAChB,CACJ,EAKO,SAASY,EAAoBC,CAAAA,CAA0B,CAC1D,OAAIA,CAAAA,YAAiBd,CAAAA,CACVc,EAAM,UAAA,EAAW,EAG5B,QAAQ,KAAA,CAAM,uCAAA,CAAyCA,CAAK,CAAA,CAErD,QAAA,CAAS,IAAA,CACZ,CACI,KAAA,CAAO,CACH,KAAM,gBAAA,CACN,OAAA,CAAS,uBACb,CACJ,CAAA,CACA,CAAE,MAAA,CAAQ,GAAI,CAClB,CAAA,CACJ,CCvHO,SAASC,CAAAA,CAA0BC,CAAAA,CAA6C,CACnF,GAAM,CACF,OAAAC,CAAAA,CACA,cAAA,CAAAC,CAAAA,CAAiB,IAAM,IAAId,CAAAA,GAAoB,UAAA,EACnD,EAAIY,CAAAA,CAEJ,OAAQG,GACG,MAAOC,CAAAA,EAA4B,CACtC,IAAMC,CAAAA,CAAO,MAAMJ,CAAAA,CAAOG,CAAO,EAEjC,GAAIC,CAAAA,EAAS,KACT,OAAO,MAAMH,CAAAA,CAAeE,CAAO,CAAA,CAIvC,IAAME,EAAkC,CACpC,GAAGF,EACH,IAAA,CAAAC,CACJ,EAEA,OAAO,MAAMF,EAAQG,CAAe,CACxC,CAER,CAkBO,SAASC,EACZP,CAAAA,CACc,CACd,GAAM,CAAE,MAAA,CAAAC,CAAO,CAAA,CAAID,CAAAA,CAEnB,OAAQG,CAAAA,EACG,MAAOC,GAA4B,CACtC,IAAMC,EAAO,MAAMJ,CAAAA,CAAOG,CAAO,CAAA,CAE3BE,CAAAA,CAAkC,CACpC,GAAGF,CAAAA,CACH,KAAMC,CAAAA,EAAQ,IAClB,EAEA,OAAO,MAAMF,CAAAA,CAAQG,CAAe,CACxC,CAER,CChFA,IAAME,CAAAA,CAAkB,CAAC,KAAA,CAAO,MAAA,CAAQ,MAAO,OAAA,CAAS,MAAA,CAAQ,QAAQ,CAAA,CAClEC,CAAAA,CAAkB,CAAC,cAAA,CAAgB,eAAe,EAmBjD,SAASC,CAAAA,CAASV,EAAuB,EAAC,CAAmB,CAChE,GAAM,CACF,MAAA,CAAAW,EAAS,GAAA,CACT,OAAA,CAAAC,EAAUJ,CAAAA,CACV,cAAA,CAAAK,EAAiBJ,CAAAA,CACjB,cAAA,CAAAK,EAAiB,EAAC,CAClB,YAAAC,CAAAA,CAAc,KAAA,CACd,OAAAC,CAAAA,CAAS,KACb,EAAIhB,CAAAA,CAEJ,OAAQG,CAAAA,EACG,MAAOC,CAAAA,EAA4B,CACtC,IAAMa,CAAAA,CAAgBb,CAAAA,CAAQ,QAAQ,OAAA,CAAQ,GAAA,CAAI,QAAQ,CAAA,EAAK,EAAA,CAG3Dc,EACAP,CAAAA,GAAW,GAAA,CACXO,EAAgB,GAAA,CACT,OAAOP,GAAW,QAAA,CACzBO,CAAAA,CAAgBP,EACT,KAAA,CAAM,OAAA,CAAQA,CAAM,CAAA,CAC3BO,CAAAA,CAAgBP,EAAO,QAAA,CAASM,CAAa,EAAIA,CAAAA,CAAgB,EAAA,CAC1D,OAAON,CAAAA,EAAW,UAAA,CACzBO,EAAgBP,CAAAA,CAAOM,CAAa,EAAIA,CAAAA,CAAgB,EAAA,CAExDC,EAAgB,EAAA,CAIpB,IAAMC,EAA2B,CAC7B,6BAAA,CAA+BD,CAAAA,CAC/B,8BAAA,CAAgCN,CAAAA,CAAQ,IAAA,CAAK,IAAI,CAAA,CACjD,8BAAA,CAAgCC,EAAe,IAAA,CAAK,IAAI,CAC5D,CAAA,CAeA,GAbIC,EAAe,MAAA,CAAS,CAAA,GACxBK,EAAY,+BAA+B,CAAA,CAAIL,EAAe,IAAA,CAAK,IAAI,GAGvEC,CAAAA,GACAI,CAAAA,CAAY,kCAAkC,CAAA,CAAI,MAAA,CAAA,CAGlDH,CAAAA,CAAS,IACTG,CAAAA,CAAY,wBAAwB,EAAI,MAAA,CAAOH,CAAM,GAIrDZ,CAAAA,CAAQ,OAAA,CAAQ,SAAW,SAAA,CAC3B,OAAO,IAAI,QAAA,CAAS,IAAA,CAAM,CACtB,MAAA,CAAQ,GAAA,CACR,QAASe,CACb,CAAC,CAAA,CAIL,IAAMC,CAAAA,CAAW,MAAMjB,EAAQC,CAAO,CAAA,CAGhCiB,EAAa,IAAI,OAAA,CAAQD,EAAS,OAAO,CAAA,CAC/C,OAAW,CAACE,CAAAA,CAAKC,CAAK,CAAA,GAAK,MAAA,CAAO,QAAQJ,CAAW,CAAA,CACjDE,EAAW,GAAA,CAAIC,CAAAA,CAAKC,CAAK,CAAA,CAG7B,OAAO,IAAI,QAAA,CAASH,CAAAA,CAAS,KAAM,CAC/B,MAAA,CAAQA,EAAS,MAAA,CACjB,UAAA,CAAYA,EAAS,UAAA,CACrB,OAAA,CAASC,CACb,CAAC,CACL,CAER,CCxFA,SAASG,EAAcvC,CAAAA,CAAiBwC,CAAAA,CAAqC,CACzE,OAAA,CAAQ,GAAA,CAAI,IAAA,CAAK,UAAU,CAAE,OAAA,CAAAxC,EAAS,GAAGwC,CAAAA,CAAM,UAAW,IAAI,IAAA,GAAO,WAAA,EAAc,CAAC,CAAC,EACzF,CAKA,SAASC,CAAAA,CAAgBlC,EAA0C,CAC/D,IAAMmC,CAAAA,CAAiC,EAAC,CACxC,OAAAnC,EAAQ,OAAA,CAAQ,CAAC+B,EAAOD,CAAAA,GAAQ,CAC5BK,EAAOL,CAAG,CAAA,CAAIC,EAClB,CAAC,CAAA,CACMI,CACX,CAKA,SAASC,EACLC,CAAAA,CACAC,CAAAA,CACA7C,EACAwC,CAAAA,CACI,CACJK,CAAAA,CAAO7C,CAAAA,CAAS,CAAE,GAAGwC,EAAM,KAAA,CAAAI,CAAM,CAAC,EACtC,CAqBO,SAASE,CAAAA,CAAY/B,CAAAA,CAA0B,EAAC,CAAmB,CACtE,GAAM,CACF,KAAA,CAAA6B,EAAQ,MAAA,CACR,MAAA,CAAAC,EAASN,CAAAA,CACT,WAAA,CAAAQ,EAAc,KAAA,CACd,eAAA,CAAAC,EAAkB,KACtB,CAAA,CAAIjC,EAEJ,OAAQG,CAAAA,EACG,MAAOC,CAAAA,EAA4B,CACtC,IAAM8B,CAAAA,CAAY,WAAA,CAAY,KAAI,CAC5BC,CAAAA,CAAY,OAAO,UAAA,EAAW,CAG9BC,EAAuC,CACzC,SAAA,CAAAD,CAAAA,CACA,IAAA,CAAM,SAAA,CACN,MAAA,CAAQ/B,EAAQ,OAAA,CAAQ,MAAA,CACxB,IAAKA,CAAAA,CAAQ,OAAA,CAAQ,IACrB,OAAA,CAASsB,CAAAA,CAAgBtB,EAAQ,OAAA,CAAQ,OAAO,CACpD,CAAA,CAEA,GAAI4B,GAAe5B,CAAAA,CAAQ,OAAA,CAAQ,SAAW,KAAA,CAC1C,GAAI,CACA,IAAMiC,CAAAA,CAAgBjC,CAAAA,CAAQ,QAAQ,KAAA,EAAM,CAC5CgC,EAAY,IAAA,CAAU,MAAMC,EAAc,IAAA,GAC9C,MAAQ,CAER,CAGJT,EAAWC,CAAAA,CAAOC,CAAAA,CAAQ,mBAAoBM,CAAW,CAAA,CAGzD,IAAM9B,CAAAA,CAAkC,CACpC,GAAGF,CAAAA,CACH,SAAA,CAAA+B,CACJ,EAEA,GAAI,CACA,IAAMf,CAAAA,CAAW,MAAMjB,EAAQG,CAAe,CAAA,CACxCgC,EAAW,WAAA,CAAY,GAAA,GAAQJ,CAAAA,CAG/BK,CAAAA,CAAwC,CAC1C,SAAA,CAAAJ,CAAAA,CACA,KAAM,UAAA,CACN,MAAA,CAAQf,EAAS,MAAA,CACjB,QAAA,CAAU,GAAGkB,CAAAA,CAAS,OAAA,CAAQ,CAAC,CAAC,CAAA,EAAA,CACpC,EAEA,GAAIL,CAAAA,CACA,GAAI,CACA,IAAMO,EAAiBpB,CAAAA,CAAS,KAAA,GAChCmB,CAAAA,CAAa,IAAA,CAAU,MAAMC,CAAAA,CAAe,IAAA,GAChD,CAAA,KAAQ,CAER,CAGJZ,EAAWC,CAAAA,CAAOC,CAAAA,CAAQ,oBAAqBS,CAAY,CAAA,CAG3D,IAAMlB,CAAAA,CAAa,IAAI,QAAQD,CAAAA,CAAS,OAAO,EAC/C,OAAAC,CAAAA,CAAW,IAAI,cAAA,CAAgBc,CAAS,EAEjC,IAAI,QAAA,CAASf,CAAAA,CAAS,IAAA,CAAM,CAC/B,MAAA,CAAQA,EAAS,MAAA,CACjB,UAAA,CAAYA,EAAS,UAAA,CACrB,OAAA,CAASC,CACb,CAAC,CACL,OAASvB,CAAAA,CAAO,CACZ,IAAMwC,CAAAA,CAAW,WAAA,CAAY,KAAI,CAAIJ,CAAAA,CAGrC,MAAAJ,CAAAA,CAAO,gBAAA,CAAkB,CACrB,SAAA,CAAAK,CAAAA,CACA,IAAA,CAAM,QACN,KAAA,CAAOrC,CAAAA,YAAiB,MAAQA,CAAAA,CAAM,OAAA,CAAU,OAAOA,CAAK,CAAA,CAC5D,MAAOA,CAAAA,YAAiB,KAAA,CAAQA,EAAM,KAAA,CAAQ,MAAA,CAC9C,SAAU,CAAA,EAAGwC,CAAAA,CAAS,QAAQ,CAAC,CAAC,IACpC,CAAC,CAAA,CAEKxC,CACV,CACJ,CAER,CAaO,SAAS2C,CAAAA,EAA6B,CACzC,OAAQtC,CAAAA,EACG,MAAOC,CAAAA,EAA4B,CACtC,IAAM8B,CAAAA,CAAY,WAAA,CAAY,KAAI,CAC5Bd,CAAAA,CAAW,MAAMjB,CAAAA,CAAQC,CAAO,CAAA,CAChCkC,CAAAA,CAAW,WAAA,CAAY,GAAA,GAAQJ,CAAAA,CAE/Bb,CAAAA,CAAa,IAAI,OAAA,CAAQD,CAAAA,CAAS,OAAO,CAAA,CAC/C,OAAAC,EAAW,GAAA,CAAI,iBAAA,CAAmB,GAAGiB,CAAAA,CAAS,OAAA,CAAQ,CAAC,CAAC,CAAA,EAAA,CAAI,EAErD,IAAI,QAAA,CAASlB,EAAS,IAAA,CAAM,CAC/B,OAAQA,CAAAA,CAAS,MAAA,CACjB,WAAYA,CAAAA,CAAS,UAAA,CACrB,QAASC,CACb,CAAC,CACL,CAER,CCjKA,IAAMqB,CAAAA,CAAQ,IAAI,IAKlB,SAASC,CAAAA,EAAqB,CAC1B,IAAMC,CAAAA,CAAM,IAAA,CAAK,GAAA,EAAI,CACrB,IAAA,GAAW,CAACtB,CAAAA,CAAKC,CAAK,IAAKmB,CAAAA,CACnBnB,CAAAA,CAAM,QAAUqB,CAAAA,EAChBF,CAAAA,CAAM,OAAOpB,CAAG,EAG5B,CAGA,WAAA,CAAYqB,CAAAA,CAAc,GAAM,CAAA,CAKhC,SAASE,EAAoBzC,CAAAA,CAAiC,CAG1D,OAAO,CAAA,WAAA,EAFWA,CAAAA,CAAQ,QAAQ,OAAA,CAAQ,GAAA,CAAI,iBAAiB,CAAA,EACzC,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,GAAG,IAAA,EAAK,EAAK,SACxB,CAAA,CAC3B,CAwBO,SAAS0C,CAAAA,CAAc9C,CAAAA,CAA2C,CACrE,GAAM,CACF,KAAA,CAAA+C,CAAAA,CACA,MAAA,CAAAC,CAAAA,CACA,aAAAC,CAAAA,CAAeJ,CAAAA,CACf,cAAAK,CACJ,CAAA,CAAIlD,EAEJ,OAAQG,CAAAA,EACG,MAAOC,CAAAA,EAA4B,CACtC,IAAMkB,CAAAA,CAAM,MAAM2B,EAAa7C,CAAO,CAAA,CAChCwC,EAAM,IAAA,CAAK,GAAA,EAAI,CACfO,CAAAA,CAAWH,CAAAA,CAAS,GAAA,CAGtBI,EAAQV,CAAAA,CAAM,GAAA,CAAIpB,CAAG,CAAA,CAAA,CAErB,CAAC8B,GAASA,CAAAA,CAAM,OAAA,CAAUR,KAE1BQ,CAAAA,CAAQ,CAAE,MAAO,CAAA,CAAG,OAAA,CAASR,EAAMO,CAAS,CAAA,CAC5CT,EAAM,GAAA,CAAIpB,CAAAA,CAAK8B,CAAK,CAAA,CAAA,CAIxBA,CAAAA,CAAM,KAAA,EAAA,CAGN,IAAMC,CAAAA,CAAY,IAAA,CAAK,IAAI,CAAA,CAAGN,CAAAA,CAAQK,EAAM,KAAK,CAAA,CAC3CE,EAAQ,IAAA,CAAK,IAAA,CAAKF,EAAM,OAAA,CAAU,GAAI,EACtC7D,CAAAA,CAAa,IAAA,CAAK,MAAM6D,CAAAA,CAAM,OAAA,CAAUR,GAAO,GAAI,CAAA,CAGzD,GAAIQ,CAAAA,CAAM,KAAA,CAAQL,EACd,OAAIG,CAAAA,CACO,MAAMA,CAAAA,CAAc9C,CAAO,EAE/B,IAAId,CAAAA,CAAe,oBAAqBC,CAAU,CAAA,CAAE,YAAW,CAI1E,IAAM6B,EAAW,MAAMjB,CAAAA,CAAQC,CAAO,CAAA,CAEhCiB,CAAAA,CAAa,IAAI,QAAQD,CAAAA,CAAS,OAAO,EAC/C,OAAAC,CAAAA,CAAW,IAAI,mBAAA,CAAqB,MAAA,CAAO0B,CAAK,CAAC,CAAA,CACjD1B,EAAW,GAAA,CAAI,uBAAA,CAAyB,OAAOgC,CAAS,CAAC,EACzDhC,CAAAA,CAAW,GAAA,CAAI,mBAAA,CAAqB,MAAA,CAAOiC,CAAK,CAAC,EAE1C,IAAI,QAAA,CAASlC,EAAS,IAAA,CAAM,CAC/B,OAAQA,CAAAA,CAAS,MAAA,CACjB,WAAYA,CAAAA,CAAS,UAAA,CACrB,QAASC,CACb,CAAC,CACL,CAER,CAoBO,SAASkC,CAAAA,CAAkBC,CAAAA,CAA6B,CAC3D,OAAO,SAA6BxD,CAAAA,CAA2C,CAC3E,GAAM,CACF,MAAA+C,CAAAA,CACA,MAAA,CAAAC,EACA,YAAA,CAAAC,CAAAA,CAAeJ,EACf,aAAA,CAAAK,CACJ,EAAIlD,CAAAA,CAEJ,OAAQG,GACG,MAAOC,CAAAA,EAA4B,CACtC,IAAMkB,CAAAA,CAAM,MAAM2B,CAAAA,CAAa7C,CAAO,EAChCwC,CAAAA,CAAM,IAAA,CAAK,KAAI,CACfO,CAAAA,CAAWH,EAAS,GAAA,CAEtBI,CAAAA,CAAQ,MAAMI,CAAAA,CAAY,GAAA,CAAIlC,CAAG,CAAA,CAEjC,CAAC8B,GAASA,CAAAA,CAAM,OAAA,CAAUR,EAC1BQ,CAAAA,CAAQ,CAAE,KAAA,CAAO,CAAA,CAAG,OAAA,CAASR,CAAAA,CAAMO,CAAS,CAAA,CAE5CC,CAAAA,CAAM,QAGV,MAAMI,CAAAA,CAAY,IAAIlC,CAAAA,CAAK8B,CAAK,EAEhC,IAAMC,CAAAA,CAAY,KAAK,GAAA,CAAI,CAAA,CAAGN,EAAQK,CAAAA,CAAM,KAAK,EAC3CE,CAAAA,CAAQ,IAAA,CAAK,IAAA,CAAKF,CAAAA,CAAM,OAAA,CAAU,GAAI,EACtC7D,CAAAA,CAAa,IAAA,CAAK,MAAM6D,CAAAA,CAAM,OAAA,CAAUR,GAAO,GAAI,CAAA,CAEzD,GAAIQ,CAAAA,CAAM,KAAA,CAAQL,EACd,OAAIG,CAAAA,CACO,MAAMA,CAAAA,CAAc9C,CAAO,EAE/B,IAAId,CAAAA,CAAe,mBAAA,CAAqBC,CAAU,CAAA,CAAE,UAAA,GAG/D,IAAM6B,CAAAA,CAAW,MAAMjB,CAAAA,CAAQC,CAAO,EAEhCiB,CAAAA,CAAa,IAAI,QAAQD,CAAAA,CAAS,OAAO,EAC/C,OAAAC,CAAAA,CAAW,IAAI,mBAAA,CAAqB,MAAA,CAAO0B,CAAK,CAAC,CAAA,CACjD1B,EAAW,GAAA,CAAI,uBAAA,CAAyB,OAAOgC,CAAS,CAAC,EACzDhC,CAAAA,CAAW,GAAA,CAAI,oBAAqB,MAAA,CAAOiC,CAAK,CAAC,CAAA,CAE1C,IAAI,SAASlC,CAAAA,CAAS,IAAA,CAAM,CAC/B,MAAA,CAAQA,CAAAA,CAAS,OACjB,UAAA,CAAYA,CAAAA,CAAS,UAAA,CACrB,OAAA,CAASC,CACb,CAAC,CACL,CAER,CACJ,CCvIO,SAASoC,CAAAA,CAAkBzD,EAA6C,CAC3E,GAAM,CAAE,MAAA,CAAA0D,CAAAA,CAAQ,OAAAC,CAAAA,CAAS,MAAA,CAAQ,YAAAC,CAAY,CAAA,CAAI5D,EAEjD,OAAQG,CAAAA,EACG,MAAOC,CAAAA,EAA4B,CACtC,IAAIqB,EAGJ,OAAQkC,CAAAA,EACJ,KAAK,MAAA,CAAQ,CACT,GAAI,CACAlC,EAAO,MAAMrB,CAAAA,CAAQ,QAAQ,IAAA,GACjC,MAAQ,CACJ,OAAO,IAAIX,CAAAA,CAAgB,mBAAmB,CAAA,CAAE,UAAA,EACpD,CACA,KACJ,CACA,KAAK,QAAS,CACV,IAAMoE,EAAM,IAAI,GAAA,CAAIzD,EAAQ,OAAA,CAAQ,GAAG,EACvCqB,CAAAA,CAAO,MAAA,CAAO,YAAYoC,CAAAA,CAAI,YAAY,EAC1C,KACJ,CACA,KAAK,QAAA,CAAU,CAEXpC,EAAOrB,CAAAA,CAAQ,MAAA,EAAa,EAAC,CAC7B,KACJ,CACJ,CAGA,IAAMuB,EAAS+B,CAAAA,CAAO,SAAA,CAAUjC,CAAI,CAAA,CAEpC,GAAI,CAACE,CAAAA,CAAO,OAAA,CAAS,CACjB,IAAMjC,CAAAA,CAAUkE,CAAAA,CAAcA,CAAAA,CAAYjC,CAAAA,CAAO,KAAK,EAAImC,CAAAA,CAAenC,CAAAA,CAAO,KAAK,CAAA,CACrF,OAAO,IAAIlC,CAAAA,CAAgB,mBAAA,CAAqBC,CAAO,CAAA,CAAE,UAAA,EAC7D,CAGA,IAAMY,EAAkC,CACpC,GAAGF,EACH,IAAA,CAAMuB,CAAAA,CAAO,IACjB,CAAA,CAEA,OAAO,MAAMxB,EAAQG,CAAe,CACxC,CAER,CAKA,SAASwD,EAAehE,CAAAA,CAA0C,CAE9D,GACIA,CAAAA,EACA,OAAOA,GAAU,QAAA,EACjB,QAAA,GAAYA,GACZ,KAAA,CAAM,OAAA,CAASA,EAAgC,MAAM,CAAA,CACvD,CACE,IAAMiE,CAAAA,CAAUjE,CAAAA,CACX,OACCkE,CAAAA,CAAsC,GAE5C,IAAA,IAAWC,CAAAA,IAASF,EAAQ,CACxB,IAAMG,EAAOD,CAAAA,CAAM,IAAA,CAAK,KAAK,GAAG,CAAA,EAAK,QAChCD,CAAAA,CAAUE,CAAI,IACfF,CAAAA,CAAUE,CAAI,EAAI,EAAC,CAAA,CAEvBF,EAAUE,CAAI,CAAA,CAAE,KAAKD,CAAAA,CAAM,OAAO,EACtC,CAEA,OAAOD,CACX,CAGA,OAAO,CAAE,MAAA,CAAQ,CAAC,OAAOlE,CAAK,CAAC,CAAE,CACrC,CAeO,SAASqE,CAAAA,CAAoBC,CAAAA,CAIjB,CACf,OAAQjE,CAAAA,EACG,MAAOC,GAA4B,CACtC,IAAMiE,EAAqC,EAAC,CACtCC,EAAkC,EAAC,CAGzC,GAAIF,CAAAA,CAAQ,IAAA,CACR,GAAI,CACA,IAAM3C,EAAO,MAAMrB,CAAAA,CAAQ,OAAA,CAAQ,KAAA,EAAM,CAAE,IAAA,GACrCuB,CAAAA,CAASyC,CAAAA,CAAQ,KAAK,SAAA,CAAU3C,CAAI,EACtCE,CAAAA,CAAO,OAAA,CACP0C,EAAU,IAAA,CAAU1C,CAAAA,CAAO,KAE3B2C,CAAAA,CAAO,IAAA,CAAUR,EAAenC,CAAAA,CAAO,KAAK,EAEpD,CAAA,KAAQ,CACJ2C,CAAAA,CAAO,IAAA,CAAU,CAAE,MAAA,CAAQ,CAAC,mBAAmB,CAAE,EACrD,CAIJ,GAAIF,EAAQ,KAAA,CAAO,CACf,IAAMP,CAAAA,CAAM,IAAI,IAAIzD,CAAAA,CAAQ,OAAA,CAAQ,GAAG,CAAA,CACjCqB,CAAAA,CAAO,OAAO,WAAA,CAAYoC,CAAAA,CAAI,YAAY,CAAA,CAC1ClC,CAAAA,CAASyC,EAAQ,KAAA,CAAM,SAAA,CAAU3C,CAAI,CAAA,CACvCE,CAAAA,CAAO,QACP0C,CAAAA,CAAU,KAAA,CAAW1C,EAAO,IAAA,CAE5B2C,CAAAA,CAAO,MAAWR,CAAAA,CAAenC,CAAAA,CAAO,KAAK,EAErD,CAGA,GAAIyC,CAAAA,CAAQ,MAAA,EAAUhE,CAAAA,CAAQ,MAAA,CAAW,CACrC,IAAMuB,EAASyC,CAAAA,CAAQ,MAAA,CAAO,UAAUhE,CAAAA,CAAQ,MAAS,EACrDuB,CAAAA,CAAO,OAAA,CACP0C,EAAU,MAAA,CAAY1C,CAAAA,CAAO,KAE7B2C,CAAAA,CAAO,MAAA,CAAYR,EAAenC,CAAAA,CAAO,KAAK,EAEtD,CAGA,GAAI,MAAA,CAAO,IAAA,CAAK2C,CAAM,CAAA,CAAE,OAAS,CAAA,CAC7B,OAAO,IAAI7E,CAAAA,CAAgB,mBAAA,CAAqB6E,CAAM,CAAA,CAAE,UAAA,GAI5D,IAAMhE,CAAAA,CAAkC,CACpC,GAAGF,CAAAA,CACH,GAAGiE,CACP,CAAA,CAEA,OAAO,MAAMlE,CAAAA,CAAQG,CAAe,CACxC,CAER","file":"chunk-UXUDTRR2.cjs","sourcesContent":["/**\n * Base error class for next-route-compose errors.\n */\nexport class RouteComposeError extends Error {\n    constructor(\n        message: string,\n        public readonly code: string,\n        public readonly statusCode: number = 500\n    ) {\n        super(message);\n        this.name = \"RouteComposeError\";\n    }\n\n    /**\n     * Convert error to a JSON Response.\n     */\n    toResponse(): Response {\n        return Response.json(\n            {\n                error: {\n                    code: this.code,\n                    message: this.message,\n                },\n            },\n            { status: this.statusCode }\n        );\n    }\n}\n\n/**\n * Error thrown when authentication fails.\n */\nexport class UnauthorizedError extends RouteComposeError {\n    constructor(message = \"Unauthorized\") {\n        super(message, \"UNAUTHORIZED\", 401);\n        this.name = \"UnauthorizedError\";\n    }\n}\n\n/**\n * Error thrown when access is forbidden.\n */\nexport class ForbiddenError extends RouteComposeError {\n    constructor(message = \"Forbidden\") {\n        super(message, \"FORBIDDEN\", 403);\n        this.name = \"ForbiddenError\";\n    }\n}\n\n/**\n * Error thrown when rate limit is exceeded.\n */\nexport class RateLimitError extends RouteComposeError {\n    constructor(\n        message = \"Too many requests\",\n        public readonly retryAfter?: number\n    ) {\n        super(message, \"RATE_LIMITED\", 429);\n        this.name = \"RateLimitError\";\n    }\n\n    override toResponse(): Response {\n        const headers: HeadersInit = {};\n        if (this.retryAfter !== undefined) {\n            headers[\"Retry-After\"] = String(this.retryAfter);\n        }\n        return Response.json(\n            {\n                error: {\n                    code: this.code,\n                    message: this.message,\n                },\n            },\n            { status: this.statusCode, headers }\n        );\n    }\n}\n\n/**\n * Error thrown when validation fails.\n */\nexport class ValidationError extends RouteComposeError {\n    constructor(\n        message = \"Validation failed\",\n        public readonly details?: unknown\n    ) {\n        super(message, \"VALIDATION_ERROR\", 400);\n        this.name = \"ValidationError\";\n    }\n\n    override toResponse(): Response {\n        return Response.json(\n            {\n                error: {\n                    code: this.code,\n                    message: this.message,\n                    details: this.details,\n                },\n            },\n            { status: this.statusCode }\n        );\n    }\n}\n\n/**\n * Error thrown for bad requests.\n */\nexport class BadRequestError extends RouteComposeError {\n    constructor(message = \"Bad request\") {\n        super(message, \"BAD_REQUEST\", 400);\n        this.name = \"BadRequestError\";\n    }\n}\n\n/**\n * Error thrown when a resource is not found.\n */\nexport class NotFoundError extends RouteComposeError {\n    constructor(message = \"Not found\") {\n        super(message, \"NOT_FOUND\", 404);\n        this.name = \"NotFoundError\";\n    }\n}\n\n/**\n * Default error handler that converts errors to JSON responses.\n */\nexport function defaultErrorHandler(error: unknown): Response {\n    if (error instanceof RouteComposeError) {\n        return error.toResponse();\n    }\n\n    console.error(\"[next-route-compose] Unhandled error:\", error);\n\n    return Response.json(\n        {\n            error: {\n                code: \"INTERNAL_ERROR\",\n                message: \"Internal server error\",\n            },\n        },\n        { status: 500 }\n    );\n}\n","import { UnauthorizedError } from \"../errors.js\";\nimport type { AuthOptions, HandlerContext, HandlerUtility } from \"../types.js\";\n\n/**\n * Authentication utility for verifying user identity.\n *\n * @example\n * ```ts\n * import { compose, withAuth } from \"next-route-compose\";\n *\n * const verifyToken = async (ctx) => {\n *   const token = ctx.request.headers.get(\"Authorization\")?.replace(\"Bearer \", \"\");\n *   if (!token) return null;\n *   return await decodeToken(token);\n * };\n *\n * export const GET = compose(\n *   withAuth({ verify: verifyToken })\n * )(async (ctx) => {\n *   // ctx.user is typed and available\n *   return Response.json({ user: ctx.user });\n * });\n * ```\n */\nexport function withAuth<TUser = unknown>(options: AuthOptions<TUser>): HandlerUtility {\n    const {\n        verify,\n        onUnauthorized = () => new UnauthorizedError().toResponse(),\n    } = options;\n\n    return (handler) => {\n        return async (context: HandlerContext) => {\n            const user = await verify(context);\n\n            if (user === null || user === undefined) {\n                return await onUnauthorized(context);\n            }\n\n            // Add user to context\n            const enrichedContext: HandlerContext = {\n                ...context,\n                user,\n            };\n\n            return await handler(enrichedContext);\n        };\n    };\n}\n\n/**\n * Optional authentication utility - doesn't fail if user is not found,\n * just sets ctx.user to null.\n *\n * @example\n * ```ts\n * export const GET = compose(\n *   withOptionalAuth({ verify: verifyToken })\n * )(async (ctx) => {\n *   if (ctx.user) {\n *     return Response.json({ message: `Hello, ${ctx.user.name}!` });\n *   }\n *   return Response.json({ message: \"Hello, guest!\" });\n * });\n * ```\n */\nexport function withOptionalAuth<TUser = unknown>(\n    options: Omit<AuthOptions<TUser>, \"onUnauthorized\">\n): HandlerUtility {\n    const { verify } = options;\n\n    return (handler) => {\n        return async (context: HandlerContext) => {\n            const user = await verify(context);\n\n            const enrichedContext: HandlerContext = {\n                ...context,\n                user: user ?? null,\n            };\n\n            return await handler(enrichedContext);\n        };\n    };\n}\n","import type { CorsOptions, HandlerContext, HandlerUtility } from \"../types.js\";\n\nconst DEFAULT_METHODS = [\"GET\", \"HEAD\", \"PUT\", \"PATCH\", \"POST\", \"DELETE\"];\nconst DEFAULT_HEADERS = [\"Content-Type\", \"Authorization\"];\n\n/**\n * CORS utility for handling Cross-Origin Resource Sharing.\n *\n * @example\n * ```ts\n * import { compose, withCors } from \"next-route-compose\";\n *\n * export const GET = compose(\n *   withCors({ origin: \"https://example.com\" })\n * )(handler);\n *\n * // Allow any origin\n * export const POST = compose(\n *   withCors({ origin: \"*\", credentials: true })\n * )(handler);\n * ```\n */\nexport function withCors(options: CorsOptions = {}): HandlerUtility {\n    const {\n        origin = \"*\",\n        methods = DEFAULT_METHODS,\n        allowedHeaders = DEFAULT_HEADERS,\n        exposedHeaders = [],\n        credentials = false,\n        maxAge = 86400, // 24 hours\n    } = options;\n\n    return (handler) => {\n        return async (context: HandlerContext) => {\n            const requestOrigin = context.request.headers.get(\"Origin\") ?? \"\";\n\n            // Calculate allowed origin\n            let allowedOrigin: string;\n            if (origin === \"*\") {\n                allowedOrigin = \"*\";\n            } else if (typeof origin === \"string\") {\n                allowedOrigin = origin;\n            } else if (Array.isArray(origin)) {\n                allowedOrigin = origin.includes(requestOrigin) ? requestOrigin : \"\";\n            } else if (typeof origin === \"function\") {\n                allowedOrigin = origin(requestOrigin) ? requestOrigin : \"\";\n            } else {\n                allowedOrigin = \"\";\n            }\n\n            // Create CORS headers\n            const corsHeaders: HeadersInit = {\n                \"Access-Control-Allow-Origin\": allowedOrigin,\n                \"Access-Control-Allow-Methods\": methods.join(\", \"),\n                \"Access-Control-Allow-Headers\": allowedHeaders.join(\", \"),\n            };\n\n            if (exposedHeaders.length > 0) {\n                corsHeaders[\"Access-Control-Expose-Headers\"] = exposedHeaders.join(\", \");\n            }\n\n            if (credentials) {\n                corsHeaders[\"Access-Control-Allow-Credentials\"] = \"true\";\n            }\n\n            if (maxAge > 0) {\n                corsHeaders[\"Access-Control-Max-Age\"] = String(maxAge);\n            }\n\n            // Handle preflight requests\n            if (context.request.method === \"OPTIONS\") {\n                return new Response(null, {\n                    status: 204,\n                    headers: corsHeaders,\n                });\n            }\n\n            // Call the next handler and add CORS headers to response\n            const response = await handler(context);\n\n            // Clone response with CORS headers\n            const newHeaders = new Headers(response.headers);\n            for (const [key, value] of Object.entries(corsHeaders)) {\n                newHeaders.set(key, value);\n            }\n\n            return new Response(response.body, {\n                status: response.status,\n                statusText: response.statusText,\n                headers: newHeaders,\n            });\n        };\n    };\n}\n","import type { HandlerContext, HandlerUtility, LoggingOptions } from \"../types.js\";\n\n/**\n * Default logger using console.\n */\nfunction defaultLogger(message: string, data: Record<string, unknown>): void {\n    console.log(JSON.stringify({ message, ...data, timestamp: new Date().toISOString() }));\n}\n\n/**\n * Convert Headers to plain object.\n */\nfunction headersToObject(headers: Headers): Record<string, string> {\n    const result: Record<string, string> = {};\n    headers.forEach((value, key) => {\n        result[key] = value;\n    });\n    return result;\n}\n\n/**\n * Log with appropriate level.\n */\nfunction logByLevel(\n    level: \"debug\" | \"info\" | \"warn\" | \"error\",\n    logger: (message: string, data: Record<string, unknown>) => void,\n    message: string,\n    data: Record<string, unknown>\n): void {\n    logger(message, { ...data, level });\n}\n\n/**\n * Logging utility for request/response logging.\n *\n * @example\n * ```ts\n * import { compose, withLogging } from \"next-route-compose\";\n *\n * export const GET = compose(\n *   withLogging({ level: \"info\" })\n * )(handler);\n *\n * // With custom logger (e.g., Pino, Winston)\n * export const POST = compose(\n *   withLogging({\n *     logger: (msg, data) => pino.info(data, msg)\n *   })\n * )(handler);\n * ```\n */\nexport function withLogging(options: LoggingOptions = {}): HandlerUtility {\n    const {\n        level = \"info\",\n        logger = defaultLogger,\n        includeBody = false,\n        includeResponse = false,\n    } = options;\n\n    return (handler) => {\n        return async (context: HandlerContext) => {\n            const startTime = performance.now();\n            const requestId = crypto.randomUUID();\n\n            // Log request\n            const requestData: Record<string, unknown> = {\n                requestId,\n                type: \"request\",\n                method: context.request.method,\n                url: context.request.url,\n                headers: headersToObject(context.request.headers),\n            };\n\n            if (includeBody && context.request.method !== \"GET\") {\n                try {\n                    const clonedRequest = context.request.clone();\n                    requestData[\"body\"] = await clonedRequest.json();\n                } catch {\n                    // Body is not JSON or already consumed\n                }\n            }\n\n            logByLevel(level, logger, \"Incoming request\", requestData);\n\n            // Add requestId to context\n            const enrichedContext: HandlerContext = {\n                ...context,\n                requestId,\n            };\n\n            try {\n                const response = await handler(enrichedContext);\n                const duration = performance.now() - startTime;\n\n                // Log response\n                const responseData: Record<string, unknown> = {\n                    requestId,\n                    type: \"response\",\n                    status: response.status,\n                    duration: `${duration.toFixed(2)}ms`,\n                };\n\n                if (includeResponse) {\n                    try {\n                        const clonedResponse = response.clone();\n                        responseData[\"body\"] = await clonedResponse.json();\n                    } catch {\n                        // Response is not JSON\n                    }\n                }\n\n                logByLevel(level, logger, \"Request completed\", responseData);\n\n                // Add request ID to response headers\n                const newHeaders = new Headers(response.headers);\n                newHeaders.set(\"X-Request-Id\", requestId);\n\n                return new Response(response.body, {\n                    status: response.status,\n                    statusText: response.statusText,\n                    headers: newHeaders,\n                });\n            } catch (error) {\n                const duration = performance.now() - startTime;\n\n                // Log error\n                logger(\"Request failed\", {\n                    requestId,\n                    type: \"error\",\n                    error: error instanceof Error ? error.message : String(error),\n                    stack: error instanceof Error ? error.stack : undefined,\n                    duration: `${duration.toFixed(2)}ms`,\n                });\n\n                throw error;\n            }\n        };\n    };\n}\n\n/**\n * Timing utility to measure handler execution time.\n *\n * @example\n * ```ts\n * export const GET = compose(\n *   withTiming()\n * )(handler);\n * // Response will include X-Response-Time header\n * ```\n */\nexport function withTiming(): HandlerUtility {\n    return (handler) => {\n        return async (context: HandlerContext) => {\n            const startTime = performance.now();\n            const response = await handler(context);\n            const duration = performance.now() - startTime;\n\n            const newHeaders = new Headers(response.headers);\n            newHeaders.set(\"X-Response-Time\", `${duration.toFixed(2)}ms`);\n\n            return new Response(response.body, {\n                status: response.status,\n                statusText: response.statusText,\n                headers: newHeaders,\n            });\n        };\n    };\n}\n","import { RateLimitError } from \"../errors.js\";\nimport type { HandlerContext, HandlerUtility, RateLimitOptions } from \"../types.js\";\n\n/**\n * In-memory store for rate limiting.\n * For production, use Redis or another distributed store.\n */\nconst store = new Map<string, { count: number; resetAt: number }>();\n\n/**\n * Clean up expired entries periodically.\n */\nfunction cleanupStore(): void {\n    const now = Date.now();\n    for (const [key, value] of store) {\n        if (value.resetAt < now) {\n            store.delete(key);\n        }\n    }\n}\n\n// Run cleanup every minute\nsetInterval(cleanupStore, 60_000);\n\n/**\n * Default key generator using IP address.\n */\nfunction defaultKeyGenerator(context: HandlerContext): string {\n    const forwarded = context.request.headers.get(\"x-forwarded-for\");\n    const ip = forwarded?.split(\",\")[0]?.trim() ?? \"unknown\";\n    return `rate-limit:${ip}`;\n}\n\n/**\n * Rate limiting utility to prevent abuse.\n *\n * @example\n * ```ts\n * import { compose, withRateLimit } from \"next-route-compose\";\n *\n * // 100 requests per minute\n * export const GET = compose(\n *   withRateLimit({ limit: 100, window: 60 })\n * )(handler);\n *\n * // Custom key generator (e.g., by user ID)\n * export const POST = compose(\n *   withRateLimit({\n *     limit: 10,\n *     window: 60,\n *     keyGenerator: (ctx) => `user:${ctx.user?.id ?? 'anonymous'}`\n *   })\n * )(handler);\n * ```\n */\nexport function withRateLimit(options: RateLimitOptions): HandlerUtility {\n    const {\n        limit,\n        window,\n        keyGenerator = defaultKeyGenerator,\n        onRateLimited,\n    } = options;\n\n    return (handler) => {\n        return async (context: HandlerContext) => {\n            const key = await keyGenerator(context);\n            const now = Date.now();\n            const windowMs = window * 1000;\n\n            // Get or create rate limit entry\n            let entry = store.get(key);\n\n            if (!entry || entry.resetAt < now) {\n                // New window\n                entry = { count: 0, resetAt: now + windowMs };\n                store.set(key, entry);\n            }\n\n            // Increment count\n            entry.count++;\n\n            // Calculate remaining and reset time\n            const remaining = Math.max(0, limit - entry.count);\n            const reset = Math.ceil(entry.resetAt / 1000);\n            const retryAfter = Math.ceil((entry.resetAt - now) / 1000);\n\n            // Check if rate limited\n            if (entry.count > limit) {\n                if (onRateLimited) {\n                    return await onRateLimited(context);\n                }\n                return new RateLimitError(\"Too many requests\", retryAfter).toResponse();\n            }\n\n            // Call handler and add rate limit headers\n            const response = await handler(context);\n\n            const newHeaders = new Headers(response.headers);\n            newHeaders.set(\"X-RateLimit-Limit\", String(limit));\n            newHeaders.set(\"X-RateLimit-Remaining\", String(remaining));\n            newHeaders.set(\"X-RateLimit-Reset\", String(reset));\n\n            return new Response(response.body, {\n                status: response.status,\n                statusText: response.statusText,\n                headers: newHeaders,\n            });\n        };\n    };\n}\n\n/**\n * Create a custom rate limiter with a different store.\n * Useful for distributed systems using Redis or other backends.\n *\n * @example\n * ```ts\n * const redisRateLimit = createRateLimiter({\n *   get: async (key) => await redis.get(key),\n *   set: async (key, value, ttl) => await redis.setex(key, ttl, value),\n *   increment: async (key) => await redis.incr(key),\n * });\n * ```\n */\nexport interface RateLimitStore {\n    get: (key: string) => Promise<{ count: number; resetAt: number } | null>;\n    set: (key: string, value: { count: number; resetAt: number }) => Promise<void>;\n}\n\nexport function createRateLimiter(customStore: RateLimitStore) {\n    return function withCustomRateLimit(options: RateLimitOptions): HandlerUtility {\n        const {\n            limit,\n            window,\n            keyGenerator = defaultKeyGenerator,\n            onRateLimited,\n        } = options;\n\n        return (handler) => {\n            return async (context: HandlerContext) => {\n                const key = await keyGenerator(context);\n                const now = Date.now();\n                const windowMs = window * 1000;\n\n                let entry = await customStore.get(key);\n\n                if (!entry || entry.resetAt < now) {\n                    entry = { count: 1, resetAt: now + windowMs };\n                } else {\n                    entry.count++;\n                }\n\n                await customStore.set(key, entry);\n\n                const remaining = Math.max(0, limit - entry.count);\n                const reset = Math.ceil(entry.resetAt / 1000);\n                const retryAfter = Math.ceil((entry.resetAt - now) / 1000);\n\n                if (entry.count > limit) {\n                    if (onRateLimited) {\n                        return await onRateLimited(context);\n                    }\n                    return new RateLimitError(\"Too many requests\", retryAfter).toResponse();\n                }\n\n                const response = await handler(context);\n\n                const newHeaders = new Headers(response.headers);\n                newHeaders.set(\"X-RateLimit-Limit\", String(limit));\n                newHeaders.set(\"X-RateLimit-Remaining\", String(remaining));\n                newHeaders.set(\"X-RateLimit-Reset\", String(reset));\n\n                return new Response(response.body, {\n                    status: response.status,\n                    statusText: response.statusText,\n                    headers: newHeaders,\n                });\n            };\n        };\n    };\n}\n","import { ValidationError } from \"../errors.js\";\nimport type { HandlerContext, HandlerUtility } from \"../types.js\";\n\n/**\n * Generic schema interface compatible with Zod and other validation libraries.\n */\nexport interface Schema<T> {\n    parse: (data: unknown) => T;\n    safeParse: (data: unknown) => { success: true; data: T } | { success: false; error: unknown };\n}\n\n/**\n * Options for the validation utility.\n */\nexport interface ValidateOptions<T> {\n    /** Schema to validate against (Zod schema or compatible) */\n    schema: Schema<T>;\n    /** Source of data to validate */\n    source?: \"body\" | \"query\" | \"params\";\n    /** Custom error formatter */\n    formatError?: (error: unknown) => unknown;\n}\n\n/**\n * Validation utility using Zod or compatible schema libraries.\n *\n * @example\n * ```ts\n * import { compose, withValidation } from \"next-route-compose\";\n * import { z } from \"zod\";\n *\n * const CreateUserSchema = z.object({\n *   name: z.string().min(1),\n *   email: z.string().email(),\n * });\n *\n * export const POST = compose(\n *   withValidation({ schema: CreateUserSchema })\n * )(async (ctx) => {\n *   // ctx.body is typed as { name: string; email: string }\n *   const { name, email } = ctx.body;\n *   return Response.json({ user: { name, email } });\n * });\n * ```\n */\nexport function withValidation<T>(options: ValidateOptions<T>): HandlerUtility {\n    const { schema, source = \"body\", formatError } = options;\n\n    return (handler) => {\n        return async (context: HandlerContext) => {\n            let data: unknown;\n\n            // Get data from source\n            switch (source) {\n                case \"body\": {\n                    try {\n                        data = await context.request.json();\n                    } catch {\n                        return new ValidationError(\"Invalid JSON body\").toResponse();\n                    }\n                    break;\n                }\n                case \"query\": {\n                    const url = new URL(context.request.url);\n                    data = Object.fromEntries(url.searchParams);\n                    break;\n                }\n                case \"params\": {\n                    // Params would typically come from Next.js route params\n                    data = context[\"params\"] ?? {};\n                    break;\n                }\n            }\n\n            // Validate data\n            const result = schema.safeParse(data);\n\n            if (!result.success) {\n                const details = formatError ? formatError(result.error) : formatZodError(result.error);\n                return new ValidationError(\"Validation failed\", details).toResponse();\n            }\n\n            // Add validated data to context\n            const enrichedContext: HandlerContext = {\n                ...context,\n                body: result.data,\n            };\n\n            return await handler(enrichedContext);\n        };\n    };\n}\n\n/**\n * Format Zod-like errors into a readable structure.\n */\nfunction formatZodError(error: unknown): Record<string, string[]> {\n    // Check if it's a Zod-like error with issues\n    if (\n        error &&\n        typeof error === \"object\" &&\n        \"issues\" in error &&\n        Array.isArray((error as { issues: unknown[] }).issues)\n    ) {\n        const issues = (error as { issues: Array<{ path: (string | number)[]; message: string }> })\n            .issues;\n        const formatted: Record<string, string[]> = {};\n\n        for (const issue of issues) {\n            const path = issue.path.join(\".\") || \"_root\";\n            if (!formatted[path]) {\n                formatted[path] = [];\n            }\n            formatted[path].push(issue.message);\n        }\n\n        return formatted;\n    }\n\n    // Fallback for other error types\n    return { _error: [String(error)] };\n}\n\n/**\n * Validate multiple sources at once.\n *\n * @example\n * ```ts\n * export const POST = compose(\n *   withMultiValidation({\n *     body: CreateUserSchema,\n *     query: PaginationSchema,\n *   })\n * )(handler);\n * ```\n */\nexport function withMultiValidation(schemas: {\n    body?: Schema<unknown>;\n    query?: Schema<unknown>;\n    params?: Schema<unknown>;\n}): HandlerUtility {\n    return (handler) => {\n        return async (context: HandlerContext) => {\n            const validated: Record<string, unknown> = {};\n            const errors: Record<string, unknown> = {};\n\n            // Validate body\n            if (schemas.body) {\n                try {\n                    const data = await context.request.clone().json();\n                    const result = schemas.body.safeParse(data);\n                    if (result.success) {\n                        validated[\"body\"] = result.data;\n                    } else {\n                        errors[\"body\"] = formatZodError(result.error);\n                    }\n                } catch {\n                    errors[\"body\"] = { _error: [\"Invalid JSON body\"] };\n                }\n            }\n\n            // Validate query\n            if (schemas.query) {\n                const url = new URL(context.request.url);\n                const data = Object.fromEntries(url.searchParams);\n                const result = schemas.query.safeParse(data);\n                if (result.success) {\n                    validated[\"query\"] = result.data;\n                } else {\n                    errors[\"query\"] = formatZodError(result.error);\n                }\n            }\n\n            // Validate params\n            if (schemas.params && context[\"params\"]) {\n                const result = schemas.params.safeParse(context[\"params\"]);\n                if (result.success) {\n                    validated[\"params\"] = result.data;\n                } else {\n                    errors[\"params\"] = formatZodError(result.error);\n                }\n            }\n\n            // If any errors, return validation error\n            if (Object.keys(errors).length > 0) {\n                return new ValidationError(\"Validation failed\", errors).toResponse();\n            }\n\n            // Add validated data to context\n            const enrichedContext: HandlerContext = {\n                ...context,\n                ...validated,\n            };\n\n            return await handler(enrichedContext);\n        };\n    };\n}\n"]}