@vielzeug/flux 1.0.7 → 2.0.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.
Files changed (160) hide show
  1. package/README.md +22 -25
  2. package/dist/_dev.cjs +1 -1
  3. package/dist/_dev.cjs.map +1 -1
  4. package/dist/_dev.js +2 -8
  5. package/dist/_dev.js.map +1 -1
  6. package/dist/_iterator.cjs +1 -1
  7. package/dist/_iterator.cjs.map +1 -1
  8. package/dist/_iterator.d.ts +3 -1
  9. package/dist/_iterator.d.ts.map +1 -1
  10. package/dist/_iterator.js +57 -35
  11. package/dist/_iterator.js.map +1 -1
  12. package/dist/_link.cjs +2 -0
  13. package/dist/_link.cjs.map +1 -0
  14. package/dist/_link.d.ts +4 -0
  15. package/dist/_link.d.ts.map +1 -0
  16. package/dist/_link.js +8 -0
  17. package/dist/_link.js.map +1 -0
  18. package/dist/_numeric.cjs +1 -1
  19. package/dist/_numeric.cjs.map +1 -1
  20. package/dist/_numeric.d.ts +2 -1
  21. package/dist/_numeric.d.ts.map +1 -1
  22. package/dist/_numeric.js +3 -7
  23. package/dist/_numeric.js.map +1 -1
  24. package/dist/_pipe.cjs +1 -1
  25. package/dist/_pipe.cjs.map +1 -1
  26. package/dist/_pipe.d.ts +2 -1
  27. package/dist/_pipe.d.ts.map +1 -1
  28. package/dist/_pipe.js +3 -3
  29. package/dist/_pipe.js.map +1 -1
  30. package/dist/_safe.cjs +1 -1
  31. package/dist/_safe.cjs.map +1 -1
  32. package/dist/_safe.d.ts +1 -1
  33. package/dist/_safe.d.ts.map +1 -1
  34. package/dist/_safe.js +2 -2
  35. package/dist/_safe.js.map +1 -1
  36. package/dist/_scheduler.cjs +1 -1
  37. package/dist/_scheduler.cjs.map +1 -1
  38. package/dist/_scheduler.d.ts +5 -2
  39. package/dist/_scheduler.d.ts.map +1 -1
  40. package/dist/_scheduler.js +1 -1
  41. package/dist/_scheduler.js.map +1 -1
  42. package/dist/_subscription.cjs +2 -0
  43. package/dist/_subscription.cjs.map +1 -0
  44. package/dist/_subscription.d.ts +8 -0
  45. package/dist/_subscription.d.ts.map +1 -0
  46. package/dist/_subscription.js +80 -0
  47. package/dist/_subscription.js.map +1 -0
  48. package/dist/adapters/courier.cjs +1 -1
  49. package/dist/adapters/courier.cjs.map +1 -1
  50. package/dist/adapters/courier.d.ts +35 -21
  51. package/dist/adapters/courier.d.ts.map +1 -1
  52. package/dist/adapters/courier.js +25 -6
  53. package/dist/adapters/courier.js.map +1 -1
  54. package/dist/adapters/herald.cjs +1 -1
  55. package/dist/adapters/herald.cjs.map +1 -1
  56. package/dist/adapters/herald.d.ts +2 -16
  57. package/dist/adapters/herald.d.ts.map +1 -1
  58. package/dist/adapters/herald.js +12 -8
  59. package/dist/adapters/herald.js.map +1 -1
  60. package/dist/adapters/pulse.cjs +1 -1
  61. package/dist/adapters/pulse.cjs.map +1 -1
  62. package/dist/adapters/pulse.d.ts +3 -20
  63. package/dist/adapters/pulse.d.ts.map +1 -1
  64. package/dist/adapters/pulse.js +2 -6
  65. package/dist/adapters/pulse.js.map +1 -1
  66. package/dist/adapters/ripple.cjs +1 -1
  67. package/dist/adapters/ripple.cjs.map +1 -1
  68. package/dist/adapters/ripple.d.ts +3 -39
  69. package/dist/adapters/ripple.d.ts.map +1 -1
  70. package/dist/adapters/ripple.js +22 -29
  71. package/dist/adapters/ripple.js.map +1 -1
  72. package/dist/async.cjs +2 -0
  73. package/dist/async.cjs.map +1 -0
  74. package/dist/async.d.ts +4 -0
  75. package/dist/async.d.ts.map +1 -0
  76. package/dist/async.js +11 -0
  77. package/dist/async.js.map +1 -0
  78. package/dist/core.cjs +1 -1
  79. package/dist/core.cjs.map +1 -1
  80. package/dist/core.d.ts +3 -16
  81. package/dist/core.d.ts.map +1 -1
  82. package/dist/core.js +12 -81
  83. package/dist/core.js.map +1 -1
  84. package/dist/courier.cjs +1 -0
  85. package/dist/courier.d.ts +2 -0
  86. package/dist/courier.d.ts.map +1 -0
  87. package/dist/courier.js +2 -0
  88. package/dist/errors.cjs.map +1 -1
  89. package/dist/errors.js.map +1 -1
  90. package/dist/flux.cjs +1 -1
  91. package/dist/flux.cjs.map +1 -1
  92. package/dist/flux.iife.js +1 -1
  93. package/dist/flux.iife.js.map +1 -1
  94. package/dist/flux.js +1 -1
  95. package/dist/flux.js.map +1 -1
  96. package/dist/herald.cjs +1 -0
  97. package/dist/herald.d.ts +2 -0
  98. package/dist/herald.d.ts.map +1 -0
  99. package/dist/herald.js +2 -0
  100. package/dist/index.cjs +1 -1
  101. package/dist/index.d.ts +13 -15
  102. package/dist/index.d.ts.map +1 -1
  103. package/dist/index.js +10 -14
  104. package/dist/operators/combination.cjs +1 -1
  105. package/dist/operators/combination.cjs.map +1 -1
  106. package/dist/operators/combination.d.ts +9 -64
  107. package/dist/operators/combination.d.ts.map +1 -1
  108. package/dist/operators/combination.js +46 -160
  109. package/dist/operators/combination.js.map +1 -1
  110. package/dist/operators/creation.cjs +1 -1
  111. package/dist/operators/creation.cjs.map +1 -1
  112. package/dist/operators/creation.d.ts +13 -46
  113. package/dist/operators/creation.d.ts.map +1 -1
  114. package/dist/operators/creation.js +61 -65
  115. package/dist/operators/creation.js.map +1 -1
  116. package/dist/operators/filtering.cjs +1 -1
  117. package/dist/operators/filtering.cjs.map +1 -1
  118. package/dist/operators/filtering.d.ts +10 -60
  119. package/dist/operators/filtering.d.ts.map +1 -1
  120. package/dist/operators/filtering.js +62 -109
  121. package/dist/operators/filtering.js.map +1 -1
  122. package/dist/operators/transformation.cjs +1 -1
  123. package/dist/operators/transformation.cjs.map +1 -1
  124. package/dist/operators/transformation.d.ts +9 -62
  125. package/dist/operators/transformation.d.ts.map +1 -1
  126. package/dist/operators/transformation.js +91 -142
  127. package/dist/operators/transformation.js.map +1 -1
  128. package/dist/operators/utility.cjs +1 -1
  129. package/dist/operators/utility.cjs.map +1 -1
  130. package/dist/operators/utility.d.ts +16 -97
  131. package/dist/operators/utility.d.ts.map +1 -1
  132. package/dist/operators/utility.js +75 -191
  133. package/dist/operators/utility.js.map +1 -1
  134. package/dist/pipe.cjs +2 -0
  135. package/dist/pipe.cjs.map +1 -0
  136. package/dist/pipe.d.ts +15 -0
  137. package/dist/pipe.d.ts.map +1 -0
  138. package/dist/pipe.js +9 -0
  139. package/dist/pipe.js.map +1 -0
  140. package/dist/pulse.cjs +1 -0
  141. package/dist/pulse.d.ts +2 -0
  142. package/dist/pulse.d.ts.map +1 -0
  143. package/dist/pulse.js +2 -0
  144. package/dist/ripple.cjs +1 -0
  145. package/dist/ripple.d.ts +3 -0
  146. package/dist/ripple.d.ts.map +1 -0
  147. package/dist/ripple.js +2 -0
  148. package/dist/subject.cjs +1 -1
  149. package/dist/subject.cjs.map +1 -1
  150. package/dist/subject.d.ts +14 -65
  151. package/dist/subject.d.ts.map +1 -1
  152. package/dist/subject.js +31 -166
  153. package/dist/subject.js.map +1 -1
  154. package/dist/subjects.cjs +1 -0
  155. package/dist/subjects.d.ts +3 -0
  156. package/dist/subjects.d.ts.map +1 -0
  157. package/dist/subjects.js +2 -0
  158. package/dist/types.d.ts +32 -79
  159. package/dist/types.d.ts.map +1 -1
  160. package/package.json +54 -15
@@ -0,0 +1,80 @@
1
+ //#region src/_subscription.ts
2
+ function e(e) {
3
+ let t = globalThis.reportError;
4
+ if (t) {
5
+ t(e);
6
+ return;
7
+ }
8
+ queueMicrotask(() => {
9
+ throw e;
10
+ });
11
+ }
12
+ function t(t, n) {
13
+ let r = typeof t == "function" ? { next: t } : t, i = new AbortController(), a = !1, o, s = () => {
14
+ if (!a) {
15
+ a = !0, i.abort(), n?.removeEventListener("abort", s);
16
+ try {
17
+ o?.();
18
+ } catch (t) {
19
+ e(t);
20
+ }
21
+ }
22
+ };
23
+ return n?.aborted ? s() : n?.addEventListener("abort", s, { once: !0 }), {
24
+ add: (t) => {
25
+ if (t) {
26
+ if (a) {
27
+ try {
28
+ t();
29
+ } catch (t) {
30
+ e(t);
31
+ }
32
+ return;
33
+ }
34
+ o = t;
35
+ }
36
+ },
37
+ signal: i.signal,
38
+ sink: {
39
+ complete() {
40
+ if (!a) {
41
+ try {
42
+ r.complete?.();
43
+ } catch (t) {
44
+ e(t);
45
+ }
46
+ s();
47
+ }
48
+ },
49
+ error(t) {
50
+ if (!a) {
51
+ if (r.error) try {
52
+ r.error(t);
53
+ } catch (t) {
54
+ e(t);
55
+ }
56
+ else e(t);
57
+ s();
58
+ }
59
+ },
60
+ next(t) {
61
+ if (!a) try {
62
+ r.next(t);
63
+ } catch (t) {
64
+ s(), e(t);
65
+ }
66
+ }
67
+ },
68
+ subscription: {
69
+ get closed() {
70
+ return a;
71
+ },
72
+ [Symbol.dispose]: s,
73
+ unsubscribe: s
74
+ }
75
+ };
76
+ }
77
+ //#endregion
78
+ export { t as createSubscription };
79
+
80
+ //# sourceMappingURL=_subscription.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_subscription.js","names":[],"sources":["../src/_subscription.ts"],"sourcesContent":["import type { Observer, Sink, Subscription, Teardown } from './types';\n\nfunction reportUnhandledError(reason: unknown): void {\n const reportError = (globalThis as { reportError?: (value: unknown) => void }).reportError;\n\n if (reportError) {\n reportError(reason);\n\n return;\n }\n\n queueMicrotask(() => {\n throw reason;\n });\n}\n\nexport function createSubscription<T>(\n observerOrNext: Observer<T> | ((value: T) => void),\n signal?: AbortSignal,\n): { add(teardown: Teardown | void): void; signal: AbortSignal; sink: Sink<T>; subscription: Subscription } {\n const observer: Observer<T> = typeof observerOrNext === 'function' ? { next: observerOrNext } : observerOrNext;\n const controller = new AbortController();\n let closed = false;\n let teardown: Teardown | undefined;\n\n const unsubscribe = (): void => {\n if (closed) return;\n\n closed = true;\n controller.abort();\n signal?.removeEventListener('abort', unsubscribe);\n\n try {\n teardown?.();\n } catch (reason) {\n reportUnhandledError(reason);\n }\n };\n\n const sink: Sink<T> = {\n complete(): void {\n if (closed) return;\n\n try {\n observer.complete?.();\n } catch (reason) {\n reportUnhandledError(reason);\n }\n\n unsubscribe();\n },\n\n error(reason: unknown): void {\n if (closed) return;\n\n if (observer.error) {\n try {\n observer.error(reason);\n } catch (callbackError) {\n reportUnhandledError(callbackError);\n }\n } else {\n reportUnhandledError(reason);\n }\n\n unsubscribe();\n },\n\n next(value: T): void {\n if (closed) return;\n\n try {\n observer.next(value);\n } catch (reason) {\n unsubscribe();\n reportUnhandledError(reason);\n }\n },\n };\n\n const add = (nextTeardown: Teardown | void): void => {\n if (!nextTeardown) return;\n\n if (closed) {\n try {\n nextTeardown();\n } catch (reason) {\n reportUnhandledError(reason);\n }\n\n return;\n }\n\n teardown = nextTeardown;\n };\n\n if (signal?.aborted) {\n unsubscribe();\n } else {\n signal?.addEventListener('abort', unsubscribe, { once: true });\n }\n\n return {\n add,\n signal: controller.signal,\n sink,\n subscription: {\n get closed(): boolean {\n return closed;\n },\n [Symbol.dispose]: unsubscribe,\n unsubscribe,\n },\n };\n}\n"],"mappings":";AAEA,SAAS,EAAqB,GAAuB;CACnD,IAAM,IAAe,WAA0D;CAE/E,IAAI,GAAa;EACf,EAAY,CAAM;EAElB;CACF;CAEA,qBAAqB;EACnB,MAAM;CACR,CAAC;AACH;AAEA,SAAgB,EACd,GACA,GAC0G;CAC1G,IAAM,IAAwB,OAAO,KAAmB,aAAa,EAAE,MAAM,EAAe,IAAI,GAC1F,IAAa,IAAI,gBAAgB,GACnC,IAAS,IACT,GAEE,UAA0B;EAC1B,QAIJ;GAFA,IAAS,IACT,EAAW,MAAM,GACjB,GAAQ,oBAAoB,SAAS,CAAW;GAEhD,IAAI;IACF,IAAW;GACb,SAAS,GAAQ;IACf,EAAqB,CAAM;GAC7B;EANgD;CAOlD;CAiEA,OANI,GAAQ,UACV,EAAY,IAEZ,GAAQ,iBAAiB,SAAS,GAAa,EAAE,MAAM,GAAK,CAAC,GAGxD;EACL,MAvBW,MAAwC;GAC9C,OAEL;QAAI,GAAQ;KACV,IAAI;MACF,EAAa;KACf,SAAS,GAAQ;MACf,EAAqB,CAAM;KAC7B;KAEA;IACF;IAEA,IAAW;GAFX;EAGF;EAUE,QAAQ,EAAW;EACnB;GAjEA,WAAiB;IACX,QAEJ;SAAI;MACF,EAAS,WAAW;KACtB,SAAS,GAAQ;MACf,EAAqB,CAAM;KAC7B;KAEA,EAAY;IAFZ;GAGF;GAEA,MAAM,GAAuB;IACvB,QAEJ;SAAI,EAAS,OACX,IAAI;MACF,EAAS,MAAM,CAAM;KACvB,SAAS,GAAe;MACtB,EAAqB,CAAa;KACpC;UAEA,EAAqB,CAAM;KAG7B,EAAY;IAHiB;GAI/B;GAEA,KAAK,GAAgB;IACf,QAEJ,IAAI;KACF,EAAS,KAAK,CAAK;IACrB,SAAS,GAAQ;KAEf,AADA,EAAY,GACZ,EAAqB,CAAM;IAC7B;GACF;EA4BA;EACA,cAAc;GACZ,IAAI,SAAkB;IACpB,OAAO;GACT;IACC,OAAO,UAAU;GAClB;EACF;CACF;AACF"}
@@ -1,2 +1,2 @@
1
- const e=require("../core.cjs");function t(t,n){return e.flux(e=>t.on(n,t=>e.next(t)))}function n(t){return e.flux(e=>(e.next(t.peek()),t.subscribe(()=>{e.next(t.peek())})))}exports.fromQuery=n,exports.fromSse=t;
1
+ const e=require("../core.cjs");function t(t,n){return e.stream((e,r)=>{let i=t[Symbol.asyncIterator]();return(async()=>{try{for(;!r.aborted;){let t=await i.next();if(t.done){e.complete();return}t.value.event===n&&e.next(t.value.data)}}catch(t){r.aborted||e.error(t)}})(),()=>{i.return?.()}})}function n(t,n){return e.stream(e=>{let r=()=>t.getSnapshot(n.key);return e.next(r()),t.subscribe(n.key,()=>e.next(r()))})}exports.fromQuery=n,exports.fromSse=t;
2
2
  //# sourceMappingURL=courier.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"courier.cjs","names":[],"sources":["../../src/adapters/courier.ts"],"sourcesContent":["import type { SseSource } from '@vielzeug/courier';\n\nimport type { Flux } from '../types';\n\nimport { flux } from '../core';\n\n/**\n * Minimal shape of a courier `SyncStore` needed to subscribe to query state changes.\n * Avoids a hard import of `@vielzeug/courier` types that are not in the peer dep.\n *\n * @internal\n */\ntype SyncStore<T> = {\n peek(): T;\n subscribe(onStoreChange: () => void): () => void;\n};\n\n/**\n * Create a `Flux` from an SSE source returned by `streamClient.sse()`.\n * Emits typed SSE events under `event`. The current SSE status is NOT emitted —\n * only data messages are forwarded.\n *\n * @example\n * const events$ = fromSse(stream.sse('/events'), 'message');\n * events$.subscribe((data) => console.log(data));\n */\nexport function fromSse<TEvents extends Record<string, unknown>, K extends keyof TEvents & string>(\n source: SseSource<TEvents>,\n event: K,\n): Flux<TEvents[K]> {\n return flux<TEvents[K]>((observer) => {\n const unsub = source.on(event, (data) => observer.next(data));\n\n return unsub;\n });\n}\n\n/**\n * Create a `Flux` from a courier `SyncStore` (returned by `qc.observe()`).\n * Emits the current state immediately, then on every state change.\n *\n * @example\n * const data$ = fromQuery(qc.observe({ key: ['users'], fn: fetchUsers }));\n * data$.subscribe((state) => console.log(state.status, state.data));\n */\nexport function fromQuery<T>(store: SyncStore<T>): Flux<T> {\n return flux<T>((observer) => {\n observer.next(store.peek());\n\n const unsub = store.subscribe(() => {\n observer.next(store.peek());\n });\n\n return unsub;\n });\n}\n"],"mappings":"+BA0BA,SAAgB,EACd,EACA,EACkB,CAClB,OAAO,EAAA,KAAkB,GACT,EAAO,GAAG,EAAQ,GAAS,EAAS,KAAK,CAAI,CAEpD,CACR,CACH,CAUA,SAAgB,EAAa,EAA8B,CACzD,OAAO,EAAA,KAAS,IACd,EAAS,KAAK,EAAM,KAAK,CAAC,EAEZ,EAAM,cAAgB,CAClC,EAAS,KAAK,EAAM,KAAK,CAAC,CAC5B,CAEO,EACR,CACH"}
1
+ {"version":3,"file":"courier.cjs","names":[],"sources":["../../src/adapters/courier.ts"],"sourcesContent":["import type { Stream } from '../types';\n\nimport { stream } from '../core';\n\ntype QueryCache = {\n getSnapshot<T>(key: readonly unknown[]): T | null;\n subscribe(key: readonly unknown[], onStoreChange: () => void): () => void;\n};\n\ntype QueryDefinition = {\n fetch: (...args: never[]) => Promise<unknown>;\n key: readonly unknown[];\n};\n\ntype QuerySnapshot<T> =\n | {\n readonly data: undefined;\n readonly error: null;\n readonly isFetching: boolean;\n readonly status: 'loading';\n readonly updatedAt: undefined;\n }\n | {\n readonly data: T;\n readonly error: null;\n readonly isFetching: boolean;\n readonly status: 'success';\n readonly updatedAt: number;\n }\n | {\n readonly data: T | undefined;\n readonly error: Error;\n readonly isFetching: false;\n readonly status: 'error';\n readonly updatedAt: number;\n };\n\ntype StreamEvent<T> = { readonly data: T; readonly event: string };\n\nexport function fromSse<T>(source: AsyncIterable<StreamEvent<T>>, event: string): Stream<T> {\n return stream((sink, signal) => {\n const iterator = source[Symbol.asyncIterator]();\n\n void (async () => {\n try {\n while (!signal.aborted) {\n const result = await iterator.next();\n\n if (result.done) {\n sink.complete();\n\n return;\n }\n\n if (result.value.event === event) sink.next(result.value.data);\n }\n } catch (reason) {\n if (!signal.aborted) sink.error(reason);\n }\n })();\n\n return () => {\n void iterator.return?.();\n };\n });\n}\n\nexport function fromQuery<T extends QueryDefinition>(\n cache: QueryCache,\n definition: T,\n): Stream<QuerySnapshot<Awaited<ReturnType<T['fetch']>>> | null> {\n return stream((sink) => {\n const snapshot = () => cache.getSnapshot<QuerySnapshot<Awaited<ReturnType<T['fetch']>>>>(definition.key);\n\n sink.next(snapshot());\n\n return cache.subscribe(definition.key, () => sink.next(snapshot()));\n });\n}\n"],"mappings":"+BAuCA,SAAgB,EAAW,EAAuC,EAA0B,CAC1F,OAAO,EAAA,QAAQ,EAAM,IAAW,CAC9B,IAAM,EAAW,EAAO,OAAO,cAAc,CAAC,EAoB9C,OAlBM,SAAY,CAChB,GAAI,CACF,KAAO,CAAC,EAAO,SAAS,CACtB,IAAM,EAAS,MAAM,EAAS,KAAK,EAEnC,GAAI,EAAO,KAAM,CACf,EAAK,SAAS,EAEd,MACF,CAEI,EAAO,MAAM,QAAU,GAAO,EAAK,KAAK,EAAO,MAAM,IAAI,CAC/D,CACF,OAAS,EAAQ,CACV,EAAO,SAAS,EAAK,MAAM,CAAM,CACxC,CACF,EAAA,CAAG,MAEU,CACX,EAAc,SAAS,CACzB,CACF,CAAC,CACH,CAEA,SAAgB,EACd,EACA,EAC+D,CAC/D,OAAO,EAAA,OAAQ,GAAS,CACtB,IAAM,MAAiB,EAAM,YAA4D,EAAW,GAAG,EAIvG,OAFA,EAAK,KAAK,EAAS,CAAC,EAEb,EAAM,UAAU,EAAW,QAAW,EAAK,KAAK,EAAS,CAAC,CAAC,CACpE,CAAC,CACH"}
@@ -1,22 +1,36 @@
1
- import type { SseSource } from '@vielzeug/courier';
2
- import type { Flux } from '../types';
3
- /**
4
- * Create a `Flux` from an SSE source returned by `streamClient.sse()`.
5
- * Emits typed SSE events under `event`. The current SSE status is NOT emitted —
6
- * only data messages are forwarded.
7
- *
8
- * @example
9
- * const events$ = fromSse(stream.sse('/events'), 'message');
10
- * events$.subscribe((data) => console.log(data));
11
- */
12
- export declare function fromSse<TEvents extends Record<string, unknown>, K extends keyof TEvents & string>(source: SseSource<TEvents>, event: K): Flux<TEvents[K]>;
13
- /**
14
- * Create a `Flux` from a courier `SyncStore` (returned by `qc.observe()`).
15
- * Emits the current state immediately, then on every state change.
16
- *
17
- * @example
18
- * const data$ = fromQuery(qc.observe({ key: ['users'], fn: fetchUsers }));
19
- * data$.subscribe((state) => console.log(state.status, state.data));
20
- */
21
- export declare function fromQuery<T>(store: SyncStore<T>): Flux<T>;
1
+ import type { Stream } from '../types';
2
+ type QueryCache = {
3
+ getSnapshot<T>(key: readonly unknown[]): T | null;
4
+ subscribe(key: readonly unknown[], onStoreChange: () => void): () => void;
5
+ };
6
+ type QueryDefinition = {
7
+ fetch: (...args: never[]) => Promise<unknown>;
8
+ key: readonly unknown[];
9
+ };
10
+ type QuerySnapshot<T> = {
11
+ readonly data: undefined;
12
+ readonly error: null;
13
+ readonly isFetching: boolean;
14
+ readonly status: 'loading';
15
+ readonly updatedAt: undefined;
16
+ } | {
17
+ readonly data: T;
18
+ readonly error: null;
19
+ readonly isFetching: boolean;
20
+ readonly status: 'success';
21
+ readonly updatedAt: number;
22
+ } | {
23
+ readonly data: T | undefined;
24
+ readonly error: Error;
25
+ readonly isFetching: false;
26
+ readonly status: 'error';
27
+ readonly updatedAt: number;
28
+ };
29
+ type StreamEvent<T> = {
30
+ readonly data: T;
31
+ readonly event: string;
32
+ };
33
+ export declare function fromSse<T>(source: AsyncIterable<StreamEvent<T>>, event: string): Stream<T>;
34
+ export declare function fromQuery<T extends QueryDefinition>(cache: QueryCache, definition: T): Stream<QuerySnapshot<Awaited<ReturnType<T['fetch']>>> | null>;
35
+ export {};
22
36
  //# sourceMappingURL=courier.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"courier.d.ts","sourceRoot":"","sources":["../../src/adapters/courier.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEnD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAerC;;;;;;;;GAQG;AACH,wBAAgB,OAAO,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,SAAS,MAAM,OAAO,GAAG,MAAM,EAC/F,MAAM,EAAE,SAAS,CAAC,OAAO,CAAC,EAC1B,KAAK,EAAE,CAAC,GACP,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAMlB;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAUzD"}
1
+ {"version":3,"file":"courier.d.ts","sourceRoot":"","sources":["../../src/adapters/courier.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAIvC,KAAK,UAAU,GAAG;IAChB,WAAW,CAAC,CAAC,EAAE,GAAG,EAAE,SAAS,OAAO,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC;IAClD,SAAS,CAAC,GAAG,EAAE,SAAS,OAAO,EAAE,EAAE,aAAa,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC;CAC3E,CAAC;AAEF,KAAK,eAAe,GAAG;IACrB,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9C,GAAG,EAAE,SAAS,OAAO,EAAE,CAAC;CACzB,CAAC;AAEF,KAAK,aAAa,CAAC,CAAC,IAChB;IACE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;IACrB,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;CAC/B,GACD;IACE,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IACjB,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;IACrB,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B,GACD;IACE,QAAQ,CAAC,IAAI,EAAE,CAAC,GAAG,SAAS,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,KAAK,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEN,KAAK,WAAW,CAAC,CAAC,IAAI;IAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnE,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,aAAa,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,CA0B1F;AAED,wBAAgB,SAAS,CAAC,CAAC,SAAS,eAAe,EACjD,KAAK,EAAE,UAAU,EACjB,UAAU,EAAE,CAAC,GACZ,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAQ/D"}
@@ -1,12 +1,31 @@
1
- import { flux as e } from "../core.js";
1
+ import { stream as e } from "../core.js";
2
2
  //#region src/adapters/courier.ts
3
3
  function t(t, n) {
4
- return e((e) => t.on(n, (t) => e.next(t)));
4
+ return e((e, r) => {
5
+ let i = t[Symbol.asyncIterator]();
6
+ return (async () => {
7
+ try {
8
+ for (; !r.aborted;) {
9
+ let t = await i.next();
10
+ if (t.done) {
11
+ e.complete();
12
+ return;
13
+ }
14
+ t.value.event === n && e.next(t.value.data);
15
+ }
16
+ } catch (t) {
17
+ r.aborted || e.error(t);
18
+ }
19
+ })(), () => {
20
+ i.return?.();
21
+ };
22
+ });
5
23
  }
6
- function n(t) {
7
- return e((e) => (e.next(t.peek()), t.subscribe(() => {
8
- e.next(t.peek());
9
- })));
24
+ function n(t, n) {
25
+ return e((e) => {
26
+ let r = () => t.getSnapshot(n.key);
27
+ return e.next(r()), t.subscribe(n.key, () => e.next(r()));
28
+ });
10
29
  }
11
30
  //#endregion
12
31
  export { n as fromQuery, t as fromSse };
@@ -1 +1 @@
1
- {"version":3,"file":"courier.js","names":[],"sources":["../../src/adapters/courier.ts"],"sourcesContent":["import type { SseSource } from '@vielzeug/courier';\n\nimport type { Flux } from '../types';\n\nimport { flux } from '../core';\n\n/**\n * Minimal shape of a courier `SyncStore` needed to subscribe to query state changes.\n * Avoids a hard import of `@vielzeug/courier` types that are not in the peer dep.\n *\n * @internal\n */\ntype SyncStore<T> = {\n peek(): T;\n subscribe(onStoreChange: () => void): () => void;\n};\n\n/**\n * Create a `Flux` from an SSE source returned by `streamClient.sse()`.\n * Emits typed SSE events under `event`. The current SSE status is NOT emitted —\n * only data messages are forwarded.\n *\n * @example\n * const events$ = fromSse(stream.sse('/events'), 'message');\n * events$.subscribe((data) => console.log(data));\n */\nexport function fromSse<TEvents extends Record<string, unknown>, K extends keyof TEvents & string>(\n source: SseSource<TEvents>,\n event: K,\n): Flux<TEvents[K]> {\n return flux<TEvents[K]>((observer) => {\n const unsub = source.on(event, (data) => observer.next(data));\n\n return unsub;\n });\n}\n\n/**\n * Create a `Flux` from a courier `SyncStore` (returned by `qc.observe()`).\n * Emits the current state immediately, then on every state change.\n *\n * @example\n * const data$ = fromQuery(qc.observe({ key: ['users'], fn: fetchUsers }));\n * data$.subscribe((state) => console.log(state.status, state.data));\n */\nexport function fromQuery<T>(store: SyncStore<T>): Flux<T> {\n return flux<T>((observer) => {\n observer.next(store.peek());\n\n const unsub = store.subscribe(() => {\n observer.next(store.peek());\n });\n\n return unsub;\n });\n}\n"],"mappings":";;AA0BA,SAAgB,EACd,GACA,GACkB;CAClB,OAAO,GAAkB,MACT,EAAO,GAAG,IAAQ,MAAS,EAAS,KAAK,CAAI,CAEpD,CACR;AACH;AAUA,SAAgB,EAAa,GAA8B;CACzD,OAAO,GAAS,OACd,EAAS,KAAK,EAAM,KAAK,CAAC,GAEZ,EAAM,gBAAgB;EAClC,EAAS,KAAK,EAAM,KAAK,CAAC;CAC5B,CAEO,EACR;AACH"}
1
+ {"version":3,"file":"courier.js","names":[],"sources":["../../src/adapters/courier.ts"],"sourcesContent":["import type { Stream } from '../types';\n\nimport { stream } from '../core';\n\ntype QueryCache = {\n getSnapshot<T>(key: readonly unknown[]): T | null;\n subscribe(key: readonly unknown[], onStoreChange: () => void): () => void;\n};\n\ntype QueryDefinition = {\n fetch: (...args: never[]) => Promise<unknown>;\n key: readonly unknown[];\n};\n\ntype QuerySnapshot<T> =\n | {\n readonly data: undefined;\n readonly error: null;\n readonly isFetching: boolean;\n readonly status: 'loading';\n readonly updatedAt: undefined;\n }\n | {\n readonly data: T;\n readonly error: null;\n readonly isFetching: boolean;\n readonly status: 'success';\n readonly updatedAt: number;\n }\n | {\n readonly data: T | undefined;\n readonly error: Error;\n readonly isFetching: false;\n readonly status: 'error';\n readonly updatedAt: number;\n };\n\ntype StreamEvent<T> = { readonly data: T; readonly event: string };\n\nexport function fromSse<T>(source: AsyncIterable<StreamEvent<T>>, event: string): Stream<T> {\n return stream((sink, signal) => {\n const iterator = source[Symbol.asyncIterator]();\n\n void (async () => {\n try {\n while (!signal.aborted) {\n const result = await iterator.next();\n\n if (result.done) {\n sink.complete();\n\n return;\n }\n\n if (result.value.event === event) sink.next(result.value.data);\n }\n } catch (reason) {\n if (!signal.aborted) sink.error(reason);\n }\n })();\n\n return () => {\n void iterator.return?.();\n };\n });\n}\n\nexport function fromQuery<T extends QueryDefinition>(\n cache: QueryCache,\n definition: T,\n): Stream<QuerySnapshot<Awaited<ReturnType<T['fetch']>>> | null> {\n return stream((sink) => {\n const snapshot = () => cache.getSnapshot<QuerySnapshot<Awaited<ReturnType<T['fetch']>>>>(definition.key);\n\n sink.next(snapshot());\n\n return cache.subscribe(definition.key, () => sink.next(snapshot()));\n });\n}\n"],"mappings":";;AAuCA,SAAgB,EAAW,GAAuC,GAA0B;CAC1F,OAAO,GAAQ,GAAM,MAAW;EAC9B,IAAM,IAAW,EAAO,OAAO,cAAc,CAAC;EAoB9C,QAlBM,YAAY;GAChB,IAAI;IACF,OAAO,CAAC,EAAO,UAAS;KACtB,IAAM,IAAS,MAAM,EAAS,KAAK;KAEnC,IAAI,EAAO,MAAM;MACf,EAAK,SAAS;MAEd;KACF;KAEA,AAAI,EAAO,MAAM,UAAU,KAAO,EAAK,KAAK,EAAO,MAAM,IAAI;IAC/D;GACF,SAAS,GAAQ;IACf,AAAK,EAAO,WAAS,EAAK,MAAM,CAAM;GACxC;EACF,EAAA,CAAG,SAEU;GACX,EAAc,SAAS;EACzB;CACF,CAAC;AACH;AAEA,SAAgB,EACd,GACA,GAC+D;CAC/D,OAAO,GAAQ,MAAS;EACtB,IAAM,UAAiB,EAAM,YAA4D,EAAW,GAAG;EAIvG,OAFA,EAAK,KAAK,EAAS,CAAC,GAEb,EAAM,UAAU,EAAW,WAAW,EAAK,KAAK,EAAS,CAAC,CAAC;CACpE,CAAC;AACH"}
@@ -1,2 +1,2 @@
1
- const e=require("../core.cjs");function t(t,n){return e.flux(e=>t.on(n,t=>e.next(t)))}function n(t,n){return r=>e.flux(e=>r.subscribe({complete:e.complete,error:e.error,next(r){t.emit(n,...r===void 0?[]:[r]),e.next(r)}}))}exports.fromBus=t,exports.toBus=n;
1
+ const e=require("../core.cjs"),t=require("../_link.cjs"),n=require("../_safe.cjs");function r(t,n){return e.stream(e=>t.on(n,t=>e.next(t)))}function i(r,i){return a=>e.stream((e,o)=>t.link(a,{complete:e.complete,error:e.error,next(t){n.tryCall(()=>{r.emit(i,...t===void 0?[]:[t]),e.next(t)},e.error)}},o).unsubscribe)}exports.fromBus=r,exports.toBus=i;
2
2
  //# sourceMappingURL=herald.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"herald.cjs","names":[],"sources":["../../src/adapters/herald.ts"],"sourcesContent":["import type { Bus, EventKey, EventMap } from '@vielzeug/herald';\n\nimport type { Flux, Operator } from '../types';\n\nimport { flux } from '../core';\n\n/**\n * Create a `Flux` that emits whenever `bus` fires `event`.\n *\n * @example\n * const clicks$ = fromBus(appBus, 'button:click');\n * clicks$.subscribe((payload) => console.log(payload));\n */\nexport function fromBus<T extends EventMap, K extends EventKey<T>>(bus: Bus<T>, event: K): Flux<T[K]> {\n return flux<T[K]>((observer) => {\n const unsub = bus.on(event, (payload) => observer.next(payload));\n\n return unsub;\n });\n}\n\n/**\n * Operator that pipes each emission to `bus` under `event`.\n * Returns the source unchanged (pass-through for side effects).\n *\n * @example\n * clicks$.pipe(toBus(appBus, 'forwarded:click'));\n */\nexport function toBus<T extends EventMap, K extends EventKey<T>>(bus: Bus<T>, event: K): Operator<T[K], T[K]> {\n return (source) =>\n flux<T[K]>((observer) =>\n source.subscribe({\n complete: observer.complete,\n error: observer.error,\n next(v) {\n bus.emit(event, ...((v === undefined ? [] : [v]) as T[K] extends void ? [] : [T[K]]));\n observer.next(v);\n },\n }),\n );\n}\n"],"mappings":"+BAaA,SAAgB,EAAmD,EAAa,EAAsB,CACpG,OAAO,EAAA,KAAY,GACH,EAAI,GAAG,EAAQ,GAAY,EAAS,KAAK,CAAO,CAEvD,CACR,CACH,CASA,SAAgB,EAAiD,EAAa,EAAgC,CAC5G,MAAQ,IACN,EAAA,KAAY,GACV,EAAO,UAAU,CACf,SAAU,EAAS,SACnB,MAAO,EAAS,MAChB,KAAK,EAAG,CACN,EAAI,KAAK,EAAO,GAAK,IAAM,IAAA,GAAY,CAAC,EAAI,CAAC,CAAC,CAAsC,EACpF,EAAS,KAAK,CAAC,CACjB,CACF,CAAC,CACH,CACJ"}
1
+ {"version":3,"file":"herald.cjs","names":[],"sources":["../../src/adapters/herald.ts"],"sourcesContent":["import type { Bus, EventKey, EventMap } from '@vielzeug/herald';\n\nimport type { Operator, Stream } from '../types';\n\nimport { link } from '../_link';\nimport { tryCall } from '../_safe';\nimport { stream } from '../core';\n\nexport function fromBus<T extends EventMap, K extends EventKey<T>>(bus: Bus<T>, event: K): Stream<T[K]> {\n return stream((sink) => bus.on(event, (payload) => sink.next(payload)));\n}\n\nexport function toBus<T extends EventMap, K extends EventKey<T>>(bus: Bus<T>, event: K): Operator<T[K], T[K]> {\n return (source) =>\n stream(\n (sink, signal) =>\n link(\n source,\n {\n complete: sink.complete,\n error: sink.error,\n next(value) {\n tryCall(() => {\n bus.emit(event, ...((value === undefined ? [] : [value]) as T[K] extends void ? [] : [T[K]]));\n sink.next(value);\n }, sink.error);\n },\n },\n signal,\n ).unsubscribe,\n );\n}\n"],"mappings":"mFAQA,SAAgB,EAAmD,EAAa,EAAwB,CACtG,OAAO,EAAA,OAAQ,GAAS,EAAI,GAAG,EAAQ,GAAY,EAAK,KAAK,CAAO,CAAC,CAAC,CACxE,CAEA,SAAgB,EAAiD,EAAa,EAAgC,CAC5G,MAAQ,IACN,EAAA,QACG,EAAM,IACL,EAAA,KACE,EACA,CACE,SAAU,EAAK,SACf,MAAO,EAAK,MACZ,KAAK,EAAO,CACV,EAAA,YAAc,CACZ,EAAI,KAAK,EAAO,GAAK,IAAU,IAAA,GAAY,CAAC,EAAI,CAAC,CAAK,CAAsC,EAC5F,EAAK,KAAK,CAAK,CACjB,EAAG,EAAK,KAAK,CACf,CACF,EACA,CACF,CAAC,CAAC,WACN,CACJ"}
@@ -1,19 +1,5 @@
1
1
  import type { Bus, EventKey, EventMap } from '@vielzeug/herald';
2
- import type { Flux, Operator } from '../types';
3
- /**
4
- * Create a `Flux` that emits whenever `bus` fires `event`.
5
- *
6
- * @example
7
- * const clicks$ = fromBus(appBus, 'button:click');
8
- * clicks$.subscribe((payload) => console.log(payload));
9
- */
10
- export declare function fromBus<T extends EventMap, K extends EventKey<T>>(bus: Bus<T>, event: K): Flux<T[K]>;
11
- /**
12
- * Operator that pipes each emission to `bus` under `event`.
13
- * Returns the source unchanged (pass-through for side effects).
14
- *
15
- * @example
16
- * clicks$.pipe(toBus(appBus, 'forwarded:click'));
17
- */
2
+ import type { Operator, Stream } from '../types';
3
+ export declare function fromBus<T extends EventMap, K extends EventKey<T>>(bus: Bus<T>, event: K): Stream<T[K]>;
18
4
  export declare function toBus<T extends EventMap, K extends EventKey<T>>(bus: Bus<T>, event: K): Operator<T[K], T[K]>;
19
5
  //# sourceMappingURL=herald.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"herald.d.ts","sourceRoot":"","sources":["../../src/adapters/herald.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEhE,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAI/C;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,CAAC,SAAS,QAAQ,EAAE,CAAC,SAAS,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAMpG;AAED;;;;;;GAMG;AACH,wBAAgB,KAAK,CAAC,CAAC,SAAS,QAAQ,EAAE,CAAC,SAAS,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAY5G"}
1
+ {"version":3,"file":"herald.d.ts","sourceRoot":"","sources":["../../src/adapters/herald.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEhE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAMjD,wBAAgB,OAAO,CAAC,CAAC,SAAS,QAAQ,EAAE,CAAC,SAAS,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAEtG;AAED,wBAAgB,KAAK,CAAC,CAAC,SAAS,QAAQ,EAAE,CAAC,SAAS,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAmB5G"}
@@ -1,18 +1,22 @@
1
- import { flux as e } from "../core.js";
1
+ import { stream as e } from "../core.js";
2
+ import { link as t } from "../_link.js";
3
+ import { tryCall as n } from "../_safe.js";
2
4
  //#region src/adapters/herald.ts
3
- function t(t, n) {
5
+ function r(t, n) {
4
6
  return e((e) => t.on(n, (t) => e.next(t)));
5
7
  }
6
- function n(t, n) {
7
- return (r) => e((e) => r.subscribe({
8
+ function i(r, i) {
9
+ return (a) => e((e, o) => t(a, {
8
10
  complete: e.complete,
9
11
  error: e.error,
10
- next(r) {
11
- t.emit(n, ...r === void 0 ? [] : [r]), e.next(r);
12
+ next(t) {
13
+ n(() => {
14
+ r.emit(i, ...t === void 0 ? [] : [t]), e.next(t);
15
+ }, e.error);
12
16
  }
13
- }));
17
+ }, o).unsubscribe);
14
18
  }
15
19
  //#endregion
16
- export { t as fromBus, n as toBus };
20
+ export { r as fromBus, i as toBus };
17
21
 
18
22
  //# sourceMappingURL=herald.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"herald.js","names":[],"sources":["../../src/adapters/herald.ts"],"sourcesContent":["import type { Bus, EventKey, EventMap } from '@vielzeug/herald';\n\nimport type { Flux, Operator } from '../types';\n\nimport { flux } from '../core';\n\n/**\n * Create a `Flux` that emits whenever `bus` fires `event`.\n *\n * @example\n * const clicks$ = fromBus(appBus, 'button:click');\n * clicks$.subscribe((payload) => console.log(payload));\n */\nexport function fromBus<T extends EventMap, K extends EventKey<T>>(bus: Bus<T>, event: K): Flux<T[K]> {\n return flux<T[K]>((observer) => {\n const unsub = bus.on(event, (payload) => observer.next(payload));\n\n return unsub;\n });\n}\n\n/**\n * Operator that pipes each emission to `bus` under `event`.\n * Returns the source unchanged (pass-through for side effects).\n *\n * @example\n * clicks$.pipe(toBus(appBus, 'forwarded:click'));\n */\nexport function toBus<T extends EventMap, K extends EventKey<T>>(bus: Bus<T>, event: K): Operator<T[K], T[K]> {\n return (source) =>\n flux<T[K]>((observer) =>\n source.subscribe({\n complete: observer.complete,\n error: observer.error,\n next(v) {\n bus.emit(event, ...((v === undefined ? [] : [v]) as T[K] extends void ? [] : [T[K]]));\n observer.next(v);\n },\n }),\n );\n}\n"],"mappings":";;AAaA,SAAgB,EAAmD,GAAa,GAAsB;CACpG,OAAO,GAAY,MACH,EAAI,GAAG,IAAQ,MAAY,EAAS,KAAK,CAAO,CAEvD,CACR;AACH;AASA,SAAgB,EAAiD,GAAa,GAAgC;CAC5G,QAAQ,MACN,GAAY,MACV,EAAO,UAAU;EACf,UAAU,EAAS;EACnB,OAAO,EAAS;EAChB,KAAK,GAAG;GAEN,AADA,EAAI,KAAK,GAAO,GAAK,MAAM,KAAA,IAAY,CAAC,IAAI,CAAC,CAAC,CAAsC,GACpF,EAAS,KAAK,CAAC;EACjB;CACF,CAAC,CACH;AACJ"}
1
+ {"version":3,"file":"herald.js","names":[],"sources":["../../src/adapters/herald.ts"],"sourcesContent":["import type { Bus, EventKey, EventMap } from '@vielzeug/herald';\n\nimport type { Operator, Stream } from '../types';\n\nimport { link } from '../_link';\nimport { tryCall } from '../_safe';\nimport { stream } from '../core';\n\nexport function fromBus<T extends EventMap, K extends EventKey<T>>(bus: Bus<T>, event: K): Stream<T[K]> {\n return stream((sink) => bus.on(event, (payload) => sink.next(payload)));\n}\n\nexport function toBus<T extends EventMap, K extends EventKey<T>>(bus: Bus<T>, event: K): Operator<T[K], T[K]> {\n return (source) =>\n stream(\n (sink, signal) =>\n link(\n source,\n {\n complete: sink.complete,\n error: sink.error,\n next(value) {\n tryCall(() => {\n bus.emit(event, ...((value === undefined ? [] : [value]) as T[K] extends void ? [] : [T[K]]));\n sink.next(value);\n }, sink.error);\n },\n },\n signal,\n ).unsubscribe,\n );\n}\n"],"mappings":";;;;AAQA,SAAgB,EAAmD,GAAa,GAAwB;CACtG,OAAO,GAAQ,MAAS,EAAI,GAAG,IAAQ,MAAY,EAAK,KAAK,CAAO,CAAC,CAAC;AACxE;AAEA,SAAgB,EAAiD,GAAa,GAAgC;CAC5G,QAAQ,MACN,GACG,GAAM,MACL,EACE,GACA;EACE,UAAU,EAAK;EACf,OAAO,EAAK;EACZ,KAAK,GAAO;GACV,QAAc;IAEZ,AADA,EAAI,KAAK,GAAO,GAAK,MAAU,KAAA,IAAY,CAAC,IAAI,CAAC,CAAK,CAAsC,GAC5F,EAAK,KAAK,CAAK;GACjB,GAAG,EAAK,KAAK;EACf;CACF,GACA,CACF,CAAC,CAAC,WACN;AACJ"}
@@ -1,2 +1,2 @@
1
- const e=require("../core.cjs");function t(t,n){return e.flux(e=>t.on(n,t=>e.next(t)))}function n(t){return e.flux(e=>{e.next(t.state.value);let n=t.onJoin(()=>{e.next(t.state.value)}),r=t.onLeave(()=>{e.next(t.state.value)});return()=>{n(),r()}})}exports.fromPresence=n,exports.fromPulse=t;
1
+ const e=require("../core.cjs");function t(t,n){return e.stream(e=>t.on(n,t=>e.next(t)))}function n(t){return e.stream(e=>{e.next(t.state.value);let n=t.onJoin(()=>e.next(t.state.value)),r=t.onLeave(()=>e.next(t.state.value));return()=>{n(),r()}})}exports.fromPresence=n,exports.fromPulse=t;
2
2
  //# sourceMappingURL=pulse.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"pulse.cjs","names":[],"sources":["../../src/adapters/pulse.ts"],"sourcesContent":["import type { EventKey, MessageMap, PresenceChannel, Pulse } from '@vielzeug/pulse';\n\nimport type { Flux } from '../types';\n\nimport { flux } from '../core';\n\n/**\n * Create a `Flux` that emits whenever a Pulse connection fires `event`.\n *\n * @example\n * const messages$ = fromPulse(pulse, 'chat:message');\n * messages$.subscribe((msg) => console.log(msg));\n */\nexport function fromPulse<T extends MessageMap, K extends EventKey<T>>(pulse: Pulse<T>, event: K): Flux<T[K]> {\n return flux<T[K]>((observer) => {\n const unsub = pulse.on(event, (payload) => observer.next(payload));\n\n return unsub;\n });\n}\n\n/**\n * Create a `Flux` from a `PresenceChannel`. Emits the full member map whenever\n * any member joins or leaves.\n *\n * The current state is emitted immediately on subscribe.\n *\n * @example\n * const members$ = fromPresence(pulse.presence('lobby'));\n * members$.subscribe((map) => console.log([...map.keys()]));\n */\nexport function fromPresence<T>(presence: PresenceChannel<T>): Flux<ReadonlyMap<string, T>> {\n return flux<ReadonlyMap<string, T>>((observer) => {\n observer.next(presence.state.value);\n\n const unsubJoin = presence.onJoin(() => {\n observer.next(presence.state.value);\n });\n\n const unsubLeave = presence.onLeave(() => {\n observer.next(presence.state.value);\n });\n\n return () => {\n unsubJoin();\n unsubLeave();\n };\n });\n}\n"],"mappings":"+BAaA,SAAgB,EAAuD,EAAiB,EAAsB,CAC5G,OAAO,EAAA,KAAY,GACH,EAAM,GAAG,EAAQ,GAAY,EAAS,KAAK,CAAO,CAEzD,CACR,CACH,CAYA,SAAgB,EAAgB,EAA4D,CAC1F,OAAO,EAAA,KAA8B,GAAa,CAChD,EAAS,KAAK,EAAS,MAAM,KAAK,EAElC,IAAM,EAAY,EAAS,WAAa,CACtC,EAAS,KAAK,EAAS,MAAM,KAAK,CACpC,CAAC,EAEK,EAAa,EAAS,YAAc,CACxC,EAAS,KAAK,EAAS,MAAM,KAAK,CACpC,CAAC,EAED,UAAa,CACX,EAAU,EACV,EAAW,CACb,CACF,CAAC,CACH"}
1
+ {"version":3,"file":"pulse.cjs","names":[],"sources":["../../src/adapters/pulse.ts"],"sourcesContent":["import type { EventKey, MessageMap, PresenceChannel, Pulse } from '@vielzeug/pulse';\n\nimport type { Stream } from '../types';\n\nimport { stream } from '../core';\n\nexport function fromPulse<T extends MessageMap, K extends EventKey<T>>(pulse: Pulse<T>, event: K): Stream<T[K]> {\n return stream((sink) => pulse.on(event, (payload) => sink.next(payload)));\n}\n\nexport function fromPresence<T>(presence: PresenceChannel<T>): Stream<ReadonlyMap<string, T>> {\n return stream((sink) => {\n sink.next(presence.state.value);\n\n const stopJoin = presence.onJoin(() => sink.next(presence.state.value));\n const stopLeave = presence.onLeave(() => sink.next(presence.state.value));\n\n return () => {\n stopJoin();\n stopLeave();\n };\n });\n}\n"],"mappings":"+BAMA,SAAgB,EAAuD,EAAiB,EAAwB,CAC9G,OAAO,EAAA,OAAQ,GAAS,EAAM,GAAG,EAAQ,GAAY,EAAK,KAAK,CAAO,CAAC,CAAC,CAC1E,CAEA,SAAgB,EAAgB,EAA8D,CAC5F,OAAO,EAAA,OAAQ,GAAS,CACtB,EAAK,KAAK,EAAS,MAAM,KAAK,EAE9B,IAAM,EAAW,EAAS,WAAa,EAAK,KAAK,EAAS,MAAM,KAAK,CAAC,EAChE,EAAY,EAAS,YAAc,EAAK,KAAK,EAAS,MAAM,KAAK,CAAC,EAExE,UAAa,CACX,EAAS,EACT,EAAU,CACZ,CACF,CAAC,CACH"}
@@ -1,22 +1,5 @@
1
1
  import type { EventKey, MessageMap, PresenceChannel, Pulse } from '@vielzeug/pulse';
2
- import type { Flux } from '../types';
3
- /**
4
- * Create a `Flux` that emits whenever a Pulse connection fires `event`.
5
- *
6
- * @example
7
- * const messages$ = fromPulse(pulse, 'chat:message');
8
- * messages$.subscribe((msg) => console.log(msg));
9
- */
10
- export declare function fromPulse<T extends MessageMap, K extends EventKey<T>>(pulse: Pulse<T>, event: K): Flux<T[K]>;
11
- /**
12
- * Create a `Flux` from a `PresenceChannel`. Emits the full member map whenever
13
- * any member joins or leaves.
14
- *
15
- * The current state is emitted immediately on subscribe.
16
- *
17
- * @example
18
- * const members$ = fromPresence(pulse.presence('lobby'));
19
- * members$.subscribe((map) => console.log([...map.keys()]));
20
- */
21
- export declare function fromPresence<T>(presence: PresenceChannel<T>): Flux<ReadonlyMap<string, T>>;
2
+ import type { Stream } from '../types';
3
+ export declare function fromPulse<T extends MessageMap, K extends EventKey<T>>(pulse: Pulse<T>, event: K): Stream<T[K]>;
4
+ export declare function fromPresence<T>(presence: PresenceChannel<T>): Stream<ReadonlyMap<string, T>>;
22
5
  //# sourceMappingURL=pulse.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"pulse.d.ts","sourceRoot":"","sources":["../../src/adapters/pulse.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAEpF,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAIrC;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS,UAAU,EAAE,CAAC,SAAS,QAAQ,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAM5G;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,QAAQ,EAAE,eAAe,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAiB1F"}
1
+ {"version":3,"file":"pulse.d.ts","sourceRoot":"","sources":["../../src/adapters/pulse.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAEpF,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAIvC,wBAAgB,SAAS,CAAC,CAAC,SAAS,UAAU,EAAE,CAAC,SAAS,QAAQ,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAE9G;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,QAAQ,EAAE,eAAe,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAY5F"}
@@ -1,4 +1,4 @@
1
- import { flux as e } from "../core.js";
1
+ import { stream as e } from "../core.js";
2
2
  //#region src/adapters/pulse.ts
3
3
  function t(t, n) {
4
4
  return e((e) => t.on(n, (t) => e.next(t)));
@@ -6,11 +6,7 @@ function t(t, n) {
6
6
  function n(t) {
7
7
  return e((e) => {
8
8
  e.next(t.state.value);
9
- let n = t.onJoin(() => {
10
- e.next(t.state.value);
11
- }), r = t.onLeave(() => {
12
- e.next(t.state.value);
13
- });
9
+ let n = t.onJoin(() => e.next(t.state.value)), r = t.onLeave(() => e.next(t.state.value));
14
10
  return () => {
15
11
  n(), r();
16
12
  };
@@ -1 +1 @@
1
- {"version":3,"file":"pulse.js","names":[],"sources":["../../src/adapters/pulse.ts"],"sourcesContent":["import type { EventKey, MessageMap, PresenceChannel, Pulse } from '@vielzeug/pulse';\n\nimport type { Flux } from '../types';\n\nimport { flux } from '../core';\n\n/**\n * Create a `Flux` that emits whenever a Pulse connection fires `event`.\n *\n * @example\n * const messages$ = fromPulse(pulse, 'chat:message');\n * messages$.subscribe((msg) => console.log(msg));\n */\nexport function fromPulse<T extends MessageMap, K extends EventKey<T>>(pulse: Pulse<T>, event: K): Flux<T[K]> {\n return flux<T[K]>((observer) => {\n const unsub = pulse.on(event, (payload) => observer.next(payload));\n\n return unsub;\n });\n}\n\n/**\n * Create a `Flux` from a `PresenceChannel`. Emits the full member map whenever\n * any member joins or leaves.\n *\n * The current state is emitted immediately on subscribe.\n *\n * @example\n * const members$ = fromPresence(pulse.presence('lobby'));\n * members$.subscribe((map) => console.log([...map.keys()]));\n */\nexport function fromPresence<T>(presence: PresenceChannel<T>): Flux<ReadonlyMap<string, T>> {\n return flux<ReadonlyMap<string, T>>((observer) => {\n observer.next(presence.state.value);\n\n const unsubJoin = presence.onJoin(() => {\n observer.next(presence.state.value);\n });\n\n const unsubLeave = presence.onLeave(() => {\n observer.next(presence.state.value);\n });\n\n return () => {\n unsubJoin();\n unsubLeave();\n };\n });\n}\n"],"mappings":";;AAaA,SAAgB,EAAuD,GAAiB,GAAsB;CAC5G,OAAO,GAAY,MACH,EAAM,GAAG,IAAQ,MAAY,EAAS,KAAK,CAAO,CAEzD,CACR;AACH;AAYA,SAAgB,EAAgB,GAA4D;CAC1F,OAAO,GAA8B,MAAa;EAChD,EAAS,KAAK,EAAS,MAAM,KAAK;EAElC,IAAM,IAAY,EAAS,aAAa;GACtC,EAAS,KAAK,EAAS,MAAM,KAAK;EACpC,CAAC,GAEK,IAAa,EAAS,cAAc;GACxC,EAAS,KAAK,EAAS,MAAM,KAAK;EACpC,CAAC;EAED,aAAa;GAEX,AADA,EAAU,GACV,EAAW;EACb;CACF,CAAC;AACH"}
1
+ {"version":3,"file":"pulse.js","names":[],"sources":["../../src/adapters/pulse.ts"],"sourcesContent":["import type { EventKey, MessageMap, PresenceChannel, Pulse } from '@vielzeug/pulse';\n\nimport type { Stream } from '../types';\n\nimport { stream } from '../core';\n\nexport function fromPulse<T extends MessageMap, K extends EventKey<T>>(pulse: Pulse<T>, event: K): Stream<T[K]> {\n return stream((sink) => pulse.on(event, (payload) => sink.next(payload)));\n}\n\nexport function fromPresence<T>(presence: PresenceChannel<T>): Stream<ReadonlyMap<string, T>> {\n return stream((sink) => {\n sink.next(presence.state.value);\n\n const stopJoin = presence.onJoin(() => sink.next(presence.state.value));\n const stopLeave = presence.onLeave(() => sink.next(presence.state.value));\n\n return () => {\n stopJoin();\n stopLeave();\n };\n });\n}\n"],"mappings":";;AAMA,SAAgB,EAAuD,GAAiB,GAAwB;CAC9G,OAAO,GAAQ,MAAS,EAAM,GAAG,IAAQ,MAAY,EAAK,KAAK,CAAO,CAAC,CAAC;AAC1E;AAEA,SAAgB,EAAgB,GAA8D;CAC5F,OAAO,GAAQ,MAAS;EACtB,EAAK,KAAK,EAAS,MAAM,KAAK;EAE9B,IAAM,IAAW,EAAS,aAAa,EAAK,KAAK,EAAS,MAAM,KAAK,CAAC,GAChE,IAAY,EAAS,cAAc,EAAK,KAAK,EAAS,MAAM,KAAK,CAAC;EAExE,aAAa;GAEX,AADA,EAAS,GACT,EAAU;EACZ;CACF,CAAC;AACH"}
@@ -1,2 +1,2 @@
1
- const e=require("../_dev.cjs"),t=require("../core.cjs");let n=require("@vielzeug/ripple");function r(e){return t.flux(t=>{t.next(e.value);let n=e.subscribe(()=>{t.next(e.value)});return()=>n.dispose()})}function i(t,r){let i=(0,n.signal)(r.initial),a=new AbortController,o=t.subscribe({error(t){e.error(`toSignal: source errored — signal value may be stale`,t)},next(e){i.value=e}},r.signal),s=()=>{a.signal.aborted||(a.abort(),o())};return{get disposalSignal(){return a.signal},dispose:s,get disposed(){return a.signal.aborted},get signal(){return i},[Symbol.dispose](){s()},get value(){return i.value}}}exports.fromSignal=r,exports.toSignal=i;
1
+ const e=require("../core.cjs");require("../_dev.cjs");let t=require("@vielzeug/ripple");function n(t){return e.stream(e=>(e.next(t.value),t.subscribe(()=>e.next(t.value))))}function r(e,n){let r=(0,t.signal)(n.initial),i=new AbortController,a={},o=()=>{i.signal.aborted||(i.abort(),n.signal?.removeEventListener(`abort`,o),a.current?.unsubscribe())};return n.signal?.aborted&&i.abort(),a.current=e.subscribe({complete:o,error(e){o()},next(e){r.value=e}},{signal:i.signal}),i.signal.aborted||n.signal?.addEventListener(`abort`,o,{once:!0}),{get disposalSignal(){return i.signal},dispose:o,get disposed(){return i.signal.aborted},get signal(){return r},[Symbol.dispose]:o,get value(){return r.value}}}exports.fromSignal=n,exports.toSignal=r;
2
2
  //# sourceMappingURL=ripple.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ripple.cjs","names":[],"sources":["../../src/adapters/ripple.ts"],"sourcesContent":["import type { Readable } from '@vielzeug/ripple';\n\nimport { signal } from '@vielzeug/ripple';\n\nimport type { Flux } from '../types';\n\nimport { error } from '../_dev';\nimport { flux } from '../core';\n\n/**\n * Create a `Flux` that emits a new value every time a ripple `Reactive` changes.\n * The current value is emitted immediately on subscribe.\n *\n * @example\n * const count = signal(0);\n * const count$ = fromSignal(count);\n * count$.subscribe((n) => console.log(n)); // logs 0 immediately, then on every change\n */\nexport function fromSignal<T>(source: Readable<T>): Flux<T> {\n return flux<T>((observer) => {\n observer.next(source.value);\n\n const subscription = source.subscribe(() => {\n observer.next(source.value);\n });\n\n return () => subscription.dispose();\n });\n}\n\nexport type ToSignalOptions<T> = {\n /** Initial value before the first emission. */\n initial: T;\n /**\n * Optional `AbortSignal` that stops tracking independently of disposal.\n * Useful when the caller does not own the flux's lifetime.\n */\n signal?: AbortSignal;\n};\n\n/**\n * A handle returned by `toSignal()` that wraps a ripple signal updated by a `Flux`.\n * Exposes `value` (reactive — usable in ripple `effect()` calls) and `dispose()` to\n * stop tracking. The underlying signal retains its last value after disposal.\n */\nexport type SignalBinding<T> = {\n /** ES2026 `using` compatible disposal. */\n [Symbol.dispose](): void;\n /** AbortSignal that aborts when `dispose()` is called. */\n readonly disposalSignal: AbortSignal;\n /** Stop tracking the source `Flux` and freeze the signal value. */\n dispose(): void;\n /** `true` after `dispose()` is called. */\n readonly disposed: boolean;\n /** The underlying ripple `Readable<T>` for use with ripple operators. */\n readonly signal: Readable<T>;\n /** The current tracked value (reactive — reads track in ripple effects). */\n readonly value: T;\n};\n\n/**\n * Create a `SignalBinding<T>` whose value is updated by each emission from a `Flux`.\n * The binding starts with `opts.initial` and updates reactively as the flux emits.\n *\n * Call `dispose()` to stop tracking; the last value remains readable after disposal.\n *\n * @example\n * const latest = toSignal(count$, { initial: 0 });\n * effect(() => console.log(latest.value)); // reactive — re-runs on flux emissions\n * latest.dispose(); // stop tracking\n */\nexport function toSignal<T>(source: Flux<T>, opts: ToSignalOptions<T>): SignalBinding<T> {\n const sig = signal<T>(opts.initial);\n const ac = new AbortController();\n\n const unsub = source.subscribe(\n {\n error(err) {\n error('toSignal: source errored — signal value may be stale', err);\n },\n next(v) {\n sig.value = v;\n },\n },\n opts.signal,\n );\n\n const dispose = (): void => {\n if (ac.signal.aborted) return;\n\n ac.abort();\n unsub();\n };\n\n return {\n get disposalSignal(): AbortSignal {\n return ac.signal;\n },\n dispose,\n get disposed(): boolean {\n return ac.signal.aborted;\n },\n get signal(): Readable<T> {\n return sig;\n },\n [Symbol.dispose](): void {\n dispose();\n },\n get value(): T {\n return sig.value;\n },\n };\n}\n"],"mappings":"0FAkBA,SAAgB,EAAc,EAA8B,CAC1D,OAAO,EAAA,KAAS,GAAa,CAC3B,EAAS,KAAK,EAAO,KAAK,EAE1B,IAAM,EAAe,EAAO,cAAgB,CAC1C,EAAS,KAAK,EAAO,KAAK,CAC5B,CAAC,EAED,UAAa,EAAa,QAAQ,CACpC,CAAC,CACH,CA2CA,SAAgB,EAAY,EAAiB,EAA4C,CACvF,IAAM,GAAA,EAAA,EAAA,OAAA,CAAgB,EAAK,OAAO,EAC5B,EAAK,IAAI,gBAET,EAAQ,EAAO,UACnB,CACE,MAAM,EAAK,CACT,EAAA,MAAM,uDAAwD,CAAG,CACnE,EACA,KAAK,EAAG,CACN,EAAI,MAAQ,CACd,CACF,EACA,EAAK,MACP,EAEM,MAAsB,CACtB,EAAG,OAAO,UAEd,EAAG,MAAM,EACT,EAAM,EACR,EAEA,MAAO,CACL,IAAI,gBAA8B,CAChC,OAAO,EAAG,MACZ,EACA,UACA,IAAI,UAAoB,CACtB,OAAO,EAAG,OAAO,OACnB,EACA,IAAI,QAAsB,CACxB,OAAO,CACT,EACA,CAAC,OAAO,UAAiB,CACvB,EAAQ,CACV,EACA,IAAI,OAAW,CACb,OAAO,EAAI,KACb,CACF,CACF"}
1
+ {"version":3,"file":"ripple.cjs","names":[],"sources":["../../src/adapters/ripple.ts"],"sourcesContent":["import type { Readable } from '@vielzeug/ripple';\n\nimport { signal } from '@vielzeug/ripple';\n\nimport type { Stream, Subscription } from '../types';\n\nimport { error } from '../_dev';\nimport { stream } from '../core';\n\nexport type ToSignalOptions<T> = {\n initial: T;\n signal?: AbortSignal;\n};\n\nexport type SignalBinding<T> = {\n [Symbol.dispose](): void;\n readonly disposalSignal: AbortSignal;\n dispose(): void;\n readonly disposed: boolean;\n readonly signal: Readable<T>;\n readonly value: T;\n};\n\nexport function fromSignal<T>(source: Readable<T>): Stream<T> {\n return stream((sink) => {\n sink.next(source.value);\n\n return source.subscribe(() => sink.next(source.value));\n });\n}\n\nexport function toSignal<T>(source: Stream<T>, options: ToSignalOptions<T>): SignalBinding<T> {\n const target = signal(options.initial);\n const controller = new AbortController();\n const subscriptionRef: { current?: Subscription } = {};\n\n const dispose = (): void => {\n if (controller.signal.aborted) return;\n\n controller.abort();\n options.signal?.removeEventListener('abort', dispose);\n subscriptionRef.current?.unsubscribe();\n };\n\n if (options.signal?.aborted) controller.abort();\n\n subscriptionRef.current = source.subscribe(\n {\n complete: dispose,\n error(reason) {\n error('toSignal source error', reason);\n dispose();\n },\n next(value) {\n target.value = value;\n },\n },\n { signal: controller.signal },\n );\n\n if (!controller.signal.aborted) options.signal?.addEventListener('abort', dispose, { once: true });\n\n return {\n get disposalSignal(): AbortSignal {\n return controller.signal;\n },\n dispose,\n get disposed(): boolean {\n return controller.signal.aborted;\n },\n get signal(): Readable<T> {\n return target;\n },\n [Symbol.dispose]: dispose,\n get value(): T {\n return target.value;\n },\n };\n}\n"],"mappings":"wFAuBA,SAAgB,EAAc,EAAgC,CAC5D,OAAO,EAAA,OAAQ,IACb,EAAK,KAAK,EAAO,KAAK,EAEf,EAAO,cAAgB,EAAK,KAAK,EAAO,KAAK,CAAC,EACtD,CACH,CAEA,SAAgB,EAAY,EAAmB,EAA+C,CAC5F,IAAM,GAAA,EAAS,EAAA,OAAA,CAAO,EAAQ,OAAO,EAC/B,EAAa,IAAI,gBACjB,EAA8C,CAAC,EAE/C,MAAsB,CACtB,EAAW,OAAO,UAEtB,EAAW,MAAM,EACjB,EAAQ,QAAQ,oBAAoB,QAAS,CAAO,EACpD,EAAgB,SAAS,YAAY,EACvC,EAoBA,OAlBI,EAAQ,QAAQ,SAAS,EAAW,MAAM,EAE9C,EAAgB,QAAU,EAAO,UAC/B,CACE,SAAU,EACV,MAAM,EAAQ,CAEZ,EAAQ,CACV,EACA,KAAK,EAAO,CACV,EAAO,MAAQ,CACjB,CACF,EACA,CAAE,OAAQ,EAAW,MAAO,CAC9B,EAEK,EAAW,OAAO,SAAS,EAAQ,QAAQ,iBAAiB,QAAS,EAAS,CAAE,KAAM,EAAK,CAAC,EAE1F,CACL,IAAI,gBAA8B,CAChC,OAAO,EAAW,MACpB,EACA,UACA,IAAI,UAAoB,CACtB,OAAO,EAAW,OAAO,OAC3B,EACA,IAAI,QAAsB,CACxB,OAAO,CACT,GACC,OAAO,SAAU,EAClB,IAAI,OAAW,CACb,OAAO,EAAO,KAChB,CACF,CACF"}
@@ -1,53 +1,17 @@
1
1
  import type { Readable } from '@vielzeug/ripple';
2
- import type { Flux } from '../types';
3
- /**
4
- * Create a `Flux` that emits a new value every time a ripple `Reactive` changes.
5
- * The current value is emitted immediately on subscribe.
6
- *
7
- * @example
8
- * const count = signal(0);
9
- * const count$ = fromSignal(count);
10
- * count$.subscribe((n) => console.log(n)); // logs 0 immediately, then on every change
11
- */
12
- export declare function fromSignal<T>(source: Readable<T>): Flux<T>;
2
+ import type { Stream } from '../types';
13
3
  export type ToSignalOptions<T> = {
14
- /** Initial value before the first emission. */
15
4
  initial: T;
16
- /**
17
- * Optional `AbortSignal` that stops tracking independently of disposal.
18
- * Useful when the caller does not own the flux's lifetime.
19
- */
20
5
  signal?: AbortSignal;
21
6
  };
22
- /**
23
- * A handle returned by `toSignal()` that wraps a ripple signal updated by a `Flux`.
24
- * Exposes `value` (reactive — usable in ripple `effect()` calls) and `dispose()` to
25
- * stop tracking. The underlying signal retains its last value after disposal.
26
- */
27
7
  export type SignalBinding<T> = {
28
- /** ES2026 `using` compatible disposal. */
29
8
  [Symbol.dispose](): void;
30
- /** AbortSignal that aborts when `dispose()` is called. */
31
9
  readonly disposalSignal: AbortSignal;
32
- /** Stop tracking the source `Flux` and freeze the signal value. */
33
10
  dispose(): void;
34
- /** `true` after `dispose()` is called. */
35
11
  readonly disposed: boolean;
36
- /** The underlying ripple `Readable<T>` for use with ripple operators. */
37
12
  readonly signal: Readable<T>;
38
- /** The current tracked value (reactive — reads track in ripple effects). */
39
13
  readonly value: T;
40
14
  };
41
- /**
42
- * Create a `SignalBinding<T>` whose value is updated by each emission from a `Flux`.
43
- * The binding starts with `opts.initial` and updates reactively as the flux emits.
44
- *
45
- * Call `dispose()` to stop tracking; the last value remains readable after disposal.
46
- *
47
- * @example
48
- * const latest = toSignal(count$, { initial: 0 });
49
- * effect(() => console.log(latest.value)); // reactive — re-runs on flux emissions
50
- * latest.dispose(); // stop tracking
51
- */
52
- export declare function toSignal<T>(source: Flux<T>, opts: ToSignalOptions<T>): SignalBinding<T>;
15
+ export declare function fromSignal<T>(source: Readable<T>): Stream<T>;
16
+ export declare function toSignal<T>(source: Stream<T>, options: ToSignalOptions<T>): SignalBinding<T>;
53
17
  //# sourceMappingURL=ripple.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ripple.d.ts","sourceRoot":"","sources":["../../src/adapters/ripple.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAIjD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAKrC;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAU1D;AAED,MAAM,MAAM,eAAe,CAAC,CAAC,IAAI;IAC/B,+CAA+C;IAC/C,OAAO,EAAE,CAAC,CAAC;IACX;;;OAGG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,aAAa,CAAC,CAAC,IAAI;IAC7B,0CAA0C;IAC1C,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC;IACzB,0DAA0D;IAC1D,QAAQ,CAAC,cAAc,EAAE,WAAW,CAAC;IACrC,mEAAmE;IACnE,OAAO,IAAI,IAAI,CAAC;IAChB,0CAA0C;IAC1C,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,yEAAyE;IACzE,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;IAC7B,4EAA4E;IAC5E,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;CACnB,CAAC;AAEF;;;;;;;;;;GAUG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,eAAe,CAAC,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,CAyCvF"}
1
+ {"version":3,"file":"ripple.d.ts","sourceRoot":"","sources":["../../src/adapters/ripple.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAIjD,OAAO,KAAK,EAAE,MAAM,EAAgB,MAAM,UAAU,CAAC;AAKrD,MAAM,MAAM,eAAe,CAAC,CAAC,IAAI;IAC/B,OAAO,EAAE,CAAC,CAAC;IACX,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,aAAa,CAAC,CAAC,IAAI;IAC7B,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC;IACzB,QAAQ,CAAC,cAAc,EAAE,WAAW,CAAC;IACrC,OAAO,IAAI,IAAI,CAAC;IAChB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;CACnB,CAAC;AAEF,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAM5D;AAED,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,CA+C5F"}
@@ -1,47 +1,40 @@
1
- import { error as e } from "../_dev.js";
2
- import { flux as t } from "../core.js";
3
- import { signal as n } from "@vielzeug/ripple";
1
+ import { stream as e } from "../core.js";
2
+ import "../_dev.js";
3
+ import { signal as t } from "@vielzeug/ripple";
4
4
  //#region src/adapters/ripple.ts
5
- function r(e) {
6
- return t((t) => {
7
- t.next(e.value);
8
- let n = e.subscribe(() => {
9
- t.next(e.value);
10
- });
11
- return () => n.dispose();
12
- });
5
+ function n(t) {
6
+ return e((e) => (e.next(t.value), t.subscribe(() => e.next(t.value))));
13
7
  }
14
- function i(t, r) {
15
- let i = n(r.initial), a = new AbortController(), o = t.subscribe({
16
- error(t) {
17
- e("toSignal: source errored — signal value may be stale", t);
8
+ function r(e, n) {
9
+ let r = t(n.initial), i = new AbortController(), a = {}, o = () => {
10
+ i.signal.aborted || (i.abort(), n.signal?.removeEventListener("abort", o), a.current?.unsubscribe());
11
+ };
12
+ return n.signal?.aborted && i.abort(), a.current = e.subscribe({
13
+ complete: o,
14
+ error(e) {
15
+ o();
18
16
  },
19
17
  next(e) {
20
- i.value = e;
18
+ r.value = e;
21
19
  }
22
- }, r.signal), s = () => {
23
- a.signal.aborted || (a.abort(), o());
24
- };
25
- return {
20
+ }, { signal: i.signal }), i.signal.aborted || n.signal?.addEventListener("abort", o, { once: !0 }), {
26
21
  get disposalSignal() {
27
- return a.signal;
22
+ return i.signal;
28
23
  },
29
- dispose: s,
24
+ dispose: o,
30
25
  get disposed() {
31
- return a.signal.aborted;
26
+ return i.signal.aborted;
32
27
  },
33
28
  get signal() {
34
- return i;
35
- },
36
- [Symbol.dispose]() {
37
- s();
29
+ return r;
38
30
  },
31
+ [Symbol.dispose]: o,
39
32
  get value() {
40
- return i.value;
33
+ return r.value;
41
34
  }
42
35
  };
43
36
  }
44
37
  //#endregion
45
- export { r as fromSignal, i as toSignal };
38
+ export { n as fromSignal, r as toSignal };
46
39
 
47
40
  //# sourceMappingURL=ripple.js.map