{"_id":"@automattic/vip-edge-workers-sdk","_rev":"12-df31ff7c381b94b2f91e61aa68a2ad5b","name":"@automattic/vip-edge-workers-sdk","dist-tags":{"next":"0.3.1","latest":"0.5.0"},"versions":{"0.1.0":{"name":"@automattic/vip-edge-workers-sdk","version":"0.1.0","_id":"@automattic/vip-edge-workers-sdk@0.1.0","maintainers":[{"name":"macbre","email":"maciej.brencz@gmail.com"},{"name":"yuliyan","email":"yuliyan.slavchev@gmail.com"},{"name":"mjangda","email":"batmoo@gmail.com"},{"name":"matticbot","email":"jetpack+engineering@automattic.com"},{"name":"a8c","email":"invoices@automattic.com"},{"name":"blowery","email":"ben@blowery.org"},{"name":"ehg_","email":"chris@ehg.sh"},{"name":"sgomes","email":"mail@sgomes.io"},{"name":"tyxla","email":"tyxla@abv.bg"},{"name":"saroshaga","email":"sarosh.aga@automattic.com"},{"name":"nejclovrencic","email":"nejc.lovrencic@gmail.com"},{"name":"sirbrillig","email":"payton@foolord.com"},{"name":"chriszarate","email":"chris@zarate.org"},{"name":"robersongomes","email":"robersonccgomes@gmail.com"},{"name":"johngodley","email":"johng75@gmail.com"},{"name":"jeherve","email":"jeremy@tagada.hu"},{"name":"daledupreez-a8c","email":"dale@automattic.com"},{"name":"t2dw4t","email":"todd.wright@automattic.com"},{"name":"luismulinari","email":"luis.mulinari@gmail.com"},{"name":"andrea-sdl","email":"andrea.grassi@automattic.com"},{"name":"elazzabi","email":"elazzabi.ahmed@gmail.com"},{"name":"fmfernandes","email":"fernando.fernandes@automattic.com"},{"name":"sirreal","email":"jon.surrell@gmail.com"},{"name":"wwa","email":"volodymyr@wildwolf.name"},{"name":"chihsuan","email":"chihsuan.tw@gmail.com"},{"name":"manzoorwanijk","email":"manzoorwani.jk@gmail.com"},{"name":"msurdi-a8c","email":"matias.emanuel.surdi@automattic.com"},{"name":"newspack-npm","email":"newspack@a8c.com"},{"name":"dsmartg","email":"derek.smart@automattic.com"},{"name":"kthai15","email":"kavin.keratikasama@automattic.com"},{"name":"bgrgicak","email":"berislav.grgicak@gmail.com"},{"name":"robertsreberski_a8c","email":"robert.sreberski@automattic.com"},{"name":"artpi","email":"artur.piszek@gmail.com"},{"name":"gmjuhasz","email":"jugergo@gmail.com"},{"name":"kat3samsin","email":"kat3samsin@gmail.com"},{"name":"brunobasto","email":"b.basto@gmail.com"},{"name":"dhenridev","email":"douglas.henri@automattic.com"},{"name":"mrmurphy","email":"m@mrmurphy.dev"},{"name":"wpvip-bot","email":"platform+npm@wpvip.com"},{"name":"etobiesen","email":"e.tobiesen@gmail.com"},{"name":"alshakero","email":"omar@omaralshaker.com"},{"name":"arthur791004","email":"arthur791004@gmail.com"},{"name":"dilirity","email":"peter.petrov89@gmail.com"},{"name":"mehmoodak","email":"npmjs.corporate906@passinbox.com"},{"name":"natalia.vidal","email":"natalia.vidal@automattic.com"},{"name":"ivan.ottinger","email":"ivan.ottinger@automattic.com"},{"name":"anandnalya","email":"anand.nalya@gmail.com"},{"name":"arcangelinis","email":"anthony.arcangelini@gmail.com"},{"name":"retrofox","email":"rdsuarez@gmail.com"},{"name":"fredrikekelund","email":"fredrik@fredrik.computer"},{"name":"chriskmnds","email":"chriskmnds@gmail.com"},{"name":"oandregal","email":"ola@oandre.gal"},{"name":"galatanovidiu","email":"galatanovidiu@gmail.com"},{"name":"kangzj","email":"kangzjnet@gmail.com"},{"name":"_mirka_","email":"lena@jaguchi.com"},{"name":"aduth","email":"andrew@andrewduthie.com"},{"name":"ebuccelli","email":"emanuele.buccelli@automattic.com"}],"dist":{"shasum":"bbb0f320eef5994a6e0220751d3f6cb67dc880ae","tarball":"https://registry.npmjs.org/@automattic/vip-edge-workers-sdk/-/vip-edge-workers-sdk-0.1.0.tgz","fileCount":8,"integrity":"sha512-SMzvvTfqL67yTx8l/AJWdMu+y5K2c7NNp2LqCffxnN4CbWzzhtbCgsLuYR1pPvO8AKXP+caz40aB+799bC5Pbw==","signatures":[{"sig":"MEQCIAx479Z+096eM7gsL9N6AHWBWXpbmecQSzGSemZQ02LIAiBEFgz5Fc7/HISPQK6e2STMmeRFHRyYsN74i3ik0RjeJA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":80691},"types":"index.ts","ascMain":"assembly/index.ts","gitHead":"8a9f2f43a2e32cdc87ce560683da2a2445027103","_npmUser":{"name":"wpvip-bot","email":"platform+npm@wpvip.com"},"_npmVersion":"10.8.2","description":"AssemblyScript SDK for VIP edge-workers","directories":{},"_nodeVersion":"20.18.0","dependencies":{},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typedoc":"^0.26.11"},"_npmOperationalInternal":{"tmp":"tmp/vip-edge-workers-sdk_0.1.0_1781096890689_0.8976698025648739","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@automattic/vip-edge-workers-sdk","version":"0.2.0","_id":"@automattic/vip-edge-workers-sdk@0.2.0","maintainers":[{"name":"macbre","email":"maciej.brencz@gmail.com"},{"name":"yuliyan","email":"yuliyan.slavchev@gmail.com"},{"name":"mjangda","email":"batmoo@gmail.com"},{"name":"matticbot","email":"jetpack+engineering@automattic.com"},{"name":"a8c","email":"invoices@automattic.com"},{"name":"blowery","email":"ben@blowery.org"},{"name":"ehg_","email":"chris@ehg.sh"},{"name":"sgomes","email":"mail@sgomes.io"},{"name":"tyxla","email":"tyxla@abv.bg"},{"name":"saroshaga","email":"sarosh.aga@automattic.com"},{"name":"nejclovrencic","email":"nejc.lovrencic@gmail.com"},{"name":"sirbrillig","email":"payton@foolord.com"},{"name":"chriszarate","email":"chris@zarate.org"},{"name":"robersongomes","email":"robersonccgomes@gmail.com"},{"name":"johngodley","email":"johng75@gmail.com"},{"name":"jeherve","email":"jeremy@tagada.hu"},{"name":"daledupreez-a8c","email":"dale@automattic.com"},{"name":"t2dw4t","email":"todd.wright@automattic.com"},{"name":"luismulinari","email":"luis.mulinari@gmail.com"},{"name":"andrea-sdl","email":"andrea.grassi@automattic.com"},{"name":"elazzabi","email":"elazzabi.ahmed@gmail.com"},{"name":"fmfernandes","email":"fernando.fernandes@automattic.com"},{"name":"sirreal","email":"jon.surrell@gmail.com"},{"name":"wwa","email":"volodymyr@wildwolf.name"},{"name":"chihsuan","email":"chihsuan.tw@gmail.com"},{"name":"manzoorwanijk","email":"manzoorwani.jk@gmail.com"},{"name":"msurdi-a8c","email":"matias.emanuel.surdi@automattic.com"},{"name":"newspack-npm","email":"newspack@a8c.com"},{"name":"dsmartg","email":"derek.smart@automattic.com"},{"name":"kthai15","email":"kavin.keratikasama@automattic.com"},{"name":"bgrgicak","email":"berislav.grgicak@gmail.com"},{"name":"robertsreberski_a8c","email":"robert.sreberski@automattic.com"},{"name":"artpi","email":"artur.piszek@gmail.com"},{"name":"gmjuhasz","email":"jugergo@gmail.com"},{"name":"kat3samsin","email":"kat3samsin@gmail.com"},{"name":"brunobasto","email":"b.basto@gmail.com"},{"name":"dhenridev","email":"douglas.henri@automattic.com"},{"name":"mrmurphy","email":"m@mrmurphy.dev"},{"name":"wpvip-bot","email":"platform+npm@wpvip.com"},{"name":"etobiesen","email":"e.tobiesen@gmail.com"},{"name":"alshakero","email":"omar@omaralshaker.com"},{"name":"arthur791004","email":"arthur791004@gmail.com"},{"name":"dilirity","email":"peter.petrov89@gmail.com"},{"name":"mehmoodak","email":"npmjs.corporate906@passinbox.com"},{"name":"natalia.vidal","email":"natalia.vidal@automattic.com"},{"name":"ivan.ottinger","email":"ivan.ottinger@automattic.com"},{"name":"anandnalya","email":"anand.nalya@gmail.com"},{"name":"arcangelinis","email":"anthony.arcangelini@gmail.com"},{"name":"retrofox","email":"rdsuarez@gmail.com"},{"name":"fredrikekelund","email":"fredrik@fredrik.computer"},{"name":"chriskmnds","email":"chriskmnds@gmail.com"},{"name":"oandregal","email":"ola@oandre.gal"},{"name":"galatanovidiu","email":"galatanovidiu@gmail.com"},{"name":"kangzj","email":"kangzjnet@gmail.com"},{"name":"_mirka_","email":"lena@jaguchi.com"},{"name":"aduth","email":"andrew@andrewduthie.com"},{"name":"ebuccelli","email":"emanuele.buccelli@automattic.com"}],"dist":{"shasum":"1379beef560e28a7c3c7c10e4e38ed754c211b17","tarball":"https://registry.npmjs.org/@automattic/vip-edge-workers-sdk/-/vip-edge-workers-sdk-0.2.0.tgz","fileCount":8,"integrity":"sha512-L8g8OOJvhDE1YoxZjRQHGPW1+wK/lFg28HjdsHUqNlIM6jlIu3P+5jHvcLlALbIWfbPfAInRnp90CAB5kwXFDA==","signatures":[{"sig":"MEUCIQDP5SLepTFBhdTXD96UG8hOeAUS9zeCoHFjKCQy1ZrxxAIgE0/NsqU6qz+hEGr2fQWSLz3GwtiB4jyysjkiePHlwFs=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":88414},"types":"index.ts","ascMain":"assembly/index.ts","gitHead":"ce75dd441d283003244755f1c8c895fb34e6a5bf","_npmUser":{"name":"wpvip-bot","email":"platform+npm@wpvip.com"},"_npmVersion":"10.8.2","description":"AssemblyScript SDK for VIP edge-workers","directories":{},"_nodeVersion":"20.18.0","dependencies":{},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typedoc":"^0.26.11"},"_npmOperationalInternal":{"tmp":"tmp/vip-edge-workers-sdk_0.2.0_1782402446869_0.5716782476975204","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@automattic/vip-edge-workers-sdk","version":"0.3.0","_id":"@automattic/vip-edge-workers-sdk@0.3.0","maintainers":[{"name":"macbre","email":"maciej.brencz@gmail.com"},{"name":"yuliyan","email":"yuliyan.slavchev@gmail.com"},{"name":"mjangda","email":"batmoo@gmail.com"},{"name":"matticbot","email":"jetpack+engineering@automattic.com"},{"name":"a8c","email":"invoices@automattic.com"},{"name":"blowery","email":"ben@blowery.org"},{"name":"ehg_","email":"chris@ehg.sh"},{"name":"sgomes","email":"mail@sgomes.io"},{"name":"tyxla","email":"tyxla@abv.bg"},{"name":"saroshaga","email":"sarosh.aga@automattic.com"},{"name":"nejclovrencic","email":"nejc.lovrencic@gmail.com"},{"name":"sirbrillig","email":"payton@foolord.com"},{"name":"chriszarate","email":"chris@zarate.org"},{"name":"robersongomes","email":"robersonccgomes@gmail.com"},{"name":"johngodley","email":"johng75@gmail.com"},{"name":"jeherve","email":"jeremy@tagada.hu"},{"name":"daledupreez-a8c","email":"dale@automattic.com"},{"name":"t2dw4t","email":"todd.wright@automattic.com"},{"name":"luismulinari","email":"luis.mulinari@gmail.com"},{"name":"andrea-sdl","email":"andrea.grassi@automattic.com"},{"name":"elazzabi","email":"elazzabi.ahmed@gmail.com"},{"name":"fmfernandes","email":"fernando.fernandes@automattic.com"},{"name":"sirreal","email":"jon.surrell@gmail.com"},{"name":"wwa","email":"volodymyr@wildwolf.name"},{"name":"chihsuan","email":"chihsuan.tw@gmail.com"},{"name":"manzoorwanijk","email":"manzoorwani.jk@gmail.com"},{"name":"msurdi-a8c","email":"matias.emanuel.surdi@automattic.com"},{"name":"newspack-npm","email":"newspack@a8c.com"},{"name":"dsmartg","email":"derek.smart@automattic.com"},{"name":"kthai15","email":"kavin.keratikasama@automattic.com"},{"name":"bgrgicak","email":"berislav.grgicak@gmail.com"},{"name":"robertsreberski_a8c","email":"robert.sreberski@automattic.com"},{"name":"artpi","email":"artur.piszek@gmail.com"},{"name":"gmjuhasz","email":"jugergo@gmail.com"},{"name":"borkweb","email":"borkweb@gmail.com"},{"name":"kat3samsin","email":"kat3samsin@gmail.com"},{"name":"brunobasto","email":"b.basto@gmail.com"},{"name":"dhenridev","email":"douglas.henri@automattic.com"},{"name":"mrmurphy","email":"m@mrmurphy.dev"},{"name":"wpvip-bot","email":"platform+npm@wpvip.com"},{"name":"etobiesen","email":"e.tobiesen@gmail.com"},{"name":"alshakero","email":"omar@omaralshaker.com"},{"name":"arthur791004","email":"arthur791004@gmail.com"},{"name":"dilirity","email":"peter.petrov89@gmail.com"},{"name":"mehmoodak","email":"npmjs.corporate906@passinbox.com"},{"name":"natalia.vidal","email":"natalia.vidal@automattic.com"},{"name":"ivan.ottinger","email":"ivan.ottinger@automattic.com"},{"name":"anandnalya","email":"anand.nalya@gmail.com"},{"name":"arcangelinis","email":"anthony.arcangelini@gmail.com"},{"name":"retrofox","email":"rdsuarez@gmail.com"},{"name":"iamchughmayank","email":"mayank.chugh@automattic.com"},{"name":"simison","email":"mikael@ihminen.org"},{"name":"fredrikekelund","email":"fredrik@fredrik.computer"},{"name":"chriskmnds","email":"chriskmnds@gmail.com"},{"name":"oandregal","email":"ola@oandre.gal"},{"name":"galatanovidiu","email":"galatanovidiu@gmail.com"},{"name":"kangzj","email":"kangzjnet@gmail.com"},{"name":"_mirka_","email":"lena@jaguchi.com"},{"name":"aduth","email":"andrew@andrewduthie.com"},{"name":"ebuccelli","email":"emanuele.buccelli@automattic.com"}],"dist":{"shasum":"2ae2e5c2eefa69a9a626935d66ef61cf4c235c9c","tarball":"https://registry.npmjs.org/@automattic/vip-edge-workers-sdk/-/vip-edge-workers-sdk-0.3.0.tgz","fileCount":8,"integrity":"sha512-4fPjh5c7t1nd+iW58Ag19014YNN64OQDrtjPb278HAFtWiZaRpOLdBO10DPJ/x99DCx+i9n/o/vLEen9jgTPQQ==","signatures":[{"sig":"MEYCIQDCf9JvSBlkZmj4Tj8KrxXoMf+hBNQOTi9gpT1EqQ1n2wIhAOf9sNdux1hrIG6EZ86tb/Xdx7EPAhkVXFB8gBnTb67G","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":97858},"types":"index.ts","ascMain":"assembly/index.ts","gitHead":"a67c0e59e3787ae16101a6d045edbe895800e73f","_npmUser":{"name":"wpvip-bot","email":"platform+npm@wpvip.com"},"_npmVersion":"10.9.2","description":"AssemblyScript SDK for VIP edge-workers","directories":{},"_nodeVersion":"22.13.1","dependencies":{},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typedoc":"^0.26.11"},"_npmOperationalInternal":{"tmp":"tmp/vip-edge-workers-sdk_0.3.0_1784119170872_0.8047337615674279","host":"s3://npm-registry-packages-npm-production"}},"0.3.1":{"name":"@automattic/vip-edge-workers-sdk","version":"0.3.1","_id":"@automattic/vip-edge-workers-sdk@0.3.1","maintainers":[{"name":"macbre","email":"maciej.brencz@gmail.com"},{"name":"yuliyan","email":"yuliyan.slavchev@gmail.com"},{"name":"mjangda","email":"batmoo@gmail.com"},{"name":"matticbot","email":"jetpack+engineering@automattic.com"},{"name":"a8c","email":"invoices@automattic.com"},{"name":"blowery","email":"ben@blowery.org"},{"name":"ehg_","email":"chris@ehg.sh"},{"name":"sgomes","email":"mail@sgomes.io"},{"name":"tyxla","email":"tyxla@abv.bg"},{"name":"saroshaga","email":"sarosh.aga@automattic.com"},{"name":"nejclovrencic","email":"nejc.lovrencic@gmail.com"},{"name":"sirbrillig","email":"payton@foolord.com"},{"name":"chriszarate","email":"chris@zarate.org"},{"name":"robersongomes","email":"robersonccgomes@gmail.com"},{"name":"johngodley","email":"johng75@gmail.com"},{"name":"jeherve","email":"jeremy@tagada.hu"},{"name":"daledupreez-a8c","email":"dale@automattic.com"},{"name":"t2dw4t","email":"todd.wright@automattic.com"},{"name":"luismulinari","email":"luis.mulinari@gmail.com"},{"name":"andrea-sdl","email":"andrea.grassi@automattic.com"},{"name":"elazzabi","email":"elazzabi.ahmed@gmail.com"},{"name":"fmfernandes","email":"fernando.fernandes@automattic.com"},{"name":"sirreal","email":"jon.surrell@gmail.com"},{"name":"wwa","email":"volodymyr@wildwolf.name"},{"name":"chihsuan","email":"chihsuan.tw@gmail.com"},{"name":"manzoorwanijk","email":"manzoorwani.jk@gmail.com"},{"name":"msurdi-a8c","email":"matias.emanuel.surdi@automattic.com"},{"name":"newspack-npm","email":"newspack@a8c.com"},{"name":"dsmartg","email":"derek.smart@automattic.com"},{"name":"kthai15","email":"kavin.keratikasama@automattic.com"},{"name":"bgrgicak","email":"berislav.grgicak@gmail.com"},{"name":"robertsreberski_a8c","email":"robert.sreberski@automattic.com"},{"name":"artpi","email":"artur.piszek@gmail.com"},{"name":"gmjuhasz","email":"jugergo@gmail.com"},{"name":"borkweb","email":"borkweb@gmail.com"},{"name":"kat3samsin","email":"kat3samsin@gmail.com"},{"name":"brunobasto","email":"b.basto@gmail.com"},{"name":"dhenridev","email":"douglas.henri@automattic.com"},{"name":"mrmurphy","email":"m@mrmurphy.dev"},{"name":"wpvip-bot","email":"platform+npm@wpvip.com"},{"name":"etobiesen","email":"e.tobiesen@gmail.com"},{"name":"alshakero","email":"omar@omaralshaker.com"},{"name":"arthur791004","email":"arthur791004@gmail.com"},{"name":"dilirity","email":"peter.petrov89@gmail.com"},{"name":"mehmoodak","email":"npmjs.corporate906@passinbox.com"},{"name":"natalia.vidal","email":"natalia.vidal@automattic.com"},{"name":"ivan.ottinger","email":"ivan.ottinger@automattic.com"},{"name":"anandnalya","email":"anand.nalya@gmail.com"},{"name":"arcangelinis","email":"anthony.arcangelini@gmail.com"},{"name":"retrofox","email":"rdsuarez@gmail.com"},{"name":"iamchughmayank","email":"mayank.chugh@automattic.com"},{"name":"simison","email":"mikael@ihminen.org"},{"name":"fredrikekelund","email":"fredrik@fredrik.computer"},{"name":"chriskmnds","email":"chriskmnds@gmail.com"},{"name":"oandregal","email":"ola@oandre.gal"},{"name":"galatanovidiu","email":"galatanovidiu@gmail.com"},{"name":"kangzj","email":"kangzjnet@gmail.com"},{"name":"_mirka_","email":"lena@jaguchi.com"},{"name":"aduth","email":"andrew@andrewduthie.com"},{"name":"ebuccelli","email":"emanuele.buccelli@automattic.com"}],"homepage":"https://github.com/Automattic/vip-edge-workers-sdk#readme","bugs":{"url":"https://github.com/Automattic/vip-edge-workers-sdk/issues"},"dist":{"shasum":"6250eb6b26188754f929613611db1cd158de9826","tarball":"https://registry.npmjs.org/@automattic/vip-edge-workers-sdk/-/vip-edge-workers-sdk-0.3.1.tgz","fileCount":51,"integrity":"sha512-4nd2NvcW1gvxnHqBSkTH1atqVw0O/wzSbpRaLh4NfRlgwHZlKwuB0tRHHjisFVXsJiQdSCr274ObhnXsCScpDw==","signatures":[{"sig":"MEUCIQC4KiBFn7eRNYNILhNT9MdA/o1YDHXy5nqNq5Y9kg3VngIga2lRRkA2DAzDeEbls3pefT5z/KzFm+XVK77dGSmmSX8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@automattic%2fvip-edge-workers-sdk@0.3.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":155470},"types":"index.d.ts","ascMain":"assembly/index.ts","exports":{".":{"types":"./index.d.ts","default":"./index.ts"},"./assembly/index":{"types":"./assembly/index.d.ts","default":"./assembly/index.ts"}},"gitHead":"065c66181e8b2030266ddea9c67fb4e998a80417","scripts":{"test":"node --test tests/*.test.mjs","version":"npm run sync-example-lockfile-versions","sync-example-lockfile-versions":"node scripts/sync-example-lockfile-versions.mjs"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:8ca1561e-2fcf-458e-b77b-78024545c9d9"}},"repository":{"url":"git+https://github.com/Automattic/vip-edge-workers-sdk.git","type":"git"},"_npmVersion":"11.19.0","description":"AssemblyScript SDK for VIP edge-workers","directories":{},"_nodeVersion":"24.19.0","dependencies":{},"publishConfig":{"access":"public"},"typesVersions":{"*":{"assembly/index":["assembly/index.d.ts"]}},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"typedoc":"^0.26.11","assemblyscript":"^0.27.0"},"_npmOperationalInternal":{"tmp":"tmp/vip-edge-workers-sdk_0.3.1_1787245037580_0.165228538475108","host":"s3://npm-registry-packages-npm-production"}},"0.3.2":{"name":"@automattic/vip-edge-workers-sdk","version":"0.3.2","_id":"@automattic/vip-edge-workers-sdk@0.3.2","maintainers":[{"name":"macbre","email":"maciej.brencz@gmail.com"},{"name":"yuliyan","email":"yuliyan.slavchev@gmail.com"},{"name":"mjangda","email":"batmoo@gmail.com"},{"name":"matticbot","email":"jetpack+engineering@automattic.com"},{"name":"a8c","email":"invoices@automattic.com"},{"name":"blowery","email":"ben@blowery.org"},{"name":"ehg_","email":"chris@ehg.sh"},{"name":"sgomes","email":"mail@sgomes.io"},{"name":"tyxla","email":"tyxla@abv.bg"},{"name":"saroshaga","email":"sarosh.aga@automattic.com"},{"name":"nejclovrencic","email":"nejc.lovrencic@gmail.com"},{"name":"sirbrillig","email":"payton@foolord.com"},{"name":"chriszarate","email":"chris@zarate.org"},{"name":"robersongomes","email":"robersonccgomes@gmail.com"},{"name":"johngodley","email":"johng75@gmail.com"},{"name":"jeherve","email":"jeremy@tagada.hu"},{"name":"daledupreez-a8c","email":"dale@automattic.com"},{"name":"t2dw4t","email":"todd.wright@automattic.com"},{"name":"luismulinari","email":"luis.mulinari@gmail.com"},{"name":"andrea-sdl","email":"andrea.grassi@automattic.com"},{"name":"elazzabi","email":"elazzabi.ahmed@gmail.com"},{"name":"fmfernandes","email":"fernando.fernandes@automattic.com"},{"name":"sirreal","email":"jon.surrell@gmail.com"},{"name":"wwa","email":"volodymyr@wildwolf.name"},{"name":"chihsuan","email":"chihsuan.tw@gmail.com"},{"name":"manzoorwanijk","email":"manzoorwani.jk@gmail.com"},{"name":"msurdi-a8c","email":"matias.emanuel.surdi@automattic.com"},{"name":"newspack-npm","email":"newspack@a8c.com"},{"name":"dsmartg","email":"derek.smart@automattic.com"},{"name":"kthai15","email":"kavin.keratikasama@automattic.com"},{"name":"bgrgicak","email":"berislav.grgicak@gmail.com"},{"name":"robertsreberski_a8c","email":"robert.sreberski@automattic.com"},{"name":"artpi","email":"artur.piszek@gmail.com"},{"name":"gmjuhasz","email":"jugergo@gmail.com"},{"name":"borkweb","email":"borkweb@gmail.com"},{"name":"kat3samsin","email":"kat3samsin@gmail.com"},{"name":"brunobasto","email":"b.basto@gmail.com"},{"name":"dhenridev","email":"douglas.henri@automattic.com"},{"name":"mrmurphy","email":"m@mrmurphy.dev"},{"name":"wpvip-bot","email":"platform+npm@wpvip.com"},{"name":"etobiesen","email":"e.tobiesen@gmail.com"},{"name":"alshakero","email":"omar@omaralshaker.com"},{"name":"arthur791004","email":"arthur791004@gmail.com"},{"name":"dilirity","email":"peter.petrov89@gmail.com"},{"name":"mehmoodak","email":"npmjs.corporate906@passinbox.com"},{"name":"natalia.vidal","email":"natalia.vidal@automattic.com"},{"name":"ivan.ottinger","email":"ivan.ottinger@automattic.com"},{"name":"anandnalya","email":"anand.nalya@gmail.com"},{"name":"arcangelinis","email":"anthony.arcangelini@gmail.com"},{"name":"retrofox","email":"rdsuarez@gmail.com"},{"name":"iamchughmayank","email":"mayank.chugh@automattic.com"},{"name":"simison","email":"mikael@ihminen.org"},{"name":"fredrikekelund","email":"fredrik@fredrik.computer"},{"name":"chriskmnds","email":"chriskmnds@gmail.com"},{"name":"oandregal","email":"ola@oandre.gal"},{"name":"galatanovidiu","email":"galatanovidiu@gmail.com"},{"name":"kangzj","email":"kangzjnet@gmail.com"},{"name":"_mirka_","email":"lena@jaguchi.com"},{"name":"aduth","email":"andrew@andrewduthie.com"},{"name":"ebuccelli","email":"emanuele.buccelli@automattic.com"}],"homepage":"https://github.com/Automattic/vip-edge-workers-sdk#readme","bugs":{"url":"https://github.com/Automattic/vip-edge-workers-sdk/issues"},"dist":{"shasum":"49e3505f8931976feb5d341eafb89c138218e565","tarball":"https://registry.npmjs.org/@automattic/vip-edge-workers-sdk/-/vip-edge-workers-sdk-0.3.2.tgz","fileCount":51,"integrity":"sha512-NpHtcVEbDRAXFUSRLpXyKuRP5MOpeftZJwr2veK0lFf20VDzwCsQ7AQiy2snUORinlUPoZWCmOYzdImKVshZpw==","signatures":[{"sig":"MEQCIG9YF7KTgfnQpa5C7ecPKnXntA/0I9tHm+sodsFFpyPRAiAudgd27rF52bujrdYokwNylm0ssSSUgDfCjEyLfPMcbA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@automattic%2fvip-edge-workers-sdk@0.3.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":155470},"types":"index.d.ts","ascMain":"assembly/index.ts","exports":{".":{"types":"./index.d.ts","default":"./index.ts"},"./assembly/index":{"types":"./assembly/index.d.ts","default":"./assembly/index.ts"}},"gitHead":"e4a5392fd6c93d7440c8ca92e510a485d28d836a","scripts":{"test":"node --test tests/*.test.mjs","version":"npm run sync-example-lockfile-versions","sync-example-lockfile-versions":"node scripts/sync-example-lockfile-versions.mjs"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:8ca1561e-2fcf-458e-b77b-78024545c9d9"}},"repository":{"url":"git+https://github.com/Automattic/vip-edge-workers-sdk.git","type":"git"},"_npmVersion":"11.19.0","description":"AssemblyScript SDK for VIP edge-workers","directories":{},"_nodeVersion":"24.19.0","dependencies":{},"publishConfig":{"access":"public"},"typesVersions":{"*":{"assembly/index":["assembly/index.d.ts"]}},"_hasShrinkwrap":false,"devDependencies":{"typedoc":"^0.26.11","assemblyscript":"^0.27.0"},"_npmOperationalInternal":{"tmp":"tmp/vip-edge-workers-sdk_0.3.2_1787245444309_0.29429669557026417","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"@automattic/vip-edge-workers-sdk","version":"0.4.0","_id":"@automattic/vip-edge-workers-sdk@0.4.0","maintainers":[{"name":"macbre","email":"maciej.brencz@gmail.com"},{"name":"yuliyan","email":"yuliyan.slavchev@gmail.com"},{"name":"mjangda","email":"batmoo@gmail.com"},{"name":"matticbot","email":"jetpack+engineering@automattic.com"},{"name":"a8c","email":"invoices@automattic.com"},{"name":"blowery","email":"ben@blowery.org"},{"name":"ehg_","email":"chris@ehg.sh"},{"name":"sgomes","email":"mail@sgomes.io"},{"name":"tyxla","email":"tyxla@abv.bg"},{"name":"saroshaga","email":"sarosh.aga@automattic.com"},{"name":"nejclovrencic","email":"nejc.lovrencic@gmail.com"},{"name":"sirbrillig","email":"payton@foolord.com"},{"name":"chriszarate","email":"chris@zarate.org"},{"name":"robersongomes","email":"robersonccgomes@gmail.com"},{"name":"johngodley","email":"johng75@gmail.com"},{"name":"jeherve","email":"jeremy@tagada.hu"},{"name":"daledupreez-a8c","email":"dale@automattic.com"},{"name":"t2dw4t","email":"todd.wright@automattic.com"},{"name":"luismulinari","email":"luis.mulinari@gmail.com"},{"name":"andrea-sdl","email":"andrea.grassi@automattic.com"},{"name":"elazzabi","email":"elazzabi.ahmed@gmail.com"},{"name":"fmfernandes","email":"fernando.fernandes@automattic.com"},{"name":"sirreal","email":"jon.surrell@gmail.com"},{"name":"wwa","email":"volodymyr@wildwolf.name"},{"name":"chihsuan","email":"chihsuan.tw@gmail.com"},{"name":"manzoorwanijk","email":"manzoorwani.jk@gmail.com"},{"name":"msurdi-a8c","email":"matias.emanuel.surdi@automattic.com"},{"name":"newspack-npm","email":"newspack@a8c.com"},{"name":"dsmartg","email":"derek.smart@automattic.com"},{"name":"kthai15","email":"kavin.keratikasama@automattic.com"},{"name":"bgrgicak","email":"berislav.grgicak@gmail.com"},{"name":"robertsreberski_a8c","email":"robert.sreberski@automattic.com"},{"name":"artpi","email":"artur.piszek@gmail.com"},{"name":"gmjuhasz","email":"jugergo@gmail.com"},{"name":"borkweb","email":"borkweb@gmail.com"},{"name":"kat3samsin","email":"kat3samsin@gmail.com"},{"name":"brunobasto","email":"b.basto@gmail.com"},{"name":"dhenridev","email":"douglas.henri@automattic.com"},{"name":"mrmurphy","email":"m@mrmurphy.dev"},{"name":"wpvip-bot","email":"platform+npm@wpvip.com"},{"name":"etobiesen","email":"e.tobiesen@gmail.com"},{"name":"alshakero","email":"omar@omaralshaker.com"},{"name":"arthur791004","email":"arthur791004@gmail.com"},{"name":"dilirity","email":"peter.petrov89@gmail.com"},{"name":"mehmoodak","email":"npmjs.corporate906@passinbox.com"},{"name":"natalia.vidal","email":"natalia.vidal@automattic.com"},{"name":"ivan.ottinger","email":"ivan.ottinger@automattic.com"},{"name":"anandnalya","email":"anand.nalya@gmail.com"},{"name":"arcangelinis","email":"anthony.arcangelini@gmail.com"},{"name":"retrofox","email":"rdsuarez@gmail.com"},{"name":"iamchughmayank","email":"mayank.chugh@automattic.com"},{"name":"simison","email":"mikael@ihminen.org"},{"name":"fredrikekelund","email":"fredrik@fredrik.computer"},{"name":"chriskmnds","email":"chriskmnds@gmail.com"},{"name":"oandregal","email":"ola@oandre.gal"},{"name":"galatanovidiu","email":"galatanovidiu@gmail.com"},{"name":"kangzj","email":"kangzjnet@gmail.com"},{"name":"_mirka_","email":"lena@jaguchi.com"},{"name":"aduth","email":"andrew@andrewduthie.com"},{"name":"ebuccelli","email":"emanuele.buccelli@automattic.com"}],"dist":{"shasum":"2af29c70ca29dcc2c94a011d43e5778bfb02c16b","tarball":"https://registry.npmjs.org/@automattic/vip-edge-workers-sdk/-/vip-edge-workers-sdk-0.4.0.tgz","fileCount":51,"integrity":"sha512-i2KlAjktOH/tfmmnb7KdaDxDTmRFQ5+pmO6c56eFSDIbeNN8PXsQebEJmSpAGn6i9vhhEW2G+xZuWA5snuB51Q==","signatures":[{"sig":"MEUCIQC8lOtqp6iL72XC6rvQslr5uRilY1UGEcFNiTZqQe8gRwIgQIMOwpPqUwQ6x1N+wB6trQHtkA7bYsZOnnKLiZxMAZY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":156985},"types":"index.d.ts","ascMain":"assembly/index.ts","exports":{".":{"types":"./index.d.ts","default":"./index.ts"},"./assembly/index":{"types":"./assembly/index.d.ts","default":"./assembly/index.ts"}},"gitHead":"f79699bbfc30fed74581224a5ccaf5410a264bba","scripts":{"test":"node --test tests/*.test.mjs"},"_npmUser":{"name":"wpvip-bot","email":"platform+npm@wpvip.com"},"_npmVersion":"10.9.2","description":"AssemblyScript SDK for VIP edge-workers","directories":{},"_nodeVersion":"22.13.1","dependencies":{},"publishConfig":{"access":"public"},"typesVersions":{"*":{"assembly/index":["assembly/index.d.ts"]}},"_hasShrinkwrap":false,"devDependencies":{"typedoc":"^0.26.11","assemblyscript":"^0.27.0"},"_npmOperationalInternal":{"tmp":"tmp/vip-edge-workers-sdk_0.4.0_1788439206331_0.8120531264761492","host":"s3://npm-registry-packages-npm-production"}},"0.5.0":{"name":"@automattic/vip-edge-workers-sdk","version":"0.5.0","_id":"@automattic/vip-edge-workers-sdk@0.5.0","maintainers":[{"name":"macbre","email":"maciej.brencz@gmail.com"},{"name":"yuliyan","email":"yuliyan.slavchev@gmail.com"},{"name":"mjangda","email":"batmoo@gmail.com"},{"name":"matticbot","email":"jetpack+engineering@automattic.com"},{"name":"a8c","email":"invoices@automattic.com"},{"name":"blowery","email":"ben@blowery.org"},{"name":"ehg_","email":"chris@ehg.sh"},{"name":"sgomes","email":"mail@sgomes.io"},{"name":"tyxla","email":"tyxla@abv.bg"},{"name":"saroshaga","email":"sarosh.aga@automattic.com"},{"name":"nejclovrencic","email":"nejc.lovrencic@gmail.com"},{"name":"sirbrillig","email":"payton@foolord.com"},{"name":"chriszarate","email":"chris@zarate.org"},{"name":"robersongomes","email":"robersonccgomes@gmail.com"},{"name":"johngodley","email":"johng75@gmail.com"},{"name":"jeherve","email":"jeremy@tagada.hu"},{"name":"daledupreez-a8c","email":"dale@automattic.com"},{"name":"t2dw4t","email":"todd.wright@automattic.com"},{"name":"luismulinari","email":"luis.mulinari@gmail.com"},{"name":"andrea-sdl","email":"andrea.grassi@automattic.com"},{"name":"elazzabi","email":"elazzabi.ahmed@gmail.com"},{"name":"fmfernandes","email":"fernando.fernandes@automattic.com"},{"name":"sirreal","email":"jon.surrell@gmail.com"},{"name":"wwa","email":"volodymyr@wildwolf.name"},{"name":"chihsuan","email":"chihsuan.tw@gmail.com"},{"name":"manzoorwanijk","email":"manzoorwani.jk@gmail.com"},{"name":"msurdi-a8c","email":"matias.emanuel.surdi@automattic.com"},{"name":"newspack-npm","email":"newspack@a8c.com"},{"name":"dsmartg","email":"derek.smart@automattic.com"},{"name":"kthai15","email":"kavin.keratikasama@automattic.com"},{"name":"bgrgicak","email":"berislav.grgicak@gmail.com"},{"name":"robertsreberski_a8c","email":"robert.sreberski@automattic.com"},{"name":"artpi","email":"artur.piszek@gmail.com"},{"name":"gmjuhasz","email":"jugergo@gmail.com"},{"name":"borkweb","email":"borkweb@gmail.com"},{"name":"kat3samsin","email":"kat3samsin@gmail.com"},{"name":"brunobasto","email":"b.basto@gmail.com"},{"name":"dhenridev","email":"douglas.henri@automattic.com"},{"name":"mrmurphy","email":"m@mrmurphy.dev"},{"name":"wpvip-bot","email":"platform+npm@wpvip.com"},{"name":"etobiesen","email":"e.tobiesen@gmail.com"},{"name":"alshakero","email":"omar@omaralshaker.com"},{"name":"arthur791004","email":"arthur791004@gmail.com"},{"name":"dilirity","email":"peter.petrov89@gmail.com"},{"name":"mehmoodak","email":"npmjs.corporate906@passinbox.com"},{"name":"natalia.vidal","email":"natalia.vidal@automattic.com"},{"name":"ivan.ottinger","email":"ivan.ottinger@automattic.com"},{"name":"anandnalya","email":"anand.nalya@gmail.com"},{"name":"arcangelinis","email":"anthony.arcangelini@gmail.com"},{"name":"retrofox","email":"rdsuarez@gmail.com"},{"name":"iamchughmayank","email":"mayank.chugh@automattic.com"},{"name":"simison","email":"mikael@ihminen.org"},{"name":"fredrikekelund","email":"fredrik@fredrik.computer"},{"name":"chriskmnds","email":"chriskmnds@gmail.com"},{"name":"oandregal","email":"ola@oandre.gal"},{"name":"galatanovidiu","email":"galatanovidiu@gmail.com"},{"name":"kangzj","email":"kangzjnet@gmail.com"},{"name":"_mirka_","email":"lena@jaguchi.com"},{"name":"aduth","email":"andrew@andrewduthie.com"},{"name":"ebuccelli","email":"emanuele.buccelli@automattic.com"}],"homepage":"https://github.com/Automattic/vip-edge-workers-sdk#readme","bugs":{"url":"https://github.com/Automattic/vip-edge-workers-sdk/issues"},"dist":{"shasum":"5a0290df802b7f22b24a9757275ed2d7eb161f7b","tarball":"https://registry.npmjs.org/@automattic/vip-edge-workers-sdk/-/vip-edge-workers-sdk-0.5.0.tgz","fileCount":52,"integrity":"sha512-3bJ58dTWefLLu4b7QfbB/1e6pFZ8iWeUxsKQRR+KczVBvYWklZL1dm8LwZXX3i+ydGT0smBQCakxVIikuLJJ0g==","signatures":[{"sig":"MEUCIGizpih76cw51SkdSJ3wueeDoAcbYJwcGtBi+5KeHvM7AiEAkPaFSUDASyLORbpxgrvv02G9j9PhpnSpwLBO5mbo/nU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@automattic%2fvip-edge-workers-sdk@0.5.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":176411},"types":"index.d.ts","ascMain":"assembly/index.ts","exports":{".":{"types":"./index.d.ts","default":"./index.ts"},"./assembly/index":{"types":"./assembly/index.d.ts","default":"./assembly/index.ts"}},"gitHead":"faf304387eb90cb4fb5c8d6afacf1945a68314e4","scripts":{"test":"node --test tests/*.test.mjs","version":"npm run sync-example-lockfile-versions","sync-example-lockfile-versions":"node scripts/sync-example-lockfile-versions.mjs"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:8ca1561e-2fcf-458e-b77b-78024545c9d9"}},"repository":{"url":"git+https://github.com/Automattic/vip-edge-workers-sdk.git","type":"git"},"_npmVersion":"11.19.1","description":"AssemblyScript SDK for VIP edge-workers","directories":{},"_nodeVersion":"24.20.0","dependencies":{},"publishConfig":{"access":"public"},"typesVersions":{"*":{"assembly/index":["assembly/index.d.ts"]}},"_hasShrinkwrap":false,"devDependencies":{"typedoc":"^0.26.11","assemblyscript":"^0.27.0"},"_npmOperationalInternal":{"tmp":"tmp/vip-edge-workers-sdk_0.5.0_1789149093528_0.2988875457559077","host":"s3://npm-registry-packages-npm-production"}}},"time":{"created":"2026-06-10T13:08:10.559Z","modified":"2026-09-25T20:24:28.108Z","0.1.0":"2026-06-10T13:08:10.832Z","0.2.0":"2026-06-25T15:47:27.025Z","0.3.0":"2026-07-15T12:39:31.063Z","0.3.1":"2026-08-20T16:57:17.719Z","0.3.2":"2026-08-20T17:04:04.483Z","0.4.0":"2026-09-03T12:40:06.470Z","0.5.0":"2026-09-11T17:51:33.656Z"},"bugs":{"url":"https://github.com/Automattic/vip-edge-workers-sdk/issues"},"homepage":"https://github.com/Automattic/vip-edge-workers-sdk#readme","repository":{"url":"git+https://github.com/Automattic/vip-edge-workers-sdk.git","type":"git"},"description":"AssemblyScript SDK for VIP edge-workers","maintainers":[{"email":"maciej.brencz@gmail.com","name":"macbre"},{"email":"yuliyan.slavchev@gmail.com","name":"yuliyan"},{"email":"batmoo@gmail.com","name":"mjangda"},{"email":"jetpack+engineering@automattic.com","name":"matticbot"},{"email":"invoices@automattic.com","name":"a8c"},{"email":"ben@blowery.org","name":"blowery"},{"email":"chris@ehg.sh","name":"ehg_"},{"email":"mail@sgomes.io","name":"sgomes"},{"email":"tyxla@abv.bg","name":"tyxla"},{"email":"sarosh.aga@automattic.com","name":"saroshaga"},{"email":"nejc.lovrencic@gmail.com","name":"nejclovrencic"},{"email":"payton@foolord.com","name":"sirbrillig"},{"email":"chris@zarate.org","name":"chriszarate"},{"email":"robersonccgomes@gmail.com","name":"robersongomes"},{"email":"johng75@gmail.com","name":"johngodley"},{"email":"jeremy@tagada.hu","name":"jeherve"},{"email":"dale@automattic.com","name":"daledupreez-a8c"},{"email":"todd.wright@automattic.com","name":"t2dw4t"},{"email":"luis.mulinari@gmail.com","name":"luismulinari"},{"email":"andrea.grassi@automattic.com","name":"andrea-sdl"},{"email":"elazzabi.ahmed@gmail.com","name":"elazzabi"},{"email":"fernando.fernandes@automattic.com","name":"fmfernandes"},{"email":"jon.surrell@gmail.com","name":"sirreal"},{"email":"volodymyr@wildwolf.name","name":"wwa"},{"email":"chihsuan.tw@gmail.com","name":"chihsuan"},{"email":"manzoorwani.jk@gmail.com","name":"manzoorwanijk"},{"email":"matias.emanuel.surdi@automattic.com","name":"msurdi-a8c"},{"email":"newspack@a8c.com","name":"newspack-npm"},{"email":"derek.smart@automattic.com","name":"dsmartg"},{"email":"kavin.keratikasama@automattic.com","name":"kthai15"},{"email":"berislav.grgicak@gmail.com","name":"bgrgicak"},{"email":"robert.sreberski@automattic.com","name":"robertsreberski_a8c"},{"email":"artur.piszek@gmail.com","name":"artpi"},{"email":"jugergo@gmail.com","name":"gmjuhasz"},{"email":"borkweb@gmail.com","name":"borkweb"},{"email":"kat3samsin@gmail.com","name":"kat3samsin"},{"email":"b.basto@gmail.com","name":"brunobasto"},{"email":"douglas.henri@automattic.com","name":"dhenridev"},{"email":"m@mrmurphy.dev","name":"mrmurphy"},{"email":"platform+npm@wpvip.com","name":"wpvip-bot"},{"email":"e.tobiesen@gmail.com","name":"etobiesen"},{"email":"omar@omaralshaker.com","name":"alshakero"},{"email":"arthur791004@gmail.com","name":"arthur791004"},{"email":"peter.petrov89@gmail.com","name":"dilirity"},{"email":"npmjs.corporate906@passinbox.com","name":"mehmoodak"},{"email":"natalia.vidal@automattic.com","name":"natalia.vidal"},{"email":"ivan.ottinger@automattic.com","name":"ivan.ottinger"},{"email":"anand.nalya@gmail.com","name":"anandnalya"},{"email":"anthony.arcangelini@gmail.com","name":"arcangelinis"},{"email":"rdsuarez@gmail.com","name":"retrofox"},{"email":"mayank.chugh@automattic.com","name":"iamchughmayank"},{"email":"mikael@ihminen.org","name":"simison"},{"email":"fredrik@fredrik.computer","name":"fredrikekelund"},{"email":"griffith.chen@automattic.com","name":"griffithchen"},{"email":"josh.boland@automattic.com","name":"jboland8"},{"email":"chriskmnds@gmail.com","name":"chriskmnds"},{"email":"ola@oandre.gal","name":"oandregal"},{"email":"galatanovidiu@gmail.com","name":"galatanovidiu"},{"email":"kangzjnet@gmail.com","name":"kangzj"},{"email":"lena@jaguchi.com","name":"_mirka_"},{"email":"andrew@andrewduthie.com","name":"aduth"},{"email":"emanuele.buccelli@automattic.com","name":"ebuccelli"}],"readme":"# @automattic/vip-edge-workers-sdk\n\nEdge Workers let you run code at the CDN layer — before the cache, after the cache, before the origin, after the origin — with sub-millisecond overhead on every request. This SDK gives you the building blocks to write those workers in [AssemblyScript](https://www.assemblyscript.org/), a TypeScript-flavored language that compiles directly to WebAssembly (WASM).\n\nYou write your worker as a set of handlers for whichever HTTP lifecycle phases you care about. The SDK handles all the plumbing — marshalling request and response data in and out of the WASM sandbox, managing the low-level ABI between the host runtime and your code — so you can focus on what your worker actually does: rewriting headers, short-circuiting to an early response, calling an upstream API, reading from a shared key-value store, or enforcing a rate limit.\n\nThe compiled `.wasm` binary is what you deploy. It's typically a few kilobytes, cold-starts in microseconds, and runs in strict isolation — a fresh instance per request with no shared state between tenants.\n\n## Install\n\n```bash\nnpm install @automattic/vip-edge-workers-sdk\n```\n\n## Quick start\n\n```ts\nimport { onClientRequest, onClientResponse } from \"@automattic/vip-edge-workers-sdk\";\n\n// Re-export the ABI symbols for each phase you handle.\n// alloc is always required.\nexport {\n  alloc,\n  on_client_request,\n  on_client_response,\n} from \"@automattic/vip-edge-workers-sdk/assembly/index\";\n\nonClientRequest((req) => {\n  if (req.url == \"/healthz\") {\n    req.respondText(200, \"ok\");  // short-circuit: skip origin entirely\n    return;\n  }\n  req.headers.set(\"x-edge-worker\", \"true\");\n});\n\nonClientResponse((resp) => {\n  resp.headers.set(\"x-served-by\", \"edge\");\n});\n```\n\n## Phases\n\nThe host invokes the worker at up to four points per request:\n\n| Phase | Register with | ABI export | Body marker | When it runs |\n| --- | --- | --- | --- | --- |\n| Client request | `onClientRequest` | `on_client_request` | `client_request_body` | Before cache lookup. Only phase that can call `fetch()`. |\n| Origin request | `onOriginRequest` | `on_origin_request` | `origin_request_body` | Cache miss, before forwarding to origin. |\n| Client response | `onClientResponse` | `on_client_response` | `client_response_body` | After cache lookup, before sending to client. |\n| Origin response | `onOriginResponse` | `on_origin_response` | `origin_response_body` | Cache miss, after origin responds. |\n\nOnly re-export the ABI symbols for phases your worker handles. `alloc` is always required. Re-export a body marker only when that phase needs the body buffered (see [Body access](#body-access)).\n\n## Phase isolation\n\nEach phase handler runs as an **isolated invocation**. The host marshals the request (or response) into your worker, runs the one handler, and marshals the result back out — then repeats, from a clean slate, for the next phase. Two consequences trip people up:\n\n**1. Module state does not survive between phases.** A module-level variable set in one handler is back at its initial value by the time the next phase runs. This is the single most common mistake — it looks correct and compiles cleanly, but the flag is always false:\n\n```ts\n// BROKEN — `tag` is not shared across phases; it resets before onClientResponse runs.\nlet tag = false;\nonClientRequest((req) => { tag = req.url.includes(\"debug\"); });\nonClientResponse((resp) => { if (tag) resp.headers.set(\"x-debug\", \"1\"); }); // never fires\n```\n\n### Sharing data across phases\n\n| You want to… | Do this |\n| --- | --- |\n| Carry a value between two **request** phases (`onClientRequest` → `onOriginRequest`) | Mutate the request itself — e.g. `req.headers.set(\"x-my-flag\", \"1\")`. Request mutations are marshaled forward to the next request phase (this is also how you change what origin sees). |\n| Share data across **requests** | Use [`KV`](#kv) — the only store that persists beyond a single request. |\n\n## API\n\n### Registration\n\n```ts\nonClientRequest((req: Request) => void): void\nonOriginRequest((req: Request) => void): void\nonClientResponse((resp: Response) => void): void\nonOriginResponse((resp: Response) => void): void\n```\n\nMutate `req` / `resp` in place. In request phases, call `req.respondWith()` or `req.respondText()` to return an early response without hitting origin or cache.\n\n---\n\n### Body access\n\nBy default, `req.body` and `resp.body` are `null` — the host streams the body without buffering it. To have the body populated for a given phase, add its body marker to your ABI re-export block:\n\n```ts\nimport { onClientRequest } from \"@automattic/vip-edge-workers-sdk\";\n\nexport {\n  alloc,\n  on_client_request,\n  client_request_body,          // ← tells the host to buffer the request body\n} from \"@automattic/vip-edge-workers-sdk/assembly/index\";\n\nonClientRequest((req) => {\n  const body = req.text();      // populated because the marker is exported\n});\n```\n\n| Phase | Marker |\n| --- | --- |\n| Client request | `client_request_body` |\n| Origin request | `origin_request_body` |\n| Client response | `client_response_body` |\n| Origin response | `origin_response_body` |\n\nThe marker is a compile-time signal — its presence in the binary is what matters, not any runtime call. Workers that omit a marker pay no buffering cost for that phase.\n\n---\n\n### `Headers`\n\n`Headers` is a WHATWG-style view over a message's headers, exposed as `req.headers` and `resp.headers`. It mirrors the [browser `Headers`](https://developer.mozilla.org/en-US/docs/Web/API/Headers) interface, with two deliberate departures forced by AssemblyScript: it is **not iterable** (no `for…of` / spread — use `entries()` / `keys()` / `values()`, which return arrays), and the constructor accepts only `[name, value]` pairs (`new Headers([[\"accept\", \"text/plain\"]])`). Header names are normalised to lowercase, per spec.\n\nMutations on `req.headers` / `resp.headers` apply directly to the in-flight message. A standalone `new Headers(...)`, or the `headers` on a `fetch()` result, is backed by a local list.\n\n```ts\nonClientRequest((req) => {\n  const ua = req.headers.get(\"user-agent\") || \"unknown\";  // string | null\n  req.headers.set(\"x-ua\", ua);                             // replace all values\n  req.headers.append(\"x-tag\", \"a\");                        // add without replacing\n  req.headers.delete(\"x-internal-token\");\n  if (req.headers.has(\"authorization\")) { /* … */ }\n});\n```\n\n| Method | Type | Notes |\n| --- | --- | --- |\n| `get(name)` | `string \\| null` | Case-insensitive. On a local `Headers`, repeated values are joined with `\", \"`; on a live message, the host returns the first value |\n| `has(name)` | `bool` | Whether the header is present |\n| `set(name, value)` | `void` | Replaces **all** existing values for that name; throws on invalid name/value or size limit exceeded |\n| `append(name, value)` | `void` | Appends without removing existing values — use for `Set-Cookie`, `Cookie`, `Vary`, … |\n| `delete(name)` | `void` | Removes all values for that name; no-op if absent |\n| `getSetCookie()` | `string[]` | All `Set-Cookie` values, one per entry |\n| `entries()` | `string[][]` | All `[name, value]` pairs, order and duplicates preserved |\n| `keys()` | `string[]` | All header names, in order |\n| `values()` | `string[]` | All header values, in order |\n| `forEach(cb)` | `void` | Calls `cb(value, name, parent)` for each header |\n\n---\n\n### `Request`\n\n`Request` is your view into the incoming HTTP request. You receive it as the argument to `onClientRequest` and `onOriginRequest` handlers. Read its method, URL, headers, and body; mutate it in place to change what the upstream or origin sees; or call `respondWith()` / `respondText()` to short-circuit the entire request with an immediate reply — skipping cache and origin entirely.\n\nThe same class also appears in response phases as the **read-only view** returned by [`resp.request`](#resprequest--request-read-only): the request as it arrived at the socket corresponding to that response phase, before that socket's request handlers mutated it. On that view all setters and mutating methods throw, and `body` is always `null`.\n\n```ts\nonClientRequest((req) => {\n  // Header manipulation\n  const ua = req.headers.get(\"user-agent\") || \"unknown\";\n  req.headers.set(\"x-ua\", ua);\n  req.headers.delete(\"x-internal-token\");\n\n  // URL helpers: path, query parameters (parsed once, cached), cookies\n  if (req.path == \"/search\" && req.queryParams.get(\"q\") === null) {\n    req.respondText(400, \"missing q\");\n    return;\n  }\n  req.queryParams.delete(\"utm_source\");          // rewrites req.url\n  const variant = req.cookies.get(\"ab-variant\");  // string | null\n\n  // Short-circuit with an early response\n  if (req.path == \"/robots.txt\") {\n    req.respondText(200, \"User-agent: *\\nDisallow: /admin/\",\n      new Headers([[\"content-type\", \"text/plain\"]]));\n    return;\n  }\n});\n```\n\n| Field / method | Type | Notes |\n| --- | --- | --- |\n| `method` | `string` | HTTP method (`\"GET\"`, `\"POST\"`, …) |\n| `url` | `string` | Request target: path and query string. (Named `url` to match WHATWG; unlike a browser `Request` this is origin-relative, not absolute.) |\n| `path` | `string` | Path part of `url`, without the query string. Assigning it keeps the current query string |\n| `query` | `string` | Query string without the leading `?` (e.g. `\"q=foo\"`), or `\"\"` if none. Assigning it replaces the query (leading `?` optional, `\"\"` removes it) |\n| `queryParams` | `URLSearchParams` | Parsed query parameters, parsed once and cached until `url` is reassigned. Mutations write back to `url`. See [`URLSearchParams`](#urlsearchparams) |\n| `cookies` | `Cookies` | Parsed `Cookie` header, cached while the header value is unchanged. See [`Cookies`](#cookies) |\n| `headers` | `Headers` | Request headers; mutations apply to the in-flight request |\n| `body` | `Uint8Array \\| null` | Raw request body; `null` if not buffered by the host |\n| `text()` | `string \\| null` | UTF-8 decode of `body`; `null` if body is absent |\n| `bytes()` | `Uint8Array \\| null` | Alias for `body` |\n| `arrayBuffer()` | `ArrayBuffer \\| null` | Copy of `body` as an `ArrayBuffer`; `null` if absent |\n| `setBodyText(text)` | `void` | UTF-8 encode and replace `body` |\n| `respondWith(response)` | `void` | Short-circuit with a `Response` (WHATWG `FetchEvent.respondWith` shape) |\n| `respondText(status, body?, headers?)` | `void` | Convenience: short-circuit with a string body (UTF-8 encoded). `headers` is a `Headers` or `null` |\n| `respondRedirect(location, status?)` | `void` | Convenience: short-circuit with a redirect to `location`. `status` defaults to `302`; must be 301/302/303/307/308 |\n| `bypassChallenge()` | `void` | Signal host to skip bot-protection for this request |\n| `forceChallenge()` | `void` | Signal host to present a bot-protection challenge for this request, even if it would not otherwise be challenged |\n\n> **Note:** unlike the WHATWG `fetch` API, `req.text()` / `req.bytes()` / `req.arrayBuffer()` are **synchronous** — they return the value directly, not a `Promise`. AssemblyScript has no `async`/`await`.\n\n---\n\n### `Response`\n\n`Response` represents an HTTP response — whether it came from the cache, the origin, or one of your `fetch()` calls. You receive it in `onClientResponse` and `onOriginResponse` handlers, and as the return value from `fetch()`. You can also construct one with `new Response(body, init)` to pass to `req.respondWith()`. Read its status and headers; mutate them to change what the client sees; call `setCacheControl()` to override how the host caches the response.\n\n```ts\nonClientResponse((resp) => {\n  resp.headers.set(\"x-served-by\", \"edge\");\n\n  if (resp.ok) {\n    resp.setCacheControl(\"public, max-age=60\");\n  }\n});\n\n// Build one to short-circuit a request:\nreq.respondWith(new Response(null, {\n  status: 302,\n  headers: new Headers([[\"location\", \"/elsewhere\"]]),\n}));\n// …or the shorthand:\nreq.respondWith(Response.redirect(\"/elsewhere\"));\n```\n\n| Field / getter / method | Type | Notes |\n| --- | --- | --- |\n| `new Response(body?, init?)` | — | `body` is `Uint8Array \\| null`; `init` is `{ status?, statusText?, headers? }` |\n| `Response.redirect(location, status?)` | `Response` | Static. Empty-body response with a `Location` header. `status` defaults to `302`; throws unless 301/302/303/307/308 |\n| `status` | `u16` | HTTP status code; `0` on `fetch()` transport error. Defaults to `200` for a constructed response |\n| `statusText` | `string` | Advisory only — not sent on the wire by this host |\n| `ok` | `bool` | `true` iff `status` is 200–299 |\n| `headers` | `Headers` | Response headers |\n| `request` | `Request` | Read-only, phase-specific request snapshot (response phases only; see below) |\n| `body` | `Uint8Array \\| null` | Raw body bytes; `null` if not buffered by the host |\n| `errorKind` | `string \\| null` | Transport error type; only set on `Response` values returned by `fetch()`, always `null` in response-phase handlers |\n| `errorMessage` | `string \\| null` | Human-readable detail when `errorKind` is set |\n| `text()` | `string \\| null` | UTF-8 decode of `body`; `null` if body is absent |\n| `bytes()` | `Uint8Array \\| null` | Alias for `body` |\n| `arrayBuffer()` | `ArrayBuffer \\| null` | Copy of `body` as an `ArrayBuffer`; `null` if absent |\n| `setBodyText(text)` | `void` | UTF-8 encode and replace `body` |\n| `isError()` | `bool` | `true` iff `errorKind` is set |\n| `setCacheControl(value)` | `void` | Override the `Cache-Control` header for custom cache behaviour |\n\n> **Note:** as with `Request`, the body accessors are **synchronous** and there is no `Response.json()` — parse `text()` with a JSON library (see the [`json`](examples/json) example).\n\n#### `resp.request` → `Request` (read-only)\n\nResponse-phase handlers run after the request has already gone upstream, so `resp.headers` is the *response* header map. To inspect the corresponding request, use `resp.request`: a **read-only snapshot taken at that response phase's socket boundary**, before the request handlers for that socket mutated it.\n\n```ts\nonClientResponse((resp) => {\n  const req = resp.request;                    // client-socket request, pre-client-handler\n\n  if (req.method == \"POST\") {\n    resp.setCacheControl(\"no-store\");          // never cache POST responses\n  }\n\n  const origin = req.headers.get(\"origin\");\n  if (origin !== null && origin.endsWith(\".example.com\")) {\n    resp.headers.set(\"access-control-allow-origin\", origin);\n  }\n});\n```\n\nSemantics worth knowing:\n\n- **`onClientResponse`: client-socket snapshot.** It shows the request as the client-facing socket received it, before `onClientRequest` handlers rewrote the URL, method, or headers.\n- **`onOriginResponse`: origin-socket snapshot.** It shows the request as it reached the origin-facing socket, after client-phase/cache-path mutations but before `onOriginRequest` handlers mutated it.\n- **Immutable.** Setters, `respondWith`/`respondText`, and header writes throw. To change the response, mutate `resp` directly.\n- **`body` is always `null`** — the host does not retain request bodies across the upstream round-trip.\n- **Free unless used.** The view is built lazily, and a worker that never touches `resp.request` compiles with no `request.*` imports at all — the host then skips taking the snapshot entirely. (Requires a runtime with `request.*` host-function support; deploy the runtime before workers that use this.)\n\n---\n\n### `URLSearchParams`\n\n`URLSearchParams` is an ordered multimap of query parameters, modelled on the [browser class](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) with the usual AssemblyScript departures: not iterable (`keys()` / `values()` / `entries()` return arrays) and constructed only from a string. Names and values are stored decoded (`+` and `%XX` handled as `application/x-www-form-urlencoded`); `toString()` re-encodes them.\n\n`req.queryParams` is the common way to get one. It is parsed on first access and cached until `req.url` is reassigned, so repeated `get()` calls don't re-parse. Mutating it rewrites `req.url` — handy for stripping tracking parameters or normalising query order before the cache lookup. Standalone construction is useful for form bodies and for building `fetch()` URLs:\n\n```ts\nonClientRequest((req) => {\n  const page = req.queryParams.get(\"page\") || \"1\";\n  req.queryParams.delete(\"fbclid\");\n  req.queryParams.sort();                       // canonical order → better cache hit rate\n\n  const form = new URLSearchParams(req.text());  // POST body, application/x-www-form-urlencoded\n  const email = form.get(\"email\");\n\n  const q = new URLSearchParams();\n  q.set(\"q\", \"café & more\");                     // encoded as q=caf%C3%A9+%26+more\n  fetch(\"https://api.example.com/search?\" + q.toString());\n});\n```\n\n| Member | Type | Notes |\n| --- | --- | --- |\n| `new URLSearchParams(init?)` | — | Parses a query string (leading `?` ignored) or form body; `null` / omitted for empty |\n| `size` | `i32` | Number of parameters, duplicates included |\n| `get(name)` | `string \\| null` | First value, or `null` if absent. An empty value (`?flag` or `?flag=`) is `\"\"` |\n| `getAll(name)` | `string[]` | Every value for `name`, in order |\n| `has(name)` | `bool` | Whether `name` is present |\n| `set(name, value)` | `void` | Replace all values for `name` with one; keeps the first occurrence's position |\n| `append(name, value)` | `void` | Add a pair without removing existing ones |\n| `delete(name)` | `void` | Remove every `name` |\n| `sort()` | `void` | Stable sort by name |\n| `keys()` / `values()` / `entries()` | arrays | In order, duplicates included |\n| `forEach(cb)` | `void` | Calls `cb(value, name, parent)` for each pair |\n| `toString()` | `string` | `a=1&b=2`, no leading `?`; `\"\"` when empty |\n\n`formEncode(s)` / `formDecode(s)` — the encoder and decoder used above — are exported too, for one-off use.\n\n---\n\n### `Cookies`\n\n`Cookies` is a read-only view over a `Cookie` request header. Values come back verbatim (RFC 6265 defines no encoding, so none is applied); names are case-sensitive; when a name repeats, the first occurrence wins (clients send the most-specific path first). Get one from `req.cookies` — parsed on first access and reused while the header value is unchanged — or parse a header yourself with `new Cookies(value)`.\n\n```ts\nonClientRequest((req) => {\n  const session = req.cookies.get(\"session\");   // string | null\n  if (session === null && req.path.startsWith(\"/account/\")) {\n    req.respondRedirect(\"/login\");\n  }\n});\n```\n\n| Member | Type | Notes |\n| --- | --- | --- |\n| `new Cookies(header?)` | — | Parses a `Cookie` header value such as `\"a=1; b=2\"`; `null` / omitted for empty |\n| `size` | `i32` | Number of distinct names |\n| `get(name)` | `string \\| null` | Value, or `null` if absent |\n| `has(name)` | `bool` | Whether `name` is present |\n| `keys()` / `entries()` | arrays | Names, or `[name, value]` pairs, in header order |\n\nTo *set* cookies on a response, use `resp.headers.append(\"set-cookie\", …)`; to read the ones a response sets, `resp.headers.getSetCookie()`.\n\n---\n\n### HTML rewriting (`HtmlRules`)\n\n`HtmlRules` rewrites HTML response bodies without the bytes ever entering your worker. You declare a set of rules — CSS selector plus an action — and call `install()` once; the host runs them with [lol-html](https://github.com/cloudflare/lol-html) as the response streams to the client. The whole rule set crosses the host/guest boundary in a single call, so cost is constant no matter how many rules you add.\n\n**Prefer this over manual body editing whenever you can.** Because the host rewrites the response as a stream, your worker never buffers the body into WASM memory: there's nothing to allocate, nothing to copy across the sandbox boundary, and **no response-size ceiling** — a multi-megabyte page rewrites the same way a small one does. Manual editing (export an `*_response_body` marker, then `text()` / `setBodyText()`) forces the host to buffer the entire body so it fits in linear memory, which is slower, costs memory proportional to the response, and is bounded by the host's buffered-body limit. Reach for the manual path only when you genuinely need to compute the change from the body's own content (something no declarative rule can express).\n\n```ts\nimport { onOriginResponse, Response, HtmlRules } from \"@automattic/vip-edge-workers-sdk\";\n\nexport {\n  alloc,\n  on_origin_response,\n} from \"@automattic/vip-edge-workers-sdk/assembly/index\";\n\nonOriginResponse((resp: Response): void => {\n  new HtmlRules()\n    .prependInside(\"head\", '<script src=\"/analytics.js\" defer></script>')\n    .setAttr(\"meta[name=robots]\", \"content\", \"noindex\")\n    .removeAttr(\"a\", \"ping\")\n    .rewriteAttrRe(\"a[href]\", \"href\", \"^http://\", \"https://\")  // force outbound links to https\n    .remove(\"script[data-tracker]\")\n    .install();\n});\n```\n\n**Phase and content-type rules:**\n\n- Effective only in response-phase handlers (`onClientResponse` / `onOriginResponse`). Rules registered in a request phase are silently dropped.\n- Applied only when the response `Content-Type` is `text/html` or `application/xhtml+xml`. JSON, images, etc. pass through untouched.\n- The body never enters the worker, so **do not** export an `*_response_body` marker for this — there is nothing to buffer.\n\n| Method | Signature | Action |\n| --- | --- | --- |\n| `insertBefore` | `(selector, html)` | Insert `html` immediately before each matching element |\n| `insertAfter` | `(selector, html)` | Insert `html` immediately after each matching element |\n| `prependInside` | `(selector, html)` | Insert `html` as the first child of each match |\n| `appendInside` | `(selector, html)` | Insert `html` as the last child of each match |\n| `replace` | `(selector, html)` | Replace each match (and its children) with `html` |\n| `remove` | `(selector)` | Remove each match (and its children) |\n| `setAttr` | `(selector, name, value)` | Set attribute `name` to `value` on each match |\n| `removeAttr` | `(selector, name)` | Remove attribute `name` from each match |\n| `rewriteAttrRe` | `(selector, name, pattern, template)` | Rewrite attribute `name` via `pattern.replace_all(template)` |\n| `setText` | `(selector, text)` | Replace the text content of each match (HTML-escaped) |\n| `install` | `() → void` | Submit the accumulated rules. Throws on any host validation error |\n\n**Notes:**\n\n- **Selectors** use lol-html's CSS subset — `a[href]`, `a[href^=\"/\"]`, `div.cls`, `#id`, `header > nav`, and most position pseudo-classes.\n- **`html` arguments are inserted verbatim, not escaped.** Escape any user-controlled content yourself before passing it in. `setText` is the exception — its `text` is HTML-escaped by the host.\n- **`rewriteAttrRe`** uses Rust `regex` (RE2-style, no lookarounds). Templates support numbered captures (`$1`..`$9`), named captures (`${name}`), the whole match (`$0`), and `$$` for a literal `$`. The attribute is left untouched if absent or if the replacement is a no-op.\n- The builder is chainable; call `install()` **once** per worker. Two `install()` calls queue two separate rule sets.\n- Limits: ≤ 256 rules and ≤ 64 KiB total payload per call. `install()` throws on an oversize payload, an invalid selector, or a bad regex pattern.\n\n---\n\n### `fetch(url, init?) → Response`\n\nMake an outbound HTTP request from the worker. Modelled on WHATWG [`fetch(url, init)`](https://developer.mozilla.org/en-US/docs/Web/API/fetch), but — because AssemblyScript has no `async` — it returns a `Response` **directly, not a `Promise`**. From your code's perspective it's a regular synchronous call: the host suspends the WASM instance while the request is in flight and resumes it with the response. Errors are surfaced via fields rather than a rejected promise, so always check `resp.isError()` before reading the body.\n\n**Available in the client-request phase only.** Calling it from any other phase returns a `Response` with `errorKind` set to `\"phase_not_allowed\"`.\n\n```ts\nimport { fetch, Headers, onClientRequest } from \"@automattic/vip-edge-workers-sdk\";\n\nonClientRequest((req) => {\n  if (!req.url.startsWith(\"/ip\")) return;\n\n  const resp = fetch(\"https://ifconfig.me/ip\", {\n    headers: new Headers([[\"accept\", \"text/plain\"]]),\n  });\n\n  if (resp.isError()) {\n    req.respondText(502, \"fetch failed: \" + resp.errorKind!);\n    return;\n  }\n\n  req.respondText(resp.status, resp.text(), new Headers([[\"content-type\", \"text/plain\"]]));\n});\n```\n\nTo send a request body:\n\n```ts\nconst body = Uint8Array.wrap(String.UTF8.encode('{\"key\":\"value\"}'));\nconst resp = fetch(\"https://api.example.com/v1/data\", {\n  method: \"POST\",\n  headers: new Headers([[\"content-type\", \"application/json\"]]),\n  body,\n});\n```\n\n`init` is a `RequestInit` — an options bag you can pass as an object literal:\n\n| `init` field | Type | Default |\n| --- | --- | --- |\n| `method` | `string` | `\"GET\"` |\n| `headers` | `Headers \\| null` | `null` |\n| `body` | `Uint8Array \\| null` | `null` |\n\n`errorKind` values: `timeout`, `too_many_inflight`, `request_too_large`, `response_too_large`, `body_read`, `transport`, `phase_not_allowed`.\n\nHost-enforced limits: 2 s end-to-end timeout · 10 MiB request body · 10 MiB response body · per-worker concurrency cap (FIFO queue).\n\n---\n\n### `KV`\n\n`KV` is a shared, host-backed key-value store. Unlike in-memory variables in your worker code — which are wiped at the end of every request because the WASM instance is discarded — `KV` persists data across requests and is shared across all instances running on the same site. It's useful for counters, feature flags, small configuration blobs, or any value that needs to outlive a single request.\n\nThe store has two distinct modes. **Bytes** holds arbitrary values up to 10 KiB. **Counters** hold atomic 64-bit integers — useful for visit counts, quotas, or any value you need to increment safely under concurrent load. A key holds one type at a time. Counter accessors throw when a key holds bytes; byte reads treat a counter key as absent; and `set` / `setText` replace a counter with a bytes value.\n\nKeys: max 64 bytes (UTF-8). Values: max 10 KiB. Entries are subject to site-wide LRU eviction; evicted counters reset to `0` on next access.\n\n**Bytes store**\n\n```ts\nimport { KV, onClientRequest } from \"@automattic/vip-edge-workers-sdk\";\n\n// PUT reads req.text() — export client_request_body to have the host buffer it.\nonClientRequest((req) => {\n  if (req.method == \"PUT\" && req.url == \"/note\") {\n    KV.setText(\"note\", req.text() || \"\");\n    req.respondText(200, \"stored\");\n    return;\n  }\n\n  if (req.method == \"GET\" && req.url == \"/note\") {\n    const note = KV.getText(\"note\");\n    req.respondText(note !== null ? 200 : 404, note || \"no note stored\");\n    return;\n  }\n});\n```\n\n| Method | Signature | Notes |\n| --- | --- | --- |\n| `get` | `(key: string) → Uint8Array \\| null` | `null` = absent or counter key; zero-length = key exists with empty value |\n| `set` | `(key: string, value: Uint8Array) → void` | Replaces a counter key with bytes; throws if key > 64 B or value > 10 KiB |\n| `del` | `(key: string) → void` | No-op if absent; works on both types |\n| `getText` | `(key: string) → string \\| null` | `get` + UTF-8 decode |\n| `setText` | `(key: string, value: string) → void` | UTF-8 encode + `set`, including counter-to-bytes replacement |\n\n**Counter store**\n\nAtomic 64-bit integers. Absent counters read as `0` and are created on first write.\n\n```ts\nonClientRequest((req) => {\n  const visits = KV.incr(\"visits\");  // atomic +1, returns new value\n  req.headers.set(\"x-visit-count\", visits.toString());\n});\n```\n\n| Method | Signature | Notes |\n| --- | --- | --- |\n| `counterGet` | `(key: string) → i64` | `0` if absent; throws if key holds bytes |\n| `counterSet` | `(key: string, value: i64) → void` | Throws if key > 64 B or key holds bytes |\n| `incr` | `(key: string, delta: i64 = 1) → i64` | Atomic add; returns new value; initialises to `0` if absent; throws if key holds bytes |\n\n---\n\n### `RateLimit`\n\n`RateLimit` lets you enforce request rate limits at the edge, before a request ever reaches your origin. You define a named limiter with a target rate in requests per second, then check each incoming request against a key — typically a client IP or authenticated user ID. Each unique key gets its own independent token bucket, so the limit applies per-client rather than globally. Limiters are shared across all instances on the same site, so the rate is enforced consistently even under concurrent load.\n\n`register` is idempotent and safe to call on every request. The `rps` value is fixed at the first `register` call; later calls with the same name are no-ops regardless of what `rps` you pass.\n\n```ts\nimport { RateLimit, onClientRequest } from \"@automattic/vip-edge-workers-sdk\";\n\nonClientRequest((req) => {\n  if (!req.url.startsWith(\"/api/\")) return;\n\n  RateLimit.register(\"api\", 50);\n  const ip = req.headers.get(\"x-forwarded-for\") || \"\";\n  if (!RateLimit.check(\"api\", ip)) {\n    req.respondText(429, \"rate limited\");\n    return;\n  }\n});\n```\n\n| Method | Signature | Notes |\n| --- | --- | --- |\n| `register` | `(name: string, rps: i32) → void` | Idempotent. Throws if name > 64 B, `rps` ≤ 0, or site-wide limiter quota (1000) exceeded |\n| `check` | `(name: string, key: string) → bool` | `true` = allowed, `false` = rate-limited. Throws if limiter not registered |\n\n**Choosing the key:** each unique key gets its own token bucket. Key on something an attacker cannot enumerate freely — client IP, authenticated user ID, a normalised path prefix. Never use `req.url` directly; arbitrary query strings create unlimited unique buckets and defeat the limit.\n\n| Good | Bad |\n| --- | --- |\n| `req.headers.get(\"x-forwarded-for\")` | `req.url` — query strings make every request unique |\n| Authenticated user ID | Any user-supplied header or body value |\n| `req.path` — path without the query string | `req.url` with arbitrary query params |\n\n---\n\n### `getenv(name) → string | null`\n\nLook up a host-provided environment variable. Variables are read-only and set at worker startup. Returns `null` if not set.\n\nEnvironment values are injected at runtime rather than embedded in the worker source or compiled binary. After `getenv()` returns, however, the value is an ordinary string: worker code can put it in a request, response, or log. Never place secrets in URLs or query strings; send them to trusted services in a header or body only when the integration requires it.\n\n```ts\nimport { getenv, onClientRequest } from \"@automattic/vip-edge-workers-sdk\";\n\nonClientRequest((req) => {\n  const key = getenv(\"API_KEY\");\n  if (key !== null) req.headers.set(\"authorization\", \"Bearer \" + key);\n});\n```\n\n---\n\n### Crypto\n\nHost-executed cryptographic primitives. No hash or HMAC code lives in the WASM binary — your worker binary stays small and the host handles all crypto operations.\n\n**HMAC-SHA256 / webhook signature verification**\n\n```ts\nimport {\n  getenv, onClientRequest,\n  hmacSha256Str, secureCompare, hexEncode,\n} from \"@automattic/vip-edge-workers-sdk\";\n\nexport {\n  alloc, on_client_request, client_request_body,\n} from \"@automattic/vip-edge-workers-sdk/assembly/index\";\n\nonClientRequest((req) => {\n  const secret = getenv(\"WEBHOOK_SECRET\");\n  if (secret === null) { req.respondText(500, \"not configured\"); return; }\n\n  const sig      = req.headers.get(\"x-hub-signature-256\") || \"\";\n  const expected = \"sha256=\" + hexEncode(hmacSha256Str(secret, req.text() || \"\"));\n\n  const a = Uint8Array.wrap(String.UTF8.encode(sig));\n  const b = Uint8Array.wrap(String.UTF8.encode(expected));\n  if (!secureCompare(a, b)) { req.respondText(401, \"invalid signature\"); return; }\n});\n```\n\n**HS256 JWT verification**\n\n```ts\nimport { getenv, onClientRequest, jwtVerifyHs256 } from \"@automattic/vip-edge-workers-sdk\";\n\nonClientRequest((req) => {\n  const auth = req.headers.get(\"authorization\") || \"\";\n  if (!auth.startsWith(\"Bearer \")) { req.respondText(401, \"missing token\"); return; }\n\n  const claims = jwtVerifyHs256(auth.slice(7), getenv(\"JWT_SECRET\") || \"\");\n  if (claims === null) { req.respondText(401, \"invalid or expired token\"); return; }\n\n  // claims is the raw JSON payload — parse with json-as if you need specific fields,\n  // or forward it to the origin as a header.\n  req.headers.set(\"x-jwt-claims\", claims);\n});\n```\n\n| Function | Signature | Notes |\n| --- | --- | --- |\n| `hmacSha256` | `(key: Uint8Array, msg: Uint8Array) → Uint8Array` | 32-byte HMAC-SHA256 digest |\n| `hmacSha256Str` | `(key: string, msg: string) → Uint8Array` | Convenience: UTF-8 encodes both inputs |\n| `sha256` | `(msg: Uint8Array) → Uint8Array` | 32-byte SHA-256 digest |\n| `secureCompare` | `(a: Uint8Array, b: Uint8Array) → bool` | Timing-attack-safe comparison; execution time depends only on input length, not content |\n| `jwtVerifyHs256` | `(token: string, secret: string) → string \\| null` | Verifies alg, signature, and `exp`; returns claims JSON or `null` |\n| `getRandomValues` | `(array: Uint8Array) → Uint8Array` | Fills `array` with OS-sourced secure random bytes; at most 64 KiB per call |\n| `hexEncode` | `(bytes: Uint8Array) → string` | Lowercase hex string (two characters per byte) |\n\n**Secure random bytes**\n\n```ts\nimport { getRandomValues, hexEncode, onClientRequest } from \"@automattic/vip-edge-workers-sdk\";\n\nonClientRequest((req) => {\n  const nonce = hexEncode(getRandomValues(new Uint8Array(16)));\n  req.headers.set(\"x-request-nonce\", nonce);\n});\n```\n\n`getRandomValues` mirrors Web Crypto: it fills the array in place from the host's OS entropy source and throws if asked for more than 64 KiB at once. `Math.random()` also works in workers, but it is an ordinary PRNG whose output can be predicted from a few observed values, so never use it for tokens, nonces, session IDs, or keys.\n\n`jwtVerifyHs256` validates `alg: \"HS256\"` strictly — RS256 / ES256 tokens return `null`. `exp` is checked against wall clock; `nbf` and `iat` are not enforced.\n\nSecrets should come from `getenv()` so they are injected at deploy time instead of embedded in the binary. Treat the returned string as sensitive: this prevents build-time disclosure, but it does not stop worker code from transmitting the value.\n\n---\n\n### Parsing JSON\n\nThe SDK does not include a JSON library. Workers that need to parse structured JSON bodies add [`json-as`](https://www.npmjs.com/package/json-as) directly to their own `package.json` and pass `--transform json-as` to `asc`. Workers that don't parse JSON pay nothing — no serialization code is included in their binary.\n\n```ts\nimport { JSON } from \"json-as\";\nimport { fetch, Headers, onClientRequest } from \"@automattic/vip-edge-workers-sdk\";\n\n@json\nclass Todo {\n  id: i32 = 0;\n  title: string = \"\";\n  completed: bool = false;\n}\n\n@json\nclass Summary {\n  id: i32 = 0;\n  title: string = \"\";\n  done: bool = false;\n}\n\nonClientRequest((req) => {\n  if (!req.url.startsWith(\"/todo/\")) return;\n\n  const resp = fetch(\"https://jsonplaceholder.typicode.com/todos/\" + req.url.slice(6));\n  if (!resp.ok) { req.respondText(resp.status, \"not found\"); return; }\n\n  const todo = JSON.parse<Todo>(resp.text()!);\n\n  const out = new Summary();\n  out.id = todo.id;\n  out.title = todo.title;\n  out.done = todo.completed;\n\n  req.respondText(\n    200,\n    JSON.stringify(out),\n    new Headers([[\"content-type\", \"application/json\"]]),\n  );\n});\n```\n\n## Building code\n\nYour worker source is [AssemblyScript](https://www.assemblyscript.org/) — a TypeScript-flavored language that compiles to WebAssembly bytecode using `asc`, the AssemblyScript compiler. Unlike TypeScript, which transpiles to JavaScript, AssemblyScript compiles all the way down to a `.wasm` binary with no JavaScript runtime dependency. The result is a small, self-contained file that the host loads and executes directly.\n\nOne compiler flag is always required, and two are strongly recommended for release builds:\n\n- **`--runtime stub`** uses a simple bump allocator with no garbage collector. Each request starts with a fresh heap and all memory is reclaimed when the request ends — there is nothing for a GC to manage.\n- **`--optimizeLevel 3`** runs the full Binaryen optimiser. Without it, binaries are significantly larger and slower.\n- **`--shrinkLevel 2`** tells the optimiser to prefer size over speed (`-Oz` equivalent) — inlines less, merges similar code. Typically cuts an additional 15–25% off the release binary.\n\nIf your worker parses JSON bodies, also add **`--transform json-as`** (see [Parsing JSON](#parsing-json)).\n\n```js\n// build.mjs\nimport { execFileSync } from 'child_process';\nimport { mkdirSync } from 'fs';\nimport { resolve, dirname } from 'path';\nimport { fileURLToPath } from 'url';\n\nconst root = dirname(fileURLToPath(import.meta.url));\nconst nodeModules = resolve(root, 'node_modules');\nconst { NODE_OPTIONS: _drop, ...env } = process.env;\n\nmkdirSync(resolve(root, 'build'), { recursive: true });\n\nexecFileSync(resolve(nodeModules, '.bin/asc'), [\n  resolve(root, 'assembly/index.ts'),\n  '--outFile', resolve(root, 'build/release.wasm'),\n  '--runtime', 'stub',\n  '--optimizeLevel', '3',\n  '--shrinkLevel', '2',\n  '--path', nodeModules,\n], { cwd: nodeModules, env, stdio: 'inherit' });\n```\n\nWorking examples under [`examples/`](examples):\n\n| Example | What it shows |\n| --- | --- |\n| [`fetch`](examples/fetch) | Outbound `fetch()` — proxy a route to an external API |\n| [`kv`](examples/kv) | KV bytes store + atomic counter forwarded to origin as a header |\n| [`rate-limit`](examples/rate-limit) | Per-path rate limiting with `RateLimit` |\n| [`json`](examples/json) | Parse a JSON API response into a typed `@json` class |\n| [`html-rewrite`](examples/html-rewrite) | Declarative HTML rewriting with `HtmlRules` — anonymize outbound links via href.li |\n| [`redirect`](examples/redirect) | 301 redirects — rename a path prefix and strip trailing slashes |\n| [`rewrite`](examples/rewrite) | Internal rewrite — repoint host + URI before cache lookup, no client-visible redirect |\n| [`headers`](examples/headers) | Override `Cache-Control` on the origin response + tag `.pdf` responses using the `resp.request` view |\n| [`webhook`](examples/webhook) | HMAC-SHA256 webhook signature verification (GitHub style) |\n| [`udger`](examples/udger) | Device/crawler detection via the Udger Cloud Parser API + `getenv` secret |\n\nRun `make examples` to build all of them.\n\n## Notes\n\n**Bodies are opt-in.** `req.body` and `resp.body` are `null` by default; see [Body access](#body-access) to enable buffering per phase. `fetch()` response bodies are always available. Use `text()` / `bytes()` to read; `setBodyText()` to replace.\n\n**Bodies are raw bytes** (`Uint8Array`). Use `text()` / `setBodyText()` for UTF-8 strings; `JSON.parse` (via json-as) for structured JSON; everything else (binary, compressed, …) is plain bytes.\n\n**Headers** — accessed via `req.headers` / `resp.headers`, a WHATWG-style [`Headers`](#headers) object. `set` replaces all existing values for a name; `append` adds a value alongside existing ones (use for `Set-Cookie`, `Vary`, etc.); `get` returns the value (joining duplicates with `\", \"` on a local `Headers`); `entries()` returns all pairs in order. Header names are normalised to lowercase. Name limit: 1 KiB; value limit: 64 KiB — `set` and `append` throw if either is exceeded.\n\n**Memory model (`--runtime stub`).** The stub runtime is a bump allocator — no GC, memory is never freed within a single phase invocation. Each phase invocation starts from a clean slate: no state is carried over from a prior phase, a prior request, or another worker — full isolation is guaranteed. Because nothing survives from one phase to the next, module-level variables **cannot** be used to pass data between phases — see [Phase isolation](#phase-isolation) for how to share data correctly.\n","readmeFilename":"README.md"}