@callbag-recharge/callbag-recharge 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +263 -0
- package/dist/adapters/http.cjs +5 -0
- package/dist/adapters/http.cjs.map +1 -0
- package/dist/adapters/http.d.cts +81 -0
- package/dist/adapters/http.d.ts +81 -0
- package/dist/adapters/http.js +2 -0
- package/dist/adapters/http.js.map +1 -0
- package/dist/adapters/index.cjs +15 -0
- package/dist/adapters/index.cjs.map +1 -0
- package/dist/adapters/index.d.cts +6 -0
- package/dist/adapters/index.d.ts +6 -0
- package/dist/adapters/index.js +2 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/sse.cjs +15 -0
- package/dist/adapters/sse.cjs.map +1 -0
- package/dist/adapters/sse.d.cts +83 -0
- package/dist/adapters/sse.d.ts +83 -0
- package/dist/adapters/sse.js +2 -0
- package/dist/adapters/sse.js.map +1 -0
- package/dist/adapters/webhook.cjs +5 -0
- package/dist/adapters/webhook.cjs.map +1 -0
- package/dist/adapters/webhook.d.cts +83 -0
- package/dist/adapters/webhook.d.ts +83 -0
- package/dist/adapters/webhook.js +2 -0
- package/dist/adapters/webhook.js.map +1 -0
- package/dist/adapters/websocket.cjs +5 -0
- package/dist/adapters/websocket.cjs.map +1 -0
- package/dist/adapters/websocket.d.cts +110 -0
- package/dist/adapters/websocket.d.ts +110 -0
- package/dist/adapters/websocket.js +2 -0
- package/dist/adapters/websocket.js.map +1 -0
- package/dist/backoff-BXsH2Ago.d.cts +25 -0
- package/dist/backoff-BXsH2Ago.d.ts +25 -0
- package/dist/chunk-2XZKPAFR.js +2 -0
- package/dist/chunk-2XZKPAFR.js.map +1 -0
- package/dist/chunk-2YXXFGBV.js +2 -0
- package/dist/chunk-2YXXFGBV.js.map +1 -0
- package/dist/chunk-3GTX37MO.js +2 -0
- package/dist/chunk-3GTX37MO.js.map +1 -0
- package/dist/chunk-3ITR5SUG.js +2 -0
- package/dist/chunk-3ITR5SUG.js.map +1 -0
- package/dist/chunk-3KKK6A2R.js +2 -0
- package/dist/chunk-3KKK6A2R.js.map +1 -0
- package/dist/chunk-4KXERB6L.js +2 -0
- package/dist/chunk-4KXERB6L.js.map +1 -0
- package/dist/chunk-4O6TV3P2.js +2 -0
- package/dist/chunk-4O6TV3P2.js.map +1 -0
- package/dist/chunk-4WIEOFXE.js +2 -0
- package/dist/chunk-4WIEOFXE.js.map +1 -0
- package/dist/chunk-5HW4TA2W.js +2 -0
- package/dist/chunk-5HW4TA2W.js.map +1 -0
- package/dist/chunk-6H2GF6AW.js +2 -0
- package/dist/chunk-6H2GF6AW.js.map +1 -0
- package/dist/chunk-6I4PF5HN.js +2 -0
- package/dist/chunk-6I4PF5HN.js.map +1 -0
- package/dist/chunk-6JYKRWZW.js +2 -0
- package/dist/chunk-6JYKRWZW.js.map +1 -0
- package/dist/chunk-6WPTNQ5U.js +2 -0
- package/dist/chunk-6WPTNQ5U.js.map +1 -0
- package/dist/chunk-77ILIGIU.js +2 -0
- package/dist/chunk-77ILIGIU.js.map +1 -0
- package/dist/chunk-BA26PO4D.js +2 -0
- package/dist/chunk-BA26PO4D.js.map +1 -0
- package/dist/chunk-BSTNVIYQ.js +2 -0
- package/dist/chunk-BSTNVIYQ.js.map +1 -0
- package/dist/chunk-BSWWXWC3.js +2 -0
- package/dist/chunk-BSWWXWC3.js.map +1 -0
- package/dist/chunk-CGUO5L22.js +2 -0
- package/dist/chunk-CGUO5L22.js.map +1 -0
- package/dist/chunk-CMJIMY36.js +2 -0
- package/dist/chunk-CMJIMY36.js.map +1 -0
- package/dist/chunk-CS4UATLX.js +2 -0
- package/dist/chunk-CS4UATLX.js.map +1 -0
- package/dist/chunk-E63D25PW.js +1 -0
- package/dist/chunk-E63D25PW.js.map +1 -0
- package/dist/chunk-EJQL3MEV.js +2 -0
- package/dist/chunk-EJQL3MEV.js.map +1 -0
- package/dist/chunk-EMTGTDAU.js +2 -0
- package/dist/chunk-EMTGTDAU.js.map +1 -0
- package/dist/chunk-GB3CQBYM.js +2 -0
- package/dist/chunk-GB3CQBYM.js.map +1 -0
- package/dist/chunk-GRLPFDTM.js +2 -0
- package/dist/chunk-GRLPFDTM.js.map +1 -0
- package/dist/chunk-GXQR6NXR.js +2 -0
- package/dist/chunk-GXQR6NXR.js.map +1 -0
- package/dist/chunk-H7ZP3KB3.js +2 -0
- package/dist/chunk-H7ZP3KB3.js.map +1 -0
- package/dist/chunk-HCVP4K7S.js +2 -0
- package/dist/chunk-HCVP4K7S.js.map +1 -0
- package/dist/chunk-HG6CGYXT.js +2 -0
- package/dist/chunk-HG6CGYXT.js.map +1 -0
- package/dist/chunk-HKDBOVSA.js +2 -0
- package/dist/chunk-HKDBOVSA.js.map +1 -0
- package/dist/chunk-I5JAP5EF.js +2 -0
- package/dist/chunk-I5JAP5EF.js.map +1 -0
- package/dist/chunk-IKEIPCOF.js +5 -0
- package/dist/chunk-IKEIPCOF.js.map +1 -0
- package/dist/chunk-JPBL2BLU.js +2 -0
- package/dist/chunk-JPBL2BLU.js.map +1 -0
- package/dist/chunk-JS7XQDIV.js +2 -0
- package/dist/chunk-JS7XQDIV.js.map +1 -0
- package/dist/chunk-KIE25AEB.js +2 -0
- package/dist/chunk-KIE25AEB.js.map +1 -0
- package/dist/chunk-KUNBON6X.js +2 -0
- package/dist/chunk-KUNBON6X.js.map +1 -0
- package/dist/chunk-KZOI5YV6.js +2 -0
- package/dist/chunk-KZOI5YV6.js.map +1 -0
- package/dist/chunk-L7RJLIOI.js +2 -0
- package/dist/chunk-L7RJLIOI.js.map +1 -0
- package/dist/chunk-M3T7KRIL.js +2 -0
- package/dist/chunk-M3T7KRIL.js.map +1 -0
- package/dist/chunk-MOIZWKB5.js +2 -0
- package/dist/chunk-MOIZWKB5.js.map +1 -0
- package/dist/chunk-MR6IZER5.js +2 -0
- package/dist/chunk-MR6IZER5.js.map +1 -0
- package/dist/chunk-N4QXBWPI.js +2 -0
- package/dist/chunk-N4QXBWPI.js.map +1 -0
- package/dist/chunk-NNBOQGP5.js +2 -0
- package/dist/chunk-NNBOQGP5.js.map +1 -0
- package/dist/chunk-NQEHDKRA.js +2 -0
- package/dist/chunk-NQEHDKRA.js.map +1 -0
- package/dist/chunk-NRJH56H7.js +2 -0
- package/dist/chunk-NRJH56H7.js.map +1 -0
- package/dist/chunk-OCC6FGTW.js +2 -0
- package/dist/chunk-OCC6FGTW.js.map +1 -0
- package/dist/chunk-OJYUMMK5.js +2 -0
- package/dist/chunk-OJYUMMK5.js.map +1 -0
- package/dist/chunk-ONLG4NVU.js +2 -0
- package/dist/chunk-ONLG4NVU.js.map +1 -0
- package/dist/chunk-OXNTLUFP.js +2 -0
- package/dist/chunk-OXNTLUFP.js.map +1 -0
- package/dist/chunk-PULKIC7K.js +2 -0
- package/dist/chunk-PULKIC7K.js.map +1 -0
- package/dist/chunk-PYRVYHZG.js +2 -0
- package/dist/chunk-PYRVYHZG.js.map +1 -0
- package/dist/chunk-QTIFMHVO.js +2 -0
- package/dist/chunk-QTIFMHVO.js.map +1 -0
- package/dist/chunk-R6XJGBW5.js +2 -0
- package/dist/chunk-R6XJGBW5.js.map +1 -0
- package/dist/chunk-RIOVFLTK.js +2 -0
- package/dist/chunk-RIOVFLTK.js.map +1 -0
- package/dist/chunk-RUNOY5B2.js +2 -0
- package/dist/chunk-RUNOY5B2.js.map +1 -0
- package/dist/chunk-SSIEMJCA.js +2 -0
- package/dist/chunk-SSIEMJCA.js.map +1 -0
- package/dist/chunk-TJWINFKW.js +2 -0
- package/dist/chunk-TJWINFKW.js.map +1 -0
- package/dist/chunk-TVM2SBAO.js +2 -0
- package/dist/chunk-TVM2SBAO.js.map +1 -0
- package/dist/chunk-U33A66AD.js +2 -0
- package/dist/chunk-U33A66AD.js.map +1 -0
- package/dist/chunk-UDDLCJUX.js +2 -0
- package/dist/chunk-UDDLCJUX.js.map +1 -0
- package/dist/chunk-VEUKIPOG.js +2 -0
- package/dist/chunk-VEUKIPOG.js.map +1 -0
- package/dist/chunk-WVJLSNDG.js +2 -0
- package/dist/chunk-WVJLSNDG.js.map +1 -0
- package/dist/chunk-XHRZBR2S.js +12 -0
- package/dist/chunk-XHRZBR2S.js.map +1 -0
- package/dist/chunk-XRHBZ5A2.js +2 -0
- package/dist/chunk-XRHBZ5A2.js.map +1 -0
- package/dist/chunk-YYVR3FEB.js +2 -0
- package/dist/chunk-YYVR3FEB.js.map +1 -0
- package/dist/chunk-Z22E3QJ7.js +2 -0
- package/dist/chunk-Z22E3QJ7.js.map +1 -0
- package/dist/chunk-Z5WRDJR3.js +2 -0
- package/dist/chunk-Z5WRDJR3.js.map +1 -0
- package/dist/chunk-Z6DVUDH3.js +2 -0
- package/dist/chunk-Z6DVUDH3.js.map +1 -0
- package/dist/chunk-ZIRT45Q2.js +2 -0
- package/dist/chunk-ZIRT45Q2.js.map +1 -0
- package/dist/compat/jotai/index.cjs +5 -0
- package/dist/compat/jotai/index.cjs.map +1 -0
- package/dist/compat/jotai/index.d.cts +81 -0
- package/dist/compat/jotai/index.d.ts +81 -0
- package/dist/compat/jotai/index.js +2 -0
- package/dist/compat/jotai/index.js.map +1 -0
- package/dist/compat/nanostores/index.cjs +5 -0
- package/dist/compat/nanostores/index.cjs.map +1 -0
- package/dist/compat/nanostores/index.d.cts +123 -0
- package/dist/compat/nanostores/index.d.ts +123 -0
- package/dist/compat/nanostores/index.js +2 -0
- package/dist/compat/nanostores/index.js.map +1 -0
- package/dist/compat/signals/index.cjs +5 -0
- package/dist/compat/signals/index.cjs.map +1 -0
- package/dist/compat/signals/index.d.cts +125 -0
- package/dist/compat/signals/index.d.ts +125 -0
- package/dist/compat/signals/index.js +2 -0
- package/dist/compat/signals/index.js.map +1 -0
- package/dist/compat/zustand/index.cjs +5 -0
- package/dist/compat/zustand/index.cjs.map +1 -0
- package/dist/compat/zustand/index.d.cts +51 -0
- package/dist/compat/zustand/index.d.ts +51 -0
- package/dist/compat/zustand/index.js +2 -0
- package/dist/compat/zustand/index.js.map +1 -0
- package/dist/data/index.cjs +5 -0
- package/dist/data/index.cjs.map +1 -0
- package/dist/data/index.d.cts +33 -0
- package/dist/data/index.d.ts +33 -0
- package/dist/data/index.js +2 -0
- package/dist/data/index.js.map +1 -0
- package/dist/eviction-DGPP1vHP.d.cts +21 -0
- package/dist/eviction-DGPP1vHP.d.ts +21 -0
- package/dist/extra/buffer.cjs +5 -0
- package/dist/extra/buffer.cjs.map +1 -0
- package/dist/extra/buffer.d.cts +19 -0
- package/dist/extra/buffer.d.ts +19 -0
- package/dist/extra/buffer.js +2 -0
- package/dist/extra/buffer.js.map +1 -0
- package/dist/extra/bufferTime.cjs +5 -0
- package/dist/extra/bufferTime.cjs.map +1 -0
- package/dist/extra/bufferTime.d.cts +17 -0
- package/dist/extra/bufferTime.d.ts +17 -0
- package/dist/extra/bufferTime.js +2 -0
- package/dist/extra/bufferTime.js.map +1 -0
- package/dist/extra/combine.cjs +5 -0
- package/dist/extra/combine.cjs.map +1 -0
- package/dist/extra/combine.d.cts +33 -0
- package/dist/extra/combine.d.ts +33 -0
- package/dist/extra/combine.js +2 -0
- package/dist/extra/combine.js.map +1 -0
- package/dist/extra/concat.cjs +5 -0
- package/dist/extra/concat.cjs.map +1 -0
- package/dist/extra/concat.d.cts +19 -0
- package/dist/extra/concat.d.ts +19 -0
- package/dist/extra/concat.js +2 -0
- package/dist/extra/concat.js.map +1 -0
- package/dist/extra/concatMap.cjs +5 -0
- package/dist/extra/concatMap.cjs.map +1 -0
- package/dist/extra/concatMap.d.cts +10 -0
- package/dist/extra/concatMap.d.ts +10 -0
- package/dist/extra/concatMap.js +2 -0
- package/dist/extra/concatMap.js.map +1 -0
- package/dist/extra/debounce.cjs +5 -0
- package/dist/extra/debounce.cjs.map +1 -0
- package/dist/extra/debounce.d.cts +31 -0
- package/dist/extra/debounce.d.ts +31 -0
- package/dist/extra/debounce.js +2 -0
- package/dist/extra/debounce.js.map +1 -0
- package/dist/extra/delay.cjs +5 -0
- package/dist/extra/delay.cjs.map +1 -0
- package/dist/extra/delay.d.cts +17 -0
- package/dist/extra/delay.d.ts +17 -0
- package/dist/extra/delay.js +2 -0
- package/dist/extra/delay.js.map +1 -0
- package/dist/extra/distinctUntilChanged.cjs +5 -0
- package/dist/extra/distinctUntilChanged.cjs.map +1 -0
- package/dist/extra/distinctUntilChanged.d.cts +17 -0
- package/dist/extra/distinctUntilChanged.d.ts +17 -0
- package/dist/extra/distinctUntilChanged.js +2 -0
- package/dist/extra/distinctUntilChanged.js.map +1 -0
- package/dist/extra/elementAt.cjs +5 -0
- package/dist/extra/elementAt.cjs.map +1 -0
- package/dist/extra/elementAt.d.cts +15 -0
- package/dist/extra/elementAt.d.ts +15 -0
- package/dist/extra/elementAt.js +2 -0
- package/dist/extra/elementAt.js.map +1 -0
- package/dist/extra/empty.cjs +5 -0
- package/dist/extra/empty.cjs.map +1 -0
- package/dist/extra/empty.d.cts +13 -0
- package/dist/extra/empty.d.ts +13 -0
- package/dist/extra/empty.js +2 -0
- package/dist/extra/empty.js.map +1 -0
- package/dist/extra/exhaustMap.cjs +5 -0
- package/dist/extra/exhaustMap.cjs.map +1 -0
- package/dist/extra/exhaustMap.d.cts +9 -0
- package/dist/extra/exhaustMap.d.ts +9 -0
- package/dist/extra/exhaustMap.js +2 -0
- package/dist/extra/exhaustMap.js.map +1 -0
- package/dist/extra/filter.cjs +5 -0
- package/dist/extra/filter.cjs.map +1 -0
- package/dist/extra/filter.d.cts +36 -0
- package/dist/extra/filter.d.ts +36 -0
- package/dist/extra/filter.js +2 -0
- package/dist/extra/filter.js.map +1 -0
- package/dist/extra/find.cjs +5 -0
- package/dist/extra/find.cjs.map +1 -0
- package/dist/extra/find.d.cts +15 -0
- package/dist/extra/find.d.ts +15 -0
- package/dist/extra/find.js +2 -0
- package/dist/extra/find.js.map +1 -0
- package/dist/extra/first.cjs +5 -0
- package/dist/extra/first.cjs.map +1 -0
- package/dist/extra/first.d.cts +15 -0
- package/dist/extra/first.d.ts +15 -0
- package/dist/extra/first.js +2 -0
- package/dist/extra/first.js.map +1 -0
- package/dist/extra/flat.cjs +5 -0
- package/dist/extra/flat.cjs.map +1 -0
- package/dist/extra/flat.d.cts +9 -0
- package/dist/extra/flat.d.ts +9 -0
- package/dist/extra/flat.js +2 -0
- package/dist/extra/flat.js.map +1 -0
- package/dist/extra/forEach.cjs +2 -0
- package/dist/extra/forEach.cjs.map +1 -0
- package/dist/extra/forEach.d.cts +17 -0
- package/dist/extra/forEach.d.ts +17 -0
- package/dist/extra/forEach.js +2 -0
- package/dist/extra/forEach.js.map +1 -0
- package/dist/extra/fromEvent.cjs +5 -0
- package/dist/extra/fromEvent.cjs.map +1 -0
- package/dist/extra/fromEvent.d.cts +16 -0
- package/dist/extra/fromEvent.d.ts +16 -0
- package/dist/extra/fromEvent.js +2 -0
- package/dist/extra/fromEvent.js.map +1 -0
- package/dist/extra/fromIter.cjs +5 -0
- package/dist/extra/fromIter.cjs.map +1 -0
- package/dist/extra/fromIter.d.cts +15 -0
- package/dist/extra/fromIter.d.ts +15 -0
- package/dist/extra/fromIter.js +2 -0
- package/dist/extra/fromIter.js.map +1 -0
- package/dist/extra/fromObs.cjs +5 -0
- package/dist/extra/fromObs.cjs.map +1 -0
- package/dist/extra/fromObs.d.cts +24 -0
- package/dist/extra/fromObs.d.ts +24 -0
- package/dist/extra/fromObs.js +2 -0
- package/dist/extra/fromObs.js.map +1 -0
- package/dist/extra/fromPromise.cjs +5 -0
- package/dist/extra/fromPromise.cjs.map +1 -0
- package/dist/extra/fromPromise.d.cts +15 -0
- package/dist/extra/fromPromise.d.ts +15 -0
- package/dist/extra/fromPromise.js +2 -0
- package/dist/extra/fromPromise.js.map +1 -0
- package/dist/extra/index.cjs +5 -0
- package/dist/extra/index.cjs.map +1 -0
- package/dist/extra/index.d.cts +201 -0
- package/dist/extra/index.d.ts +201 -0
- package/dist/extra/index.js +2 -0
- package/dist/extra/index.js.map +1 -0
- package/dist/extra/interval.cjs +5 -0
- package/dist/extra/interval.cjs.map +1 -0
- package/dist/extra/interval.d.cts +15 -0
- package/dist/extra/interval.d.ts +15 -0
- package/dist/extra/interval.js +2 -0
- package/dist/extra/interval.js.map +1 -0
- package/dist/extra/last.cjs +5 -0
- package/dist/extra/last.cjs.map +1 -0
- package/dist/extra/last.d.cts +13 -0
- package/dist/extra/last.d.ts +13 -0
- package/dist/extra/last.js +2 -0
- package/dist/extra/last.js.map +1 -0
- package/dist/extra/map.cjs +5 -0
- package/dist/extra/map.cjs.map +1 -0
- package/dist/extra/map.d.cts +64 -0
- package/dist/extra/map.d.ts +64 -0
- package/dist/extra/map.js +2 -0
- package/dist/extra/map.js.map +1 -0
- package/dist/extra/merge.cjs +5 -0
- package/dist/extra/merge.cjs.map +1 -0
- package/dist/extra/merge.d.cts +32 -0
- package/dist/extra/merge.d.ts +32 -0
- package/dist/extra/merge.js +2 -0
- package/dist/extra/merge.js.map +1 -0
- package/dist/extra/never.cjs +5 -0
- package/dist/extra/never.cjs.map +1 -0
- package/dist/extra/never.d.cts +13 -0
- package/dist/extra/never.d.ts +13 -0
- package/dist/extra/never.js +2 -0
- package/dist/extra/never.js.map +1 -0
- package/dist/extra/of.cjs +5 -0
- package/dist/extra/of.cjs.map +1 -0
- package/dist/extra/of.d.cts +15 -0
- package/dist/extra/of.d.ts +15 -0
- package/dist/extra/of.js +2 -0
- package/dist/extra/of.js.map +1 -0
- package/dist/extra/pairwise.cjs +5 -0
- package/dist/extra/pairwise.cjs.map +1 -0
- package/dist/extra/pairwise.d.cts +13 -0
- package/dist/extra/pairwise.d.ts +13 -0
- package/dist/extra/pairwise.js +2 -0
- package/dist/extra/pairwise.js.map +1 -0
- package/dist/extra/partition.cjs +5 -0
- package/dist/extra/partition.cjs.map +1 -0
- package/dist/extra/partition.d.cts +15 -0
- package/dist/extra/partition.d.ts +15 -0
- package/dist/extra/partition.js +2 -0
- package/dist/extra/partition.js.map +1 -0
- package/dist/extra/pipeRaw.cjs +5 -0
- package/dist/extra/pipeRaw.cjs.map +1 -0
- package/dist/extra/pipeRaw.d.cts +12 -0
- package/dist/extra/pipeRaw.d.ts +12 -0
- package/dist/extra/pipeRaw.js +2 -0
- package/dist/extra/pipeRaw.js.map +1 -0
- package/dist/extra/remember.cjs +5 -0
- package/dist/extra/remember.cjs.map +1 -0
- package/dist/extra/remember.d.cts +13 -0
- package/dist/extra/remember.d.ts +13 -0
- package/dist/extra/remember.js +2 -0
- package/dist/extra/remember.js.map +1 -0
- package/dist/extra/repeat.cjs +5 -0
- package/dist/extra/repeat.cjs.map +1 -0
- package/dist/extra/repeat.d.cts +18 -0
- package/dist/extra/repeat.d.ts +18 -0
- package/dist/extra/repeat.js +2 -0
- package/dist/extra/repeat.js.map +1 -0
- package/dist/extra/rescue.cjs +5 -0
- package/dist/extra/rescue.cjs.map +1 -0
- package/dist/extra/rescue.d.cts +17 -0
- package/dist/extra/rescue.d.ts +17 -0
- package/dist/extra/rescue.js +2 -0
- package/dist/extra/rescue.js.map +1 -0
- package/dist/extra/retry.cjs +5 -0
- package/dist/extra/retry.cjs.map +1 -0
- package/dist/extra/retry.d.cts +31 -0
- package/dist/extra/retry.d.ts +31 -0
- package/dist/extra/retry.js +2 -0
- package/dist/extra/retry.js.map +1 -0
- package/dist/extra/sample.cjs +5 -0
- package/dist/extra/sample.cjs.map +1 -0
- package/dist/extra/sample.d.cts +15 -0
- package/dist/extra/sample.d.ts +15 -0
- package/dist/extra/sample.js +2 -0
- package/dist/extra/sample.js.map +1 -0
- package/dist/extra/scan.cjs +5 -0
- package/dist/extra/scan.cjs.map +1 -0
- package/dist/extra/scan.d.cts +37 -0
- package/dist/extra/scan.d.ts +37 -0
- package/dist/extra/scan.js +2 -0
- package/dist/extra/scan.js.map +1 -0
- package/dist/extra/share.cjs +2 -0
- package/dist/extra/share.cjs.map +1 -0
- package/dist/extra/share.d.cts +13 -0
- package/dist/extra/share.d.ts +13 -0
- package/dist/extra/share.js +2 -0
- package/dist/extra/share.js.map +1 -0
- package/dist/extra/skip.cjs +5 -0
- package/dist/extra/skip.cjs.map +1 -0
- package/dist/extra/skip.d.cts +28 -0
- package/dist/extra/skip.d.ts +28 -0
- package/dist/extra/skip.js +2 -0
- package/dist/extra/skip.js.map +1 -0
- package/dist/extra/startWith.cjs +5 -0
- package/dist/extra/startWith.cjs.map +1 -0
- package/dist/extra/startWith.d.cts +16 -0
- package/dist/extra/startWith.d.ts +16 -0
- package/dist/extra/startWith.js +2 -0
- package/dist/extra/startWith.js.map +1 -0
- package/dist/extra/subject.cjs +5 -0
- package/dist/extra/subject.cjs.map +1 -0
- package/dist/extra/subject.d.cts +21 -0
- package/dist/extra/subject.d.ts +21 -0
- package/dist/extra/subject.js +2 -0
- package/dist/extra/subject.js.map +1 -0
- package/dist/extra/subscribe.cjs +2 -0
- package/dist/extra/subscribe.cjs.map +1 -0
- package/dist/extra/subscribe.d.cts +46 -0
- package/dist/extra/subscribe.d.ts +46 -0
- package/dist/extra/subscribe.js +2 -0
- package/dist/extra/subscribe.js.map +1 -0
- package/dist/extra/switchMap.cjs +5 -0
- package/dist/extra/switchMap.cjs.map +1 -0
- package/dist/extra/switchMap.d.cts +9 -0
- package/dist/extra/switchMap.d.ts +9 -0
- package/dist/extra/switchMap.js +2 -0
- package/dist/extra/switchMap.js.map +1 -0
- package/dist/extra/take.cjs +5 -0
- package/dist/extra/take.cjs.map +1 -0
- package/dist/extra/take.d.cts +28 -0
- package/dist/extra/take.d.ts +28 -0
- package/dist/extra/take.js +2 -0
- package/dist/extra/take.js.map +1 -0
- package/dist/extra/takeUntil.cjs +5 -0
- package/dist/extra/takeUntil.cjs.map +1 -0
- package/dist/extra/takeUntil.d.cts +15 -0
- package/dist/extra/takeUntil.d.ts +15 -0
- package/dist/extra/takeUntil.js +2 -0
- package/dist/extra/takeUntil.js.map +1 -0
- package/dist/extra/takeWhile.cjs +5 -0
- package/dist/extra/takeWhile.cjs.map +1 -0
- package/dist/extra/takeWhile.d.cts +41 -0
- package/dist/extra/takeWhile.d.ts +41 -0
- package/dist/extra/takeWhile.js +2 -0
- package/dist/extra/takeWhile.js.map +1 -0
- package/dist/extra/tap.cjs +5 -0
- package/dist/extra/tap.cjs.map +1 -0
- package/dist/extra/tap.d.cts +15 -0
- package/dist/extra/tap.d.ts +15 -0
- package/dist/extra/tap.js +2 -0
- package/dist/extra/tap.js.map +1 -0
- package/dist/extra/throttle.cjs +5 -0
- package/dist/extra/throttle.cjs.map +1 -0
- package/dist/extra/throttle.d.cts +19 -0
- package/dist/extra/throttle.d.ts +19 -0
- package/dist/extra/throttle.js +2 -0
- package/dist/extra/throttle.js.map +1 -0
- package/dist/extra/throwError.cjs +5 -0
- package/dist/extra/throwError.cjs.map +1 -0
- package/dist/extra/throwError.d.cts +15 -0
- package/dist/extra/throwError.d.ts +15 -0
- package/dist/extra/throwError.js +2 -0
- package/dist/extra/throwError.js.map +1 -0
- package/dist/extra/timeout.cjs +5 -0
- package/dist/extra/timeout.cjs.map +1 -0
- package/dist/extra/timeout.d.cts +21 -0
- package/dist/extra/timeout.d.ts +21 -0
- package/dist/extra/timeout.js +2 -0
- package/dist/extra/timeout.js.map +1 -0
- package/dist/index.cjs +5 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +447 -0
- package/dist/index.d.ts +447 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/memory/index.cjs +5 -0
- package/dist/memory/index.cjs.map +1 -0
- package/dist/memory/index.d.cts +22 -0
- package/dist/memory/index.d.ts +22 -0
- package/dist/memory/index.js +2 -0
- package/dist/memory/index.js.map +1 -0
- package/dist/orchestrate/index.cjs +5 -0
- package/dist/orchestrate/index.cjs.map +1 -0
- package/dist/orchestrate/index.d.cts +790 -0
- package/dist/orchestrate/index.d.ts +790 -0
- package/dist/orchestrate/index.js +2 -0
- package/dist/orchestrate/index.js.map +1 -0
- package/dist/patterns/chatStream/index.cjs +5 -0
- package/dist/patterns/chatStream/index.cjs.map +1 -0
- package/dist/patterns/chatStream/index.d.cts +83 -0
- package/dist/patterns/chatStream/index.d.ts +83 -0
- package/dist/patterns/chatStream/index.js +2 -0
- package/dist/patterns/chatStream/index.js.map +1 -0
- package/dist/patterns/createStore/index.cjs +5 -0
- package/dist/patterns/createStore/index.cjs.map +1 -0
- package/dist/patterns/createStore/index.d.cts +66 -0
- package/dist/patterns/createStore/index.d.ts +66 -0
- package/dist/patterns/createStore/index.js +2 -0
- package/dist/patterns/createStore/index.js.map +1 -0
- package/dist/patterns/formField/index.cjs +5 -0
- package/dist/patterns/formField/index.cjs.map +1 -0
- package/dist/patterns/formField/index.d.cts +56 -0
- package/dist/patterns/formField/index.d.ts +56 -0
- package/dist/patterns/formField/index.js +2 -0
- package/dist/patterns/formField/index.js.map +1 -0
- package/dist/patterns/memoryStore/index.cjs +5 -0
- package/dist/patterns/memoryStore/index.cjs.map +1 -0
- package/dist/patterns/memoryStore/index.d.cts +87 -0
- package/dist/patterns/memoryStore/index.d.ts +87 -0
- package/dist/patterns/memoryStore/index.js +2 -0
- package/dist/patterns/memoryStore/index.js.map +1 -0
- package/dist/patterns/pagination/index.cjs +5 -0
- package/dist/patterns/pagination/index.cjs.map +1 -0
- package/dist/patterns/pagination/index.d.cts +55 -0
- package/dist/patterns/pagination/index.d.ts +55 -0
- package/dist/patterns/pagination/index.js +2 -0
- package/dist/patterns/pagination/index.js.map +1 -0
- package/dist/patterns/rateLimiter/index.cjs +5 -0
- package/dist/patterns/rateLimiter/index.cjs.map +1 -0
- package/dist/patterns/rateLimiter/index.d.cts +48 -0
- package/dist/patterns/rateLimiter/index.d.ts +48 -0
- package/dist/patterns/rateLimiter/index.js +2 -0
- package/dist/patterns/rateLimiter/index.js.map +1 -0
- package/dist/patterns/undoRedo/index.cjs +5 -0
- package/dist/patterns/undoRedo/index.cjs.map +1 -0
- package/dist/patterns/undoRedo/index.d.cts +47 -0
- package/dist/patterns/undoRedo/index.d.ts +47 -0
- package/dist/patterns/undoRedo/index.js +2 -0
- package/dist/patterns/undoRedo/index.js.map +1 -0
- package/dist/protocol-BVxRx57r.d.cts +68 -0
- package/dist/protocol-BVxRx57r.d.ts +68 -0
- package/dist/rateLimiter-DMeuSBxF.d.cts +30 -0
- package/dist/rateLimiter-DMeuSBxF.d.ts +30 -0
- package/dist/types-B9Xcup3y.d.ts +192 -0
- package/dist/types-BwU0Zcuz.d.cts +68 -0
- package/dist/types-Cy19Qubl.d.cts +192 -0
- package/dist/types-DGII6w5S.d.ts +68 -0
- package/dist/types-DVURpSl5.d.cts +97 -0
- package/dist/types-gYn5ONQ3.d.ts +97 -0
- package/dist/utils/index.cjs +5 -0
- package/dist/utils/index.cjs.map +1 -0
- package/dist/utils/index.d.cts +359 -0
- package/dist/utils/index.d.ts +359 -0
- package/dist/utils/index.js +2 -0
- package/dist/utils/index.js.map +1 -0
- package/package.json +285 -0
package/README.md
ADDED
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
# callbag-recharge
|
|
2
|
+
|
|
3
|
+
**State that flows.** Reactive state management for TypeScript — from simple atoms to streaming pipelines, in one library.
|
|
4
|
+
|
|
5
|
+
- **6 primitives** — `state`, `derived`, `dynamicDerived`, `effect`, `producer`, `operator`
|
|
6
|
+
- **60+ operators** — `switchMap`, `debounce`, `scan`, `retry`, and more — tree-shakeable
|
|
7
|
+
- **Glitch-free** — two-phase push resolves diamonds correctly, every time
|
|
8
|
+
- **Streaming-native** — LLM chunks, WebSocket, SSE are first-class, not bolted on
|
|
9
|
+
- **Inspectable** — every node in the graph is observable via `Inspector` — names, edges, phases, values
|
|
10
|
+
- **Framework-agnostic** — no providers, no wrappers, works anywhere JS runs
|
|
11
|
+
- Zero dependencies
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { state, derived, effect } from 'callbag-recharge'
|
|
15
|
+
|
|
16
|
+
const count = state(0)
|
|
17
|
+
const doubled = derived([count], () => count.get() * 2)
|
|
18
|
+
|
|
19
|
+
effect([doubled], () => {
|
|
20
|
+
console.log(doubled.get()) // 0, then 10
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
count.set(5)
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## When to use
|
|
29
|
+
|
|
30
|
+
- **Simple state management** — like Zustand/Jotai but framework-agnostic, no providers, no ceremony
|
|
31
|
+
- **Streaming data** — LLM token streams, WebSocket, SSE flowing into reactive state via `producer` or `fromAsyncIter`
|
|
32
|
+
- **Cancellable async** — `switchMap` auto-cancels the previous operation when a new one starts
|
|
33
|
+
- **Derived values you can trust** — diamond-safe, cached, always consistent
|
|
34
|
+
- **On-device / edge LLM streaming** — manage WebLLM, Ollama, or ExecuTorch token streams as reactive sources. Conversation state as stores, context window as derived computation
|
|
35
|
+
- **Hybrid cloud+edge model routing** — confidence-based routing between local and cloud LLMs with automatic fallback via `route()` + `rescue()`. Research shows 60% cost reduction and 40% latency improvement
|
|
36
|
+
- **Tool call state machines** — reactive state machines for LLM tool call lifecycle (request → execute → result → continue) using `stateMachine` + `producer`
|
|
37
|
+
- **Agentic workflows** — session state, tool call lifecycle, multi-agent coordination, memory with decay-scored eviction
|
|
38
|
+
- **Event pipelines** — transform, buffer, window, throttle, retry — compose with `pipe`
|
|
39
|
+
- **Reactive data structures** — `reactiveMap`, `reactiveLog`, `reactiveIndex` with near-native read performance
|
|
40
|
+
- **Scheduled pipelines** — cron triggers, task state tracking, DAG validation — Airflow-in-TypeScript
|
|
41
|
+
- **Durable workflows** — checkpoint persistence (file, SQLite, IndexedDB), execution logging, pipeline builder with topological sort
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Why callbag-recharge?
|
|
46
|
+
|
|
47
|
+
Most state managers stop at atoms and computed values. Most streaming libraries don't have state. This library is both — signals-style `.get()/.set()` ergonomics with callbag's streaming protocol underneath.
|
|
48
|
+
|
|
49
|
+
**What you get that others don't — all in one library:**
|
|
50
|
+
|
|
51
|
+
- **Glitch-free diamond resolution** — when A → B, A → C, B+C → D, D computes exactly once with consistent values. Jotai, Nanostores, and vanilla signals all glitch here.
|
|
52
|
+
- **Streaming operators as first-class citizens** — `switchMap`, `debounce`, `throttle`, `scan`, `retry`, `bufferTime` — not an afterthought, not a separate library.
|
|
53
|
+
- **Inspectable graph** — every store has a name, a kind, dependency edges, and a status. `Inspector.graph()` shows the full picture. No other state manager gives you this without runtime cost in production.
|
|
54
|
+
- **Effects with dirty tracking** — `effect()` knows which deps changed and waits for all to resolve before running. Smarter than `useEffect`, `autorun`, or `watch`.
|
|
55
|
+
- **Completion and error semantics** — stores can complete and error, just like streams. `retry`, `rescue`, `repeat` handle recovery. No ad-hoc try/catch.
|
|
56
|
+
- **Built-in batching** — `batch()` defers value propagation until all writes finish. No torn reads mid-update.
|
|
57
|
+
- **Reactive data structures** — `reactiveMap` (1.56x native Map), `reactiveLog` (2.5x native), `reactiveIndex` (1.01x native reads) — near-native reactive collections that no competitor offers.
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Quick start
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
import { state, derived, effect, pipe, producer, Inspector } from 'callbag-recharge'
|
|
65
|
+
import { map, filter, scan, subscribe } from 'callbag-recharge/extra'
|
|
66
|
+
|
|
67
|
+
// Writable state — the source of truth
|
|
68
|
+
const count = state(0)
|
|
69
|
+
count.set(5)
|
|
70
|
+
count.get() // 5
|
|
71
|
+
|
|
72
|
+
// Derived — explicit deps, cached, always fresh
|
|
73
|
+
const doubled = derived([count], () => count.get() * 2)
|
|
74
|
+
doubled.get() // 10
|
|
75
|
+
|
|
76
|
+
// Producer — push-based source with cleanup
|
|
77
|
+
const ticks = producer<number>(({ emit }) => {
|
|
78
|
+
const id = setInterval(() => emit(Date.now()), 1000)
|
|
79
|
+
return () => clearInterval(id)
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
// Effect — explicit deps, re-runs when deps change
|
|
83
|
+
const dispose = effect([doubled], () => {
|
|
84
|
+
console.log(doubled.get())
|
|
85
|
+
return () => { /* cleanup */ }
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
// Pipe — each step is an inspectable store
|
|
89
|
+
const result = pipe(
|
|
90
|
+
count,
|
|
91
|
+
map(n => n * 2),
|
|
92
|
+
filter(n => n > 0),
|
|
93
|
+
scan((acc, n) => acc + n, 0),
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
// Subscribe — listen to value changes
|
|
97
|
+
const unsub = subscribe(count, (value, prev) => {
|
|
98
|
+
console.log(`${prev} → ${value}`)
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
// Inspect the entire reactive graph
|
|
102
|
+
Inspector.graph()
|
|
103
|
+
// Map { 'count' => { kind: 'state', value: 5 }, ... }
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## 60+ operators, tree-shakeable
|
|
109
|
+
|
|
110
|
+
Import only what you need from `callbag-recharge/extra`.
|
|
111
|
+
|
|
112
|
+
**Sources** — `interval` · `fromIter` · `fromAsyncIter` · `fromEvent` · `fromPromise` · `fromObs` · `of` · `empty` · `throwError` · `never`
|
|
113
|
+
|
|
114
|
+
**Filtering** — `filter` · `take` · `skip` · `first` · `last` · `find` · `elementAt` · `distinctUntilChanged` · `takeUntil`
|
|
115
|
+
|
|
116
|
+
**Transformation** — `map` · `scan` · `pairwise` · `startWith` · `flat` · `switchMap` · `concatMap` · `exhaustMap` · `groupBy`
|
|
117
|
+
|
|
118
|
+
**Combination** — `merge` · `combine` · `concat` · `race` · `withLatestFrom` · `partition`
|
|
119
|
+
|
|
120
|
+
**Time** — `debounce` · `throttle` · `delay` · `timeout` · `sample` · `audit`
|
|
121
|
+
|
|
122
|
+
**Buffering** — `buffer` · `bufferCount` · `bufferTime`
|
|
123
|
+
|
|
124
|
+
**Windowing** — `window` · `windowCount` · `windowTime`
|
|
125
|
+
|
|
126
|
+
**Aggregation** — `reduce` · `toArray`
|
|
127
|
+
|
|
128
|
+
**Error handling** — `rescue` · `retry` · `repeat`
|
|
129
|
+
|
|
130
|
+
**Utilities** — `tap` · `share` · `remember` · `subject` · `wrap`
|
|
131
|
+
|
|
132
|
+
**Piping** — `pipeRaw` · `SKIP`
|
|
133
|
+
|
|
134
|
+
**Sinks** — `forEach` · `subscribe`
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## Design principles
|
|
139
|
+
|
|
140
|
+
1. **Stores are plain objects** — `{ get, set?, source }`, no classes, no property descriptors
|
|
141
|
+
2. **Two-phase push** — DIRTY propagates on type 3, then values flow on type 1; glitch-free diamonds without pull
|
|
142
|
+
3. **Explicit deps** — `derived` and `effect` declare dependencies upfront; callbag protocol is the sole connection mechanism
|
|
143
|
+
4. **Lazy derived** — no computation at construction. `get()` pull-computes from deps (always fresh). `source()` subscription triggers push-based connection; disconnects when last subscriber leaves
|
|
144
|
+
5. **`undefined` means empty** — no special symbols, no `.ready` flag
|
|
145
|
+
6. **Observability is external** — Inspector singleton with WeakMaps, zero per-store cost
|
|
146
|
+
|
|
147
|
+
See [docs/architecture.md](./docs/architecture.md) for the full design and implementation details.
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## Reactive data structures
|
|
152
|
+
|
|
153
|
+
Built on the core primitives, these provide reactive wrappers around common data structures with near-native read performance.
|
|
154
|
+
|
|
155
|
+
```ts
|
|
156
|
+
import { reactiveMap, reactiveLog, reactiveIndex } from 'callbag-recharge/data'
|
|
157
|
+
|
|
158
|
+
// Reactive Map — .get()/.set() with observable changes
|
|
159
|
+
const users = reactiveMap<string, User>()
|
|
160
|
+
users.set('alice', { name: 'Alice' })
|
|
161
|
+
const alice = users.select('alice') // Store<User | undefined> — reactive, cached
|
|
162
|
+
|
|
163
|
+
// Reactive Log — append-only with bounded mode (circular buffer)
|
|
164
|
+
const log = reactiveLog<string>({ maxSize: 1000 })
|
|
165
|
+
log.append('event happened')
|
|
166
|
+
const recent = log.slice(-10) // Store<string[]> — reactive
|
|
167
|
+
|
|
168
|
+
// Reactive Index — dual-key lookup, 1.01x native Map.get speed on reads
|
|
169
|
+
const index = reactiveIndex<string, string, Item>()
|
|
170
|
+
index.set('pk', 'sk', item)
|
|
171
|
+
const found = index.select('pk', 'sk') // Store<Item | undefined>
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## Scheduling & orchestration
|
|
177
|
+
|
|
178
|
+
Lightweight scheduling primitives that compose with `derived()` + `effect()` — diamond resolution IS the DAG executor.
|
|
179
|
+
|
|
180
|
+
```ts
|
|
181
|
+
import { fromCron, taskState, dag } from 'callbag-recharge/orchestrate'
|
|
182
|
+
import { pipe } from 'callbag-recharge'
|
|
183
|
+
import { exhaustMap, retry } from 'callbag-recharge/extra'
|
|
184
|
+
|
|
185
|
+
// Cron-triggered pipeline with retry
|
|
186
|
+
const daily = fromCron('0 9 * * *')
|
|
187
|
+
const fetchBank = pipe(daily, exhaustMap(() => fromPromise(plaid.sync())), retry(3))
|
|
188
|
+
const fetchCards = pipe(daily, exhaustMap(() => fromPromise(stripe.charges())), retry(3))
|
|
189
|
+
|
|
190
|
+
// Diamond resolution ensures aggregate runs once when both complete
|
|
191
|
+
const aggregate = derived([fetchBank, fetchCards], () => merge(fetchBank.get(), fetchCards.get()))
|
|
192
|
+
|
|
193
|
+
// Task state tracking
|
|
194
|
+
const task = taskState<Result>({ id: 'daily-sync' })
|
|
195
|
+
await task.run(() => syncAll())
|
|
196
|
+
task.get().status // 'success'
|
|
197
|
+
task.get().duration // ms
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## Agent memory
|
|
203
|
+
|
|
204
|
+
Reactive memory primitives for agentic workflows — push-based dirty tracking, decay-scored eviction, tag-based retrieval.
|
|
205
|
+
|
|
206
|
+
```ts
|
|
207
|
+
import { collection, memoryNode } from 'callbag-recharge/memory'
|
|
208
|
+
|
|
209
|
+
const memory = collection<string>({ maxSize: 100 })
|
|
210
|
+
memory.add('User prefers TypeScript', { id: 'pref-1', tags: ['preference'] })
|
|
211
|
+
|
|
212
|
+
// Tag-based retrieval via reactive index
|
|
213
|
+
memory.tagIndex.select('preference').get() // Set{'pref-1'}
|
|
214
|
+
|
|
215
|
+
// Decay-scored eviction — oldest/least important items evicted first
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## Callbag interop
|
|
221
|
+
|
|
222
|
+
Every store exposes a `.source` property — a standard callbag source function. State management signals (DIRTY, RESOLVED) flow on the type 3 STATE channel, keeping type 1 DATA for real values only.
|
|
223
|
+
|
|
224
|
+
```ts
|
|
225
|
+
import { STATE, DIRTY, RESOLVED } from 'callbag-recharge'
|
|
226
|
+
|
|
227
|
+
store.source(0, (type, data) => {
|
|
228
|
+
if (type === 3 && data === DIRTY) { /* invalidation */ }
|
|
229
|
+
if (type === 3 && data === RESOLVED) { /* resolved unchanged */ }
|
|
230
|
+
if (type === 1) { /* value */ }
|
|
231
|
+
})
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
## Documentation
|
|
237
|
+
|
|
238
|
+
- **[Docs site](https://callbag-recharge.github.io/callbag-recharge/)** — getting started, API reference, recipes
|
|
239
|
+
- [Architecture](./docs/architecture.md) — layers, design principles, how each primitive works
|
|
240
|
+
- [Extras](./docs/extras.md) — 60+ operators, sources, and sinks
|
|
241
|
+
- [Recipes](https://callbag-recharge.github.io/callbag-recharge/recipes/) — AI chat streaming, data pipelines, and more
|
|
242
|
+
- [llms.txt](./llms.txt) / [llms-full.txt](./llms-full.txt) — AI-readable documentation
|
|
243
|
+
- [Benchmarks](./docs/benchmarks.md) — Vitest + tinybench (`pnpm run bench`)
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
## Install
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
npm install callbag-recharge
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## Contributing
|
|
256
|
+
|
|
257
|
+
Clone, run `corepack enable` and `pnpm install`, then `pnpm test` / `pnpm run build`. See **[CONTRIBUTING.md](./CONTRIBUTING.md)** for commits; maintainers see **[docs/github-actions-release-setup.md](./docs/github-actions-release-setup.md)** for npm/GitHub Actions secrets.
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
## License
|
|
262
|
+
|
|
263
|
+
MIT
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";var H=Object.defineProperty;var lt=Object.getOwnPropertyDescriptor;var ct=Object.getOwnPropertyNames;var ft=Object.prototype.hasOwnProperty;var dt=(e,t)=>{for(var i in t)H(e,i,{get:t[i],enumerable:!0})},pt=(e,t,i,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of ct(t))!ft.call(e,s)&&s!==i&&H(e,s,{get:()=>t[s],enumerable:!(n=lt(t,s))||n.enumerable});return e};var gt=e=>pt(H({},"__esModule",{value:!0}),e);var Dt={};dt(Dt,{fromHTTP:()=>bt});module.exports=gt(Dt);var D=Symbol("DIRTY"),L=Symbol("RESOLVED"),B=Symbol("SINGLE_DEP"),J=0,Z=1,Q=2,X=3,tt=4,et=5,k=7,U=7<<k,ht=["DISCONNECTED","DIRTY","SETTLED","RESOLVED","COMPLETED","ERRORED"];function st(e){return ht[(e&U)>>>k]}var x=0,m=1,h=2,v=3,_t=0,Tt=[];function j(){return _t>0}function K(e){Tt.push(e)}var St=0,mt=[];function nt(e){St>0?mt.push(e):e()}var w=class e{static _names=new WeakMap;static _kinds=new WeakMap;static _keys=new WeakMap;static _stores=new Set;static _edges=new Map;static _nextId=0;static _usedKeys=new Set;static _explicitEnabled=null;static _cachedDefault=null;static get enabled(){if(e._explicitEnabled!==null)return e._explicitEnabled;if(e._cachedDefault!==null)return e._cachedDefault;try{e._cachedDefault=globalThis.process?.env?.NODE_ENV!=="production"}catch{e._cachedDefault=!0}return e._cachedDefault}static set enabled(t){e._explicitEnabled=t}static _depSuffix(t){if(!t?.length)return;let n=t.map(s=>e._names.get(s)??"?").join(",");return n.length>40?`${n.slice(0,37)}...`:n}static _resolveKey(t){return e._keys.get(t)??e._names.get(t)??"anonymous"}static register(t,i){if(!e.enabled)return;i?.name&&e._names.set(t,i.name),i?.kind&&e._kinds.set(t,i.kind);let n=e._nextId++,s=i?.name;if(!(s&&!e._usedKeys.has(s)))if(s){let r=e._depSuffix(i?.deps);s=r?`${s}(${r})`:`${s}_${n}`,e._usedKeys.has(s)&&(s=`${s}_${n}`)}else{let r=i?.kind??"store",o=e._depSuffix(i?.deps);s=o?`${r}(${o})`:`${r}_${n}`,e._usedKeys.has(s)&&(s=`${s}_${n}`)}e._usedKeys.add(s),e._keys.set(t,s),e._stores.add(new WeakRef(t))}static registerEdge(t,i){if(!e.enabled)return;let n=e._resolveKey(t),s=e._resolveKey(i),r=e._edges.get(n);r?r.includes(s)||r.push(s):e._edges.set(n,[s])}static getEdges(){return new Map(e._edges)}static getName(t){if(e.enabled)return e._names.get(t)}static getKind(t){return e._kinds.get(t)}static inspect(t){return{name:e._names.get(t),kind:e._kinds.get(t)??"unknown",value:typeof t.get=="function"?t.get():void 0,status:t._status}}static graph(){let t=new Map,i=new Set;for(let n of e._stores){let s=n.deref();if(!s){e._stores.delete(n);continue}let r=e._resolveKey(s);i.add(r),t.set(r,e.inspect(s))}for(let[n,s]of e._edges){if(!i.has(n)){e._edges.delete(n),e._usedKeys.delete(n);continue}let r=s.filter(o=>i.has(o));r.length===0?e._edges.delete(n):r.length!==s.length&&e._edges.set(n,r)}return t}static trace(t,i){let n=null,s=t.get();return t.source(x,(r,o)=>{if(r===x&&(n=o),r===h){n=null;return}if(r===1){let l=o;if(!Object.is(l,s)){let c=s;s=l,i(l,c)}}}),()=>n?.(h)}static dumpGraph(){let t=e.graph(),i=e.getEdges(),n=new Map;for(let[o,l]of i)for(let c of l){let f=n.get(c);f?f.includes(o)||f.push(o):n.set(c,[o])}let s=[];for(let[o,l]of t){let c=n.get(o),f=i.get(o),a=c?.length?` \u2190 [${c.join(", ")}]`:"",u=f?.length?` \u2192 [${f.join(", ")}]`:"";s.push(` ${o} (${l.kind}) = ${JSON.stringify(l.value)} [${l.status??"?"}]${a}${u}`)}return[`Store Graph (${t.size} nodes):`,...s].join(`
|
|
2
|
+
`)}static _observe(t,i,n){let s=null,r=i??e.getName(t),o={values:[],signals:[],events:[],ended:!1,endError:void 0,dirtyCount:0,resolvedCount:0,name:r,dispose:()=>s?.(h)};return t.source(x,(l,c)=>{if(l===x){s=c;return}l===m?(o.values.push(c),o.events.push({type:"data",data:c}),n&&n(`[${r}] DATA:`,c)):l===v?(o.signals.push(c),o.events.push({type:"signal",data:c}),c===D?o.dirtyCount++:c===L&&o.resolvedCount++,n&&n(`[${r}] STATE:`,c)):l===h&&(o.ended=!0,o.endError=c,o.events.push({type:"end",data:c}),n&&n(`[${r}] END`,c!==void 0?c:""),s=null)}),o}static observe(t){return e._observe(t)}static tap(t,i){let n=i??`tap(${e.getName(t)??"anon"})`,s={get:()=>t.get(),source:t.source};return e.register(s,{name:n,kind:"tap"}),e.registerEdge(t,s),s}static spy(t,i){let n=i?.name??e.getName(t)??"spy",s=i?.log??console.log;return e._observe(t,n,s)}static snapshot(){let t=e.graph(),i=e.getEdges(),n=[];for(let[r,o]of t)n.push({name:r,kind:o.kind,value:o.value,status:o.status});let s=[];for(let[r,o]of i)for(let l of o)s.push({from:r,to:l});return{nodes:n,edges:s}}static toMermaid(t){let i=t?.direction??"TD",n=e.snapshot(),s=[`graph ${i}`],r={SETTLED:":::settled",DIRTY:":::dirty",ERRORED:":::errored",COMPLETED:":::completed"},o=new Map;function l(a){let u=a.replace(/[^a-zA-Z0-9_]/g,"_"),d=o.get(u);return d===void 0?(o.set(u,1),u):(o.set(u,d+1),`${u}__${d}`)}let c=new Map;function f(a){let u=JSON.stringify(a);return u&&u.length>30?`${u.slice(0,27)}...`:u??"undefined"}for(let a of n.nodes){let u=l(a.name);c.set(a.name,u);let d=`${a.name} (${a.kind}) = ${f(a.value)}`,g=r[a.status??""]??"";s.push(` ${u}["${d}"]${g}`)}for(let a of n.edges){let u=c.get(a.from)??l(a.from),d=c.get(a.to)??l(a.to);s.push(` ${u} --> ${d}`)}return s.push(""),s.push(" classDef settled fill:#d4edda,stroke:#28a745"),s.push(" classDef dirty fill:#fff3cd,stroke:#ffc107"),s.push(" classDef errored fill:#f8d7da,stroke:#dc3545"),s.push(" classDef completed fill:#cce5ff,stroke:#007bff"),s.join(`
|
|
3
|
+
`)}static toD2(t){let i=t?.direction??"down",n=e.snapshot(),s=[`direction: ${i}`,""],r={state:"rectangle",derived:"hexagon",effect:"oval",producer:"rectangle",operator:"parallelogram","pipeline-step":"rectangle","pipeline-status":"diamond",checkpoint:"cylinder"},o=new Map;function l(a){let u=a.replace(/[^a-zA-Z0-9_]/g,"_"),d=o.get(u);return d===void 0?(o.set(u,1),u):(o.set(u,d+1),`${u}__${d}`)}let c=new Map;function f(a){let u=JSON.stringify(a);return u&&u.length>30?`${u.slice(0,27)}...`:u??"undefined"}for(let a of n.nodes){let u=l(a.name);c.set(a.name,u);let d=r[a.kind]??"rectangle",g=`${a.name} (${a.kind}) = ${f(a.value)}`,E=a.status?` [${a.status}]`:"";s.push(`${u}: "${g}${E}" { shape: ${d} }`)}n.edges.length>0&&s.push("");for(let a of n.edges){let u=c.get(a.from)??l(a.from),d=c.get(a.to)??l(a.to);s.push(`${u} -> ${d}`)}return s.join(`
|
|
4
|
+
`)}static _reset(){e._names=new WeakMap,e._kinds=new WeakMap,e._keys=new WeakMap,e._stores=new Set,e._edges=new Map,e._usedKeys=new Set,e._nextId=0,e._explicitEnabled=null,e._cachedDefault=null}};var F=1,_=64,T=2,I=4,it=8,rt=16,R=32,y=1024,p=U,P=Z<<k,A=Q<<k,Y=J<<k,vt=tt<<k,yt=et<<k,Et=X<<k,C=class{_value;_output=null;_flags;get _status(){return st(this._flags)}_cleanup;_fn;_eqFn;_getterFn;_initial;_singleDepCount=0;constructor(t,i){this._value=i?.initial,this._fn=t,this._eqFn=i?.equals,this._getterFn=i?.getter,this._initial=i?.initial;let n=0;i?.autoDirty!==!1&&(n|=I),i?.resetOnTeardown&&(n|=it),i?.resubscribable&&(n|=rt),this._flags=n,this.source=this.source.bind(this),this.emit=this.emit.bind(this),i?._skipInspect||w.register(this,{kind:"producer",...i})}get(){return this._getterFn?this._getterFn(this._value):this._value}_dispatch(t,i){let n=this._output;if(n)if(this._flags&_)for(let s of n)s(t,i);else n(t,i)}emit(t){this._flags&T||this._eqFn&&this._value!==void 0&&this._eqFn(this._value,t)||(this._value=t,this._output&&(j()?this._flags&R||(this._flags|=R,this._flags&I&&(this._flags=this._flags&~p|P,this._dispatch(v,D)),K(()=>{this._flags&=~R,this._flags=this._flags&~p|A,this._dispatch(m,this._value)})):(this._flags&I&&!(this._flags&y)&&(this._flags=this._flags&~p|P,this._dispatch(v,D)),this._flags=this._flags&~p|A,this._dispatch(m,this._value))))}signal(t){this._flags&T||!this._output||(t===D?this._flags=this._flags&~p|P:t===L&&(this._flags=this._flags&~p|Et),this._dispatch(v,t))}complete(){if(this._flags&T)return;this._flags=(this._flags|T)&~p|vt;let t=this._output,i=this._flags&_;if(this._output=null,this._flags&=~(_|y),this._singleDepCount=0,this._stop(),t)if(i)for(let n of t)n(h);else t(h)}error(t){if(this._flags&T)return;this._flags=(this._flags|T)&~p|yt;let i=this._output,n=this._flags&_;if(this._output=null,this._flags&=~(_|y),this._singleDepCount=0,this._stop(),i)if(n)for(let s of i)s(h,t);else i(h,t)}_start(){if(this._flags&F||!this._fn)return;this._flags|=F;let t=this._fn({emit:this.emit,signal:i=>this.signal(i),complete:()=>this.complete(),error:i=>this.error(i)});this._cleanup=typeof t=="function"?t:void 0}_stop(){this._flags&F&&(this._flags&=~F,this._cleanup&&this._cleanup(),this._cleanup=void 0,this._flags&it&&(this._value=this._initial),this._flags&T||(this._flags=this._flags&~p|Y))}source(t,i){if(t===x){let n=i;if(this._flags&T)if(this._flags&rt&&this._output===null)this._flags=this._flags&~(T|p)|Y;else{n(x,r=>{}),n(h);return}if(this._output===null)this._output=n;else if(this._flags&_)this._output.add(n);else{let r=new Set;r.add(this._output),r.add(n),this._output=r,this._flags=(this._flags|_)&~y}let s=!1;n(x,(r,o)=>{if(r===m&&n(m,this._value),r===v&&o===B&&!s&&(s=!0,this._singleDepCount++,this._flags&_||(this._flags|=y)),r===h){if(s&&(s=!1,this._singleDepCount--),this._output===null)return;if(this._flags&_){let l=this._output;l.delete(n),l.size===1?(this._output=l.values().next().value,this._flags&=~_,this._singleDepCount>0&&(this._flags|=y)):l.size===0&&(this._output=null,this._flags&=~(_|y),this._singleDepCount=0,this._flags=this._flags&~p|Y,this._stop())}else this._output===n&&(this._output=null,this._flags&=~y,this._singleDepCount=0,this._flags=this._flags&~p|Y,this._stop())}}),nt(()=>this._start())}}};function ot(e,t){return new C(e,t)}var W=class extends C{constructor(t,i){super(void 0,{initial:t,autoDirty:!0,equals:i?.equals??Object.is,_skipInspect:!0}),this.set=this.set.bind(this),w.register(this,{kind:"state",...i})}get(){return this._value}set(t){this._flags&T||this._value!==void 0&&this._eqFn(this._value,t)||(this._value=t,this._output&&(j()?this._flags&R||(this._flags|=R,this._flags&I&&(this._flags=this._flags&~p|P,this._dispatch(v,D)),K(()=>{this._flags&=~R,this._flags=this._flags&~p|A,this._dispatch(m,this._value)})):(this._flags&I&&!(this._flags&y)&&(this._flags=this._flags&~p|P,this._dispatch(v,D)),this._flags=this._flags&~p|A,this._dispatch(m,this._value))))}update(t){this.set(t(this._value))}};function G(e,t){return new W(e,t)}function bt(e,t){let i=t?.name??"http",n=t?.method??"GET",s=t?.headers,r=t?.body,o=t?.poll??0,l=t?.transform??(O=>O.json()),c=t?.timeout??3e4,f=G("idle",{name:`${i}:status`,equals:()=>!1}),a=G(0,{name:`${i}:fetchCount`}),u=null,d=null,g=null,E=null,S=!1;async function V(){if(!S||!u)return;E=new AbortController;let O=[E.signal];t?.signal&&O.push(t.signal);let $=new AbortController;for(let b of O){if(b.aborted){$.abort(b.reason);break}b.addEventListener("abort",()=>$.abort(b.reason),{once:!0})}let N=setTimeout(()=>$.abort(new Error("Request timeout")),c);try{f.set("fetching");let b=r!==void 0?typeof r=="string"?r:JSON.stringify(r):void 0,M=await fetch(e,{method:n,headers:s,body:b,signal:$.signal});if(!S)return;if(!M.ok)throw new Error(`HTTP ${M.status}: ${M.statusText}`);let at=await l(M);if(!S)return;a.update(ut=>ut+1),f.set("success"),u(at)}catch(b){if(!S||b?.name==="AbortError")return;f.set("error"),d?.(b)}finally{clearTimeout(N),E=null}}function z(){!S||o<=0||(g=setTimeout(()=>{g=null,V().then(()=>{S&&z()}).catch(()=>{})},o))}let q=null;return{store:ot(({emit:O,error:$})=>(u=O,d=$,S=!0,q=()=>{V()},V().then(()=>{S&&z()}),()=>{S=!1,u=null,d=null,q=null,E?.abort(),E=null,g!==null&&(clearTimeout(g),g=null);let N=f.get();N!=="error"&&N!=="success"&&f.set("idle")}),{name:i,kind:"http"}),status:f,fetchCount:a,refetch(){q?.()},stop(){S=!1,E?.abort(),E=null,g!==null&&(clearTimeout(g),g=null),f.get()==="fetching"&&f.set("idle")}}}0&&(module.exports={fromHTTP});
|
|
5
|
+
//# sourceMappingURL=http.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/adapters/http.ts","../../src/core/protocol.ts","../../src/core/inspector.ts","../../src/core/producer.ts","../../src/core/state.ts"],"sourcesContent":["// ---------------------------------------------------------------------------\n// fromHTTP — HTTP client source (fetch-based)\n// ---------------------------------------------------------------------------\n// Reactive source that fetches data from an HTTP endpoint. Supports\n// one-shot, polling, and custom transforms.\n//\n// Usage:\n// const data = fromHTTP(\"https://api.example.com/status\", { poll: 5000 });\n// subscribe(data.store, v => console.log(v));\n// data.stop();\n// ---------------------------------------------------------------------------\n\nimport { producer } from \"../core/producer\";\nimport { state } from \"../core/state\";\nimport type { Store } from \"../core/types\";\n\nexport type HTTPStatus = \"idle\" | \"fetching\" | \"success\" | \"error\";\n\nexport interface FromHTTPOptions {\n\t/** HTTP method. Default: \"GET\". */\n\tmethod?: string;\n\t/** Request headers. */\n\theaders?: Record<string, string>;\n\t/** Request body (for POST/PUT/PATCH). */\n\tbody?: string | object;\n\t/** Poll interval in ms. Omit or set 0 for one-shot. */\n\tpoll?: number;\n\t/** Transform the Response before emitting. Default: response.json(). */\n\ttransform?: (response: Response) => unknown | Promise<unknown>;\n\t/** Debug name for Inspector. */\n\tname?: string;\n\t/** AbortSignal for external cancellation. */\n\tsignal?: AbortSignal;\n\t/** Timeout per request in ms. Default: 30000. */\n\ttimeout?: number;\n}\n\nexport interface HTTPStore<T = unknown> {\n\t/** Reactive store emitting fetched values. */\n\tstore: Store<T | undefined>;\n\t/** Fetch status store. */\n\tstatus: Store<HTTPStatus>;\n\t/** Number of completed fetches. */\n\tfetchCount: Store<number>;\n\t/** Manually trigger a fetch (useful with polling disabled). */\n\trefetch(): void;\n\t/** Stop polling and cancel any in-flight request. */\n\tstop(): void;\n}\n\n/**\n * Creates a fetch-based HTTP source. Emits transformed response data as reactive values (Tier 2).\n *\n * @param url - The URL to fetch.\n * @param opts - Optional configuration.\n *\n * @returns `HTTPStore<T>` — reactive store with status, fetch count, and manual refetch.\n *\n * @returnsTable store | Store\\<T \\| undefined\\> | Reactive store emitting fetched values.\n * status | Store\\<HTTPStatus\\> | Fetch status: \"idle\", \"fetching\", \"success\", \"error\".\n * fetchCount | Store\\<number\\> | Number of completed fetches.\n * refetch() | () => void | Manually trigger a fetch.\n * stop() | () => void | Stop polling and cancel in-flight request.\n *\n * @remarks **Tier 2:** Cycle boundary — each fetch result starts a new DIRTY+value cycle.\n * @remarks **Polling:** Set `poll` interval for periodic refetch. Omit for one-shot.\n * @remarks **Transform:** Default extracts JSON. Override with `transform` for text, blob, etc.\n * @remarks **Timeout:** Default 30s per request. Uses AbortController internally.\n *\n * @example\n * ```ts\n * import { fromHTTP } from 'callbag-recharge/adapters/http';\n * import { subscribe } from 'callbag-recharge';\n *\n * const api = fromHTTP(\"https://api.example.com/status\", { poll: 5000 });\n * subscribe(api.store, data => console.log(\"status:\", data));\n * // Fetches immediately, then every 5s\n * api.stop();\n * ```\n *\n * @example One-shot POST\n * ```ts\n * const result = fromHTTP(\"https://api.example.com/submit\", {\n * method: \"POST\",\n * headers: { \"Content-Type\": \"application/json\" },\n * body: { name: \"test\" },\n * });\n * subscribe(result.store, v => console.log(v));\n * ```\n *\n * @seeAlso [fromWebhook](./webhook) — HTTP trigger (server-side), [fromWebSocket](./websocket) — WebSocket source\n *\n * @category adapters\n */\nexport function fromHTTP<T = unknown>(url: string, opts?: FromHTTPOptions): HTTPStore<T> {\n\tconst baseName = opts?.name ?? \"http\";\n\tconst method = opts?.method ?? \"GET\";\n\tconst headers = opts?.headers;\n\tconst bodyOpt = opts?.body;\n\tconst pollInterval = opts?.poll ?? 0;\n\tconst transform = opts?.transform ?? ((r: Response) => r.json());\n\tconst requestTimeout = opts?.timeout ?? 30000;\n\n\tconst statusStore = state<HTTPStatus>(\"idle\", {\n\t\tname: `${baseName}:status`,\n\t\tequals: () => false,\n\t});\n\tconst fetchCountStore = state<number>(0, { name: `${baseName}:fetchCount` });\n\n\tlet _emit: ((value: T) => void) | null = null;\n\tlet _error: ((e: unknown) => void) | null = null;\n\tlet pollTimer: ReturnType<typeof setTimeout> | null = null;\n\tlet currentAbort: AbortController | null = null;\n\tlet active = false;\n\n\tasync function doFetch() {\n\t\tif (!active || !_emit) return;\n\n\t\tcurrentAbort = new AbortController();\n\t\tconst signals: AbortSignal[] = [currentAbort.signal];\n\t\tif (opts?.signal) signals.push(opts.signal);\n\n\t\t// Combine signals\n\t\tconst combinedAbort = new AbortController();\n\t\tfor (const sig of signals) {\n\t\t\tif (sig.aborted) {\n\t\t\t\tcombinedAbort.abort(sig.reason);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tsig.addEventListener(\"abort\", () => combinedAbort.abort(sig.reason), { once: true });\n\t\t}\n\n\t\t// Timeout\n\t\tconst timeoutId = setTimeout(\n\t\t\t() => combinedAbort.abort(new Error(\"Request timeout\")),\n\t\t\trequestTimeout,\n\t\t);\n\n\t\ttry {\n\t\t\tstatusStore.set(\"fetching\");\n\n\t\t\tconst body =\n\t\t\t\tbodyOpt !== undefined\n\t\t\t\t\t? typeof bodyOpt === \"string\"\n\t\t\t\t\t\t? bodyOpt\n\t\t\t\t\t\t: JSON.stringify(bodyOpt)\n\t\t\t\t\t: undefined;\n\n\t\t\tconst response = await fetch(url, {\n\t\t\t\tmethod,\n\t\t\t\theaders,\n\t\t\t\tbody,\n\t\t\t\tsignal: combinedAbort.signal,\n\t\t\t});\n\n\t\t\tif (!active) return;\n\n\t\t\tif (!response.ok) {\n\t\t\t\tthrow new Error(`HTTP ${response.status}: ${response.statusText}`);\n\t\t\t}\n\n\t\t\tconst data = (await transform(response)) as T;\n\n\t\t\tif (!active) return;\n\n\t\t\tfetchCountStore.update((n) => n + 1);\n\t\t\tstatusStore.set(\"success\");\n\t\t\t_emit(data);\n\t\t} catch (err: any) {\n\t\t\tif (!active) return;\n\t\t\tif (err?.name === \"AbortError\") return; // Cancelled\n\t\t\tstatusStore.set(\"error\");\n\t\t\t_error?.(err);\n\t\t} finally {\n\t\t\tclearTimeout(timeoutId);\n\t\t\tcurrentAbort = null;\n\t\t}\n\t}\n\n\tfunction schedulePoll() {\n\t\tif (!active || pollInterval <= 0) return;\n\t\tpollTimer = setTimeout(() => {\n\t\t\tpollTimer = null;\n\t\t\tdoFetch()\n\t\t\t\t.then(() => {\n\t\t\t\t\tif (active) schedulePoll();\n\t\t\t\t})\n\t\t\t\t.catch(() => {\n\t\t\t\t\t// Already handled internally\n\t\t\t\t});\n\t\t}, pollInterval);\n\t}\n\n\tlet _refetch: (() => void) | null = null;\n\n\tconst store = producer<T>(\n\t\t({ emit, error }) => {\n\t\t\t_emit = emit;\n\t\t\t_error = error;\n\t\t\tactive = true;\n\n\t\t\t_refetch = () => {\n\t\t\t\tdoFetch();\n\t\t\t};\n\n\t\t\t// Initial fetch\n\t\t\tdoFetch().then(() => {\n\t\t\t\tif (active) schedulePoll();\n\t\t\t});\n\n\t\t\treturn () => {\n\t\t\t\tactive = false;\n\t\t\t\t_emit = null;\n\t\t\t\t_error = null;\n\t\t\t\t_refetch = null;\n\t\t\t\tcurrentAbort?.abort();\n\t\t\t\tcurrentAbort = null;\n\t\t\t\tif (pollTimer !== null) {\n\t\t\t\t\tclearTimeout(pollTimer);\n\t\t\t\t\tpollTimer = null;\n\t\t\t\t}\n\t\t\t\t// Don't overwrite error/success status on teardown\n\t\t\t\tconst currentStatus = statusStore.get();\n\t\t\t\tif (currentStatus !== \"error\" && currentStatus !== \"success\") {\n\t\t\t\t\tstatusStore.set(\"idle\");\n\t\t\t\t}\n\t\t\t};\n\t\t},\n\t\t{ name: baseName, kind: \"http\" },\n\t);\n\n\treturn {\n\t\tstore,\n\t\tstatus: statusStore,\n\t\tfetchCount: fetchCountStore,\n\t\trefetch() {\n\t\t\t_refetch?.();\n\t\t},\n\t\tstop() {\n\t\t\tactive = false;\n\t\t\tcurrentAbort?.abort();\n\t\t\tcurrentAbort = null;\n\t\t\tif (pollTimer !== null) {\n\t\t\t\tclearTimeout(pollTimer);\n\t\t\t\tpollTimer = null;\n\t\t\t}\n\t\t\t// Reset fetching status to idle on explicit stop\n\t\t\tif (statusStore.get() === \"fetching\") {\n\t\t\t\tstatusStore.set(\"idle\");\n\t\t\t}\n\t\t},\n\t};\n}\n","// ---------------------------------------------------------------------------\n// Protocol — v3 type 3 control channel\n// ---------------------------------------------------------------------------\n// Type 3 (STATE) carries control signals: DIRTY, RESOLVED\n// Type 1 (DATA) carries only real values — never sentinels\n// ---------------------------------------------------------------------------\n\n/** Control signal: \"my value is about to change\" */\nexport const DIRTY = Symbol(\"DIRTY\");\n\n/** Control signal: \"I was dirty but my value didn't change\" */\nexport const RESOLVED = Symbol(\"RESOLVED\");\n\n/** Talkback signal: \"I'm the only dep subscriber — skip DIRTY in unbatched paths\" */\nexport const SINGLE_DEP = Symbol(\"SINGLE_DEP\");\n\nexport type Signal = typeof DIRTY | typeof RESOLVED;\n\n/** Node status — tracks current lifecycle state (v4) */\nexport type NodeStatus =\n\t| \"DISCONNECTED\"\n\t| \"DIRTY\"\n\t| \"SETTLED\"\n\t| \"RESOLVED\"\n\t| \"COMPLETED\"\n\t| \"ERRORED\";\n\n// ---------------------------------------------------------------------------\n// Integer status constants — pack into _flags for hot-path performance.\n// 3 bits (7-9) encode 6 statuses. Use STATUS_MASK to read/write.\n// ---------------------------------------------------------------------------\nexport const S_DISCONNECTED = 0;\nexport const S_DIRTY = 1;\nexport const S_SETTLED = 2;\nexport const S_RESOLVED = 3;\nexport const S_COMPLETED = 4;\nexport const S_ERRORED = 5;\nexport const STATUS_SHIFT = 7;\nexport const STATUS_MASK = 0b111 << STATUS_SHIFT; // bits 7-9\n\nconst STATUS_STRINGS: NodeStatus[] = [\n\t\"DISCONNECTED\",\n\t\"DIRTY\",\n\t\"SETTLED\",\n\t\"RESOLVED\",\n\t\"COMPLETED\",\n\t\"ERRORED\",\n];\n\n/** Decode integer status bits back to string (for Inspector / tests) */\nexport function decodeStatus(flags: number): NodeStatus {\n\treturn STATUS_STRINGS[(flags & STATUS_MASK) >>> STATUS_SHIFT];\n}\n\n/** Callbag signal types */\nexport const START = 0;\nexport const DATA = 1;\nexport const END = 2;\nexport const STATE = 3;\n\n// ---------------------------------------------------------------------------\n// Batch — defers type 1 value emissions; type 3 DIRTY propagates immediately\n// ---------------------------------------------------------------------------\n\nlet batchDepth = 0;\nconst deferredEmissions: Array<() => void> = [];\n\n// `draining` prevents re-entrant drain when a nested batch() call ends while\n// the outer drain loop is already running. Without it, the inner batch's\n// finally block would see batchDepth===0 and start a second drain, racing the\n// outer loop — potentially double-processing items or clearing the array mid-\n// iteration. With draining=true, the inner batch skips its drain; any items it\n// pushes are picked up by the outer loop (the `for` condition re-evaluates\n// `deferredEmissions.length` on every iteration, so appends during drain are\n// naturally included in the same pass).\nlet draining = false;\n\n/**\n * Runs `fn` while deferring type 1 (DATA) emissions until the outermost batch completes.\n * Type 3 (STATE) DIRTY signals still propagate immediately so the graph knows what changed.\n *\n * @param fn - Synchronous work that may call `set()` / `emit()` on many stores.\n *\n * @returns The return value of `fn`.\n *\n * @remarks **Nesting:** Inner batches increment depth; only the outermost `finally` drains deferred emissions.\n * @remarks **Derived/effects:** Downstream nodes typically see one settled value per batch boundary.\n *\n * @example\n * ```ts\n * import { state, derived, batch } from 'callbag-recharge';\n *\n * const a = state(1);\n * const b = state(2);\n * const sum = derived([a, b], () => a.get() + b.get());\n * batch(() => {\n * a.set(10);\n * b.set(20);\n * });\n * sum.get(); // 30\n * ```\n *\n * @seeAlso [state](./state), [derived](./derived)\n */\nexport function batch<T>(fn: () => T): T {\n\tbatchDepth++;\n\ttry {\n\t\treturn fn();\n\t} finally {\n\t\tbatchDepth--;\n\t\tif (batchDepth === 0 && !draining) {\n\t\t\tdraining = true;\n\t\t\tfor (let i = 0; i < deferredEmissions.length; i++) {\n\t\t\t\tdeferredEmissions[i]();\n\t\t\t}\n\t\t\tdeferredEmissions.length = 0;\n\t\t\tdraining = false;\n\t\t}\n\t}\n}\n\nexport function isBatching(): boolean {\n\treturn batchDepth > 0;\n}\n\nexport function deferEmission(fn: () => void): void {\n\tdeferredEmissions.push(fn);\n}\n\n// ---------------------------------------------------------------------------\n// Connection batching (producer start deferral) — unchanged from v2\n// ---------------------------------------------------------------------------\n\nlet connectDepth = 0;\nconst pendingStarts: Array<() => void> = [];\n\nexport function beginDeferredStart(): void {\n\tconnectDepth++;\n}\n\nexport function endDeferredStart(): void {\n\tconnectDepth--;\n\tif (connectDepth === 0) {\n\t\tfor (let i = 0; i < pendingStarts.length; i++) {\n\t\t\tpendingStarts[i]();\n\t\t}\n\t\tpendingStarts.length = 0;\n\t}\n}\n\nexport function deferStart(start: () => void): void {\n\tif (connectDepth > 0) {\n\t\tpendingStarts.push(start);\n\t} else {\n\t\tstart();\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// teardown — protocol-level graph destruction\n// ---------------------------------------------------------------------------\n// Sends END to all downstream sinks of a store node, cascading through the\n// entire subgraph. After teardown, the node is in COMPLETED state and won't\n// accept new values or subscriptions.\n//\n// Works with any node that uses the output slot model:\n// - ProducerImpl / StateImpl / OperatorImpl → calls .complete()\n// - DerivedImpl → calls ._handleEnd() (no public complete() on derived)\n// ---------------------------------------------------------------------------\n\n/**\n * Completes a store-like node and cascades END to all downstream sinks (and tears down the subgraph).\n * After teardown, the node will not accept new subscriptions or values in the usual way.\n *\n * @param store - Any node with `source` and optionally `complete()` or internal `_handleEnd` (e.g. derived).\n *\n * @remarks **Producers:** Calls `complete()` when available. **Derived:** Uses `_handleEnd` when present.\n *\n * @example\n * ```ts\n * import { producer, teardown } from 'callbag-recharge';\n *\n * const s = producer<number>();\n * teardown(s);\n * ```\n *\n * @seeAlso [producer](./producer)\n */\nexport function teardown(store: { source: (type: number, payload?: any) => void }): void {\n\tconst node = store as any;\n\tif (typeof node.complete === \"function\") {\n\t\tnode.complete();\n\t} else if (typeof node._handleEnd === \"function\") {\n\t\tnode._handleEnd(undefined);\n\t}\n}\n","// ---------------------------------------------------------------------------\n// Inspector — static class for observability\n// ---------------------------------------------------------------------------\n// All debug metadata lives here in WeakMaps, not on the store objects.\n// Stores stay lean. Inspector is opt-in overhead.\n//\n// v5: Zero intrusion into primitives. No hooks in hot paths. All methods\n// are static — call directly as Inspector.observe(), Inspector.tap(), etc.\n// - register/registerEdge: metadata collection (called from constructors)\n// - inspect/graph/dumpGraph/snapshot: read-only graph queries\n// - observe/spy/trace: callbag sinks for debugging (subscribe externally)\n// - tap: transparent passthrough wrapper for graph visualization\n// ---------------------------------------------------------------------------\n\nimport type { NodeStatus, Signal } from \"./protocol\";\nimport { DATA, DIRTY, END, RESOLVED, START, STATE } from \"./protocol\";\nimport type { Store } from \"./types\";\n\nexport interface StoreInfo<T = unknown> {\n\tname: string | undefined;\n\tkind: string;\n\tvalue: T;\n\t/** v4: node lifecycle status */\n\tstatus: NodeStatus | undefined;\n}\n\nexport interface ObserveResult<T> {\n\t/** All DATA (type 1) values received, in order */\n\tvalues: T[];\n\t/** All STATE (type 3) payloads received (DIRTY, RESOLVED, or unknown) */\n\tsignals: Signal[];\n\t/** All events in protocol order: { type, data } */\n\tevents: Array<{ type: \"data\" | \"signal\" | \"end\"; data: unknown }>;\n\t/** Whether END (type 2) has been received */\n\tended: boolean;\n\t/** Error payload from END, if any */\n\tendError: unknown;\n\t/** Count of DIRTY signals received */\n\tdirtyCount: number;\n\t/** Count of RESOLVED signals received */\n\tresolvedCount: number;\n\t/** Store name (from Inspector, if registered) */\n\tname: string | undefined;\n\t/** Disconnect the observer */\n\tdispose: () => void;\n}\n\n// Static-only class is intentional API for Inspector namespace\n/**\n * Opt-in graph observability (`inspect`, `graph`, `trace`, `observe`, …). Metadata in WeakMaps.\n *\n * @example\n * ```ts\n * const n = state(0, { name: \"n\" });\n * Inspector.inspect(n).value; // 0\n * Inspector.inspect(n).kind; // \"state\"\n * ```\n */\n// biome-ignore lint/complexity/noStaticOnlyClass: public API surface\nexport class Inspector {\n\t// WeakMaps for metadata — keyed by any graph node (stores, effects, etc.)\n\tprivate static _names = new WeakMap<object, string>();\n\tprivate static _kinds = new WeakMap<object, string>();\n\tprivate static _keys = new WeakMap<object, string>();\n\n\t// WeakRef set for graph() — allows GC of unused nodes\n\tprivate static _stores = new Set<WeakRef<object>>();\n\n\t// Dependency edges: parent key → child keys\n\tprivate static _edges = new Map<string, string[]>();\n\n\t// Unique key generation\n\tprivate static _nextId = 0;\n\tprivate static _usedKeys = new Set<string>();\n\n\t// Enabled flag — when false, register/getName are no-ops\n\tprivate static _explicitEnabled: boolean | null = null;\n\tprivate static _cachedDefault: boolean | null = null;\n\n\tstatic get enabled(): boolean {\n\t\tif (Inspector._explicitEnabled !== null) return Inspector._explicitEnabled;\n\t\tif (Inspector._cachedDefault !== null) return Inspector._cachedDefault;\n\t\ttry {\n\t\t\tInspector._cachedDefault = (globalThis as any).process?.env?.NODE_ENV !== \"production\";\n\t\t} catch {\n\t\t\tInspector._cachedDefault = true;\n\t\t}\n\t\treturn Inspector._cachedDefault;\n\t}\n\n\tstatic set enabled(value: boolean) {\n\t\tInspector._explicitEnabled = value;\n\t}\n\n\t/** Compute a dep-name-based suffix for unique key generation */\n\tprivate static _depSuffix(deps?: object[]): string | undefined {\n\t\tif (!deps?.length) return undefined;\n\t\tconst names = deps.map((d) => Inspector._names.get(d) ?? \"?\");\n\t\tconst joined = names.join(\",\");\n\t\treturn joined.length > 40 ? `${joined.slice(0, 37)}...` : joined;\n\t}\n\n\t/** Resolve a node to its unique graph key */\n\tprivate static _resolveKey(node: object): string {\n\t\treturn Inspector._keys.get(node) ?? Inspector._names.get(node) ?? \"anonymous\";\n\t}\n\n\t/** Register a graph node (store, effect, etc.) with the inspector */\n\tstatic register(node: object, opts?: { name?: string; kind?: string; deps?: object[] }): void {\n\t\tif (!Inspector.enabled) return;\n\t\tif (opts?.name) Inspector._names.set(node, opts.name);\n\t\tif (opts?.kind) Inspector._kinds.set(node, opts.kind);\n\n\t\t// Compute unique key\n\t\tconst id = Inspector._nextId++;\n\t\tlet key = opts?.name;\n\t\tif (key && !Inspector._usedKeys.has(key)) {\n\t\t\t// Unique name — use as-is\n\t\t} else if (key) {\n\t\t\t// Name collision — differentiate with dep names or ID\n\t\t\tconst depSuffix = Inspector._depSuffix(opts?.deps);\n\t\t\tkey = depSuffix ? `${key}(${depSuffix})` : `${key}_${id}`;\n\t\t\tif (Inspector._usedKeys.has(key)) key = `${key}_${id}`;\n\t\t} else {\n\t\t\t// Unnamed — use kind + dep names or ID\n\t\t\tconst kind = opts?.kind ?? \"store\";\n\t\t\tconst depSuffix = Inspector._depSuffix(opts?.deps);\n\t\t\tkey = depSuffix ? `${kind}(${depSuffix})` : `${kind}_${id}`;\n\t\t\tif (Inspector._usedKeys.has(key)) key = `${key}_${id}`;\n\t\t}\n\n\t\tInspector._usedKeys.add(key);\n\t\tInspector._keys.set(node, key);\n\t\tInspector._stores.add(new WeakRef(node));\n\t}\n\n\t/** Register a dependency edge between parent and child nodes */\n\tstatic registerEdge(parent: object, child: object): void {\n\t\tif (!Inspector.enabled) return;\n\t\tconst parentKey = Inspector._resolveKey(parent);\n\t\tconst childKey = Inspector._resolveKey(child);\n\t\tconst children = Inspector._edges.get(parentKey);\n\t\tif (children) {\n\t\t\tif (!children.includes(childKey)) children.push(childKey);\n\t\t} else {\n\t\t\tInspector._edges.set(parentKey, [childKey]);\n\t\t}\n\t}\n\n\t/** Get dependency edges: parent → children */\n\tstatic getEdges(): Map<string, string[]> {\n\t\treturn new Map(Inspector._edges);\n\t}\n\n\t/** Get the name of a node */\n\tstatic getName(node: object): string | undefined {\n\t\tif (!Inspector.enabled) return undefined;\n\t\treturn Inspector._names.get(node);\n\t}\n\n\t/** Get the kind of a node */\n\tstatic getKind(node: object): string | undefined {\n\t\treturn Inspector._kinds.get(node);\n\t}\n\n\t/** Inspect a single graph node — includes status and value (if available) */\n\tstatic inspect<T = unknown>(node: object): StoreInfo<T> {\n\t\treturn {\n\t\t\tname: Inspector._names.get(node),\n\t\t\tkind: Inspector._kinds.get(node) ?? \"unknown\",\n\t\t\tvalue: (typeof (node as any).get === \"function\" ? (node as any).get() : undefined) as T,\n\t\t\tstatus: (node as any)._status,\n\t\t};\n\t}\n\n\t/** Get all living nodes as a Map. Also prunes dead edges from GC'd nodes. */\n\tstatic graph(): Map<string, StoreInfo> {\n\t\tconst result = new Map<string, StoreInfo>();\n\t\tconst livingKeys = new Set<string>();\n\t\tfor (const ref of Inspector._stores) {\n\t\t\tconst node = ref.deref();\n\t\t\tif (!node) {\n\t\t\t\tInspector._stores.delete(ref); // cleanup GC'd refs\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst key = Inspector._resolveKey(node);\n\t\t\tlivingKeys.add(key);\n\t\t\tresult.set(key, Inspector.inspect(node));\n\t\t}\n\t\t// Prune edges referencing GC'd stores\n\t\tfor (const [key, children] of Inspector._edges) {\n\t\t\tif (!livingKeys.has(key)) {\n\t\t\t\tInspector._edges.delete(key);\n\t\t\t\tInspector._usedKeys.delete(key);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst alive = children.filter((c) => livingKeys.has(c));\n\t\t\tif (alive.length === 0) {\n\t\t\t\tInspector._edges.delete(key);\n\t\t\t} else if (alive.length !== children.length) {\n\t\t\t\tInspector._edges.set(key, alive);\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\n\t/** Trace a specific store's value changes (raw callbag — no extra/ dependency) */\n\tstatic trace<T>(store: Store<T>, cb: (value: T, prev: T | undefined) => void): () => void {\n\t\tlet talkback: ((type: number) => void) | null = null;\n\t\tlet prev: T | undefined = store.get();\n\t\tstore.source(START, (type: number, data: any) => {\n\t\t\tif (type === START) talkback = data;\n\t\t\tif (type === END) {\n\t\t\t\ttalkback = null;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (type === 1) {\n\t\t\t\tconst next = data as T;\n\t\t\t\tif (!Object.is(next, prev)) {\n\t\t\t\t\tconst p = prev;\n\t\t\t\t\tprev = next;\n\t\t\t\t\tcb(next, p);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\treturn () => talkback?.(END);\n\t}\n\n\t/** Pretty-print the entire store graph for console/CLI debugging */\n\tstatic dumpGraph(): string {\n\t\tconst g = Inspector.graph();\n\t\tconst edges = Inspector.getEdges();\n\n\t\t// Build reverse map: child key → parent keys (deps)\n\t\tconst depsMap = new Map<string, string[]>();\n\t\tfor (const [parent, children] of edges) {\n\t\t\tfor (const child of children) {\n\t\t\t\tconst deps = depsMap.get(child);\n\t\t\t\tif (deps) {\n\t\t\t\t\tif (!deps.includes(parent)) deps.push(parent);\n\t\t\t\t} else {\n\t\t\t\t\tdepsMap.set(child, [parent]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst lines: string[] = [];\n\t\tfor (const [key, info] of g) {\n\t\t\tconst deps = depsMap.get(key);\n\t\t\tconst children = edges.get(key);\n\t\t\tconst depsStr = deps?.length ? ` ← [${deps.join(\", \")}]` : \"\";\n\t\t\tconst childStr = children?.length ? ` → [${children.join(\", \")}]` : \"\";\n\t\t\tlines.push(\n\t\t\t\t` ${key} (${info.kind}) = ${JSON.stringify(info.value)} [${info.status ?? \"?\"}]${depsStr}${childStr}`,\n\t\t\t);\n\t\t}\n\t\tconst header = `Store Graph (${g.size} nodes):`;\n\t\treturn [header, ...lines].join(\"\\n\");\n\t}\n\n\t/**\n\t * Internal observe implementation shared by observe() and spy().\n\t */\n\tprivate static _observe<T>(\n\t\tstore: Store<T>,\n\t\tlabel?: string,\n\t\tlog?: (...args: any[]) => void,\n\t): ObserveResult<T> {\n\t\tlet talkback: ((type: number) => void) | null = null;\n\t\tconst name = label ?? Inspector.getName(store);\n\t\tconst result: ObserveResult<T> = {\n\t\t\tvalues: [],\n\t\t\tsignals: [],\n\t\t\tevents: [],\n\t\t\tended: false,\n\t\t\tendError: undefined,\n\t\t\tdirtyCount: 0,\n\t\t\tresolvedCount: 0,\n\t\t\tname,\n\t\t\tdispose: () => talkback?.(END),\n\t\t};\n\n\t\tstore.source(START, (type: number, data: any) => {\n\t\t\tif (type === START) {\n\t\t\t\ttalkback = data;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (type === DATA) {\n\t\t\t\tresult.values.push(data);\n\t\t\t\tresult.events.push({ type: \"data\", data });\n\t\t\t\tif (log) log(`[${name}] DATA:`, data);\n\t\t\t} else if (type === STATE) {\n\t\t\t\tresult.signals.push(data);\n\t\t\t\tresult.events.push({ type: \"signal\", data });\n\t\t\t\tif (data === DIRTY) result.dirtyCount++;\n\t\t\t\telse if (data === RESOLVED) result.resolvedCount++;\n\t\t\t\tif (log) log(`[${name}] STATE:`, data);\n\t\t\t} else if (type === END) {\n\t\t\t\tresult.ended = true;\n\t\t\t\tresult.endError = data;\n\t\t\t\tresult.events.push({ type: \"end\", data });\n\t\t\t\tif (log) log(`[${name}] END`, data !== undefined ? data : \"\");\n\t\t\t\ttalkback = null;\n\t\t\t}\n\t\t});\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Observe a store's full callbag protocol — the test-friendly alternative\n\t * to hooks. Captures DATA values, STATE signals, END, and provides\n\t * convenience accessors.\n\t *\n\t * Returns a live observation object — arrays grow as the store emits.\n\t *\n\t * ```ts\n\t * const obs = Inspector.observe(myStore);\n\t * myState.set(5);\n\t * obs.values // [5]\n\t * obs.signals // [DIRTY]\n\t * obs.ended // false\n\t * obs.dirtyCount // 1\n\t * obs.dispose() // stop observing\n\t * ```\n\t */\n\tstatic observe<T>(store: Store<T>): ObserveResult<T> {\n\t\treturn Inspector._observe(store);\n\t}\n\n\t/**\n\t * Create a transparent passthrough wrapper for graph visualization.\n\t * The wrapper delegates `get()` and `source()` to the original store,\n\t * appearing as a distinct node in the Inspector graph. Zero overhead —\n\t * subscribers connect directly to the original store's source.\n\t */\n\tstatic tap<T>(store: Store<T>, name?: string): Store<T> {\n\t\tconst tapName = name ?? `tap(${Inspector.getName(store) ?? \"anon\"})`;\n\t\tconst wrapper: Store<T> = {\n\t\t\tget: () => store.get(),\n\t\t\tsource: store.source,\n\t\t};\n\t\tInspector.register(wrapper, { name: tapName, kind: \"tap\" });\n\t\tInspector.registerEdge(store, wrapper);\n\t\treturn wrapper;\n\t}\n\n\t/**\n\t * Enhanced observe() with logging — for interactive debugging.\n\t * Returns the same observation object as observe(), but also logs each\n\t * event as it happens. Pass a custom logger or defaults to console.log.\n\t */\n\tstatic spy<T>(\n\t\tstore: Store<T>,\n\t\topts?: { name?: string; log?: (...args: any[]) => void },\n\t): ObserveResult<T> {\n\t\tconst label = opts?.name ?? Inspector.getName(store) ?? \"spy\";\n\t\tconst log = opts?.log ?? console.log;\n\t\treturn Inspector._observe(store, label, log);\n\t}\n\n\t/**\n\t * JSON-serializable snapshot of the entire graph — nodes + edges.\n\t * Designed for AI consumption during debugging sessions.\n\t */\n\tstatic snapshot(): {\n\t\tnodes: Array<{ name: string; kind: string; value: unknown; status: string | undefined }>;\n\t\tedges: Array<{ from: string; to: string }>;\n\t} {\n\t\tconst g = Inspector.graph();\n\t\tconst edgeMap = Inspector.getEdges();\n\t\tconst nodes: Array<{ name: string; kind: string; value: unknown; status: string | undefined }> =\n\t\t\t[];\n\t\tfor (const [key, info] of g) {\n\t\t\tnodes.push({ name: key, kind: info.kind, value: info.value, status: info.status });\n\t\t}\n\t\tconst edges: Array<{ from: string; to: string }> = [];\n\t\tfor (const [parent, children] of edgeMap) {\n\t\t\tfor (const child of children) {\n\t\t\t\tedges.push({ from: parent, to: child });\n\t\t\t}\n\t\t}\n\t\treturn { nodes, edges };\n\t}\n\n\t/**\n\t * Export the graph as a Mermaid flowchart string.\n\t *\n\t * ```ts\n\t * console.log(Inspector.toMermaid());\n\t * // graph TD\n\t * // count[\"count (state) = 0\"]\n\t * // doubled[\"doubled (derived) = 0\"]\n\t * // count --> doubled\n\t * ```\n\t */\n\tstatic toMermaid(opts?: { direction?: \"TD\" | \"LR\" | \"BT\" | \"RL\" }): string {\n\t\tconst direction = opts?.direction ?? \"TD\";\n\t\tconst snap = Inspector.snapshot();\n\t\tconst lines: string[] = [`graph ${direction}`];\n\n\t\tconst statusStyle: Record<string, string> = {\n\t\t\tSETTLED: \":::settled\",\n\t\t\tDIRTY: \":::dirty\",\n\t\t\tERRORED: \":::errored\",\n\t\t\tCOMPLETED: \":::completed\",\n\t\t};\n\n\t\t// Sanitize for Mermaid node IDs — use deterministic suffix on collision\n\t\tconst usedIds = new Map<string, number>();\n\t\tfunction sanitizeId(name: string): string {\n\t\t\tconst base = name.replace(/[^a-zA-Z0-9_]/g, \"_\");\n\t\t\tconst count = usedIds.get(base);\n\t\t\tif (count === undefined) {\n\t\t\t\tusedIds.set(base, 1);\n\t\t\t\treturn base;\n\t\t\t}\n\t\t\tusedIds.set(base, count + 1);\n\t\t\treturn `${base}__${count}`;\n\t\t}\n\n\t\t// Cache name→id mapping for edge resolution\n\t\tconst nameToId = new Map<string, string>();\n\n\t\tfunction truncateValue(v: unknown): string {\n\t\t\tconst s = JSON.stringify(v);\n\t\t\treturn s && s.length > 30 ? `${s.slice(0, 27)}...` : (s ?? \"undefined\");\n\t\t}\n\n\t\tfor (const node of snap.nodes) {\n\t\t\tconst id = sanitizeId(node.name);\n\t\t\tnameToId.set(node.name, id);\n\t\t\tconst label = `${node.name} (${node.kind}) = ${truncateValue(node.value)}`;\n\t\t\tconst style = statusStyle[node.status ?? \"\"] ?? \"\";\n\t\t\tlines.push(` ${id}[\"${label}\"]${style}`);\n\t\t}\n\n\t\tfor (const edge of snap.edges) {\n\t\t\tconst fromId = nameToId.get(edge.from) ?? sanitizeId(edge.from);\n\t\t\tconst toId = nameToId.get(edge.to) ?? sanitizeId(edge.to);\n\t\t\tlines.push(` ${fromId} --> ${toId}`);\n\t\t}\n\n\t\t// classDef declarations for status-based styling\n\t\tlines.push(\"\");\n\t\tlines.push(\" classDef settled fill:#d4edda,stroke:#28a745\");\n\t\tlines.push(\" classDef dirty fill:#fff3cd,stroke:#ffc107\");\n\t\tlines.push(\" classDef errored fill:#f8d7da,stroke:#dc3545\");\n\t\tlines.push(\" classDef completed fill:#cce5ff,stroke:#007bff\");\n\n\t\treturn lines.join(\"\\n\");\n\t}\n\n\t/**\n\t * Export the graph as a D2 diagram string.\n\t *\n\t * ```ts\n\t * console.log(Inspector.toD2());\n\t * // count: \"count (state) = 0\" { shape: rectangle }\n\t * // doubled: \"doubled (derived) = 0\" { shape: rectangle }\n\t * // count -> doubled\n\t * ```\n\t */\n\tstatic toD2(opts?: { direction?: \"right\" | \"down\" | \"left\" | \"up\" }): string {\n\t\tconst direction = opts?.direction ?? \"down\";\n\t\tconst snap = Inspector.snapshot();\n\t\tconst lines: string[] = [`direction: ${direction}`, \"\"];\n\n\t\tconst kindShape: Record<string, string> = {\n\t\t\tstate: \"rectangle\",\n\t\t\tderived: \"hexagon\",\n\t\t\teffect: \"oval\",\n\t\t\tproducer: \"rectangle\",\n\t\t\toperator: \"parallelogram\",\n\t\t\t\"pipeline-step\": \"rectangle\",\n\t\t\t\"pipeline-status\": \"diamond\",\n\t\t\tcheckpoint: \"cylinder\",\n\t\t};\n\n\t\t// Sanitize with collision avoidance\n\t\tconst usedIds = new Map<string, number>();\n\t\tfunction sanitizeId(name: string): string {\n\t\t\tconst base = name.replace(/[^a-zA-Z0-9_]/g, \"_\");\n\t\t\tconst count = usedIds.get(base);\n\t\t\tif (count === undefined) {\n\t\t\t\tusedIds.set(base, 1);\n\t\t\t\treturn base;\n\t\t\t}\n\t\t\tusedIds.set(base, count + 1);\n\t\t\treturn `${base}__${count}`;\n\t\t}\n\n\t\tconst nameToId = new Map<string, string>();\n\n\t\tfunction truncateValue(v: unknown): string {\n\t\t\tconst s = JSON.stringify(v);\n\t\t\treturn s && s.length > 30 ? `${s.slice(0, 27)}...` : (s ?? \"undefined\");\n\t\t}\n\n\t\tfor (const node of snap.nodes) {\n\t\t\tconst id = sanitizeId(node.name);\n\t\t\tnameToId.set(node.name, id);\n\t\t\tconst shape = kindShape[node.kind] ?? \"rectangle\";\n\t\t\tconst label = `${node.name} (${node.kind}) = ${truncateValue(node.value)}`;\n\t\t\tconst statusStr = node.status ? ` [${node.status}]` : \"\";\n\t\t\tlines.push(`${id}: \"${label}${statusStr}\" { shape: ${shape} }`);\n\t\t}\n\n\t\tif (snap.edges.length > 0) lines.push(\"\");\n\n\t\tfor (const edge of snap.edges) {\n\t\t\tconst fromId = nameToId.get(edge.from) ?? sanitizeId(edge.from);\n\t\t\tconst toId = nameToId.get(edge.to) ?? sanitizeId(edge.to);\n\t\t\tlines.push(`${fromId} -> ${toId}`);\n\t\t}\n\n\t\treturn lines.join(\"\\n\");\n\t}\n\n\t/** Reset all state (for testing) */\n\tstatic _reset(): void {\n\t\tInspector._names = new WeakMap<object, string>();\n\t\tInspector._kinds = new WeakMap<object, string>();\n\t\tInspector._keys = new WeakMap<object, string>();\n\t\tInspector._stores = new Set<WeakRef<object>>();\n\t\tInspector._edges = new Map();\n\t\tInspector._usedKeys = new Set();\n\t\tInspector._nextId = 0;\n\t\tInspector._explicitEnabled = null;\n\t\tInspector._cachedDefault = null;\n\t}\n}\n","/**\n * General-purpose source primitive. Can emit values, send control signals,\n * complete, and error. Lazy start on first sink, auto-cleanup on last\n * sink disconnect.\n *\n * Stateful: maintains currentValue. get() returns currentValue (or\n * getter(currentValue) when getter option is provided).\n *\n * v4: Output slot model replaces _sinks Set. _output is null (no sinks),\n * a function (single sink — P0 optimization), or a Set (multi sink).\n * _status tracks node lifecycle. autoDirty (default true) sends DIRTY on\n * type 3 before each type 1 DATA. equals option guards emit();\n * resetOnTeardown resets value on stop.\n *\n * v5: _status packed into _flags bits 7-9 for hot-path performance.\n * String status exposed via getter for Inspector/test backward compat.\n *\n * Class-based for V8 hidden class optimization and prototype method sharing.\n * Boolean fields packed into _flags bitmask to reduce hidden class size.\n */\n\nimport { Inspector } from \"./inspector\";\nimport type { Signal } from \"./protocol\";\nimport {\n\tDATA,\n\tDIRTY,\n\tdecodeStatus,\n\tdeferEmission,\n\tdeferStart,\n\tEND,\n\tisBatching,\n\tRESOLVED,\n\tS_COMPLETED,\n\tS_DIRTY,\n\tS_DISCONNECTED,\n\tS_ERRORED,\n\tS_RESOLVED,\n\tS_SETTLED,\n\tSINGLE_DEP,\n\tSTART,\n\tSTATE,\n\tSTATUS_MASK,\n\tSTATUS_SHIFT,\n} from \"./protocol\";\nimport type { ProducerStore, SourceOptions, Store } from \"./types\";\n\nexport type ProducerFn<T> = (actions: {\n\temit: (value: T) => void;\n\tsignal: (s: Signal) => void;\n\tcomplete: () => void;\n\terror: (e: unknown) => void;\n}) => (() => void) | undefined;\n\nexport type ProducerOpts<T> = SourceOptions<T> & {\n\tautoDirty?: boolean;\n\t_skipInspect?: boolean;\n};\n\n// Flag bits for _flags bitmask (bits 0-6)\nconst P_STARTED = 1;\nconst P_MULTI = 64;\n\n// Exported for subclass fast paths (StateImpl)\nexport const P_COMPLETED = 2;\nexport const P_AUTO_DIRTY = 4;\nconst P_RESET = 8;\nconst P_RESUB = 16;\nexport const P_PENDING = 32;\n\n// Bit 10: single subscriber signaled SINGLE_DEP — skip DIRTY in unbatched emit/set\nexport const P_SKIP_DIRTY = 1 << 10;\n\n// Status bits (bits 7-9) — exported for StateImpl fast path\nexport const _STATUS_MASK = STATUS_MASK;\nexport const _S_DIRTY = S_DIRTY << STATUS_SHIFT;\nexport const _S_SETTLED = S_SETTLED << STATUS_SHIFT;\nexport const _S_DISCONNECTED = S_DISCONNECTED << STATUS_SHIFT;\nexport const _S_COMPLETED = S_COMPLETED << STATUS_SHIFT;\nexport const _S_ERRORED = S_ERRORED << STATUS_SHIFT;\nexport const _S_RESOLVED = S_RESOLVED << STATUS_SHIFT;\n\nexport class ProducerImpl<T> {\n\t_value: T | undefined;\n\t_output: ((type: number, data?: any) => void) | Set<any> | null = null;\n\t_flags: number;\n\n\tget _status() {\n\t\treturn decodeStatus(this._flags);\n\t}\n\t_cleanup: (() => void) | undefined;\n\t_fn: ProducerFn<T> | undefined;\n\t_eqFn: ((a: T, b: T) => boolean) | undefined;\n\t_getterFn: ((cached: T | undefined) => T) | undefined;\n\t_initial: T | undefined;\n\t_singleDepCount = 0;\n\n\tconstructor(fn?: ProducerFn<T>, opts?: ProducerOpts<T>) {\n\t\tthis._value = opts?.initial;\n\t\tthis._fn = fn;\n\t\tthis._eqFn = opts?.equals;\n\t\tthis._getterFn = opts?.getter;\n\t\tthis._initial = opts?.initial;\n\n\t\tlet flags = 0;\n\t\tif (opts?.autoDirty !== false) flags |= P_AUTO_DIRTY;\n\t\tif (opts?.resetOnTeardown) flags |= P_RESET;\n\t\tif (opts?.resubscribable) flags |= P_RESUB;\n\t\t// S_DISCONNECTED = 0, so no need to set status bits\n\t\tthis._flags = flags;\n\n\t\t// Bind only source + emit (commonly detached in callbag interop and\n\t\t// destructuring). signal/complete/error are provided via actions wrapper\n\t\t// in _start() — see Optimization #2 in docs/optimizations.md.\n\t\tthis.source = this.source.bind(this);\n\t\tthis.emit = this.emit.bind(this);\n\n\t\tif (!opts?._skipInspect) Inspector.register(this as any, { kind: \"producer\", ...opts });\n\t}\n\n\tget(): T | undefined {\n\t\treturn this._getterFn ? this._getterFn(this._value) : this._value;\n\t}\n\n\t/**\n\t * Dispatch a signal to all current subscribers via the output slot.\n\t *\n\t * Safety: P_MULTI flag and _output type are always updated together.\n\t * No reentrancy can occur between the two assignments (source() doesn't\n\t * trigger dispatch, and dispatch doesn't trigger source()). The null-check\n\t * provides an additional guard for the MULTI→null transition path.\n\t */\n\t_dispatch(type: number, data?: any): void {\n\t\tconst output = this._output;\n\t\tif (!output) return;\n\t\tif (this._flags & P_MULTI) {\n\t\t\tfor (const sink of output as Set<any>) sink(type, data);\n\t\t} else {\n\t\t\t(output as (type: number, data?: any) => void)(type, data);\n\t\t}\n\t}\n\n\temit(value: T): void {\n\t\tif (this._flags & P_COMPLETED) return;\n\t\tif (this._eqFn && this._value !== undefined && this._eqFn(this._value as T, value)) return;\n\t\tthis._value = value;\n\t\tif (!this._output) return;\n\t\tif (isBatching()) {\n\t\t\tif (!(this._flags & P_PENDING)) {\n\t\t\t\tthis._flags |= P_PENDING;\n\t\t\t\tif (this._flags & P_AUTO_DIRTY) {\n\t\t\t\t\tthis._flags = (this._flags & ~_STATUS_MASK) | _S_DIRTY;\n\t\t\t\t\tthis._dispatch(STATE, DIRTY);\n\t\t\t\t}\n\t\t\t\tdeferEmission(() => {\n\t\t\t\t\tthis._flags &= ~P_PENDING;\n\t\t\t\t\tthis._flags = (this._flags & ~_STATUS_MASK) | _S_SETTLED;\n\t\t\t\t\tthis._dispatch(DATA, this._value);\n\t\t\t\t});\n\t\t\t}\n\t\t} else {\n\t\t\tif (this._flags & P_AUTO_DIRTY && !(this._flags & P_SKIP_DIRTY)) {\n\t\t\t\tthis._flags = (this._flags & ~_STATUS_MASK) | _S_DIRTY;\n\t\t\t\tthis._dispatch(STATE, DIRTY);\n\t\t\t}\n\t\t\tthis._flags = (this._flags & ~_STATUS_MASK) | _S_SETTLED;\n\t\t\tthis._dispatch(DATA, this._value);\n\t\t}\n\t}\n\n\tsignal(s: Signal): void {\n\t\tif (this._flags & P_COMPLETED || !this._output) return;\n\t\tif (s === DIRTY) this._flags = (this._flags & ~_STATUS_MASK) | _S_DIRTY;\n\t\telse if (s === RESOLVED) this._flags = (this._flags & ~_STATUS_MASK) | _S_RESOLVED;\n\t\t// Unknown signals: dispatch without _status change (v4 forward-compat)\n\t\tthis._dispatch(STATE, s);\n\t}\n\n\tcomplete(): void {\n\t\tif (this._flags & P_COMPLETED) return;\n\t\tthis._flags = ((this._flags | P_COMPLETED) & ~_STATUS_MASK) | _S_COMPLETED;\n\t\tconst output = this._output;\n\t\tconst wasMulti = this._flags & P_MULTI;\n\t\tthis._output = null;\n\t\tthis._flags &= ~(P_MULTI | P_SKIP_DIRTY);\n\t\tthis._singleDepCount = 0;\n\t\tthis._stop();\n\t\tif (output) {\n\t\t\tif (wasMulti) {\n\t\t\t\tfor (const sink of output as Set<any>) sink(END);\n\t\t\t} else {\n\t\t\t\t(output as (type: number, data?: any) => void)(END);\n\t\t\t}\n\t\t}\n\t}\n\n\terror(e: unknown): void {\n\t\tif (this._flags & P_COMPLETED) return;\n\t\tthis._flags = ((this._flags | P_COMPLETED) & ~_STATUS_MASK) | _S_ERRORED;\n\t\tconst output = this._output;\n\t\tconst wasMulti = this._flags & P_MULTI;\n\t\tthis._output = null;\n\t\tthis._flags &= ~(P_MULTI | P_SKIP_DIRTY);\n\t\tthis._singleDepCount = 0;\n\t\tthis._stop();\n\t\tif (output) {\n\t\t\tif (wasMulti) {\n\t\t\t\tfor (const sink of output as Set<any>) sink(END, e);\n\t\t\t} else {\n\t\t\t\t(output as (type: number, data?: any) => void)(END, e);\n\t\t\t}\n\t\t}\n\t}\n\n\t_start(): void {\n\t\tif (this._flags & P_STARTED || !this._fn) return;\n\t\tthis._flags |= P_STARTED;\n\t\tconst result = this._fn({\n\t\t\temit: this.emit,\n\t\t\tsignal: (s: Signal) => this.signal(s),\n\t\t\tcomplete: () => this.complete(),\n\t\t\terror: (e: unknown) => this.error(e),\n\t\t} as any);\n\t\tthis._cleanup = typeof result === \"function\" ? result : undefined;\n\t}\n\n\t_stop(): void {\n\t\tif (!(this._flags & P_STARTED)) return;\n\t\tthis._flags &= ~P_STARTED;\n\t\tif (this._cleanup) this._cleanup();\n\t\tthis._cleanup = undefined;\n\t\tif (this._flags & P_RESET) this._value = this._initial;\n\t\tif (!(this._flags & P_COMPLETED)) this._flags = (this._flags & ~_STATUS_MASK) | _S_DISCONNECTED;\n\t}\n\n\tsource(type: number, payload?: any): void {\n\t\tif (type === START) {\n\t\t\tconst sink = payload;\n\t\t\tif (this._flags & P_COMPLETED) {\n\t\t\t\tif (this._flags & P_RESUB && this._output === null) {\n\t\t\t\t\tthis._flags = (this._flags & ~(P_COMPLETED | _STATUS_MASK)) | _S_DISCONNECTED;\n\t\t\t\t} else {\n\t\t\t\t\tsink(START, (_t: number) => {});\n\t\t\t\t\tsink(END);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (this._output === null) {\n\t\t\t\tthis._output = sink;\n\t\t\t} else if (!(this._flags & P_MULTI)) {\n\t\t\t\tconst set = new Set<any>();\n\t\t\t\tset.add(this._output);\n\t\t\t\tset.add(sink);\n\t\t\t\tthis._output = set;\n\t\t\t\tthis._flags = (this._flags | P_MULTI) & ~P_SKIP_DIRTY;\n\t\t\t} else {\n\t\t\t\t(this._output as Set<any>).add(sink);\n\t\t\t}\n\t\t\tlet isSingleDep = false;\n\t\t\tsink(START, (t: number, d?: any) => {\n\t\t\t\tif (t === DATA) sink(DATA, this._value);\n\t\t\t\tif (t === STATE && d === SINGLE_DEP && !isSingleDep) {\n\t\t\t\t\tisSingleDep = true;\n\t\t\t\t\tthis._singleDepCount++;\n\t\t\t\t\tif (!(this._flags & P_MULTI)) this._flags |= P_SKIP_DIRTY;\n\t\t\t\t}\n\t\t\t\tif (t === END) {\n\t\t\t\t\tif (isSingleDep) {\n\t\t\t\t\t\tisSingleDep = false;\n\t\t\t\t\t\tthis._singleDepCount--;\n\t\t\t\t\t}\n\t\t\t\t\tif (this._output === null) return;\n\t\t\t\t\tif (this._flags & P_MULTI) {\n\t\t\t\t\t\tconst set = this._output as Set<any>;\n\t\t\t\t\t\tset.delete(sink);\n\t\t\t\t\t\tif (set.size === 1) {\n\t\t\t\t\t\t\tthis._output = set.values().next().value;\n\t\t\t\t\t\t\tthis._flags &= ~P_MULTI;\n\t\t\t\t\t\t\t// Restore P_SKIP_DIRTY if remaining subscriber is single-dep\n\t\t\t\t\t\t\tif (this._singleDepCount > 0) this._flags |= P_SKIP_DIRTY;\n\t\t\t\t\t\t} else if (set.size === 0) {\n\t\t\t\t\t\t\tthis._output = null;\n\t\t\t\t\t\t\tthis._flags &= ~(P_MULTI | P_SKIP_DIRTY);\n\t\t\t\t\t\t\tthis._singleDepCount = 0;\n\t\t\t\t\t\t\tthis._flags = (this._flags & ~_STATUS_MASK) | _S_DISCONNECTED;\n\t\t\t\t\t\t\tthis._stop();\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (this._output === sink) {\n\t\t\t\t\t\tthis._output = null;\n\t\t\t\t\t\tthis._flags &= ~P_SKIP_DIRTY;\n\t\t\t\t\t\tthis._singleDepCount = 0;\n\t\t\t\t\t\tthis._flags = (this._flags & ~_STATUS_MASK) | _S_DISCONNECTED;\n\t\t\t\t\t\tthis._stop();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\tdeferStart(() => this._start());\n\t\t}\n\t}\n}\n\nexport function producer<T>(\n\tfn: ProducerFn<T> | undefined,\n\topts: ProducerOpts<T> & { initial: T },\n): ProducerStore<T> & Store<T>;\nexport function producer<T>(fn?: ProducerFn<T>, opts?: ProducerOpts<T>): ProducerStore<T>;\n/**\n * Creates a general-purpose reactive source with `emit`, `signal`, `complete`, and `error`.\n * The optional factory runs on first subscriber; its return value is cleanup on last disconnect.\n *\n * @param fn - Optional setup function receiving action callbacks; return teardown on disconnect.\n * @param opts - Optional configuration (initial value, equality, autoDirty, getter, etc.).\n *\n * @returns `ProducerStore<T>` — a store with:\n *\n * @returnsTable get() | () => T \\| undefined | Current value (or `getter` result when disconnected).\n * emit(value) | (value: T) => void | Pushes a new value to subscribers.\n * signal(s) | (s: Signal) => void | Sends DIRTY or RESOLVED on the STATE channel.\n * complete() | () => void | Ends the stream successfully.\n * error(e) | (e: unknown) => void | Ends the stream with an error.\n * source | callbag | Underlying callbag source for subscriptions.\n *\n * @optionsType ProducerOpts\n * @option initial | T | undefined | Value before first emit; reset target when `resetOnTeardown`.\n * @option equals | (a: T, b: T) => boolean | undefined | Skips emit when new value equals cached.\n * @option autoDirty | boolean | true | Send DIRTY on STATE before each DATA emission.\n * @option getter | (cached) => T | undefined | Pull-based recompute when disconnected.\n * @option resetOnTeardown | boolean | false | Reset to `initial` when last sink disconnects.\n * @option resubscribable | boolean | false | Allow new subscriptions after complete/error.\n * @option name | string | undefined | Debug name for Inspector.\n *\n * @remarks **Lazy start:** No work until the first `source()` subscription.\n * @remarks **Tier 2 boundary:** Used by async/timer operators; each `emit` starts a new DIRTY+value cycle when `autoDirty` is true.\n *\n * @example Manual emit (no factory)\n * ```ts\n * import { producer } from 'callbag-recharge';\n *\n * const bus = producer<string>();\n * bus.emit('a');\n * bus.get(); // 'a'\n * ```\n *\n * @example Factory with cleanup\n * ```ts\n * const ticks = producer<number>(({ emit, complete }) => {\n * let n = 0;\n * const id = setInterval(() => {\n * emit(n++);\n * if (n >= 3) complete();\n * }, 10);\n * return () => clearInterval(id);\n * });\n * ```\n *\n * @seeAlso [state](./state) — writable store, [operator](./operator) — transform primitive, [effect](./effect) — side-effects\n */\nexport function producer<T>(fn?: ProducerFn<T>, opts?: ProducerOpts<T>): ProducerStore<T> {\n\treturn new ProducerImpl<T>(fn, opts) as any;\n}\n","/**\n * A writable store, subclass of ProducerImpl.\n * Adds set()/update() API and defaults equals to Object.is.\n *\n * v5: _status packed into _flags bits 7-9 (inherited from ProducerImpl).\n * set() fast path uses pre-shifted status constants for zero-overhead writes.\n */\n\nimport { Inspector } from \"./inspector\";\nimport {\n\t_S_DIRTY,\n\t_S_SETTLED,\n\t_STATUS_MASK,\n\tP_AUTO_DIRTY,\n\tP_COMPLETED,\n\tP_PENDING,\n\tP_SKIP_DIRTY,\n\tProducerImpl,\n} from \"./producer\";\nimport { DATA, DIRTY, deferEmission, isBatching, STATE } from \"./protocol\";\nimport type { StoreOptions, WritableStore } from \"./types\";\n\nexport class StateImpl<T> extends ProducerImpl<T> {\n\tconstructor(initial: T, opts?: StoreOptions<T>) {\n\t\tsuper(undefined, {\n\t\t\tinitial,\n\t\t\tautoDirty: true,\n\t\t\tequals: opts?.equals ?? Object.is,\n\t\t\t_skipInspect: true,\n\t\t});\n\t\tthis.set = this.set.bind(this);\n\t\tInspector.register(this as any, { kind: \"state\", ...opts });\n\t}\n\n\toverride get(): T {\n\t\treturn this._value as T;\n\t}\n\n\t/**\n\t * Fast path: inlines ProducerImpl.emit() to skip the bound method call.\n\t * For no-subscriber writes, this is just an equals check + value assign.\n\t * Status writes use pre-shifted integer constants (bits 7-9 of _flags).\n\t */\n\tset(value: T): void {\n\t\tif (this._flags & P_COMPLETED) return;\n\t\tif (this._value !== undefined && this._eqFn!(this._value as T, value)) return;\n\t\tthis._value = value;\n\t\tif (!this._output) return;\n\t\tif (isBatching()) {\n\t\t\tif (!(this._flags & P_PENDING)) {\n\t\t\t\tthis._flags |= P_PENDING;\n\t\t\t\tif (this._flags & P_AUTO_DIRTY) {\n\t\t\t\t\tthis._flags = (this._flags & ~_STATUS_MASK) | _S_DIRTY;\n\t\t\t\t\tthis._dispatch(STATE, DIRTY);\n\t\t\t\t}\n\t\t\t\tdeferEmission(() => {\n\t\t\t\t\tthis._flags &= ~P_PENDING;\n\t\t\t\t\tthis._flags = (this._flags & ~_STATUS_MASK) | _S_SETTLED;\n\t\t\t\t\tthis._dispatch(DATA, this._value);\n\t\t\t\t});\n\t\t\t}\n\t\t} else {\n\t\t\tif (this._flags & P_AUTO_DIRTY && !(this._flags & P_SKIP_DIRTY)) {\n\t\t\t\tthis._flags = (this._flags & ~_STATUS_MASK) | _S_DIRTY;\n\t\t\t\tthis._dispatch(STATE, DIRTY);\n\t\t\t}\n\t\t\tthis._flags = (this._flags & ~_STATUS_MASK) | _S_SETTLED;\n\t\t\tthis._dispatch(DATA, this._value);\n\t\t}\n\t}\n\n\tupdate(fn: (current: T) => T): void {\n\t\tthis.set(fn(this._value as T));\n\t}\n}\n\n/**\n * Creates a writable reactive store with an initial value and optional equality check.\n *\n * @param initial - The initial value of the store.\n * @param opts - Optional configuration.\n *\n * @returns `WritableStore<T>` — a store with the following API:\n *\n * @returnsTable get() | () => T | Returns the current value.\n * set(value) | (value: T) => void | Sets a new value and notifies subscribers.\n * update(fn) | (fn: (current: T) => T) => void | Updates the value using a function of the current value.\n * source | callbag | The underlying callbag source for subscriptions.\n *\n * @optionsType StoreOptions\n * @option name | string | undefined | Debug name for Inspector.\n * @option equals | (a: T, b: T) => boolean | Object.is | Equality function to prevent redundant emissions.\n *\n * @remarks **Equality guard:** `equals` defaults to `Object.is`. If `set()` is called with a value equal to the current value, the emission is skipped entirely.\n * @remarks **Post-completion no-op:** `set()` is a no-op after `complete()` or `error()`. Both the value update and the emission are skipped. This differs from TC39 Signals, where `Signal.State` has no completion concept.\n * @remarks **Batching:** Within `batch()`, DIRTY signals propagate immediately but DATA emission is deferred until the outermost batch ends. Multiple `set()` calls in a batch coalesce to only the latest value.\n * @remarks **Pre-bound `set`:** The `set` method is bound at construction, so it is safe to destructure: `const { set } = myState`.\n *\n * @example\n * ```ts\n * import { state } from 'callbag-recharge';\n *\n * const count = state(0);\n *\n * count.get(); // 0\n * count.set(1);\n * count.get(); // 1\n * ```\n *\n * @example Update with a function\n * ```ts\n * const count = state(0);\n * count.update(n => n + 1);\n * count.get(); // 1\n * ```\n *\n * @example Custom equals for objects\n * ```ts\n * const pos = state(\n * { x: 0, y: 0 },\n * { equals: (a, b) => a.x === b.x && a.y === b.y }\n * );\n *\n * pos.set({ x: 0, y: 0 }); // no emission — values are equal\n * ```\n *\n * @example Batching multiple sets\n * ```ts\n * import { state, derived, batch } from 'callbag-recharge';\n *\n * const a = state(1);\n * const b = state(2);\n * const sum = derived([a, b], () => a.get() + b.get());\n *\n * batch(() => {\n * a.set(10);\n * b.set(20);\n * });\n * // sum recomputes only once, after the batch completes\n * sum.get(); // 30\n * ```\n *\n * @seeAlso [derived](./derived) — computed stores from dependencies, [effect](./effect) — side-effects on store changes, [producer](./producer) — general-purpose push source, [batch](./batch) — atomic multi-store updates\n */\nexport function state<T>(initial: T, opts?: StoreOptions<T>): WritableStore<T> {\n\treturn new StateImpl<T>(initial, opts) as any;\n}\n"],"mappings":"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","names":["http_exports","__export","fromHTTP","__toCommonJS","DIRTY","RESOLVED","SINGLE_DEP","S_DISCONNECTED","S_DIRTY","S_SETTLED","S_RESOLVED","S_COMPLETED","S_ERRORED","STATUS_SHIFT","STATUS_MASK","STATUS_STRINGS","decodeStatus","flags","START","DATA","END","STATE","batchDepth","deferredEmissions","isBatching","batchDepth","deferEmission","fn","deferredEmissions","connectDepth","pendingStarts","deferStart","start","connectDepth","pendingStarts","Inspector","_Inspector","value","deps","joined","d","node","opts","id","key","depSuffix","kind","parent","child","parentKey","childKey","children","result","livingKeys","ref","alive","c","store","cb","talkback","prev","START","type","data","END","next","p","g","edges","depsMap","lines","info","depsStr","childStr","label","log","name","DATA","STATE","DIRTY","RESOLVED","tapName","wrapper","edgeMap","nodes","direction","snap","statusStyle","usedIds","sanitizeId","base","count","nameToId","truncateValue","v","s","style","edge","fromId","toId","kindShape","shape","statusStr","P_STARTED","P_MULTI","P_COMPLETED","P_AUTO_DIRTY","P_RESET","P_RESUB","P_PENDING","P_SKIP_DIRTY","_STATUS_MASK","STATUS_MASK","_S_DIRTY","S_DIRTY","STATUS_SHIFT","_S_SETTLED","S_SETTLED","_S_DISCONNECTED","S_DISCONNECTED","_S_COMPLETED","S_COMPLETED","_S_ERRORED","S_ERRORED","_S_RESOLVED","S_RESOLVED","ProducerImpl","decodeStatus","fn","opts","flags","Inspector","type","data","output","sink","value","isBatching","STATE","DIRTY","deferEmission","DATA","s","RESOLVED","wasMulti","END","e","result","payload","START","_t","set","isSingleDep","t","d","SINGLE_DEP","deferStart","producer","StateImpl","ProducerImpl","initial","opts","Inspector","value","P_COMPLETED","isBatching","P_PENDING","P_AUTO_DIRTY","_STATUS_MASK","_S_DIRTY","STATE","DIRTY","deferEmission","_S_SETTLED","DATA","P_SKIP_DIRTY","fn","state","fromHTTP","url","opts","baseName","method","headers","bodyOpt","pollInterval","transform","r","requestTimeout","statusStore","state","fetchCountStore","_emit","_error","pollTimer","currentAbort","active","doFetch","signals","combinedAbort","sig","timeoutId","body","response","data","n","err","schedulePoll","_refetch","producer","emit","error","currentStatus"]}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { S as Store } from '../types-BwU0Zcuz.cjs';
|
|
2
|
+
import '../protocol-BVxRx57r.cjs';
|
|
3
|
+
|
|
4
|
+
type HTTPStatus = "idle" | "fetching" | "success" | "error";
|
|
5
|
+
interface FromHTTPOptions {
|
|
6
|
+
/** HTTP method. Default: "GET". */
|
|
7
|
+
method?: string;
|
|
8
|
+
/** Request headers. */
|
|
9
|
+
headers?: Record<string, string>;
|
|
10
|
+
/** Request body (for POST/PUT/PATCH). */
|
|
11
|
+
body?: string | object;
|
|
12
|
+
/** Poll interval in ms. Omit or set 0 for one-shot. */
|
|
13
|
+
poll?: number;
|
|
14
|
+
/** Transform the Response before emitting. Default: response.json(). */
|
|
15
|
+
transform?: (response: Response) => unknown | Promise<unknown>;
|
|
16
|
+
/** Debug name for Inspector. */
|
|
17
|
+
name?: string;
|
|
18
|
+
/** AbortSignal for external cancellation. */
|
|
19
|
+
signal?: AbortSignal;
|
|
20
|
+
/** Timeout per request in ms. Default: 30000. */
|
|
21
|
+
timeout?: number;
|
|
22
|
+
}
|
|
23
|
+
interface HTTPStore<T = unknown> {
|
|
24
|
+
/** Reactive store emitting fetched values. */
|
|
25
|
+
store: Store<T | undefined>;
|
|
26
|
+
/** Fetch status store. */
|
|
27
|
+
status: Store<HTTPStatus>;
|
|
28
|
+
/** Number of completed fetches. */
|
|
29
|
+
fetchCount: Store<number>;
|
|
30
|
+
/** Manually trigger a fetch (useful with polling disabled). */
|
|
31
|
+
refetch(): void;
|
|
32
|
+
/** Stop polling and cancel any in-flight request. */
|
|
33
|
+
stop(): void;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Creates a fetch-based HTTP source. Emits transformed response data as reactive values (Tier 2).
|
|
37
|
+
*
|
|
38
|
+
* @param url - The URL to fetch.
|
|
39
|
+
* @param opts - Optional configuration.
|
|
40
|
+
*
|
|
41
|
+
* @returns `HTTPStore<T>` — reactive store with status, fetch count, and manual refetch.
|
|
42
|
+
*
|
|
43
|
+
* @returnsTable store | Store\<T \| undefined\> | Reactive store emitting fetched values.
|
|
44
|
+
* status | Store\<HTTPStatus\> | Fetch status: "idle", "fetching", "success", "error".
|
|
45
|
+
* fetchCount | Store\<number\> | Number of completed fetches.
|
|
46
|
+
* refetch() | () => void | Manually trigger a fetch.
|
|
47
|
+
* stop() | () => void | Stop polling and cancel in-flight request.
|
|
48
|
+
*
|
|
49
|
+
* @remarks **Tier 2:** Cycle boundary — each fetch result starts a new DIRTY+value cycle.
|
|
50
|
+
* @remarks **Polling:** Set `poll` interval for periodic refetch. Omit for one-shot.
|
|
51
|
+
* @remarks **Transform:** Default extracts JSON. Override with `transform` for text, blob, etc.
|
|
52
|
+
* @remarks **Timeout:** Default 30s per request. Uses AbortController internally.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```ts
|
|
56
|
+
* import { fromHTTP } from 'callbag-recharge/adapters/http';
|
|
57
|
+
* import { subscribe } from 'callbag-recharge';
|
|
58
|
+
*
|
|
59
|
+
* const api = fromHTTP("https://api.example.com/status", { poll: 5000 });
|
|
60
|
+
* subscribe(api.store, data => console.log("status:", data));
|
|
61
|
+
* // Fetches immediately, then every 5s
|
|
62
|
+
* api.stop();
|
|
63
|
+
* ```
|
|
64
|
+
*
|
|
65
|
+
* @example One-shot POST
|
|
66
|
+
* ```ts
|
|
67
|
+
* const result = fromHTTP("https://api.example.com/submit", {
|
|
68
|
+
* method: "POST",
|
|
69
|
+
* headers: { "Content-Type": "application/json" },
|
|
70
|
+
* body: { name: "test" },
|
|
71
|
+
* });
|
|
72
|
+
* subscribe(result.store, v => console.log(v));
|
|
73
|
+
* ```
|
|
74
|
+
*
|
|
75
|
+
* @seeAlso [fromWebhook](./webhook) — HTTP trigger (server-side), [fromWebSocket](./websocket) — WebSocket source
|
|
76
|
+
*
|
|
77
|
+
* @category adapters
|
|
78
|
+
*/
|
|
79
|
+
declare function fromHTTP<T = unknown>(url: string, opts?: FromHTTPOptions): HTTPStore<T>;
|
|
80
|
+
|
|
81
|
+
export { type FromHTTPOptions, type HTTPStatus, type HTTPStore, fromHTTP };
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { S as Store } from '../types-DGII6w5S.js';
|
|
2
|
+
import '../protocol-BVxRx57r.js';
|
|
3
|
+
|
|
4
|
+
type HTTPStatus = "idle" | "fetching" | "success" | "error";
|
|
5
|
+
interface FromHTTPOptions {
|
|
6
|
+
/** HTTP method. Default: "GET". */
|
|
7
|
+
method?: string;
|
|
8
|
+
/** Request headers. */
|
|
9
|
+
headers?: Record<string, string>;
|
|
10
|
+
/** Request body (for POST/PUT/PATCH). */
|
|
11
|
+
body?: string | object;
|
|
12
|
+
/** Poll interval in ms. Omit or set 0 for one-shot. */
|
|
13
|
+
poll?: number;
|
|
14
|
+
/** Transform the Response before emitting. Default: response.json(). */
|
|
15
|
+
transform?: (response: Response) => unknown | Promise<unknown>;
|
|
16
|
+
/** Debug name for Inspector. */
|
|
17
|
+
name?: string;
|
|
18
|
+
/** AbortSignal for external cancellation. */
|
|
19
|
+
signal?: AbortSignal;
|
|
20
|
+
/** Timeout per request in ms. Default: 30000. */
|
|
21
|
+
timeout?: number;
|
|
22
|
+
}
|
|
23
|
+
interface HTTPStore<T = unknown> {
|
|
24
|
+
/** Reactive store emitting fetched values. */
|
|
25
|
+
store: Store<T | undefined>;
|
|
26
|
+
/** Fetch status store. */
|
|
27
|
+
status: Store<HTTPStatus>;
|
|
28
|
+
/** Number of completed fetches. */
|
|
29
|
+
fetchCount: Store<number>;
|
|
30
|
+
/** Manually trigger a fetch (useful with polling disabled). */
|
|
31
|
+
refetch(): void;
|
|
32
|
+
/** Stop polling and cancel any in-flight request. */
|
|
33
|
+
stop(): void;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Creates a fetch-based HTTP source. Emits transformed response data as reactive values (Tier 2).
|
|
37
|
+
*
|
|
38
|
+
* @param url - The URL to fetch.
|
|
39
|
+
* @param opts - Optional configuration.
|
|
40
|
+
*
|
|
41
|
+
* @returns `HTTPStore<T>` — reactive store with status, fetch count, and manual refetch.
|
|
42
|
+
*
|
|
43
|
+
* @returnsTable store | Store\<T \| undefined\> | Reactive store emitting fetched values.
|
|
44
|
+
* status | Store\<HTTPStatus\> | Fetch status: "idle", "fetching", "success", "error".
|
|
45
|
+
* fetchCount | Store\<number\> | Number of completed fetches.
|
|
46
|
+
* refetch() | () => void | Manually trigger a fetch.
|
|
47
|
+
* stop() | () => void | Stop polling and cancel in-flight request.
|
|
48
|
+
*
|
|
49
|
+
* @remarks **Tier 2:** Cycle boundary — each fetch result starts a new DIRTY+value cycle.
|
|
50
|
+
* @remarks **Polling:** Set `poll` interval for periodic refetch. Omit for one-shot.
|
|
51
|
+
* @remarks **Transform:** Default extracts JSON. Override with `transform` for text, blob, etc.
|
|
52
|
+
* @remarks **Timeout:** Default 30s per request. Uses AbortController internally.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```ts
|
|
56
|
+
* import { fromHTTP } from 'callbag-recharge/adapters/http';
|
|
57
|
+
* import { subscribe } from 'callbag-recharge';
|
|
58
|
+
*
|
|
59
|
+
* const api = fromHTTP("https://api.example.com/status", { poll: 5000 });
|
|
60
|
+
* subscribe(api.store, data => console.log("status:", data));
|
|
61
|
+
* // Fetches immediately, then every 5s
|
|
62
|
+
* api.stop();
|
|
63
|
+
* ```
|
|
64
|
+
*
|
|
65
|
+
* @example One-shot POST
|
|
66
|
+
* ```ts
|
|
67
|
+
* const result = fromHTTP("https://api.example.com/submit", {
|
|
68
|
+
* method: "POST",
|
|
69
|
+
* headers: { "Content-Type": "application/json" },
|
|
70
|
+
* body: { name: "test" },
|
|
71
|
+
* });
|
|
72
|
+
* subscribe(result.store, v => console.log(v));
|
|
73
|
+
* ```
|
|
74
|
+
*
|
|
75
|
+
* @seeAlso [fromWebhook](./webhook) — HTTP trigger (server-side), [fromWebSocket](./websocket) — WebSocket source
|
|
76
|
+
*
|
|
77
|
+
* @category adapters
|
|
78
|
+
*/
|
|
79
|
+
declare function fromHTTP<T = unknown>(url: string, opts?: FromHTTPOptions): HTTPStore<T>;
|
|
80
|
+
|
|
81
|
+
export { type FromHTTPOptions, type HTTPStatus, type HTTPStore, fromHTTP };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|