{"_id":"@aryanbansal-launch/edge-utils","_rev":"15-7906f810c7ac5da2ae1315fc833e7c5f","name":"@aryanbansal-launch/edge-utils","dist-tags":{"latest":"0.3.0"},"versions":{"0.1.0":{"name":"@aryanbansal-launch/edge-utils","version":"0.1.0","_id":"@aryanbansal-launch/edge-utils@0.1.0","maintainers":[{"name":"aryanbansal-launch","email":"aryan.bansal@contentstack.com"}],"dist":{"shasum":"edc62f493f5c5578e843a5bfb2288d9775d1ec20","tarball":"https://registry.npmjs.org/@aryanbansal-launch/edge-utils/-/edge-utils-0.1.0.tgz","fileCount":11,"integrity":"sha512-6FdQp3I2T8x0jbcZzOB4tmVcpFc4QrxDltzi7RTRArvrBmxIS5dF3lxIMLj9BYiQmX7Ejsv6Vt4cPmp9RVuE+w==","signatures":[{"sig":"MEUCIQDyZv5ycYE9nNYh/7ZjwkF8tUdjJRON4+mZGw/TYj6mLQIgFJ4qA8IKY7YtEST3rgLFrVyI4pGZC5vzy2pVLau7S4I=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":7278},"main":"dist/index.js","type":"module","exports":{".":"./dist/index.js"},"gitHead":"bef7a70daa168f14dc7927f2248045243177b71f","scripts":{"build":"tsc"},"_npmUser":{"name":"aryanbansal-launch","email":"aryan.bansal@contentstack.com"},"_npmVersion":"11.6.0","description":"A collection of high-performance utilities designed for Edge Computing environments (like Cloudflare Workers, Vercel Edge Functions, or Contentstack Launch). These utilities help you handle common tasks like authentication, security, redirection, and geo-","directories":{},"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/edge-utils_0.1.0_1766207697987_0.6632205490194876","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@aryanbansal-launch/edge-utils","version":"0.1.1","license":"MIT","_id":"@aryanbansal-launch/edge-utils@0.1.1","maintainers":[{"name":"aryanbansal-launch","email":"aryan.bansal@contentstack.com"}],"dist":{"shasum":"ae435cbdda7ce54fce7c3874cd8a20670a05fc8e","tarball":"https://registry.npmjs.org/@aryanbansal-launch/edge-utils/-/edge-utils-0.1.1.tgz","fileCount":11,"integrity":"sha512-9XwCy0z/ycvsfpZy8fcDhTnTtYreV+aYaGE6mlgKbB1N8eU8eC0cb6LCFTqF6jpKTw3K9HFwRJCtBAQnmpxejg==","signatures":[{"sig":"MEQCIB0xYQju2jp5r45SwGiENgwohlhGcnELm1Gf59ItrfW8AiAj/Bi/UiSnh8Tz+iEqITj74W7KW2BKPCsmbetlYYkzzg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":7306},"main":"dist/index.js","type":"module","exports":{".":"./dist/index.js"},"gitHead":"3b438da4fad018be82e4fc02e2db2f56113ef251","scripts":{"build":"tsc"},"_npmUser":{"name":"aryanbansal-launch","email":"aryan.bansal@contentstack.com"},"_npmVersion":"11.6.0","description":"A collection of high-performance utilities designed for Edge Computing environments (like Cloudflare Workers, Vercel Edge Functions, or Contentstack Launch). These utilities help you handle common tasks like authentication, security, redirection, and geo-","directories":{},"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/edge-utils_0.1.1_1766208192844_0.7119129143851604","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@aryanbansal-launch/edge-utils","version":"0.1.2","license":"MIT","_id":"@aryanbansal-launch/edge-utils@0.1.2","maintainers":[{"name":"aryanbansal-launch","email":"aryan.bansal@contentstack.com"}],"dist":{"shasum":"aae3172cede1a632593d7f064ea28d657bd922a0","tarball":"https://registry.npmjs.org/@aryanbansal-launch/edge-utils/-/edge-utils-0.1.2.tgz","fileCount":12,"integrity":"sha512-1ptDC1/A++dd1Zulfy780sgXsz0z/ZemC/IS4LZhhuLzDkHQuo+EDwEmvcrp8DFj3xDHdA2U2dhLVAUNB5WyHg==","signatures":[{"sig":"MEUCIQCQlfPwGGitLYKScqp+NC9P2PDa7VI/SQCnM0lSGJwtzQIgGng/huZMquwioLWCjI9EHpaRuhayu1Id+osOck24E1k=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":9832},"main":"dist/index.js","type":"module","exports":{".":"./dist/index.js"},"gitHead":"217e8c93f768c3a5364ddde5b818cf4e4a7822b4","scripts":{"build":"tsc"},"_npmUser":{"name":"aryanbansal-launch","email":"aryan.bansal@contentstack.com"},"_npmVersion":"11.6.0","description":"[![npm version](https://img.shields.io/npm/v/@launch/edge-utils.svg)](https://www.npmjs.com/package/@launch/edge-utils) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Platform Support](https:","directories":{},"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/edge-utils_0.1.2_1766209444833_0.9353733361801813","host":"s3://npm-registry-packages-npm-production"}},"0.1.3":{"name":"@aryanbansal-launch/edge-utils","version":"0.1.3","license":"MIT","_id":"@aryanbansal-launch/edge-utils@0.1.3","maintainers":[{"name":"aryanbansal-launch","email":"aryan.bansal@contentstack.com"}],"homepage":"https://github.com/AryanBansal-launch/launch-edge-utils#readme","bugs":{"url":"https://github.com/AryanBansal-launch/launch-edge-utils/issues"},"dist":{"shasum":"0dd79391bb8223d4b3d2b287b7861d01c8c719c6","tarball":"https://registry.npmjs.org/@aryanbansal-launch/edge-utils/-/edge-utils-0.1.3.tgz","fileCount":12,"integrity":"sha512-Vwq3l1826e24APw22DEC9Q3C+RieyNmKyRrycyyKB4ueeMQcS++xjtT84HaV4t4/Ghjk5QZL+y3vY1MrTFNNXw==","signatures":[{"sig":"MEQCIH8QZ+pmJmDVGEzzxYRLnZ4RThuVSzILuza9aheTe0iEAiAES7cu9/+v+8aZIeOhBx05hG2KwLP9VLhXTeb5j7Q4vQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":10120},"main":"dist/index.js","type":"module","exports":{".":"./dist/index.js"},"gitHead":"63c9781082b37923614aceef1fde7b6905435a9f","scripts":{"build":"tsc"},"_npmUser":{"name":"aryanbansal-launch","email":"aryan.bansal@contentstack.com"},"repository":{"url":"git+https://github.com/AryanBansal-launch/launch-edge-utils.git","type":"git"},"_npmVersion":"11.6.0","description":"[![npm version](https://img.shields.io/npm/v/@launch/edge-utils.svg)](https://www.npmjs.com/package/@launch/edge-utils) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Platform Support](https:","directories":{},"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/edge-utils_0.1.3_1766209782952_0.7965748557019794","host":"s3://npm-registry-packages-npm-production"}},"0.1.4":{"name":"@aryanbansal-launch/edge-utils","version":"0.1.4","license":"MIT","_id":"@aryanbansal-launch/edge-utils@0.1.4","maintainers":[{"name":"aryanbansal-launch","email":"aryan.bansal@contentstack.com"}],"homepage":"https://github.com/AryanBansal-launch/launch-edge-utils#readme","bugs":{"url":"https://github.com/AryanBansal-launch/launch-edge-utils/issues"},"bin":{"launch-init":"bin/launch-init.js"},"dist":{"shasum":"05d9dd0b8b41527cba174a2735a6055edbb76c60","tarball":"https://registry.npmjs.org/@aryanbansal-launch/edge-utils/-/edge-utils-0.1.4.tgz","fileCount":13,"integrity":"sha512-Ta5UwXMq7avXsbqeBsAtVB83VQzKfPB8X1PT8iTuSPnfRGc6Jq/AFylStCFpZsK94L2q1TR0OAQGE5VPClXuRw==","signatures":[{"sig":"MEQCIFn0MvoHihfeL50tkgjzERQs8xCReHXId6vhvjmdJRa6AiA5RjzC46rcEC+qUgbbTM4yQmECQLUhPuAXXs7y/hwMyQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":15519},"main":"dist/index.js","type":"module","exports":{".":"./dist/index.js"},"gitHead":"65ca4e734a7c36e5a78cb64326a655e34cf7e289","scripts":{"build":"tsc"},"_npmUser":{"name":"aryanbansal-launch","email":"aryan.bansal@contentstack.com"},"repository":{"url":"git+https://github.com/AryanBansal-launch/launch-edge-utils.git","type":"git"},"_npmVersion":"11.6.0","description":"[![npm version](https://img.shields.io/npm/v/@launch/edge-utils.svg)](https://www.npmjs.com/package/@launch/edge-utils) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Platform Support](https:","directories":{},"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/edge-utils_0.1.4_1766238361676_0.5048516610576772","host":"s3://npm-registry-packages-npm-production"}},"0.1.5":{"name":"@aryanbansal-launch/edge-utils","version":"0.1.5","license":"MIT","_id":"@aryanbansal-launch/edge-utils@0.1.5","maintainers":[{"name":"aryanbansal-launch","email":"aryan.bansal@contentstack.com"}],"homepage":"https://github.com/AryanBansal-launch/launch-edge-utils#readme","bugs":{"url":"https://github.com/AryanBansal-launch/launch-edge-utils/issues"},"bin":{"launch-init":"bin/launch-init.js"},"dist":{"shasum":"b82d26476eda1de5003fd25cebda8b4ef1ac8581","tarball":"https://registry.npmjs.org/@aryanbansal-launch/edge-utils/-/edge-utils-0.1.5.tgz","fileCount":13,"integrity":"sha512-wK2ziVQBHpEF+yDrIS4hLhgFxpWMJynUCO75FyggmbVFtL5MqCRi4XzjMKwB02NPIFXUlXvbtF5e+Sn6m7u5HQ==","signatures":[{"sig":"MEQCIGCfcFRePJEZ4QuYH7KxQaN7s/F5cM9ZV1orV+OL6IYOAiAkNkle3sjhUmhA8NS1wkOfK6U81B7cXqO7Xo/kpnISqg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":13264},"main":"dist/index.js","type":"module","exports":{".":"./dist/index.js"},"gitHead":"3826c69abf82a685effb95cbb720ca4db1e2ea6d","scripts":{"build":"tsc"},"_npmUser":{"name":"aryanbansal-launch","email":"aryan.bansal@contentstack.com"},"repository":{"url":"git+https://github.com/AryanBansal-launch/launch-edge-utils.git","type":"git"},"_npmVersion":"11.6.0","description":"[![npm version](https://img.shields.io/npm/v/@launch/edge-utils.svg)](https://www.npmjs.com/package/@launch/edge-utils) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)","directories":{},"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/edge-utils_0.1.5_1766239506742_0.566401196104934","host":"s3://npm-registry-packages-npm-production"}},"0.1.6":{"name":"@aryanbansal-launch/edge-utils","version":"0.1.6","license":"MIT","_id":"@aryanbansal-launch/edge-utils@0.1.6","maintainers":[{"name":"aryanbansal-launch","email":"aryan.bansal@contentstack.com"}],"homepage":"https://github.com/AryanBansal-launch/launch-edge-utils#readme","bugs":{"url":"https://github.com/AryanBansal-launch/launch-edge-utils/issues"},"bin":{"launch-init":"bin/launch-init.js"},"dist":{"shasum":"96c915fe16cbb68c0e76bee58499d7b4f13056f2","tarball":"https://registry.npmjs.org/@aryanbansal-launch/edge-utils/-/edge-utils-0.1.6.tgz","fileCount":14,"integrity":"sha512-IIE1nRKxLx/Da6kXBjgXWf4V9ergEbVRLv8DVlAx8jTdUDI1BOfCqaOWi/lc8sy1YkTG6m1/giFmoaO4xm47xA==","signatures":[{"sig":"MEUCIEu9UfK1NYSmOTFJaAbqftULciLeqeAP899wZZuxO4VIAiEAgZqCrkOjFfGaB/ht59m9rrFIFmTI6jxKTMSJ9rWKj4c=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":14440},"main":"dist/index.js","type":"module","exports":{".":"./dist/index.js"},"gitHead":"e262c3750e6b0286c43f53874e850b0c978359b6","scripts":{"build":"tsc"},"_npmUser":{"name":"aryanbansal-launch","email":"aryan.bansal@contentstack.com"},"repository":{"url":"git+https://github.com/AryanBansal-launch/launch-edge-utils.git","type":"git"},"_npmVersion":"11.6.0","description":"[![npm version](https://img.shields.io/npm/v/@launch/edge-utils.svg)](https://www.npmjs.com/package/@aryanbansal-launch/edge-utils) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)","directories":{},"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/edge-utils_0.1.6_1767250533688_0.3903964474786126","host":"s3://npm-registry-packages-npm-production"}},"0.1.7":{"name":"@aryanbansal-launch/edge-utils","version":"0.1.7","license":"MIT","_id":"@aryanbansal-launch/edge-utils@0.1.7","maintainers":[{"name":"aryanbansal-launch","email":"aryan.bansal@contentstack.com"}],"homepage":"https://github.com/AryanBansal-launch/launch-edge-utils#readme","bugs":{"url":"https://github.com/AryanBansal-launch/launch-edge-utils/issues"},"bin":{"launch-init":"bin/launch-init.js","launch-config":"bin/launch-config.js"},"dist":{"shasum":"d33b0917da94cabaf92d7cb8df872b39a8a5e460","tarball":"https://registry.npmjs.org/@aryanbansal-launch/edge-utils/-/edge-utils-0.1.7.tgz","fileCount":16,"integrity":"sha512-zblTH5++vjL9uIWm+fRkPZWLaiwjBuT60vQM//yDDU7AIS9K+A8d3DNTVVkRrQ4OD/LCbmqGOVdKpvBR1cZBbA==","signatures":[{"sig":"MEUCIAKwqmZQS2QsA4KysNuUIJWTjoCw0/niMFHnL+hrgZVwAiEA6wmm3UFIQm/hQ0pSZmDVglnj1SFV9l63i/W4rzaFwCE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":19095},"main":"dist/index.js","type":"module","exports":{".":"./dist/index.js"},"gitHead":"ecc96e9244b1df465262c66aa59d2477056ec714","scripts":{"build":"tsc"},"_npmUser":{"name":"aryanbansal-launch","email":"aryan.bansal@contentstack.com"},"repository":{"url":"git+https://github.com/AryanBansal-launch/launch-edge-utils.git","type":"git"},"_npmVersion":"11.6.0","description":"[![npm version](https://img.shields.io/npm/v/@launch/edge-utils.svg)](https://www.npmjs.com/package/@aryanbansal-launch/edge-utils) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)","directories":{},"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/edge-utils_0.1.7_1767252430624_0.20169693106998565","host":"s3://npm-registry-packages-npm-production"}},"0.1.8":{"name":"@aryanbansal-launch/edge-utils","version":"0.1.8","license":"MIT","_id":"@aryanbansal-launch/edge-utils@0.1.8","maintainers":[{"name":"aryanbansal-launch","email":"aryan.bansal@contentstack.com"}],"homepage":"https://github.com/AryanBansal-launch/launch-edge-utils#readme","bugs":{"url":"https://github.com/AryanBansal-launch/launch-edge-utils/issues"},"bin":{"launch-init":"bin/launch-init.js","launch-config":"bin/launch-config.js"},"dist":{"shasum":"281000835f34eb082f4bcc0e865e8ae15533b4a2","tarball":"https://registry.npmjs.org/@aryanbansal-launch/edge-utils/-/edge-utils-0.1.8.tgz","fileCount":16,"integrity":"sha512-a3+aZLtGwGeS0dyuqayXrxwleuFjveOguzrCKpzKsABn5TcbOQ5i5Cn4CVpN8Ogb29G04zfcbKKDDvglhBgETQ==","signatures":[{"sig":"MEYCIQDkoTlPh36nxf5kD7OQSqB9eBxvSJVb6oc9npa4LYGGgwIhANhMIUoxPJ+YygRZ2ii4I3fcBCaPX6kaYLK3UMlUmyhs","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":19506},"main":"dist/index.js","type":"module","exports":{".":"./dist/index.js"},"gitHead":"0c649a78dca06ee4d4ab63939cae9b0536606c4e","scripts":{"build":"tsc"},"_npmUser":{"name":"aryanbansal-launch","email":"aryan.bansal@contentstack.com"},"repository":{"url":"git+https://github.com/AryanBansal-launch/launch-edge-utils.git","type":"git"},"_npmVersion":"11.6.0","description":"[![npm version](https://img.shields.io/npm/v/@aryanbansal-launch/edge-utils.svg)](https://www.npmjs.com/package/@aryanbansal-launch/edge-utils) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)","directories":{},"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/edge-utils_0.1.8_1767334885480_0.7169343900350529","host":"s3://npm-registry-packages-npm-production"}},"0.1.9":{"name":"@aryanbansal-launch/edge-utils","version":"0.1.9","license":"MIT","_id":"@aryanbansal-launch/edge-utils@0.1.9","maintainers":[{"name":"aryanbansal-launch","email":"aryan.bansal@contentstack.com"}],"homepage":"https://github.com/AryanBansal-launch/launch-edge-utils#readme","bugs":{"url":"https://github.com/AryanBansal-launch/launch-edge-utils/issues"},"bin":{"launch-config":"bin/launch-config.js","create-launch-edge":"bin/launch-init.js"},"dist":{"shasum":"b46e460ea44834d8bca1b44151985694cb4248d0","tarball":"https://registry.npmjs.org/@aryanbansal-launch/edge-utils/-/edge-utils-0.1.9.tgz","fileCount":16,"integrity":"sha512-v4U6MImvdmFMYXcdgqmybwXefq6lSDiM5ZesDDbBGLvDQRU6sfZfafI+8L3+/xocltKgz3s2Sk8CqewMFa9NNA==","signatures":[{"sig":"MEYCIQDJucRSEA+LGSe7cmoKdHxTpvic9h889saNTaXBMxmkEgIhAIdUjHAJ7jKgrUw2zj3D1oVDDdES9O5eUS/QNYD7GZoj","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":20373},"main":"dist/index.js","type":"module","exports":{".":"./dist/index.js"},"gitHead":"c9fd27505a0da73ec6a6758cc11efed989c89c54","scripts":{"build":"tsc"},"_npmUser":{"name":"aryanbansal-launch","email":"aryan.bansal@contentstack.com"},"repository":{"url":"git+https://github.com/AryanBansal-launch/launch-edge-utils.git","type":"git"},"_npmVersion":"11.6.0","description":"[![npm version](https://img.shields.io/npm/v/@aryanbansal-launch/edge-utils.svg)](https://www.npmjs.com/package/@aryanbansal-launch/edge-utils) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)","directories":{},"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/edge-utils_0.1.9_1767355313279_0.7365935878439993","host":"s3://npm-registry-packages-npm-production"}},"0.1.10":{"name":"@aryanbansal-launch/edge-utils","version":"0.1.10","license":"MIT","_id":"@aryanbansal-launch/edge-utils@0.1.10","maintainers":[{"name":"aryanbansal-launch","email":"aryan.bansal@contentstack.com"}],"homepage":"https://github.com/AryanBansal-launch/launch-edge-utils#readme","bugs":{"url":"https://github.com/AryanBansal-launch/launch-edge-utils/issues"},"bin":{"launch-config":"bin/launch-config.js","create-launch-edge":"bin/launch-init.js"},"dist":{"shasum":"1ef7f77b9c5421a50828269df2800ba700619891","tarball":"https://registry.npmjs.org/@aryanbansal-launch/edge-utils/-/edge-utils-0.1.10.tgz","fileCount":16,"integrity":"sha512-IJFH7HAEbXstPnh7rq/nKIlU1UtnXRGBuSaNDIrpdUFrXYhN4uka9c4k3P3NOsT43MJsKCOtqRY/GXTye88oCA==","signatures":[{"sig":"MEYCIQDLBOZE1bF0UgVn9S/EoSVL/Kbs77l/nea241LOf88vuwIhAMshK/FV64e2Rxq+1pC+ECKIoHeHiofZNdF+J3VYlL2o","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":21003},"main":"dist/index.js","type":"module","exports":{".":"./dist/index.js"},"gitHead":"841665d82baa6df4477fd3cdfb50ef92b20ce1e5","scripts":{"build":"tsc"},"_npmUser":{"name":"aryanbansal-launch","email":"aryan.bansal@contentstack.com"},"repository":{"url":"git+https://github.com/AryanBansal-launch/launch-edge-utils.git","type":"git"},"_npmVersion":"11.6.0","description":"[![npm version](https://img.shields.io/npm/v/@aryanbansal-launch/edge-utils.svg)](https://www.npmjs.com/package/@aryanbansal-launch/edge-utils) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)","directories":{},"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/edge-utils_0.1.10_1767439589696_0.7722958127529311","host":"s3://npm-registry-packages-npm-production"}},"0.1.11":{"name":"@aryanbansal-launch/edge-utils","version":"0.1.11","keywords":["contentstack","launch","edge-functions","edge","middleware","security","nextjs","redirect","geo-location","basic-auth","ip-access"],"license":"MIT","_id":"@aryanbansal-launch/edge-utils@0.1.11","maintainers":[{"name":"aryanbansal-launch","email":"aryan.bansal@contentstack.com"}],"homepage":"https://github.com/AryanBansal-launch/launch-edge-utils#readme","bugs":{"url":"https://github.com/AryanBansal-launch/launch-edge-utils/issues"},"bin":{"launch-help":"bin/launch-help.js","launch-config":"bin/launch-config.js","create-launch-edge":"bin/launch-init.js"},"dist":{"shasum":"0a54142eb0685c9aeb05d27a724b4d7a48a96e90","tarball":"https://registry.npmjs.org/@aryanbansal-launch/edge-utils/-/edge-utils-0.1.11.tgz","fileCount":19,"integrity":"sha512-yfH1nE76CJ7pv5fHr+QQIZrt6GDvPlj+NA4xpDbwXxC3/nny5l8XOM0rgJuk/oWgDfi0DgTIGzVEfjAOByruoA==","signatures":[{"sig":"MEUCIBd9/evzW9UkiMWxPU/dWFNBSCfoRGP0ae7CZ6RAtLkeAiEAzXKMPhTbqu9dJOtdmTvqvZcr9KeT4nVJJTZH8hHs2yo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":52185},"main":"dist/index.js","type":"module","exports":{".":"./dist/index.js"},"gitHead":"4519571f3835f774874d26d6d1c721d368b1a09f","scripts":{"build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"aryanbansal-launch","email":"aryan.bansal@contentstack.com"},"repository":{"url":"git+https://github.com/AryanBansal-launch/launch-edge-utils.git","type":"git"},"_npmVersion":"11.6.0","description":"[![npm version](https://img.shields.io/npm/v/@aryanbansal-launch/edge-utils.svg)](https://www.npmjs.com/package/@aryanbansal-launch/edge-utils) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)","directories":{},"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/edge-utils_0.1.11_1769921234841_0.20615374951183463","host":"s3://npm-registry-packages-npm-production"}},"0.1.12":{"name":"@aryanbansal-launch/edge-utils","version":"0.1.12","keywords":["contentstack","launch","edge-functions","edge","middleware","security","nextjs","redirect","geo-location","basic-auth","ip-access"],"license":"MIT","_id":"@aryanbansal-launch/edge-utils@0.1.12","maintainers":[{"name":"aryanbansal-launch","email":"aryan.bansal@contentstack.com"}],"homepage":"https://github.com/AryanBansal-launch/launch-edge-utils#readme","bugs":{"url":"https://github.com/AryanBansal-launch/launch-edge-utils/issues"},"bin":{"launch-help":"bin/launch-help.js","launch-config":"bin/launch-config.js","create-launch-edge":"bin/launch-init.js"},"dist":{"shasum":"b8297f42b2134bfaaa3206e18f38ae3ac99db773","tarball":"https://registry.npmjs.org/@aryanbansal-launch/edge-utils/-/edge-utils-0.1.12.tgz","fileCount":21,"integrity":"sha512-VMiaBhakOj2SxMeo1ZCKfHMKruYWW1Cpn1OBxHguyyTxX6LdvCahoPaepNoZG5QKRkKR7RX9cllksQWTQbfkPg==","signatures":[{"sig":"MEYCIQCBGEDKdDV0ZBfzDQoOh07YabRAgZopx3vfLoFgBv6uKwIhAOPhJ7OV2xhZB9QIC7dCsPBsLCHDAOEsr7W8HRkqWbjF","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":60738},"main":"dist/index.js","type":"module","exports":{".":"./dist/index.js"},"gitHead":"aae6dc020773c0a84565b8605c2f659ee0c1777d","scripts":{"build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"aryanbansal-launch","email":"aryan.bansal@contentstack.com"},"repository":{"url":"git+https://github.com/AryanBansal-launch/launch-edge-utils.git","type":"git"},"_npmVersion":"11.6.0","description":"[![npm version](https://img.shields.io/npm/v/@aryanbansal-launch/edge-utils.svg)](https://www.npmjs.com/package/@aryanbansal-launch/edge-utils) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)","directories":{},"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/edge-utils_0.1.12_1769923262138_0.9340738036278924","host":"s3://npm-registry-packages-npm-production"}},"0.1.13":{"name":"@aryanbansal-launch/edge-utils","version":"0.1.13","keywords":["contentstack","launch","edge-functions","edge","middleware","security","nextjs","redirect","geo-location","basic-auth","ip-access"],"license":"MIT","_id":"@aryanbansal-launch/edge-utils@0.1.13","maintainers":[{"name":"aryanbansal-launch","email":"aryan.bansal@contentstack.com"}],"homepage":"https://github.com/AryanBansal-launch/launch-edge-utils#readme","bugs":{"url":"https://github.com/AryanBansal-launch/launch-edge-utils/issues"},"bin":{"launch-help":"bin/launch-help.js","launch-config":"bin/launch-config.js","launch-edge-local":"bin/launch-edge-local.js","create-launch-edge":"bin/launch-init.js","launch-edge-test-local":"bin/launch-edge-test-local.js"},"dist":{"shasum":"0a5713c6aecc0205d8818f76df46d6bb27de70eb","tarball":"https://registry.npmjs.org/@aryanbansal-launch/edge-utils/-/edge-utils-0.1.13.tgz","fileCount":30,"integrity":"sha512-ZvxHMouRKGaAHZGu+1xEQRnqD3Gvl0jXckJIZYkqCFSwbco1mcVVuWvIdQtNHVsYrXBXp6fU/PVQZ9ofn9ehQw==","signatures":[{"sig":"MEQCIERviYxe+h59TXIVzHEtW9XF2tslCIzUWXFXi9x9GfmXAiA53NyQhuGub97p2gY3TD660ejTD2mH07Fn4148TYHGGg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":88421},"main":"dist/index.js","type":"module","exports":{".":"./dist/index.js"},"gitHead":"55592db6a09ff58c754969db691eb7bdc43a884d","scripts":{"build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"aryanbansal-launch","email":"aryan.bansal@contentstack.com"},"repository":{"url":"git+https://github.com/AryanBansal-launch/launch-edge-utils.git","type":"git"},"_npmVersion":"11.6.0","description":"[![npm version](https://img.shields.io/npm/v/@aryanbansal-launch/edge-utils.svg)](https://www.npmjs.com/package/@aryanbansal-launch/edge-utils) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)","directories":{},"_nodeVersion":"22.14.0","dependencies":{"wrangler":"^3.114.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/edge-utils_0.1.13_1776800273198_0.5141900590174244","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@aryanbansal-launch/edge-utils","version":"0.3.0","license":"MIT","type":"module","repository":{"type":"git","url":"git+https://github.com/AryanBansal-launch/launch-edge-utils.git"},"homepage":"https://github.com/AryanBansal-launch/launch-edge-utils#readme","bugs":{"url":"https://github.com/AryanBansal-launch/launch-edge-utils/issues"},"main":"dist/index.js","types":"dist/index.d.ts","bin":{"create-launch-edge":"bin/launch-init.js","launch-config":"bin/launch-config.js","launch-help":"bin/launch-help.js","launch-edge-local":"bin/launch-edge-local.js","launch-edge-test-local":"bin/launch-edge-test-local.js","launch-edge-seed-local":"bin/launch-edge-seed-local.js","launch-edge-quickstart":"bin/launch-edge-quickstart.js"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"optionalDependencies":{"wrangler":"^3.114.0"},"devDependencies":{"@types/node":"^20.11.0","typescript":"^5.4.0","vitest":"^1.6.0"},"scripts":{"build":"tsc","test":"vitest run","test:watch":"vitest","typecheck":"tsc --noEmit","prepublishOnly":"npm run build"},"keywords":["contentstack","launch","edge-functions","edge","middleware","security","nextjs","redirect","geo-location","basic-auth","ip-access"],"_id":"@aryanbansal-launch/edge-utils@0.3.0","gitHead":"4af377841a44f718c310e57e518068d797e78dc8","description":"[![npm version](https://img.shields.io/npm/v/@aryanbansal-launch/edge-utils.svg)](https://www.npmjs.com/package/@aryanbansal-launch/edge-utils) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)","_nodeVersion":"22.14.0","_npmVersion":"11.6.0","dist":{"integrity":"sha512-alQgk2F19Oxa+S5ZtmS8TuvCVxcX0T62PhHCF+icSLhV/n2sRNclG3Xee+Uqlmx6YXEyLsKNeAFLzAPY3SwUgw==","shasum":"e2651cd7fc011c2d01854f98f945110e6534dbe0","tarball":"https://registry.npmjs.org/@aryanbansal-launch/edge-utils/-/edge-utils-0.3.0.tgz","fileCount":100,"unpackedSize":174946,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCID1nNdIVsWvGZ7RNjtUln3sNMlTQzWn+H+Wl6woX7lpTAiEAlQSHZ6oiLlGzNZjz9p4gwFuOZrFksAyzk8kvAYQkvcM="}]},"_npmUser":{"name":"aryanbansal-launch","email":"aryan.bansal@contentstack.com"},"directories":{},"maintainers":[{"name":"aryanbansal-launch","email":"aryan.bansal@contentstack.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/edge-utils_0.3.0_1784356287538_0.8585332644040702"},"_hasShrinkwrap":false}},"time":{"created":"2025-12-20T05:14:57.908Z","modified":"2026-07-18T06:31:27.854Z","0.1.0":"2025-12-20T05:14:58.122Z","0.1.1":"2025-12-20T05:23:13.010Z","0.1.2":"2025-12-20T05:44:04.997Z","0.1.3":"2025-12-20T05:49:43.097Z","0.1.4":"2025-12-20T13:46:01.829Z","0.1.5":"2025-12-20T14:05:06.931Z","0.1.6":"2026-01-01T06:55:33.821Z","0.1.7":"2026-01-01T07:27:10.777Z","0.1.8":"2026-01-02T06:21:25.617Z","0.1.9":"2026-01-02T12:01:53.414Z","0.1.10":"2026-01-03T11:26:29.845Z","0.1.11":"2026-02-01T04:47:15.002Z","0.1.12":"2026-02-01T05:21:02.302Z","0.1.13":"2026-04-21T19:37:53.348Z","0.3.0":"2026-07-18T06:31:27.678Z"},"bugs":{"url":"https://github.com/AryanBansal-launch/launch-edge-utils/issues"},"license":"MIT","homepage":"https://github.com/AryanBansal-launch/launch-edge-utils#readme","keywords":["contentstack","launch","edge-functions","edge","middleware","security","nextjs","redirect","geo-location","basic-auth","ip-access"],"repository":{"type":"git","url":"git+https://github.com/AryanBansal-launch/launch-edge-utils.git"},"description":"[![npm version](https://img.shields.io/npm/v/@aryanbansal-launch/edge-utils.svg)](https://www.npmjs.com/package/@aryanbansal-launch/edge-utils) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)","maintainers":[{"name":"aryanbansal-launch","email":"aryan.bansal@contentstack.com"}],"readme":"# 🚀 Edge Utils for Contentstack Launch\n\n[![npm version](https://img.shields.io/npm/v/@aryanbansal-launch/edge-utils.svg)](https://www.npmjs.com/package/@aryanbansal-launch/edge-utils)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA production-ready toolkit for [Contentstack Launch](https://www.contentstack.com/docs/developers/launch) Edge Functions — security, auth, routing, Next.js fixes, and geo-awareness, plus a full local dev/test setup so you can try everything before you deploy.\n\n---\n\n## ⚡ Try it in one command\n\n```bash\nnpm install @aryanbansal-launch/edge-utils\nnpx launch-edge-quickstart\n```\n\nThat's it. This one command scaffolds an edge function, sets up a local KV store to simulate Launch's redirect/rewrite/cache-priming config, seeds it with sample data, and starts a local dev server — printing exactly what's configured and what URL to try for each feature:\n\n```\nReady — here's what's configured\n\n  ✔ Redirects  2 rule(s) configured\n      curl -i http://localhost:8787/legacy/about  → 301 to /about\n  ✔ Rewrites  2 rule(s) configured\n      curl --compressed http://localhost:8787/home  → serves /, URL unchanged\n  ✔ Cache priming  2 URL(s), auto-primed on startup\n      curl -i http://localhost:8787/  → X-Cache: HIT once warmed\n```\n\nRun it again any time — it never overwrites files you already have (your handler, your `launch.json`), it only fills in what's missing. See [Local testing](#-local-testing) for the full picture, or jump to [Table of contents](#-table-of-contents).\n\n---\n\n## 📋 Table of contents\n\n- [Try it in one command](#-try-it-in-one-command) — the fastest path\n- [Features](#-features)\n- [Use this in production](#-use-this-in-production) — add utilities to your real edge handler\n- [Local testing](#-local-testing) — quickstart, step-by-step, and how KV/cache simulation works\n- [Config-driven redirects (`launch.json`)](#-config-driven-redirects-launchjson)\n- [Writing a handler](#-writing-a-handler)\n- [API Reference](#-api-reference)\n- [CLI Commands](#-cli-commands)\n- [Platform Support](#-platform-support)\n\n---\n\n## ✨ Features\n\n- 🛡️ **Security** — block AI crawlers, IP allow/deny lists, block default Launch domains\n- 🔐 **Edge Auth** — Basic Auth for specific hostnames (e.g. staging)\n- 📍 **Geo-Aware** — read country/region/city from Launch's geo headers\n- ⚛️ **Next.js Ready** — fixes for RSC header issues on Launch proxies\n- 🔀 **Routing** — code-level conditional redirects, plus config-driven redirects/rewrites via `launch.json`\n- 🧪 **Full local dev setup** — run your edge function *and* simulate Launch's redirect/rewrite/cache-priming config, entirely offline (Wrangler + Miniflare, no Cloudflare account)\n- ⚡ **Lean** — no runtime deps in the code you import at the edge; Wrangler is bundled so local testing needs no separate install\n\n---\n\n## 🎯 Use this in production\n\nAdd one or more helpers to your real Contentstack Launch edge handler.\n\n```bash\nnpm install @aryanbansal-launch/edge-utils\nnpx create-launch-edge          # scaffolds functions/[proxy].edge.js if it doesn't exist\n```\n\nThen import what you need and wire it into your handler — each utility returns a `Response` on match (return it immediately) or `null` (fall through to the next check):\n\n```javascript\nimport { blockAICrawlers, redirectIfMatch, passThrough } from \"@aryanbansal-launch/edge-utils\";\n\nexport default async function handler(request, context) {\n  const botCheck = blockAICrawlers(request);\n  if (botCheck) return botCheck;\n\n  const redirect = redirectIfMatch(request, { path: \"/old-page\", to: \"/new-page\", status: 301 });\n  if (redirect) return redirect;\n\n  return passThrough(request);\n}\n```\n\nDeploy through Contentstack Launch as usual — it runs `functions/[proxy].edge.js` at the edge before traffic reaches your app. See [Writing a handler](#-writing-a-handler) for a fuller example and the [API Reference](#-api-reference) for every utility.\n\n---\n\n## 🧪 Local testing\n\nTest redirects, rewrites, cache priming, and your handler's own logic **on your machine**, without deploying. Wrangler's dev server runs on **Miniflare**, a Workers-compatible runtime — no Cloudflare account, no network calls.\n\n### The fast way\n\n```bash\nnpx launch-edge-quickstart\n```\n\nNon-interactively creates whatever's missing — `functions/[proxy].edge.js` (a self-contained demo handler, if you don't have one yet), `functions/dev-worker.edge.js` (the local KV-aware shim), `wrangler.toml`, and a sample `launch.json` — **never** overwrites an existing handler or config, seeds the local KV, prints a status report with copy-pasteable `curl` commands per feature, then starts the dev server (which auto-primes the cache once ready).\n\nPass through `wrangler dev` args as usual: `npx launch-edge-quickstart --port 8788`. Add `--no-prime` to skip the automatic startup cache warm-up. Edit `launch.json` and re-run the same command any time to pick up changes.\n\nTry it:\n\n```bash\ncurl -i http://localhost:8787/legacy/about        # redirect: 301 -> /about\ncurl -i http://localhost:8787/old-shop/tees/blue  # wildcard redirect: 301 -> /shop/tees/blue\ncurl    http://localhost:8787/home                # rewrite: serves /, URL unchanged\ncurl -i http://localhost:8787/about                # X-Cache: HIT (auto-primed on startup)\n```\n\n### If you want your own edge function's logic instead\n\nAlready have `functions/[proxy].edge.js` with your own code (auth, geo, bot-block, etc.)? Quickstart leaves it completely untouched — it only adds the KV plumbing *around* it. If you'd rather test **only your handler**, with no KV/redirect/rewrite/cache involved at all, remove the `[[kv_namespaces]]` block from `wrangler.toml` — with no KV bound, `dev-worker.edge.js` becomes a pure passthrough to your handler, no cache headers, no KV reads.\n\n### Step-by-step (more control)\n\nUse this instead of the one-shot command if you want to pick a specific preset via a wizard, or run scaffold/seed/serve as separate steps.\n\n```bash\nnpx launch-edge-local          # interactive wizard — pick a preset (see below)\nnpx launch-edge-seed-local     # seed the local KV from launch.json\nnpx launch-edge-test-local     # start the dev server\n```\n\n`npx launch-edge-local` shows a numbered menu:\n\n| # | Preset | Try |\n|---|---|---|\n| 1 | Redirect (code-level) | `/legacy-demo` → 301 |\n| 2 | JSON edge route | `/api/edge-ping` |\n| 3 | Basic auth | prompts for `demo`/`demo` |\n| 4 | Block AI crawlers | `curl -A \"GPTBot\" ...` → 403 |\n| 5 | Next.js RSC fix | strips RSC header on configured paths |\n| 6 | **KV redirects** | `/legacy/about` → 301 (from `launch.json`) |\n| 7 | **KV rewrites** | `/docs/intro` serves `/blog/intro` |\n| 8 | **Cache priming** | `/__prime` warms the cache, then `/about` is `X-Cache: HIT` |\n\nPresets 6–8 also write a sample `launch.json`. If `functions/[proxy].edge.js` already exists you're asked before it's overwritten — say no to keep your own handler; the KV logic lives in `dev-worker.edge.js` regardless.\n\nAlign `BACKEND_URL` in `wrangler.toml` with your app's dev server (default `http://127.0.0.1:3000`) if your handler passes requests through to a real backend.\n\n### How the KV simulation works\n\n`launch.json` — the same file you deploy — is the single source of truth for redirects, rewrites, and cache priming. Locally, it's seeded into a **Miniflare-emulated KV namespace** (`EDGE_CONFIG`) so your setup can read it exactly as Launch would in production:\n\n- **`functions/[proxy].edge.js`** — your real handler. Deploys to Launch unchanged; never touched by the KV tooling.\n- **`functions/dev-worker.edge.js`** — a **local-dev-only shim** that reads `EDGE_CONFIG`, applies redirects/rewrites/cache priming, then delegates everything else to your handler. It's feature-detected (`if (env.EDGE_CONFIG)`), so with no KV bound it's just a plain rewrite-to-origin dev worker.\n- **Cache priming runs automatically** — on startup (once the dev server reports ready) and again in the background on the first request served, mirroring how Launch warms pages after a deploy. `GET /__prime` remains available to re-trigger manually.\n\nFor the full mental model (two-layer worker design, request lifecycle, KV/cache persistence, diagrams), see **[ARCHITECTURE.md](ARCHITECTURE.md)**.\n\n### Caveats\n\n- **Cacheability**: the Cache API only retains responses that are cacheable per HTTP semantics — a response with no `Cache-Control` header is silently dropped, so cache priming won't show a `HIT` for it. Set `Cache-Control` on routes you want cached.\n- **Fidelity**: local KV/cache is functional, not timing-accurate — it won't reproduce real KV propagation delay or edge cache tiering.\n- **Persist dir**: `launch-edge-seed-local` and `launch-edge-test-local` both default to `.wrangler-local`; if you override one with `--persist-to`, override the other the same way.\n- **Hostname rules** (`protectWithBasicAuth`): matching checks both the request URL host and the `Host` header, so `hostnameIncludes: \"localhost\"` works locally even though the rewritten request points at `127.0.0.1`.\n- **Geo/IP headers**: Miniflare doesn't inject Cloudflare's `cf` metadata, so `getGeoHeaders`/`getClientIP` may return empty values locally unless you set headers yourself.\n\nSee [`examples/local-dev/`](examples/local-dev/) for a minimal runnable project with the KV simulation wired up (`npm install`, then `npm start`).\n\n---\n\n## ⚙️ Config-driven redirects (`launch.json`)\n\nFor static, predictable redirects/rewrites/cache priming that don't need request-time logic, skip the edge function entirely — `launch.json` at your project root is read directly by Launch.\n\n```bash\nnpx launch-config\n```\n\nInteractively add redirects (one-by-one or bulk import from CSV/JSON), rewrites, and cache-priming URLs. See [`npx launch-config` bulk import formats](#npx-launch-config-bulk-import-formats) below for the file formats. Test it locally the same way as the edge function — see [Local testing](#-local-testing) above.\n\n**Config vs. edge function** — use `launch.json` for bulk, static rules (hundreds of SEO redirects, simple path changes); use the edge function for anything that needs request data (cookies, geo, A/B tests, headers). They compose: keep static rules in `launch.json`, dynamic logic in `functions/[proxy].edge.js`.\n\nYou can also generate `launch.json` in code with `generateLaunchConfig` — see the [API Reference](#-api-reference).\n\n---\n\n## 🔄 Writing a handler\n\nEdge Functions run as **middleware** before requests reach your origin: `User Request → Edge Function → Your Application`. Every utility follows the same pattern — call it, return its result if truthy, otherwise keep going:\n\n```javascript\nimport {\n  blockDefaultDomains,\n  handleNextJS_RSC,\n  blockAICrawlers,\n  ipAccessControl,\n  protectWithBasicAuth,\n  redirectIfMatch,\n  getGeoHeaders,\n  jsonResponse,\n  passThrough\n} from \"@aryanbansal-launch/edge-utils\";\n\nexport default async function handler(request, context) {\n  // Security\n  const domainCheck = blockDefaultDomains(request);\n  if (domainCheck) return domainCheck;\n\n  const botCheck = blockAICrawlers(request);\n  if (botCheck) return botCheck;\n\n  const ipCheck = ipAccessControl(request, { allow: [\"203.0.113.10\", \"198.51.100.5\"] });\n  if (ipCheck) return ipCheck;\n\n  // Auth\n  const auth = await protectWithBasicAuth(request, {\n    hostnameIncludes: \"staging.myapp.com\",\n    username: \"admin\",\n    password: \"securepass123\"\n  });\n  if (auth && auth.status === 401) return auth;\n\n  // Framework fixes\n  const rscCheck = await handleNextJS_RSC(request, { affectedPaths: [\"/shop\", \"/products\", \"/about\"] });\n  if (rscCheck) return rscCheck;\n\n  // Routing\n  const redirect = redirectIfMatch(request, { path: \"/old-page\", to: \"/new-page\", status: 301 });\n  if (redirect) return redirect;\n\n  // Personalization\n  const geo = getGeoHeaders(request);\n  if (geo.country === \"US\") console.log(`US visitor from ${geo.city}, ${geo.region}`);\n\n  // Custom API endpoint\n  const url = new URL(request.url);\n  if (url.pathname === \"/api/health\") {\n    return jsonResponse({ status: \"healthy\", region: geo.region, timestamp: Date.now() });\n  }\n\n  // Default: pass to origin\n  return passThrough(request);\n}\n```\n\n---\n\n## 📚 API Reference\n\n### 🛡️ Security & Access Control\n\n#### `blockAICrawlers(request, bots?)`\nBlocks common AI/SEO crawlers by user-agent. `bots` (string[], optional) overrides the default list (`claudebot`, `gptbot`, `googlebot`, `bingbot`, `ahrefsbot`, `yandexbot`, `semrushbot`, `mj12bot`, `facebookexternalhit`, `twitterbot`, case-insensitive). Returns `403 Response` on match, `null` otherwise.\n```javascript\nconst response = blockAICrawlers(request);           // default list\nif (response) return response;\n\nconst response = blockAICrawlers(request, [\"gptbot\", \"my-custom-bot\"]);  // custom list\n```\n\n#### `blockDefaultDomains(request, options?)`\nBlocks access via the default Launch domain (`*.contentstackapps.com`) so search engines only index your custom domain. `options.domainToBlock` (string, optional) overrides the default. Returns `403 Response` on match, `null` otherwise.\n```javascript\nconst response = blockDefaultDomains(request);\nif (response) return response;\n```\n[Learn more](https://www.contentstack.com/docs/developers/launch/blocking-default-launch-domains-from-google-search)\n\n#### `ipAccessControl(request, { allow?, deny? })`\nIP allow/deny list. `deny` takes precedence over `allow`. Returns `403 Response` if blocked, `null` if allowed.\n```javascript\nconst response = ipAccessControl(request, { allow: [\"203.0.113.0/24\"], deny: [\"203.0.113.50\"] });\nif (response) return response;\n```\n[Learn more](https://www.contentstack.com/docs/developers/launch/ip-based-access-control-using-edge-functions)\n\n#### `protectWithBasicAuth(request, { hostnameIncludes, username, password, realm? })`\nBasic Auth gate for a specific hostname. `hostnameIncludes` matches against the request URL hostname, the `Host` header, or `X-Forwarded-Host` (useful locally, since `rewriteRequestToOrigin` sets that header). Returns `401 Response` on failed/missing auth, `null` if `hostnameIncludes` doesn't match (chain continues).\n```javascript\nconst auth = await protectWithBasicAuth(request, {\n  hostnameIncludes: \"staging.myapp.com\",\n  username: \"admin\",\n  password: \"securepass123\"\n});\nif (auth && auth.status === 401) return auth;\n```\nNot for production-grade security — Basic Auth credentials are base64-encoded, not encrypted. [Learn more](https://www.contentstack.com/docs/developers/launch/password-protection-for-environments)\n\n---\n\n### 🔀 Routing & Redirects\n\n#### `redirectIfMatch(request, { path, to, method?, status? })`\nCode-level conditional redirect. Returns a redirect `Response` if `request` matches `path` (and `method`, if given), else `null`. `status` defaults to `301`.\n```javascript\nconst redirect = redirectIfMatch(request, { path: \"/old-page\", to: \"/new-page\", status: 301 });\nif (redirect) return redirect;\n```\n[Learn more](https://www.contentstack.com/docs/developers/launch/edge-url-redirects) · For bulk/static redirects without code, see [`launch.json`](#-config-driven-redirects-launchjson).\n\n---\n\n### ⚛️ Next.js\n\n#### `handleNextJS_RSC(request, { affectedPaths })`\nFixes a class of Next.js React Server Components bugs where a cache incorrectly serves RSC JSON data instead of a full page load, by stripping the offending header on the paths you list.\n```javascript\nconst rsc = await handleNextJS_RSC(request, { affectedPaths: [\"/shop\", \"/products\", \"/about\"] });\nif (rsc) return rsc;\n```\n[Learn more](https://www.contentstack.com/docs/developers/launch/handling-nextjs-rsc-issues-on-launch)\n\n---\n\n### 📍 Geo-Location\n\n#### `getGeoHeaders(request)`\nReads Launch's geo headers. Returns `{ country, region, city, latitude, longitude }` (all `string | null`).\n```javascript\nconst geo = getGeoHeaders(request);\nif (geo.country === \"FR\") return Response.redirect(\"https://fr.mysite.com\", 302);\n```\n[Learn more](https://www.contentstack.com/docs/developers/launch/geolocation-headers-in-launch)\n\n#### `getClientIP(request)`\nReturns the client's IP address from Launch's forwarded headers.\n\n---\n\n### 📤 Response Utilities\n\n#### `jsonResponse(body, init?)`\nBuilds a `Response` with `Content-Type: application/json`. `init` (status/headers) merges in as usual.\n```javascript\nreturn jsonResponse({ status: \"ok\" });\nreturn jsonResponse({ error: \"Not found\" }, { status: 404 });\n```\n\n#### `passThrough(request)`\nForwards the request to the origin — equivalent to `fetch(request)`. The typical default/fallback at the end of a handler chain.\n\n---\n\n### ⚙️ Configuration\n\n#### `generateLaunchConfig({ redirects?, rewrites?, cache? })`\nBuilds a `LaunchConfig` object in code, so you can generate `launch.json` programmatically (e.g. from CMS data) instead of using the interactive CLI.\n```typescript\ninterface LaunchRedirect { source: string; destination: string; statusCode?: number; response?: { headers?: Record<string, string> } }\ninterface LaunchRewrite { source: string; destination: string }\n```\n```javascript\nimport { generateLaunchConfig } from \"@aryanbansal-launch/edge-utils\";\nimport fs from \"fs\";\n\nconst config = generateLaunchConfig({\n  redirects: [{ source: \"/old-blog/:slug\", destination: \"/blog/:slug\", statusCode: 301 }],\n  rewrites: [{ source: \"/api/:path*\", destination: \"https://api.mybackend.com/:path*\" }],\n  cache: { cachePriming: { urls: [\"/\", \"/about\", \"/products\"] } }\n});\n\nfs.writeFileSync(\"launch.json\", JSON.stringify(config, null, 2));\n```\n\n---\n\n### 🗄️ KV-backed config (local simulation / Workers deployment)\n\nThese read the same redirect/rewrite/cache-priming shape as `launch.json`, but from a KV namespace — emulated locally by Miniflare (see [Local testing](#-local-testing)), or a real namespace if you deploy this pattern to Cloudflare Workers directly.\n\n- **`redirectFromKV(request, { kv, key?, status? })`** — reads a redirect table from KV (default key `\"redirects\"`), returns a redirect `Response` on match (exact path or trailing `/*` wildcard), else `null`.\n- **`rewriteFromKV(request, { kv, key? })`** — reads a rewrite table from KV (default key `\"rewrites\"`), returns a new `Request` with the path swapped (client URL unchanged) on match, else `null`.\n- **`primeCache({ urls, cache, keyBase?, fetchBase?, fetcher? })`** / **`primeCacheFromKV({ kv, cache, key?, ... })`** — warms the Cache API by fetching a list of URLs (or the list stored in KV, default key `\"cache:priming\"`) and storing cacheable responses.\n- **`serveWithCache(request, { cache, fetcher?, waitUntil? })`** — serves a GET from the Cache API when warm, else fetches and populates it; adds `X-Cache: HIT | MISS`.\n- **`matchRule(pathname, rules)`** — the shared exact/wildcard matcher behind the two helpers above.\n- **`loadRedirects` / `loadRewrites` / `loadCachePrimingUrls`** — lower-level readers returning parsed config from KV (empty array on missing/invalid keys).\n\n### 🧰 Local development\n\n- **`rewriteRequestToOrigin(request, backendOrigin)`** — builds a new `Request` pointed at `backendOrigin`, preserving path/query/body. Used internally by `functions/dev-worker.edge.js` so `passThrough` reaches your local app.\n\n---\n\n## 🛠️ CLI Commands\n\n| Command | Purpose |\n|---|---|\n| `npx create-launch-edge` | Scaffold `functions/[proxy].edge.js` (production handler) and local-dev files. Creates only what's missing. |\n| `npx launch-edge-quickstart` | **One command**: scaffold + seed + run the whole local KV/cache setup. See [Local testing](#-local-testing). |\n| `npx launch-edge-local` | Interactive wizard — pick a preset (code or KV) and scaffold for it. |\n| `npx launch-edge-seed-local` | Seed the local KV namespace from `launch.json`. |\n| `npx launch-edge-test-local` | Start the local dev server (`wrangler dev`), with automatic cache priming. |\n| `npx launch-config` | Interactive editor for `launch.json` — redirects, rewrites, cache priming, with CSV/JSON bulk import. |\n| `npx launch-help` | Print a full reference of methods and CLI commands. |\n\nAll local-dev commands run from your project root and accept extra flags passed through to `wrangler dev` (e.g. `--port 8788`).\n\n### `npx launch-config` bulk import formats\n\n**CSV** (`redirects.csv`):\n```csv\nsource,destination,statusCode\n/old-blog/post-1,/blog/post-1,301\n/products/old-sku-123,/products/new-sku-456,308\n/legacy/*,/new/*,301\n```\n\n**JSON** (`redirects.json`):\n```json\n[\n  { \"source\": \"/old-blog/post-1\", \"destination\": \"/blog/post-1\", \"statusCode\": 301 },\n  { \"source\": \"/products/old-sku-123\", \"destination\": \"/products/new-sku-456\", \"statusCode\": 308 }\n]\n```\n\nReady-to-use templates: [`examples/redirects.csv`](examples/redirects.csv), [`examples/redirects.json`](examples/redirects.json).\n\n---\n\n## 🌐 Platform Support\n\nBuilt for **[Contentstack Launch](https://www.contentstack.com/docs/developers/launch)** — assumes standard Web APIs (`Request`, `Response`, `fetch`), an edge runtime, and Launch's geo-location headers.\n\nNot intended for Node.js servers, traditional hosting, or other edge platforms (Cloudflare Workers, Vercel Edge, etc.) — though the KV-backed helpers happen to work anywhere Workers-style KV/Cache APIs are available, since that's what powers the local simulation.\n\n---\n\n## 🤝 Contributing\n\nContributions welcome — please open an issue or pull request.\n\n**Repository:** https://github.com/AryanBansal-launch/launch-edge-utils\n\n## 📄 License\n\nDistributed under the MIT License. See `LICENSE` for details.\n\n## 🔗 Useful Links\n\n- **[Contentstack Launch Documentation](https://www.contentstack.com/docs/developers/launch)**\n- **[Edge Functions Guide](https://www.contentstack.com/docs/developers/launch/edge-functions)**\n- **[NPM Package](https://www.npmjs.com/package/@aryanbansal-launch/edge-utils)**\n- **[GitHub Repository](https://github.com/AryanBansal-launch/launch-edge-utils)**\n- **[Architecture: Local Edge Dev Setup](ARCHITECTURE.md)** — deep dive into how local testing, KV simulation, and cache priming work internally\n\n---\n\n**Made with ❤️ for the Contentstack Launch community**\n","readmeFilename":"readme.md"}