From d9544fde0f5e6a35faa049fdeecd4c8f8650babe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Oliva?= Date: Wed, 19 Oct 2022 17:51:45 +0200 Subject: [PATCH] feat: create-signal --- packages/context-state/src/create-signal.ts | 52 +++++++++++++++++++ .../src/internal/detached-node.ts | 12 +++-- packages/context-state/src/internal/index.ts | 1 + packages/context-state/src/types.ts | 7 ++- 4 files changed, 67 insertions(+), 5 deletions(-) create mode 100644 packages/context-state/src/create-signal.ts diff --git a/packages/context-state/src/create-signal.ts b/packages/context-state/src/create-signal.ts new file mode 100644 index 0000000..4f7f0a2 --- /dev/null +++ b/packages/context-state/src/create-signal.ts @@ -0,0 +1,52 @@ +import { Subject } from "rxjs" +import { + getInternals, + inactiveContext, + NestedMap, + recursiveError, +} from "./internal" +import type { Signal, StateNode, StringRecord } from "./types" + +export const createSignal = >( + parent: StateNode, +): Signal => { + const instances = new NestedMap>() + const parentInternals = getInternals(parent) + + parentInternals.childRunners.push((key, isActive) => { + const current = instances.get(key) + if (isActive && !current) { + instances.set(key, new Subject()) + } + if (!isActive && current) { + instances.delete(key) + current.complete() + } + }) + + return { + getSignal$(keyObj: K = {} as K) { + const sortedKey = parentInternals.keysOrder.map((key) => keyObj[key]) + const instance = instances.get(sortedKey) + if (!instance) + throw ( + recursiveError(sortedKey, parentInternals, new Set()) || + inactiveContext() + ) + return instance + }, + push(keyOrValue: T | K, value?: T) { + const keyObj = (arguments.length > 1 ? keyOrValue : {}) as K + const safeValue = arguments.length > 1 ? value! : (keyOrValue as T) + + const sortedKey = parentInternals.keysOrder.map((key) => keyObj[key]) + const instance = instances.get(sortedKey) + if (!instance) + throw ( + recursiveError(sortedKey, parentInternals, new Set()) || + inactiveContext() + ) + instance.next(safeValue) + }, + } +} diff --git a/packages/context-state/src/internal/detached-node.ts b/packages/context-state/src/internal/detached-node.ts index 1b66ff8..3ff9187 100644 --- a/packages/context-state/src/internal/detached-node.ts +++ b/packages/context-state/src/internal/detached-node.ts @@ -1,5 +1,5 @@ import { Observable, ReplaySubject, Subscription } from "rxjs" -import type { CtxFn, StateNode, StringRecord } from "../types" +import type { CtxFn, Signal, StateNode, StringRecord } from "../types" import { InternalStateNode, EMPTY_VALUE, @@ -13,7 +13,7 @@ import { } from "./" import { NestedMap } from "./nested-map" -const recursiveError = ( +export const recursiveError = ( key: any[], start: InternalStateNode, searched: Set>, @@ -153,9 +153,13 @@ export const detachedNode = >( } const ctxObservable = >( - node: StateNode, + node: StateNode | Signal, partialKey: Omit, - ): Observable => node.getState$({ ...objKey, ...partialKey }) + ): Observable => + ("getSignal$" in node ? node.getSignal$ : node.getState$)({ + ...objKey, + ...partialKey, + } as CK) const onError = (err: any) => { const prevPromise = actualInstance.promise diff --git a/packages/context-state/src/internal/index.ts b/packages/context-state/src/internal/index.ts index ab0d722..111a79f 100644 --- a/packages/context-state/src/internal/index.ts +++ b/packages/context-state/src/internal/index.ts @@ -4,3 +4,4 @@ export * from "./promisses" export * from "./internals" export * from "./detached-node" export * from "./record-utils" +export * from "./nested-map" diff --git a/packages/context-state/src/types.ts b/packages/context-state/src/types.ts index 69341f0..d18e55b 100644 --- a/packages/context-state/src/types.ts +++ b/packages/context-state/src/types.ts @@ -12,10 +12,15 @@ export interface StateNode> { : (key: K) => Observable } +export interface Signal> { + push: {} extends K ? (value: T) => void : (key: K, value: T) => void + getSignal$: {} extends K ? () => Observable : (key: K) => Observable +} + export type CtxFn> = ( ctxValue: (node: StateNode) => CT, ctxObservable: >( - node: StateNode, + node: StateNode | Signal, key: Omit, ) => Observable, key: K,