[{"data":1,"prerenderedAt":4618},["ShallowReactive",2],{"navLinks":3,"sidebar_docs_navigation_\u002Fdocs\u002Fbot-detection":64,"navigation":191,"navLinks_footer":816,"\u002Fdocs\u002Fbot-detection\u002Fgetting-started_page":829,"\u002Fdocs\u002Fbot-detection\u002Fgetting-started_surround":2921,"\u002Fdocs\u002Fbot-detection\u002Fgetting-started":2924},{"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":70,"path":35,"stem":71,"children":72},"Bot Detector","docs\u002Fbot-detection\u002Findex",[73,74,77,81,85,106,180,183,187],{"title":70,"path":35,"stem":71},{"title":14,"path":75,"stem":76},"\u002Fdocs\u002Fbot-detection\u002Fgetting-started","docs\u002Fbot-detection\u002F00.getting-started",{"title":78,"path":79,"stem":80},"CLI","\u002Fdocs\u002Fbot-detection\u002Fcli","docs\u002Fbot-detection\u002F01.cli",{"title":82,"path":83,"stem":84},"Data Sources","\u002Fdocs\u002Fbot-detection\u002Fdata-sources","docs\u002Fbot-detection\u002F02.data-sources",{"title":86,"path":87,"stem":88,"children":89,"page":53},"Guides","\u002Fdocs\u002Fbot-detection\u002Fguides","docs\u002Fbot-detection\u002F03.guides",[90,94,98,102],{"title":91,"path":92,"stem":93},"Custom Checkers","\u002Fdocs\u002Fbot-detection\u002Fguides\u002Fcustom","docs\u002Fbot-detection\u002F03.guides\u002FCUSTOM",{"title":95,"path":96,"stem":97},"Scheduling Database Generation","\u002Fdocs\u002Fbot-detection\u002Fguides\u002Fgenerate","docs\u002Fbot-detection\u002F03.guides\u002FGENERATE",{"title":99,"path":100,"stem":101},"Logging","\u002Fdocs\u002Fbot-detection\u002Fguides\u002Flogging","docs\u002Fbot-detection\u002F03.guides\u002FLOGGING",{"title":103,"path":104,"stem":105},"Score Modes and Reputation Healing","\u002Fdocs\u002Fbot-detection\u002Fguides\u002Fscore","docs\u002Fbot-detection\u002F03.guides\u002FSCORE",{"title":107,"path":108,"stem":109,"children":110},"Checkers","\u002Fdocs\u002Fbot-detection\u002Fcheckers","docs\u002Fbot-detection\u002F04.checkers\u002Findex",[111,112,116,120,124,128,132,136,140,144,148,152,156,160,164,168,172,176],{"title":107,"path":108,"stem":109},{"title":113,"path":114,"stem":115},"IP Validation","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fip-validation","docs\u002Fbot-detection\u002F04.checkers\u002F01.ip-validation",{"title":117,"path":118,"stem":119},"Good \u002F Bad Bot Verification","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fgood-bots","docs\u002Fbot-detection\u002F04.checkers\u002F02.good-bots",{"title":121,"path":122,"stem":123},"Browser & Device Fingerprint","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fbrowser-device","docs\u002Fbot-detection\u002F04.checkers\u002F03.browser-device",{"title":125,"path":126,"stem":127},"Locale Map","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Flocale-map","docs\u002Fbot-detection\u002F04.checkers\u002F04.locale-map",{"title":129,"path":130,"stem":131},"Known Threats","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fknown-threats","docs\u002Fbot-detection\u002F04.checkers\u002F05.known-threats",{"title":133,"path":134,"stem":135},"ASN Classification","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fasn-classification","docs\u002Fbot-detection\u002F04.checkers\u002F06.asn-classification",{"title":137,"path":138,"stem":139},"Tor Analysis","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Ftor-analysis","docs\u002Fbot-detection\u002F04.checkers\u002F07.tor-analysis",{"title":141,"path":142,"stem":143},"Timezone Consistency","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Ftimezone-consistency","docs\u002Fbot-detection\u002F04.checkers\u002F08.timezone-consistency",{"title":145,"path":146,"stem":147},"Honeypot","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fhoneypot","docs\u002Fbot-detection\u002F04.checkers\u002F09.honeypot",{"title":149,"path":150,"stem":151},"Known Bad IPs","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fknown-bad-ips","docs\u002Fbot-detection\u002F04.checkers\u002F10.known-bad-ips",{"title":153,"path":154,"stem":155},"Behavior Rate","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fbehavior-rate","docs\u002Fbot-detection\u002F04.checkers\u002F11.behavior-rate",{"title":157,"path":158,"stem":159},"Proxy \u002F ISP \u002F Cookie","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fproxy-isp-cookies","docs\u002Fbot-detection\u002F04.checkers\u002F12.proxy-isp-cookies",{"title":161,"path":162,"stem":163},"Session Coherence","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fsession-coherence","docs\u002Fbot-detection\u002F04.checkers\u002F13.session-coherence",{"title":165,"path":166,"stem":167},"Velocity Fingerprint","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fvelocity-fingerprint","docs\u002Fbot-detection\u002F04.checkers\u002F14.velocity-fingerprint",{"title":169,"path":170,"stem":171},"UA & Header Analysis","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fua-header","docs\u002Fbot-detection\u002F04.checkers\u002F15.ua-header",{"title":173,"path":174,"stem":175},"Geolocation","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fgeolocation","docs\u002Fbot-detection\u002F04.checkers\u002F16.geolocation",{"title":177,"path":178,"stem":179},"Known Bad User-Agents","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fknown-bad-ua","docs\u002Fbot-detection\u002F04.checkers\u002F17.known-bad-ua",{"title":38,"path":181,"stem":182},"\u002Fdocs\u002Fbot-detection\u002Fsecurity","docs\u002Fbot-detection\u002F04.security",{"title":184,"path":185,"stem":186},"API Reference","\u002Fdocs\u002Fbot-detection\u002Fapi","docs\u002Fbot-detection\u002F05.api",{"title":188,"path":189,"stem":190},"Configuration","\u002Fdocs\u002Fbot-detection\u002Fconfiguration","docs\u002Fbot-detection\u002F06.configuration",[192],{"title":9,"path":66,"stem":67,"children":193,"page":53},[194,338,373,378,556,623],{"title":20,"path":22,"stem":195,"children":196},"docs\u002Fauth-h3client\u002Findex",[197,198,207,243,269,291,294,314,317],{"title":20,"path":22,"stem":195},{"title":14,"path":199,"stem":200,"children":201},"\u002Fdocs\u002Fauth-h3client\u002Fgetting-started","docs\u002Fauth-h3client\u002F00.getting-started\u002Findex",[202,203],{"title":14,"path":199,"stem":200},{"title":204,"path":205,"stem":206},"Nuxt Module","\u002Fdocs\u002Fauth-h3client\u002Fgetting-started\u002Fnuxt","docs\u002Fauth-h3client\u002F00.getting-started\u002F00.nuxt",{"title":208,"path":209,"stem":210,"children":211},"Essentials","\u002Fdocs\u002Fauth-h3client\u002Fessentials","docs\u002Fauth-h3client\u002F01.essentials\u002Findex",[212,213,217,221,225,229,233,236,240],{"title":208,"path":209,"stem":210},{"title":214,"path":215,"stem":216},"Session Management","\u002Fdocs\u002Fauth-h3client\u002Fessentials\u002Fsession","docs\u002Fauth-h3client\u002F01.essentials\u002F00.session",{"title":218,"path":219,"stem":220},"Route Protection","\u002Fdocs\u002Fauth-h3client\u002Fessentials\u002Froute-protection","docs\u002Fauth-h3client\u002F01.essentials\u002F01.route-protection",{"title":222,"path":223,"stem":224},"CSRF Protection","\u002Fdocs\u002Fauth-h3client\u002Fessentials\u002Fcsrf","docs\u002Fauth-h3client\u002F01.essentials\u002F02.csrf",{"title":226,"path":227,"stem":228},"Auth Flows","\u002Fdocs\u002Fauth-h3client\u002Fessentials\u002Fauth-flows","docs\u002Fauth-h3client\u002F01.essentials\u002F03.auth-flows",{"title":230,"path":231,"stem":232},"OAuth and OIDC","\u002Fdocs\u002Fauth-h3client\u002Fessentials\u002Foauth","docs\u002Fauth-h3client\u002F01.essentials\u002F04.oauth",{"title":33,"path":234,"stem":235},"\u002Fdocs\u002Fauth-h3client\u002Fessentials\u002Fbot-detection","docs\u002Fauth-h3client\u002F01.essentials\u002F05.bot-detection",{"title":237,"path":238,"stem":239},"Cookies","\u002Fdocs\u002Fauth-h3client\u002Fessentials\u002Fcookies","docs\u002Fauth-h3client\u002F01.essentials\u002F06.cookies",{"title":99,"path":241,"stem":242},"\u002Fdocs\u002Fauth-h3client\u002Fessentials\u002Flogging","docs\u002Fauth-h3client\u002F01.essentials\u002F07.logging",{"title":244,"path":245,"stem":246,"children":247},"MFA","\u002Fdocs\u002Fauth-h3client\u002Fmfa","docs\u002Fauth-h3client\u002F02.mfa\u002Findex",[248,249,253,257,261,265],{"title":244,"path":245,"stem":246},{"title":250,"path":251,"stem":252},"Built-in MFA","\u002Fdocs\u002Fauth-h3client\u002Fmfa\u002Fbuilt-in-flow","docs\u002Fauth-h3client\u002F02.mfa\u002F01.built-in-flow",{"title":254,"path":255,"stem":256},"Password Reset","\u002Fdocs\u002Fauth-h3client\u002Fmfa\u002Fpassword-reset","docs\u002Fauth-h3client\u002F02.mfa\u002F02.password-reset",{"title":258,"path":259,"stem":260},"Email Change","\u002Fdocs\u002Fauth-h3client\u002Fmfa\u002Femail-change","docs\u002Fauth-h3client\u002F02.mfa\u002F03.email-change",{"title":262,"path":263,"stem":264},"Custom MFA Flow","\u002Fdocs\u002Fauth-h3client\u002Fmfa\u002Fcustom-flow","docs\u002Fauth-h3client\u002F02.mfa\u002F04.custom-flow",{"title":266,"path":267,"stem":268},"Client-Side MFA","\u002Fdocs\u002Fauth-h3client\u002Fmfa\u002Fclient-side","docs\u002Fauth-h3client\u002F02.mfa\u002F05.client-side",{"title":270,"path":271,"stem":272,"children":273},"Client-side","\u002Fdocs\u002Fauth-h3client\u002Fclient","docs\u002Fauth-h3client\u002F03.client\u002Findex",[274,275,279,283,287],{"title":270,"path":271,"stem":272},{"title":276,"path":277,"stem":278},"useAuthData","\u002Fdocs\u002Fauth-h3client\u002Fclient\u002Fuse-auth-data","docs\u002Fauth-h3client\u002F03.client\u002F00.use-auth-data",{"title":280,"path":281,"stem":282},"useMagicLink","\u002Fdocs\u002Fauth-h3client\u002Fclient\u002Fuse-magic-link","docs\u002Fauth-h3client\u002F03.client\u002F01.use-magic-link",{"title":284,"path":285,"stem":286},"executeRequest","\u002Fdocs\u002Fauth-h3client\u002Fclient\u002Fexecute-request","docs\u002Fauth-h3client\u002F03.client\u002F02.execute-request",{"title":288,"path":289,"stem":290},"getCsrfToken","\u002Fdocs\u002Fauth-h3client\u002Fclient\u002Fget-csrf-token","docs\u002Fauth-h3client\u002F03.client\u002F03.get-csrf-token",{"title":38,"path":292,"stem":293},"\u002Fdocs\u002Fauth-h3client\u002Fsecurity","docs\u002Fauth-h3client\u002F04.security",{"title":86,"path":295,"stem":296,"children":297,"page":53},"\u002Fdocs\u002Fauth-h3client\u002Fguides","docs\u002Fauth-h3client\u002F05.guides",[298,302,306,310],{"title":299,"path":300,"stem":301},"H3 and Nitro Setup","\u002Fdocs\u002Fauth-h3client\u002Fguides\u002Fh3-nitro","docs\u002Fauth-h3client\u002F05.guides\u002F00.h3-nitro",{"title":303,"path":304,"stem":305},"HMAC Inter-service Auth","\u002Fdocs\u002Fauth-h3client\u002Fguides\u002Fhmac","docs\u002Fauth-h3client\u002F05.guides\u002Fhmac",{"title":307,"path":308,"stem":309},"Image Upload","\u002Fdocs\u002Fauth-h3client\u002Fguides\u002Fimage-upload","docs\u002Fauth-h3client\u002F05.guides\u002Fimage-upload",{"title":311,"path":312,"stem":313},"mTLS Configuration","\u002Fdocs\u002Fauth-h3client\u002Fguides\u002Fmtls","docs\u002Fauth-h3client\u002F05.guides\u002Fmtls",{"title":188,"path":315,"stem":316},"\u002Fdocs\u002Fauth-h3client\u002Fconfiguration","docs\u002Fauth-h3client\u002F06.configuration",{"title":184,"path":318,"stem":319,"children":320},"\u002Fdocs\u002Fauth-h3client\u002Fapi","docs\u002Fauth-h3client\u002F07.api\u002Findex",[321,322,326,330,334],{"title":184,"path":318,"stem":319},{"title":323,"path":324,"stem":325},"Routes Reference","\u002Fdocs\u002Fauth-h3client\u002Fapi\u002Fcontrollers","docs\u002Fauth-h3client\u002F07.api\u002F00.controllers",{"title":327,"path":328,"stem":329},"Middleware Reference","\u002Fdocs\u002Fauth-h3client\u002Fapi\u002Fmiddleware","docs\u002Fauth-h3client\u002F07.api\u002F01.middleware",{"title":331,"path":332,"stem":333},"Client-side Reference","\u002Fdocs\u002Fauth-h3client\u002Fapi\u002Fcomposables","docs\u002Fauth-h3client\u002F07.api\u002F02.composables",{"title":335,"path":336,"stem":337},"Utilities","\u002Fdocs\u002Fauth-h3client\u002Fapi\u002Futilities","docs\u002Fauth-h3client\u002F07.api\u002F03.utilities",{"title":70,"path":35,"stem":71,"children":339},[340,341,342,343,344,350,370,371,372],{"title":70,"path":35,"stem":71},{"title":14,"path":75,"stem":76},{"title":78,"path":79,"stem":80},{"title":82,"path":83,"stem":84},{"title":86,"path":87,"stem":88,"children":345,"page":53},[346,347,348,349],{"title":91,"path":92,"stem":93},{"title":95,"path":96,"stem":97},{"title":99,"path":100,"stem":101},{"title":103,"path":104,"stem":105},{"title":107,"path":108,"stem":109,"children":351},[352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369],{"title":107,"path":108,"stem":109},{"title":113,"path":114,"stem":115},{"title":117,"path":118,"stem":119},{"title":121,"path":122,"stem":123},{"title":125,"path":126,"stem":127},{"title":129,"path":130,"stem":131},{"title":133,"path":134,"stem":135},{"title":137,"path":138,"stem":139},{"title":141,"path":142,"stem":143},{"title":145,"path":146,"stem":147},{"title":149,"path":150,"stem":151},{"title":153,"path":154,"stem":155},{"title":157,"path":158,"stem":159},{"title":161,"path":162,"stem":163},{"title":165,"path":166,"stem":167},{"title":169,"path":170,"stem":171},{"title":173,"path":174,"stem":175},{"title":177,"path":178,"stem":179},{"title":38,"path":181,"stem":182},{"title":184,"path":185,"stem":186},{"title":188,"path":189,"stem":190},{"title":374,"path":11,"stem":375,"children":376},"Introduction","docs\u002Fgetting-started\u002Findex",[377],{"title":374,"path":11,"stem":375},{"title":27,"path":29,"stem":379,"children":380},"docs\u002Fiam\u002Findex",[381,382,385,520,523,539,542],{"title":27,"path":29,"stem":379},{"title":14,"path":383,"stem":384},"\u002Fdocs\u002Fiam\u002Fgetting-started","docs\u002Fiam\u002F00.getting-started",{"title":208,"path":386,"stem":387,"children":388},"\u002Fdocs\u002Fiam\u002Fessentials","docs\u002Fiam\u002F01.essentials\u002Findex",[389,390,394,398,402,406,410,414,418,422,426,430,433,437,441,445,449,452,456,460,463,467,470],{"title":208,"path":386,"stem":387},{"title":391,"path":392,"stem":393},"Tokens","\u002Fdocs\u002Fiam\u002Fessentials\u002Ftokens","docs\u002Fiam\u002F01.essentials\u002F00.tokens",{"title":395,"path":396,"stem":397},"Access Tokens","\u002Fdocs\u002Fiam\u002Fessentials\u002Faccess-tokens","docs\u002Fiam\u002F01.essentials\u002F01.access-tokens",{"title":399,"path":400,"stem":401},"Refresh Tokens","\u002Fdocs\u002Fiam\u002Fessentials\u002Frefresh-tokens","docs\u002Fiam\u002F01.essentials\u002F02.refresh-tokens",{"title":403,"path":404,"stem":405},"Anomaly Detection","\u002Fdocs\u002Fiam\u002Fessentials\u002Fanomalies","docs\u002Fiam\u002F01.essentials\u002F03.anomalies",{"title":407,"path":408,"stem":409},"Signup","\u002Fdocs\u002Fiam\u002Fessentials\u002Fsignup","docs\u002Fiam\u002F01.essentials\u002F04.signup",{"title":411,"path":412,"stem":413},"Login","\u002Fdocs\u002Fiam\u002Fessentials\u002Flogin","docs\u002Fiam\u002F01.essentials\u002F05.login",{"title":415,"path":416,"stem":417},"Logout","\u002Fdocs\u002Fiam\u002Fessentials\u002Flogout","docs\u002Fiam\u002F01.essentials\u002F06.logout",{"title":419,"path":420,"stem":421},"OAuth","\u002Fdocs\u002Fiam\u002Fessentials\u002Foauth","docs\u002Fiam\u002F01.essentials\u002F07.oauth",{"title":423,"path":424,"stem":425},"Magic Links","\u002Fdocs\u002Fiam\u002Fessentials\u002Fmagic-links","docs\u002Fiam\u002F01.essentials\u002F08.magic-links",{"title":427,"path":428,"stem":429},"Emails","\u002Fdocs\u002Fiam\u002Fessentials\u002Femails","docs\u002Fiam\u002F01.essentials\u002F09.emails",{"title":244,"path":431,"stem":432},"\u002Fdocs\u002Fiam\u002Fessentials\u002Fmfa","docs\u002Fiam\u002F01.essentials\u002F10.mfa",{"title":434,"path":435,"stem":436},"Fingerprinting","\u002Fdocs\u002Fiam\u002Fessentials\u002Ffingerprinting","docs\u002Fiam\u002F01.essentials\u002F11.fingerprinting",{"title":438,"path":439,"stem":440},"Backend for Frontend","\u002Fdocs\u002Fiam\u002Fessentials\u002Fbff","docs\u002Fiam\u002F01.essentials\u002F12.bff",{"title":442,"path":443,"stem":444},"HMAC Authentication","\u002Fdocs\u002Fiam\u002Fessentials\u002Fhmac","docs\u002Fiam\u002F01.essentials\u002F13.hmac",{"title":446,"path":447,"stem":448},"XSS Protection","\u002Fdocs\u002Fiam\u002Fessentials\u002Fxss","docs\u002Fiam\u002F01.essentials\u002F14.xss",{"title":99,"path":450,"stem":451},"\u002Fdocs\u002Fiam\u002Fessentials\u002Flogging","docs\u002Fiam\u002F01.essentials\u002F15.logging",{"title":453,"path":454,"stem":455},"Rate Limiting","\u002Fdocs\u002Fiam\u002Fessentials\u002Frate-limiting","docs\u002Fiam\u002F01.essentials\u002F16.rate-limiting",{"title":457,"path":458,"stem":459},"Database","\u002Fdocs\u002Fiam\u002Fessentials\u002Fdatabase","docs\u002Fiam\u002F01.essentials\u002F17.database",{"title":237,"path":461,"stem":462},"\u002Fdocs\u002Fiam\u002Fessentials\u002Fcookies","docs\u002Fiam\u002F01.essentials\u002F18.cookies",{"title":464,"path":465,"stem":466},"Service Startup","\u002Fdocs\u002Fiam\u002Fessentials\u002Fservice","docs\u002Fiam\u002F01.essentials\u002F19.service",{"title":254,"path":468,"stem":469},"\u002Fdocs\u002Fiam\u002Fessentials\u002Fpassword-reset","docs\u002Fiam\u002F01.essentials\u002F20.password-reset",{"title":471,"path":472,"stem":473,"children":474},"API Tokens","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi","docs\u002Fiam\u002F01.essentials\u002F21.api\u002Findex",[475,476,480,484,514,517],{"title":471,"path":472,"stem":473},{"title":477,"path":478,"stem":479},"Creating Tokens","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fcreation","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F00.creation",{"title":481,"path":482,"stem":483},"Verifying Tokens","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fverification","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F01.verification",{"title":485,"path":486,"stem":487,"children":488},"Manage Tokens","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fmanagement","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F02.management\u002Findex",[489,490,494,498,502,506,510],{"title":485,"path":486,"stem":487},{"title":491,"path":492,"stem":493},"Privileges","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fmanagement\u002Fprivilege","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F02.management\u002F00.privilege",{"title":495,"path":496,"stem":497},"Revocation","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fmanagement\u002Frevocation","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F02.management\u002F01.revocation",{"title":499,"path":500,"stem":501},"Rotation","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fmanagement\u002Frotation","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F02.management\u002F02.rotation",{"title":503,"path":504,"stem":505},"IP Restriction","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fmanagement\u002Fip-updates","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F02.management\u002F03.ip-updates",{"title":507,"path":508,"stem":509},"Metadata","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fmanagement\u002Fmetadata","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F02.management\u002F04.metadata",{"title":511,"path":512,"stem":513},"Token Listing","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fmanagement\u002Flist","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F02.management\u002F05.list",{"title":453,"path":515,"stem":516},"\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Frate-limiting","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F03.rate-limiting",{"title":38,"path":518,"stem":519},"\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fsecurity","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F04.security",{"title":38,"path":521,"stem":522},"\u002Fdocs\u002Fiam\u002Fsecurity","docs\u002Fiam\u002F02.security",{"title":86,"path":524,"stem":525,"children":526,"page":53},"\u002Fdocs\u002Fiam\u002Fguides","docs\u002Fiam\u002F03.guides",[527,531,535],{"title":528,"path":529,"stem":530},"Deployment","\u002Fdocs\u002Fiam\u002Fguides\u002Fdeployment","docs\u002Fiam\u002F03.guides\u002Fdeployment",{"title":532,"path":533,"stem":534},"Operation Scripts","\u002Fdocs\u002Fiam\u002Fguides\u002Foperation-scripts","docs\u002Fiam\u002F03.guides\u002Foperation-scripts",{"title":536,"path":537,"stem":538},"Role-Based Access Control","\u002Fdocs\u002Fiam\u002Fguides\u002Frbac","docs\u002Fiam\u002F03.guides\u002Frbac",{"title":188,"path":540,"stem":541},"\u002Fdocs\u002Fiam\u002Fconfiguration","docs\u002Fiam\u002F04.configuration",{"title":543,"path":544,"stem":545,"children":546,"page":53},"Api","\u002Fdocs\u002Fiam\u002Fapi","docs\u002Fiam\u002F05.API",[547,550,553],{"title":184,"path":548,"stem":549},"\u002Fdocs\u002Fiam\u002Fapi\u002Fapi","docs\u002Fiam\u002F05.API\u002F00.api",{"title":327,"path":551,"stem":552},"\u002Fdocs\u002Fiam\u002Fapi\u002Fmiddlewares","docs\u002Fiam\u002F05.API\u002F02.middlewares",{"title":323,"path":554,"stem":555},"\u002Fdocs\u002Fiam\u002Fapi\u002Froutes","docs\u002Fiam\u002F05.API\u002F03.routes",{"title":40,"path":42,"stem":557,"children":558},"docs\u002Fshield-base\u002Findex",[559,560,563,567,608,612,616,620],{"title":40,"path":42,"stem":557},{"title":14,"path":561,"stem":562},"\u002Fdocs\u002Fshield-base\u002Fgetting-started","docs\u002Fshield-base\u002F00.getting-started",{"title":564,"path":565,"stem":566},"CLI Reference","\u002Fdocs\u002Fshield-base\u002Fcli","docs\u002Fshield-base\u002F01.cli",{"title":82,"path":568,"stem":569,"children":570},"\u002Fdocs\u002Fshield-base\u002Fdata-sources","docs\u002Fshield-base\u002F02.data-sources\u002Findex",[571,572,576,580,584,588,592,596,600,604],{"title":82,"path":568,"stem":569},{"title":573,"path":574,"stem":575},"BGP \u002F ASN","\u002Fdocs\u002Fshield-base\u002Fdata-sources\u002Fbgp","docs\u002Fshield-base\u002F02.data-sources\u002Fbgp",{"title":577,"path":578,"stem":579},"City Geolocation","\u002Fdocs\u002Fshield-base\u002Fdata-sources\u002Fcity","docs\u002Fshield-base\u002F02.data-sources\u002Fcity",{"title":581,"path":582,"stem":583},"Country Geolocation","\u002Fdocs\u002Fshield-base\u002Fdata-sources\u002Fcountry","docs\u002Fshield-base\u002F02.data-sources\u002Fcountry",{"title":585,"path":586,"stem":587},"Verified Crawlers","\u002Fdocs\u002Fshield-base\u002Fdata-sources\u002Fcrawlers","docs\u002Fshield-base\u002F02.data-sources\u002Fcrawlers",{"title":589,"path":590,"stem":591},"Disposable Emails","\u002Fdocs\u002Fshield-base\u002Fdata-sources\u002Femail","docs\u002Fshield-base\u002F02.data-sources\u002Femail",{"title":593,"path":594,"stem":595},"FireHOL Threat Intelligence","\u002Fdocs\u002Fshield-base\u002Fdata-sources\u002Ffirehol","docs\u002Fshield-base\u002F02.data-sources\u002Ffirehol",{"title":597,"path":598,"stem":599},"Proxy Detection","\u002Fdocs\u002Fshield-base\u002Fdata-sources\u002Fproxy","docs\u002Fshield-base\u002F02.data-sources\u002Fproxy",{"title":601,"path":602,"stem":603},"Tor Nodes","\u002Fdocs\u002Fshield-base\u002Fdata-sources\u002Ftor","docs\u002Fshield-base\u002F02.data-sources\u002Ftor",{"title":605,"path":606,"stem":607},"Suspicious User-Agents","\u002Fdocs\u002Fshield-base\u002Fdata-sources\u002Fuseragent","docs\u002Fshield-base\u002F02.data-sources\u002Fuseragent",{"title":609,"path":610,"stem":611},"Programmatic Usage","\u002Fdocs\u002Fshield-base\u002Fusage","docs\u002Fshield-base\u002F03.usage",{"title":613,"path":614,"stem":615},"Custom Data Sources","\u002Fdocs\u002Fshield-base\u002Fcustom-data-sources","docs\u002Fshield-base\u002F04.custom-data-sources",{"title":617,"path":618,"stem":619},"TypeScript Types","\u002Fdocs\u002Fshield-base\u002Ftypes","docs\u002Fshield-base\u002F05.types",{"title":184,"path":621,"stem":622},"\u002Fdocs\u002Fshield-base\u002Fapi","docs\u002Fshield-base\u002F06.api",{"title":335,"path":48,"stem":624,"children":625},"docs\u002Futils\u002Findex",[626,627,644,677,774],{"title":335,"path":48,"stem":624},{"title":628,"path":629,"stem":630,"children":631,"page":53},"Eslint","\u002Fdocs\u002Futils\u002Feslint","docs\u002Futils\u002Feslint",[632,636,640],{"title":633,"path":634,"stem":635},"React Config","\u002Fdocs\u002Futils\u002Feslint\u002Freact","docs\u002Futils\u002Feslint\u002Freact",{"title":637,"path":638,"stem":639},"TypeScript Config","\u002Fdocs\u002Futils\u002Feslint\u002Ftypescript","docs\u002Futils\u002Feslint\u002Ftypescript",{"title":641,"path":642,"stem":643},"Vue Config","\u002Fdocs\u002Futils\u002Feslint\u002Fvue","docs\u002Futils\u002Feslint\u002Fvue",{"title":645,"path":646,"stem":647,"children":648,"page":53},"Server","\u002Fdocs\u002Futils\u002Fserver","docs\u002Futils\u002Fserver",[649,653,657,661,665,669,673],{"title":650,"path":651,"stem":652},"Encryption","\u002Fdocs\u002Futils\u002Fserver\u002Fencryption","docs\u002Futils\u002Fserver\u002Fencryption",{"title":654,"path":655,"stem":656},"Path Resolver","\u002Fdocs\u002Futils\u002Fserver\u002Fpathresolver","docs\u002Futils\u002Fserver\u002FpathResolver",{"title":658,"path":659,"stem":660},"File Replacements","\u002Fdocs\u002Futils\u002Fserver\u002Freplace","docs\u002Futils\u002Fserver\u002Freplace",{"title":662,"path":663,"stem":664},"run","\u002Fdocs\u002Futils\u002Fserver\u002Frun","docs\u002Futils\u002Fserver\u002Frun",{"title":666,"path":667,"stem":668},"scheduleTask","\u002Fdocs\u002Futils\u002Fserver\u002Fscheduletask","docs\u002Futils\u002Fserver\u002FscheduleTask",{"title":670,"path":671,"stem":672},"spawnRun","\u002Fdocs\u002Futils\u002Fserver\u002Fspawnrun","docs\u002Futils\u002Fserver\u002FspawnRun",{"title":674,"path":675,"stem":676},"uploadCsv","\u002Fdocs\u002Futils\u002Fserver\u002Fuploadcsv","docs\u002Futils\u002Fserver\u002FuploadCsv",{"title":678,"path":679,"stem":680,"children":681,"page":53},"Shared","\u002Fdocs\u002Futils\u002Fshared","docs\u002Futils\u002Fshared",[682,686,690,694,698,702,706,710,714,718,722,726,730,734,738,742,746,750,754,758,762,766,770],{"title":683,"path":684,"stem":685},"BatchQueue","\u002Fdocs\u002Futils\u002Fshared\u002Fbatchqueue","docs\u002Futils\u002Fshared\u002FbatchQueue",{"title":687,"path":688,"stem":689},"capitalize","\u002Fdocs\u002Futils\u002Fshared\u002Fcapitalize","docs\u002Futils\u002Fshared\u002Fcapitalize",{"title":691,"path":692,"stem":693},"chunkProcess","\u002Fdocs\u002Futils\u002Fshared\u002Fchunkprocess","docs\u002Futils\u002Fshared\u002FchunkProcess",{"title":695,"path":696,"stem":697},"cleanObject","\u002Fdocs\u002Futils\u002Fshared\u002Fcleanobject","docs\u002Futils\u002Fshared\u002FcleanObject",{"title":699,"path":700,"stem":701},"createConfigManager","\u002Fdocs\u002Futils\u002Fshared\u002Fconfigurationdefiner","docs\u002Futils\u002Fshared\u002FconfigurationDefiner",{"title":703,"path":704,"stem":705},"debounce","\u002Fdocs\u002Futils\u002Fshared\u002Fdebounce","docs\u002Futils\u002Fshared\u002Fdebounce",{"title":707,"path":708,"stem":709},"ensureArray","\u002Fdocs\u002Futils\u002Fshared\u002Fensurearray","docs\u002Futils\u002Fshared\u002FensureArray",{"title":711,"path":712,"stem":713},"fetchWithRetry","\u002Fdocs\u002Futils\u002Fshared\u002Ffetchwithretry","docs\u002Futils\u002Fshared\u002FfetchWithRetry",{"title":715,"path":716,"stem":717},"filterEmptyValues","\u002Fdocs\u002Futils\u002Fshared\u002Ffilteremptyvalues","docs\u002Futils\u002Fshared\u002FfilterEmptyValues",{"title":719,"path":720,"stem":721},"findStringsInObject","\u002Fdocs\u002Futils\u002Fshared\u002Ffindobjectvalues","docs\u002Futils\u002Fshared\u002FfindObjectValues",{"title":723,"path":724,"stem":725},"fisherYatesShuffle","\u002Fdocs\u002Futils\u002Fshared\u002Ffisheryatesshuffle","docs\u002Futils\u002Fshared\u002FfisherYatesShuffle",{"title":727,"path":728,"stem":729},"getRandomImage","\u002Fdocs\u002Futils\u002Fshared\u002Fgetrandomimage","docs\u002Futils\u002Fshared\u002FgetRandomImage",{"title":731,"path":732,"stem":733},"isObjectHasValues","\u002Fdocs\u002Futils\u002Fshared\u002Fisobjecthasvalues","docs\u002Futils\u002Fshared\u002FisObjectHasValues",{"title":735,"path":736,"stem":737},"isAsyncOrPromise","\u002Fdocs\u002Futils\u002Fshared\u002Fispromise","docs\u002Futils\u002Fshared\u002FisPromise",{"title":739,"path":740,"stem":741},"MiniCache","\u002Fdocs\u002Futils\u002Fshared\u002Fminicache","docs\u002Futils\u002Fshared\u002FminiCache",{"title":743,"path":744,"stem":745},"parseCookies","\u002Fdocs\u002Futils\u002Fshared\u002Fparserawcookies","docs\u002Futils\u002Fshared\u002FparseRawCookies",{"title":747,"path":748,"stem":749},"safeAction","\u002Fdocs\u002Futils\u002Fshared\u002Fpromiselocker","docs\u002Futils\u002Fshared\u002FpromiseLocker",{"title":751,"path":752,"stem":753},"Random","\u002Fdocs\u002Futils\u002Fshared\u002Frandom","docs\u002Futils\u002Fshared\u002Frandom",{"title":755,"path":756,"stem":757},"range","\u002Fdocs\u002Futils\u002Fshared\u002Frange","docs\u002Futils\u002Fshared\u002Frange",{"title":759,"path":760,"stem":761},"rateLimiters","\u002Fdocs\u002Futils\u002Fshared\u002Fratelimiters","docs\u002Futils\u002Fshared\u002FrateLimiters",{"title":763,"path":764,"stem":765},"safeObjectMerge","\u002Fdocs\u002Futils\u002Fshared\u002Fsafemerge","docs\u002Futils\u002Fshared\u002FsafeMerge",{"title":767,"path":768,"stem":769},"textTruncation","\u002Fdocs\u002Futils\u002Fshared\u002Ftexttruncation","docs\u002Futils\u002Fshared\u002FtextTruncation",{"title":771,"path":772,"stem":773},"validateZodSchema","\u002Fdocs\u002Futils\u002Fshared\u002Fvalidatezodschema","docs\u002Futils\u002Fshared\u002FvalidateZodSchema",{"title":775,"path":776,"stem":777,"children":778},"Utility Types","\u002Fdocs\u002Futils\u002Ftypes","docs\u002Futils\u002Ftypes\u002Findex",[779,780,784,788,792,796,800,804,808,812],{"title":775,"path":776,"stem":777},{"title":781,"path":782,"stem":783},"Brand","\u002Fdocs\u002Futils\u002Ftypes\u002Fbrand","docs\u002Futils\u002Ftypes\u002FBrand",{"title":785,"path":786,"stem":787},"DeepPartial","\u002Fdocs\u002Futils\u002Ftypes\u002Fdeeppartial","docs\u002Futils\u002Ftypes\u002FDeepPartial",{"title":789,"path":790,"stem":791},"Merge","\u002Fdocs\u002Futils\u002Ftypes\u002Fmerge","docs\u002Futils\u002Ftypes\u002FMerge",{"title":793,"path":794,"stem":795},"NonNullable","\u002Fdocs\u002Futils\u002Ftypes\u002Fnonnullable","docs\u002Futils\u002Ftypes\u002FNonNullable",{"title":797,"path":798,"stem":799},"Prettify","\u002Fdocs\u002Futils\u002Ftypes\u002Fprettify","docs\u002Futils\u002Ftypes\u002FPrettify",{"title":801,"path":802,"stem":803},"PromiseType","\u002Fdocs\u002Futils\u002Ftypes\u002Fpromisetype","docs\u002Futils\u002Ftypes\u002FPromiseType",{"title":805,"path":806,"stem":807},"RequireKeys","\u002Fdocs\u002Futils\u002Ftypes\u002Frequirekeys","docs\u002Futils\u002Ftypes\u002FRequireKeys",{"title":809,"path":810,"stem":811},"StandardResponse","\u002Fdocs\u002Futils\u002Ftypes\u002Fstandardresponse","docs\u002Futils\u002Ftypes\u002FStandardResponse",{"title":813,"path":814,"stem":815},"ValueOf","\u002Fdocs\u002Futils\u002Ftypes\u002Fvalueof","docs\u002Futils\u002Ftypes\u002FValueOf",{"id":4,"extension":5,"links":817,"meta":828,"stem":62,"__hash__":63},[818,826,827],{"nested":8,"label":9,"icon":10,"to":11,"children":819},[820,821,822,823,824,825],{"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":830,"title":14,"body":831,"description":2914,"extension":2915,"icon":15,"meta":2916,"module":2917,"navigation":8,"path":75,"rawbody":2918,"seo":2919,"stem":76,"__hash__":2920},"docs\u002Fdocs\u002Fbot-detection\u002F00.getting-started.md",{"type":832,"value":833,"toc":2907},"minimark",[834,842,847,850,883,901,905,912,980,991,1006,1010,1013,2415,2418,2423,2511,2636,2640,2647,2749,2903],[835,836,837,841],"p",{},[838,839,840],"code",{},"@riavzon\u002Fbot-detector"," works as an Express middleware. Getting started requires installing the package, downloading the threat intelligence data sources, configuring the module, and creating the database schema.",[843,844,846],"h2",{"id":845},"requirements","Requirements",[835,848,849],{},"Before you begin, ensure your environment meets the following requirements:",[851,852,853,860,865,871],"ul",{},[854,855,856],"li",{},[857,858,859],"strong",{},"Node.js 18 or later",[854,861,862],{},[857,863,864],{},"Express 5",[854,866,867,870],{},[857,868,869],{},"A supported database",": SQLite, MySQL, PostgreSQL, Cloudflare D1, or PlanetScale for visitor persistence",[854,872,873,878,879,882],{},[857,874,875],{},[838,876,877],{},"mmdbctl",": The CLI downloads and compiles data sources into MMDB format. The ",[838,880,881],{},"init"," command detects and installs it automatically if it is not found.",[884,885,886],"warning",{},[835,887,888,889,892,893,896,897,900],{},"The ",[838,890,891],{},"punishmentType.enableFireWallBan"," option requires a Linux environment with ",[838,894,895],{},"ufw"," available and passwordless ",[838,898,899],{},"sudo"," access for the Node.js process. All other features run on any platform that supports Node.js 18+.",[843,902,904],{"id":903},"quick-setup","Quick Setup",[835,906,907,908,911],{},"The fastest way to get started is with the ",[838,909,910],{},"create"," package. Run this command in the root of your Express project:",[913,914,915,938,953,967],"code-group",{},[916,917,923],"pre",{"className":918,"code":919,"filename":920,"language":921,"meta":922,"style":922},"language-bash shiki shiki-themes light-plus light-plus dracula","npx @riavzon\u002Fbot-detector-create\n","npm","bash","",[838,924,925],{"__ignoreMap":922},[926,927,930,934],"span",{"class":928,"line":929},"line",1,[926,931,933],{"class":932},"sHOzp","npx",[926,935,937],{"class":936},"sFB1V"," @riavzon\u002Fbot-detector-create\n",[916,939,942],{"className":918,"code":940,"filename":941,"language":921,"meta":922,"style":922},"pnpm dlx @riavzon\u002Fbot-detector-create\n","pnpm",[838,943,944],{"__ignoreMap":922},[926,945,946,948,951],{"class":928,"line":929},[926,947,941],{"class":932},[926,949,950],{"class":936}," dlx",[926,952,937],{"class":936},[916,954,957],{"className":918,"code":955,"filename":956,"language":921,"meta":922,"style":922},"yarn dlx @riavzon\u002Fbot-detector-create\n","yarn",[838,958,959],{"__ignoreMap":922},[926,960,961,963,965],{"class":928,"line":929},[926,962,956],{"class":932},[926,964,950],{"class":936},[926,966,937],{"class":936},[916,968,971],{"className":918,"code":969,"filename":970,"language":921,"meta":922,"style":922},"bunx @riavzon\u002Fbot-detector-create\n","bun",[838,972,973],{"__ignoreMap":922},[926,974,975,978],{"class":928,"line":929},[926,976,977],{"class":932},"bunx",[926,979,937],{"class":936},[835,981,982,983,986,987,990],{},"This command installs all required dependencies, downloads and compiles every threat intelligence feed, generates a fully annotated ",[838,984,985],{},"botDetectorConfig.ts"," with all 17 checkers at their defaults, creates a ready-to-run Express entry point, and initializes the database tables. It defaults to ",[838,988,989],{},"better-sqlite3"," as the database driver.",[992,993,994],"tip",{},[835,995,996,997,999,1000,1005],{},"If you are starting a new project, the ",[838,998,910],{}," package is the recommended path. Skip to ",[1001,1002,1004],"a",{"href":1003},"#next-steps","Next Steps"," after running it.",[843,1007,1009],{"id":1008},"manual-setup","Manual Setup",[835,1011,1012],{},"If you prefer to wire things up yourself, follow the steps below.",[1014,1015,1017,1022,1032,1116,1127,1131,1137,1196,1206,1209,1306,1310,1321,1680,1689,1693,1700,2196,2210,2334,2342,2346,2353,2412],"steps",{"level":1016},"4",[1018,1019,1021],"h4",{"id":1020},"install-the-package","Install the package",[835,1023,1024,1025,1027,1028,1031],{},"Install ",[838,1026,840],{}," along with Express, ",[838,1029,1030],{},"cookie-parser",", and your chosen database driver.",[913,1033,1034,1058,1078,1097],{},[916,1035,1037],{"className":918,"code":1036,"filename":920,"language":921,"meta":922,"style":922},"npm install @riavzon\u002Fbot-detector express cookie-parser better-sqlite3\n",[838,1038,1039],{"__ignoreMap":922},[926,1040,1041,1043,1046,1049,1052,1055],{"class":928,"line":929},[926,1042,920],{"class":932},[926,1044,1045],{"class":936}," install",[926,1047,1048],{"class":936}," @riavzon\u002Fbot-detector",[926,1050,1051],{"class":936}," express",[926,1053,1054],{"class":936}," cookie-parser",[926,1056,1057],{"class":936}," better-sqlite3\n",[916,1059,1061],{"className":918,"code":1060,"filename":941,"language":921,"meta":922,"style":922},"pnpm add @riavzon\u002Fbot-detector express cookie-parser better-sqlite3\n",[838,1062,1063],{"__ignoreMap":922},[926,1064,1065,1067,1070,1072,1074,1076],{"class":928,"line":929},[926,1066,941],{"class":932},[926,1068,1069],{"class":936}," add",[926,1071,1048],{"class":936},[926,1073,1051],{"class":936},[926,1075,1054],{"class":936},[926,1077,1057],{"class":936},[916,1079,1081],{"className":918,"code":1080,"filename":956,"language":921,"meta":922,"style":922},"yarn add @riavzon\u002Fbot-detector express cookie-parser better-sqlite3\n",[838,1082,1083],{"__ignoreMap":922},[926,1084,1085,1087,1089,1091,1093,1095],{"class":928,"line":929},[926,1086,956],{"class":932},[926,1088,1069],{"class":936},[926,1090,1048],{"class":936},[926,1092,1051],{"class":936},[926,1094,1054],{"class":936},[926,1096,1057],{"class":936},[916,1098,1100],{"className":918,"code":1099,"filename":970,"language":921,"meta":922,"style":922},"bun add @riavzon\u002Fbot-detector express cookie-parser better-sqlite3\n",[838,1101,1102],{"__ignoreMap":922},[926,1103,1104,1106,1108,1110,1112,1114],{"class":928,"line":929},[926,1105,970],{"class":932},[926,1107,1069],{"class":936},[926,1109,1048],{"class":936},[926,1111,1051],{"class":936},[926,1113,1054],{"class":936},[926,1115,1057],{"class":936},[835,1117,1118,1119,1121,1122,1126],{},"Replace ",[838,1120,989],{}," with your preferred driver. See ",[1001,1123,1125],{"href":1124},"#database-drivers","Database Drivers"," for the full list and their peer dependencies.",[1018,1128,1130],{"id":1129},"initialize-data-sources","Initialize data sources",[835,1132,1133,1134,1136],{},"Run the ",[838,1135,881],{}," command to download and compile the threat intelligence databases. This step is required before the middleware can run.",[913,1138,1139,1153,1168,1183],{},[916,1140,1142],{"className":918,"code":1141,"filename":920,"language":921,"meta":922,"style":922},"npx @riavzon\u002Fbot-detector init\n",[838,1143,1144],{"__ignoreMap":922},[926,1145,1146,1148,1150],{"class":928,"line":929},[926,1147,933],{"class":932},[926,1149,1048],{"class":936},[926,1151,1152],{"class":936}," init\n",[916,1154,1156],{"className":918,"code":1155,"filename":941,"language":921,"meta":922,"style":922},"pnpm dlx @riavzon\u002Fbot-detector init\n",[838,1157,1158],{"__ignoreMap":922},[926,1159,1160,1162,1164,1166],{"class":928,"line":929},[926,1161,941],{"class":932},[926,1163,950],{"class":936},[926,1165,1048],{"class":936},[926,1167,1152],{"class":936},[916,1169,1171],{"className":918,"code":1170,"filename":956,"language":921,"meta":922,"style":922},"yarn dlx @riavzon\u002Fbot-detector init\n",[838,1172,1173],{"__ignoreMap":922},[926,1174,1175,1177,1179,1181],{"class":928,"line":929},[926,1176,956],{"class":932},[926,1178,950],{"class":936},[926,1180,1048],{"class":936},[926,1182,1152],{"class":936},[916,1184,1186],{"className":918,"code":1185,"filename":970,"language":921,"meta":922,"style":922},"bunx @riavzon\u002Fbot-detector init\n",[838,1187,1188],{"__ignoreMap":922},[926,1189,1190,1192,1194],{"class":928,"line":929},[926,1191,977],{"class":932},[926,1193,1048],{"class":936},[926,1195,1152],{"class":936},[835,1197,1198,1199,1201,1202,1205],{},"The command verifies that ",[838,1200,877],{}," is installed (and installs it if not found), prompts for a BGP.tools contact string required to download BGP data, then compiles all data sources in parallel. The compiled databases are written to ",[838,1203,1204],{},"_data-sources\u002F"," inside the package directory.",[835,1207,1208],{},"To skip the interactive prompt in CI or automated environments, pass your contact string as a flag:",[913,1210,1211,1239,1262,1285],{},[916,1212,1214],{"className":918,"code":1213,"filename":920,"language":921,"meta":922,"style":922},"npx @riavzon\u002Fbot-detector init --contact=\"MyApp - contact@example.com\"\n",[838,1215,1216],{"__ignoreMap":922},[926,1217,1218,1220,1222,1225,1229,1233,1236],{"class":928,"line":929},[926,1219,933],{"class":932},[926,1221,1048],{"class":936},[926,1223,1224],{"class":936}," init",[926,1226,1228],{"class":1227},"sjR7W"," --contact=",[926,1230,1232],{"class":1231},"sFkSl","\"",[926,1234,1235],{"class":936},"MyApp - contact@example.com",[926,1237,1238],{"class":1231},"\"\n",[916,1240,1242],{"className":918,"code":1241,"filename":941,"language":921,"meta":922,"style":922},"pnpm dlx @riavzon\u002Fbot-detector init --contact=\"MyApp - contact@example.com\"\n",[838,1243,1244],{"__ignoreMap":922},[926,1245,1246,1248,1250,1252,1254,1256,1258,1260],{"class":928,"line":929},[926,1247,941],{"class":932},[926,1249,950],{"class":936},[926,1251,1048],{"class":936},[926,1253,1224],{"class":936},[926,1255,1228],{"class":1227},[926,1257,1232],{"class":1231},[926,1259,1235],{"class":936},[926,1261,1238],{"class":1231},[916,1263,1265],{"className":918,"code":1264,"filename":956,"language":921,"meta":922,"style":922},"yarn dlx @riavzon\u002Fbot-detector init --contact=\"MyApp - contact@example.com\"\n",[838,1266,1267],{"__ignoreMap":922},[926,1268,1269,1271,1273,1275,1277,1279,1281,1283],{"class":928,"line":929},[926,1270,956],{"class":932},[926,1272,950],{"class":936},[926,1274,1048],{"class":936},[926,1276,1224],{"class":936},[926,1278,1228],{"class":1227},[926,1280,1232],{"class":1231},[926,1282,1235],{"class":936},[926,1284,1238],{"class":1231},[916,1286,1288],{"className":918,"code":1287,"filename":970,"language":921,"meta":922,"style":922},"bunx @riavzon\u002Fbot-detector init --contact=\"MyApp - contact@example.com\"\n",[838,1289,1290],{"__ignoreMap":922},[926,1291,1292,1294,1296,1298,1300,1302,1304],{"class":928,"line":929},[926,1293,977],{"class":932},[926,1295,1048],{"class":936},[926,1297,1224],{"class":936},[926,1299,1228],{"class":1227},[926,1301,1232],{"class":1231},[926,1303,1235],{"class":936},[926,1305,1238],{"class":1231},[1018,1307,1309],{"id":1308},"configure-the-middleware","Configure the middleware",[835,1311,1312,1313,1316,1317,1320],{},"Create a startup file and call ",[838,1314,1315],{},"defineConfiguration"," before attaching any middleware to your app. The only required field is ",[838,1318,1319],{},"store.main",", which sets the database driver for visitor persistence.",[916,1322,1327],{"className":1323,"code":1324,"filename":1325,"language":1326,"meta":922,"style":922},"language-ts shiki shiki-themes light-plus light-plus dracula","import express from 'express'\nimport cookieParser from 'cookie-parser'\nimport { defineConfiguration, detectBots } from '@riavzon\u002Fbot-detector'\n\nconst app = express()\napp.use(cookieParser())\napp.use(express.json())\n\nawait defineConfiguration({\n  store: {\n    main: { driver: 'sqlite', name: '.\u002Fbot-detector.db' },\n  },\n})\n\napp.use(detectBots())\n\napp.get('\u002F', (req, res) => {\n  res.json({ ok: true, banned: req.botDetection?.banned })\n})\n\napp.listen(3000)\n","server.ts","ts",[838,1328,1329,1350,1366,1395,1401,1421,1442,1461,1466,1478,1491,1531,1537,1543,1548,1563,1568,1607,1651,1656,1661],{"__ignoreMap":922},[926,1330,1331,1335,1338,1341,1344,1347],{"class":928,"line":929},[926,1332,1334],{"class":1333},"sZ328","import",[926,1336,1051],{"class":1337},"sjsA6",[926,1339,1340],{"class":1333}," from",[926,1342,1343],{"class":1231}," '",[926,1345,1346],{"class":936},"express",[926,1348,1349],{"class":1231},"'\n",[926,1351,1353,1355,1358,1360,1362,1364],{"class":928,"line":1352},2,[926,1354,1334],{"class":1333},[926,1356,1357],{"class":1337}," cookieParser",[926,1359,1340],{"class":1333},[926,1361,1343],{"class":1231},[926,1363,1030],{"class":936},[926,1365,1349],{"class":1231},[926,1367,1369,1371,1375,1377,1380,1383,1386,1389,1391,1393],{"class":928,"line":1368},3,[926,1370,1334],{"class":1333},[926,1372,1374],{"class":1373},"sDd4n"," { ",[926,1376,1315],{"class":1337},[926,1378,1379],{"class":1373},", ",[926,1381,1382],{"class":1337},"detectBots",[926,1384,1385],{"class":1373}," } ",[926,1387,1388],{"class":1333},"from",[926,1390,1343],{"class":1231},[926,1392,840],{"class":936},[926,1394,1349],{"class":1231},[926,1396,1398],{"class":928,"line":1397},4,[926,1399,1400],{"emptyLinePlaceholder":8},"\n",[926,1402,1404,1408,1412,1416,1418],{"class":928,"line":1403},5,[926,1405,1407],{"class":1406},"sl46w","const",[926,1409,1411],{"class":1410},"s3JHE"," app",[926,1413,1415],{"class":1414},"saOXh"," =",[926,1417,1051],{"class":932},[926,1419,1420],{"class":1373},"()\n",[926,1422,1424,1427,1430,1433,1436,1439],{"class":928,"line":1423},6,[926,1425,1426],{"class":1337},"app",[926,1428,1429],{"class":1373},".",[926,1431,1432],{"class":932},"use",[926,1434,1435],{"class":1373},"(",[926,1437,1438],{"class":932},"cookieParser",[926,1440,1441],{"class":1373},"())\n",[926,1443,1445,1447,1449,1451,1453,1455,1457,1459],{"class":928,"line":1444},7,[926,1446,1426],{"class":1337},[926,1448,1429],{"class":1373},[926,1450,1432],{"class":932},[926,1452,1435],{"class":1373},[926,1454,1346],{"class":1337},[926,1456,1429],{"class":1373},[926,1458,5],{"class":932},[926,1460,1441],{"class":1373},[926,1462,1464],{"class":928,"line":1463},8,[926,1465,1400],{"emptyLinePlaceholder":8},[926,1467,1469,1472,1475],{"class":928,"line":1468},9,[926,1470,1471],{"class":1333},"await",[926,1473,1474],{"class":932}," defineConfiguration",[926,1476,1477],{"class":1373},"({\n",[926,1479,1481,1484,1488],{"class":928,"line":1480},10,[926,1482,1483],{"class":1337},"  store",[926,1485,1487],{"class":1486},"s34zl",":",[926,1489,1490],{"class":1373}," {\n",[926,1492,1494,1497,1499,1501,1504,1506,1508,1511,1514,1516,1519,1521,1523,1526,1528],{"class":928,"line":1493},11,[926,1495,1496],{"class":1337},"    main",[926,1498,1487],{"class":1486},[926,1500,1374],{"class":1373},[926,1502,1503],{"class":1337},"driver",[926,1505,1487],{"class":1486},[926,1507,1343],{"class":1231},[926,1509,1510],{"class":936},"sqlite",[926,1512,1513],{"class":1231},"'",[926,1515,1379],{"class":1373},[926,1517,1518],{"class":1337},"name",[926,1520,1487],{"class":1486},[926,1522,1343],{"class":1231},[926,1524,1525],{"class":936},".\u002Fbot-detector.db",[926,1527,1513],{"class":1231},[926,1529,1530],{"class":1373}," },\n",[926,1532,1534],{"class":928,"line":1533},12,[926,1535,1536],{"class":1373},"  },\n",[926,1538,1540],{"class":928,"line":1539},13,[926,1541,1542],{"class":1373},"})\n",[926,1544,1546],{"class":928,"line":1545},14,[926,1547,1400],{"emptyLinePlaceholder":8},[926,1549,1551,1553,1555,1557,1559,1561],{"class":928,"line":1550},15,[926,1552,1426],{"class":1337},[926,1554,1429],{"class":1373},[926,1556,1432],{"class":932},[926,1558,1435],{"class":1373},[926,1560,1382],{"class":932},[926,1562,1441],{"class":1373},[926,1564,1566],{"class":928,"line":1565},16,[926,1567,1400],{"emptyLinePlaceholder":8},[926,1569,1571,1573,1575,1578,1580,1582,1585,1587,1590,1594,1596,1599,1602,1605],{"class":928,"line":1570},17,[926,1572,1426],{"class":1337},[926,1574,1429],{"class":1373},[926,1576,1577],{"class":932},"get",[926,1579,1435],{"class":1373},[926,1581,1513],{"class":1231},[926,1583,1584],{"class":936},"\u002F",[926,1586,1513],{"class":1231},[926,1588,1589],{"class":1373},", (",[926,1591,1593],{"class":1592},"sygFZ","req",[926,1595,1379],{"class":1373},[926,1597,1598],{"class":1592},"res",[926,1600,1601],{"class":1373},") ",[926,1603,1604],{"class":1406},"=>",[926,1606,1490],{"class":1373},[926,1608,1610,1613,1615,1617,1620,1623,1625,1628,1630,1633,1635,1638,1640,1643,1646,1648],{"class":928,"line":1609},18,[926,1611,1612],{"class":1337},"  res",[926,1614,1429],{"class":1373},[926,1616,5],{"class":932},[926,1618,1619],{"class":1373},"({ ",[926,1621,1622],{"class":1337},"ok",[926,1624,1487],{"class":1486},[926,1626,1627],{"class":1227}," true",[926,1629,1379],{"class":1373},[926,1631,1632],{"class":1337},"banned",[926,1634,1487],{"class":1486},[926,1636,1637],{"class":1337}," req",[926,1639,1429],{"class":1373},[926,1641,1642],{"class":1337},"botDetection",[926,1644,1645],{"class":1373},"?.",[926,1647,1632],{"class":1337},[926,1649,1650],{"class":1373}," })\n",[926,1652,1654],{"class":928,"line":1653},19,[926,1655,1542],{"class":1373},[926,1657,1659],{"class":928,"line":1658},20,[926,1660,1400],{"emptyLinePlaceholder":8},[926,1662,1664,1666,1668,1671,1673,1677],{"class":928,"line":1663},21,[926,1665,1426],{"class":1337},[926,1667,1429],{"class":1373},[926,1669,1670],{"class":932},"listen",[926,1672,1435],{"class":1373},[926,1674,1676],{"class":1675},"spgvN","3000",[926,1678,1679],{"class":1373},")\n",[835,1681,1682,1684,1685,1688],{},[838,1683,1315],{}," is async and must resolve before you call ",[838,1686,1687],{},"detectBots()"," or any getter function. Call it exactly once during startup.",[1018,1690,1692],{"id":1691},"create-the-database-tables","Create the database tables",[835,1694,1695,1696,1699],{},"Run ",[838,1697,1698],{},"load-schema"," once after configuration to create the required tables in your database:",[1701,1702,1703,1788,1898,2005,2088],"tabs",{},[1704,1705,1707],"tabs-item",{"icon":41,"label":1706},"SQLite",[913,1708,1709,1732,1752,1771],{},[916,1710,1712],{"className":918,"code":1711,"filename":920,"language":921,"meta":922,"style":922},"npx @riavzon\u002Fbot-detector load-schema --db sqlite --db-name=.\u002Fbot-detector.db\n",[838,1713,1714],{"__ignoreMap":922},[926,1715,1716,1718,1720,1723,1726,1729],{"class":928,"line":929},[926,1717,933],{"class":932},[926,1719,1048],{"class":936},[926,1721,1722],{"class":936}," load-schema",[926,1724,1725],{"class":1227}," --db",[926,1727,1728],{"class":936}," sqlite",[926,1730,1731],{"class":1227}," --db-name=.\u002Fbot-detector.db\n",[916,1733,1735],{"className":918,"code":1734,"filename":941,"language":921,"meta":922,"style":922},"pnpm dlx @riavzon\u002Fbot-detector load-schema --db=sqlite --db-name=.\u002Fbot-detector.db\n",[838,1736,1737],{"__ignoreMap":922},[926,1738,1739,1741,1743,1745,1747,1750],{"class":928,"line":929},[926,1740,941],{"class":932},[926,1742,950],{"class":936},[926,1744,1048],{"class":936},[926,1746,1722],{"class":936},[926,1748,1749],{"class":1227}," --db=sqlite",[926,1751,1731],{"class":1227},[916,1753,1755],{"className":918,"code":1754,"filename":956,"language":921,"meta":922,"style":922},"yarn dlx @riavzon\u002Fbot-detector load-schema --db=sqlite --db-name=.\u002Fbot-detector.db\n",[838,1756,1757],{"__ignoreMap":922},[926,1758,1759,1761,1763,1765,1767,1769],{"class":928,"line":929},[926,1760,956],{"class":932},[926,1762,950],{"class":936},[926,1764,1048],{"class":936},[926,1766,1722],{"class":936},[926,1768,1749],{"class":1227},[926,1770,1731],{"class":1227},[916,1772,1774],{"className":918,"code":1773,"filename":970,"language":921,"meta":922,"style":922},"bunx @riavzon\u002Fbot-detector load-schema --db=sqlite --db-name=.\u002Fbot-detector.db\n",[838,1775,1776],{"__ignoreMap":922},[926,1777,1778,1780,1782,1784,1786],{"class":928,"line":929},[926,1779,977],{"class":932},[926,1781,1048],{"class":936},[926,1783,1722],{"class":936},[926,1785,1749],{"class":1227},[926,1787,1731],{"class":1227},[1704,1789,1792],{"icon":1790,"label":1791},"i-lucide-database","MySql",[913,1793,1794,1824,1850,1875],{},[916,1795,1797],{"className":918,"code":1796,"filename":920,"language":921,"meta":922,"style":922},"npx @riavzon\u002Fbot-detector load-schema --db mysql-pool --db-host=localhost --db-user=root --db-password=secret --db-name=botdb\n",[838,1798,1799],{"__ignoreMap":922},[926,1800,1801,1803,1805,1807,1809,1812,1815,1818,1821],{"class":928,"line":929},[926,1802,933],{"class":932},[926,1804,1048],{"class":936},[926,1806,1722],{"class":936},[926,1808,1725],{"class":1227},[926,1810,1811],{"class":936}," mysql-pool",[926,1813,1814],{"class":1227}," --db-host=localhost",[926,1816,1817],{"class":1227}," --db-user=root",[926,1819,1820],{"class":1227}," --db-password=secret",[926,1822,1823],{"class":1227}," --db-name=botdb\n",[916,1825,1827],{"className":918,"code":1826,"filename":941,"language":921,"meta":922,"style":922},"pnpm dlx @riavzon\u002Fbot-detector load-schema --db=mysql-pool --db-host=localhost --db-user=root --db-password=secret --db-name=botdb\n",[838,1828,1829],{"__ignoreMap":922},[926,1830,1831,1833,1835,1837,1839,1842,1844,1846,1848],{"class":928,"line":929},[926,1832,941],{"class":932},[926,1834,950],{"class":936},[926,1836,1048],{"class":936},[926,1838,1722],{"class":936},[926,1840,1841],{"class":1227}," --db=mysql-pool",[926,1843,1814],{"class":1227},[926,1845,1817],{"class":1227},[926,1847,1820],{"class":1227},[926,1849,1823],{"class":1227},[916,1851,1853],{"className":918,"code":1852,"filename":956,"language":921,"meta":922,"style":922},"yarn dlx @riavzon\u002Fbot-detector load-schema --db=mysql-pool --db-host=localhost --db-user=root --db-password=secret --db-name=botdb\n",[838,1854,1855],{"__ignoreMap":922},[926,1856,1857,1859,1861,1863,1865,1867,1869,1871,1873],{"class":928,"line":929},[926,1858,956],{"class":932},[926,1860,950],{"class":936},[926,1862,1048],{"class":936},[926,1864,1722],{"class":936},[926,1866,1841],{"class":1227},[926,1868,1814],{"class":1227},[926,1870,1817],{"class":1227},[926,1872,1820],{"class":1227},[926,1874,1823],{"class":1227},[916,1876,1878],{"className":918,"code":1877,"filename":970,"language":921,"meta":922,"style":922},"bunx @riavzon\u002Fbot-detector load-schema --db=mysql-pool --db-host=localhost --db-user=root --db-password=secret --db-name=botdb\n",[838,1879,1880],{"__ignoreMap":922},[926,1881,1882,1884,1886,1888,1890,1892,1894,1896],{"class":928,"line":929},[926,1883,977],{"class":932},[926,1885,1048],{"class":936},[926,1887,1722],{"class":936},[926,1889,1841],{"class":1227},[926,1891,1814],{"class":1227},[926,1893,1817],{"class":1227},[926,1895,1820],{"class":1227},[926,1897,1823],{"class":1227},[1704,1899,1902],{"icon":1900,"label":1901},"i-lucide-server","PostgreSQL",[913,1903,1904,1931,1957,1982],{},[916,1905,1907],{"className":918,"code":1906,"filename":920,"language":921,"meta":922,"style":922},"npx @riavzon\u002Fbot-detector load-schema --db postgresql --db-host=localhost --db-user=postgres --db-password=secret --db-name=botdb\n",[838,1908,1909],{"__ignoreMap":922},[926,1910,1911,1913,1915,1917,1919,1922,1924,1927,1929],{"class":928,"line":929},[926,1912,933],{"class":932},[926,1914,1048],{"class":936},[926,1916,1722],{"class":936},[926,1918,1725],{"class":1227},[926,1920,1921],{"class":936}," postgresql",[926,1923,1814],{"class":1227},[926,1925,1926],{"class":1227}," --db-user=postgres",[926,1928,1820],{"class":1227},[926,1930,1823],{"class":1227},[916,1932,1934],{"className":918,"code":1933,"filename":941,"language":921,"meta":922,"style":922},"pnpm dlx @riavzon\u002Fbot-detector load-schema --db=postgresql --db-host=localhost --db-user=postgres --db-password=secret --db-name=botdb\n",[838,1935,1936],{"__ignoreMap":922},[926,1937,1938,1940,1942,1944,1946,1949,1951,1953,1955],{"class":928,"line":929},[926,1939,941],{"class":932},[926,1941,950],{"class":936},[926,1943,1048],{"class":936},[926,1945,1722],{"class":936},[926,1947,1948],{"class":1227}," --db=postgresql",[926,1950,1814],{"class":1227},[926,1952,1926],{"class":1227},[926,1954,1820],{"class":1227},[926,1956,1823],{"class":1227},[916,1958,1960],{"className":918,"code":1959,"filename":956,"language":921,"meta":922,"style":922},"yarn dlx @riavzon\u002Fbot-detector load-schema --db=postgresql --db-host=localhost --db-user=postgres --db-password=secret --db-name=botdb\n",[838,1961,1962],{"__ignoreMap":922},[926,1963,1964,1966,1968,1970,1972,1974,1976,1978,1980],{"class":928,"line":929},[926,1965,956],{"class":932},[926,1967,950],{"class":936},[926,1969,1048],{"class":936},[926,1971,1722],{"class":936},[926,1973,1948],{"class":1227},[926,1975,1814],{"class":1227},[926,1977,1926],{"class":1227},[926,1979,1820],{"class":1227},[926,1981,1823],{"class":1227},[916,1983,1985],{"className":918,"code":1984,"filename":970,"language":921,"meta":922,"style":922},"bunx @riavzon\u002Fbot-detector load-schema --db=postgresql --db-host=localhost --db-user=postgres --db-password=secret --db-name=botdb\n",[838,1986,1987],{"__ignoreMap":922},[926,1988,1989,1991,1993,1995,1997,1999,2001,2003],{"class":928,"line":929},[926,1990,977],{"class":932},[926,1992,1048],{"class":936},[926,1994,1722],{"class":936},[926,1996,1948],{"class":1227},[926,1998,1814],{"class":1227},[926,2000,1926],{"class":1227},[926,2002,1820],{"class":1227},[926,2004,1823],{"class":1227},[1704,2006,2009],{"icon":2007,"label":2008},"i-lucide-cloud","Cloudflare D1",[913,2010,2011,2032,2052,2071],{},[916,2012,2014],{"className":918,"code":2013,"filename":920,"language":921,"meta":922,"style":922},"npx @riavzon\u002Fbot-detector load-schema --db cloudflare-d1 --db-name=my-d1-binding\n",[838,2015,2016],{"__ignoreMap":922},[926,2017,2018,2020,2022,2024,2026,2029],{"class":928,"line":929},[926,2019,933],{"class":932},[926,2021,1048],{"class":936},[926,2023,1722],{"class":936},[926,2025,1725],{"class":1227},[926,2027,2028],{"class":936}," cloudflare-d1",[926,2030,2031],{"class":1227}," --db-name=my-d1-binding\n",[916,2033,2035],{"className":918,"code":2034,"filename":941,"language":921,"meta":922,"style":922},"pnpm dlx @riavzon\u002Fbot-detector load-schema --db=cloudflare-d1 --db-name=my-d1-binding\n",[838,2036,2037],{"__ignoreMap":922},[926,2038,2039,2041,2043,2045,2047,2050],{"class":928,"line":929},[926,2040,941],{"class":932},[926,2042,950],{"class":936},[926,2044,1048],{"class":936},[926,2046,1722],{"class":936},[926,2048,2049],{"class":1227}," --db=cloudflare-d1",[926,2051,2031],{"class":1227},[916,2053,2055],{"className":918,"code":2054,"filename":956,"language":921,"meta":922,"style":922},"yarn dlx @riavzon\u002Fbot-detector load-schema --db=cloudflare-d1 --db-name=my-d1-binding\n",[838,2056,2057],{"__ignoreMap":922},[926,2058,2059,2061,2063,2065,2067,2069],{"class":928,"line":929},[926,2060,956],{"class":932},[926,2062,950],{"class":936},[926,2064,1048],{"class":936},[926,2066,1722],{"class":936},[926,2068,2049],{"class":1227},[926,2070,2031],{"class":1227},[916,2072,2074],{"className":918,"code":2073,"filename":970,"language":921,"meta":922,"style":922},"bunx @riavzon\u002Fbot-detector load-schema --db=cloudflare-d1 --db-name=my-d1-binding\n",[838,2075,2076],{"__ignoreMap":922},[926,2077,2078,2080,2082,2084,2086],{"class":928,"line":929},[926,2079,977],{"class":932},[926,2081,1048],{"class":936},[926,2083,1722],{"class":936},[926,2085,2049],{"class":1227},[926,2087,2031],{"class":1227},[1704,2089,2092],{"icon":2090,"label":2091},"i-lucide-globe","PlanetScale",[913,2093,2094,2122,2148,2173],{},[916,2095,2097],{"className":918,"code":2096,"filename":920,"language":921,"meta":922,"style":922},"npx @riavzon\u002Fbot-detector load-schema --db planetscale --db-url=\"mysql:\u002F\u002F\u003Cuser>:\u003Cpass>@\u003Chost>\u002F\u003Cdb>\"\n",[838,2098,2099],{"__ignoreMap":922},[926,2100,2101,2103,2105,2107,2109,2112,2115,2117,2120],{"class":928,"line":929},[926,2102,933],{"class":932},[926,2104,1048],{"class":936},[926,2106,1722],{"class":936},[926,2108,1725],{"class":1227},[926,2110,2111],{"class":936}," planetscale",[926,2113,2114],{"class":1227}," --db-url=",[926,2116,1232],{"class":1231},[926,2118,2119],{"class":936},"mysql:\u002F\u002F\u003Cuser>:\u003Cpass>@\u003Chost>\u002F\u003Cdb>",[926,2121,1238],{"class":1231},[916,2123,2125],{"className":918,"code":2124,"filename":941,"language":921,"meta":922,"style":922},"pnpm dlx @riavzon\u002Fbot-detector load-schema --db=planetscale --db-url=\"mysql:\u002F\u002F\u003Cuser>:\u003Cpass>@\u003Chost>\u002F\u003Cdb>\"\n",[838,2126,2127],{"__ignoreMap":922},[926,2128,2129,2131,2133,2135,2137,2140,2142,2144,2146],{"class":928,"line":929},[926,2130,941],{"class":932},[926,2132,950],{"class":936},[926,2134,1048],{"class":936},[926,2136,1722],{"class":936},[926,2138,2139],{"class":1227}," --db=planetscale",[926,2141,2114],{"class":1227},[926,2143,1232],{"class":1231},[926,2145,2119],{"class":936},[926,2147,1238],{"class":1231},[916,2149,2151],{"className":918,"code":2150,"filename":956,"language":921,"meta":922,"style":922},"yarn dlx @riavzon\u002Fbot-detector load-schema --db=planetscale --db-url=\"mysql:\u002F\u002F\u003Cuser>:\u003Cpass>@\u003Chost>\u002F\u003Cdb>\"\n",[838,2152,2153],{"__ignoreMap":922},[926,2154,2155,2157,2159,2161,2163,2165,2167,2169,2171],{"class":928,"line":929},[926,2156,956],{"class":932},[926,2158,950],{"class":936},[926,2160,1048],{"class":936},[926,2162,1722],{"class":936},[926,2164,2139],{"class":1227},[926,2166,2114],{"class":1227},[926,2168,1232],{"class":1231},[926,2170,2119],{"class":936},[926,2172,1238],{"class":1231},[916,2174,2176],{"className":918,"code":2175,"filename":970,"language":921,"meta":922,"style":922},"bunx @riavzon\u002Fbot-detector load-schema --db=planetscale --db-url=\"mysql:\u002F\u002F\u003Cuser>:\u003Cpass>@\u003Chost>\u002F\u003Cdb>\"\n",[838,2177,2178],{"__ignoreMap":922},[926,2179,2180,2182,2184,2186,2188,2190,2192,2194],{"class":928,"line":929},[926,2181,977],{"class":932},[926,2183,1048],{"class":936},[926,2185,1722],{"class":936},[926,2187,2139],{"class":1227},[926,2189,2114],{"class":1227},[926,2191,1232],{"class":1231},[926,2193,2119],{"class":936},[926,2195,1238],{"class":1231},[835,2197,2198,2199,2202,2203,2206,2207,2209],{},"You can also call it programmatically with ",[838,2200,2201],{},"createTables(db)",". Pass ",[838,2204,2205],{},"getDb()"," to provide the initialized instance, call this after ",[838,2208,1315],{}," resolves:",[916,2211,2213],{"className":1323,"code":2212,"language":1326,"meta":922,"style":922},"import { defineConfiguration, createTables, getDb } from '@riavzon\u002Fbot-detector';\n\nawait defineConfiguration({\nstore: {\n  main: { driver: 'sqlite', name: '.\u002Fbot-detector.db' },\n},\n});\n\n\u002F\u002F createTables expects a Database instance, pass getDb()\nawait createTables(getDb());\n\n",[838,2214,2215,2246,2250,2258,2267,2300,2305,2310,2314,2320],{"__ignoreMap":922},[926,2216,2217,2219,2221,2223,2225,2228,2230,2233,2235,2237,2239,2241,2243],{"class":928,"line":929},[926,2218,1334],{"class":1333},[926,2220,1374],{"class":1373},[926,2222,1315],{"class":1337},[926,2224,1379],{"class":1373},[926,2226,2227],{"class":1337},"createTables",[926,2229,1379],{"class":1373},[926,2231,2232],{"class":1337},"getDb",[926,2234,1385],{"class":1373},[926,2236,1388],{"class":1333},[926,2238,1343],{"class":1231},[926,2240,840],{"class":936},[926,2242,1513],{"class":1231},[926,2244,2245],{"class":1373},";\n",[926,2247,2248],{"class":928,"line":1352},[926,2249,1400],{"emptyLinePlaceholder":8},[926,2251,2252,2254,2256],{"class":928,"line":1368},[926,2253,1471],{"class":1333},[926,2255,1474],{"class":932},[926,2257,1477],{"class":1373},[926,2259,2260,2263,2265],{"class":928,"line":1397},[926,2261,2262],{"class":1337},"store",[926,2264,1487],{"class":1486},[926,2266,1490],{"class":1373},[926,2268,2269,2272,2274,2276,2278,2280,2282,2284,2286,2288,2290,2292,2294,2296,2298],{"class":928,"line":1403},[926,2270,2271],{"class":1337},"  main",[926,2273,1487],{"class":1486},[926,2275,1374],{"class":1373},[926,2277,1503],{"class":1337},[926,2279,1487],{"class":1486},[926,2281,1343],{"class":1231},[926,2283,1510],{"class":936},[926,2285,1513],{"class":1231},[926,2287,1379],{"class":1373},[926,2289,1518],{"class":1337},[926,2291,1487],{"class":1486},[926,2293,1343],{"class":1231},[926,2295,1525],{"class":936},[926,2297,1513],{"class":1231},[926,2299,1530],{"class":1373},[926,2301,2302],{"class":928,"line":1423},[926,2303,2304],{"class":1373},"},\n",[926,2306,2307],{"class":928,"line":1444},[926,2308,2309],{"class":1373},"});\n",[926,2311,2312],{"class":928,"line":1463},[926,2313,1400],{"emptyLinePlaceholder":8},[926,2315,2316],{"class":928,"line":1468},[926,2317,2319],{"class":2318},"sghk6","\u002F\u002F createTables expects a Database instance, pass getDb()\n",[926,2321,2322,2324,2327,2329,2331],{"class":928,"line":1480},[926,2323,1471],{"class":1333},[926,2325,2326],{"class":932}," createTables",[926,2328,1435],{"class":1373},[926,2330,2232],{"class":932},[926,2332,2333],{"class":1373},"());\n",[2335,2336,2337],"note",{},[835,2338,1695,2339,2341],{},[838,2340,1698],{}," before starting the server for the first time. It is safe to skip on subsequent restarts.",[1018,2343,2345],{"id":2344},"schedule-data-source-refreshes","Schedule data source refreshes",[835,2347,2348,2349,2352],{},"Threat intelligence data degrades over time. Run ",[838,2350,2351],{},"refresh"," at least once every 24 hours to redownload and recompile the latest feeds:",[913,2354,2355,2369,2384,2399],{},[916,2356,2358],{"className":918,"code":2357,"filename":920,"language":921,"meta":922,"style":922},"npx @riavzon\u002Fbot-detector refresh\n",[838,2359,2360],{"__ignoreMap":922},[926,2361,2362,2364,2366],{"class":928,"line":929},[926,2363,933],{"class":932},[926,2365,1048],{"class":936},[926,2367,2368],{"class":936}," refresh\n",[916,2370,2372],{"className":918,"code":2371,"filename":941,"language":921,"meta":922,"style":922},"pnpm dlx @riavzon\u002Fbot-detector refresh\n",[838,2373,2374],{"__ignoreMap":922},[926,2375,2376,2378,2380,2382],{"class":928,"line":929},[926,2377,941],{"class":932},[926,2379,950],{"class":936},[926,2381,1048],{"class":936},[926,2383,2368],{"class":936},[916,2385,2387],{"className":918,"code":2386,"filename":956,"language":921,"meta":922,"style":922},"yarn dlx @riavzon\u002Fbot-detector refresh\n",[838,2388,2389],{"__ignoreMap":922},[926,2390,2391,2393,2395,2397],{"class":928,"line":929},[926,2392,956],{"class":932},[926,2394,950],{"class":936},[926,2396,1048],{"class":936},[926,2398,2368],{"class":936},[916,2400,2402],{"className":918,"code":2401,"filename":970,"language":921,"meta":922,"style":922},"bunx @riavzon\u002Fbot-detector refresh\n",[838,2403,2404],{"__ignoreMap":922},[926,2405,2406,2408,2410],{"class":928,"line":929},[926,2407,977],{"class":932},[926,2409,1048],{"class":936},[926,2411,2368],{"class":936},[835,2413,2414],{},"Add this command to a cron job or a CI\u002FCD pipeline to keep the data current.",[843,2416,1125],{"id":2417},"database-drivers",[835,2419,888,2420,2422],{},[838,2421,1319],{}," field accepts the following drivers. Each requires the corresponding peer dependency to be installed separately.",[2424,2425,2426,2442],"table",{},[2427,2428,2429],"thead",{},[2430,2431,2432,2436,2439],"tr",{},[2433,2434,2435],"th",{},"Driver",[2433,2437,2438],{},"Value",[2433,2440,2441],{},"Peer Dependency",[2443,2444,2445,2458,2473,2487,2499],"tbody",{},[2430,2446,2447,2450,2454],{},[2448,2449,1706],"td",{},[2448,2451,2452],{},[838,2453,1510],{},[2448,2455,2456],{},[838,2457,989],{},[2430,2459,2460,2463,2468],{},[2448,2461,2462],{},"MySQL pool",[2448,2464,2465],{},[838,2466,2467],{},"mysql-pool",[2448,2469,2470],{},[838,2471,2472],{},"mysql2 >= 3",[2430,2474,2475,2477,2482],{},[2448,2476,1901],{},[2448,2478,2479],{},[838,2480,2481],{},"postgresql",[2448,2483,2484],{},[838,2485,2486],{},"pg",[2430,2488,2489,2491,2496],{},[2448,2490,2008],{},[2448,2492,2493],{},[838,2494,2495],{},"cloudflare-d1",[2448,2497,2498],{},"Worker environment binding",[2430,2500,2501,2503,2508],{},[2448,2502,2091],{},[2448,2504,2505],{},[838,2506,2507],{},"planetscale",[2448,2509,2510],{},"Serverless driver",[916,2512,2514],{"className":1323,"code":2513,"filename":1325,"language":1326,"meta":922,"style":922},"\u002F\u002F SQLite\n{ driver: 'sqlite', name: '.\u002Fbot-detector.db' }\n\n\u002F\u002F MySQL pool\n{ driver: 'mysql-pool', host: 'localhost', user: 'root', password: 'secret', database: 'mydb' }\n\n\u002F\u002F PostgreSQL\n{ driver: 'postgresql', connectionString: 'postgres:\u002F\u002Fuser:pass@localhost\u002Fmydb' }\n",[838,2515,2516,2521,2544,2548,2553,2605,2609,2614],{"__ignoreMap":922},[926,2517,2518],{"class":928,"line":929},[926,2519,2520],{"class":2318},"\u002F\u002F SQLite\n",[926,2522,2523,2526,2528,2530,2532,2535,2537,2539,2541],{"class":928,"line":1352},[926,2524,2525],{"class":1373},"{ driver: ",[926,2527,1513],{"class":1231},[926,2529,1510],{"class":936},[926,2531,1513],{"class":1231},[926,2533,2534],{"class":1373},", name: ",[926,2536,1513],{"class":1231},[926,2538,1525],{"class":936},[926,2540,1513],{"class":1231},[926,2542,2543],{"class":1373}," }\n",[926,2545,2546],{"class":928,"line":1368},[926,2547,1400],{"emptyLinePlaceholder":8},[926,2549,2550],{"class":928,"line":1397},[926,2551,2552],{"class":2318},"\u002F\u002F MySQL pool\n",[926,2554,2555,2557,2559,2561,2563,2566,2568,2571,2573,2576,2578,2581,2583,2586,2588,2591,2593,2596,2598,2601,2603],{"class":928,"line":1403},[926,2556,2525],{"class":1373},[926,2558,1513],{"class":1231},[926,2560,2467],{"class":936},[926,2562,1513],{"class":1231},[926,2564,2565],{"class":1373},", host: ",[926,2567,1513],{"class":1231},[926,2569,2570],{"class":936},"localhost",[926,2572,1513],{"class":1231},[926,2574,2575],{"class":1373},", user: ",[926,2577,1513],{"class":1231},[926,2579,2580],{"class":936},"root",[926,2582,1513],{"class":1231},[926,2584,2585],{"class":1373},", password: ",[926,2587,1513],{"class":1231},[926,2589,2590],{"class":936},"secret",[926,2592,1513],{"class":1231},[926,2594,2595],{"class":1373},", database: ",[926,2597,1513],{"class":1231},[926,2599,2600],{"class":936},"mydb",[926,2602,1513],{"class":1231},[926,2604,2543],{"class":1373},[926,2606,2607],{"class":928,"line":1423},[926,2608,1400],{"emptyLinePlaceholder":8},[926,2610,2611],{"class":928,"line":1444},[926,2612,2613],{"class":2318},"\u002F\u002F PostgreSQL\n",[926,2615,2616,2618,2620,2622,2624,2627,2629,2632,2634],{"class":928,"line":1463},[926,2617,2525],{"class":1373},[926,2619,1513],{"class":1231},[926,2621,2481],{"class":936},[926,2623,1513],{"class":1231},[926,2625,2626],{"class":1373},", connectionString: ",[926,2628,1513],{"class":1231},[926,2630,2631],{"class":936},"postgres:\u002F\u002Fuser:pass@localhost\u002Fmydb",[926,2633,1513],{"class":1231},[926,2635,2543],{"class":1373},[843,2637,2639],{"id":2638},"cache-drivers","Cache Drivers",[835,2641,2642,2643,2646],{},"By default, visitor state and behavioral data are stored in memory. This works for single-process deployments. For multi-process or distributed deployments, configure a shared ",[838,2644,2645],{},"storage"," driver so all instances share the same visitor cache.",[916,2648,2650],{"className":1323,"code":2649,"filename":1325,"language":1326,"meta":922,"style":922},"await defineConfiguration({\n  store: { main: { driver: 'sqlite', name: '.\u002Fbot-detector.db' } },\n  storage: { driver: 'redis', host: 'localhost', port: 6379 },\n})\n",[838,2651,2652,2660,2700,2745],{"__ignoreMap":922},[926,2653,2654,2656,2658],{"class":928,"line":929},[926,2655,1471],{"class":1333},[926,2657,1474],{"class":932},[926,2659,1477],{"class":1373},[926,2661,2662,2664,2666,2668,2671,2673,2675,2677,2679,2681,2683,2685,2687,2689,2691,2693,2695,2697],{"class":928,"line":1352},[926,2663,1483],{"class":1337},[926,2665,1487],{"class":1486},[926,2667,1374],{"class":1373},[926,2669,2670],{"class":1337},"main",[926,2672,1487],{"class":1486},[926,2674,1374],{"class":1373},[926,2676,1503],{"class":1337},[926,2678,1487],{"class":1486},[926,2680,1343],{"class":1231},[926,2682,1510],{"class":936},[926,2684,1513],{"class":1231},[926,2686,1379],{"class":1373},[926,2688,1518],{"class":1337},[926,2690,1487],{"class":1486},[926,2692,1343],{"class":1231},[926,2694,1525],{"class":936},[926,2696,1513],{"class":1231},[926,2698,2699],{"class":1373}," } },\n",[926,2701,2702,2705,2707,2709,2711,2713,2715,2718,2720,2722,2725,2727,2729,2731,2733,2735,2738,2740,2743],{"class":928,"line":1368},[926,2703,2704],{"class":1337},"  storage",[926,2706,1487],{"class":1486},[926,2708,1374],{"class":1373},[926,2710,1503],{"class":1337},[926,2712,1487],{"class":1486},[926,2714,1343],{"class":1231},[926,2716,2717],{"class":936},"redis",[926,2719,1513],{"class":1231},[926,2721,1379],{"class":1373},[926,2723,2724],{"class":1337},"host",[926,2726,1487],{"class":1486},[926,2728,1343],{"class":1231},[926,2730,2570],{"class":936},[926,2732,1513],{"class":1231},[926,2734,1379],{"class":1373},[926,2736,2737],{"class":1337},"port",[926,2739,1487],{"class":1486},[926,2741,2742],{"class":1675}," 6379",[926,2744,1530],{"class":1373},[926,2746,2747],{"class":928,"line":1397},[926,2748,1542],{"class":1373},[2424,2750,2751,2762],{},[2427,2752,2753],{},[2430,2754,2755,2757,2759],{},[2433,2756,2435],{},[2433,2758,2438],{},[2433,2760,2761],{},"Notes",[2443,2763,2764,2781,2801,2813,2826,2839,2855,2876,2890],{},[2430,2765,2766,2769,2778],{},[2448,2767,2768],{},"Memory (default)",[2448,2770,2771],{},[2772,2773,2774,2775,2777],"em",{},"(omit ",[838,2776,2645],{},")",[2448,2779,2780],{},"Single-process only",[2430,2782,2783,2786,2791],{},[2448,2784,2785],{},"LRU cache",[2448,2787,2788],{},[838,2789,2790],{},"lru",[2448,2792,2793,2794,2797,2798],{},"In-process LRU; set ",[838,2795,2796],{},"max"," and ",[838,2799,2800],{},"ttl",[2430,2802,2803,2806,2810],{},[2448,2804,2805],{},"Redis",[2448,2807,2808],{},[838,2809,2717],{},[2448,2811,2812],{},"Shared across instances",[2430,2814,2815,2818,2823],{},[2448,2816,2817],{},"Upstash Redis",[2448,2819,2820],{},[838,2821,2822],{},"upstash",[2448,2824,2825],{},"Serverless Redis via HTTP",[2430,2827,2828,2831,2836],{},[2448,2829,2830],{},"Filesystem",[2448,2832,2833],{},[838,2834,2835],{},"fs",[2448,2837,2838],{},"Local persistent storage for development",[2430,2840,2841,2844,2849],{},[2448,2842,2843],{},"Cloudflare KV (binding)",[2448,2845,2846],{},[838,2847,2848],{},"cloudflare-kv-binding",[2448,2850,2851,2852],{},"Pass ",[838,2853,2854],{},"binding",[2430,2856,2857,2860,2865],{},[2448,2858,2859],{},"Cloudflare KV (HTTP)",[2448,2861,2862],{},[838,2863,2864],{},"cloudflare-kv-http",[2448,2866,2851,2867,1379,2870,1379,2873],{},[838,2868,2869],{},"accountId",[838,2871,2872],{},"namespaceId",[838,2874,2875],{},"apiToken",[2430,2877,2878,2881,2886],{},[2448,2879,2880],{},"Cloudflare R2",[2448,2882,2883],{},[838,2884,2885],{},"cloudflare-r2-binding",[2448,2887,2851,2888],{},[838,2889,2854],{},[2430,2891,2892,2895,2900],{},[2448,2893,2894],{},"Vercel",[2448,2896,2897],{},[838,2898,2899],{},"vercel",[2448,2901,2902],{},"Vercel Runtime Cache",[2904,2905,2906],"style",{},"html pre.shiki code .sZ328, html code.shiki .sZ328{--shiki-light:#AF00DB;--shiki-default:#AF00DB;--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 .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 .sDd4n, html code.shiki .sDd4n{--shiki-light:#000000;--shiki-default:#000000;--shiki-dark:#F8F8F2}html pre.shiki code .sl46w, html code.shiki .sl46w{--shiki-light:#0000FF;--shiki-default:#0000FF;--shiki-dark:#FF79C6}html pre.shiki code .s3JHE, html code.shiki .s3JHE{--shiki-light:#0070C1;--shiki-default:#0070C1;--shiki-dark:#F8F8F2}html pre.shiki code .saOXh, html code.shiki .saOXh{--shiki-light:#000000;--shiki-default:#000000;--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 .s34zl, html code.shiki .s34zl{--shiki-light:#001080;--shiki-default:#001080;--shiki-dark:#FF79C6}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 .sjR7W, html code.shiki .sjR7W{--shiki-light:#0000FF;--shiki-default:#0000FF;--shiki-dark:#BD93F9}html pre.shiki code .spgvN, html code.shiki .spgvN{--shiki-light:#098658;--shiki-default:#098658;--shiki-dark:#BD93F9}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 .sghk6, html code.shiki .sghk6{--shiki-light:#008000;--shiki-default:#008000;--shiki-dark:#6272A4}",{"title":922,"searchDepth":1352,"depth":1352,"links":2908},[2909,2910,2911,2912,2913],{"id":845,"depth":1352,"text":846},{"id":903,"depth":1352,"text":904},{"id":1008,"depth":1352,"text":1009},{"id":2417,"depth":1352,"text":1125},{"id":2638,"depth":1352,"text":2639},"Install and configure Bot Detector in your Express application.","md",{},null,"---\ntitle: Getting Started\ndescription: Install and configure Bot Detector in your Express application.\nicon: i-lucide-rocket\n---\n\n`@riavzon\u002Fbot-detector` works as an Express middleware. Getting started requires installing the package, downloading the threat intelligence data sources, configuring the module, and creating the database schema.\n\n## Requirements\n\nBefore you begin, ensure your environment meets the following requirements:\n\n- **Node.js 18 or later**\n- **Express 5**\n- **A supported database**: SQLite, MySQL, PostgreSQL, Cloudflare D1, or PlanetScale for visitor persistence\n- **`mmdbctl`**: The CLI downloads and compiles data sources into MMDB format. The `init` command detects and installs it automatically if it is not found.\n\n::warning\nThe `punishmentType.enableFireWallBan` option requires a Linux environment with `ufw` available and passwordless `sudo` access for the Node.js process. All other features run on any platform that supports Node.js 18+.\n::\n\n## Quick Setup\n\nThe fastest way to get started is with the `create` package. Run this command in the root of your Express project:\n\n\n\n::code-group\n\n```bash [npm]\nnpx @riavzon\u002Fbot-detector-create\n```\n\n```bash [pnpm]\npnpm dlx @riavzon\u002Fbot-detector-create\n```\n\n```bash [yarn]\nyarn dlx @riavzon\u002Fbot-detector-create\n```\n\n\n```bash [bun]\nbunx @riavzon\u002Fbot-detector-create\n```\n::\n\nThis command installs all required dependencies, downloads and compiles every threat intelligence feed, generates a fully annotated `botDetectorConfig.ts` with all 17 checkers at their defaults, creates a ready-to-run Express entry point, and initializes the database tables. It defaults to `better-sqlite3` as the database driver.\n\n::tip\nIf you are starting a new project, the `create` package is the recommended path. Skip to [Next Steps](#next-steps) after running it.\n::\n\n## Manual Setup\n\nIf you prefer to wire things up yourself, follow the steps below.\n  \n::steps{level=\"4\"}\n \n#### Install the package\n\nInstall `@riavzon\u002Fbot-detector` along with Express, `cookie-parser`, and your chosen database driver.\n\n::code-group\n\n```bash [npm]\nnpm install @riavzon\u002Fbot-detector express cookie-parser better-sqlite3\n```\n\n```bash [pnpm]\npnpm add @riavzon\u002Fbot-detector express cookie-parser better-sqlite3\n```\n\n```bash [yarn]\nyarn add @riavzon\u002Fbot-detector express cookie-parser better-sqlite3\n```\n\n\n```bash [bun]\nbun add @riavzon\u002Fbot-detector express cookie-parser better-sqlite3\n```\n::\n\nReplace `better-sqlite3` with your preferred driver. See [Database Drivers](#database-drivers) for the full list and their peer dependencies.\n\n#### Initialize data sources\n\nRun the `init` command to download and compile the threat intelligence databases. This step is required before the middleware can run.\n\n::code-group\n\n```bash [npm]\nnpx @riavzon\u002Fbot-detector init\n```\n\n```bash [pnpm]\npnpm dlx @riavzon\u002Fbot-detector init\n```\n\n```bash [yarn]\nyarn dlx @riavzon\u002Fbot-detector init\n```\n\n\n```bash [bun]\nbunx @riavzon\u002Fbot-detector init\n```\n::\n\nThe command verifies that `mmdbctl` is installed (and installs it if not found), prompts for a BGP.tools contact string required to download BGP data, then compiles all data sources in parallel. The compiled databases are written to `_data-sources\u002F` inside the package directory.\n\nTo skip the interactive prompt in CI or automated environments, pass your contact string as a flag:\n\n::code-group\n\n```bash [npm]\nnpx @riavzon\u002Fbot-detector init --contact=\"MyApp - contact@example.com\"\n```\n\n```bash [pnpm]\npnpm dlx @riavzon\u002Fbot-detector init --contact=\"MyApp - contact@example.com\"\n```\n\n```bash [yarn]\nyarn dlx @riavzon\u002Fbot-detector init --contact=\"MyApp - contact@example.com\"\n```\n\n\n```bash [bun]\nbunx @riavzon\u002Fbot-detector init --contact=\"MyApp - contact@example.com\"\n```\n::\n\n#### Configure the middleware\n\nCreate a startup file and call `defineConfiguration` before attaching any middleware to your app. The only required field is `store.main`, which sets the database driver for visitor persistence.\n\n```ts [server.ts]\nimport express from 'express'\nimport cookieParser from 'cookie-parser'\nimport { defineConfiguration, detectBots } from '@riavzon\u002Fbot-detector'\n\nconst app = express()\napp.use(cookieParser())\napp.use(express.json())\n\nawait defineConfiguration({\n  store: {\n    main: { driver: 'sqlite', name: '.\u002Fbot-detector.db' },\n  },\n})\n\napp.use(detectBots())\n\napp.get('\u002F', (req, res) => {\n  res.json({ ok: true, banned: req.botDetection?.banned })\n})\n\napp.listen(3000)\n```\n\n`defineConfiguration` is async and must resolve before you call `detectBots()` or any getter function. Call it exactly once during startup.\n\n#### Create the database tables\n\nRun `load-schema` once after configuration to create the required tables in your database:\n\n\n\n::tabs\n  :::tabs-item{label=\"SQLite\" icon=\"i-lucide-database-zap\"}\n    ::code-group\n\n      ```bash [npm]\n      npx @riavzon\u002Fbot-detector load-schema --db sqlite --db-name=.\u002Fbot-detector.db\n      ```\n\n      ```bash [pnpm]\n      pnpm dlx @riavzon\u002Fbot-detector load-schema --db=sqlite --db-name=.\u002Fbot-detector.db\n      ```\n\n      ```bash [yarn]\n      yarn dlx @riavzon\u002Fbot-detector load-schema --db=sqlite --db-name=.\u002Fbot-detector.db\n      ```\n\n\n      ```bash [bun]\n      bunx @riavzon\u002Fbot-detector load-schema --db=sqlite --db-name=.\u002Fbot-detector.db\n      ```\n    ::\n  :::\n\n  :::tabs-item{label=\"MySql\" icon=\"i-lucide-database\"}\n    ::code-group\n\n      ```bash [npm]\n      npx @riavzon\u002Fbot-detector load-schema --db mysql-pool --db-host=localhost --db-user=root --db-password=secret --db-name=botdb\n      ```\n\n      ```bash [pnpm]\n      pnpm dlx @riavzon\u002Fbot-detector load-schema --db=mysql-pool --db-host=localhost --db-user=root --db-password=secret --db-name=botdb\n      ```\n\n      ```bash [yarn]\n      yarn dlx @riavzon\u002Fbot-detector load-schema --db=mysql-pool --db-host=localhost --db-user=root --db-password=secret --db-name=botdb\n      ```\n\n\n      ```bash [bun]\n      bunx @riavzon\u002Fbot-detector load-schema --db=mysql-pool --db-host=localhost --db-user=root --db-password=secret --db-name=botdb\n      ```\n    ::\n  :::\n\n  :::tabs-item{label=\"PostgreSQL\" icon=\"i-lucide-server\"}\n    ::code-group\n\n      ```bash [npm]\n      npx @riavzon\u002Fbot-detector load-schema --db postgresql --db-host=localhost --db-user=postgres --db-password=secret --db-name=botdb\n      ```\n\n      ```bash [pnpm]\n      pnpm dlx @riavzon\u002Fbot-detector load-schema --db=postgresql --db-host=localhost --db-user=postgres --db-password=secret --db-name=botdb\n      ```\n\n      ```bash [yarn]\n      yarn dlx @riavzon\u002Fbot-detector load-schema --db=postgresql --db-host=localhost --db-user=postgres --db-password=secret --db-name=botdb\n      ```\n\n\n      ```bash [bun]\n      bunx @riavzon\u002Fbot-detector load-schema --db=postgresql --db-host=localhost --db-user=postgres --db-password=secret --db-name=botdb\n      ```\n    ::\n  :::\n\n  :::tabs-item{label=\"Cloudflare D1\" icon=\"i-lucide-cloud\"}\n    ::code-group\n\n      ```bash [npm]\n      npx @riavzon\u002Fbot-detector load-schema --db cloudflare-d1 --db-name=my-d1-binding\n      ```\n\n      ```bash [pnpm]\n      pnpm dlx @riavzon\u002Fbot-detector load-schema --db=cloudflare-d1 --db-name=my-d1-binding\n      ```\n\n      ```bash [yarn]\n      yarn dlx @riavzon\u002Fbot-detector load-schema --db=cloudflare-d1 --db-name=my-d1-binding\n      ```\n\n\n      ```bash [bun]\n      bunx @riavzon\u002Fbot-detector load-schema --db=cloudflare-d1 --db-name=my-d1-binding\n      ```\n    ::\n  :::\n\n  :::tabs-item{label=\"PlanetScale\" icon=\"i-lucide-globe\"}\n    ::code-group\n\n      ```bash [npm]\n      npx @riavzon\u002Fbot-detector load-schema --db planetscale --db-url=\"mysql:\u002F\u002F\u003Cuser>:\u003Cpass>@\u003Chost>\u002F\u003Cdb>\"\n      ```\n\n      ```bash [pnpm]\n      pnpm dlx @riavzon\u002Fbot-detector load-schema --db=planetscale --db-url=\"mysql:\u002F\u002F\u003Cuser>:\u003Cpass>@\u003Chost>\u002F\u003Cdb>\"\n      ```\n\n      ```bash [yarn]\n      yarn dlx @riavzon\u002Fbot-detector load-schema --db=planetscale --db-url=\"mysql:\u002F\u002F\u003Cuser>:\u003Cpass>@\u003Chost>\u002F\u003Cdb>\"\n      ```\n\n\n      ```bash [bun]\n      bunx @riavzon\u002Fbot-detector load-schema --db=planetscale --db-url=\"mysql:\u002F\u002F\u003Cuser>:\u003Cpass>@\u003Chost>\u002F\u003Cdb>\"\n      ```\n    ::\n  :::\n::\n\n\nYou can also call it programmatically with `createTables(db)`. Pass `getDb()` to provide the initialized instance, call this after `defineConfiguration` resolves:\n\n```ts\nimport { defineConfiguration, createTables, getDb } from '@riavzon\u002Fbot-detector';\n\nawait defineConfiguration({\n  store: {\n    main: { driver: 'sqlite', name: '.\u002Fbot-detector.db' },\n  },\n});\n\n\u002F\u002F createTables expects a Database instance, pass getDb()\nawait createTables(getDb());\n\n```\n\n::note\nRun `load-schema` before starting the server for the first time. It is safe to skip on subsequent restarts.\n::\n\n#### Schedule data source refreshes\n\nThreat intelligence data degrades over time. Run `refresh` at least once every 24 hours to redownload and recompile the latest feeds:\n\n::code-group\n\n```bash [npm]\nnpx @riavzon\u002Fbot-detector refresh\n```\n\n```bash [pnpm]\npnpm dlx @riavzon\u002Fbot-detector refresh\n```\n\n```bash [yarn]\nyarn dlx @riavzon\u002Fbot-detector refresh\n```\n\n\n```bash [bun]\nbunx @riavzon\u002Fbot-detector refresh\n```\n::\n\nAdd this command to a cron job or a CI\u002FCD pipeline to keep the data current.\n\n::\n\n## Database Drivers\n\nThe `store.main` field accepts the following drivers. Each requires the corresponding peer dependency to be installed separately.\n\n| Driver | Value | Peer Dependency |\n| --- | --- | --- |\n| SQLite | `sqlite` | `better-sqlite3` |\n| MySQL pool | `mysql-pool` | `mysql2 >= 3` |\n| PostgreSQL | `postgresql` | `pg` |\n| Cloudflare D1 | `cloudflare-d1` | Worker environment binding |\n| PlanetScale | `planetscale` | Serverless driver |\n\n```ts [server.ts]\n\u002F\u002F SQLite\n{ driver: 'sqlite', name: '.\u002Fbot-detector.db' }\n\n\u002F\u002F MySQL pool\n{ driver: 'mysql-pool', host: 'localhost', user: 'root', password: 'secret', database: 'mydb' }\n\n\u002F\u002F PostgreSQL\n{ driver: 'postgresql', connectionString: 'postgres:\u002F\u002Fuser:pass@localhost\u002Fmydb' }\n```\n\n## Cache Drivers\n\nBy default, visitor state and behavioral data are stored in memory. This works for single-process deployments. For multi-process or distributed deployments, configure a shared `storage` driver so all instances share the same visitor cache.\n\n```ts [server.ts]\nawait defineConfiguration({\n  store: { main: { driver: 'sqlite', name: '.\u002Fbot-detector.db' } },\n  storage: { driver: 'redis', host: 'localhost', port: 6379 },\n})\n```\n\n| Driver | Value | Notes |\n| --- | --- | --- |\n| Memory (default) | *(omit `storage`)* | Single-process only |\n| LRU cache | `lru` | In-process LRU; set `max` and `ttl` |\n| Redis | `redis` | Shared across instances |\n| Upstash Redis | `upstash` | Serverless Redis via HTTP |\n| Filesystem | `fs` | Local persistent storage for development |\n| Cloudflare KV (binding) | `cloudflare-kv-binding` | Pass `binding` |\n| Cloudflare KV (HTTP) | `cloudflare-kv-http` | Pass `accountId`, `namespaceId`, `apiToken` |\n| Cloudflare R2 | `cloudflare-r2-binding` | Pass `binding` |\n| Vercel | `vercel` | Vercel Runtime Cache |\n",{"title":14,"description":2914},"5XpVScQHWRjmxpTQQUkhBkRr7coriqvCqUnqNcmheIU",[2922,2923],{"title":70,"path":35,"stem":71,"children":-1},{"title":78,"path":79,"stem":80,"children":-1},{"id":830,"title":14,"body":2925,"description":2914,"extension":2915,"icon":15,"meta":4616,"module":2917,"navigation":8,"path":75,"rawbody":2918,"seo":4617,"stem":76,"__hash__":2920},{"type":832,"value":2926,"toc":4609},[2927,2931,2933,2935,2957,2967,2969,2973,3019,3025,3033,3035,3037,4203,4205,4209,4279,4387,4389,4393,4487,4607],[835,2928,2929,841],{},[838,2930,840],{},[843,2932,846],{"id":845},[835,2934,849],{},[851,2936,2937,2941,2945,2949],{},[854,2938,2939],{},[857,2940,859],{},[854,2942,2943],{},[857,2944,864],{},[854,2946,2947,870],{},[857,2948,869],{},[854,2950,2951,878,2955,882],{},[857,2952,2953],{},[838,2954,877],{},[838,2956,881],{},[884,2958,2959],{},[835,2960,888,2961,892,2963,896,2965,900],{},[838,2962,891],{},[838,2964,895],{},[838,2966,899],{},[843,2968,904],{"id":903},[835,2970,907,2971,911],{},[838,2972,910],{},[913,2974,2975,2985,2997,3009],{},[916,2976,2977],{"className":918,"code":919,"filename":920,"language":921,"meta":922,"style":922},[838,2978,2979],{"__ignoreMap":922},[926,2980,2981,2983],{"class":928,"line":929},[926,2982,933],{"class":932},[926,2984,937],{"class":936},[916,2986,2987],{"className":918,"code":940,"filename":941,"language":921,"meta":922,"style":922},[838,2988,2989],{"__ignoreMap":922},[926,2990,2991,2993,2995],{"class":928,"line":929},[926,2992,941],{"class":932},[926,2994,950],{"class":936},[926,2996,937],{"class":936},[916,2998,2999],{"className":918,"code":955,"filename":956,"language":921,"meta":922,"style":922},[838,3000,3001],{"__ignoreMap":922},[926,3002,3003,3005,3007],{"class":928,"line":929},[926,3004,956],{"class":932},[926,3006,950],{"class":936},[926,3008,937],{"class":936},[916,3010,3011],{"className":918,"code":969,"filename":970,"language":921,"meta":922,"style":922},[838,3012,3013],{"__ignoreMap":922},[926,3014,3015,3017],{"class":928,"line":929},[926,3016,977],{"class":932},[926,3018,937],{"class":936},[835,3020,982,3021,986,3023,990],{},[838,3022,985],{},[838,3024,989],{},[992,3026,3027],{},[835,3028,996,3029,999,3031,1005],{},[838,3030,910],{},[1001,3032,1004],{"href":1003},[843,3034,1009],{"id":1008},[835,3036,1012],{},[1014,3038,3039,3041,3047,3121,3127,3129,3133,3187,3193,3195,3281,3283,3289,3559,3565,3567,3571,4015,4023,4135,4141,4143,4147,4201],{"level":1016},[1018,3040,1021],{"id":1020},[835,3042,1024,3043,1027,3045,1031],{},[838,3044,840],{},[838,3046,1030],{},[913,3048,3049,3067,3085,3103],{},[916,3050,3051],{"className":918,"code":1036,"filename":920,"language":921,"meta":922,"style":922},[838,3052,3053],{"__ignoreMap":922},[926,3054,3055,3057,3059,3061,3063,3065],{"class":928,"line":929},[926,3056,920],{"class":932},[926,3058,1045],{"class":936},[926,3060,1048],{"class":936},[926,3062,1051],{"class":936},[926,3064,1054],{"class":936},[926,3066,1057],{"class":936},[916,3068,3069],{"className":918,"code":1060,"filename":941,"language":921,"meta":922,"style":922},[838,3070,3071],{"__ignoreMap":922},[926,3072,3073,3075,3077,3079,3081,3083],{"class":928,"line":929},[926,3074,941],{"class":932},[926,3076,1069],{"class":936},[926,3078,1048],{"class":936},[926,3080,1051],{"class":936},[926,3082,1054],{"class":936},[926,3084,1057],{"class":936},[916,3086,3087],{"className":918,"code":1080,"filename":956,"language":921,"meta":922,"style":922},[838,3088,3089],{"__ignoreMap":922},[926,3090,3091,3093,3095,3097,3099,3101],{"class":928,"line":929},[926,3092,956],{"class":932},[926,3094,1069],{"class":936},[926,3096,1048],{"class":936},[926,3098,1051],{"class":936},[926,3100,1054],{"class":936},[926,3102,1057],{"class":936},[916,3104,3105],{"className":918,"code":1099,"filename":970,"language":921,"meta":922,"style":922},[838,3106,3107],{"__ignoreMap":922},[926,3108,3109,3111,3113,3115,3117,3119],{"class":928,"line":929},[926,3110,970],{"class":932},[926,3112,1069],{"class":936},[926,3114,1048],{"class":936},[926,3116,1051],{"class":936},[926,3118,1054],{"class":936},[926,3120,1057],{"class":936},[835,3122,1118,3123,1121,3125,1126],{},[838,3124,989],{},[1001,3126,1125],{"href":1124},[1018,3128,1130],{"id":1129},[835,3130,1133,3131,1136],{},[838,3132,881],{},[913,3134,3135,3147,3161,3175],{},[916,3136,3137],{"className":918,"code":1141,"filename":920,"language":921,"meta":922,"style":922},[838,3138,3139],{"__ignoreMap":922},[926,3140,3141,3143,3145],{"class":928,"line":929},[926,3142,933],{"class":932},[926,3144,1048],{"class":936},[926,3146,1152],{"class":936},[916,3148,3149],{"className":918,"code":1155,"filename":941,"language":921,"meta":922,"style":922},[838,3150,3151],{"__ignoreMap":922},[926,3152,3153,3155,3157,3159],{"class":928,"line":929},[926,3154,941],{"class":932},[926,3156,950],{"class":936},[926,3158,1048],{"class":936},[926,3160,1152],{"class":936},[916,3162,3163],{"className":918,"code":1170,"filename":956,"language":921,"meta":922,"style":922},[838,3164,3165],{"__ignoreMap":922},[926,3166,3167,3169,3171,3173],{"class":928,"line":929},[926,3168,956],{"class":932},[926,3170,950],{"class":936},[926,3172,1048],{"class":936},[926,3174,1152],{"class":936},[916,3176,3177],{"className":918,"code":1185,"filename":970,"language":921,"meta":922,"style":922},[838,3178,3179],{"__ignoreMap":922},[926,3180,3181,3183,3185],{"class":928,"line":929},[926,3182,977],{"class":932},[926,3184,1048],{"class":936},[926,3186,1152],{"class":936},[835,3188,1198,3189,1201,3191,1205],{},[838,3190,877],{},[838,3192,1204],{},[835,3194,1208],{},[913,3196,3197,3217,3239,3261],{},[916,3198,3199],{"className":918,"code":1213,"filename":920,"language":921,"meta":922,"style":922},[838,3200,3201],{"__ignoreMap":922},[926,3202,3203,3205,3207,3209,3211,3213,3215],{"class":928,"line":929},[926,3204,933],{"class":932},[926,3206,1048],{"class":936},[926,3208,1224],{"class":936},[926,3210,1228],{"class":1227},[926,3212,1232],{"class":1231},[926,3214,1235],{"class":936},[926,3216,1238],{"class":1231},[916,3218,3219],{"className":918,"code":1241,"filename":941,"language":921,"meta":922,"style":922},[838,3220,3221],{"__ignoreMap":922},[926,3222,3223,3225,3227,3229,3231,3233,3235,3237],{"class":928,"line":929},[926,3224,941],{"class":932},[926,3226,950],{"class":936},[926,3228,1048],{"class":936},[926,3230,1224],{"class":936},[926,3232,1228],{"class":1227},[926,3234,1232],{"class":1231},[926,3236,1235],{"class":936},[926,3238,1238],{"class":1231},[916,3240,3241],{"className":918,"code":1264,"filename":956,"language":921,"meta":922,"style":922},[838,3242,3243],{"__ignoreMap":922},[926,3244,3245,3247,3249,3251,3253,3255,3257,3259],{"class":928,"line":929},[926,3246,956],{"class":932},[926,3248,950],{"class":936},[926,3250,1048],{"class":936},[926,3252,1224],{"class":936},[926,3254,1228],{"class":1227},[926,3256,1232],{"class":1231},[926,3258,1235],{"class":936},[926,3260,1238],{"class":1231},[916,3262,3263],{"className":918,"code":1287,"filename":970,"language":921,"meta":922,"style":922},[838,3264,3265],{"__ignoreMap":922},[926,3266,3267,3269,3271,3273,3275,3277,3279],{"class":928,"line":929},[926,3268,977],{"class":932},[926,3270,1048],{"class":936},[926,3272,1224],{"class":936},[926,3274,1228],{"class":1227},[926,3276,1232],{"class":1231},[926,3278,1235],{"class":936},[926,3280,1238],{"class":1231},[1018,3282,1309],{"id":1308},[835,3284,1312,3285,1316,3287,1320],{},[838,3286,1315],{},[838,3288,1319],{},[916,3290,3291],{"className":1323,"code":1324,"filename":1325,"language":1326,"meta":922,"style":922},[838,3292,3293,3307,3321,3343,3347,3359,3373,3391,3395,3403,3411,3443,3447,3451,3455,3469,3473,3503,3537,3541,3545],{"__ignoreMap":922},[926,3294,3295,3297,3299,3301,3303,3305],{"class":928,"line":929},[926,3296,1334],{"class":1333},[926,3298,1051],{"class":1337},[926,3300,1340],{"class":1333},[926,3302,1343],{"class":1231},[926,3304,1346],{"class":936},[926,3306,1349],{"class":1231},[926,3308,3309,3311,3313,3315,3317,3319],{"class":928,"line":1352},[926,3310,1334],{"class":1333},[926,3312,1357],{"class":1337},[926,3314,1340],{"class":1333},[926,3316,1343],{"class":1231},[926,3318,1030],{"class":936},[926,3320,1349],{"class":1231},[926,3322,3323,3325,3327,3329,3331,3333,3335,3337,3339,3341],{"class":928,"line":1368},[926,3324,1334],{"class":1333},[926,3326,1374],{"class":1373},[926,3328,1315],{"class":1337},[926,3330,1379],{"class":1373},[926,3332,1382],{"class":1337},[926,3334,1385],{"class":1373},[926,3336,1388],{"class":1333},[926,3338,1343],{"class":1231},[926,3340,840],{"class":936},[926,3342,1349],{"class":1231},[926,3344,3345],{"class":928,"line":1397},[926,3346,1400],{"emptyLinePlaceholder":8},[926,3348,3349,3351,3353,3355,3357],{"class":928,"line":1403},[926,3350,1407],{"class":1406},[926,3352,1411],{"class":1410},[926,3354,1415],{"class":1414},[926,3356,1051],{"class":932},[926,3358,1420],{"class":1373},[926,3360,3361,3363,3365,3367,3369,3371],{"class":928,"line":1423},[926,3362,1426],{"class":1337},[926,3364,1429],{"class":1373},[926,3366,1432],{"class":932},[926,3368,1435],{"class":1373},[926,3370,1438],{"class":932},[926,3372,1441],{"class":1373},[926,3374,3375,3377,3379,3381,3383,3385,3387,3389],{"class":928,"line":1444},[926,3376,1426],{"class":1337},[926,3378,1429],{"class":1373},[926,3380,1432],{"class":932},[926,3382,1435],{"class":1373},[926,3384,1346],{"class":1337},[926,3386,1429],{"class":1373},[926,3388,5],{"class":932},[926,3390,1441],{"class":1373},[926,3392,3393],{"class":928,"line":1463},[926,3394,1400],{"emptyLinePlaceholder":8},[926,3396,3397,3399,3401],{"class":928,"line":1468},[926,3398,1471],{"class":1333},[926,3400,1474],{"class":932},[926,3402,1477],{"class":1373},[926,3404,3405,3407,3409],{"class":928,"line":1480},[926,3406,1483],{"class":1337},[926,3408,1487],{"class":1486},[926,3410,1490],{"class":1373},[926,3412,3413,3415,3417,3419,3421,3423,3425,3427,3429,3431,3433,3435,3437,3439,3441],{"class":928,"line":1493},[926,3414,1496],{"class":1337},[926,3416,1487],{"class":1486},[926,3418,1374],{"class":1373},[926,3420,1503],{"class":1337},[926,3422,1487],{"class":1486},[926,3424,1343],{"class":1231},[926,3426,1510],{"class":936},[926,3428,1513],{"class":1231},[926,3430,1379],{"class":1373},[926,3432,1518],{"class":1337},[926,3434,1487],{"class":1486},[926,3436,1343],{"class":1231},[926,3438,1525],{"class":936},[926,3440,1513],{"class":1231},[926,3442,1530],{"class":1373},[926,3444,3445],{"class":928,"line":1533},[926,3446,1536],{"class":1373},[926,3448,3449],{"class":928,"line":1539},[926,3450,1542],{"class":1373},[926,3452,3453],{"class":928,"line":1545},[926,3454,1400],{"emptyLinePlaceholder":8},[926,3456,3457,3459,3461,3463,3465,3467],{"class":928,"line":1550},[926,3458,1426],{"class":1337},[926,3460,1429],{"class":1373},[926,3462,1432],{"class":932},[926,3464,1435],{"class":1373},[926,3466,1382],{"class":932},[926,3468,1441],{"class":1373},[926,3470,3471],{"class":928,"line":1565},[926,3472,1400],{"emptyLinePlaceholder":8},[926,3474,3475,3477,3479,3481,3483,3485,3487,3489,3491,3493,3495,3497,3499,3501],{"class":928,"line":1570},[926,3476,1426],{"class":1337},[926,3478,1429],{"class":1373},[926,3480,1577],{"class":932},[926,3482,1435],{"class":1373},[926,3484,1513],{"class":1231},[926,3486,1584],{"class":936},[926,3488,1513],{"class":1231},[926,3490,1589],{"class":1373},[926,3492,1593],{"class":1592},[926,3494,1379],{"class":1373},[926,3496,1598],{"class":1592},[926,3498,1601],{"class":1373},[926,3500,1604],{"class":1406},[926,3502,1490],{"class":1373},[926,3504,3505,3507,3509,3511,3513,3515,3517,3519,3521,3523,3525,3527,3529,3531,3533,3535],{"class":928,"line":1609},[926,3506,1612],{"class":1337},[926,3508,1429],{"class":1373},[926,3510,5],{"class":932},[926,3512,1619],{"class":1373},[926,3514,1622],{"class":1337},[926,3516,1487],{"class":1486},[926,3518,1627],{"class":1227},[926,3520,1379],{"class":1373},[926,3522,1632],{"class":1337},[926,3524,1487],{"class":1486},[926,3526,1637],{"class":1337},[926,3528,1429],{"class":1373},[926,3530,1642],{"class":1337},[926,3532,1645],{"class":1373},[926,3534,1632],{"class":1337},[926,3536,1650],{"class":1373},[926,3538,3539],{"class":928,"line":1653},[926,3540,1542],{"class":1373},[926,3542,3543],{"class":928,"line":1658},[926,3544,1400],{"emptyLinePlaceholder":8},[926,3546,3547,3549,3551,3553,3555,3557],{"class":928,"line":1663},[926,3548,1426],{"class":1337},[926,3550,1429],{"class":1373},[926,3552,1670],{"class":932},[926,3554,1435],{"class":1373},[926,3556,1676],{"class":1675},[926,3558,1679],{"class":1373},[835,3560,3561,1684,3563,1688],{},[838,3562,1315],{},[838,3564,1687],{},[1018,3566,1692],{"id":1691},[835,3568,1695,3569,1699],{},[838,3570,1698],{},[1701,3572,3573,3647,3745,3843,3917],{},[1704,3574,3575],{"icon":41,"label":1706},[913,3576,3577,3595,3613,3631],{},[916,3578,3579],{"className":918,"code":1711,"filename":920,"language":921,"meta":922,"style":922},[838,3580,3581],{"__ignoreMap":922},[926,3582,3583,3585,3587,3589,3591,3593],{"class":928,"line":929},[926,3584,933],{"class":932},[926,3586,1048],{"class":936},[926,3588,1722],{"class":936},[926,3590,1725],{"class":1227},[926,3592,1728],{"class":936},[926,3594,1731],{"class":1227},[916,3596,3597],{"className":918,"code":1734,"filename":941,"language":921,"meta":922,"style":922},[838,3598,3599],{"__ignoreMap":922},[926,3600,3601,3603,3605,3607,3609,3611],{"class":928,"line":929},[926,3602,941],{"class":932},[926,3604,950],{"class":936},[926,3606,1048],{"class":936},[926,3608,1722],{"class":936},[926,3610,1749],{"class":1227},[926,3612,1731],{"class":1227},[916,3614,3615],{"className":918,"code":1754,"filename":956,"language":921,"meta":922,"style":922},[838,3616,3617],{"__ignoreMap":922},[926,3618,3619,3621,3623,3625,3627,3629],{"class":928,"line":929},[926,3620,956],{"class":932},[926,3622,950],{"class":936},[926,3624,1048],{"class":936},[926,3626,1722],{"class":936},[926,3628,1749],{"class":1227},[926,3630,1731],{"class":1227},[916,3632,3633],{"className":918,"code":1773,"filename":970,"language":921,"meta":922,"style":922},[838,3634,3635],{"__ignoreMap":922},[926,3636,3637,3639,3641,3643,3645],{"class":928,"line":929},[926,3638,977],{"class":932},[926,3640,1048],{"class":936},[926,3642,1722],{"class":936},[926,3644,1749],{"class":1227},[926,3646,1731],{"class":1227},[1704,3648,3649],{"icon":1790,"label":1791},[913,3650,3651,3675,3699,3723],{},[916,3652,3653],{"className":918,"code":1796,"filename":920,"language":921,"meta":922,"style":922},[838,3654,3655],{"__ignoreMap":922},[926,3656,3657,3659,3661,3663,3665,3667,3669,3671,3673],{"class":928,"line":929},[926,3658,933],{"class":932},[926,3660,1048],{"class":936},[926,3662,1722],{"class":936},[926,3664,1725],{"class":1227},[926,3666,1811],{"class":936},[926,3668,1814],{"class":1227},[926,3670,1817],{"class":1227},[926,3672,1820],{"class":1227},[926,3674,1823],{"class":1227},[916,3676,3677],{"className":918,"code":1826,"filename":941,"language":921,"meta":922,"style":922},[838,3678,3679],{"__ignoreMap":922},[926,3680,3681,3683,3685,3687,3689,3691,3693,3695,3697],{"class":928,"line":929},[926,3682,941],{"class":932},[926,3684,950],{"class":936},[926,3686,1048],{"class":936},[926,3688,1722],{"class":936},[926,3690,1841],{"class":1227},[926,3692,1814],{"class":1227},[926,3694,1817],{"class":1227},[926,3696,1820],{"class":1227},[926,3698,1823],{"class":1227},[916,3700,3701],{"className":918,"code":1852,"filename":956,"language":921,"meta":922,"style":922},[838,3702,3703],{"__ignoreMap":922},[926,3704,3705,3707,3709,3711,3713,3715,3717,3719,3721],{"class":928,"line":929},[926,3706,956],{"class":932},[926,3708,950],{"class":936},[926,3710,1048],{"class":936},[926,3712,1722],{"class":936},[926,3714,1841],{"class":1227},[926,3716,1814],{"class":1227},[926,3718,1817],{"class":1227},[926,3720,1820],{"class":1227},[926,3722,1823],{"class":1227},[916,3724,3725],{"className":918,"code":1877,"filename":970,"language":921,"meta":922,"style":922},[838,3726,3727],{"__ignoreMap":922},[926,3728,3729,3731,3733,3735,3737,3739,3741,3743],{"class":928,"line":929},[926,3730,977],{"class":932},[926,3732,1048],{"class":936},[926,3734,1722],{"class":936},[926,3736,1841],{"class":1227},[926,3738,1814],{"class":1227},[926,3740,1817],{"class":1227},[926,3742,1820],{"class":1227},[926,3744,1823],{"class":1227},[1704,3746,3747],{"icon":1900,"label":1901},[913,3748,3749,3773,3797,3821],{},[916,3750,3751],{"className":918,"code":1906,"filename":920,"language":921,"meta":922,"style":922},[838,3752,3753],{"__ignoreMap":922},[926,3754,3755,3757,3759,3761,3763,3765,3767,3769,3771],{"class":928,"line":929},[926,3756,933],{"class":932},[926,3758,1048],{"class":936},[926,3760,1722],{"class":936},[926,3762,1725],{"class":1227},[926,3764,1921],{"class":936},[926,3766,1814],{"class":1227},[926,3768,1926],{"class":1227},[926,3770,1820],{"class":1227},[926,3772,1823],{"class":1227},[916,3774,3775],{"className":918,"code":1933,"filename":941,"language":921,"meta":922,"style":922},[838,3776,3777],{"__ignoreMap":922},[926,3778,3779,3781,3783,3785,3787,3789,3791,3793,3795],{"class":928,"line":929},[926,3780,941],{"class":932},[926,3782,950],{"class":936},[926,3784,1048],{"class":936},[926,3786,1722],{"class":936},[926,3788,1948],{"class":1227},[926,3790,1814],{"class":1227},[926,3792,1926],{"class":1227},[926,3794,1820],{"class":1227},[926,3796,1823],{"class":1227},[916,3798,3799],{"className":918,"code":1959,"filename":956,"language":921,"meta":922,"style":922},[838,3800,3801],{"__ignoreMap":922},[926,3802,3803,3805,3807,3809,3811,3813,3815,3817,3819],{"class":928,"line":929},[926,3804,956],{"class":932},[926,3806,950],{"class":936},[926,3808,1048],{"class":936},[926,3810,1722],{"class":936},[926,3812,1948],{"class":1227},[926,3814,1814],{"class":1227},[926,3816,1926],{"class":1227},[926,3818,1820],{"class":1227},[926,3820,1823],{"class":1227},[916,3822,3823],{"className":918,"code":1984,"filename":970,"language":921,"meta":922,"style":922},[838,3824,3825],{"__ignoreMap":922},[926,3826,3827,3829,3831,3833,3835,3837,3839,3841],{"class":928,"line":929},[926,3828,977],{"class":932},[926,3830,1048],{"class":936},[926,3832,1722],{"class":936},[926,3834,1948],{"class":1227},[926,3836,1814],{"class":1227},[926,3838,1926],{"class":1227},[926,3840,1820],{"class":1227},[926,3842,1823],{"class":1227},[1704,3844,3845],{"icon":2007,"label":2008},[913,3846,3847,3865,3883,3901],{},[916,3848,3849],{"className":918,"code":2013,"filename":920,"language":921,"meta":922,"style":922},[838,3850,3851],{"__ignoreMap":922},[926,3852,3853,3855,3857,3859,3861,3863],{"class":928,"line":929},[926,3854,933],{"class":932},[926,3856,1048],{"class":936},[926,3858,1722],{"class":936},[926,3860,1725],{"class":1227},[926,3862,2028],{"class":936},[926,3864,2031],{"class":1227},[916,3866,3867],{"className":918,"code":2034,"filename":941,"language":921,"meta":922,"style":922},[838,3868,3869],{"__ignoreMap":922},[926,3870,3871,3873,3875,3877,3879,3881],{"class":928,"line":929},[926,3872,941],{"class":932},[926,3874,950],{"class":936},[926,3876,1048],{"class":936},[926,3878,1722],{"class":936},[926,3880,2049],{"class":1227},[926,3882,2031],{"class":1227},[916,3884,3885],{"className":918,"code":2054,"filename":956,"language":921,"meta":922,"style":922},[838,3886,3887],{"__ignoreMap":922},[926,3888,3889,3891,3893,3895,3897,3899],{"class":928,"line":929},[926,3890,956],{"class":932},[926,3892,950],{"class":936},[926,3894,1048],{"class":936},[926,3896,1722],{"class":936},[926,3898,2049],{"class":1227},[926,3900,2031],{"class":1227},[916,3902,3903],{"className":918,"code":2073,"filename":970,"language":921,"meta":922,"style":922},[838,3904,3905],{"__ignoreMap":922},[926,3906,3907,3909,3911,3913,3915],{"class":928,"line":929},[926,3908,977],{"class":932},[926,3910,1048],{"class":936},[926,3912,1722],{"class":936},[926,3914,2049],{"class":1227},[926,3916,2031],{"class":1227},[1704,3918,3919],{"icon":2090,"label":2091},[913,3920,3921,3945,3969,3993],{},[916,3922,3923],{"className":918,"code":2096,"filename":920,"language":921,"meta":922,"style":922},[838,3924,3925],{"__ignoreMap":922},[926,3926,3927,3929,3931,3933,3935,3937,3939,3941,3943],{"class":928,"line":929},[926,3928,933],{"class":932},[926,3930,1048],{"class":936},[926,3932,1722],{"class":936},[926,3934,1725],{"class":1227},[926,3936,2111],{"class":936},[926,3938,2114],{"class":1227},[926,3940,1232],{"class":1231},[926,3942,2119],{"class":936},[926,3944,1238],{"class":1231},[916,3946,3947],{"className":918,"code":2124,"filename":941,"language":921,"meta":922,"style":922},[838,3948,3949],{"__ignoreMap":922},[926,3950,3951,3953,3955,3957,3959,3961,3963,3965,3967],{"class":928,"line":929},[926,3952,941],{"class":932},[926,3954,950],{"class":936},[926,3956,1048],{"class":936},[926,3958,1722],{"class":936},[926,3960,2139],{"class":1227},[926,3962,2114],{"class":1227},[926,3964,1232],{"class":1231},[926,3966,2119],{"class":936},[926,3968,1238],{"class":1231},[916,3970,3971],{"className":918,"code":2150,"filename":956,"language":921,"meta":922,"style":922},[838,3972,3973],{"__ignoreMap":922},[926,3974,3975,3977,3979,3981,3983,3985,3987,3989,3991],{"class":928,"line":929},[926,3976,956],{"class":932},[926,3978,950],{"class":936},[926,3980,1048],{"class":936},[926,3982,1722],{"class":936},[926,3984,2139],{"class":1227},[926,3986,2114],{"class":1227},[926,3988,1232],{"class":1231},[926,3990,2119],{"class":936},[926,3992,1238],{"class":1231},[916,3994,3995],{"className":918,"code":2175,"filename":970,"language":921,"meta":922,"style":922},[838,3996,3997],{"__ignoreMap":922},[926,3998,3999,4001,4003,4005,4007,4009,4011,4013],{"class":928,"line":929},[926,4000,977],{"class":932},[926,4002,1048],{"class":936},[926,4004,1722],{"class":936},[926,4006,2139],{"class":1227},[926,4008,2114],{"class":1227},[926,4010,1232],{"class":1231},[926,4012,2119],{"class":936},[926,4014,1238],{"class":1231},[835,4016,2198,4017,2202,4019,2206,4021,2209],{},[838,4018,2201],{},[838,4020,2205],{},[838,4022,1315],{},[916,4024,4025],{"className":1323,"code":2212,"language":1326,"meta":922,"style":922},[838,4026,4027,4055,4059,4067,4075,4107,4111,4115,4119,4123],{"__ignoreMap":922},[926,4028,4029,4031,4033,4035,4037,4039,4041,4043,4045,4047,4049,4051,4053],{"class":928,"line":929},[926,4030,1334],{"class":1333},[926,4032,1374],{"class":1373},[926,4034,1315],{"class":1337},[926,4036,1379],{"class":1373},[926,4038,2227],{"class":1337},[926,4040,1379],{"class":1373},[926,4042,2232],{"class":1337},[926,4044,1385],{"class":1373},[926,4046,1388],{"class":1333},[926,4048,1343],{"class":1231},[926,4050,840],{"class":936},[926,4052,1513],{"class":1231},[926,4054,2245],{"class":1373},[926,4056,4057],{"class":928,"line":1352},[926,4058,1400],{"emptyLinePlaceholder":8},[926,4060,4061,4063,4065],{"class":928,"line":1368},[926,4062,1471],{"class":1333},[926,4064,1474],{"class":932},[926,4066,1477],{"class":1373},[926,4068,4069,4071,4073],{"class":928,"line":1397},[926,4070,2262],{"class":1337},[926,4072,1487],{"class":1486},[926,4074,1490],{"class":1373},[926,4076,4077,4079,4081,4083,4085,4087,4089,4091,4093,4095,4097,4099,4101,4103,4105],{"class":928,"line":1403},[926,4078,2271],{"class":1337},[926,4080,1487],{"class":1486},[926,4082,1374],{"class":1373},[926,4084,1503],{"class":1337},[926,4086,1487],{"class":1486},[926,4088,1343],{"class":1231},[926,4090,1510],{"class":936},[926,4092,1513],{"class":1231},[926,4094,1379],{"class":1373},[926,4096,1518],{"class":1337},[926,4098,1487],{"class":1486},[926,4100,1343],{"class":1231},[926,4102,1525],{"class":936},[926,4104,1513],{"class":1231},[926,4106,1530],{"class":1373},[926,4108,4109],{"class":928,"line":1423},[926,4110,2304],{"class":1373},[926,4112,4113],{"class":928,"line":1444},[926,4114,2309],{"class":1373},[926,4116,4117],{"class":928,"line":1463},[926,4118,1400],{"emptyLinePlaceholder":8},[926,4120,4121],{"class":928,"line":1468},[926,4122,2319],{"class":2318},[926,4124,4125,4127,4129,4131,4133],{"class":928,"line":1480},[926,4126,1471],{"class":1333},[926,4128,2326],{"class":932},[926,4130,1435],{"class":1373},[926,4132,2232],{"class":932},[926,4134,2333],{"class":1373},[2335,4136,4137],{},[835,4138,1695,4139,2341],{},[838,4140,1698],{},[1018,4142,2345],{"id":2344},[835,4144,2348,4145,2352],{},[838,4146,2351],{},[913,4148,4149,4161,4175,4189],{},[916,4150,4151],{"className":918,"code":2357,"filename":920,"language":921,"meta":922,"style":922},[838,4152,4153],{"__ignoreMap":922},[926,4154,4155,4157,4159],{"class":928,"line":929},[926,4156,933],{"class":932},[926,4158,1048],{"class":936},[926,4160,2368],{"class":936},[916,4162,4163],{"className":918,"code":2371,"filename":941,"language":921,"meta":922,"style":922},[838,4164,4165],{"__ignoreMap":922},[926,4166,4167,4169,4171,4173],{"class":928,"line":929},[926,4168,941],{"class":932},[926,4170,950],{"class":936},[926,4172,1048],{"class":936},[926,4174,2368],{"class":936},[916,4176,4177],{"className":918,"code":2386,"filename":956,"language":921,"meta":922,"style":922},[838,4178,4179],{"__ignoreMap":922},[926,4180,4181,4183,4185,4187],{"class":928,"line":929},[926,4182,956],{"class":932},[926,4184,950],{"class":936},[926,4186,1048],{"class":936},[926,4188,2368],{"class":936},[916,4190,4191],{"className":918,"code":2401,"filename":970,"language":921,"meta":922,"style":922},[838,4192,4193],{"__ignoreMap":922},[926,4194,4195,4197,4199],{"class":928,"line":929},[926,4196,977],{"class":932},[926,4198,1048],{"class":936},[926,4200,2368],{"class":936},[835,4202,2414],{},[843,4204,1125],{"id":2417},[835,4206,888,4207,2422],{},[838,4208,1319],{},[2424,4210,4211,4221],{},[2427,4212,4213],{},[2430,4214,4215,4217,4219],{},[2433,4216,2435],{},[2433,4218,2438],{},[2433,4220,2441],{},[2443,4222,4223,4235,4247,4259,4269],{},[2430,4224,4225,4227,4231],{},[2448,4226,1706],{},[2448,4228,4229],{},[838,4230,1510],{},[2448,4232,4233],{},[838,4234,989],{},[2430,4236,4237,4239,4243],{},[2448,4238,2462],{},[2448,4240,4241],{},[838,4242,2467],{},[2448,4244,4245],{},[838,4246,2472],{},[2430,4248,4249,4251,4255],{},[2448,4250,1901],{},[2448,4252,4253],{},[838,4254,2481],{},[2448,4256,4257],{},[838,4258,2486],{},[2430,4260,4261,4263,4267],{},[2448,4262,2008],{},[2448,4264,4265],{},[838,4266,2495],{},[2448,4268,2498],{},[2430,4270,4271,4273,4277],{},[2448,4272,2091],{},[2448,4274,4275],{},[838,4276,2507],{},[2448,4278,2510],{},[916,4280,4281],{"className":1323,"code":2513,"filename":1325,"language":1326,"meta":922,"style":922},[838,4282,4283,4287,4307,4311,4315,4359,4363,4367],{"__ignoreMap":922},[926,4284,4285],{"class":928,"line":929},[926,4286,2520],{"class":2318},[926,4288,4289,4291,4293,4295,4297,4299,4301,4303,4305],{"class":928,"line":1352},[926,4290,2525],{"class":1373},[926,4292,1513],{"class":1231},[926,4294,1510],{"class":936},[926,4296,1513],{"class":1231},[926,4298,2534],{"class":1373},[926,4300,1513],{"class":1231},[926,4302,1525],{"class":936},[926,4304,1513],{"class":1231},[926,4306,2543],{"class":1373},[926,4308,4309],{"class":928,"line":1368},[926,4310,1400],{"emptyLinePlaceholder":8},[926,4312,4313],{"class":928,"line":1397},[926,4314,2552],{"class":2318},[926,4316,4317,4319,4321,4323,4325,4327,4329,4331,4333,4335,4337,4339,4341,4343,4345,4347,4349,4351,4353,4355,4357],{"class":928,"line":1403},[926,4318,2525],{"class":1373},[926,4320,1513],{"class":1231},[926,4322,2467],{"class":936},[926,4324,1513],{"class":1231},[926,4326,2565],{"class":1373},[926,4328,1513],{"class":1231},[926,4330,2570],{"class":936},[926,4332,1513],{"class":1231},[926,4334,2575],{"class":1373},[926,4336,1513],{"class":1231},[926,4338,2580],{"class":936},[926,4340,1513],{"class":1231},[926,4342,2585],{"class":1373},[926,4344,1513],{"class":1231},[926,4346,2590],{"class":936},[926,4348,1513],{"class":1231},[926,4350,2595],{"class":1373},[926,4352,1513],{"class":1231},[926,4354,2600],{"class":936},[926,4356,1513],{"class":1231},[926,4358,2543],{"class":1373},[926,4360,4361],{"class":928,"line":1423},[926,4362,1400],{"emptyLinePlaceholder":8},[926,4364,4365],{"class":928,"line":1444},[926,4366,2613],{"class":2318},[926,4368,4369,4371,4373,4375,4377,4379,4381,4383,4385],{"class":928,"line":1463},[926,4370,2525],{"class":1373},[926,4372,1513],{"class":1231},[926,4374,2481],{"class":936},[926,4376,1513],{"class":1231},[926,4378,2626],{"class":1373},[926,4380,1513],{"class":1231},[926,4382,2631],{"class":936},[926,4384,1513],{"class":1231},[926,4386,2543],{"class":1373},[843,4388,2639],{"id":2638},[835,4390,2642,4391,2646],{},[838,4392,2645],{},[916,4394,4395],{"className":1323,"code":2649,"filename":1325,"language":1326,"meta":922,"style":922},[838,4396,4397,4405,4443,4483],{"__ignoreMap":922},[926,4398,4399,4401,4403],{"class":928,"line":929},[926,4400,1471],{"class":1333},[926,4402,1474],{"class":932},[926,4404,1477],{"class":1373},[926,4406,4407,4409,4411,4413,4415,4417,4419,4421,4423,4425,4427,4429,4431,4433,4435,4437,4439,4441],{"class":928,"line":1352},[926,4408,1483],{"class":1337},[926,4410,1487],{"class":1486},[926,4412,1374],{"class":1373},[926,4414,2670],{"class":1337},[926,4416,1487],{"class":1486},[926,4418,1374],{"class":1373},[926,4420,1503],{"class":1337},[926,4422,1487],{"class":1486},[926,4424,1343],{"class":1231},[926,4426,1510],{"class":936},[926,4428,1513],{"class":1231},[926,4430,1379],{"class":1373},[926,4432,1518],{"class":1337},[926,4434,1487],{"class":1486},[926,4436,1343],{"class":1231},[926,4438,1525],{"class":936},[926,4440,1513],{"class":1231},[926,4442,2699],{"class":1373},[926,4444,4445,4447,4449,4451,4453,4455,4457,4459,4461,4463,4465,4467,4469,4471,4473,4475,4477,4479,4481],{"class":928,"line":1368},[926,4446,2704],{"class":1337},[926,4448,1487],{"class":1486},[926,4450,1374],{"class":1373},[926,4452,1503],{"class":1337},[926,4454,1487],{"class":1486},[926,4456,1343],{"class":1231},[926,4458,2717],{"class":936},[926,4460,1513],{"class":1231},[926,4462,1379],{"class":1373},[926,4464,2724],{"class":1337},[926,4466,1487],{"class":1486},[926,4468,1343],{"class":1231},[926,4470,2570],{"class":936},[926,4472,1513],{"class":1231},[926,4474,1379],{"class":1373},[926,4476,2737],{"class":1337},[926,4478,1487],{"class":1486},[926,4480,2742],{"class":1675},[926,4482,1530],{"class":1373},[926,4484,4485],{"class":928,"line":1397},[926,4486,1542],{"class":1373},[2424,4488,4489,4499],{},[2427,4490,4491],{},[2430,4492,4493,4495,4497],{},[2433,4494,2435],{},[2433,4496,2438],{},[2433,4498,2761],{},[2443,4500,4501,4513,4527,4537,4547,4557,4569,4585,4597],{},[2430,4502,4503,4505,4511],{},[2448,4504,2768],{},[2448,4506,4507],{},[2772,4508,2774,4509,2777],{},[838,4510,2645],{},[2448,4512,2780],{},[2430,4514,4515,4517,4521],{},[2448,4516,2785],{},[2448,4518,4519],{},[838,4520,2790],{},[2448,4522,2793,4523,2797,4525],{},[838,4524,2796],{},[838,4526,2800],{},[2430,4528,4529,4531,4535],{},[2448,4530,2805],{},[2448,4532,4533],{},[838,4534,2717],{},[2448,4536,2812],{},[2430,4538,4539,4541,4545],{},[2448,4540,2817],{},[2448,4542,4543],{},[838,4544,2822],{},[2448,4546,2825],{},[2430,4548,4549,4551,4555],{},[2448,4550,2830],{},[2448,4552,4553],{},[838,4554,2835],{},[2448,4556,2838],{},[2430,4558,4559,4561,4565],{},[2448,4560,2843],{},[2448,4562,4563],{},[838,4564,2848],{},[2448,4566,2851,4567],{},[838,4568,2854],{},[2430,4570,4571,4573,4577],{},[2448,4572,2859],{},[2448,4574,4575],{},[838,4576,2864],{},[2448,4578,2851,4579,1379,4581,1379,4583],{},[838,4580,2869],{},[838,4582,2872],{},[838,4584,2875],{},[2430,4586,4587,4589,4593],{},[2448,4588,2880],{},[2448,4590,4591],{},[838,4592,2885],{},[2448,4594,2851,4595],{},[838,4596,2854],{},[2430,4598,4599,4601,4605],{},[2448,4600,2894],{},[2448,4602,4603],{},[838,4604,2899],{},[2448,4606,2902],{},[2904,4608,2906],{},{"title":922,"searchDepth":1352,"depth":1352,"links":4610},[4611,4612,4613,4614,4615],{"id":845,"depth":1352,"text":846},{"id":903,"depth":1352,"text":904},{"id":1008,"depth":1352,"text":1009},{"id":2417,"depth":1352,"text":1125},{"id":2638,"depth":1352,"text":2639},{},{"title":14,"description":2914},1780436274295]