Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 | 1x 1x 1x 1x 1x 85x 85x 85x 85x 85x 85x 85x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 2x 2x 2x 2x 2x 2x 2x 5x 3x 5x 85x 85x 1x 2x 2x 1x 61x 61x 1x 10x 3x 3x 3x 3x 10x 2x 2x 2x 2x 10x 2x 4x 2x 2x 3x 7x 3x 3x 1x 12x 3x 3x 3x 3x 12x 1x 1x 1x 1x 8x 8x 8x 33x 19x 33x 8x 8x 6x 8x 2x 2x 2x 2x 2x 2x 33x 11x 11x 19x 8x 8x 26x 16x 26x 8x 8x 6x 8x 2x 2x 2x 2x 2x 2x 8x 8x 8x 16x 8x 8x 8x 8x 8x 8x 1x | import type { DeriveFn, Linkable, ObjLike, State, StateSubscriber, StateUnsubscribe } from './types.js'; import { CONTROLLER_REGISTRY } from './registry.js'; import { isFunction } from '@beerush/utils'; import { assign } from './helper.js'; import { captureStack } from './exception.js'; import { anchor } from './anchor.js'; /** * Derives a new subscription from an existing anchored state. * This is a convenience function to subscribe to changes of an already anchored state. * * @template T The type of the state. * @param state - The anchored state object to derive from. * @param handler - The subscriber function to call on state changes. * @param recursive - Whether to recursively subscribe to child states (Default: follow). * @returns A function to unsubscribe from the derived state. */ function deriveFn<T extends Linkable>( state: State<T>, handler: StateSubscriber<T>, recursive?: boolean ): StateUnsubscribe { const ctrl = CONTROLLER_REGISTRY.get(state); if (typeof ctrl?.subscribe !== 'function') { captureStack.warning.external( 'Invalid subscription target:', 'Attempted to subscribe to non-reactive state.', 'Object is not reactive', deriveFn, deriveFn.pipe ); try { handler(state, { type: 'init', keys: [] }); } catch (error) { captureStack.error.external( 'Unable to execute the subscription handler function.', error as Error, deriveFn, deriveFn.pipe ); } return () => { // No-op, as there is no subscription to unsubscribe from. }; } return ctrl?.subscribe(handler as StateSubscriber<unknown>, undefined, recursive); } deriveFn.log = ((state) => { return deriveFn(state, console.log); }) satisfies DeriveFn['log']; deriveFn.resolve = ((state) => { return CONTROLLER_REGISTRY.get(state) as never; }) satisfies DeriveFn['resolve']; deriveFn.pipe = ((source, target, transform) => { if (!anchor.has(source)) { const error = new Error('State is not reactive.'); captureStack.violation.derivation('Attempted to pipe state from a non-reactive state.', error); return () => {}; } if (typeof target !== 'object' || target === null) { const error = new Error('Target is not an assignable object.'); captureStack.violation.derivation('Attempted to pipe state to a non-assignable target.', error); return () => {}; } if (!isFunction(transform)) { return deriveFn(source, (current) => { assign(target as ObjLike, current as ObjLike); }); } return deriveFn(source, (current) => { assign(target as ObjLike, transform(current)); }); }) satisfies DeriveFn['pipe']; deriveFn.bind = ((left, right, transformLeft, transformRight) => { if (!anchor.has(left)) { const error = new Error('State is not reactive.'); captureStack.violation.derivation('Attempted to bind state from a non-reactive state.', error); return () => {}; } if (!anchor.has(right)) { const error = new Error('State is not reactive.'); captureStack.violation.derivation('Attempted to bind state to a non-reactive state.', error); return () => {}; } let updatingLeft = false; let updatingRight = false; const unsubscribeLeft = deriveFn(left, (current) => { if (updatingLeft) return; updatingRight = true; if (isFunction(transformLeft)) { const result = transformLeft(current); if (result) { anchor.assign(right, result); } else { captureStack.warning.external( 'Invalid binding transformation:', 'The transformation function returned an invalid value. Please check your transformation function.', 'Undefined is not assignable value.' ); } } else { anchor.assign(right as ObjLike, current as ObjLike); } updatingRight = false; }); const unsubscribeRight = deriveFn(right, (current) => { if (updatingRight) return; updatingLeft = true; if (isFunction(transformRight)) { const result = transformRight(current); if (result) { anchor.assign(left, result); } else { captureStack.warning.external( 'Invalid binding transformation:', 'The transformation function returned an invalid value. Please check your transformation function.', 'Undefined is not assignable value.' ); } } else { assign(left as ObjLike, current as ObjLike); } updatingLeft = false; }); return () => { unsubscribeLeft(); unsubscribeRight(); }; }) satisfies DeriveFn['bind']; export const derive = deriveFn as DeriveFn; |