{"_id":"@sanity/worker-channels","_rev":"43-d0b2c41f84a36872b5a89085bd10a97d","name":"@sanity/worker-channels","dist-tags":{"latest":"2.0.0"},"versions":{"1.0.0":{"name":"@sanity/worker-channels","version":"1.0.0","keywords":["sanity"],"author":{"name":"Sanity.io","email":"hello@sanity.io"},"license":"MIT","_id":"@sanity/worker-channels@1.0.0","maintainers":[{"name":"kmelve","email":"knut.melvaer@gmail.com"},{"name":"bjoerge","email":"bjoerge@gmail.com"},{"name":"rexxars","email":"espen@hovlandsdal.com"},{"name":"skogsmaskin","email":"per.kristian.nordnes@gmail.com"},{"name":"tonina","email":"zhelyazkova.tonina@gmail.com"},{"name":"mattcraig","email":"matt@sanity.io"},{"name":"joneidejohnsen","email":"jon@sanity.io"},{"name":"rubioz","email":"jarubc@gmail.com"},{"name":"robinpyon","email":"robin@robinpyon.com"},{"name":"mariuslundgard","email":"studio@mariuslundgard.com"},{"name":"sanity-io","email":"developers@sanity.io"},{"name":"evenw","email":"even@sanity.io"},{"name":"radhe_sanity","email":"radhe@sanity.io"},{"name":"rbotten","email":"rbotten@gmail.com"},{"name":"danielsgroves","email":"hello@danielgroves.net"},{"name":"judofyr","email":"judofyr@gmail.com"},{"name":"ryanblock","email":"rblock+npm@gmail.com"},{"name":"obliadp","email":"orjan@sanity.io"},{"name":"dcilke","email":"dain.cilke@gmail.com"},{"name":"madken","email":"kenneth.madsen@sanity.io"},{"name":"fredcarlsen","email":"fred@superbig.co"},{"name":"hermanw","email":"herman@sanity.io"},{"name":"tambet","email":"tambet.masik@gmail.com"},{"name":"sgulseth","email":"sgulseth@gmail.com"},{"name":"atombender","email":"npm@purefiction.net"},{"name":"simeonsanity","email":"simeon@sanity.io"},{"name":"stipsan","email":"stipsan@gmail.com"},{"name":"snorreeb","email":"snorre.e.brekke@gmail.com"},{"name":"rankers","email":"richardankers@gmail.com"},{"name":"rdunk","email":"rupert@rupertdunk.com"},{"name":"michael-sanity","email":"michael@sanity.io"},{"name":"vincentquigley","email":"vincent@sanity.io"},{"name":"ritasdias","email":"anarita151@gmail.com"},{"name":"kenjonespizza","email":"ken@sanity.io"},{"name":"josh_sanity_io","email":"josh@sanity.io"},{"name":"cngonzalez-sanity","email":"carolina@sanity.io"},{"name":"jjburbridge","email":"jonathan.burbridge@sanity.io"},{"name":"tdfka_rick","email":"joshua.ellis18@gmail.com"},{"name":"svirs","email":"shur@sanity.io"},{"name":"ryanbonial-sanity","email":"ryan.bonial@sanity.io"},{"name":"indrek.karner","email":"indrek.karner@sanity.io"},{"name":"ash","email":"ashley@juice49.com"},{"name":"sergeisarviro","email":"sergei@sanity.io"},{"name":"refiito","email":"margus@sanity.io"},{"name":"drewsanity","email":"drew.lyton@sanity.io"},{"name":"kaspar.lippmaa.sanity","email":"kaspar.lippmaa@sanity.io"},{"name":"dam","email":"kristoferjoseph@gmail.com"},{"name":"simen.svale","email":"simen@sanity.io"},{"name":"tbeseda","email":"tbeseda@gmail.com"},{"name":"daniel.malmer","email":"daniel.malmer@sanity.io"},{"name":"jordanl17","email":"jordanl17@me.com"},{"name":"colepeters","email":"cole@colepeters.com"},{"name":"armandocerna","email":"armando@cerna.ca"},{"name":"joan_miralles_paez","email":"joan.miralles@sanity.io"},{"name":"christianhg","email":"services@groengaard.dk"},{"name":"pedro-sanity","email":"pedro@sanity.io"},{"name":"jwoods-sanity","email":"james.woods@sanity.io"},{"name":"ricokahler","email":"ricokahler@me.com"},{"name":"tiit.kass.saity","email":"tiit.kass@sanity.io"},{"name":"binoy14","email":"me@binoy.io"},{"name":"pauloborgesf","email":"paulo@sanity.io"},{"name":"ausha","email":"ausha@sanity.io"},{"name":"chrislarocquesanity","email":"chris.larocque@sanity.io"},{"name":"rostimelk","email":"hello@rosti.no"},{"name":"mattlewine.sanity","email":"matt.lewine@sanity.io"},{"name":"msfragala","email":"ms.fragala@gmail.com"},{"name":"adoprog","email":"adoprog@gmail.com"},{"name":"tonysanity","email":"tony.lepmets@sanity.io"},{"name":"mrmrs","email":"hi@mrmrs.cc"},{"name":"betson","email":"ben.getson@gmail.com"},{"name":"georgedoescode","email":"georgedoescode@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"eoinsanity","email":"eoin.falconer@sanity.io"},{"name":"dashedstripes","email":"adamgrayscale@gmail.com"},{"name":"jmswrnr","email":"npm@jmswrnr.com"},{"name":"snocorp_sanity","email":"dave.sewell@sanity.io"},{"name":"mmgj","email":"controloptioncommand+npm@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"samhem","email":"sam.hemingway@sanity.io"},{"name":"gu-stav","email":"gu@stav.dev"},{"name":"patricksanity","email":"patrick.mccarthy@sanity.io"},{"name":"mads.mogenshoj","email":"mads.mogenshoj@sanity.io"},{"name":"sanitytom","email":"tom@sanity.io"},{"name":"sanity-cb","email":"charlie.brown@sanity.io"},{"name":"mm-sanity","email":"mark.michon@sanity.io"},{"name":"sanitykev","email":"kevin.green@sanity.io"},{"name":"victor.ayogu","email":"victor.ayogu@sanity.io"},{"name":"ryanbethel_sanity","email":"ryan.bethel@sanity.io"},{"name":"brianleroux","email":"b@brian.io"},{"name":"johnsicili","email":"john.siciliano@sanity.io"},{"name":"p10e","email":"peter@sanity.io"},{"name":"krlund","email":"kristoffer.lund@sanity.io"},{"name":"adrainhiss-sanity","email":"adrian.hiss@sanity.io"},{"name":"jonahsnider","email":"jonah@jonah.pw"},{"name":"mwritter","email":"matthew.ritter@sanity.io"}],"homepage":"https://github.com/sanity-io/worker-channels#readme","bugs":{"url":"https://github.com/sanity-io/worker-channels/issues"},"dist":{"shasum":"2866cd04fed48e8d2f67cb9d5f341eda84ae9b12","tarball":"https://registry.npmjs.org/@sanity/worker-channels/-/worker-channels-1.0.0.tgz","fileCount":8,"integrity":"sha512-LhA4+dgL0O/rNEMIhJ3ATPAdXVKfkLHLBfkDGSivtNGMf4Q54rYTiPyqNhuueDgDz99i7J8/d3k/aF5Ve1qriw==","signatures":[{"sig":"MEYCIQDZct9CwB9WxIZeY/OoAVimfGf3OmnmrsI9qRdb9jzxtgIhAND0hofwtuvY5DkXI//5sJEwMXAAMb3VdVLesVcWj9Py","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":97383},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=18.2"},"exports":{".":{"import":"./dist/index.js","source":"./src/index.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"dd9a172bf07bc9caccfa006743ef842732e28ef6","scripts":{"lint":"eslint .","test":"tsc && vitest --run --coverage","build":"pkg-utils build --strict --check --clean","prepublishOnly":"npm run build"},"_npmUser":{"name":"sanity-io","email":"developers@sanity.io"},"prettier":"@sanity/prettier-config","repository":{"url":"git+https://github.com/sanity-io/worker-channels.git","type":"git"},"_npmVersion":"10.9.2","description":"Type-safe, structured communication between worker threads and parent processes via TypeScript meta-programming.","directories":{},"sideEffects":false,"_nodeVersion":"22.17.1","browserslist":"extends @sanity/browserslist-config","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"packageManager":"pnpm@9.15.9+sha512.68046141893c66fad01c079231128e9afb89ef87e2691d69e4d40eee228988295fd4682181bae55b58418c3a253bde65a505ec7c5f9403ece5cc3cd37dcf2531","devDependencies":{"eslint":"^9.29.0","vitest":"^3.2.4","typescript":"^5.3.3","semantic-release":"^24.2.5","@sanity/pkg-utils":"^7.8.4","typescript-eslint":"^8.34.1","@vitest/coverage-v8":"^3.2.4","eslint-plugin-tsdoc":"^0.4.0","eslint-config-prettier":"^10.1.5","eslint-plugin-import-x":"^4.15.2","eslint-plugin-prettier":"^5.5.0","@sanity/prettier-config":"^1.0.5","@sanity/browserslist-config":"^1.0.5","@sanity/semantic-release-preset":"^5.0.0","eslint-import-resolver-typescript":"^4.4.3"},"_npmOperationalInternal":{"tmp":"tmp/worker-channels_1.0.0_1754457466905_0.9547930846092001","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@sanity/worker-channels","version":"1.1.0","keywords":["sanity"],"author":{"name":"Sanity.io","email":"hello@sanity.io"},"license":"MIT","_id":"@sanity/worker-channels@1.1.0","maintainers":[{"name":"kmelve","email":"knut.melvaer@gmail.com"},{"name":"bjoerge","email":"bjoerge@gmail.com"},{"name":"rexxars","email":"espen@hovlandsdal.com"},{"name":"skogsmaskin","email":"per.kristian.nordnes@gmail.com"},{"name":"tonina","email":"zhelyazkova.tonina@gmail.com"},{"name":"mattcraig","email":"matt@sanity.io"},{"name":"joneidejohnsen","email":"jon@sanity.io"},{"name":"rubioz","email":"jarubc@gmail.com"},{"name":"robinpyon","email":"robin@robinpyon.com"},{"name":"mariuslundgard","email":"studio@mariuslundgard.com"},{"name":"sanity-io","email":"developers@sanity.io"},{"name":"evenw","email":"even@sanity.io"},{"name":"radhe_sanity","email":"radhe@sanity.io"},{"name":"rbotten","email":"rbotten@gmail.com"},{"name":"danielsgroves","email":"hello@danielgroves.net"},{"name":"judofyr","email":"judofyr@gmail.com"},{"name":"ryanblock","email":"rblock+npm@gmail.com"},{"name":"obliadp","email":"orjan@sanity.io"},{"name":"dcilke","email":"dain.cilke@gmail.com"},{"name":"madken","email":"kenneth.madsen@sanity.io"},{"name":"fredcarlsen","email":"fred@superbig.co"},{"name":"hermanw","email":"herman@sanity.io"},{"name":"tambet","email":"tambet.masik@gmail.com"},{"name":"sgulseth","email":"sgulseth@gmail.com"},{"name":"atombender","email":"npm@purefiction.net"},{"name":"simeonsanity","email":"simeon@sanity.io"},{"name":"stipsan","email":"stipsan@gmail.com"},{"name":"snorreeb","email":"snorre.e.brekke@gmail.com"},{"name":"rankers","email":"richardankers@gmail.com"},{"name":"rdunk","email":"rupert@rupertdunk.com"},{"name":"michael-sanity","email":"michael@sanity.io"},{"name":"vincentquigley","email":"vincent@sanity.io"},{"name":"ritasdias","email":"anarita151@gmail.com"},{"name":"kenjonespizza","email":"ken@sanity.io"},{"name":"josh_sanity_io","email":"josh@sanity.io"},{"name":"cngonzalez-sanity","email":"carolina@sanity.io"},{"name":"jjburbridge","email":"jonathan.burbridge@sanity.io"},{"name":"tdfka_rick","email":"joshua.ellis18@gmail.com"},{"name":"svirs","email":"shur@sanity.io"},{"name":"ryanbonial-sanity","email":"ryan.bonial@sanity.io"},{"name":"indrek.karner","email":"indrek.karner@sanity.io"},{"name":"ash","email":"ashley@juice49.com"},{"name":"sergeisarviro","email":"sergei@sanity.io"},{"name":"refiito","email":"margus@sanity.io"},{"name":"drewsanity","email":"drew.lyton@sanity.io"},{"name":"kaspar.lippmaa.sanity","email":"kaspar.lippmaa@sanity.io"},{"name":"dam","email":"kristoferjoseph@gmail.com"},{"name":"simen.svale","email":"simen@sanity.io"},{"name":"tbeseda","email":"tbeseda@gmail.com"},{"name":"daniel.malmer","email":"daniel.malmer@sanity.io"},{"name":"jordanl17","email":"jordanl17@me.com"},{"name":"colepeters","email":"cole@colepeters.com"},{"name":"armandocerna","email":"armando@cerna.ca"},{"name":"joan_miralles_paez","email":"joan.miralles@sanity.io"},{"name":"christianhg","email":"services@groengaard.dk"},{"name":"pedro-sanity","email":"pedro@sanity.io"},{"name":"jwoods-sanity","email":"james.woods@sanity.io"},{"name":"ricokahler","email":"ricokahler@me.com"},{"name":"tiit.kass.saity","email":"tiit.kass@sanity.io"},{"name":"binoy14","email":"me@binoy.io"},{"name":"pauloborgesf","email":"paulo@sanity.io"},{"name":"ausha","email":"ausha@sanity.io"},{"name":"chrislarocquesanity","email":"chris.larocque@sanity.io"},{"name":"rostimelk","email":"hello@rosti.no"},{"name":"mattlewine.sanity","email":"matt.lewine@sanity.io"},{"name":"msfragala","email":"ms.fragala@gmail.com"},{"name":"adoprog","email":"adoprog@gmail.com"},{"name":"tonysanity","email":"tony.lepmets@sanity.io"},{"name":"mrmrs","email":"hi@mrmrs.cc"},{"name":"betson","email":"ben.getson@gmail.com"},{"name":"georgedoescode","email":"georgedoescode@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"eoinsanity","email":"eoin.falconer@sanity.io"},{"name":"dashedstripes","email":"adamgrayscale@gmail.com"},{"name":"jmswrnr","email":"npm@jmswrnr.com"},{"name":"snocorp_sanity","email":"dave.sewell@sanity.io"},{"name":"mmgj","email":"controloptioncommand+npm@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"samhem","email":"sam.hemingway@sanity.io"},{"name":"gu-stav","email":"gu@stav.dev"},{"name":"patricksanity","email":"patrick.mccarthy@sanity.io"},{"name":"mads.mogenshoj","email":"mads.mogenshoj@sanity.io"},{"name":"sanitytom","email":"tom@sanity.io"},{"name":"sanity-cb","email":"charlie.brown@sanity.io"},{"name":"mm-sanity","email":"mark.michon@sanity.io"},{"name":"sanitykev","email":"kevin.green@sanity.io"},{"name":"victor.ayogu","email":"victor.ayogu@sanity.io"},{"name":"ryanbethel_sanity","email":"ryan.bethel@sanity.io"},{"name":"brianleroux","email":"b@brian.io"},{"name":"johnsicili","email":"john.siciliano@sanity.io"},{"name":"p10e","email":"peter@sanity.io"},{"name":"krlund","email":"kristoffer.lund@sanity.io"},{"name":"adrainhiss-sanity","email":"adrian.hiss@sanity.io"},{"name":"jonahsnider","email":"jonah@jonah.pw"},{"name":"mwritter","email":"matthew.ritter@sanity.io"}],"homepage":"https://github.com/sanity-io/worker-channels#readme","bugs":{"url":"https://github.com/sanity-io/worker-channels/issues"},"dist":{"shasum":"f4ad866c601741fae6156944567748e31764de19","tarball":"https://registry.npmjs.org/@sanity/worker-channels/-/worker-channels-1.1.0.tgz","fileCount":11,"integrity":"sha512-25SS2RuQFRLZ8STlW7fdxb7vvxMWhryh3tY2ADQaZiaQt1r57GZgeMma85AG0mSesaMvFL1ndO+XiBOFHBHSmg==","signatures":[{"sig":"MEYCIQCpNFnRY1f4PJUIW3D7jQt95MX8rhLOOt6ntzaJKKLm9gIhAN1SDgKyHo9uNwCVGZgcaWzrQq8OUdoZWLfHi/CvCHl+","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":143881},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","engines":{"node":">=18.2"},"exports":{".":{"import":"./dist/index.js","source":"./src/index.ts","default":"./dist/index.js","require":"./dist/index.cjs"},"./package.json":"./package.json"},"gitHead":"7260bae04337ba475460282bf345a71d5de6f0ba","scripts":{"lint":"eslint .","test":"tsc && vitest --run --coverage","build":"pkg-utils build --strict --check --clean","prepublishOnly":"npm run build"},"_npmUser":{"name":"sanity-io","email":"developers@sanity.io"},"prettier":"@sanity/prettier-config","repository":{"url":"git+https://github.com/sanity-io/worker-channels.git","type":"git"},"_npmVersion":"10.9.2","description":"Type-safe, structured communication between worker threads and parent processes via TypeScript meta-programming.","directories":{},"sideEffects":false,"_nodeVersion":"22.17.1","browserslist":"extends @sanity/browserslist-config","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"packageManager":"pnpm@9.15.9+sha512.68046141893c66fad01c079231128e9afb89ef87e2691d69e4d40eee228988295fd4682181bae55b58418c3a253bde65a505ec7c5f9403ece5cc3cd37dcf2531","devDependencies":{"eslint":"^9.29.0","vitest":"^3.2.4","typescript":"^5.3.3","semantic-release":"^24.2.5","@sanity/pkg-utils":"^7.8.4","typescript-eslint":"^8.34.1","@vitest/coverage-v8":"^3.2.4","eslint-plugin-tsdoc":"^0.4.0","eslint-config-prettier":"^10.1.5","eslint-plugin-import-x":"^4.15.2","eslint-plugin-prettier":"^5.5.0","@sanity/prettier-config":"^1.0.5","@sanity/browserslist-config":"^1.0.5","@sanity/semantic-release-preset":"^5.0.0","eslint-import-resolver-typescript":"^4.4.3"},"_npmOperationalInternal":{"tmp":"tmp/worker-channels_1.1.0_1754558598579_0.6133431896748276","host":"s3://npm-registry-packages-npm-production"}},"2.0.0":{"name":"@sanity/worker-channels","version":"2.0.0","keywords":["sanity"],"author":{"name":"Sanity.io","email":"hello@sanity.io"},"license":"MIT","_id":"@sanity/worker-channels@2.0.0","maintainers":[{"name":"kmelve","email":"knut.melvaer@gmail.com"},{"name":"bjoerge","email":"bjoerge@gmail.com"},{"name":"rexxars","email":"espen@hovlandsdal.com"},{"name":"skogsmaskin","email":"per.kristian.nordnes@gmail.com"},{"name":"tonina","email":"zhelyazkova.tonina@gmail.com"},{"name":"mattcraig","email":"matt@sanity.io"},{"name":"joneidejohnsen","email":"jon@sanity.io"},{"name":"rubioz","email":"jarubc@gmail.com"},{"name":"robinpyon","email":"robin@robinpyon.com"},{"name":"mariuslundgard","email":"studio@mariuslundgard.com"},{"name":"sanity-io","email":"developers@sanity.io"},{"name":"irina937","email":"irina@sanity.io"},{"name":"evenw","email":"even@sanity.io"},{"name":"radhe_sanity","email":"radhe@sanity.io"},{"name":"rbotten","email":"rbotten@gmail.com"},{"name":"danielsgroves","email":"hello@danielgroves.net"},{"name":"judofyr","email":"judofyr@gmail.com"},{"name":"ryanblock","email":"rblock+npm@gmail.com"},{"name":"obliadp","email":"orjan@sanity.io"},{"name":"dcilke","email":"dain.cilke@gmail.com"},{"name":"madken","email":"kenneth.madsen@sanity.io"},{"name":"fredcarlsen","email":"fred@superbig.co"},{"name":"hermanw","email":"herman@sanity.io"},{"name":"tambet","email":"tambet.masik@gmail.com"},{"name":"sgulseth","email":"sgulseth@gmail.com"},{"name":"atombender","email":"npm@purefiction.net"},{"name":"stipsan","email":"stipsan@gmail.com"},{"name":"snorreeb","email":"snorre.e.brekke@gmail.com"},{"name":"sanity-svc.npm","email":"svc.npm@sanity.io"},{"name":"rankers","email":"richardankers@gmail.com"},{"name":"rdunk","email":"rupert@rupertdunk.com"},{"name":"michael-sanity","email":"michael@sanity.io"},{"name":"vincentquigley","email":"vincent@sanity.io"},{"name":"ritasdias","email":"anarita151@gmail.com"},{"name":"pete-garnett-sanity","email":"pete.garnett@sanity.io"},{"name":"kenjonespizza","email":"ken@sanity.io"},{"name":"josh_sanity_io","email":"josh@sanity.io"},{"name":"cngonzalez-sanity","email":"carolina@sanity.io"},{"name":"jjburbridge","email":"jonathan.burbridge@sanity.io"},{"name":"tdfka_rick","email":"joshua.ellis18@gmail.com"},{"name":"ryanbonial-sanity","email":"ryan.bonial@sanity.io"},{"name":"indrek.karner","email":"indrek.karner@sanity.io"},{"name":"ash","email":"ashley@juice49.com"},{"name":"sergeisarviro","email":"sergei@sanity.io"},{"name":"refiito","email":"margus@sanity.io"},{"name":"drewsanity","email":"drew.lyton@sanity.io"},{"name":"kaspar.lippmaa.sanity","email":"kaspar.lippmaa@sanity.io"},{"name":"dam","email":"kristoferjoseph@gmail.com"},{"name":"simen.svale","email":"simen@sanity.io"},{"name":"tbeseda","email":"tbeseda@gmail.com"},{"name":"daniel.malmer","email":"daniel.malmer@sanity.io"},{"name":"jordanl17","email":"jordanl17@me.com"},{"name":"colepeters","email":"cole@colepeters.com"},{"name":"armandocerna","email":"armando@cerna.ca"},{"name":"joan_miralles_paez","email":"joan.miralles@sanity.io"},{"name":"realmfour","email":"darius.west@sanity.io"},{"name":"christianhg","email":"services@groengaard.dk"},{"name":"pedro-sanity","email":"pedro@sanity.io"},{"name":"jwoods-sanity","email":"james.woods@sanity.io"},{"name":"binoy14","email":"me@binoy.io"},{"name":"pauloborgesf","email":"paulo@sanity.io"},{"name":"ausha","email":"ausha@sanity.io"},{"name":"chrislarocquesanity","email":"chris.larocque@sanity.io"},{"name":"tnaughts1","email":"tim.naughton@sanity.io"},{"name":"mm-sanity","email":"mark.michon@sanity.io"},{"name":"dennis.padiernos","email":"dennis.padiernos@sanity.io"},{"name":"alexjmold-sanity","email":"alex.mold@sanity.io"},{"name":"jason.brown","email":"jason.brown@sanity.io"},{"name":"taclandwork","email":"thomas.acland@sanity.io"},{"name":"rostimelk","email":"hello@rosti.no"},{"name":"mdinning","email":"michael.dinning@sanity.io"},{"name":"mattlewine.sanity","email":"matt.lewine@sanity.io"},{"name":"msfragala","email":"npm@msfragala.com"},{"name":"adoprog","email":"adoprog@gmail.com"},{"name":"tonysanity","email":"tony.lepmets@sanity.io"},{"name":"u269c","email":"francis@sanity.io"},{"name":"bramdo_","email":"bram.doppen@sanity.io"},{"name":"samhem","email":"sam.hemingway@sanity.io"},{"name":"betson","email":"ben.getson@gmail.com"},{"name":"georgedoescode","email":"georgedoescode@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"eoinsanity","email":"eoin.falconer@sanity.io"},{"name":"dashedstripes","email":"adamgrayscale@gmail.com"},{"name":"jmswrnr","email":"npm@jmswrnr.com"},{"name":"snocorp_sanity","email":"dave.sewell@sanity.io"},{"name":"mmgj","email":"controloptioncommand+npm@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"gu-stav","email":"gu@stav.dev"},{"name":"mads.mogenshoj","email":"mads.mogenshoj@sanity.io"},{"name":"sanitytom","email":"tom@sanity.io"},{"name":"sanity-cb","email":"charlie.brown@sanity.io"},{"name":"sanitykev","email":"kevin.green@sanity.io"},{"name":"victor.ayogu","email":"victor.ayogu@sanity.io"},{"name":"ryanbethel_sanity","email":"ryan.bethel@sanity.io"},{"name":"brianleroux","email":"b@brian.io"},{"name":"p10e","email":"peter@sanity.io"},{"name":"krlund","email":"kristoffer.lund@sanity.io"},{"name":"jonahsnider","email":"jonah@jonah.pw"},{"name":"mwritter","email":"matthew.ritter@sanity.io"},{"name":"torbratsbergsanity","email":"tor.bratsberg@sanity.io"},{"name":"evelinawahlstrom","email":"evelina.wahlstrom@sanity.io"},{"name":"jw-sanity","email":"jack.wilson@sanity.io"},{"name":"bobinska.dev","email":"bobinska.dev@gmail.com"},{"name":"oleg1357","email":"oleg.shcherbina@sanity.io"},{"name":"josef-sanity","email":"josef.hlavacek@sanity.io"},{"name":"gabe.wyatt","email":"gabe.wyatt@sanity.io"},{"name":"kbrabrand","email":"kristoffer@brabrand.no"},{"name":"annez-sanity","email":"david.annez@sanity.io"},{"name":"sanityjamie","email":"jamie.paulson@sanity.io"},{"name":"laurenashpolesanity","email":"lauren.ashpole@sanity.io"},{"name":"geoffball","email":"geoff@gball.dev"},{"name":"carsten.schwesig","email":"carsten.schwesig@sanity.io"},{"name":"fishstix81","email":"stephen.fisher@sanity.io"}],"homepage":"https://github.com/sanity-io/worker-channels#readme","bugs":{"url":"https://github.com/sanity-io/worker-channels/issues"},"dist":{"shasum":"8dfacfc9d1f5683e06829e3069e55dbaae4dde13","tarball":"https://registry.npmjs.org/@sanity/worker-channels/-/worker-channels-2.0.0.tgz","fileCount":8,"integrity":"sha512-mC+8yPQuw2rHXdHigFPU9thNa6vTaPmh7jFR6RvloE8s+6dmnk9bHdPXRbrrUqafxzK3L9aH2E170ubXyxcAIA==","signatures":[{"sig":"MEYCIQDyhAwAzxIo1h77GMcBcyedCo3PMR1KCilYCnLISKFJHgIhANZbFwSJCltDpdwfnG70+7DQufsakhZya7K5GO3f2mMW","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":108270},"type":"module","types":"./dist/index.d.ts","engines":{"node":">=20.19.1 <22 || >=22.12"},"exports":{".":{"source":"./src/index.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"bd1510403f2bddfdea9c4c0346c5235e31e9f192","scripts":{"lint":"eslint .","test":"tsc && vitest --run --coverage","build":"pkg-utils build --strict --check --clean","format":"prettier --write .","prepublishOnly":"npm run build"},"_npmUser":{"name":"sanity-svc.npm","email":"svc.npm@sanity.io"},"prettier":"@sanity/prettier-config","repository":{"url":"git+https://github.com/sanity-io/worker-channels.git","type":"git"},"_npmVersion":"11.8.0","description":"Type-safe, structured communication between worker threads and parent processes via TypeScript meta-programming.","directories":{},"sideEffects":false,"_nodeVersion":"24.13.1","browserslist":"extends @sanity/browserslist-config","publishConfig":{"access":"public","exports":{".":"./dist/index.js","./package.json":"./package.json"}},"_hasShrinkwrap":false,"packageManager":"pnpm@10.30.3+sha512.c961d1e0a2d8e354ecaa5166b822516668b7f44cb5bd95122d590dd81922f606f5473b6d23ec4a5be05e7fcd18e8488d47d978bbe981872f1145d06e9a740017","devDependencies":{"eslint":"^9.29.0","vitest":"^4.0.18","prettier":"^3.8.1","typescript":"^5.9.3","@sanity/tsconfig":"^2.1.0","semantic-release":"^25.0.3","@sanity/pkg-utils":"^10.4.4","typescript-eslint":"^8.56.1","@vitest/coverage-v8":"^4.0.18","eslint-plugin-tsdoc":"^0.5.2","eslint-config-prettier":"^10.1.5","eslint-plugin-import-x":"^4.15.2","eslint-plugin-prettier":"^5.5.5","@sanity/prettier-config":"^3.0.0","@sanity/browserslist-config":"^1.0.5","prettier-plugin-packagejson":"^3.0.0","@sanity/semantic-release-preset":"^6.0.0","eslint-import-resolver-typescript":"^4.4.3"},"_npmOperationalInternal":{"tmp":"tmp/worker-channels_2.0.0_1772471906100_0.041873718055920994","host":"s3://npm-registry-packages-npm-production"}}},"time":{"created":"2025-08-06T05:17:46.834Z","modified":"2026-04-08T15:21:08.549Z","1.0.0":"2025-08-06T05:17:47.088Z","1.1.0":"2025-08-07T09:23:18.742Z","2.0.0":"2026-03-02T17:18:26.249Z"},"bugs":{"url":"https://github.com/sanity-io/worker-channels/issues"},"author":{"name":"Sanity.io","email":"hello@sanity.io"},"license":"MIT","homepage":"https://github.com/sanity-io/worker-channels#readme","keywords":["sanity"],"repository":{"url":"git+https://github.com/sanity-io/worker-channels.git","type":"git"},"description":"Type-safe, structured communication between worker threads and parent processes via TypeScript meta-programming.","maintainers":[{"email":"svc.npm@sanity.io","name":"sanity-svc.npm"},{"email":"developers@sanity.io","name":"sanity-io"}],"readme":"# @sanity/worker-channels\n\n[![npm version](https://img.shields.io/npm/v/@sanity/worker-channels.svg)](https://www.npmjs.com/package/@sanity/worker-channels) [![bundle size](https://deno.bundlejs.com/?q=@sanity/worker-channels&badge)](https://bundlejs.com/?q=@sanity/worker-channels) [![github status checks](https://badgen.net/github/checks/sanity-io/worker-channels)](https://github.com/sanity-io/worker-channels/actions) [![npm weekly downloads](https://img.shields.io/npm/dw/@sanity/worker-channels.svg)](https://www.npmjs.com/package/@sanity/worker-channels) [![semantic-release: angular](https://img.shields.io/badge/semantic--release-angular-e10079?logo=semantic-release)](https://github.com/semantic-release/semantic-release)\n\n> Type-safe, structured communication between worker threads and parent processes via TypeScript meta-programming.\n\n## Table of Contents\n\n- [Motivation](#motivation)\n- [Installation](#installation)\n- [Quick Start](#quick-start)\n  - [1. Define your channel contract](#1-define-your-channel-contract)\n  - [2. Report events in your worker thread](#2-report-events-in-your-worker-thread)\n  - [3. Await events in your parent process](#3-await-events-in-your-parent-process)\n- [Usage Examples](#usage-examples)\n  - [Node.js Workers](#nodejs-workers)\n  - [Web Workers](#web-workers)\n  - [EventEmitter](#eventemitter)\n  - [EventTarget](#eventtarget)\n- [API Reference](#api-reference)\n  - [`WorkerChannel.Definition`](#workerchanneldefinition-workerchannelevent-workerchannelstream)\n  - [`WorkerChannelReporter`](#workerchannelreporter)\n  - [`WorkerChannelReceiver`](#workerchannelreceiver)\n- [Important Caveats](#important-caveats)\n  - [Events are one-time only](#events-are-one-time-only)\n  - [Streams must be ended](#streams-must-be-ended)\n  - [Control flow must match between worker and parent](#control-flow-must-match-between-worker-and-parent)\n- [LICENSE](#license)\n\n## Motivation\n\nWorker communication often becomes messy when different types of messages flow through the same channel. Worker channels provide **type-safe, structured communication** with clear contracts defined entirely in TypeScript.\n\n<table>\n<thead>\n<tr>\n<th>Traditional Approach ❌</th>\n<th>Worker Channels ✅</th>\n</tr>\n</thead>\n\n<tbody>\n<tr>\n<td>\n\n```ts\n// ================= worker.ts ====================\n// traditional worker — simple enough\n// ================================================\n\nimport {parentPort, workerData} from 'node:worker_threads'\nimport {processImage} from './processImage'\n\nconst imageFiles = workerData\n\nparentPort.postMessage({\n  type: 'started',\n  expected: imageFiles.length,\n})\n\nlet processed = 0\nfor (let i = 0; i < imageFiles.length; i++) {\n  const file = imageFiles[i]\n\n  try {\n    const result = await processImage(file)\n    parentPort.postMessage({\n      type: 'progress',\n      file: file.name,\n      completed: i + 1,\n      result,\n    })\n    processed++\n  } catch {\n    // ...\n  }\n}\n\nparentPort.postMessage({\n  type: 'finished',\n  processed,\n})\n```\n\n</td>\n\n<td>\n\n```ts\n// ================ worker.ts ========================\n// worker-channel worker — still simple and type-safe!\n// ===================================================\nimport {parentPort, workerData} from 'node:worker_threads'\nimport {WorkerChannelReporter} from '@sanity/worker-channels'\nimport {processImage} from './processImage'\nimport type {ImageChannel} from '...'\n\nconst report = WorkerChannelReporter.from<ImageChannel>(parentPort)\nconst imageFiles = workerData\n\nreport.event.started({expected: imageFiles.length})\n\nlet processed = 0\nfor (let i = 0; i < imageFiles.length; i++) {\n  const file = imageFiles[i]\n\n  try {\n    const result = await processImage(file)\n    report.stream.progress.emit({\n      file: file.name,\n      completed: i + 1,\n      result,\n    })\n    processed++\n  } catch {\n    // ...\n  }\n}\nreport.stream.progress.end()\n\nreport.event.finished({processed})\n```\n\n</td>\n</tr>\n\n<tr>\n<td>\n\n```ts\n// ================= main.ts ===================\n// a traditional parent — spaghetti control flow\n// =============================================\nimport {Worker} from 'node:worker_threads'\n\nconst worker = new Worker(/* ... */)\nlet expected = 0\n\nawait new Promise((resolve, reject) => {\n  worker.on('message', (msg) => {\n    switch (msg.type) {\n      case 'started':\n        expected = msg.expected\n        console.log(`Processing ${expected} images...`)\n        break\n      case 'progress':\n        const {file, completed} = msg\n        console.log(`${file}: ${completed}/${expected}`)\n        break\n      case 'finished':\n        const {processed} = msg\n        console.log(`Processed ${processed}/${expected}`)\n        resolve()\n        break\n      default:\n        console.warn('Unknown message type:', msg.type)\n    }\n  })\n\n  // don't forget to propagate errors\n  worker.on('error', reject)\n})\n```\n\n</td>\n<td>\n\n```ts\n// ==================== main.ts =======================\n// a worker-channel parent — control flow matches child\n// ====================================================\nimport {Worker} from 'node:worker_threads'\nimport {WorkerChannelReceiver} from '@sanity/worker-channels'\nimport type {ImageChannel} from '...'\n\nconst worker = new Worker(/* ... */)\n\nconst receiver = WorkerChannelReceiver.from<ImageChannel>(worker)\n\n// BONUS: the receiver automatically propagates errors\nconst {expected} = await receiver.event.started()\nconsole.log(`Processing ${expected} images...`)\n\nfor await (const progress of receiver.stream.progress()) {\n  const {file, completed} = progress\n  console.log(`${file}: ${completed}/${expected}`)\n}\n\nconst {processed} = await receiver.event.finished()\nconsole.log(`Processed ${processed}/${expected}`)\n\nreceiver.unsubscribe() // clean up after the worker\n```\n\n</td>\n</tr>\n</tbody>\n</table>\n\n> [!IMPORTANT]\n> The channel contract exists **solely in TypeScript types** and is shared between worker and parent processes.\n\nThis library uses Proxies to dynamically intercept property access and route messages to the correct handlers, providing **compile-time safety with minimal runtime overhead** while keeping worker and parent code cleanly isolated.\n\n```ts\nimport {type WorkerChannel} from '@sanity/worker-channels'\n\n// both the child and parent can import this with a type import\nexport type ImageChannel = WorkerChannel.Definition<{\n  started: WorkerChannel.Event<{expected: number}>\n  progress: WorkerChannel.Stream<{file: ImageFile; completed: number}>\n  finished: WorkerChannel.Event<{processed: number}>\n}>\n```\n\n## Installation\n\n```bash\nnpm install @sanity/worker-channels\n```\n\n## Quick Start\n\n### 1. Define your channel contract\n\n```ts\n// types.ts - shared between worker and parent\nimport {type WorkerChannel} from '@sanity/worker-channels'\n\nexport type BuildChannel = WorkerChannel.Definition<{\n  buildStart: WorkerChannel.Event<{target: string}>\n  progress: WorkerChannel.Stream<{file: string; percent: number}>\n  buildComplete: WorkerChannel.Event<{duration: number; files: string[]}>\n}>\n```\n\n### 2. Report events in your worker thread\n\n```ts\n// worker.ts\nimport {parentPort} from 'node:worker_threads'\nimport {WorkerChannelReporter} from '@sanity/worker-channels'\nimport type {BuildChannel} from './types'\n\nconst report = WorkerChannelReporter.from<BuildChannel>(parentPort)\n\n// Signal build started\nreport.event.buildStart({target: 'production'})\n\n// Stream progress updates\nconst files = ['app.js', 'styles.css', 'index.html']\nfor (let i = 0; i < files.length; i++) {\n  report.stream.progress.emit({\n    file: files[i],\n    percent: Math.round(((i + 1) / files.length) * 100),\n  })\n  await new Promise((resolve) => setTimeout(resolve, 1000)) // Simulate work\n}\nreport.stream.progress.end() // Important: end the stream\n\n// Signal completion\nreport.event.buildComplete({duration: 3000, files})\n```\n\n### 3. Await events in your parent process\n\n```ts\n// main.ts\nimport {Worker} from 'node:worker_threads'\nimport {WorkerChannelReceiver} from '@sanity/worker-channels'\nimport type {BuildChannel} from './types'\n\nconst worker = new Worker('./worker.js')\nconst receiver = WorkerChannelReceiver.from<BuildChannel>(worker)\n\n// Wait for build to start\nconst {target} = await receiver.event.buildStart()\nconsole.log(`Build started for ${target}`)\n\n// Monitor progress stream\nfor await (const {file, percent} of receiver.stream.progress()) {\n  console.log(`${file}: ${percent}%`)\n}\n\n// Wait for completion\nconst {duration, files} = await receiver.event.buildComplete()\nconsole.log(`Build completed in ${duration}ms, ${files.length} files`)\n\nreceiver.unsubscribe() // Clean up\n```\n\n## Usage Examples\n\n### Node.js Workers\n\n```ts\nimport {Worker} from 'node:worker_threads'\nimport {parentPort} from 'node:worker_threads'\n\n// Worker thread\nconst report = WorkerChannelReporter.from<MyChannel>(parentPort)\n\n// Parent process\nconst worker = new Worker('./worker.js')\nconst receiver = WorkerChannelReceiver.from<MyChannel>(worker)\n```\n\n### Web Workers\n\n```ts\n// In web worker\nconst report = WorkerChannelReporter.from<MyChannel>(self)\n\n// In main thread\nconst worker = new Worker('./worker.js')\nconst receiver = WorkerChannelReceiver.from<MyChannel>(worker)\n```\n\n### EventEmitter\n\nUseful for asynchronously reporting progress within the same thread in Node.js.\n\n```ts\nimport {EventEmitter} from 'node:events'\n\nconst emitter = new EventEmitter()\nconst reporter = WorkerChannelReporter.from<MyChannel>(emitter)\nconst receiver = WorkerChannelReceiver.from<MyChannel>(emitter)\n```\n\n### EventTarget\n\nSimilarly, `EventTarget` is also supported and useful for asynchronously reporting progress within the same thread in non-Node.js environments.\n\n```ts\nconst target = new EventTarget()\nconst reporter = WorkerChannelReporter.from<MyChannel>(target)\nconst receiver = WorkerChannelReceiver.from<MyChannel>(target)\n```\n\n## API Reference\n\n### `WorkerChannel.Definition`, `WorkerChannel.Event`, `WorkerChannel.Stream`\n\n```ts\ntype MyChannel = WorkerChannel.Definition<{\n  eventName: WorkerChannel.Event<PayloadType> // One-time events\n  streamName: WorkerChannel.Stream<PayloadType> // Continuous data streams\n}>\n```\n\n### `WorkerChannelReporter`\n\nReports events and streams from worker to parent process.\n\n#### Creation\n\n**Static factory (recommended):**\n\n```ts\n// Automatically detects the interface type\nconst report = WorkerChannelReporter.from<MyChannel>(parentPort)\n```\n\n**Constructor:**\n\n```ts\n// For custom message posting logic\nconst report = new WorkerChannelReporter<MyChannel>((message) => {\n  parentPort.postMessage(message)\n})\n```\n\n#### Usage\n\n```ts\n// Events (one-time only)\nreport.event.eventName(payload)\n\n// Streams (multiple emissions + end)\nreport.stream.streamName.emit(payload)\nreport.stream.streamName.emit(anotherPayload)\nreport.stream.streamName.end()\n```\n\n### `WorkerChannelReceiver`\n\nReceives events and streams from worker in the parent process.\n\n#### Creation\n\n**Static factory (recommended):**\n\n```ts\n// Automatically detects the interface type and sets up listeners\nconst receiver = WorkerChannelReceiver.from<MyChannel>(worker)\n```\n\n**Constructor:**\n\n```ts\n// For custom subscription logic\nconst receiver = new WorkerChannelReceiver<MyChannel>((subscriber) => {\n  worker.addListener('message', subscriber.next)\n  worker.addListener('error', subscriber.error)\n\n  // Return cleanup function\n  return () => {\n    worker.removeListener('message', subscriber.next)\n    worker.removeListener('error', subscriber.error)\n  }\n})\n```\n\n#### Usage\n\n```ts\n// Events (returns Promise that resolves once)\nconst payload = await receiver.event.eventName()\n\n// Streams (returns AsyncIterable for multiple values)\nfor await (const payload of receiver.stream.streamName()) {\n  console.log('Received:', payload)\n}\n\n// Cleanup (important for static factory instances)\nreceiver.unsubscribe()\n```\n\n#### Error Propagation\n\nWhen an error occurs in the worker thread, it automatically propagates to any awaiting event handlers or stream iterators in the parent process:\n\n```ts\n// If the worker throws an error...\n// worker.ts\nthrow new Error('Something went wrong in worker')\n```\n\n```ts\n// ...it will reject awaiting promises in the parent\n// main.ts\ntry {\n  const result = await receiver.event.completed() // ← Will reject with worker error\n} catch (error) {\n  console.error('Worker failed:', error.message) // \"Something went wrong in worker\"\n}\n\n// ...and cause stream iteration to throw\ntry {\n  for await (const progress of receiver.stream.progress()) {\n    // ← Will throw worker error\n    console.log(progress)\n  }\n} catch (error) {\n  console.error('Stream failed:', error.message) // \"Something went wrong in worker\"\n}\n```\n\nThis eliminates the need for manual error handling patterns like `worker.on('error', ...)` - errors are automatically propagated to the appropriate awaiting code.\n\n## Important Caveats\n\n### Events are one-time only\n\n```ts\n// ❌ This will throw an error\nreporter.event.buildComplete({duration: 1000})\nreporter.event.buildComplete({duration: 2000}) // Error: already reported\n\n// ✅ Use streams for multiple values instead\nreporter.stream.status.emit('processing')\nreporter.stream.status.emit('finalizing')\nreporter.stream.status.end()\n```\n\n> [!NOTE]\n> This design prevents bugs where the same event fires multiple times unexpectedly. It makes the contract explicit: use events for singular occurrences, streams for continuous data.\n\n### Streams must be ended\n\n```ts\n// ❌ Stream never ends - receiver will wait forever\nreporter.stream.progress.emit(50)\nreporter.stream.progress.emit(100)\n// Missing: reporter.stream.progress.end()\n\n// ✅ Always end streams\nreporter.stream.progress.emit(50)\nreporter.stream.progress.emit(100)\nreporter.stream.progress.end() // Signals completion\n```\n\n### Control flow must match between worker and parent\n\nThe parent's control flow should mirror the worker's control flow. If a condition prevents the worker from reporting an event/stream that the parent is awaiting, the parent will hang indefinitely:\n\n```ts\n// ❌ Worker may conditionally skip events\n// worker.ts\nif (shouldProcess) {\n  report.event.started({count: files.length})\n  // ... processing\n  report.event.finished({success: true})\n}\n// If shouldProcess is false, no events are sent\n\n// ❌ Parent unconditionally awaits - will hang if worker skips\n// main.ts\nawait receiver.event.started() // ← Will hang forever if shouldProcess is false\n// ...\nawait receiver.event.finished()\n```\n\n```ts\n// ✅ Match the conditional logic or use different events\n// worker.ts\nif (shouldProcess) {\n  report.event.started({count: files.length})\n  // ... processing\n  report.event.finished({success: true})\n} else {\n  report.event.skipped({reason: 'No processing needed'})\n}\n\n// ✅ Parent handles both cases\n// main.ts\nconst startResult = await Promise.race([\n  receiver.event.started().then((data) => ({type: 'started', data})),\n  receiver.event.skipped().then((data) => ({type: 'skipped', data})),\n])\n\nif (startResult.type === 'started') {\n  // ... handle processing flow\n  await receiver.event.finished()\n} else {\n  console.log('Processing skipped:', startResult.data.reason)\n}\n```\n\n> [!WARNING]\n> Worker channels provide message routing, not flow validation. The library doesn't verify that events are sent in the expected order or that all expected events are sent - it only ensures messages reach the right handlers when they are sent.\n\n## LICENSE\n\nMIT License - see [LICENSE](./LICENSE) file for details.\n","readmeFilename":"README.md"}