Skip to content

Commit 87cb88c

Browse files
author
Duke
committed
feat: expose observables.createState and provideState
1 parent 027b127 commit 87cb88c

File tree

2 files changed

+36
-1
lines changed

2 files changed

+36
-1
lines changed

src/index.ts

+23-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { observables, pipe, pushObservable, type Operator, type PushObservable, type Subscribable } from "./rx"
1+
import { observables, pipe, pushObservable, type Operator, type PushObservable, type Subscribable, type Subscriber } from "./rx"
22

33
declare const ExecutorIdBrand: unique symbol
44
export type ExecutorId = string & { readonly [ExecutorIdBrand]: never }
@@ -842,6 +842,28 @@ export function providePushObservable<Value>(
842842
})
843843
}
844844

845+
/**
846+
* Utility to integrate state with submodule ecosystem
847+
* @param pValue - value that will be used as initial state
848+
* @param controller - api to control the state
849+
* @returns
850+
*/
851+
export function provideState<
852+
Value,
853+
Controller,
854+
ControllerFn extends (sub: Subscriber<Value>, get: () => Value) => Controller
855+
>(
856+
pValue: Value | Executor<Value>,
857+
controller: ControllerFn | Executor<ControllerFn>
858+
): Executor<readonly [Subscribable<Value>, Controller]> {
859+
return map(
860+
{ value: normalize(pValue), controller: normalize(controller) },
861+
({ value, controller }) => {
862+
return observables.createState<Value, Controller>(value, controller)
863+
}
864+
)
865+
}
866+
845867
export type OperatorLike<S, A> = Operator<S, A> | Executor<Operator<S, A>>
846868

847869
/**

src/rx.ts

+13
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,19 @@ export const observables = {
627627
}
628628
}
629629
},
630+
631+
/** Simplified version of push observable that focusing on providing a shaped api */
632+
createState: <T, C>(
633+
initialValue: T,
634+
fn: (subscriber: Subscriber<T>, get: () => T) => C
635+
): readonly [Subscribable<T>, C] => {
636+
const [observable, subscriber] = pushObservable<T>(initialValue);
637+
// biome-ignore lint/style/noNonNullAssertion: <explanation>
638+
const get = () => observable.lastValue!;
639+
640+
const controller = fn(subscriber, get);
641+
return [observable, controller] as const;
642+
},
630643
/**
631644
* Combines the latest values from multiple observables into a single observable.
632645
* @template T The type of the combined value.

0 commit comments

Comments
 (0)