@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
package/dist/pulse.cjs ADDED
@@ -0,0 +1 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./adapters/pulse.cjs");exports.fromPresence=e.fromPresence,exports.fromPulse=e.fromPulse;
@@ -0,0 +1,2 @@
1
+ export { fromPresence, fromPulse } from './adapters/pulse';
2
+ //# sourceMappingURL=pulse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pulse.d.ts","sourceRoot":"","sources":["../src/pulse.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC"}
package/dist/pulse.js ADDED
@@ -0,0 +1,2 @@
1
+ import { fromPresence as e, fromPulse as t } from "./adapters/pulse.js";
2
+ export { e as fromPresence, t as fromPulse };
@@ -0,0 +1 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./adapters/ripple.cjs");exports.fromSignal=e.fromSignal,exports.toSignal=e.toSignal;
@@ -0,0 +1,3 @@
1
+ export { fromSignal, toSignal } from './adapters/ripple';
2
+ export type { SignalBinding, ToSignalOptions } from './adapters/ripple';
3
+ //# sourceMappingURL=ripple.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ripple.d.ts","sourceRoot":"","sources":["../src/ripple.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AACzD,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC"}
package/dist/ripple.js ADDED
@@ -0,0 +1,2 @@
1
+ import { fromSignal as e, toSignal as t } from "./adapters/ripple.js";
2
+ export { e as fromSignal, t as toSignal };
package/dist/subject.cjs CHANGED
@@ -1,2 +1,2 @@
1
- const e=require("./_dev.cjs"),t=require("./_iterator.cjs"),n=require("./_pipe.cjs"),r=require("./_numeric.cjs");var i=()=>{};function a(){let t=new AbortController,n=new Set;function r(t){for(let r of[...n])try{t(r)}catch(t){e.error(`Subscriber threw during broadcast`,t)}}function a(e,r){let a=typeof e==`function`?{next:e}:e;if(t.signal.aborted||r?.aborted){try{a.complete?.()}catch{}return i}n.add(a);let o=()=>{n.delete(a),r&&r.removeEventListener(`abort`,o)};return r&&r.addEventListener(`abort`,o,{once:!0}),o}return{ac:t,broadcast:r,doSubscribe:a,subscribers:n}}function o(e,t,n,r){let a=typeof n==`function`?{next:n}:n;if(e.ac.signal.aborted||r?.aborted){try{a.complete?.()}catch{}return i}if(t(),e.ac.signal.aborted){try{a.complete?.()}catch{}return i}return e.doSubscribe(a,r)}function s(e){return()=>{e.ac.signal.aborted||(e.ac.abort(),e.broadcast(e=>e.complete?.()),e.subscribers.clear())}}function c(e){return t=>{e.ac.signal.aborted||(e.ac.abort(),e.broadcast(e=>e.error?.(t)),e.subscribers.clear())}}function l(){let e=a(),r=s(e),i={complete:r,get disposalSignal(){return e.ac.signal},dispose:r,get disposed(){return e.ac.signal.aborted},emit(t){e.ac.signal.aborted||e.broadcast(e=>e.next(t))},fail:c(e),pipe:n.makePipe(()=>i),subscribe(t,n){return e.doSubscribe(t,n)},[Symbol.asyncIterator](){return t.makeAsyncIterator(t=>e.doSubscribe(t))},[Symbol.dispose](){r()}};return i}function u(r){let i=a(),l=s(i),u=c(i),d=r,f={complete:l,get disposalSignal(){return i.ac.signal},dispose:l,get disposed(){return i.ac.signal.aborted},emit(e){i.ac.signal.aborted||(d=e,i.broadcast(t=>t.next(e)))},fail:u,pipe:n.makePipe(()=>f),subscribe(t,n){return o(i,()=>{let n=typeof t==`function`?{next:t}:t;try{n.next(d)}catch(t){e.error(`BehaviorSubject: subscriber threw during initial replay`,t)}},t,n)},[Symbol.asyncIterator](){return t.makeAsyncIterator(t=>o(i,()=>{try{t.next(d)}catch(t){e.error(`BehaviorSubject: subscriber threw during initial replay`,t)}},t))},[Symbol.dispose](){l()},get value(){return d}};return f}function d(i){let l=a(),u=s(l),d=c(l),{clamped:f,value:p}=r.clampPositiveInt(i),m=[];f&&e.warn(`createReplaySubject: bufferSize must be a finite integer >= 1, got ${i} — clamped to ${p}`);let h={get buffer(){return m},complete:u,get disposalSignal(){return l.ac.signal},dispose:u,get disposed(){return l.ac.signal.aborted},emit(e){l.ac.signal.aborted||(m.length>=p&&m.shift(),m.push(e),l.broadcast(t=>t.next(e)))},fail:d,pipe:n.makePipe(()=>h),subscribe(t,n){return o(l,()=>{let n=typeof t==`function`?{next:t}:t;for(let t of m)try{n.next(t)}catch(t){e.error(`ReplaySubject: subscriber threw during replay`,t)}},t,n)},[Symbol.asyncIterator](){return t.makeAsyncIterator(t=>o(l,()=>{for(let n of m)try{t.next(n)}catch(t){e.error(`ReplaySubject: subscriber threw during replay`,t)}},t))},[Symbol.dispose](){u()}};return h}exports.createBehaviorSubject=u,exports.createReplaySubject=d,exports.createSubject=l;
1
+ const e=require("./core.cjs"),t=require("./_numeric.cjs");function n(e){let n=e.replay??+(`initial`in e);return t.assertNonNegativeInteger(n,`Channel replay`),n}function r(t={}){let r=n(t),i=new AbortController,a=new Set,o=[];`initial`in t&&r>0&&o.push(t.initial);let s=e.stream(e=>{for(let t of o)e.next(t);if(i.signal.aborted){e.complete();return}return a.add(e),()=>a.delete(e)}),c=()=>{if(!i.signal.aborted){i.abort();for(let e of[...a])e.complete();a.clear()}};return{get disposalSignal(){return i.signal},dispose:c,get disposed(){return i.signal.aborted},send(e){if(!i.signal.aborted){r>0&&(o.length===r&&o.shift(),o.push(e));for(let t of[...a])t.next(e)}},stream:s,[Symbol.dispose]:c}}exports.createChannel=r;
2
2
  //# sourceMappingURL=subject.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"subject.cjs","names":[],"sources":["../src/subject.ts"],"sourcesContent":["import type { Flux, Observer, Unsubscribe } from './types';\n\nimport { error, warn } from './_dev';\nimport { makeAsyncIterator } from './_iterator';\nimport { clampPositiveInt } from './_numeric';\nimport { makePipe } from './_pipe';\n\nconst NOOP: Unsubscribe = () => {};\n\n/**\n * A `Subject` is both a `Flux` and a manual emission handle.\n * Calling `emit()` pushes a value to all active subscribers.\n *\n * A Subject is hot — all subscribers share the same emission sequence.\n * Subscribers that subscribe after an emission will NOT receive past values.\n * Use `BehaviorSubject` to replay the latest value to late subscribers.\n */\nexport interface Subject<T> extends Flux<T> {\n /** `true` after `dispose()` or `complete()` is called. */\n readonly disposed: boolean;\n /** Emit a complete signal to all subscribers and dispose the subject. */\n complete(): void;\n /** Push a value to all active subscribers. */\n emit(value: T): void;\n /** Push an error to all active subscribers and dispose the subject. */\n fail(err: unknown): void;\n}\n\n/**\n * A `BehaviorSubject` is a `Subject` that replays the latest value to\n * any new subscriber immediately on subscription.\n */\nexport interface BehaviorSubject<T> extends Subject<T> {\n /** The current (latest emitted) value. */\n readonly value: T;\n}\n\n/**\n * A `ReplaySubject` is a `Subject` that replays the last N emitted values\n * to any new subscriber immediately on subscription.\n */\nexport interface ReplaySubject<T> extends Subject<T> {\n /** Snapshot of the current replay buffer (up to `bufferSize` entries). */\n readonly buffer: readonly T[];\n}\n\n// ── Shared internals ──────────────────────────────────────────────────────────\n\ninterface SubjectCore<T> {\n ac: AbortController;\n broadcast(fn: (obs: Observer<T>) => void): void;\n doSubscribe(observerOrNext: Observer<T> | ((value: T) => void), signal?: AbortSignal): Unsubscribe;\n subscribers: Set<Observer<T>>;\n}\n\nfunction makeCore<T>(): SubjectCore<T> {\n const ac = new AbortController();\n const subscribers = new Set<Observer<T>>();\n\n function broadcast(fn: (obs: Observer<T>) => void): void {\n for (const obs of [...subscribers]) {\n try {\n fn(obs);\n } catch (err) {\n error('Subscriber threw during broadcast', err);\n }\n }\n }\n\n function doSubscribe(observerOrNext: Observer<T> | ((value: T) => void), signal?: AbortSignal): Unsubscribe {\n const observer: Observer<T> = typeof observerOrNext === 'function' ? { next: observerOrNext } : observerOrNext;\n\n if (ac.signal.aborted || signal?.aborted) {\n try {\n observer.complete?.();\n } catch {\n /* empty */\n }\n\n return NOOP;\n }\n\n subscribers.add(observer);\n\n const unsub = (): void => {\n subscribers.delete(observer);\n\n if (signal) signal.removeEventListener('abort', unsub);\n };\n\n if (signal) signal.addEventListener('abort', unsub, { once: true });\n\n return unsub;\n }\n\n return { ac, broadcast, doSubscribe, subscribers };\n}\n\n// Safely emit initial replay values; re-check disposed after sync replay.\nfunction replaySubscribe<T>(\n core: SubjectCore<T>,\n replay: () => void,\n observerOrNext: Observer<T> | ((value: T) => void),\n signal?: AbortSignal,\n): Unsubscribe {\n const observer: Observer<T> = typeof observerOrNext === 'function' ? { next: observerOrNext } : observerOrNext;\n\n if (core.ac.signal.aborted || signal?.aborted) {\n try {\n observer.complete?.();\n } catch {\n /* empty */\n }\n\n return NOOP;\n }\n\n replay();\n\n // Re-check: the synchronous replay may have triggered a dispose.\n if (core.ac.signal.aborted) {\n try {\n observer.complete?.();\n } catch {\n /* empty */\n }\n\n return NOOP;\n }\n\n return core.doSubscribe(observer, signal);\n}\n\n/**\n * Shared `dispose()` implementation for every `Subject` variant: aborts the core,\n * notifies all active subscribers with `complete()`, and clears the subscriber set.\n * Reused instead of being copy-pasted per factory.\n * @internal\n */\nfunction makeDispose<T>(core: SubjectCore<T>): () => void {\n return () => {\n if (core.ac.signal.aborted) return;\n\n core.ac.abort();\n core.broadcast((obs) => obs.complete?.());\n core.subscribers.clear();\n };\n}\n\n/**\n * Shared `fail()` implementation for every `Subject` variant: aborts the core,\n * notifies all active subscribers with `error()`, and clears the subscriber set.\n * Reused instead of being copy-pasted per factory.\n * @internal\n */\nfunction makeFail<T>(core: SubjectCore<T>): (err: unknown) => void {\n return (err) => {\n if (core.ac.signal.aborted) return;\n\n core.ac.abort();\n core.broadcast((obs) => obs.error?.(err));\n core.subscribers.clear();\n };\n}\n\n// ── createSubject ─────────────────────────────────────────────────────────────\n\n/**\n * Creates a new `Subject<T>`.\n *\n * @example\n * const events = createSubject<string>();\n * events.subscribe((s) => console.log(s));\n * events.emit('hello');\n * events.dispose();\n */\nexport function createSubject<T>(): Subject<T> {\n const core = makeCore<T>();\n const dispose = makeDispose(core);\n const fail = makeFail(core);\n\n const subject: Subject<T> = {\n complete: dispose,\n\n get disposalSignal(): AbortSignal {\n return core.ac.signal;\n },\n\n dispose,\n\n get disposed(): boolean {\n return core.ac.signal.aborted;\n },\n\n emit(value: T): void {\n if (core.ac.signal.aborted) return;\n\n core.broadcast((obs) => obs.next(value));\n },\n\n fail,\n\n pipe: makePipe(() => subject),\n\n subscribe(observerOrNext, signal) {\n return core.doSubscribe(observerOrNext, signal);\n },\n\n [Symbol.asyncIterator](): AsyncIterableIterator<T> {\n return makeAsyncIterator<T>((obs) => core.doSubscribe(obs));\n },\n\n [Symbol.dispose](): void {\n dispose();\n },\n };\n\n return subject;\n}\n\n// ── createBehaviorSubject ─────────────────────────────────────────────────────\n\n/**\n * Creates a new `BehaviorSubject<T>` with an initial value.\n * Late subscribers immediately receive the current value on subscribe.\n *\n * @example\n * const count = createBehaviorSubject(0);\n * count.subscribe((n) => console.log(n)); // logs 0 immediately\n * count.emit(1); // logs 1\n */\nexport function createBehaviorSubject<T>(initial: T): BehaviorSubject<T> {\n const core = makeCore<T>();\n const dispose = makeDispose(core);\n const fail = makeFail(core);\n let current = initial;\n\n const subject: BehaviorSubject<T> = {\n complete: dispose,\n\n get disposalSignal(): AbortSignal {\n return core.ac.signal;\n },\n\n dispose,\n\n get disposed(): boolean {\n return core.ac.signal.aborted;\n },\n\n emit(value: T): void {\n if (core.ac.signal.aborted) return;\n\n current = value;\n core.broadcast((obs) => obs.next(value));\n },\n\n fail,\n\n pipe: makePipe(() => subject),\n\n subscribe(observerOrNext, signal) {\n return replaySubscribe(\n core,\n () => {\n const observer: Observer<T> =\n typeof observerOrNext === 'function' ? { next: observerOrNext } : observerOrNext;\n\n try {\n observer.next(current);\n } catch (err) {\n error('BehaviorSubject: subscriber threw during initial replay', err);\n }\n },\n observerOrNext,\n signal,\n );\n },\n\n [Symbol.asyncIterator](): AsyncIterableIterator<T> {\n return makeAsyncIterator<T>((obs) =>\n replaySubscribe(\n core,\n () => {\n try {\n obs.next(current);\n } catch (err) {\n error('BehaviorSubject: subscriber threw during initial replay', err);\n }\n },\n obs,\n ),\n );\n },\n\n [Symbol.dispose](): void {\n dispose();\n },\n\n get value(): T {\n return current;\n },\n };\n\n return subject;\n}\n\n// ── createReplaySubject ───────────────────────────────────────────────────────\n\n/**\n * Creates a `ReplaySubject<T>` that buffers up to `bufferSize` values and\n * replays them in order to any new subscriber immediately on subscription.\n *\n * @example\n * const history = createReplaySubject<string>(3);\n * history.emit('a');\n * history.emit('b');\n * history.subscribe(console.log); // logs 'a', 'b' immediately\n */\nexport function createReplaySubject<T>(bufferSize: number): ReplaySubject<T> {\n const core = makeCore<T>();\n const dispose = makeDispose(core);\n const fail = makeFail(core);\n const { clamped, value: max } = clampPositiveInt(bufferSize);\n const buf: T[] = [];\n\n if (clamped) {\n warn(`createReplaySubject: bufferSize must be a finite integer >= 1, got ${bufferSize} — clamped to ${max}`);\n }\n\n const subject: ReplaySubject<T> = {\n get buffer(): readonly T[] {\n return buf;\n },\n\n complete: dispose,\n\n get disposalSignal(): AbortSignal {\n return core.ac.signal;\n },\n\n dispose,\n\n get disposed(): boolean {\n return core.ac.signal.aborted;\n },\n\n emit(value: T): void {\n if (core.ac.signal.aborted) return;\n\n if (buf.length >= max) buf.shift();\n\n buf.push(value);\n core.broadcast((obs) => obs.next(value));\n },\n\n fail,\n\n pipe: makePipe(() => subject),\n\n subscribe(observerOrNext, signal) {\n return replaySubscribe(\n core,\n () => {\n const observer: Observer<T> =\n typeof observerOrNext === 'function' ? { next: observerOrNext } : observerOrNext;\n\n for (const v of buf) {\n try {\n observer.next(v);\n } catch (err) {\n error('ReplaySubject: subscriber threw during replay', err);\n }\n }\n },\n observerOrNext,\n signal,\n );\n },\n\n [Symbol.asyncIterator](): AsyncIterableIterator<T> {\n return makeAsyncIterator<T>((obs) =>\n replaySubscribe(\n core,\n () => {\n for (const v of buf) {\n try {\n obs.next(v);\n } catch (err) {\n error('ReplaySubject: subscriber threw during replay', err);\n }\n }\n },\n obs,\n ),\n );\n },\n\n [Symbol.dispose](): void {\n dispose();\n },\n };\n\n return subject;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"subject.cjs","names":[],"sources":["../src/subject.ts"],"sourcesContent":["import type { Sink, Stream } from './types';\n\nimport { assertNonNegativeInteger } from './_numeric';\nimport { stream } from './core';\n\nexport type ChannelOptions<T> = {\n initial?: T;\n replay?: number;\n};\n\nexport type Channel<T> = {\n [Symbol.dispose](): void;\n readonly disposalSignal: AbortSignal;\n dispose(): void;\n readonly disposed: boolean;\n send(value: T): void;\n readonly stream: Stream<T>;\n};\n\nfunction replayCapacity<T>(options: ChannelOptions<T>): number {\n const capacity = options.replay ?? ('initial' in options ? 1 : 0);\n\n assertNonNegativeInteger(capacity, 'Channel replay');\n\n return capacity;\n}\n\n/** Channels own mutable multicast state; disposal is their only terminal event. */\nexport function createChannel<T>(options: ChannelOptions<T> = {}): Channel<T> {\n const capacity = replayCapacity(options);\n const controller = new AbortController();\n const listeners = new Set<Sink<T>>();\n const replay: T[] = [];\n\n if ('initial' in options && capacity > 0) replay.push(options.initial as T);\n\n const source = stream<T>((sink) => {\n for (const value of replay) sink.next(value);\n\n if (controller.signal.aborted) {\n sink.complete();\n\n return;\n }\n\n listeners.add(sink);\n\n return () => listeners.delete(sink);\n });\n\n const dispose = (): void => {\n if (controller.signal.aborted) return;\n\n controller.abort();\n\n for (const listener of [...listeners]) listener.complete();\n\n listeners.clear();\n };\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 send(value: T): void {\n if (controller.signal.aborted) return;\n\n if (capacity > 0) {\n if (replay.length === capacity) replay.shift();\n\n replay.push(value);\n }\n\n for (const listener of [...listeners]) listener.next(value);\n },\n stream: source,\n [Symbol.dispose]: dispose,\n };\n}\n"],"mappings":"0DAmBA,SAAS,EAAkB,EAAoC,CAC7D,IAAM,EAAW,EAAQ,QAAW,cAAa,GAIjD,OAFA,EAAA,yBAAyB,EAAU,gBAAgB,EAE5C,CACT,CAGA,SAAgB,EAAiB,EAA6B,CAAC,EAAe,CAC5E,IAAM,EAAW,EAAe,CAAO,EACjC,EAAa,IAAI,gBACjB,EAAY,IAAI,IAChB,EAAc,CAAC,EAEjB,YAAa,GAAW,EAAW,GAAG,EAAO,KAAK,EAAQ,OAAY,EAE1E,IAAM,EAAS,EAAA,OAAW,GAAS,CACjC,IAAK,IAAM,KAAS,EAAQ,EAAK,KAAK,CAAK,EAE3C,GAAI,EAAW,OAAO,QAAS,CAC7B,EAAK,SAAS,EAEd,MACF,CAIA,OAFA,EAAU,IAAI,CAAI,MAEL,EAAU,OAAO,CAAI,CACpC,CAAC,EAEK,MAAsB,CACtB,MAAW,OAAO,QAEtB,GAAW,MAAM,EAEjB,IAAK,IAAM,IAAY,CAAC,GAAG,CAAS,EAAG,EAAS,SAAS,EAEzD,EAAU,MAAM,CAJC,CAKnB,EAEA,MAAO,CACL,IAAI,gBAA8B,CAChC,OAAO,EAAW,MACpB,EACA,UACA,IAAI,UAAoB,CACtB,OAAO,EAAW,OAAO,OAC3B,EACA,KAAK,EAAgB,CACf,MAAW,OAAO,QAEtB,CAAI,EAAW,IACT,EAAO,SAAW,GAAU,EAAO,MAAM,EAE7C,EAAO,KAAK,CAAK,GAGnB,IAAK,IAAM,IAAY,CAAC,GAAG,CAAS,EAAG,EAAS,KAAK,CAAK,CAF1D,CAGF,EACA,OAAQ,GACP,OAAO,SAAU,CACpB,CACF"}
package/dist/subject.d.ts CHANGED
@@ -1,67 +1,16 @@
1
- import type { Flux } from './types';
2
- /**
3
- * A `Subject` is both a `Flux` and a manual emission handle.
4
- * Calling `emit()` pushes a value to all active subscribers.
5
- *
6
- * A Subject is hot — all subscribers share the same emission sequence.
7
- * Subscribers that subscribe after an emission will NOT receive past values.
8
- * Use `BehaviorSubject` to replay the latest value to late subscribers.
9
- */
10
- export interface Subject<T> extends Flux<T> {
11
- /** `true` after `dispose()` or `complete()` is called. */
1
+ import type { Stream } from './types';
2
+ export type ChannelOptions<T> = {
3
+ initial?: T;
4
+ replay?: number;
5
+ };
6
+ export type Channel<T> = {
7
+ [Symbol.dispose](): void;
8
+ readonly disposalSignal: AbortSignal;
9
+ dispose(): void;
12
10
  readonly disposed: boolean;
13
- /** Emit a complete signal to all subscribers and dispose the subject. */
14
- complete(): void;
15
- /** Push a value to all active subscribers. */
16
- emit(value: T): void;
17
- /** Push an error to all active subscribers and dispose the subject. */
18
- fail(err: unknown): void;
19
- }
20
- /**
21
- * A `BehaviorSubject` is a `Subject` that replays the latest value to
22
- * any new subscriber immediately on subscription.
23
- */
24
- export interface BehaviorSubject<T> extends Subject<T> {
25
- /** The current (latest emitted) value. */
26
- readonly value: T;
27
- }
28
- /**
29
- * A `ReplaySubject` is a `Subject` that replays the last N emitted values
30
- * to any new subscriber immediately on subscription.
31
- */
32
- export interface ReplaySubject<T> extends Subject<T> {
33
- /** Snapshot of the current replay buffer (up to `bufferSize` entries). */
34
- readonly buffer: readonly T[];
35
- }
36
- /**
37
- * Creates a new `Subject<T>`.
38
- *
39
- * @example
40
- * const events = createSubject<string>();
41
- * events.subscribe((s) => console.log(s));
42
- * events.emit('hello');
43
- * events.dispose();
44
- */
45
- export declare function createSubject<T>(): Subject<T>;
46
- /**
47
- * Creates a new `BehaviorSubject<T>` with an initial value.
48
- * Late subscribers immediately receive the current value on subscribe.
49
- *
50
- * @example
51
- * const count = createBehaviorSubject(0);
52
- * count.subscribe((n) => console.log(n)); // logs 0 immediately
53
- * count.emit(1); // logs 1
54
- */
55
- export declare function createBehaviorSubject<T>(initial: T): BehaviorSubject<T>;
56
- /**
57
- * Creates a `ReplaySubject<T>` that buffers up to `bufferSize` values and
58
- * replays them in order to any new subscriber immediately on subscription.
59
- *
60
- * @example
61
- * const history = createReplaySubject<string>(3);
62
- * history.emit('a');
63
- * history.emit('b');
64
- * history.subscribe(console.log); // logs 'a', 'b' immediately
65
- */
66
- export declare function createReplaySubject<T>(bufferSize: number): ReplaySubject<T>;
11
+ send(value: T): void;
12
+ readonly stream: Stream<T>;
13
+ };
14
+ /** Channels own mutable multicast state; disposal is their only terminal event. */
15
+ export declare function createChannel<T>(options?: ChannelOptions<T>): Channel<T>;
67
16
  //# sourceMappingURL=subject.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"subject.d.ts","sourceRoot":"","sources":["../src/subject.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAyB,MAAM,SAAS,CAAC;AAS3D;;;;;;;GAOG;AACH,MAAM,WAAW,OAAO,CAAC,CAAC,CAAE,SAAQ,IAAI,CAAC,CAAC,CAAC;IACzC,0DAA0D;IAC1D,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,yEAAyE;IACzE,QAAQ,IAAI,IAAI,CAAC;IACjB,8CAA8C;IAC9C,IAAI,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC;IACrB,uEAAuE;IACvE,IAAI,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAAC;CAC1B;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe,CAAC,CAAC,CAAE,SAAQ,OAAO,CAAC,CAAC,CAAC;IACpD,0CAA0C;IAC1C,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;CACnB;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa,CAAC,CAAC,CAAE,SAAQ,OAAO,CAAC,CAAC,CAAC;IAClD,0EAA0E;IAC1E,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE,CAAC;CAC/B;AA2HD;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CA0C7C;AAID;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,CA0EvE;AAID;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,GAAG,aAAa,CAAC,CAAC,CAAC,CAqF3E"}
1
+ {"version":3,"file":"subject.d.ts","sourceRoot":"","sources":["../src/subject.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAQ,MAAM,EAAE,MAAM,SAAS,CAAC;AAK5C,MAAM,MAAM,cAAc,CAAC,CAAC,IAAI;IAC9B,OAAO,CAAC,EAAE,CAAC,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,OAAO,CAAC,CAAC,IAAI;IACvB,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,IAAI,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;CAC5B,CAAC;AAUF,mFAAmF;AACnF,wBAAgB,aAAa,CAAC,CAAC,EAAE,OAAO,GAAE,cAAc,CAAC,CAAC,CAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAsD5E"}
package/dist/subject.js CHANGED
@@ -1,181 +1,46 @@
1
- import { error as e, warn as t } from "./_dev.js";
2
- import { makeAsyncIterator as n } from "./_iterator.js";
3
- import { makePipe as r } from "./_pipe.js";
4
- import { clampPositiveInt as i } from "./_numeric.js";
1
+ import { stream as e } from "./core.js";
2
+ import { assertNonNegativeInteger as t } from "./_numeric.js";
5
3
  //#region src/subject.ts
6
- var a = () => {};
7
- function o() {
8
- let t = new AbortController(), n = /* @__PURE__ */ new Set();
9
- function r(t) {
10
- for (let r of [...n]) try {
11
- t(r);
12
- } catch (t) {
13
- e("Subscriber threw during broadcast", t);
14
- }
15
- }
16
- function i(e, r) {
17
- let i = typeof e == "function" ? { next: e } : e;
18
- if (t.signal.aborted || r?.aborted) {
19
- try {
20
- i.complete?.();
21
- } catch {}
22
- return a;
23
- }
24
- n.add(i);
25
- let o = () => {
26
- n.delete(i), r && r.removeEventListener("abort", o);
27
- };
28
- return r && r.addEventListener("abort", o, { once: !0 }), o;
29
- }
30
- return {
31
- ac: t,
32
- broadcast: r,
33
- doSubscribe: i,
34
- subscribers: n
35
- };
36
- }
37
- function s(e, t, n, r) {
38
- let i = typeof n == "function" ? { next: n } : n;
39
- if (e.ac.signal.aborted || r?.aborted) {
40
- try {
41
- i.complete?.();
42
- } catch {}
43
- return a;
44
- }
45
- if (t(), e.ac.signal.aborted) {
46
- try {
47
- i.complete?.();
48
- } catch {}
49
- return a;
50
- }
51
- return e.doSubscribe(i, r);
52
- }
53
- function c(e) {
54
- return () => {
55
- e.ac.signal.aborted || (e.ac.abort(), e.broadcast((e) => e.complete?.()), e.subscribers.clear());
56
- };
57
- }
58
- function l(e) {
59
- return (t) => {
60
- e.ac.signal.aborted || (e.ac.abort(), e.broadcast((e) => e.error?.(t)), e.subscribers.clear());
61
- };
4
+ function n(e) {
5
+ let n = e.replay ?? +("initial" in e);
6
+ return t(n, "Channel replay"), n;
62
7
  }
63
- function u() {
64
- let e = o(), t = c(e), i = {
65
- complete: t,
66
- get disposalSignal() {
67
- return e.ac.signal;
68
- },
69
- dispose: t,
70
- get disposed() {
71
- return e.ac.signal.aborted;
72
- },
73
- emit(t) {
74
- e.ac.signal.aborted || e.broadcast((e) => e.next(t));
75
- },
76
- fail: l(e),
77
- pipe: r(() => i),
78
- subscribe(t, n) {
79
- return e.doSubscribe(t, n);
80
- },
81
- [Symbol.asyncIterator]() {
82
- return n((t) => e.doSubscribe(t));
83
- },
84
- [Symbol.dispose]() {
85
- t();
8
+ function r(t = {}) {
9
+ let r = n(t), i = new AbortController(), a = /* @__PURE__ */ new Set(), o = [];
10
+ "initial" in t && r > 0 && o.push(t.initial);
11
+ let s = e((e) => {
12
+ for (let t of o) e.next(t);
13
+ if (i.signal.aborted) {
14
+ e.complete();
15
+ return;
86
16
  }
87
- };
88
- return i;
89
- }
90
- function d(t) {
91
- let i = o(), a = c(i), u = l(i), d = t, f = {
92
- complete: a,
93
- get disposalSignal() {
94
- return i.ac.signal;
95
- },
96
- dispose: a,
97
- get disposed() {
98
- return i.ac.signal.aborted;
99
- },
100
- emit(e) {
101
- i.ac.signal.aborted || (d = e, i.broadcast((t) => t.next(e)));
102
- },
103
- fail: u,
104
- pipe: r(() => f),
105
- subscribe(t, n) {
106
- return s(i, () => {
107
- let n = typeof t == "function" ? { next: t } : t;
108
- try {
109
- n.next(d);
110
- } catch (t) {
111
- e("BehaviorSubject: subscriber threw during initial replay", t);
112
- }
113
- }, t, n);
114
- },
115
- [Symbol.asyncIterator]() {
116
- return n((t) => s(i, () => {
117
- try {
118
- t.next(d);
119
- } catch (t) {
120
- e("BehaviorSubject: subscriber threw during initial replay", t);
121
- }
122
- }, t));
123
- },
124
- [Symbol.dispose]() {
125
- a();
126
- },
127
- get value() {
128
- return d;
17
+ return a.add(e), () => a.delete(e);
18
+ }), c = () => {
19
+ if (!i.signal.aborted) {
20
+ i.abort();
21
+ for (let e of [...a]) e.complete();
22
+ a.clear();
129
23
  }
130
24
  };
131
- return f;
132
- }
133
- function f(a) {
134
- let u = o(), d = c(u), f = l(u), { clamped: p, value: m } = i(a), h = [];
135
- p && t(`createReplaySubject: bufferSize must be a finite integer >= 1, got ${a} — clamped to ${m}`);
136
- let g = {
137
- get buffer() {
138
- return h;
139
- },
140
- complete: d,
25
+ return {
141
26
  get disposalSignal() {
142
- return u.ac.signal;
27
+ return i.signal;
143
28
  },
144
- dispose: d,
29
+ dispose: c,
145
30
  get disposed() {
146
- return u.ac.signal.aborted;
147
- },
148
- emit(e) {
149
- u.ac.signal.aborted || (h.length >= m && h.shift(), h.push(e), u.broadcast((t) => t.next(e)));
31
+ return i.signal.aborted;
150
32
  },
151
- fail: f,
152
- pipe: r(() => g),
153
- subscribe(t, n) {
154
- return s(u, () => {
155
- let n = typeof t == "function" ? { next: t } : t;
156
- for (let t of h) try {
157
- n.next(t);
158
- } catch (t) {
159
- e("ReplaySubject: subscriber threw during replay", t);
160
- }
161
- }, t, n);
33
+ send(e) {
34
+ if (!i.signal.aborted) {
35
+ r > 0 && (o.length === r && o.shift(), o.push(e));
36
+ for (let t of [...a]) t.next(e);
37
+ }
162
38
  },
163
- [Symbol.asyncIterator]() {
164
- return n((t) => s(u, () => {
165
- for (let n of h) try {
166
- t.next(n);
167
- } catch (t) {
168
- e("ReplaySubject: subscriber threw during replay", t);
169
- }
170
- }, t));
171
- },
172
- [Symbol.dispose]() {
173
- d();
174
- }
39
+ stream: s,
40
+ [Symbol.dispose]: c
175
41
  };
176
- return g;
177
42
  }
178
43
  //#endregion
179
- export { d as createBehaviorSubject, f as createReplaySubject, u as createSubject };
44
+ export { r as createChannel };
180
45
 
181
46
  //# sourceMappingURL=subject.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"subject.js","names":[],"sources":["../src/subject.ts"],"sourcesContent":["import type { Flux, Observer, Unsubscribe } from './types';\n\nimport { error, warn } from './_dev';\nimport { makeAsyncIterator } from './_iterator';\nimport { clampPositiveInt } from './_numeric';\nimport { makePipe } from './_pipe';\n\nconst NOOP: Unsubscribe = () => {};\n\n/**\n * A `Subject` is both a `Flux` and a manual emission handle.\n * Calling `emit()` pushes a value to all active subscribers.\n *\n * A Subject is hot — all subscribers share the same emission sequence.\n * Subscribers that subscribe after an emission will NOT receive past values.\n * Use `BehaviorSubject` to replay the latest value to late subscribers.\n */\nexport interface Subject<T> extends Flux<T> {\n /** `true` after `dispose()` or `complete()` is called. */\n readonly disposed: boolean;\n /** Emit a complete signal to all subscribers and dispose the subject. */\n complete(): void;\n /** Push a value to all active subscribers. */\n emit(value: T): void;\n /** Push an error to all active subscribers and dispose the subject. */\n fail(err: unknown): void;\n}\n\n/**\n * A `BehaviorSubject` is a `Subject` that replays the latest value to\n * any new subscriber immediately on subscription.\n */\nexport interface BehaviorSubject<T> extends Subject<T> {\n /** The current (latest emitted) value. */\n readonly value: T;\n}\n\n/**\n * A `ReplaySubject` is a `Subject` that replays the last N emitted values\n * to any new subscriber immediately on subscription.\n */\nexport interface ReplaySubject<T> extends Subject<T> {\n /** Snapshot of the current replay buffer (up to `bufferSize` entries). */\n readonly buffer: readonly T[];\n}\n\n// ── Shared internals ──────────────────────────────────────────────────────────\n\ninterface SubjectCore<T> {\n ac: AbortController;\n broadcast(fn: (obs: Observer<T>) => void): void;\n doSubscribe(observerOrNext: Observer<T> | ((value: T) => void), signal?: AbortSignal): Unsubscribe;\n subscribers: Set<Observer<T>>;\n}\n\nfunction makeCore<T>(): SubjectCore<T> {\n const ac = new AbortController();\n const subscribers = new Set<Observer<T>>();\n\n function broadcast(fn: (obs: Observer<T>) => void): void {\n for (const obs of [...subscribers]) {\n try {\n fn(obs);\n } catch (err) {\n error('Subscriber threw during broadcast', err);\n }\n }\n }\n\n function doSubscribe(observerOrNext: Observer<T> | ((value: T) => void), signal?: AbortSignal): Unsubscribe {\n const observer: Observer<T> = typeof observerOrNext === 'function' ? { next: observerOrNext } : observerOrNext;\n\n if (ac.signal.aborted || signal?.aborted) {\n try {\n observer.complete?.();\n } catch {\n /* empty */\n }\n\n return NOOP;\n }\n\n subscribers.add(observer);\n\n const unsub = (): void => {\n subscribers.delete(observer);\n\n if (signal) signal.removeEventListener('abort', unsub);\n };\n\n if (signal) signal.addEventListener('abort', unsub, { once: true });\n\n return unsub;\n }\n\n return { ac, broadcast, doSubscribe, subscribers };\n}\n\n// Safely emit initial replay values; re-check disposed after sync replay.\nfunction replaySubscribe<T>(\n core: SubjectCore<T>,\n replay: () => void,\n observerOrNext: Observer<T> | ((value: T) => void),\n signal?: AbortSignal,\n): Unsubscribe {\n const observer: Observer<T> = typeof observerOrNext === 'function' ? { next: observerOrNext } : observerOrNext;\n\n if (core.ac.signal.aborted || signal?.aborted) {\n try {\n observer.complete?.();\n } catch {\n /* empty */\n }\n\n return NOOP;\n }\n\n replay();\n\n // Re-check: the synchronous replay may have triggered a dispose.\n if (core.ac.signal.aborted) {\n try {\n observer.complete?.();\n } catch {\n /* empty */\n }\n\n return NOOP;\n }\n\n return core.doSubscribe(observer, signal);\n}\n\n/**\n * Shared `dispose()` implementation for every `Subject` variant: aborts the core,\n * notifies all active subscribers with `complete()`, and clears the subscriber set.\n * Reused instead of being copy-pasted per factory.\n * @internal\n */\nfunction makeDispose<T>(core: SubjectCore<T>): () => void {\n return () => {\n if (core.ac.signal.aborted) return;\n\n core.ac.abort();\n core.broadcast((obs) => obs.complete?.());\n core.subscribers.clear();\n };\n}\n\n/**\n * Shared `fail()` implementation for every `Subject` variant: aborts the core,\n * notifies all active subscribers with `error()`, and clears the subscriber set.\n * Reused instead of being copy-pasted per factory.\n * @internal\n */\nfunction makeFail<T>(core: SubjectCore<T>): (err: unknown) => void {\n return (err) => {\n if (core.ac.signal.aborted) return;\n\n core.ac.abort();\n core.broadcast((obs) => obs.error?.(err));\n core.subscribers.clear();\n };\n}\n\n// ── createSubject ─────────────────────────────────────────────────────────────\n\n/**\n * Creates a new `Subject<T>`.\n *\n * @example\n * const events = createSubject<string>();\n * events.subscribe((s) => console.log(s));\n * events.emit('hello');\n * events.dispose();\n */\nexport function createSubject<T>(): Subject<T> {\n const core = makeCore<T>();\n const dispose = makeDispose(core);\n const fail = makeFail(core);\n\n const subject: Subject<T> = {\n complete: dispose,\n\n get disposalSignal(): AbortSignal {\n return core.ac.signal;\n },\n\n dispose,\n\n get disposed(): boolean {\n return core.ac.signal.aborted;\n },\n\n emit(value: T): void {\n if (core.ac.signal.aborted) return;\n\n core.broadcast((obs) => obs.next(value));\n },\n\n fail,\n\n pipe: makePipe(() => subject),\n\n subscribe(observerOrNext, signal) {\n return core.doSubscribe(observerOrNext, signal);\n },\n\n [Symbol.asyncIterator](): AsyncIterableIterator<T> {\n return makeAsyncIterator<T>((obs) => core.doSubscribe(obs));\n },\n\n [Symbol.dispose](): void {\n dispose();\n },\n };\n\n return subject;\n}\n\n// ── createBehaviorSubject ─────────────────────────────────────────────────────\n\n/**\n * Creates a new `BehaviorSubject<T>` with an initial value.\n * Late subscribers immediately receive the current value on subscribe.\n *\n * @example\n * const count = createBehaviorSubject(0);\n * count.subscribe((n) => console.log(n)); // logs 0 immediately\n * count.emit(1); // logs 1\n */\nexport function createBehaviorSubject<T>(initial: T): BehaviorSubject<T> {\n const core = makeCore<T>();\n const dispose = makeDispose(core);\n const fail = makeFail(core);\n let current = initial;\n\n const subject: BehaviorSubject<T> = {\n complete: dispose,\n\n get disposalSignal(): AbortSignal {\n return core.ac.signal;\n },\n\n dispose,\n\n get disposed(): boolean {\n return core.ac.signal.aborted;\n },\n\n emit(value: T): void {\n if (core.ac.signal.aborted) return;\n\n current = value;\n core.broadcast((obs) => obs.next(value));\n },\n\n fail,\n\n pipe: makePipe(() => subject),\n\n subscribe(observerOrNext, signal) {\n return replaySubscribe(\n core,\n () => {\n const observer: Observer<T> =\n typeof observerOrNext === 'function' ? { next: observerOrNext } : observerOrNext;\n\n try {\n observer.next(current);\n } catch (err) {\n error('BehaviorSubject: subscriber threw during initial replay', err);\n }\n },\n observerOrNext,\n signal,\n );\n },\n\n [Symbol.asyncIterator](): AsyncIterableIterator<T> {\n return makeAsyncIterator<T>((obs) =>\n replaySubscribe(\n core,\n () => {\n try {\n obs.next(current);\n } catch (err) {\n error('BehaviorSubject: subscriber threw during initial replay', err);\n }\n },\n obs,\n ),\n );\n },\n\n [Symbol.dispose](): void {\n dispose();\n },\n\n get value(): T {\n return current;\n },\n };\n\n return subject;\n}\n\n// ── createReplaySubject ───────────────────────────────────────────────────────\n\n/**\n * Creates a `ReplaySubject<T>` that buffers up to `bufferSize` values and\n * replays them in order to any new subscriber immediately on subscription.\n *\n * @example\n * const history = createReplaySubject<string>(3);\n * history.emit('a');\n * history.emit('b');\n * history.subscribe(console.log); // logs 'a', 'b' immediately\n */\nexport function createReplaySubject<T>(bufferSize: number): ReplaySubject<T> {\n const core = makeCore<T>();\n const dispose = makeDispose(core);\n const fail = makeFail(core);\n const { clamped, value: max } = clampPositiveInt(bufferSize);\n const buf: T[] = [];\n\n if (clamped) {\n warn(`createReplaySubject: bufferSize must be a finite integer >= 1, got ${bufferSize} — clamped to ${max}`);\n }\n\n const subject: ReplaySubject<T> = {\n get buffer(): readonly T[] {\n return buf;\n },\n\n complete: dispose,\n\n get disposalSignal(): AbortSignal {\n return core.ac.signal;\n },\n\n dispose,\n\n get disposed(): boolean {\n return core.ac.signal.aborted;\n },\n\n emit(value: T): void {\n if (core.ac.signal.aborted) return;\n\n if (buf.length >= max) buf.shift();\n\n buf.push(value);\n core.broadcast((obs) => obs.next(value));\n },\n\n fail,\n\n pipe: makePipe(() => subject),\n\n subscribe(observerOrNext, signal) {\n return replaySubscribe(\n core,\n () => {\n const observer: Observer<T> =\n typeof observerOrNext === 'function' ? { next: observerOrNext } : observerOrNext;\n\n for (const v of buf) {\n try {\n observer.next(v);\n } catch (err) {\n error('ReplaySubject: subscriber threw during replay', err);\n }\n }\n },\n observerOrNext,\n signal,\n );\n },\n\n [Symbol.asyncIterator](): AsyncIterableIterator<T> {\n return makeAsyncIterator<T>((obs) =>\n replaySubscribe(\n core,\n () => {\n for (const v of buf) {\n try {\n obs.next(v);\n } catch (err) {\n error('ReplaySubject: subscriber threw during replay', err);\n }\n }\n },\n obs,\n ),\n );\n },\n\n [Symbol.dispose](): void {\n dispose();\n },\n };\n\n return subject;\n}\n"],"mappings":";;;;;AAOA,IAAM,UAA0B,CAAC;AAgDjC,SAAS,IAA8B;CACrC,IAAM,IAAK,IAAI,gBAAgB,GACzB,oBAAc,IAAI,IAAiB;CAEzC,SAAS,EAAU,GAAsC;EACvD,KAAK,IAAM,KAAO,CAAC,GAAG,CAAW,GAC/B,IAAI;GACF,EAAG,CAAG;EACR,SAAS,GAAK;GACZ,EAAM,qCAAqC,CAAG;EAChD;CAEJ;CAEA,SAAS,EAAY,GAAoD,GAAmC;EAC1G,IAAM,IAAwB,OAAO,KAAmB,aAAa,EAAE,MAAM,EAAe,IAAI;EAEhG,IAAI,EAAG,OAAO,WAAW,GAAQ,SAAS;GACxC,IAAI;IACF,EAAS,WAAW;GACtB,QAAQ,CAER;GAEA,OAAO;EACT;EAEA,EAAY,IAAI,CAAQ;EAExB,IAAM,UAAoB;GAGxB,AAFA,EAAY,OAAO,CAAQ,GAEvB,KAAQ,EAAO,oBAAoB,SAAS,CAAK;EACvD;EAIA,OAFI,KAAQ,EAAO,iBAAiB,SAAS,GAAO,EAAE,MAAM,GAAK,CAAC,GAE3D;CACT;CAEA,OAAO;EAAE;EAAI;EAAW;EAAa;CAAY;AACnD;AAGA,SAAS,EACP,GACA,GACA,GACA,GACa;CACb,IAAM,IAAwB,OAAO,KAAmB,aAAa,EAAE,MAAM,EAAe,IAAI;CAEhG,IAAI,EAAK,GAAG,OAAO,WAAW,GAAQ,SAAS;EAC7C,IAAI;GACF,EAAS,WAAW;EACtB,QAAQ,CAER;EAEA,OAAO;CACT;CAKA,IAHA,EAAO,GAGH,EAAK,GAAG,OAAO,SAAS;EAC1B,IAAI;GACF,EAAS,WAAW;EACtB,QAAQ,CAER;EAEA,OAAO;CACT;CAEA,OAAO,EAAK,YAAY,GAAU,CAAM;AAC1C;AAQA,SAAS,EAAe,GAAkC;CACxD,aAAa;EACP,EAAK,GAAG,OAAO,YAEnB,EAAK,GAAG,MAAM,GACd,EAAK,WAAW,MAAQ,EAAI,WAAW,CAAC,GACxC,EAAK,YAAY,MAAM;CACzB;AACF;AAQA,SAAS,EAAY,GAA8C;CACjE,QAAQ,MAAQ;EACV,EAAK,GAAG,OAAO,YAEnB,EAAK,GAAG,MAAM,GACd,EAAK,WAAW,MAAQ,EAAI,QAAQ,CAAG,CAAC,GACxC,EAAK,YAAY,MAAM;CACzB;AACF;AAaA,SAAgB,IAA+B;CAC7C,IAAM,IAAO,EAAY,GACnB,IAAU,EAAY,CAAI,GAG1B,IAAsB;EAC1B,UAAU;EAEV,IAAI,iBAA8B;GAChC,OAAO,EAAK,GAAG;EACjB;EAEA;EAEA,IAAI,WAAoB;GACtB,OAAO,EAAK,GAAG,OAAO;EACxB;EAEA,KAAK,GAAgB;GACf,EAAK,GAAG,OAAO,WAEnB,EAAK,WAAW,MAAQ,EAAI,KAAK,CAAK,CAAC;EACzC;EAEA,MArBW,EAAS,CAqBpB;EAEA,MAAM,QAAe,CAAO;EAE5B,UAAU,GAAgB,GAAQ;GAChC,OAAO,EAAK,YAAY,GAAgB,CAAM;EAChD;EAEA,CAAC,OAAO,iBAA2C;GACjD,OAAO,GAAsB,MAAQ,EAAK,YAAY,CAAG,CAAC;EAC5D;EAEA,CAAC,OAAO,WAAiB;GACvB,EAAQ;EACV;CACF;CAEA,OAAO;AACT;AAaA,SAAgB,EAAyB,GAAgC;CACvE,IAAM,IAAO,EAAY,GACnB,IAAU,EAAY,CAAI,GAC1B,IAAO,EAAS,CAAI,GACtB,IAAU,GAER,IAA8B;EAClC,UAAU;EAEV,IAAI,iBAA8B;GAChC,OAAO,EAAK,GAAG;EACjB;EAEA;EAEA,IAAI,WAAoB;GACtB,OAAO,EAAK,GAAG,OAAO;EACxB;EAEA,KAAK,GAAgB;GACf,EAAK,GAAG,OAAO,YAEnB,IAAU,GACV,EAAK,WAAW,MAAQ,EAAI,KAAK,CAAK,CAAC;EACzC;EAEA;EAEA,MAAM,QAAe,CAAO;EAE5B,UAAU,GAAgB,GAAQ;GAChC,OAAO,EACL,SACM;IACJ,IAAM,IACJ,OAAO,KAAmB,aAAa,EAAE,MAAM,EAAe,IAAI;IAEpE,IAAI;KACF,EAAS,KAAK,CAAO;IACvB,SAAS,GAAK;KACZ,EAAM,2DAA2D,CAAG;IACtE;GACF,GACA,GACA,CACF;EACF;EAEA,CAAC,OAAO,iBAA2C;GACjD,OAAO,GAAsB,MAC3B,EACE,SACM;IACJ,IAAI;KACF,EAAI,KAAK,CAAO;IAClB,SAAS,GAAK;KACZ,EAAM,2DAA2D,CAAG;IACtE;GACF,GACA,CACF,CACF;EACF;EAEA,CAAC,OAAO,WAAiB;GACvB,EAAQ;EACV;EAEA,IAAI,QAAW;GACb,OAAO;EACT;CACF;CAEA,OAAO;AACT;AAcA,SAAgB,EAAuB,GAAsC;CAC3E,IAAM,IAAO,EAAY,GACnB,IAAU,EAAY,CAAI,GAC1B,IAAO,EAAS,CAAI,GACpB,EAAE,YAAS,OAAO,MAAQ,EAAiB,CAAU,GACrD,IAAW,CAAC;CAElB,AAAI,KACF,EAAK,sEAAsE,EAAW,gBAAgB,GAAK;CAG7G,IAAM,IAA4B;EAChC,IAAI,SAAuB;GACzB,OAAO;EACT;EAEA,UAAU;EAEV,IAAI,iBAA8B;GAChC,OAAO,EAAK,GAAG;EACjB;EAEA;EAEA,IAAI,WAAoB;GACtB,OAAO,EAAK,GAAG,OAAO;EACxB;EAEA,KAAK,GAAgB;GACf,EAAK,GAAG,OAAO,YAEf,EAAI,UAAU,KAAK,EAAI,MAAM,GAEjC,EAAI,KAAK,CAAK,GACd,EAAK,WAAW,MAAQ,EAAI,KAAK,CAAK,CAAC;EACzC;EAEA;EAEA,MAAM,QAAe,CAAO;EAE5B,UAAU,GAAgB,GAAQ;GAChC,OAAO,EACL,SACM;IACJ,IAAM,IACJ,OAAO,KAAmB,aAAa,EAAE,MAAM,EAAe,IAAI;IAEpE,KAAK,IAAM,KAAK,GACd,IAAI;KACF,EAAS,KAAK,CAAC;IACjB,SAAS,GAAK;KACZ,EAAM,iDAAiD,CAAG;IAC5D;GAEJ,GACA,GACA,CACF;EACF;EAEA,CAAC,OAAO,iBAA2C;GACjD,OAAO,GAAsB,MAC3B,EACE,SACM;IACJ,KAAK,IAAM,KAAK,GACd,IAAI;KACF,EAAI,KAAK,CAAC;IACZ,SAAS,GAAK;KACZ,EAAM,iDAAiD,CAAG;IAC5D;GAEJ,GACA,CACF,CACF;EACF;EAEA,CAAC,OAAO,WAAiB;GACvB,EAAQ;EACV;CACF;CAEA,OAAO;AACT"}
1
+ {"version":3,"file":"subject.js","names":[],"sources":["../src/subject.ts"],"sourcesContent":["import type { Sink, Stream } from './types';\n\nimport { assertNonNegativeInteger } from './_numeric';\nimport { stream } from './core';\n\nexport type ChannelOptions<T> = {\n initial?: T;\n replay?: number;\n};\n\nexport type Channel<T> = {\n [Symbol.dispose](): void;\n readonly disposalSignal: AbortSignal;\n dispose(): void;\n readonly disposed: boolean;\n send(value: T): void;\n readonly stream: Stream<T>;\n};\n\nfunction replayCapacity<T>(options: ChannelOptions<T>): number {\n const capacity = options.replay ?? ('initial' in options ? 1 : 0);\n\n assertNonNegativeInteger(capacity, 'Channel replay');\n\n return capacity;\n}\n\n/** Channels own mutable multicast state; disposal is their only terminal event. */\nexport function createChannel<T>(options: ChannelOptions<T> = {}): Channel<T> {\n const capacity = replayCapacity(options);\n const controller = new AbortController();\n const listeners = new Set<Sink<T>>();\n const replay: T[] = [];\n\n if ('initial' in options && capacity > 0) replay.push(options.initial as T);\n\n const source = stream<T>((sink) => {\n for (const value of replay) sink.next(value);\n\n if (controller.signal.aborted) {\n sink.complete();\n\n return;\n }\n\n listeners.add(sink);\n\n return () => listeners.delete(sink);\n });\n\n const dispose = (): void => {\n if (controller.signal.aborted) return;\n\n controller.abort();\n\n for (const listener of [...listeners]) listener.complete();\n\n listeners.clear();\n };\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 send(value: T): void {\n if (controller.signal.aborted) return;\n\n if (capacity > 0) {\n if (replay.length === capacity) replay.shift();\n\n replay.push(value);\n }\n\n for (const listener of [...listeners]) listener.next(value);\n },\n stream: source,\n [Symbol.dispose]: dispose,\n };\n}\n"],"mappings":";;;AAmBA,SAAS,EAAkB,GAAoC;CAC7D,IAAM,IAAW,EAAQ,UAAW,eAAa;CAIjD,OAFA,EAAyB,GAAU,gBAAgB,GAE5C;AACT;AAGA,SAAgB,EAAiB,IAA6B,CAAC,GAAe;CAC5E,IAAM,IAAW,EAAe,CAAO,GACjC,IAAa,IAAI,gBAAgB,GACjC,oBAAY,IAAI,IAAa,GAC7B,IAAc,CAAC;CAErB,AAAI,aAAa,KAAW,IAAW,KAAG,EAAO,KAAK,EAAQ,OAAY;CAE1E,IAAM,IAAS,GAAW,MAAS;EACjC,KAAK,IAAM,KAAS,GAAQ,EAAK,KAAK,CAAK;EAE3C,IAAI,EAAW,OAAO,SAAS;GAC7B,EAAK,SAAS;GAEd;EACF;EAIA,OAFA,EAAU,IAAI,CAAI,SAEL,EAAU,OAAO,CAAI;CACpC,CAAC,GAEK,UAAsB;EACtB,OAAW,OAAO,SAEtB;KAAW,MAAM;GAEjB,KAAK,IAAM,KAAY,CAAC,GAAG,CAAS,GAAG,EAAS,SAAS;GAEzD,EAAU,MAAM;EAJC;CAKnB;CAEA,OAAO;EACL,IAAI,iBAA8B;GAChC,OAAO,EAAW;EACpB;EACA;EACA,IAAI,WAAoB;GACtB,OAAO,EAAW,OAAO;EAC3B;EACA,KAAK,GAAgB;GACf,OAAW,OAAO,SAEtB;IAAI,IAAW,MACT,EAAO,WAAW,KAAU,EAAO,MAAM,GAE7C,EAAO,KAAK,CAAK;IAGnB,KAAK,IAAM,KAAY,CAAC,GAAG,CAAS,GAAG,EAAS,KAAK,CAAK;GAF1D;EAGF;EACA,QAAQ;GACP,OAAO,UAAU;CACpB;AACF"}
@@ -0,0 +1 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./subject.cjs");exports.createChannel=e.createChannel;
@@ -0,0 +1,3 @@
1
+ export { createChannel } from './subject';
2
+ export type { Channel, ChannelOptions } from './subject';
3
+ //# sourceMappingURL=subjects.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subjects.d.ts","sourceRoot":"","sources":["../src/subjects.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,YAAY,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { createChannel as e } from "./subject.js";
2
+ export { e as createChannel };
package/dist/types.d.ts CHANGED
@@ -1,86 +1,39 @@
1
- /** Cleanup / unsubscribe function returned by `subscribe()`. */
2
- export type Unsubscribe = () => void;
3
- /**
4
- * Minimal time-scheduling abstraction for operators that depend on timers.
5
- * Inject a custom implementation in tests to control time without relying on
6
- * global fake-timer mechanisms (`vi.useFakeTimers()`).
7
- *
8
- * @example
9
- * const testScheduler: Scheduler = {
10
- * delay(fn, ms) { ... },
11
- * repeat(fn, ms) { ... },
12
- * };
13
- * debounce(300, testScheduler);
14
- */
15
- export type Scheduler = {
16
- /** Schedule `fn` to run once after `ms` milliseconds. Returns a cancel function. */
17
- delay(fn: () => void, ms: number): () => void;
18
- /** Schedule `fn` to run repeatedly every `ms` milliseconds. Returns a cancel function. */
19
- repeat(fn: () => void, ms: number): () => void;
1
+ export type Teardown = () => void;
2
+ export type Subscription = {
3
+ [Symbol.dispose](): void;
4
+ readonly closed: boolean;
5
+ unsubscribe(): void;
20
6
  };
21
- /**
22
- * Observer passed to a producer or `subscribe()`.
23
- * `error` and `complete` are optional — omit them to ignore those signals.
24
- */
25
7
  export type Observer<T> = {
26
8
  complete?: () => void;
27
- error?: (err: unknown) => void;
9
+ error?: (reason: unknown) => void;
28
10
  next: (value: T) => void;
29
11
  };
30
- /**
31
- * Producer function passed to `flux()`.
32
- * Called once per `subscribe()` invocation (cold by default).
33
- * Return a cleanup function (or nothing) — it is called on unsubscribe.
34
- */
35
- export type Producer<T> = (observer: Observer<T>) => Unsubscribe | void;
36
- /**
37
- * A pipeable operator: a function that takes a source `Flux<A>` and returns a new `Flux<B>`.
38
- *
39
- * @example
40
- * const double: Operator<number, number> = (source) =>
41
- * source.pipe(map((n) => n * 2));
42
- */
43
- export type Operator<A = unknown, B = unknown> = (source: Flux<A>) => Flux<B>;
44
- /**
45
- * The core stream primitive. Lazy (cold) by default — each `subscribe()` invocation
46
- * starts its own producer. Use `.pipe(share())` to multicast to many subscribers.
47
- */
48
- export interface Flux<T> {
49
- /** `true` after `dispose()` is called. New subscriptions receive an immediate `complete` notification. */
50
- readonly disposed: boolean;
51
- /** AbortSignal that aborts when `dispose()` is called. */
52
- readonly disposalSignal: AbortSignal;
53
- /** Permanently terminates this stream. All active subscribers receive a `complete` notification. */
54
- dispose(): void;
55
- /**
56
- * Apply one or more operators in sequence. Each operator receives the output
57
- * of the previous one as its input, forming a pipeline.
58
- */
59
- pipe<B>(op1: Operator<T, B>): Flux<B>;
60
- pipe<B, C>(op1: Operator<T, B>, op2: Operator<B, C>): Flux<C>;
61
- pipe<B, C, D>(op1: Operator<T, B>, op2: Operator<B, C>, op3: Operator<C, D>): Flux<D>;
62
- pipe<B, C, D, E>(op1: Operator<T, B>, op2: Operator<B, C>, op3: Operator<C, D>, op4: Operator<D, E>): Flux<E>;
63
- pipe(...operators: Operator[]): Flux<unknown>;
64
- /**
65
- * Subscribe to values emitted by this stream.
66
- * Accepts either a full `Observer<T>` object or a plain `next` function.
67
- * Returns an unsubscribe function — call it to stop receiving values.
68
- * Pass an optional `AbortSignal` to unsubscribe automatically when the signal aborts.
69
- * If the stream is already disposed, the observer receives an immediate `complete` notification.
70
- */
71
- subscribe(observerOrNext: Observer<T> | ((value: T) => void), signal?: AbortSignal): Unsubscribe;
72
- /**
73
- * Consume the stream as an async iterator.
74
- * Buffers incoming values until consumed.
75
- * Calling `return()` on the iterator (or exiting a `for await` loop early) unsubscribes from the source.
76
- *
77
- * @example
78
- * for await (const value of source$) {
79
- * console.log(value);
80
- * }
81
- */
82
- [Symbol.asyncIterator](): AsyncIterableIterator<T>;
83
- /** ES2026 `using` compatible disposal. Delegates to `dispose()`. */
84
- [Symbol.dispose](): void;
12
+ export type SubscribeOptions = {
13
+ signal?: AbortSignal;
14
+ };
15
+ export type Sink<T> = {
16
+ complete(): void;
17
+ error(reason: unknown): void;
18
+ next(value: T): void;
19
+ };
20
+ export type Producer<T> = (sink: Sink<T>, signal: AbortSignal) => Teardown | void;
21
+ export type Operator<A = unknown, B = unknown> = (source: Stream<A>) => Stream<B>;
22
+ /** Streams describe reusable work. Subscriptions own lifetime. */
23
+ export interface Stream<T> {
24
+ subscribe(observer: Observer<T> | ((value: T) => void), options?: SubscribeOptions): Subscription;
85
25
  }
26
+ export type OverflowPolicy = 'drop-newest' | 'drop-oldest' | 'error';
27
+ export type AsyncIterableOptions = {
28
+ capacity: number;
29
+ overflow: OverflowPolicy;
30
+ signal?: AbortSignal;
31
+ };
32
+ type PipeResult<Input, Operators extends readonly unknown[]> = Operators extends readonly [
33
+ Operator<Input, infer Output>,
34
+ ...infer Remaining
35
+ ] ? PipeResult<Output, Remaining> : Stream<Input>;
36
+ export type ValidPipe<Input, Operators extends readonly unknown[]> = Operators extends readonly [] ? [] : Operators extends readonly [Operator<Input, infer Output>, ...infer Remaining] ? [Operator<Input, Output>, ...ValidPipe<Output, Remaining>] : never;
37
+ export type PipedStream<Input, Operators extends readonly unknown[]> = PipeResult<Input, Operators>;
38
+ export {};
86
39
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,gEAAgE;AAChE,MAAM,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC;AAErC;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,SAAS,GAAG;IACtB,oFAAoF;IACpF,KAAK,CAAC,EAAE,EAAE,MAAM,IAAI,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,IAAI,CAAC;IAC9C,0FAA0F;IAC1F,MAAM,CAAC,EAAE,EAAE,MAAM,IAAI,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,IAAI,CAAC;CAChD,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI;IACxB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;IAC/B,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;CAC1B,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,WAAW,GAAG,IAAI,CAAC;AAExE;;;;;;GAMG;AACH,MAAM,MAAM,QAAQ,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC;AAE9E;;;GAGG;AACH,MAAM,WAAW,IAAI,CAAC,CAAC;IACrB,0GAA0G;IAC1G,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,0DAA0D;IAC1D,QAAQ,CAAC,cAAc,EAAE,WAAW,CAAC;IACrC,oGAAoG;IACpG,OAAO,IAAI,IAAI,CAAC;IAChB;;;OAGG;IACH,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACtC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IAC9D,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACtF,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IAC9G,IAAI,CAAC,GAAG,SAAS,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;IAC9C;;;;;;OAMG;IACH,SAAS,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,WAAW,CAAC;IACjG;;;;;;;;;OASG;IACH,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,qBAAqB,CAAC,CAAC,CAAC,CAAC;IACnD,oEAAoE;IACpE,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC;CAC1B"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC;AAElC,MAAM,MAAM,YAAY,GAAG;IACzB,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,WAAW,IAAI,IAAI,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI;IACxB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IAClC,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,IAAI,CAAC,CAAC,IAAI;IACpB,QAAQ,IAAI,IAAI,CAAC;IACjB,KAAK,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;IAC7B,IAAI,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,KAAK,QAAQ,GAAG,IAAI,CAAC;AAElF,MAAM,MAAM,QAAQ,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC;AAElF,kEAAkE;AAClE,MAAM,WAAW,MAAM,CAAC,CAAC;IACvB,SAAS,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,YAAY,CAAC;CACnG;AAED,MAAM,MAAM,cAAc,GAAG,aAAa,GAAG,aAAa,GAAG,OAAO,CAAC;AAErE,MAAM,MAAM,oBAAoB,GAAG;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,cAAc,CAAC;IACzB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,CAAC;AAEF,KAAK,UAAU,CAAC,KAAK,EAAE,SAAS,SAAS,SAAS,OAAO,EAAE,IAAI,SAAS,SAAS,SAAS;IACxF,QAAQ,CAAC,KAAK,EAAE,MAAM,MAAM,CAAC;IAC7B,GAAG,MAAM,SAAS;CACnB,GACG,UAAU,CAAC,MAAM,EAAE,SAAS,CAAC,GAC7B,MAAM,CAAC,KAAK,CAAC,CAAC;AAElB,MAAM,MAAM,SAAS,CAAC,KAAK,EAAE,SAAS,SAAS,SAAS,OAAO,EAAE,IAAI,SAAS,SAAS,SAAS,EAAE,GAC9F,EAAE,GACF,SAAS,SAAS,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,MAAM,CAAC,EAAE,GAAG,MAAM,SAAS,CAAC,GAC5E,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,GAAG,SAAS,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,GAC1D,KAAK,CAAC;AAEZ,MAAM,MAAM,WAAW,CAAC,KAAK,EAAE,SAAS,SAAS,SAAS,OAAO,EAAE,IAAI,UAAU,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC"}