[{"data":1,"prerenderedAt":2994},["ShallowReactive",2],{"navLinks":3,"sidebar_docs_navigation_\u002Fdocs\u002Fauth-h3client":64,"navigation":217,"navLinks_footer":829,"\u002Fdocs\u002Fauth-h3client\u002Fguides\u002Fimage-upload_page":842,"\u002Fdocs\u002Fauth-h3client\u002Fguides\u002Fimage-upload_surround":2076,"\u002Fdocs\u002Fauth-h3client\u002Fguides\u002Fimage-upload":2079},{"id":4,"extension":5,"links":6,"meta":61,"stem":62,"__hash__":63},"navigationMenu\u002Fnavigation.json","json",[7,52,57],{"nested":8,"label":9,"icon":10,"to":11,"children":12},true,"Docs","i-lucide-book-open","\u002Fdocs\u002Fgetting-started",[13,19,26,32,39,45],{"label":14,"icon":15,"to":11,"description":16,"github":17,"badge":18},"Getting Started","i-lucide-rocket","An introduction to help you understand the core components.","https:\u002F\u002Fgithub.com\u002FSergo706\u002Fdocshub","Start Here",{"label":20,"icon":21,"to":22,"description":23,"github":24,"badge":25},"Auth H3 Client","i-lucide-key-round","\u002Fdocs\u002Fauth-h3client","Seamlessly enforce OAuth 2.0 authentication and session management integrated directly as the client of the IAM module.","https:\u002F\u002Fgithub.com\u002FSergo706\u002Fauth-h3client","Core",{"label":27,"icon":28,"to":29,"description":30,"github":31,"badge":25},"IAM","i-lucide-shield-check","\u002Fdocs\u002Fiam","Identity and Access Management featuring granular roles, permissions, and security policies.","https:\u002F\u002Fgithub.com\u002FSergo706\u002Fauth",{"label":33,"icon":34,"to":35,"description":36,"github":37,"badge":38},"Bot Detection","i-lucide-cpu","\u002Fdocs\u002Fbot-detection","Advanced behavioral analysis and request fingerprinting to stop malicious automated traffic.","https:\u002F\u002Fgithub.com\u002FSergo706\u002Fbot-detector","Security",{"label":40,"icon":41,"to":42,"description":43,"github":44,"badge":38},"Shield Base","i-lucide-database-zap","\u002Fdocs\u002Fshield-base","CLI and programmatic toolkit for compiling offline-ready IP intelligence databases from BGP, GeoIP, Tor, FireHOL, and other public threat feeds.","https:\u002F\u002Fgithub.com\u002FSergo706\u002Fshield-base-cli",{"label":46,"icon":47,"to":48,"description":49,"github":50,"badge":51},"Utils","i-lucide-wrench","\u002Fdocs\u002Futils","A standard library of highly optimized helpers for formatting, validation, and core logic.","https:\u002F\u002Fgithub.com\u002FSergo706\u002Futils","Library",{"nested":53,"label":54,"icon":55,"to":56},false,"Blog","i-lucide-pen-line","\u002Fblog",{"nested":53,"label":58,"icon":59,"to":60},"Website","lucide:app-window-mac","https:\u002F\u002Friavzon.com",{},"navigation","gkaQ0xRGxSLrLyM3kttLe0oBwkrR1EBjlepF8LSbwF8",[65],{"title":9,"path":66,"stem":67,"children":68,"page":53},"\u002Fdocs","docs",[69],{"title":20,"path":22,"stem":70,"children":71},"docs\u002Fauth-h3client\u002Findex",[72,73,82,119,145,167,170,191,195],{"title":20,"path":22,"stem":70},{"title":14,"path":74,"stem":75,"children":76},"\u002Fdocs\u002Fauth-h3client\u002Fgetting-started","docs\u002Fauth-h3client\u002F00.getting-started\u002Findex",[77,78],{"title":14,"path":74,"stem":75},{"title":79,"path":80,"stem":81},"Nuxt Module","\u002Fdocs\u002Fauth-h3client\u002Fgetting-started\u002Fnuxt","docs\u002Fauth-h3client\u002F00.getting-started\u002F00.nuxt",{"title":83,"path":84,"stem":85,"children":86},"Essentials","\u002Fdocs\u002Fauth-h3client\u002Fessentials","docs\u002Fauth-h3client\u002F01.essentials\u002Findex",[87,88,92,96,100,104,108,111,115],{"title":83,"path":84,"stem":85},{"title":89,"path":90,"stem":91},"Session Management","\u002Fdocs\u002Fauth-h3client\u002Fessentials\u002Fsession","docs\u002Fauth-h3client\u002F01.essentials\u002F00.session",{"title":93,"path":94,"stem":95},"Route Protection","\u002Fdocs\u002Fauth-h3client\u002Fessentials\u002Froute-protection","docs\u002Fauth-h3client\u002F01.essentials\u002F01.route-protection",{"title":97,"path":98,"stem":99},"CSRF Protection","\u002Fdocs\u002Fauth-h3client\u002Fessentials\u002Fcsrf","docs\u002Fauth-h3client\u002F01.essentials\u002F02.csrf",{"title":101,"path":102,"stem":103},"Auth Flows","\u002Fdocs\u002Fauth-h3client\u002Fessentials\u002Fauth-flows","docs\u002Fauth-h3client\u002F01.essentials\u002F03.auth-flows",{"title":105,"path":106,"stem":107},"OAuth and OIDC","\u002Fdocs\u002Fauth-h3client\u002Fessentials\u002Foauth","docs\u002Fauth-h3client\u002F01.essentials\u002F04.oauth",{"title":33,"path":109,"stem":110},"\u002Fdocs\u002Fauth-h3client\u002Fessentials\u002Fbot-detection","docs\u002Fauth-h3client\u002F01.essentials\u002F05.bot-detection",{"title":112,"path":113,"stem":114},"Cookies","\u002Fdocs\u002Fauth-h3client\u002Fessentials\u002Fcookies","docs\u002Fauth-h3client\u002F01.essentials\u002F06.cookies",{"title":116,"path":117,"stem":118},"Logging","\u002Fdocs\u002Fauth-h3client\u002Fessentials\u002Flogging","docs\u002Fauth-h3client\u002F01.essentials\u002F07.logging",{"title":120,"path":121,"stem":122,"children":123},"MFA","\u002Fdocs\u002Fauth-h3client\u002Fmfa","docs\u002Fauth-h3client\u002F02.mfa\u002Findex",[124,125,129,133,137,141],{"title":120,"path":121,"stem":122},{"title":126,"path":127,"stem":128},"Built-in MFA","\u002Fdocs\u002Fauth-h3client\u002Fmfa\u002Fbuilt-in-flow","docs\u002Fauth-h3client\u002F02.mfa\u002F01.built-in-flow",{"title":130,"path":131,"stem":132},"Password Reset","\u002Fdocs\u002Fauth-h3client\u002Fmfa\u002Fpassword-reset","docs\u002Fauth-h3client\u002F02.mfa\u002F02.password-reset",{"title":134,"path":135,"stem":136},"Email Change","\u002Fdocs\u002Fauth-h3client\u002Fmfa\u002Femail-change","docs\u002Fauth-h3client\u002F02.mfa\u002F03.email-change",{"title":138,"path":139,"stem":140},"Custom MFA Flow","\u002Fdocs\u002Fauth-h3client\u002Fmfa\u002Fcustom-flow","docs\u002Fauth-h3client\u002F02.mfa\u002F04.custom-flow",{"title":142,"path":143,"stem":144},"Client-Side MFA","\u002Fdocs\u002Fauth-h3client\u002Fmfa\u002Fclient-side","docs\u002Fauth-h3client\u002F02.mfa\u002F05.client-side",{"title":146,"path":147,"stem":148,"children":149},"Client-side","\u002Fdocs\u002Fauth-h3client\u002Fclient","docs\u002Fauth-h3client\u002F03.client\u002Findex",[150,151,155,159,163],{"title":146,"path":147,"stem":148},{"title":152,"path":153,"stem":154},"useAuthData","\u002Fdocs\u002Fauth-h3client\u002Fclient\u002Fuse-auth-data","docs\u002Fauth-h3client\u002F03.client\u002F00.use-auth-data",{"title":156,"path":157,"stem":158},"useMagicLink","\u002Fdocs\u002Fauth-h3client\u002Fclient\u002Fuse-magic-link","docs\u002Fauth-h3client\u002F03.client\u002F01.use-magic-link",{"title":160,"path":161,"stem":162},"executeRequest","\u002Fdocs\u002Fauth-h3client\u002Fclient\u002Fexecute-request","docs\u002Fauth-h3client\u002F03.client\u002F02.execute-request",{"title":164,"path":165,"stem":166},"getCsrfToken","\u002Fdocs\u002Fauth-h3client\u002Fclient\u002Fget-csrf-token","docs\u002Fauth-h3client\u002F03.client\u002F03.get-csrf-token",{"title":38,"path":168,"stem":169},"\u002Fdocs\u002Fauth-h3client\u002Fsecurity","docs\u002Fauth-h3client\u002F04.security",{"title":171,"path":172,"stem":173,"children":174,"page":53},"Guides","\u002Fdocs\u002Fauth-h3client\u002Fguides","docs\u002Fauth-h3client\u002F05.guides",[175,179,183,187],{"title":176,"path":177,"stem":178},"H3 and Nitro Setup","\u002Fdocs\u002Fauth-h3client\u002Fguides\u002Fh3-nitro","docs\u002Fauth-h3client\u002F05.guides\u002F00.h3-nitro",{"title":180,"path":181,"stem":182},"HMAC Inter-service Auth","\u002Fdocs\u002Fauth-h3client\u002Fguides\u002Fhmac","docs\u002Fauth-h3client\u002F05.guides\u002Fhmac",{"title":184,"path":185,"stem":186},"Image Upload","\u002Fdocs\u002Fauth-h3client\u002Fguides\u002Fimage-upload","docs\u002Fauth-h3client\u002F05.guides\u002Fimage-upload",{"title":188,"path":189,"stem":190},"mTLS Configuration","\u002Fdocs\u002Fauth-h3client\u002Fguides\u002Fmtls","docs\u002Fauth-h3client\u002F05.guides\u002Fmtls",{"title":192,"path":193,"stem":194},"Configuration","\u002Fdocs\u002Fauth-h3client\u002Fconfiguration","docs\u002Fauth-h3client\u002F06.configuration",{"title":196,"path":197,"stem":198,"children":199},"API Reference","\u002Fdocs\u002Fauth-h3client\u002Fapi","docs\u002Fauth-h3client\u002F07.api\u002Findex",[200,201,205,209,213],{"title":196,"path":197,"stem":198},{"title":202,"path":203,"stem":204},"Routes Reference","\u002Fdocs\u002Fauth-h3client\u002Fapi\u002Fcontrollers","docs\u002Fauth-h3client\u002F07.api\u002F00.controllers",{"title":206,"path":207,"stem":208},"Middleware Reference","\u002Fdocs\u002Fauth-h3client\u002Fapi\u002Fmiddleware","docs\u002Fauth-h3client\u002F07.api\u002F01.middleware",{"title":210,"path":211,"stem":212},"Client-side Reference","\u002Fdocs\u002Fauth-h3client\u002Fapi\u002Fcomposables","docs\u002Fauth-h3client\u002F07.api\u002F02.composables",{"title":214,"path":215,"stem":216},"Utilities","\u002Fdocs\u002Fauth-h3client\u002Fapi\u002Futilities","docs\u002Fauth-h3client\u002F07.api\u002F03.utilities",[218],{"title":9,"path":66,"stem":67,"children":219,"page":53},[220,268,386,391,569,636],{"title":20,"path":22,"stem":70,"children":221},[222,223,227,238,246,253,254,260,261],{"title":20,"path":22,"stem":70},{"title":14,"path":74,"stem":75,"children":224},[225,226],{"title":14,"path":74,"stem":75},{"title":79,"path":80,"stem":81},{"title":83,"path":84,"stem":85,"children":228},[229,230,231,232,233,234,235,236,237],{"title":83,"path":84,"stem":85},{"title":89,"path":90,"stem":91},{"title":93,"path":94,"stem":95},{"title":97,"path":98,"stem":99},{"title":101,"path":102,"stem":103},{"title":105,"path":106,"stem":107},{"title":33,"path":109,"stem":110},{"title":112,"path":113,"stem":114},{"title":116,"path":117,"stem":118},{"title":120,"path":121,"stem":122,"children":239},[240,241,242,243,244,245],{"title":120,"path":121,"stem":122},{"title":126,"path":127,"stem":128},{"title":130,"path":131,"stem":132},{"title":134,"path":135,"stem":136},{"title":138,"path":139,"stem":140},{"title":142,"path":143,"stem":144},{"title":146,"path":147,"stem":148,"children":247},[248,249,250,251,252],{"title":146,"path":147,"stem":148},{"title":152,"path":153,"stem":154},{"title":156,"path":157,"stem":158},{"title":160,"path":161,"stem":162},{"title":164,"path":165,"stem":166},{"title":38,"path":168,"stem":169},{"title":171,"path":172,"stem":173,"children":255,"page":53},[256,257,258,259],{"title":176,"path":177,"stem":178},{"title":180,"path":181,"stem":182},{"title":184,"path":185,"stem":186},{"title":188,"path":189,"stem":190},{"title":192,"path":193,"stem":194},{"title":196,"path":197,"stem":198,"children":262},[263,264,265,266,267],{"title":196,"path":197,"stem":198},{"title":202,"path":203,"stem":204},{"title":206,"path":207,"stem":208},{"title":210,"path":211,"stem":212},{"title":214,"path":215,"stem":216},{"title":269,"path":35,"stem":270,"children":271},"Bot Detector","docs\u002Fbot-detection\u002Findex",[272,273,276,280,284,303,377,380,383],{"title":269,"path":35,"stem":270},{"title":14,"path":274,"stem":275},"\u002Fdocs\u002Fbot-detection\u002Fgetting-started","docs\u002Fbot-detection\u002F00.getting-started",{"title":277,"path":278,"stem":279},"CLI","\u002Fdocs\u002Fbot-detection\u002Fcli","docs\u002Fbot-detection\u002F01.cli",{"title":281,"path":282,"stem":283},"Data Sources","\u002Fdocs\u002Fbot-detection\u002Fdata-sources","docs\u002Fbot-detection\u002F02.data-sources",{"title":171,"path":285,"stem":286,"children":287,"page":53},"\u002Fdocs\u002Fbot-detection\u002Fguides","docs\u002Fbot-detection\u002F03.guides",[288,292,296,299],{"title":289,"path":290,"stem":291},"Custom Checkers","\u002Fdocs\u002Fbot-detection\u002Fguides\u002Fcustom","docs\u002Fbot-detection\u002F03.guides\u002FCUSTOM",{"title":293,"path":294,"stem":295},"Scheduling Database Generation","\u002Fdocs\u002Fbot-detection\u002Fguides\u002Fgenerate","docs\u002Fbot-detection\u002F03.guides\u002FGENERATE",{"title":116,"path":297,"stem":298},"\u002Fdocs\u002Fbot-detection\u002Fguides\u002Flogging","docs\u002Fbot-detection\u002F03.guides\u002FLOGGING",{"title":300,"path":301,"stem":302},"Score Modes and Reputation Healing","\u002Fdocs\u002Fbot-detection\u002Fguides\u002Fscore","docs\u002Fbot-detection\u002F03.guides\u002FSCORE",{"title":304,"path":305,"stem":306,"children":307},"Checkers","\u002Fdocs\u002Fbot-detection\u002Fcheckers","docs\u002Fbot-detection\u002F04.checkers\u002Findex",[308,309,313,317,321,325,329,333,337,341,345,349,353,357,361,365,369,373],{"title":304,"path":305,"stem":306},{"title":310,"path":311,"stem":312},"IP Validation","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fip-validation","docs\u002Fbot-detection\u002F04.checkers\u002F01.ip-validation",{"title":314,"path":315,"stem":316},"Good \u002F Bad Bot Verification","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fgood-bots","docs\u002Fbot-detection\u002F04.checkers\u002F02.good-bots",{"title":318,"path":319,"stem":320},"Browser & Device Fingerprint","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fbrowser-device","docs\u002Fbot-detection\u002F04.checkers\u002F03.browser-device",{"title":322,"path":323,"stem":324},"Locale Map","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Flocale-map","docs\u002Fbot-detection\u002F04.checkers\u002F04.locale-map",{"title":326,"path":327,"stem":328},"Known Threats","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fknown-threats","docs\u002Fbot-detection\u002F04.checkers\u002F05.known-threats",{"title":330,"path":331,"stem":332},"ASN Classification","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fasn-classification","docs\u002Fbot-detection\u002F04.checkers\u002F06.asn-classification",{"title":334,"path":335,"stem":336},"Tor Analysis","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Ftor-analysis","docs\u002Fbot-detection\u002F04.checkers\u002F07.tor-analysis",{"title":338,"path":339,"stem":340},"Timezone Consistency","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Ftimezone-consistency","docs\u002Fbot-detection\u002F04.checkers\u002F08.timezone-consistency",{"title":342,"path":343,"stem":344},"Honeypot","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fhoneypot","docs\u002Fbot-detection\u002F04.checkers\u002F09.honeypot",{"title":346,"path":347,"stem":348},"Known Bad IPs","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fknown-bad-ips","docs\u002Fbot-detection\u002F04.checkers\u002F10.known-bad-ips",{"title":350,"path":351,"stem":352},"Behavior Rate","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fbehavior-rate","docs\u002Fbot-detection\u002F04.checkers\u002F11.behavior-rate",{"title":354,"path":355,"stem":356},"Proxy \u002F ISP \u002F Cookie","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fproxy-isp-cookies","docs\u002Fbot-detection\u002F04.checkers\u002F12.proxy-isp-cookies",{"title":358,"path":359,"stem":360},"Session Coherence","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fsession-coherence","docs\u002Fbot-detection\u002F04.checkers\u002F13.session-coherence",{"title":362,"path":363,"stem":364},"Velocity Fingerprint","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fvelocity-fingerprint","docs\u002Fbot-detection\u002F04.checkers\u002F14.velocity-fingerprint",{"title":366,"path":367,"stem":368},"UA & Header Analysis","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fua-header","docs\u002Fbot-detection\u002F04.checkers\u002F15.ua-header",{"title":370,"path":371,"stem":372},"Geolocation","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fgeolocation","docs\u002Fbot-detection\u002F04.checkers\u002F16.geolocation",{"title":374,"path":375,"stem":376},"Known Bad User-Agents","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fknown-bad-ua","docs\u002Fbot-detection\u002F04.checkers\u002F17.known-bad-ua",{"title":38,"path":378,"stem":379},"\u002Fdocs\u002Fbot-detection\u002Fsecurity","docs\u002Fbot-detection\u002F04.security",{"title":196,"path":381,"stem":382},"\u002Fdocs\u002Fbot-detection\u002Fapi","docs\u002Fbot-detection\u002F05.api",{"title":192,"path":384,"stem":385},"\u002Fdocs\u002Fbot-detection\u002Fconfiguration","docs\u002Fbot-detection\u002F06.configuration",{"title":387,"path":11,"stem":388,"children":389},"Introduction","docs\u002Fgetting-started\u002Findex",[390],{"title":387,"path":11,"stem":388},{"title":27,"path":29,"stem":392,"children":393},"docs\u002Fiam\u002Findex",[394,395,398,533,536,552,555],{"title":27,"path":29,"stem":392},{"title":14,"path":396,"stem":397},"\u002Fdocs\u002Fiam\u002Fgetting-started","docs\u002Fiam\u002F00.getting-started",{"title":83,"path":399,"stem":400,"children":401},"\u002Fdocs\u002Fiam\u002Fessentials","docs\u002Fiam\u002F01.essentials\u002Findex",[402,403,407,411,415,419,423,427,431,435,439,443,446,450,454,458,462,465,469,473,476,480,483],{"title":83,"path":399,"stem":400},{"title":404,"path":405,"stem":406},"Tokens","\u002Fdocs\u002Fiam\u002Fessentials\u002Ftokens","docs\u002Fiam\u002F01.essentials\u002F00.tokens",{"title":408,"path":409,"stem":410},"Access Tokens","\u002Fdocs\u002Fiam\u002Fessentials\u002Faccess-tokens","docs\u002Fiam\u002F01.essentials\u002F01.access-tokens",{"title":412,"path":413,"stem":414},"Refresh Tokens","\u002Fdocs\u002Fiam\u002Fessentials\u002Frefresh-tokens","docs\u002Fiam\u002F01.essentials\u002F02.refresh-tokens",{"title":416,"path":417,"stem":418},"Anomaly Detection","\u002Fdocs\u002Fiam\u002Fessentials\u002Fanomalies","docs\u002Fiam\u002F01.essentials\u002F03.anomalies",{"title":420,"path":421,"stem":422},"Signup","\u002Fdocs\u002Fiam\u002Fessentials\u002Fsignup","docs\u002Fiam\u002F01.essentials\u002F04.signup",{"title":424,"path":425,"stem":426},"Login","\u002Fdocs\u002Fiam\u002Fessentials\u002Flogin","docs\u002Fiam\u002F01.essentials\u002F05.login",{"title":428,"path":429,"stem":430},"Logout","\u002Fdocs\u002Fiam\u002Fessentials\u002Flogout","docs\u002Fiam\u002F01.essentials\u002F06.logout",{"title":432,"path":433,"stem":434},"OAuth","\u002Fdocs\u002Fiam\u002Fessentials\u002Foauth","docs\u002Fiam\u002F01.essentials\u002F07.oauth",{"title":436,"path":437,"stem":438},"Magic Links","\u002Fdocs\u002Fiam\u002Fessentials\u002Fmagic-links","docs\u002Fiam\u002F01.essentials\u002F08.magic-links",{"title":440,"path":441,"stem":442},"Emails","\u002Fdocs\u002Fiam\u002Fessentials\u002Femails","docs\u002Fiam\u002F01.essentials\u002F09.emails",{"title":120,"path":444,"stem":445},"\u002Fdocs\u002Fiam\u002Fessentials\u002Fmfa","docs\u002Fiam\u002F01.essentials\u002F10.mfa",{"title":447,"path":448,"stem":449},"Fingerprinting","\u002Fdocs\u002Fiam\u002Fessentials\u002Ffingerprinting","docs\u002Fiam\u002F01.essentials\u002F11.fingerprinting",{"title":451,"path":452,"stem":453},"Backend for Frontend","\u002Fdocs\u002Fiam\u002Fessentials\u002Fbff","docs\u002Fiam\u002F01.essentials\u002F12.bff",{"title":455,"path":456,"stem":457},"HMAC Authentication","\u002Fdocs\u002Fiam\u002Fessentials\u002Fhmac","docs\u002Fiam\u002F01.essentials\u002F13.hmac",{"title":459,"path":460,"stem":461},"XSS Protection","\u002Fdocs\u002Fiam\u002Fessentials\u002Fxss","docs\u002Fiam\u002F01.essentials\u002F14.xss",{"title":116,"path":463,"stem":464},"\u002Fdocs\u002Fiam\u002Fessentials\u002Flogging","docs\u002Fiam\u002F01.essentials\u002F15.logging",{"title":466,"path":467,"stem":468},"Rate Limiting","\u002Fdocs\u002Fiam\u002Fessentials\u002Frate-limiting","docs\u002Fiam\u002F01.essentials\u002F16.rate-limiting",{"title":470,"path":471,"stem":472},"Database","\u002Fdocs\u002Fiam\u002Fessentials\u002Fdatabase","docs\u002Fiam\u002F01.essentials\u002F17.database",{"title":112,"path":474,"stem":475},"\u002Fdocs\u002Fiam\u002Fessentials\u002Fcookies","docs\u002Fiam\u002F01.essentials\u002F18.cookies",{"title":477,"path":478,"stem":479},"Service Startup","\u002Fdocs\u002Fiam\u002Fessentials\u002Fservice","docs\u002Fiam\u002F01.essentials\u002F19.service",{"title":130,"path":481,"stem":482},"\u002Fdocs\u002Fiam\u002Fessentials\u002Fpassword-reset","docs\u002Fiam\u002F01.essentials\u002F20.password-reset",{"title":484,"path":485,"stem":486,"children":487},"API Tokens","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi","docs\u002Fiam\u002F01.essentials\u002F21.api\u002Findex",[488,489,493,497,527,530],{"title":484,"path":485,"stem":486},{"title":490,"path":491,"stem":492},"Creating Tokens","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fcreation","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F00.creation",{"title":494,"path":495,"stem":496},"Verifying Tokens","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fverification","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F01.verification",{"title":498,"path":499,"stem":500,"children":501},"Manage Tokens","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fmanagement","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F02.management\u002Findex",[502,503,507,511,515,519,523],{"title":498,"path":499,"stem":500},{"title":504,"path":505,"stem":506},"Privileges","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fmanagement\u002Fprivilege","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F02.management\u002F00.privilege",{"title":508,"path":509,"stem":510},"Revocation","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fmanagement\u002Frevocation","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F02.management\u002F01.revocation",{"title":512,"path":513,"stem":514},"Rotation","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fmanagement\u002Frotation","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F02.management\u002F02.rotation",{"title":516,"path":517,"stem":518},"IP Restriction","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fmanagement\u002Fip-updates","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F02.management\u002F03.ip-updates",{"title":520,"path":521,"stem":522},"Metadata","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fmanagement\u002Fmetadata","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F02.management\u002F04.metadata",{"title":524,"path":525,"stem":526},"Token Listing","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fmanagement\u002Flist","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F02.management\u002F05.list",{"title":466,"path":528,"stem":529},"\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Frate-limiting","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F03.rate-limiting",{"title":38,"path":531,"stem":532},"\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fsecurity","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F04.security",{"title":38,"path":534,"stem":535},"\u002Fdocs\u002Fiam\u002Fsecurity","docs\u002Fiam\u002F02.security",{"title":171,"path":537,"stem":538,"children":539,"page":53},"\u002Fdocs\u002Fiam\u002Fguides","docs\u002Fiam\u002F03.guides",[540,544,548],{"title":541,"path":542,"stem":543},"Deployment","\u002Fdocs\u002Fiam\u002Fguides\u002Fdeployment","docs\u002Fiam\u002F03.guides\u002Fdeployment",{"title":545,"path":546,"stem":547},"Operation Scripts","\u002Fdocs\u002Fiam\u002Fguides\u002Foperation-scripts","docs\u002Fiam\u002F03.guides\u002Foperation-scripts",{"title":549,"path":550,"stem":551},"Role-Based Access Control","\u002Fdocs\u002Fiam\u002Fguides\u002Frbac","docs\u002Fiam\u002F03.guides\u002Frbac",{"title":192,"path":553,"stem":554},"\u002Fdocs\u002Fiam\u002Fconfiguration","docs\u002Fiam\u002F04.configuration",{"title":556,"path":557,"stem":558,"children":559,"page":53},"Api","\u002Fdocs\u002Fiam\u002Fapi","docs\u002Fiam\u002F05.API",[560,563,566],{"title":196,"path":561,"stem":562},"\u002Fdocs\u002Fiam\u002Fapi\u002Fapi","docs\u002Fiam\u002F05.API\u002F00.api",{"title":206,"path":564,"stem":565},"\u002Fdocs\u002Fiam\u002Fapi\u002Fmiddlewares","docs\u002Fiam\u002F05.API\u002F02.middlewares",{"title":202,"path":567,"stem":568},"\u002Fdocs\u002Fiam\u002Fapi\u002Froutes","docs\u002Fiam\u002F05.API\u002F03.routes",{"title":40,"path":42,"stem":570,"children":571},"docs\u002Fshield-base\u002Findex",[572,573,576,580,621,625,629,633],{"title":40,"path":42,"stem":570},{"title":14,"path":574,"stem":575},"\u002Fdocs\u002Fshield-base\u002Fgetting-started","docs\u002Fshield-base\u002F00.getting-started",{"title":577,"path":578,"stem":579},"CLI Reference","\u002Fdocs\u002Fshield-base\u002Fcli","docs\u002Fshield-base\u002F01.cli",{"title":281,"path":581,"stem":582,"children":583},"\u002Fdocs\u002Fshield-base\u002Fdata-sources","docs\u002Fshield-base\u002F02.data-sources\u002Findex",[584,585,589,593,597,601,605,609,613,617],{"title":281,"path":581,"stem":582},{"title":586,"path":587,"stem":588},"BGP \u002F ASN","\u002Fdocs\u002Fshield-base\u002Fdata-sources\u002Fbgp","docs\u002Fshield-base\u002F02.data-sources\u002Fbgp",{"title":590,"path":591,"stem":592},"City Geolocation","\u002Fdocs\u002Fshield-base\u002Fdata-sources\u002Fcity","docs\u002Fshield-base\u002F02.data-sources\u002Fcity",{"title":594,"path":595,"stem":596},"Country Geolocation","\u002Fdocs\u002Fshield-base\u002Fdata-sources\u002Fcountry","docs\u002Fshield-base\u002F02.data-sources\u002Fcountry",{"title":598,"path":599,"stem":600},"Verified Crawlers","\u002Fdocs\u002Fshield-base\u002Fdata-sources\u002Fcrawlers","docs\u002Fshield-base\u002F02.data-sources\u002Fcrawlers",{"title":602,"path":603,"stem":604},"Disposable Emails","\u002Fdocs\u002Fshield-base\u002Fdata-sources\u002Femail","docs\u002Fshield-base\u002F02.data-sources\u002Femail",{"title":606,"path":607,"stem":608},"FireHOL Threat Intelligence","\u002Fdocs\u002Fshield-base\u002Fdata-sources\u002Ffirehol","docs\u002Fshield-base\u002F02.data-sources\u002Ffirehol",{"title":610,"path":611,"stem":612},"Proxy Detection","\u002Fdocs\u002Fshield-base\u002Fdata-sources\u002Fproxy","docs\u002Fshield-base\u002F02.data-sources\u002Fproxy",{"title":614,"path":615,"stem":616},"Tor Nodes","\u002Fdocs\u002Fshield-base\u002Fdata-sources\u002Ftor","docs\u002Fshield-base\u002F02.data-sources\u002Ftor",{"title":618,"path":619,"stem":620},"Suspicious User-Agents","\u002Fdocs\u002Fshield-base\u002Fdata-sources\u002Fuseragent","docs\u002Fshield-base\u002F02.data-sources\u002Fuseragent",{"title":622,"path":623,"stem":624},"Programmatic Usage","\u002Fdocs\u002Fshield-base\u002Fusage","docs\u002Fshield-base\u002F03.usage",{"title":626,"path":627,"stem":628},"Custom Data Sources","\u002Fdocs\u002Fshield-base\u002Fcustom-data-sources","docs\u002Fshield-base\u002F04.custom-data-sources",{"title":630,"path":631,"stem":632},"TypeScript Types","\u002Fdocs\u002Fshield-base\u002Ftypes","docs\u002Fshield-base\u002F05.types",{"title":196,"path":634,"stem":635},"\u002Fdocs\u002Fshield-base\u002Fapi","docs\u002Fshield-base\u002F06.api",{"title":214,"path":48,"stem":637,"children":638},"docs\u002Futils\u002Findex",[639,640,657,690,787],{"title":214,"path":48,"stem":637},{"title":641,"path":642,"stem":643,"children":644,"page":53},"Eslint","\u002Fdocs\u002Futils\u002Feslint","docs\u002Futils\u002Feslint",[645,649,653],{"title":646,"path":647,"stem":648},"React Config","\u002Fdocs\u002Futils\u002Feslint\u002Freact","docs\u002Futils\u002Feslint\u002Freact",{"title":650,"path":651,"stem":652},"TypeScript Config","\u002Fdocs\u002Futils\u002Feslint\u002Ftypescript","docs\u002Futils\u002Feslint\u002Ftypescript",{"title":654,"path":655,"stem":656},"Vue Config","\u002Fdocs\u002Futils\u002Feslint\u002Fvue","docs\u002Futils\u002Feslint\u002Fvue",{"title":658,"path":659,"stem":660,"children":661,"page":53},"Server","\u002Fdocs\u002Futils\u002Fserver","docs\u002Futils\u002Fserver",[662,666,670,674,678,682,686],{"title":663,"path":664,"stem":665},"Encryption","\u002Fdocs\u002Futils\u002Fserver\u002Fencryption","docs\u002Futils\u002Fserver\u002Fencryption",{"title":667,"path":668,"stem":669},"Path Resolver","\u002Fdocs\u002Futils\u002Fserver\u002Fpathresolver","docs\u002Futils\u002Fserver\u002FpathResolver",{"title":671,"path":672,"stem":673},"File Replacements","\u002Fdocs\u002Futils\u002Fserver\u002Freplace","docs\u002Futils\u002Fserver\u002Freplace",{"title":675,"path":676,"stem":677},"run","\u002Fdocs\u002Futils\u002Fserver\u002Frun","docs\u002Futils\u002Fserver\u002Frun",{"title":679,"path":680,"stem":681},"scheduleTask","\u002Fdocs\u002Futils\u002Fserver\u002Fscheduletask","docs\u002Futils\u002Fserver\u002FscheduleTask",{"title":683,"path":684,"stem":685},"spawnRun","\u002Fdocs\u002Futils\u002Fserver\u002Fspawnrun","docs\u002Futils\u002Fserver\u002FspawnRun",{"title":687,"path":688,"stem":689},"uploadCsv","\u002Fdocs\u002Futils\u002Fserver\u002Fuploadcsv","docs\u002Futils\u002Fserver\u002FuploadCsv",{"title":691,"path":692,"stem":693,"children":694,"page":53},"Shared","\u002Fdocs\u002Futils\u002Fshared","docs\u002Futils\u002Fshared",[695,699,703,707,711,715,719,723,727,731,735,739,743,747,751,755,759,763,767,771,775,779,783],{"title":696,"path":697,"stem":698},"BatchQueue","\u002Fdocs\u002Futils\u002Fshared\u002Fbatchqueue","docs\u002Futils\u002Fshared\u002FbatchQueue",{"title":700,"path":701,"stem":702},"capitalize","\u002Fdocs\u002Futils\u002Fshared\u002Fcapitalize","docs\u002Futils\u002Fshared\u002Fcapitalize",{"title":704,"path":705,"stem":706},"chunkProcess","\u002Fdocs\u002Futils\u002Fshared\u002Fchunkprocess","docs\u002Futils\u002Fshared\u002FchunkProcess",{"title":708,"path":709,"stem":710},"cleanObject","\u002Fdocs\u002Futils\u002Fshared\u002Fcleanobject","docs\u002Futils\u002Fshared\u002FcleanObject",{"title":712,"path":713,"stem":714},"createConfigManager","\u002Fdocs\u002Futils\u002Fshared\u002Fconfigurationdefiner","docs\u002Futils\u002Fshared\u002FconfigurationDefiner",{"title":716,"path":717,"stem":718},"debounce","\u002Fdocs\u002Futils\u002Fshared\u002Fdebounce","docs\u002Futils\u002Fshared\u002Fdebounce",{"title":720,"path":721,"stem":722},"ensureArray","\u002Fdocs\u002Futils\u002Fshared\u002Fensurearray","docs\u002Futils\u002Fshared\u002FensureArray",{"title":724,"path":725,"stem":726},"fetchWithRetry","\u002Fdocs\u002Futils\u002Fshared\u002Ffetchwithretry","docs\u002Futils\u002Fshared\u002FfetchWithRetry",{"title":728,"path":729,"stem":730},"filterEmptyValues","\u002Fdocs\u002Futils\u002Fshared\u002Ffilteremptyvalues","docs\u002Futils\u002Fshared\u002FfilterEmptyValues",{"title":732,"path":733,"stem":734},"findStringsInObject","\u002Fdocs\u002Futils\u002Fshared\u002Ffindobjectvalues","docs\u002Futils\u002Fshared\u002FfindObjectValues",{"title":736,"path":737,"stem":738},"fisherYatesShuffle","\u002Fdocs\u002Futils\u002Fshared\u002Ffisheryatesshuffle","docs\u002Futils\u002Fshared\u002FfisherYatesShuffle",{"title":740,"path":741,"stem":742},"getRandomImage","\u002Fdocs\u002Futils\u002Fshared\u002Fgetrandomimage","docs\u002Futils\u002Fshared\u002FgetRandomImage",{"title":744,"path":745,"stem":746},"isObjectHasValues","\u002Fdocs\u002Futils\u002Fshared\u002Fisobjecthasvalues","docs\u002Futils\u002Fshared\u002FisObjectHasValues",{"title":748,"path":749,"stem":750},"isAsyncOrPromise","\u002Fdocs\u002Futils\u002Fshared\u002Fispromise","docs\u002Futils\u002Fshared\u002FisPromise",{"title":752,"path":753,"stem":754},"MiniCache","\u002Fdocs\u002Futils\u002Fshared\u002Fminicache","docs\u002Futils\u002Fshared\u002FminiCache",{"title":756,"path":757,"stem":758},"parseCookies","\u002Fdocs\u002Futils\u002Fshared\u002Fparserawcookies","docs\u002Futils\u002Fshared\u002FparseRawCookies",{"title":760,"path":761,"stem":762},"safeAction","\u002Fdocs\u002Futils\u002Fshared\u002Fpromiselocker","docs\u002Futils\u002Fshared\u002FpromiseLocker",{"title":764,"path":765,"stem":766},"Random","\u002Fdocs\u002Futils\u002Fshared\u002Frandom","docs\u002Futils\u002Fshared\u002Frandom",{"title":768,"path":769,"stem":770},"range","\u002Fdocs\u002Futils\u002Fshared\u002Frange","docs\u002Futils\u002Fshared\u002Frange",{"title":772,"path":773,"stem":774},"rateLimiters","\u002Fdocs\u002Futils\u002Fshared\u002Fratelimiters","docs\u002Futils\u002Fshared\u002FrateLimiters",{"title":776,"path":777,"stem":778},"safeObjectMerge","\u002Fdocs\u002Futils\u002Fshared\u002Fsafemerge","docs\u002Futils\u002Fshared\u002FsafeMerge",{"title":780,"path":781,"stem":782},"textTruncation","\u002Fdocs\u002Futils\u002Fshared\u002Ftexttruncation","docs\u002Futils\u002Fshared\u002FtextTruncation",{"title":784,"path":785,"stem":786},"validateZodSchema","\u002Fdocs\u002Futils\u002Fshared\u002Fvalidatezodschema","docs\u002Futils\u002Fshared\u002FvalidateZodSchema",{"title":788,"path":789,"stem":790,"children":791},"Utility Types","\u002Fdocs\u002Futils\u002Ftypes","docs\u002Futils\u002Ftypes\u002Findex",[792,793,797,801,805,809,813,817,821,825],{"title":788,"path":789,"stem":790},{"title":794,"path":795,"stem":796},"Brand","\u002Fdocs\u002Futils\u002Ftypes\u002Fbrand","docs\u002Futils\u002Ftypes\u002FBrand",{"title":798,"path":799,"stem":800},"DeepPartial","\u002Fdocs\u002Futils\u002Ftypes\u002Fdeeppartial","docs\u002Futils\u002Ftypes\u002FDeepPartial",{"title":802,"path":803,"stem":804},"Merge","\u002Fdocs\u002Futils\u002Ftypes\u002Fmerge","docs\u002Futils\u002Ftypes\u002FMerge",{"title":806,"path":807,"stem":808},"NonNullable","\u002Fdocs\u002Futils\u002Ftypes\u002Fnonnullable","docs\u002Futils\u002Ftypes\u002FNonNullable",{"title":810,"path":811,"stem":812},"Prettify","\u002Fdocs\u002Futils\u002Ftypes\u002Fprettify","docs\u002Futils\u002Ftypes\u002FPrettify",{"title":814,"path":815,"stem":816},"PromiseType","\u002Fdocs\u002Futils\u002Ftypes\u002Fpromisetype","docs\u002Futils\u002Ftypes\u002FPromiseType",{"title":818,"path":819,"stem":820},"RequireKeys","\u002Fdocs\u002Futils\u002Ftypes\u002Frequirekeys","docs\u002Futils\u002Ftypes\u002FRequireKeys",{"title":822,"path":823,"stem":824},"StandardResponse","\u002Fdocs\u002Futils\u002Ftypes\u002Fstandardresponse","docs\u002Futils\u002Ftypes\u002FStandardResponse",{"title":826,"path":827,"stem":828},"ValueOf","\u002Fdocs\u002Futils\u002Ftypes\u002Fvalueof","docs\u002Futils\u002Ftypes\u002FValueOf",{"id":4,"extension":5,"links":830,"meta":841,"stem":62,"__hash__":63},[831,839,840],{"nested":8,"label":9,"icon":10,"to":11,"children":832},[833,834,835,836,837,838],{"label":14,"icon":15,"to":11,"description":16,"github":17,"badge":18},{"label":20,"icon":21,"to":22,"description":23,"github":24,"badge":25},{"label":27,"icon":28,"to":29,"description":30,"github":31,"badge":25},{"label":33,"icon":34,"to":35,"description":36,"github":37,"badge":38},{"label":40,"icon":41,"to":42,"description":43,"github":44,"badge":38},{"label":46,"icon":47,"to":48,"description":49,"github":50,"badge":51},{"nested":53,"label":54,"icon":55,"to":56},{"nested":53,"label":58,"icon":59,"to":60},{},{"id":843,"title":184,"body":844,"description":2068,"extension":2069,"icon":2070,"meta":2071,"module":2072,"navigation":8,"path":185,"rawbody":2073,"seo":2074,"stem":186,"__hash__":2075},"docs\u002Fdocs\u002Fauth-h3client\u002F05.guides\u002Fimage-upload.md",{"type":845,"value":846,"toc":2061},"minimark",[847,865,868,872,880,1043,1092,1094,1100,1110,1193,1196,1324,1326,1330,1337,1778,1780,1784,1794,1868,1870,1874,1886,2020,2033,2057],[848,849,850,851,858,859,864],"p",{},"The module provides an image validation and conversion pipeline built on ",[852,853,857],"a",{"href":854,"rel":855},"https:\u002F\u002Fsharp.pixelplumbing.com\u002F",[856],"nofollow","sharp"," and ",[852,860,863],{"href":861,"rel":862},"https:\u002F\u002Fgithub.com\u002Fsindresorhus\u002Ffile-type",[856],"file-type",". It validates the uploaded buffer against configured limits, detects the actual MIME type from the file magic bytes rather than trusting the filename extension, converts the image to WebP, and derives a storage key.",[866,867],"hr",{},[869,870,192],"h2",{"id":871},"configuration",[848,873,874,875,879],{},"The ",[876,877,878],"code",{},"imageUploader"," block in the configuration controls what is allowed:",[881,882,887],"pre",{"className":883,"code":884,"language":885,"meta":886,"style":886},"language-ts shiki shiki-themes light-plus light-plus dracula","imageUploader: {\n  allowedBytes: 5_000_000,                              \u002F\u002F 5 MB max\n  allowedMimes: ['image\u002Fpng', 'image\u002Fjpeg', 'image\u002Fwebp'],\n  allowedExtensions: ['png', 'webp', 'jpeg', 'jpg'],\n  key: (input) => `uploads\u002Fusers\u002F${input.userId}`       \u002F\u002F optional\n}\n","ts","",[876,888,889,898,915,953,995,1037],{"__ignoreMap":886},[890,891,894],"span",{"class":892,"line":893},"line",1,[890,895,897],{"class":896},"sDd4n","imageUploader: {\n",[890,899,901,904,908,911],{"class":892,"line":900},2,[890,902,903],{"class":896},"  allowedBytes: ",[890,905,907],{"class":906},"spgvN","5_000_000",[890,909,910],{"class":896},",                              ",[890,912,914],{"class":913},"sghk6","\u002F\u002F 5 MB max\n",[890,916,918,921,925,929,931,934,936,939,941,943,945,948,950],{"class":892,"line":917},3,[890,919,920],{"class":896},"  allowedMimes: [",[890,922,924],{"class":923},"sFkSl","'",[890,926,928],{"class":927},"sFB1V","image\u002Fpng",[890,930,924],{"class":923},[890,932,933],{"class":896},", ",[890,935,924],{"class":923},[890,937,938],{"class":927},"image\u002Fjpeg",[890,940,924],{"class":923},[890,942,933],{"class":896},[890,944,924],{"class":923},[890,946,947],{"class":927},"image\u002Fwebp",[890,949,924],{"class":923},[890,951,952],{"class":896},"],\n",[890,954,956,959,961,964,966,968,970,973,975,977,979,982,984,986,988,991,993],{"class":892,"line":955},4,[890,957,958],{"class":896},"  allowedExtensions: [",[890,960,924],{"class":923},[890,962,963],{"class":927},"png",[890,965,924],{"class":923},[890,967,933],{"class":896},[890,969,924],{"class":923},[890,971,972],{"class":927},"webp",[890,974,924],{"class":923},[890,976,933],{"class":896},[890,978,924],{"class":923},[890,980,981],{"class":927},"jpeg",[890,983,924],{"class":923},[890,985,933],{"class":896},[890,987,924],{"class":923},[890,989,990],{"class":927},"jpg",[890,992,924],{"class":923},[890,994,952],{"class":896},[890,996,998,1001,1005,1008,1012,1015,1018,1021,1025,1028,1031,1034],{"class":892,"line":997},5,[890,999,1000],{"class":896},"  key: (",[890,1002,1004],{"class":1003},"sygFZ","input",[890,1006,1007],{"class":896},") ",[890,1009,1011],{"class":1010},"sl46w","=>",[890,1013,1014],{"class":927}," `uploads\u002Fusers\u002F",[890,1016,1017],{"class":1010},"${",[890,1019,1004],{"class":1020},"sjsA6",[890,1022,1024],{"class":1023},"s1lnM",".",[890,1026,1027],{"class":1020},"userId",[890,1029,1030],{"class":1010},"}",[890,1032,1033],{"class":927},"`",[890,1035,1036],{"class":913},"       \u002F\u002F optional\n",[890,1038,1040],{"class":892,"line":1039},6,[890,1041,1042],{"class":896},"}\n",[1044,1045,1046,1058,1068,1077],"field-group",{},[1047,1048,1051],"field",{"name":1049,"type":1050},"allowedBytes","number",[848,1052,1053,1054,1057],{},"Maximum buffer size in bytes. Buffers exceeding this limit are rejected before any processing begins. Default to ",[876,1055,1056],{},"5000000"," (5 MB).",[1047,1059,1062],{"name":1060,"type":1061},"allowedMimes","string[]",[848,1063,1064,1065,1024],{},"Allowed MIME types. Validated against the actual detected type from the file magic bytes, not the declared content type. Default to ",[876,1066,1067],{},"[\"image\u002Fpng\", \"image\u002Fjpeg\", \"image\u002Fwebp\"]",[1047,1069,1071],{"name":1070,"type":1061},"allowedExtensions",[848,1072,1073,1074,1024],{},"Allowed file extensions, matched against the extension detected from magic bytes. Default to ",[876,1075,1076],{},"[\"png\", \"webp\", \"jpeg\", \"jpg\"]",[1047,1078,1081],{"name":1079,"type":1080},"key","Function",[848,1082,1083,1084,1087,1088,1091],{},"Optional function that returns a storage path prefix. Called with no arguments in the current implementation. The key is combined with a sanitized filename and ",[876,1085,1086],{},".webp"," extension: ",[876,1089,1090],{},"{key()}_{sanitizedName}.webp",". When omitted, a UUID is used as the prefix.",[866,1093],{},[869,1095,1097],{"id":1096},"validateimage",[876,1098,1099],{},"validateImage",[848,1101,1102,1105,1106,1109],{},[876,1103,1104],{},"validateImage(data, filename)"," takes a raw ",[876,1107,1108],{},"Buffer"," and the original filename. It runs the following checks in order:",[1111,1112,1114,1119,1129,1133,1142,1146,1158,1162,1165,1178,1182],"steps",{"level":1113},"4",[1115,1116,1118],"h4",{"id":1117},"size-check","Size check",[848,1120,1121,1122,1124,1125,1128],{},"Rejects buffers larger than ",[876,1123,1049],{},". Returns ",[876,1126,1127],{},"{ ok: false, reason: 'File to large' }"," immediately without processing.",[1115,1130,1132],{"id":1131},"mime-detection","MIME detection",[848,1134,1135,1136,1138,1139,1024],{},"Reads the file magic bytes using ",[876,1137,863],{},". If the type cannot be detected, returns ",[876,1140,1141],{},"{ ok: false, reason: 'Error validating mime' }",[1115,1143,1145],{"id":1144},"type-and-extension-check","Type and extension check",[848,1147,1148,1149,858,1151,1153,1154,1157],{},"Compares the detected MIME type and extension against ",[876,1150,1060],{},[876,1152,1070],{},". Both must be in the allowed lists. Returns ",[876,1155,1156],{},"{ ok: false, reason: 'Not allowed file type.' }"," on mismatch.",[1115,1159,1161],{"id":1160},"webp-conversion","WebP conversion",[848,1163,1164],{},"Passes the buffer through sharp with:",[1166,1167,1168,1172,1175],"ul",{},[1169,1170,1171],"li",{},"Auto-rotation based on EXIF orientation",[1169,1173,1174],{},"Resize to fit within 2000×2000 pixels, preserving aspect ratio",[1169,1176,1177],{},"WebP conversion at effort level 5",[1115,1179,1181],{"id":1180},"key-generation","Key generation",[848,1183,1184,1185,1188,1189,1192],{},"Sanitizes the filename using ",[876,1186,1187],{},"sanitizeBaseName(filename, 64)"," to strip unsafe characters and truncate to 64 characters. Combines it with the ",[876,1190,1191],{},"key()"," result or a UUID to produce the final storage key.",[848,1194,1195],{},"Return value:",[881,1197,1199],{"className":883,"code":1198,"language":885,"meta":886,"style":886},"type ValidFile = {\n  ok: true\n  body: Buffer      \u002F\u002F WebP-converted image buffer\n  key: string       \u002F\u002F Storage key including sanitized filename and .webp extension\n  mime: string      \u002F\u002F Always 'image\u002Fwebp'\n}\n\ntype UploadError = {\n  ok: false\n  date: string\n  reason: string\n}\n",[876,1200,1201,1217,1228,1241,1254,1266,1270,1276,1288,1298,1309,1319],{"__ignoreMap":886},[890,1202,1203,1206,1210,1214],{"class":892,"line":893},[890,1204,1205],{"class":1010},"type",[890,1207,1209],{"class":1208},"sFs1U"," ValidFile",[890,1211,1213],{"class":1212},"saOXh"," =",[890,1215,1216],{"class":896}," {\n",[890,1218,1219,1222,1225],{"class":892,"line":900},[890,1220,1221],{"class":1020},"  ok",[890,1223,1224],{"class":1212},":",[890,1226,1227],{"class":1208}," true\n",[890,1229,1230,1233,1235,1238],{"class":892,"line":917},[890,1231,1232],{"class":1020},"  body",[890,1234,1224],{"class":1212},[890,1236,1237],{"class":1208}," Buffer",[890,1239,1240],{"class":913},"      \u002F\u002F WebP-converted image buffer\n",[890,1242,1243,1246,1248,1251],{"class":892,"line":955},[890,1244,1245],{"class":1020},"  key",[890,1247,1224],{"class":1212},[890,1249,1250],{"class":1208}," string",[890,1252,1253],{"class":913},"       \u002F\u002F Storage key including sanitized filename and .webp extension\n",[890,1255,1256,1259,1261,1263],{"class":892,"line":997},[890,1257,1258],{"class":1020},"  mime",[890,1260,1224],{"class":1212},[890,1262,1250],{"class":1208},[890,1264,1265],{"class":913},"      \u002F\u002F Always 'image\u002Fwebp'\n",[890,1267,1268],{"class":892,"line":1039},[890,1269,1042],{"class":896},[890,1271,1273],{"class":892,"line":1272},7,[890,1274,1275],{"emptyLinePlaceholder":8},"\n",[890,1277,1279,1281,1284,1286],{"class":892,"line":1278},8,[890,1280,1205],{"class":1010},[890,1282,1283],{"class":1208}," UploadError",[890,1285,1213],{"class":1212},[890,1287,1216],{"class":896},[890,1289,1291,1293,1295],{"class":892,"line":1290},9,[890,1292,1221],{"class":1020},[890,1294,1224],{"class":1212},[890,1296,1297],{"class":1208}," false\n",[890,1299,1301,1304,1306],{"class":892,"line":1300},10,[890,1302,1303],{"class":1020},"  date",[890,1305,1224],{"class":1212},[890,1307,1308],{"class":1208}," string\n",[890,1310,1312,1315,1317],{"class":892,"line":1311},11,[890,1313,1314],{"class":1020},"  reason",[890,1316,1224],{"class":1212},[890,1318,1308],{"class":1208},[890,1320,1322],{"class":892,"line":1321},12,[890,1323,1042],{"class":896},[866,1325],{},[869,1327,1329],{"id":1328},"usage-in-a-route","Usage in a route",[848,1331,1332,1333,1336],{},"Use ",[876,1334,1335],{},"limitBytes"," before reading the body to reject oversized payloads at the HTTP layer before the buffer is allocated. Then read the body, validate, and store:",[881,1338,1341],{"className":883,"code":1339,"filename":1340,"language":885,"meta":886,"style":886},"export default defineAuthenticatedEventPostHandlers(async (event) => {\n  await limitBytes(5_000_000)(event)\n\n  const { userId } = event.context.authorizedData\n  const body = await readMultipartFormData(event)\n\n  const file = body?.find(f => f.name === 'avatar')\n  if (!file?.data || !file.filename) {\n    throw createError({ statusCode: 400, message: 'No file provided' })\n  }\n\n  const result = await validateImage(file.data, file.filename)\n\n  if (!result.ok) {\n    throw createError({ statusCode: 400, message: result.reason })\n  }\n\n  \u002F\u002F Store result.body at result.key using your storage provider\n  const storage = useStorage('images')\n  await storage.setItemRaw(result.key, result.body)\n\n  return { ok: true, key: result.key }\n})\n","server\u002Fapi\u002Fupload\u002Favatar.post.ts",[876,1342,1343,1374,1394,1398,1428,1449,1453,1499,1533,1570,1575,1579,1611,1616,1635,1665,1670,1675,1681,1705,1736,1741,1772],{"__ignoreMap":886},[890,1344,1345,1349,1352,1356,1359,1362,1365,1368,1370,1372],{"class":892,"line":893},[890,1346,1348],{"class":1347},"sZ328","export",[890,1350,1351],{"class":1347}," default",[890,1353,1355],{"class":1354},"sHOzp"," defineAuthenticatedEventPostHandlers",[890,1357,1358],{"class":896},"(",[890,1360,1361],{"class":1010},"async",[890,1363,1364],{"class":896}," (",[890,1366,1367],{"class":1003},"event",[890,1369,1007],{"class":896},[890,1371,1011],{"class":1010},[890,1373,1216],{"class":896},[890,1375,1376,1379,1382,1384,1386,1389,1391],{"class":892,"line":900},[890,1377,1378],{"class":1347},"  await",[890,1380,1381],{"class":1354}," limitBytes",[890,1383,1358],{"class":896},[890,1385,907],{"class":906},[890,1387,1388],{"class":896},")(",[890,1390,1367],{"class":1020},[890,1392,1393],{"class":896},")\n",[890,1395,1396],{"class":892,"line":917},[890,1397,1275],{"emptyLinePlaceholder":8},[890,1399,1400,1403,1406,1409,1412,1415,1418,1420,1423,1425],{"class":892,"line":955},[890,1401,1402],{"class":1010},"  const",[890,1404,1405],{"class":896}," { ",[890,1407,1027],{"class":1408},"s3JHE",[890,1410,1411],{"class":896}," } ",[890,1413,1414],{"class":1212},"=",[890,1416,1417],{"class":1020}," event",[890,1419,1024],{"class":896},[890,1421,1422],{"class":1020},"context",[890,1424,1024],{"class":896},[890,1426,1427],{"class":1020},"authorizedData\n",[890,1429,1430,1432,1435,1437,1440,1443,1445,1447],{"class":892,"line":997},[890,1431,1402],{"class":1010},[890,1433,1434],{"class":1408}," body",[890,1436,1213],{"class":1212},[890,1438,1439],{"class":1347}," await",[890,1441,1442],{"class":1354}," readMultipartFormData",[890,1444,1358],{"class":896},[890,1446,1367],{"class":1020},[890,1448,1393],{"class":896},[890,1450,1451],{"class":892,"line":1039},[890,1452,1275],{"emptyLinePlaceholder":8},[890,1454,1455,1457,1460,1462,1464,1467,1470,1472,1475,1478,1481,1483,1486,1489,1492,1495,1497],{"class":892,"line":1272},[890,1456,1402],{"class":1010},[890,1458,1459],{"class":1408}," file",[890,1461,1213],{"class":1212},[890,1463,1434],{"class":1020},[890,1465,1466],{"class":896},"?.",[890,1468,1469],{"class":1354},"find",[890,1471,1358],{"class":896},[890,1473,1474],{"class":1003},"f",[890,1476,1477],{"class":1010}," =>",[890,1479,1480],{"class":1020}," f",[890,1482,1024],{"class":896},[890,1484,1485],{"class":1020},"name",[890,1487,1488],{"class":1212}," ===",[890,1490,1491],{"class":923}," '",[890,1493,1494],{"class":927},"avatar",[890,1496,924],{"class":923},[890,1498,1393],{"class":896},[890,1500,1501,1504,1506,1509,1512,1514,1517,1520,1523,1525,1527,1530],{"class":892,"line":1278},[890,1502,1503],{"class":1347},"  if",[890,1505,1364],{"class":896},[890,1507,1508],{"class":1212},"!",[890,1510,1511],{"class":1020},"file",[890,1513,1466],{"class":896},[890,1515,1516],{"class":1020},"data",[890,1518,1519],{"class":1212}," ||",[890,1521,1522],{"class":1212}," !",[890,1524,1511],{"class":1020},[890,1526,1024],{"class":896},[890,1528,1529],{"class":1020},"filename",[890,1531,1532],{"class":896},") {\n",[890,1534,1535,1538,1541,1544,1547,1550,1553,1555,1558,1560,1562,1565,1567],{"class":892,"line":1290},[890,1536,1537],{"class":1347},"    throw",[890,1539,1540],{"class":1354}," createError",[890,1542,1543],{"class":896},"({ ",[890,1545,1546],{"class":1020},"statusCode",[890,1548,1224],{"class":1549},"s34zl",[890,1551,1552],{"class":906}," 400",[890,1554,933],{"class":896},[890,1556,1557],{"class":1020},"message",[890,1559,1224],{"class":1549},[890,1561,1491],{"class":923},[890,1563,1564],{"class":927},"No file provided",[890,1566,924],{"class":923},[890,1568,1569],{"class":896}," })\n",[890,1571,1572],{"class":892,"line":1300},[890,1573,1574],{"class":896},"  }\n",[890,1576,1577],{"class":892,"line":1311},[890,1578,1275],{"emptyLinePlaceholder":8},[890,1580,1581,1583,1586,1588,1590,1593,1595,1597,1599,1601,1603,1605,1607,1609],{"class":892,"line":1321},[890,1582,1402],{"class":1010},[890,1584,1585],{"class":1408}," result",[890,1587,1213],{"class":1212},[890,1589,1439],{"class":1347},[890,1591,1592],{"class":1354}," validateImage",[890,1594,1358],{"class":896},[890,1596,1511],{"class":1020},[890,1598,1024],{"class":896},[890,1600,1516],{"class":1020},[890,1602,933],{"class":896},[890,1604,1511],{"class":1020},[890,1606,1024],{"class":896},[890,1608,1529],{"class":1020},[890,1610,1393],{"class":896},[890,1612,1614],{"class":892,"line":1613},13,[890,1615,1275],{"emptyLinePlaceholder":8},[890,1617,1619,1621,1623,1625,1628,1630,1633],{"class":892,"line":1618},14,[890,1620,1503],{"class":1347},[890,1622,1364],{"class":896},[890,1624,1508],{"class":1212},[890,1626,1627],{"class":1020},"result",[890,1629,1024],{"class":896},[890,1631,1632],{"class":1020},"ok",[890,1634,1532],{"class":896},[890,1636,1638,1640,1642,1644,1646,1648,1650,1652,1654,1656,1658,1660,1663],{"class":892,"line":1637},15,[890,1639,1537],{"class":1347},[890,1641,1540],{"class":1354},[890,1643,1543],{"class":896},[890,1645,1546],{"class":1020},[890,1647,1224],{"class":1549},[890,1649,1552],{"class":906},[890,1651,933],{"class":896},[890,1653,1557],{"class":1020},[890,1655,1224],{"class":1549},[890,1657,1585],{"class":1020},[890,1659,1024],{"class":896},[890,1661,1662],{"class":1020},"reason",[890,1664,1569],{"class":896},[890,1666,1668],{"class":892,"line":1667},16,[890,1669,1574],{"class":896},[890,1671,1673],{"class":892,"line":1672},17,[890,1674,1275],{"emptyLinePlaceholder":8},[890,1676,1678],{"class":892,"line":1677},18,[890,1679,1680],{"class":913},"  \u002F\u002F Store result.body at result.key using your storage provider\n",[890,1682,1684,1686,1689,1691,1694,1696,1698,1701,1703],{"class":892,"line":1683},19,[890,1685,1402],{"class":1010},[890,1687,1688],{"class":1408}," storage",[890,1690,1213],{"class":1212},[890,1692,1693],{"class":1354}," useStorage",[890,1695,1358],{"class":896},[890,1697,924],{"class":923},[890,1699,1700],{"class":927},"images",[890,1702,924],{"class":923},[890,1704,1393],{"class":896},[890,1706,1708,1710,1712,1714,1717,1719,1721,1723,1725,1727,1729,1731,1734],{"class":892,"line":1707},20,[890,1709,1378],{"class":1347},[890,1711,1688],{"class":1020},[890,1713,1024],{"class":896},[890,1715,1716],{"class":1354},"setItemRaw",[890,1718,1358],{"class":896},[890,1720,1627],{"class":1020},[890,1722,1024],{"class":896},[890,1724,1079],{"class":1020},[890,1726,933],{"class":896},[890,1728,1627],{"class":1020},[890,1730,1024],{"class":896},[890,1732,1733],{"class":1020},"body",[890,1735,1393],{"class":896},[890,1737,1739],{"class":892,"line":1738},21,[890,1740,1275],{"emptyLinePlaceholder":8},[890,1742,1744,1747,1749,1751,1753,1757,1759,1761,1763,1765,1767,1769],{"class":892,"line":1743},22,[890,1745,1746],{"class":1347},"  return",[890,1748,1405],{"class":896},[890,1750,1632],{"class":1020},[890,1752,1224],{"class":1549},[890,1754,1756],{"class":1755},"sjR7W"," true",[890,1758,933],{"class":896},[890,1760,1079],{"class":1020},[890,1762,1224],{"class":1549},[890,1764,1585],{"class":1020},[890,1766,1024],{"class":896},[890,1768,1079],{"class":1020},[890,1770,1771],{"class":896}," }\n",[890,1773,1775],{"class":892,"line":1774},23,[890,1776,1777],{"class":896},"})\n",[866,1779],{},[869,1781,1783],{"id":1782},"filename-sanitization","Filename sanitization",[848,1785,1786,1789,1790,1793],{},[876,1787,1788],{},"sanitizeBaseName(input, max)"," strips path traversal sequences, null bytes, control characters, and other unsafe characters from a filename. It truncates to ",[876,1791,1792],{},"max"," characters. Use it whenever you derive a storage path from user-supplied input:",[881,1795,1797],{"className":883,"code":1796,"language":885,"meta":886,"style":886},"const cleanName = sanitizeBaseName('..\u002F..\u002Fetc\u002Fpasswd.png', 64)\n\u002F\u002F 'etcpasswd.png'\n\nconst cleanName2 = sanitizeBaseName('my profile photo (2026).jpeg', 64)\n\u002F\u002F 'my_profile_photo_2026.jpeg'\n",[876,1798,1799,1828,1833,1837,1863],{"__ignoreMap":886},[890,1800,1801,1804,1807,1809,1812,1814,1816,1819,1821,1823,1826],{"class":892,"line":893},[890,1802,1803],{"class":1010},"const",[890,1805,1806],{"class":1408}," cleanName",[890,1808,1213],{"class":1212},[890,1810,1811],{"class":1354}," sanitizeBaseName",[890,1813,1358],{"class":896},[890,1815,924],{"class":923},[890,1817,1818],{"class":927},"..\u002F..\u002Fetc\u002Fpasswd.png",[890,1820,924],{"class":923},[890,1822,933],{"class":896},[890,1824,1825],{"class":906},"64",[890,1827,1393],{"class":896},[890,1829,1830],{"class":892,"line":900},[890,1831,1832],{"class":913},"\u002F\u002F 'etcpasswd.png'\n",[890,1834,1835],{"class":892,"line":917},[890,1836,1275],{"emptyLinePlaceholder":8},[890,1838,1839,1841,1844,1846,1848,1850,1852,1855,1857,1859,1861],{"class":892,"line":955},[890,1840,1803],{"class":1010},[890,1842,1843],{"class":1408}," cleanName2",[890,1845,1213],{"class":1212},[890,1847,1811],{"class":1354},[890,1849,1358],{"class":896},[890,1851,924],{"class":923},[890,1853,1854],{"class":927},"my profile photo (2026).jpeg",[890,1856,924],{"class":923},[890,1858,933],{"class":896},[890,1860,1825],{"class":906},[890,1862,1393],{"class":896},[890,1864,1865],{"class":892,"line":997},[890,1866,1867],{"class":913},"\u002F\u002F 'my_profile_photo_2026.jpeg'\n",[866,1869],{},[869,1871,1873],{"id":1872},"storage","Storage",[848,1875,874,1876,1879,1880,1885],{},[876,1877,1878],{},"uStorage"," configuration accepts any ",[852,1881,1884],{"href":1882,"rel":1883},"https:\u002F\u002Funstorage.unjs.io\u002F",[856],"unstorage"," instance. Use the same storage instance for auth caching and image metadata, or configure separate instances:",[881,1887,1889],{"className":883,"code":1888,"language":885,"meta":886,"style":886},"import { createStorage } from 'unstorage'\nimport fsDriver from 'unstorage\u002Fdrivers\u002Ffs'\n\nuStorage: {\n  storage: createStorage({ driver: fsDriver({ base: '.\u002Fdata' }) }),\n  cacheOptions: {\n    successTtl: 60 * 60 * 24 * 30,\n    rateLimitTtl: 10\n  }\n}\n",[876,1890,1891,1913,1930,1934,1939,1972,1977,2004,2012,2016],{"__ignoreMap":886},[890,1892,1893,1896,1898,1901,1903,1906,1908,1910],{"class":892,"line":893},[890,1894,1895],{"class":1347},"import",[890,1897,1405],{"class":896},[890,1899,1900],{"class":1020},"createStorage",[890,1902,1411],{"class":896},[890,1904,1905],{"class":1347},"from",[890,1907,1491],{"class":923},[890,1909,1884],{"class":927},[890,1911,1912],{"class":923},"'\n",[890,1914,1915,1917,1920,1923,1925,1928],{"class":892,"line":900},[890,1916,1895],{"class":1347},[890,1918,1919],{"class":1020}," fsDriver",[890,1921,1922],{"class":1347}," from",[890,1924,1491],{"class":923},[890,1926,1927],{"class":927},"unstorage\u002Fdrivers\u002Ffs",[890,1929,1912],{"class":923},[890,1931,1932],{"class":892,"line":917},[890,1933,1275],{"emptyLinePlaceholder":8},[890,1935,1936],{"class":892,"line":955},[890,1937,1938],{"class":896},"uStorage: {\n",[890,1940,1941,1944,1946,1948,1951,1953,1955,1957,1960,1962,1964,1967,1969],{"class":892,"line":997},[890,1942,1943],{"class":896},"  storage: ",[890,1945,1900],{"class":1354},[890,1947,1543],{"class":896},[890,1949,1950],{"class":1020},"driver",[890,1952,1224],{"class":1549},[890,1954,1919],{"class":1354},[890,1956,1543],{"class":896},[890,1958,1959],{"class":1020},"base",[890,1961,1224],{"class":1549},[890,1963,1491],{"class":923},[890,1965,1966],{"class":927},".\u002Fdata",[890,1968,924],{"class":923},[890,1970,1971],{"class":896}," }) }),\n",[890,1973,1974],{"class":892,"line":1039},[890,1975,1976],{"class":896},"  cacheOptions: {\n",[890,1978,1979,1982,1985,1988,1991,1993,1996,1998,2001],{"class":892,"line":1272},[890,1980,1981],{"class":896},"    successTtl: ",[890,1983,1984],{"class":906},"60",[890,1986,1987],{"class":1212}," *",[890,1989,1990],{"class":906}," 60",[890,1992,1987],{"class":1212},[890,1994,1995],{"class":906}," 24",[890,1997,1987],{"class":1212},[890,1999,2000],{"class":906}," 30",[890,2002,2003],{"class":896},",\n",[890,2005,2006,2009],{"class":892,"line":1278},[890,2007,2008],{"class":896},"    rateLimitTtl: ",[890,2010,2011],{"class":906},"10\n",[890,2013,2014],{"class":892,"line":1290},[890,2015,1574],{"class":896},[890,2017,2018],{"class":892,"line":1300},[890,2019,1042],{"class":896},[848,2021,874,2022,2025,2026,2029,2030,2032],{},[876,2023,2024],{},"uStorage.storage"," instance is used by ",[876,2027,2028],{},"getCachedUserData"," for session caching. Image buffers stored via ",[876,2031,1716],{}," use the same storage instance but different key namespaces, so there is no conflict.",[848,2034,2035,2036,2040,2041,2044,2045,2047,2048,2050,2051,2053,2054,1024],{},"See ",[852,2037,2039],{"href":2038},"\u002Fdocs\u002Fauth-h3client\u002Fsecurity#input-validation","Security: Input Validation"," for how ",[876,2042,2043],{},"sanitizeBaseName"," fits into the module's broader input sanitization strategy. The ",[876,2046,1099],{}," function reference with the full ",[876,2049,1632],{}," \u002F ",[876,2052,1662],{}," return type is in ",[852,2055,214],{"href":2056},"\u002Fdocs\u002Fauth-h3client\u002Fapi\u002Futilities#validateimage",[2058,2059,2060],"style",{},"html pre.shiki code .sDd4n, html code.shiki .sDd4n{--shiki-light:#000000;--shiki-default:#000000;--shiki-dark:#F8F8F2}html pre.shiki code .spgvN, html code.shiki .spgvN{--shiki-light:#098658;--shiki-default:#098658;--shiki-dark:#BD93F9}html pre.shiki code .sghk6, html code.shiki .sghk6{--shiki-light:#008000;--shiki-default:#008000;--shiki-dark:#6272A4}html pre.shiki code .sFkSl, html code.shiki .sFkSl{--shiki-light:#A31515;--shiki-default:#A31515;--shiki-dark:#E9F284}html pre.shiki code .sFB1V, html code.shiki .sFB1V{--shiki-light:#A31515;--shiki-default:#A31515;--shiki-dark:#F1FA8C}html pre.shiki code .sygFZ, html code.shiki .sygFZ{--shiki-light:#001080;--shiki-light-font-style:inherit;--shiki-default:#001080;--shiki-default-font-style:inherit;--shiki-dark:#FFB86C;--shiki-dark-font-style:italic}html pre.shiki code .sl46w, html code.shiki .sl46w{--shiki-light:#0000FF;--shiki-default:#0000FF;--shiki-dark:#FF79C6}html pre.shiki code .sjsA6, html code.shiki .sjsA6{--shiki-light:#001080;--shiki-default:#001080;--shiki-dark:#F8F8F2}html pre.shiki code .s1lnM, html code.shiki .s1lnM{--shiki-light:#000000FF;--shiki-default:#000000FF;--shiki-dark:#F8F8F2}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sFs1U, html code.shiki .sFs1U{--shiki-light:#267F99;--shiki-light-font-style:inherit;--shiki-default:#267F99;--shiki-default-font-style:inherit;--shiki-dark:#8BE9FD;--shiki-dark-font-style:italic}html pre.shiki code .saOXh, html code.shiki .saOXh{--shiki-light:#000000;--shiki-default:#000000;--shiki-dark:#FF79C6}html pre.shiki code .sZ328, html code.shiki .sZ328{--shiki-light:#AF00DB;--shiki-default:#AF00DB;--shiki-dark:#FF79C6}html pre.shiki code .sHOzp, html code.shiki .sHOzp{--shiki-light:#795E26;--shiki-default:#795E26;--shiki-dark:#50FA7B}html pre.shiki code .s3JHE, html code.shiki .s3JHE{--shiki-light:#0070C1;--shiki-default:#0070C1;--shiki-dark:#F8F8F2}html pre.shiki code .s34zl, html code.shiki .s34zl{--shiki-light:#001080;--shiki-default:#001080;--shiki-dark:#FF79C6}html pre.shiki code .sjR7W, html code.shiki .sjR7W{--shiki-light:#0000FF;--shiki-default:#0000FF;--shiki-dark:#BD93F9}",{"title":886,"searchDepth":900,"depth":900,"links":2062},[2063,2064,2065,2066,2067],{"id":871,"depth":900,"text":192},{"id":1096,"depth":900,"text":1099},{"id":1328,"depth":900,"text":1329},{"id":1782,"depth":900,"text":1783},{"id":1872,"depth":900,"text":1873},"How to validate uploaded image buffers, enforce size and type limits, convert to WebP, and store the result using the configured unstorage instance.","md","i-lucide-image",{},null,"---\ntitle: Image Upload\ndescription: How to validate uploaded image buffers, enforce size and type limits, convert to WebP, and store the result using the configured unstorage instance.\nicon: i-lucide-image\n---\n\nThe module provides an image validation and conversion pipeline built on [sharp](https:\u002F\u002Fsharp.pixelplumbing.com\u002F) and [file-type](https:\u002F\u002Fgithub.com\u002Fsindresorhus\u002Ffile-type). It validates the uploaded buffer against configured limits, detects the actual MIME type from the file magic bytes rather than trusting the filename extension, converts the image to WebP, and derives a storage key.\n\n---\n\n## Configuration\n\nThe `imageUploader` block in the configuration controls what is allowed:\n\n```ts\nimageUploader: {\n  allowedBytes: 5_000_000,                              \u002F\u002F 5 MB max\n  allowedMimes: ['image\u002Fpng', 'image\u002Fjpeg', 'image\u002Fwebp'],\n  allowedExtensions: ['png', 'webp', 'jpeg', 'jpg'],\n  key: (input) => `uploads\u002Fusers\u002F${input.userId}`       \u002F\u002F optional\n}\n```\n\n::field-group\n\n::field{name=\"allowedBytes\" type=\"number\"}\nMaximum buffer size in bytes. Buffers exceeding this limit are rejected before any processing begins. Default to `5000000` (5 MB).\n::\n\n::field{name=\"allowedMimes\" type=\"string[]\"}\nAllowed MIME types. Validated against the actual detected type from the file magic bytes, not the declared content type. Default to `[\"image\u002Fpng\", \"image\u002Fjpeg\", \"image\u002Fwebp\"]`.\n::\n\n::field{name=\"allowedExtensions\" type=\"string[]\"}\nAllowed file extensions, matched against the extension detected from magic bytes. Default to `[\"png\", \"webp\", \"jpeg\", \"jpg\"]`.\n::\n\n::field{name=\"key\" type=\"Function\"}\nOptional function that returns a storage path prefix. Called with no arguments in the current implementation. The key is combined with a sanitized filename and `.webp` extension: `{key()}_{sanitizedName}.webp`. When omitted, a UUID is used as the prefix.\n::\n\n::\n\n---\n\n## `validateImage`\n\n`validateImage(data, filename)` takes a raw `Buffer` and the original filename. It runs the following checks in order:\n\n::steps{level=\"4\"}\n\n#### Size check\n\nRejects buffers larger than `allowedBytes`. Returns `{ ok: false, reason: 'File to large' }` immediately without processing.\n\n#### MIME detection\n\nReads the file magic bytes using `file-type`. If the type cannot be detected, returns `{ ok: false, reason: 'Error validating mime' }`.\n\n#### Type and extension check\n\nCompares the detected MIME type and extension against `allowedMimes` and `allowedExtensions`. Both must be in the allowed lists. Returns `{ ok: false, reason: 'Not allowed file type.' }` on mismatch.\n\n#### WebP conversion\n\nPasses the buffer through sharp with:\n- Auto-rotation based on EXIF orientation\n- Resize to fit within 2000×2000 pixels, preserving aspect ratio\n- WebP conversion at effort level 5\n\n#### Key generation\n\nSanitizes the filename using `sanitizeBaseName(filename, 64)` to strip unsafe characters and truncate to 64 characters. Combines it with the `key()` result or a UUID to produce the final storage key.\n\n::\n\nReturn value:\n\n```ts\ntype ValidFile = {\n  ok: true\n  body: Buffer      \u002F\u002F WebP-converted image buffer\n  key: string       \u002F\u002F Storage key including sanitized filename and .webp extension\n  mime: string      \u002F\u002F Always 'image\u002Fwebp'\n}\n\ntype UploadError = {\n  ok: false\n  date: string\n  reason: string\n}\n```\n\n---\n\n## Usage in a route\n\nUse `limitBytes` before reading the body to reject oversized payloads at the HTTP layer before the buffer is allocated. Then read the body, validate, and store:\n\n```ts [server\u002Fapi\u002Fupload\u002Favatar.post.ts]\nexport default defineAuthenticatedEventPostHandlers(async (event) => {\n  await limitBytes(5_000_000)(event)\n\n  const { userId } = event.context.authorizedData\n  const body = await readMultipartFormData(event)\n\n  const file = body?.find(f => f.name === 'avatar')\n  if (!file?.data || !file.filename) {\n    throw createError({ statusCode: 400, message: 'No file provided' })\n  }\n\n  const result = await validateImage(file.data, file.filename)\n\n  if (!result.ok) {\n    throw createError({ statusCode: 400, message: result.reason })\n  }\n\n  \u002F\u002F Store result.body at result.key using your storage provider\n  const storage = useStorage('images')\n  await storage.setItemRaw(result.key, result.body)\n\n  return { ok: true, key: result.key }\n})\n```\n\n---\n\n## Filename sanitization\n\n`sanitizeBaseName(input, max)` strips path traversal sequences, null bytes, control characters, and other unsafe characters from a filename. It truncates to `max` characters. Use it whenever you derive a storage path from user-supplied input:\n\n```ts\nconst cleanName = sanitizeBaseName('..\u002F..\u002Fetc\u002Fpasswd.png', 64)\n\u002F\u002F 'etcpasswd.png'\n\nconst cleanName2 = sanitizeBaseName('my profile photo (2026).jpeg', 64)\n\u002F\u002F 'my_profile_photo_2026.jpeg'\n```\n\n---\n\n## Storage\n\nThe `uStorage` configuration accepts any [unstorage](https:\u002F\u002Funstorage.unjs.io\u002F) instance. Use the same storage instance for auth caching and image metadata, or configure separate instances:\n\n```ts\nimport { createStorage } from 'unstorage'\nimport fsDriver from 'unstorage\u002Fdrivers\u002Ffs'\n\nuStorage: {\n  storage: createStorage({ driver: fsDriver({ base: '.\u002Fdata' }) }),\n  cacheOptions: {\n    successTtl: 60 * 60 * 24 * 30,\n    rateLimitTtl: 10\n  }\n}\n```\n\nThe `uStorage.storage` instance is used by `getCachedUserData` for session caching. Image buffers stored via `setItemRaw` use the same storage instance but different key namespaces, so there is no conflict.\n\nSee [Security: Input Validation](\u002Fdocs\u002Fauth-h3client\u002Fsecurity#input-validation) for how `sanitizeBaseName` fits into the module's broader input sanitization strategy. The `validateImage` function reference with the full `ok` \u002F `reason` return type is in [Utilities](\u002Fdocs\u002Fauth-h3client\u002Fapi\u002Futilities#validateimage).\n",{"title":184,"description":2068},"g0iIO8TLiUGnrKxtqxmLZPNqwXVanLqzzsfJd0lgTIk",[2077,2078],{"title":180,"path":181,"stem":182,"children":-1},{"title":188,"path":189,"stem":190,"children":-1},{"id":843,"title":184,"body":2080,"description":2068,"extension":2069,"icon":2070,"meta":2992,"module":2072,"navigation":8,"path":185,"rawbody":2073,"seo":2993,"stem":186,"__hash__":2075},{"type":845,"value":2081,"toc":2985},[2082,2090,2092,2094,2098,2210,2238,2240,2244,2250,2298,2300,2398,2400,2402,2406,2766,2768,2770,2776,2840,2842,2844,2851,2961,2969,2983],[848,2083,850,2084,858,2087,864],{},[852,2085,857],{"href":854,"rel":2086},[856],[852,2088,863],{"href":861,"rel":2089},[856],[866,2091],{},[869,2093,192],{"id":871},[848,2095,874,2096,879],{},[876,2097,878],{},[881,2099,2100],{"className":883,"code":884,"language":885,"meta":886,"style":886},[876,2101,2102,2106,2116,2144,2180,2206],{"__ignoreMap":886},[890,2103,2104],{"class":892,"line":893},[890,2105,897],{"class":896},[890,2107,2108,2110,2112,2114],{"class":892,"line":900},[890,2109,903],{"class":896},[890,2111,907],{"class":906},[890,2113,910],{"class":896},[890,2115,914],{"class":913},[890,2117,2118,2120,2122,2124,2126,2128,2130,2132,2134,2136,2138,2140,2142],{"class":892,"line":917},[890,2119,920],{"class":896},[890,2121,924],{"class":923},[890,2123,928],{"class":927},[890,2125,924],{"class":923},[890,2127,933],{"class":896},[890,2129,924],{"class":923},[890,2131,938],{"class":927},[890,2133,924],{"class":923},[890,2135,933],{"class":896},[890,2137,924],{"class":923},[890,2139,947],{"class":927},[890,2141,924],{"class":923},[890,2143,952],{"class":896},[890,2145,2146,2148,2150,2152,2154,2156,2158,2160,2162,2164,2166,2168,2170,2172,2174,2176,2178],{"class":892,"line":955},[890,2147,958],{"class":896},[890,2149,924],{"class":923},[890,2151,963],{"class":927},[890,2153,924],{"class":923},[890,2155,933],{"class":896},[890,2157,924],{"class":923},[890,2159,972],{"class":927},[890,2161,924],{"class":923},[890,2163,933],{"class":896},[890,2165,924],{"class":923},[890,2167,981],{"class":927},[890,2169,924],{"class":923},[890,2171,933],{"class":896},[890,2173,924],{"class":923},[890,2175,990],{"class":927},[890,2177,924],{"class":923},[890,2179,952],{"class":896},[890,2181,2182,2184,2186,2188,2190,2192,2194,2196,2198,2200,2202,2204],{"class":892,"line":997},[890,2183,1000],{"class":896},[890,2185,1004],{"class":1003},[890,2187,1007],{"class":896},[890,2189,1011],{"class":1010},[890,2191,1014],{"class":927},[890,2193,1017],{"class":1010},[890,2195,1004],{"class":1020},[890,2197,1024],{"class":1023},[890,2199,1027],{"class":1020},[890,2201,1030],{"class":1010},[890,2203,1033],{"class":927},[890,2205,1036],{"class":913},[890,2207,2208],{"class":892,"line":1039},[890,2209,1042],{"class":896},[1044,2211,2212,2218,2224,2230],{},[1047,2213,2214],{"name":1049,"type":1050},[848,2215,1053,2216,1057],{},[876,2217,1056],{},[1047,2219,2220],{"name":1060,"type":1061},[848,2221,1064,2222,1024],{},[876,2223,1067],{},[1047,2225,2226],{"name":1070,"type":1061},[848,2227,1073,2228,1024],{},[876,2229,1076],{},[1047,2231,2232],{"name":1079,"type":1080},[848,2233,1083,2234,1087,2236,1091],{},[876,2235,1086],{},[876,2237,1090],{},[866,2239],{},[869,2241,2242],{"id":1096},[876,2243,1099],{},[848,2245,2246,1105,2248,1109],{},[876,2247,1104],{},[876,2249,1108],{},[1111,2251,2252,2254,2260,2262,2268,2270,2278,2280,2282,2290,2292],{"level":1113},[1115,2253,1118],{"id":1117},[848,2255,1121,2256,1124,2258,1128],{},[876,2257,1049],{},[876,2259,1127],{},[1115,2261,1132],{"id":1131},[848,2263,1135,2264,1138,2266,1024],{},[876,2265,863],{},[876,2267,1141],{},[1115,2269,1145],{"id":1144},[848,2271,1148,2272,858,2274,1153,2276,1157],{},[876,2273,1060],{},[876,2275,1070],{},[876,2277,1156],{},[1115,2279,1161],{"id":1160},[848,2281,1164],{},[1166,2283,2284,2286,2288],{},[1169,2285,1171],{},[1169,2287,1174],{},[1169,2289,1177],{},[1115,2291,1181],{"id":1180},[848,2293,1184,2294,1188,2296,1192],{},[876,2295,1187],{},[876,2297,1191],{},[848,2299,1195],{},[881,2301,2302],{"className":883,"code":1198,"language":885,"meta":886,"style":886},[876,2303,2304,2314,2322,2332,2342,2352,2356,2360,2370,2378,2386,2394],{"__ignoreMap":886},[890,2305,2306,2308,2310,2312],{"class":892,"line":893},[890,2307,1205],{"class":1010},[890,2309,1209],{"class":1208},[890,2311,1213],{"class":1212},[890,2313,1216],{"class":896},[890,2315,2316,2318,2320],{"class":892,"line":900},[890,2317,1221],{"class":1020},[890,2319,1224],{"class":1212},[890,2321,1227],{"class":1208},[890,2323,2324,2326,2328,2330],{"class":892,"line":917},[890,2325,1232],{"class":1020},[890,2327,1224],{"class":1212},[890,2329,1237],{"class":1208},[890,2331,1240],{"class":913},[890,2333,2334,2336,2338,2340],{"class":892,"line":955},[890,2335,1245],{"class":1020},[890,2337,1224],{"class":1212},[890,2339,1250],{"class":1208},[890,2341,1253],{"class":913},[890,2343,2344,2346,2348,2350],{"class":892,"line":997},[890,2345,1258],{"class":1020},[890,2347,1224],{"class":1212},[890,2349,1250],{"class":1208},[890,2351,1265],{"class":913},[890,2353,2354],{"class":892,"line":1039},[890,2355,1042],{"class":896},[890,2357,2358],{"class":892,"line":1272},[890,2359,1275],{"emptyLinePlaceholder":8},[890,2361,2362,2364,2366,2368],{"class":892,"line":1278},[890,2363,1205],{"class":1010},[890,2365,1283],{"class":1208},[890,2367,1213],{"class":1212},[890,2369,1216],{"class":896},[890,2371,2372,2374,2376],{"class":892,"line":1290},[890,2373,1221],{"class":1020},[890,2375,1224],{"class":1212},[890,2377,1297],{"class":1208},[890,2379,2380,2382,2384],{"class":892,"line":1300},[890,2381,1303],{"class":1020},[890,2383,1224],{"class":1212},[890,2385,1308],{"class":1208},[890,2387,2388,2390,2392],{"class":892,"line":1311},[890,2389,1314],{"class":1020},[890,2391,1224],{"class":1212},[890,2393,1308],{"class":1208},[890,2395,2396],{"class":892,"line":1321},[890,2397,1042],{"class":896},[866,2399],{},[869,2401,1329],{"id":1328},[848,2403,1332,2404,1336],{},[876,2405,1335],{},[881,2407,2408],{"className":883,"code":1339,"filename":1340,"language":885,"meta":886,"style":886},[876,2409,2410,2432,2448,2452,2474,2492,2496,2532,2558,2586,2590,2594,2624,2628,2644,2672,2676,2680,2684,2704,2732,2736,2762],{"__ignoreMap":886},[890,2411,2412,2414,2416,2418,2420,2422,2424,2426,2428,2430],{"class":892,"line":893},[890,2413,1348],{"class":1347},[890,2415,1351],{"class":1347},[890,2417,1355],{"class":1354},[890,2419,1358],{"class":896},[890,2421,1361],{"class":1010},[890,2423,1364],{"class":896},[890,2425,1367],{"class":1003},[890,2427,1007],{"class":896},[890,2429,1011],{"class":1010},[890,2431,1216],{"class":896},[890,2433,2434,2436,2438,2440,2442,2444,2446],{"class":892,"line":900},[890,2435,1378],{"class":1347},[890,2437,1381],{"class":1354},[890,2439,1358],{"class":896},[890,2441,907],{"class":906},[890,2443,1388],{"class":896},[890,2445,1367],{"class":1020},[890,2447,1393],{"class":896},[890,2449,2450],{"class":892,"line":917},[890,2451,1275],{"emptyLinePlaceholder":8},[890,2453,2454,2456,2458,2460,2462,2464,2466,2468,2470,2472],{"class":892,"line":955},[890,2455,1402],{"class":1010},[890,2457,1405],{"class":896},[890,2459,1027],{"class":1408},[890,2461,1411],{"class":896},[890,2463,1414],{"class":1212},[890,2465,1417],{"class":1020},[890,2467,1024],{"class":896},[890,2469,1422],{"class":1020},[890,2471,1024],{"class":896},[890,2473,1427],{"class":1020},[890,2475,2476,2478,2480,2482,2484,2486,2488,2490],{"class":892,"line":997},[890,2477,1402],{"class":1010},[890,2479,1434],{"class":1408},[890,2481,1213],{"class":1212},[890,2483,1439],{"class":1347},[890,2485,1442],{"class":1354},[890,2487,1358],{"class":896},[890,2489,1367],{"class":1020},[890,2491,1393],{"class":896},[890,2493,2494],{"class":892,"line":1039},[890,2495,1275],{"emptyLinePlaceholder":8},[890,2497,2498,2500,2502,2504,2506,2508,2510,2512,2514,2516,2518,2520,2522,2524,2526,2528,2530],{"class":892,"line":1272},[890,2499,1402],{"class":1010},[890,2501,1459],{"class":1408},[890,2503,1213],{"class":1212},[890,2505,1434],{"class":1020},[890,2507,1466],{"class":896},[890,2509,1469],{"class":1354},[890,2511,1358],{"class":896},[890,2513,1474],{"class":1003},[890,2515,1477],{"class":1010},[890,2517,1480],{"class":1020},[890,2519,1024],{"class":896},[890,2521,1485],{"class":1020},[890,2523,1488],{"class":1212},[890,2525,1491],{"class":923},[890,2527,1494],{"class":927},[890,2529,924],{"class":923},[890,2531,1393],{"class":896},[890,2533,2534,2536,2538,2540,2542,2544,2546,2548,2550,2552,2554,2556],{"class":892,"line":1278},[890,2535,1503],{"class":1347},[890,2537,1364],{"class":896},[890,2539,1508],{"class":1212},[890,2541,1511],{"class":1020},[890,2543,1466],{"class":896},[890,2545,1516],{"class":1020},[890,2547,1519],{"class":1212},[890,2549,1522],{"class":1212},[890,2551,1511],{"class":1020},[890,2553,1024],{"class":896},[890,2555,1529],{"class":1020},[890,2557,1532],{"class":896},[890,2559,2560,2562,2564,2566,2568,2570,2572,2574,2576,2578,2580,2582,2584],{"class":892,"line":1290},[890,2561,1537],{"class":1347},[890,2563,1540],{"class":1354},[890,2565,1543],{"class":896},[890,2567,1546],{"class":1020},[890,2569,1224],{"class":1549},[890,2571,1552],{"class":906},[890,2573,933],{"class":896},[890,2575,1557],{"class":1020},[890,2577,1224],{"class":1549},[890,2579,1491],{"class":923},[890,2581,1564],{"class":927},[890,2583,924],{"class":923},[890,2585,1569],{"class":896},[890,2587,2588],{"class":892,"line":1300},[890,2589,1574],{"class":896},[890,2591,2592],{"class":892,"line":1311},[890,2593,1275],{"emptyLinePlaceholder":8},[890,2595,2596,2598,2600,2602,2604,2606,2608,2610,2612,2614,2616,2618,2620,2622],{"class":892,"line":1321},[890,2597,1402],{"class":1010},[890,2599,1585],{"class":1408},[890,2601,1213],{"class":1212},[890,2603,1439],{"class":1347},[890,2605,1592],{"class":1354},[890,2607,1358],{"class":896},[890,2609,1511],{"class":1020},[890,2611,1024],{"class":896},[890,2613,1516],{"class":1020},[890,2615,933],{"class":896},[890,2617,1511],{"class":1020},[890,2619,1024],{"class":896},[890,2621,1529],{"class":1020},[890,2623,1393],{"class":896},[890,2625,2626],{"class":892,"line":1613},[890,2627,1275],{"emptyLinePlaceholder":8},[890,2629,2630,2632,2634,2636,2638,2640,2642],{"class":892,"line":1618},[890,2631,1503],{"class":1347},[890,2633,1364],{"class":896},[890,2635,1508],{"class":1212},[890,2637,1627],{"class":1020},[890,2639,1024],{"class":896},[890,2641,1632],{"class":1020},[890,2643,1532],{"class":896},[890,2645,2646,2648,2650,2652,2654,2656,2658,2660,2662,2664,2666,2668,2670],{"class":892,"line":1637},[890,2647,1537],{"class":1347},[890,2649,1540],{"class":1354},[890,2651,1543],{"class":896},[890,2653,1546],{"class":1020},[890,2655,1224],{"class":1549},[890,2657,1552],{"class":906},[890,2659,933],{"class":896},[890,2661,1557],{"class":1020},[890,2663,1224],{"class":1549},[890,2665,1585],{"class":1020},[890,2667,1024],{"class":896},[890,2669,1662],{"class":1020},[890,2671,1569],{"class":896},[890,2673,2674],{"class":892,"line":1667},[890,2675,1574],{"class":896},[890,2677,2678],{"class":892,"line":1672},[890,2679,1275],{"emptyLinePlaceholder":8},[890,2681,2682],{"class":892,"line":1677},[890,2683,1680],{"class":913},[890,2685,2686,2688,2690,2692,2694,2696,2698,2700,2702],{"class":892,"line":1683},[890,2687,1402],{"class":1010},[890,2689,1688],{"class":1408},[890,2691,1213],{"class":1212},[890,2693,1693],{"class":1354},[890,2695,1358],{"class":896},[890,2697,924],{"class":923},[890,2699,1700],{"class":927},[890,2701,924],{"class":923},[890,2703,1393],{"class":896},[890,2705,2706,2708,2710,2712,2714,2716,2718,2720,2722,2724,2726,2728,2730],{"class":892,"line":1707},[890,2707,1378],{"class":1347},[890,2709,1688],{"class":1020},[890,2711,1024],{"class":896},[890,2713,1716],{"class":1354},[890,2715,1358],{"class":896},[890,2717,1627],{"class":1020},[890,2719,1024],{"class":896},[890,2721,1079],{"class":1020},[890,2723,933],{"class":896},[890,2725,1627],{"class":1020},[890,2727,1024],{"class":896},[890,2729,1733],{"class":1020},[890,2731,1393],{"class":896},[890,2733,2734],{"class":892,"line":1738},[890,2735,1275],{"emptyLinePlaceholder":8},[890,2737,2738,2740,2742,2744,2746,2748,2750,2752,2754,2756,2758,2760],{"class":892,"line":1743},[890,2739,1746],{"class":1347},[890,2741,1405],{"class":896},[890,2743,1632],{"class":1020},[890,2745,1224],{"class":1549},[890,2747,1756],{"class":1755},[890,2749,933],{"class":896},[890,2751,1079],{"class":1020},[890,2753,1224],{"class":1549},[890,2755,1585],{"class":1020},[890,2757,1024],{"class":896},[890,2759,1079],{"class":1020},[890,2761,1771],{"class":896},[890,2763,2764],{"class":892,"line":1774},[890,2765,1777],{"class":896},[866,2767],{},[869,2769,1783],{"id":1782},[848,2771,2772,1789,2774,1793],{},[876,2773,1788],{},[876,2775,1792],{},[881,2777,2778],{"className":883,"code":1796,"language":885,"meta":886,"style":886},[876,2779,2780,2804,2808,2812,2836],{"__ignoreMap":886},[890,2781,2782,2784,2786,2788,2790,2792,2794,2796,2798,2800,2802],{"class":892,"line":893},[890,2783,1803],{"class":1010},[890,2785,1806],{"class":1408},[890,2787,1213],{"class":1212},[890,2789,1811],{"class":1354},[890,2791,1358],{"class":896},[890,2793,924],{"class":923},[890,2795,1818],{"class":927},[890,2797,924],{"class":923},[890,2799,933],{"class":896},[890,2801,1825],{"class":906},[890,2803,1393],{"class":896},[890,2805,2806],{"class":892,"line":900},[890,2807,1832],{"class":913},[890,2809,2810],{"class":892,"line":917},[890,2811,1275],{"emptyLinePlaceholder":8},[890,2813,2814,2816,2818,2820,2822,2824,2826,2828,2830,2832,2834],{"class":892,"line":955},[890,2815,1803],{"class":1010},[890,2817,1843],{"class":1408},[890,2819,1213],{"class":1212},[890,2821,1811],{"class":1354},[890,2823,1358],{"class":896},[890,2825,924],{"class":923},[890,2827,1854],{"class":927},[890,2829,924],{"class":923},[890,2831,933],{"class":896},[890,2833,1825],{"class":906},[890,2835,1393],{"class":896},[890,2837,2838],{"class":892,"line":997},[890,2839,1867],{"class":913},[866,2841],{},[869,2843,1873],{"id":1872},[848,2845,874,2846,1879,2848,1885],{},[876,2847,1878],{},[852,2849,1884],{"href":1882,"rel":2850},[856],[881,2852,2853],{"className":883,"code":1888,"language":885,"meta":886,"style":886},[876,2854,2855,2873,2887,2891,2895,2923,2927,2947,2953,2957],{"__ignoreMap":886},[890,2856,2857,2859,2861,2863,2865,2867,2869,2871],{"class":892,"line":893},[890,2858,1895],{"class":1347},[890,2860,1405],{"class":896},[890,2862,1900],{"class":1020},[890,2864,1411],{"class":896},[890,2866,1905],{"class":1347},[890,2868,1491],{"class":923},[890,2870,1884],{"class":927},[890,2872,1912],{"class":923},[890,2874,2875,2877,2879,2881,2883,2885],{"class":892,"line":900},[890,2876,1895],{"class":1347},[890,2878,1919],{"class":1020},[890,2880,1922],{"class":1347},[890,2882,1491],{"class":923},[890,2884,1927],{"class":927},[890,2886,1912],{"class":923},[890,2888,2889],{"class":892,"line":917},[890,2890,1275],{"emptyLinePlaceholder":8},[890,2892,2893],{"class":892,"line":955},[890,2894,1938],{"class":896},[890,2896,2897,2899,2901,2903,2905,2907,2909,2911,2913,2915,2917,2919,2921],{"class":892,"line":997},[890,2898,1943],{"class":896},[890,2900,1900],{"class":1354},[890,2902,1543],{"class":896},[890,2904,1950],{"class":1020},[890,2906,1224],{"class":1549},[890,2908,1919],{"class":1354},[890,2910,1543],{"class":896},[890,2912,1959],{"class":1020},[890,2914,1224],{"class":1549},[890,2916,1491],{"class":923},[890,2918,1966],{"class":927},[890,2920,924],{"class":923},[890,2922,1971],{"class":896},[890,2924,2925],{"class":892,"line":1039},[890,2926,1976],{"class":896},[890,2928,2929,2931,2933,2935,2937,2939,2941,2943,2945],{"class":892,"line":1272},[890,2930,1981],{"class":896},[890,2932,1984],{"class":906},[890,2934,1987],{"class":1212},[890,2936,1990],{"class":906},[890,2938,1987],{"class":1212},[890,2940,1995],{"class":906},[890,2942,1987],{"class":1212},[890,2944,2000],{"class":906},[890,2946,2003],{"class":896},[890,2948,2949,2951],{"class":892,"line":1278},[890,2950,2008],{"class":896},[890,2952,2011],{"class":906},[890,2954,2955],{"class":892,"line":1290},[890,2956,1574],{"class":896},[890,2958,2959],{"class":892,"line":1300},[890,2960,1042],{"class":896},[848,2962,874,2963,2025,2965,2029,2967,2032],{},[876,2964,2024],{},[876,2966,2028],{},[876,2968,1716],{},[848,2970,2035,2971,2040,2973,2044,2975,2047,2977,2050,2979,2053,2981,1024],{},[852,2972,2039],{"href":2038},[876,2974,2043],{},[876,2976,1099],{},[876,2978,1632],{},[876,2980,1662],{},[852,2982,214],{"href":2056},[2058,2984,2060],{},{"title":886,"searchDepth":900,"depth":900,"links":2986},[2987,2988,2989,2990,2991],{"id":871,"depth":900,"text":192},{"id":1096,"depth":900,"text":1099},{"id":1328,"depth":900,"text":1329},{"id":1782,"depth":900,"text":1783},{"id":1872,"depth":900,"text":1873},{},{"title":184,"description":2068},1780436292681]