@thalesfp/snapstate 0.1.0 → 0.2.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.
- package/README.md +201 -317
- package/dist/form/index.cjs +25 -4
- package/dist/form/index.cjs.map +1 -1
- package/dist/form/index.d.cts +9 -0
- package/dist/form/index.d.ts +9 -0
- package/dist/form/index.js +25 -4
- package/dist/form/index.js.map +1 -1
- package/dist/react/index.cjs +25 -4
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +9 -0
- package/dist/react/index.d.ts +9 -0
- package/dist/react/index.js +25 -4
- package/dist/react/index.js.map +1 -1
- package/package.json +2 -2
package/dist/react/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/react/index.ts","../../src/react/store.ts","../../src/core/types.ts","../../src/core/trie.ts","../../src/core/structural.ts","../../src/core/computed.ts","../../src/core/store.ts","../../src/core/base.ts"],"sourcesContent":["export { ReactSnapStore as SnapStore } from \"./store.js\";\nexport { setHttpClient, setDefaultHeaders } from \"../core/base.js\";\nexport { asyncStatus } from \"../core/types.js\";\nexport type {\n AsyncStatus,\n AsyncStatusValue,\n OperationState,\n HttpClient,\n HttpRequestInit,\n ApiRequestOptions,\n} from \"../core/types.js\";\n","import {\n useSyncExternalStore,\n useCallback,\n useRef,\n useState,\n useEffect,\n createElement,\n forwardRef,\n} from \"react\";\nimport { SnapStore } from \"../core/base.js\";\nimport { asyncStatus } from \"../core/types.js\";\nimport type { StoreOptions, AsyncStatus, DotPaths, GetByPath } from \"../core/types.js\";\n\ninterface ConnectConfig<S, MappedProps> {\n props: (store: S) => MappedProps;\n fetch: (store: S) => Promise<void>;\n loading?: React.ComponentType;\n error?: React.ComponentType<{ error: string }>;\n}\n\ntype PickFn<T extends object> = <P extends DotPaths<T>>(path: P) => GetByPath<T, P>;\n\ninterface SelectConnectConfig<T extends object, MappedProps> {\n select: (pick: PickFn<T>) => MappedProps;\n}\n\nfunction shallowEqual(a: Record<string, unknown>, b: Record<string, unknown>): boolean {\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n if (keysA.length !== keysB.length) { return false; }\n for (const key of keysA) {\n if (a[key] !== b[key]) { return false; }\n }\n return true;\n}\n\nexport class ReactSnapStore<T extends object, K extends string = string> extends SnapStore<T, K> {\n constructor(initialState: T, options?: StoreOptions) {\n super(initialState, options);\n }\n\n /** Wire a component to the store, injecting props derived from state via `mapToProps`. */\n connect<P extends object, MappedProps extends Record<string, unknown>>(\n Component: React.ComponentType<P>,\n mapToProps: (store: this) => MappedProps,\n ): React.FC<Omit<P, keyof MappedProps>>;\n /** Wire a component to the store with async data fetching, loading, and error handling. */\n connect<P extends object, MappedProps extends Record<string, unknown>>(\n Component: React.ComponentType<P>,\n config: ConnectConfig<this, MappedProps>,\n ): React.FC<Omit<P, keyof MappedProps | \"status\" | \"error\">>;\n /** Wire a component to the store with granular path-based subscriptions via `select`.\n * Paths are captured once at connect-time — select must use a stable set of paths.\n * For conditional/dynamic path selection, use the `mapToProps` overload instead. */\n connect<P extends object, MappedProps extends Record<string, unknown>>(\n Component: React.ComponentType<P>,\n config: SelectConnectConfig<T, MappedProps>,\n ): React.FC<Omit<P, keyof MappedProps>>;\n connect<P extends object, MappedProps extends Record<string, unknown>>(\n Component: React.ComponentType<P>,\n configOrMapper:\n | ((store: this) => MappedProps)\n | ConnectConfig<this, MappedProps>\n | SelectConnectConfig<T, MappedProps>,\n ): React.FC<Omit<P, keyof MappedProps>> {\n const store = this;\n\n if (typeof configOrMapper === \"object\" && \"select\" in configOrMapper) {\n return this._connectWithSelect<P, MappedProps>(Component, configOrMapper.select);\n }\n\n const mapToProps =\n typeof configOrMapper === \"function\" ? configOrMapper : configOrMapper.props;\n const fetchFn =\n typeof configOrMapper === \"function\" ? undefined : configOrMapper.fetch;\n const loadingComponent =\n typeof configOrMapper === \"function\" ? undefined : configOrMapper.loading;\n const errorComponent =\n typeof configOrMapper === \"function\" ? undefined : configOrMapper.error;\n\n const Connected = forwardRef<unknown, Omit<P, keyof MappedProps>>(function Connected(ownProps, ref) {\n const cachedRef = useRef<{ revision: number; props: MappedProps } | null>(null);\n const revisionRef = useRef(0);\n\n const subscribe = useCallback(\n (cb: () => void) => store.subscribe(() => {\n revisionRef.current++;\n cb();\n }),\n [store],\n );\n\n const getSnapshot = useCallback(() => {\n const currentRevision = revisionRef.current;\n if (cachedRef.current && cachedRef.current.revision === currentRevision) {\n return cachedRef.current.props;\n }\n const next = mapToProps(store);\n if (cachedRef.current && shallowEqual(cachedRef.current.props, next)) {\n cachedRef.current = { revision: currentRevision, props: cachedRef.current.props };\n return cachedRef.current.props;\n }\n cachedRef.current = { revision: currentRevision, props: next };\n return next;\n }, [store]);\n\n const mappedProps = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n\n const [asyncState, setAsyncState] = useState<{\n status: AsyncStatus;\n error: string | null;\n }>({ status: asyncStatus(\"idle\"), error: null });\n\n const fetchGenRef = useRef(0);\n\n useEffect(() => {\n if (!fetchFn) { return; }\n let cancelled = false;\n const gen = ++fetchGenRef.current;\n setAsyncState({ status: asyncStatus(\"loading\"), error: null });\n Promise.resolve()\n .then(() => {\n if (cancelled) { return; }\n return fetchFn(store);\n })\n .then(() => {\n if (gen === fetchGenRef.current) {\n setAsyncState({ status: asyncStatus(\"ready\"), error: null });\n }\n })\n .catch((e) => {\n if (gen === fetchGenRef.current) {\n setAsyncState({\n status: asyncStatus(\"error\"),\n error: e instanceof Error ? e.message : \"Unknown error\",\n });\n }\n });\n return () => { cancelled = true; };\n }, []);\n\n if (fetchFn) {\n if (loadingComponent && (asyncState.status.isIdle || asyncState.status.isLoading)) {\n return createElement(loadingComponent);\n }\n if (errorComponent && asyncState.status.isError) {\n return createElement(errorComponent, { error: asyncState.error! });\n }\n }\n\n return createElement(Component, {\n ...ownProps,\n ...mappedProps,\n ...(fetchFn ? asyncState : {}),\n ref,\n } as unknown as P);\n });\n\n Connected.displayName = `Connect(${Component.displayName || Component.name || \"Component\"})`;\n return Connected as unknown as React.FC<Omit<P, keyof MappedProps>>;\n }\n\n private _connectWithSelect<P extends object, MappedProps extends Record<string, unknown>>(\n Component: React.ComponentType<P>,\n selectFn: (pick: PickFn<T>) => MappedProps,\n ): React.FC<Omit<P, keyof MappedProps>> {\n const store = this;\n\n const resolvePathValue = (path: string): any => {\n const segments = path.split(\".\");\n let val: any = store.getSnapshot();\n for (const seg of segments) {\n if (val == null) { return undefined; }\n val = val[seg];\n }\n return val;\n };\n\n const trackedPaths: string[] = [];\n const trackingPick: PickFn<T> = ((path: string) => {\n trackedPaths.push(path);\n return resolvePathValue(path);\n }) as PickFn<T>;\n selectFn(trackingPick);\n const paths = [...trackedPaths];\n\n const readPick: PickFn<T> = ((path: string) => {\n return resolvePathValue(path);\n }) as PickFn<T>;\n\n const Connected = forwardRef<unknown, Omit<P, keyof MappedProps>>(function Connected(ownProps, ref) {\n const cachedRef = useRef<{ revision: number; props: MappedProps } | null>(null);\n const revisionRef = useRef(0);\n\n const subscribe = useCallback(\n (cb: () => void) => {\n const unsubs = paths.map((p) =>\n store.subscribe(p, () => {\n revisionRef.current++;\n cb();\n }),\n );\n return () => unsubs.forEach((u) => u());\n },\n [store],\n );\n\n const getSnapshot = useCallback(() => {\n const currentRevision = revisionRef.current;\n if (cachedRef.current && cachedRef.current.revision === currentRevision) {\n return cachedRef.current.props;\n }\n const next = selectFn(readPick);\n if (cachedRef.current && shallowEqual(cachedRef.current.props, next)) {\n cachedRef.current = { revision: currentRevision, props: cachedRef.current.props };\n return cachedRef.current.props;\n }\n cachedRef.current = { revision: currentRevision, props: next };\n return next;\n }, [store]);\n\n const mappedProps = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n\n return createElement(Component, {\n ...ownProps,\n ...mappedProps,\n ref,\n } as unknown as P);\n });\n\n Connected.displayName = `Connect(${Component.displayName || Component.name || \"Component\"})`;\n return Connected as unknown as React.FC<Omit<P, keyof MappedProps>>;\n }\n}\n","export type AsyncStatusValue = \"idle\" | \"loading\" | \"ready\" | \"error\";\n\nexport interface AsyncStatus {\n readonly value: AsyncStatusValue;\n readonly isIdle: boolean;\n readonly isLoading: boolean;\n readonly isReady: boolean;\n readonly isError: boolean;\n}\n\nconst _statuses: Record<AsyncStatusValue, AsyncStatus> = {\n idle: Object.freeze({ value: \"idle\", isIdle: true, isLoading: false, isReady: false, isError: false }),\n loading: Object.freeze({ value: \"loading\", isIdle: false, isLoading: true, isReady: false, isError: false }),\n ready: Object.freeze({ value: \"ready\", isIdle: false, isLoading: false, isReady: true, isError: false }),\n error: Object.freeze({ value: \"error\", isIdle: false, isLoading: false, isReady: false, isError: true }),\n};\n\nexport function asyncStatus(value: AsyncStatusValue): AsyncStatus {\n return _statuses[value];\n}\n\n/** Async operation status and error. Tracks the lifecycle of an `api.fetch`/`api.get`/`api.post` call. */\nexport interface OperationState {\n status: AsyncStatus;\n error: string | null;\n}\n\nexport type Path = string & { readonly __brand?: \"Path\" };\n\nexport type Listener = () => void;\n\nexport type Unsubscribe = () => void;\n\n// Union of all valid dot-separated paths into T (for autocomplete)\nexport type DotPaths<T, Prefix extends string = \"\"> = T extends object\n ? { [K in keyof T & string]:\n | `${Prefix}${K}`\n | DotPaths<T[K], `${Prefix}${K}.`>\n }[keyof T & string]\n : never;\n\n// Extract a deeply nested type by dot-separated path\nexport type GetByPath<T, P extends string> = P extends \"\"\n ? T\n : P extends `${infer K}.${infer Rest}`\n ? K extends keyof T\n ? GetByPath<T[K], Rest>\n : never\n : P extends keyof T\n ? T[P]\n : never;\n\nexport type DeepPartial<T> = T extends object\n ? { [K in keyof T]?: DeepPartial<T[K]> }\n : T;\n\nexport type ArrayPaths<T> = {\n [K in keyof T & string]: T[K] extends any[] ? K : never;\n}[keyof T & string];\n\nexport type ObjectArrayPaths<T> = {\n [K in keyof T & string]: T[K] extends (infer V)[]\n ? V extends Date | RegExp | Map<any, any> | Set<any> | Function | any[]\n ? never\n : V extends Record<string, any> ? K : never\n : never;\n}[keyof T & string];\n\nexport type ElementOf<A> = A extends (infer V)[] ? V : never;\n\nexport type Updater<V> = V | ((prev: V) => V);\n\nexport interface StoreOptions {\n /** Auto-batch synchronous sets via microtask (default: true) */\n autoBatch?: boolean;\n}\n\n/** Handle to a computed (derived) value. Call `get()` to read, `destroy()` to stop tracking. */\nexport interface ComputedRef<V> {\n get(): V;\n destroy(): void;\n}\n\n/** Options for an HTTP request (method, body, headers). */\nexport interface HttpRequestInit {\n method?: string;\n body?: unknown;\n headers?: Record<string, string>;\n}\n\n/** Interface for the HTTP layer used by `api.get` and `api.post/put/patch/delete`. */\nexport interface HttpClient {\n request<R = unknown>(url: string, init?: HttpRequestInit): Promise<R>;\n}\n\n/** Options for HTTP verb methods (`api.post`, `api.put`, etc.). */\nexport interface ApiRequestOptions<R = unknown> {\n body?: unknown;\n headers?: Record<string, string>;\n onSuccess?: (data: R) => void;\n onError?: (error: Error) => void;\n}\n\nexport interface Subscribable<T extends object> {\n subscribe(callback: Listener): Unsubscribe;\n getSnapshot(): T;\n}\n\nexport interface StateAccessor<T extends object> {\n get(): T;\n get<P extends DotPaths<T>>(path: P): GetByPath<T, P>;\n set<P extends DotPaths<T>>(path: P, value: Updater<GetByPath<T, P>>): void;\n batch(fn: () => void): void;\n computed<V>(deps: (keyof T & string)[], fn: (state: T) => V): ComputedRef<V>;\n append<P extends ArrayPaths<T>>(path: P, ...items: ElementOf<T[P]>[]): void;\n prepend<P extends ArrayPaths<T>>(path: P, ...items: ElementOf<T[P]>[]): void;\n insertAt<P extends ArrayPaths<T>>(path: P, index: number, ...items: ElementOf<T[P]>[]): void;\n patch<P extends ObjectArrayPaths<T>>(path: P, predicate: (item: ElementOf<T[P]>) => boolean, updates: Partial<ElementOf<T[P]>>): void;\n remove<P extends ArrayPaths<T>>(path: P, predicate: (item: ElementOf<T[P]>) => boolean): void;\n removeAt<P extends ArrayPaths<T>>(path: P, index: number): void;\n at<P extends ArrayPaths<T>>(path: P, index: number): ElementOf<T[P]> | undefined;\n filter<P extends ArrayPaths<T>>(path: P, predicate: (item: ElementOf<T[P]>) => boolean): ElementOf<T[P]>[];\n find<P extends ArrayPaths<T>>(path: P, predicate: (item: ElementOf<T[P]>) => boolean): ElementOf<T[P]> | undefined;\n findIndexOf<P extends ArrayPaths<T>>(path: P, predicate: (item: ElementOf<T[P]>) => boolean): number;\n count<P extends ArrayPaths<T>>(path: P, predicate: (item: ElementOf<T[P]>) => boolean): number;\n}\n\nexport interface ApiAccessor<K extends string> {\n fetch(key: K, fn: () => Promise<void>): Promise<void>;\n get<R = unknown>(key: K, url: string, onSuccess?: (data: R) => void): Promise<void>;\n post<R = unknown>(key: K, url: string, options?: ApiRequestOptions<R>): Promise<void>;\n put<R = unknown>(key: K, url: string, options?: ApiRequestOptions<R>): Promise<void>;\n patch<R = unknown>(key: K, url: string, options?: ApiRequestOptions<R>): Promise<void>;\n delete<R = unknown>(key: K, url: string, options?: ApiRequestOptions<R>): Promise<void>;\n}\n\nexport interface RawStore<T extends object> extends Subscribable<T> {\n get(): T;\n get<P extends DotPaths<T>>(path: P): GetByPath<T, P>;\n\n set<P extends DotPaths<T>>(path: P, value: Updater<GetByPath<T, P>>): void;\n\n batch(fn: () => void): void;\n\n subscribe(callback: Listener): Unsubscribe;\n subscribe(path: string, callback: Listener): Unsubscribe;\n\n getSnapshot(): T;\n\n computed<V>(deps: (keyof T & string)[], fn: (state: T) => V): ComputedRef<V>;\n\n notify(): void;\n\n destroy(): void;\n}\n","import type { Listener, Unsubscribe } from \"./types.js\";\n\nfunction invokeAll(listeners: Set<Listener>): void {\n let firstError: unknown;\n for (const l of listeners) {\n try { l(); } catch (e) { firstError ??= e; }\n }\n if (firstError !== undefined) { throw firstError; }\n}\n\ninterface TrieNode {\n listeners: Set<Listener>;\n children: Map<string, TrieNode>;\n}\n\nfunction createNode(): TrieNode {\n return { listeners: new Set(), children: new Map() };\n}\n\nfunction parsePath(path: string): string[] {\n if (path === \"\") { return []; }\n return path.split(\".\");\n}\n\nexport class SubscriptionTrie {\n private root = createNode();\n private globalListeners = new Set<Listener>();\n\n /** Subscribe to a specific path. Returns unsubscribe function. */\n add(path: string, listener: Listener): Unsubscribe {\n const segments = parsePath(path);\n const parents: { parent: TrieNode; segment: string }[] = [];\n let node = this.root;\n for (const seg of segments) {\n if (!node.children.has(seg)) {\n node.children.set(seg, createNode());\n }\n parents.push({ parent: node, segment: seg });\n node = node.children.get(seg)!;\n }\n node.listeners.add(listener);\n return () => {\n node.listeners.delete(listener);\n for (let i = parents.length - 1; i >= 0; i--) {\n const { parent, segment } = parents[i];\n const child = parent.children.get(segment)!;\n if (child.listeners.size === 0 && child.children.size === 0) {\n parent.children.delete(segment);\n } else {\n break;\n }\n }\n };\n }\n\n /** Subscribe to all changes (no path filter). */\n addGlobal(listener: Listener): Unsubscribe {\n this.globalListeners.add(listener);\n return () => {\n this.globalListeners.delete(listener);\n };\n }\n\n /** Notify listeners for exact path, all ancestors, and all descendants. */\n notify(path: string): void {\n const segments = parsePath(path);\n const collected = new Set<Listener>();\n\n // Collect global listeners\n for (const l of this.globalListeners) collected.add(l);\n\n // Walk down to the target, collecting ancestor listeners\n let node = this.root;\n // Root-level listeners (subscribe to \"\")\n for (const l of node.listeners) collected.add(l);\n\n let matched = true;\n for (const seg of segments) {\n // Check wildcard sibling at this level\n const wildcard = node.children.get(\"*\");\n if (wildcard) {\n for (const l of wildcard.listeners) collected.add(l);\n this.collectDescendants(wildcard, collected);\n }\n\n const child = node.children.get(seg);\n if (!child) {\n matched = false;\n break;\n }\n node = child;\n for (const l of node.listeners) collected.add(l);\n }\n\n // Only collect descendants if we matched the full path\n if (matched) {\n this.collectDescendants(node, collected);\n }\n\n invokeAll(collected);\n }\n\n /** Notify all listeners in the trie. */\n notifyAll(): void {\n const collected = new Set<Listener>();\n for (const l of this.globalListeners) collected.add(l);\n this.collectDescendants(this.root, collected);\n for (const l of this.root.listeners) collected.add(l);\n invokeAll(collected);\n }\n\n private collectDescendants(node: TrieNode, out: Set<Listener>): void {\n for (const child of node.children.values()) {\n for (const l of child.listeners) out.add(l);\n this.collectDescendants(child, out);\n }\n }\n\n clear(): void {\n this.root = createNode();\n this.globalListeners.clear();\n }\n}\n","/**\n * Immutable update with structural sharing.\n * Only clones objects along the changed path; unchanged subtrees keep their references.\n */\nexport function applyUpdate<T extends object>(\n state: T,\n path: string,\n value: unknown,\n): T {\n const segments = path.split(\".\");\n return updateAtPath(state, segments, 0, value) as T;\n}\n\nfunction updateAtPath(\n current: unknown,\n segments: string[],\n index: number,\n value: unknown,\n): unknown {\n if (index === segments.length) {\n // Functional updater support\n if (typeof value === \"function\") {\n return (value as (prev: unknown) => unknown)(current);\n }\n return value;\n }\n\n const key = segments[index];\n\n if (Array.isArray(current)) {\n const i = Number(key);\n const next = updateAtPath(current[i], segments, index + 1, value);\n if (Object.is(next, current[i])) { return current; }\n const copy = current.slice();\n copy[i] = next;\n return copy;\n }\n\n if (current !== null && typeof current === \"object\") {\n const obj = current as Record<string, unknown>;\n const next = updateAtPath(obj[key], segments, index + 1, value);\n if (Object.is(next, obj[key])) { return current; }\n return { ...obj, [key]: next };\n }\n\n // Path doesn't exist yet — create nested objects\n const next = updateAtPath(undefined, segments, index + 1, value);\n return { [key]: next };\n}\n\n/** Read a value at a dot-separated path. */\nexport function getAtPath(state: unknown, path: string): unknown {\n if (path === \"\") { return state; }\n const segments = path.split(\".\");\n let current = state;\n for (const seg of segments) {\n if (current === null || current === undefined) { return undefined; }\n current = (current as Record<string, unknown>)[seg];\n }\n return current;\n}\n","import type { ComputedRef, Listener, Unsubscribe } from \"./types.js\";\n\ninterface ComputedHost {\n getSnapshot(): object;\n subscribe(path: string, callback: Listener): Unsubscribe;\n}\n\nexport function createComputed<T extends object, V>(\n host: ComputedHost,\n deps: string[],\n fn: (state: T) => V,\n): ComputedRef<V> {\n let cachedValue: V;\n let dirty = true;\n const unsubs: Unsubscribe[] = [];\n\n const markDirty = () => {\n dirty = true;\n };\n\n for (const dep of deps) {\n unsubs.push(host.subscribe(dep, markDirty));\n }\n\n // Compute initial value; clean up subscriptions if it throws\n try {\n cachedValue = fn(host.getSnapshot() as T);\n } catch (e) {\n for (const unsub of unsubs) unsub();\n unsubs.length = 0;\n throw e;\n }\n dirty = false;\n\n return {\n get(): V {\n if (dirty) {\n cachedValue = fn(host.getSnapshot() as T);\n dirty = false;\n }\n return cachedValue;\n },\n destroy(): void {\n for (const unsub of unsubs) unsub();\n unsubs.length = 0;\n },\n };\n}\n","import type {\n RawStore,\n StoreOptions,\n Listener,\n Unsubscribe,\n Updater,\n ComputedRef,\n GetByPath,\n} from \"./types.js\";\nimport { SubscriptionTrie } from \"./trie.js\";\nimport { applyUpdate, getAtPath } from \"./structural.js\";\nimport { createComputed } from \"./computed.js\";\n\nexport function createStore<T extends object>(\n initialState: T,\n options: StoreOptions = {},\n): RawStore<T> {\n const { autoBatch = true } = options;\n\n let state: T = initialState;\n const trie = new SubscriptionTrie();\n\n // Batching\n let batchDepth = 0;\n let pendingPaths = new Set<string>();\n let microtaskScheduled = false;\n\n function flushNotifications(): void {\n const paths = pendingPaths;\n pendingPaths = new Set();\n microtaskScheduled = false;\n\n if (paths.size === 0) { return; }\n\n // Deduplicate: if a parent path is present, skip its children\n const sorted = [...paths].sort();\n const deduped: string[] = [];\n for (const p of sorted) {\n const last = deduped[deduped.length - 1];\n if (last !== undefined && p.startsWith(last + \".\")) { continue; }\n deduped.push(p);\n }\n\n for (const path of deduped) {\n trie.notify(path);\n }\n }\n\n function scheduleFlush(): void {\n if (batchDepth > 0) { return; }\n if (autoBatch && !microtaskScheduled) {\n microtaskScheduled = true;\n queueMicrotask(flushNotifications);\n } else if (!autoBatch) {\n flushNotifications();\n }\n }\n\n function get(): T;\n function get<P extends string>(path: P): GetByPath<T, P>;\n function get(path?: string): unknown {\n if (path === undefined || path === \"\") { return state; }\n return getAtPath(state, path);\n }\n\n function set<P extends string>(\n path: P,\n value: Updater<GetByPath<T, P>>,\n ): void {\n if (path === \"\") {\n throw new Error(\"Cannot set with an empty path. Use a specific path to update state.\");\n }\n const prev = state;\n state = applyUpdate(state, path, value);\n if (state !== prev) {\n pendingPaths.add(path);\n scheduleFlush();\n }\n }\n\n function batch(fn: () => void): void {\n batchDepth++;\n try {\n fn();\n } finally {\n batchDepth--;\n if (batchDepth === 0) {\n flushNotifications();\n }\n }\n }\n\n function subscribe(callback: Listener): Unsubscribe;\n function subscribe(path: string, callback: Listener): Unsubscribe;\n function subscribe(\n pathOrCallback: string | Listener,\n callback?: Listener,\n ): Unsubscribe {\n if (typeof pathOrCallback === \"function\") {\n return trie.addGlobal(pathOrCallback);\n }\n return trie.add(pathOrCallback, callback!);\n }\n\n function getSnapshot(): T {\n return state;\n }\n\n function computed<V>(deps: (keyof T & string)[], fn: (state: T) => V): ComputedRef<V> {\n return createComputed<T, V>({ getSnapshot, subscribe }, deps, fn);\n }\n\n function notify(): void {\n trie.notifyAll();\n }\n\n function destroy(): void {\n trie.clear();\n pendingPaths.clear();\n }\n\n return {\n get,\n set,\n batch,\n subscribe,\n getSnapshot,\n computed,\n notify,\n destroy,\n } as RawStore<T>;\n}\n","import type {\n RawStore,\n StoreOptions,\n Listener,\n Unsubscribe,\n OperationState,\n HttpClient,\n StateAccessor,\n ApiAccessor,\n ApiRequestOptions,\n} from \"./types.js\";\nimport { asyncStatus } from \"./types.js\";\nimport { createStore } from \"./store.js\";\n\nconst IDLE_STATE: OperationState = { status: asyncStatus(\"idle\"), error: null };\n\nconst defaultHttpClient: HttpClient = {\n async request(url, init) {\n const fetchInit: RequestInit = { method: init?.method ?? \"GET\" };\n const merged = { ...defaultHeaders, ...init?.headers };\n if (Object.keys(merged).length) { fetchInit.headers = merged; }\n if (init?.body !== undefined) {\n fetchInit.body = JSON.stringify(init.body);\n fetchInit.headers = { \"Content-Type\": \"application/json\", ...merged };\n }\n const res = await fetch(url, fetchInit);\n if (!res.ok) {\n let message = `HTTP ${res.status}`;\n try {\n const text = await res.text();\n if (text) {\n const json = JSON.parse(text);\n message = json.error ?? json.message ?? message;\n }\n } catch {}\n throw new Error(message);\n }\n const text = await res.text();\n return text ? JSON.parse(text) : undefined;\n },\n};\n\nlet httpClient: HttpClient = defaultHttpClient;\nlet defaultHeaders: Record<string, string> = {};\n\n/** Replace the global HTTP client used by `api.get` and `api.post/put/patch/delete`. */\nexport function setHttpClient(client: HttpClient): void {\n httpClient = client;\n}\n\n/** Set default headers merged into every HTTP request. Per-request headers override defaults. */\nexport function setDefaultHeaders(headers: Record<string, string>): void {\n defaultHeaders = headers;\n}\n\nexport class SnapStore<T extends object, K extends string = string> {\n private _store: RawStore<T>;\n private _operations = new Map<K, OperationState>();\n private _generations = new Map<K, number>();\n\n protected readonly state: StateAccessor<T>;\n protected readonly api: ApiAccessor<K>;\n\n constructor(initialState: T, options?: StoreOptions) {\n this._store = createStore(initialState, options);\n\n const store = this._store;\n const operations = this._operations;\n const generations = this._generations;\n\n // takeLatest semantic: if a newer call starts for the same key, the older\n // call's promise resolves silently (no reject, no state update).\n const doFetch = async (key: K, fn: () => Promise<void>): Promise<void> => {\n const gen = (generations.get(key) ?? 0) + 1;\n generations.set(key, gen);\n operations.set(key, { status: asyncStatus(\"loading\"), error: null });\n store.notify();\n try {\n await fn();\n if (generations.get(key) !== gen) { return; }\n operations.set(key, { status: asyncStatus(\"ready\"), error: null });\n } catch (e) {\n if (generations.get(key) !== gen) { return; }\n operations.set(key, {\n status: asyncStatus(\"error\"),\n error: e instanceof Error ? e.message : \"Unknown error\",\n });\n store.notify();\n throw e;\n }\n store.notify();\n };\n\n const doSend = async <R>(key: K, method: string, url: string, options?: ApiRequestOptions<R>): Promise<void> => {\n await doFetch(key, async () => {\n try {\n const data = await httpClient.request<R>(url, {\n method,\n body: options?.body,\n headers: options?.headers,\n });\n options?.onSuccess?.(data);\n } catch (e) {\n options?.onError?.(e instanceof Error ? e : new Error(\"Unknown error\"));\n throw e;\n }\n });\n };\n\n this.state = {\n get: ((path?: string): unknown => {\n if (path === undefined) { return store.get(); }\n return (store.get as (p: string) => unknown)(path);\n }) as StateAccessor<T>[\"get\"],\n\n set: (path, value) => store.set(path, value),\n batch: (fn) => store.batch(fn),\n computed: (deps, fn) => store.computed(deps, fn),\n\n append: (path, ...items) => {\n store.set(path as any, ((prev: any) => [...(prev as any[]), ...items]) as any);\n },\n prepend: (path, ...items) => {\n store.set(path as any, ((prev: any) => [...items, ...(prev as any[])]) as any);\n },\n insertAt: (path, index, ...items) => {\n store.set(path as any, ((prev: any) => {\n const arr = prev as any[];\n return [...arr.slice(0, index), ...items, ...arr.slice(index)];\n }) as any);\n },\n patch: (path, predicate, updates) => {\n store.set(path as any, ((prev: any) => {\n const arr = prev as any[];\n let changed = false;\n const result = arr.map((item: any) => {\n if (item == null) { return item; }\n if (predicate(item)) {\n changed = true;\n return Object.assign(Object.create(Object.getPrototypeOf(item)), item, updates);\n }\n return item;\n });\n return changed ? result : arr;\n }) as any);\n },\n remove: (path, predicate) => {\n store.set(path as any, ((prev: any) => {\n const arr = prev as any[];\n const result = arr.filter((item: any) => !predicate(item));\n return result.length === arr.length ? arr : result;\n }) as any);\n },\n removeAt: (path, index) => {\n store.set(path as any, ((prev: any) => {\n const arr = prev as any[];\n const i = index < 0 ? arr.length + index : index;\n if (i < 0 || i >= arr.length) {\n throw new RangeError(`Index ${index} out of bounds for array of length ${arr.length}`);\n }\n return [...arr.slice(0, i), ...arr.slice(i + 1)];\n }) as any);\n },\n at: (path, index) => {\n return (store.get(path as any) as any[]).at(index);\n },\n filter: (path, predicate) => {\n return (store.get(path as any) as any[]).filter(predicate);\n },\n find: (path, predicate) => {\n return (store.get(path as any) as any[]).find(predicate);\n },\n findIndexOf: (path, predicate) => {\n return (store.get(path as any) as any[]).findIndex(predicate);\n },\n count: (path, predicate) => {\n return (store.get(path as any) as any[]).filter(predicate).length;\n },\n };\n\n this.api = {\n fetch: doFetch,\n get: async <R>(key: K, url: string, onSuccess?: (data: R) => void): Promise<void> => {\n await doFetch(key, async () => {\n const data = await httpClient.request<R>(url);\n onSuccess?.(data);\n });\n },\n post: (key, url, options?) => doSend(key, \"POST\", url, options),\n put: (key, url, options?) => doSend(key, \"PUT\", url, options),\n patch: (key, url, options?) => doSend(key, \"PATCH\", url, options),\n delete: (key, url, options?) => doSend(key, \"DELETE\", url, options),\n };\n }\n\n /** Subscribe to all state changes. Returns an unsubscribe function. */\n subscribe(callback: Listener): Unsubscribe;\n /** Subscribe to changes at a specific dot-separated path. */\n subscribe(path: string, callback: Listener): Unsubscribe;\n subscribe(pathOrCallback: string | Listener, callback?: Listener): Unsubscribe {\n if (typeof pathOrCallback === \"function\") {\n return this._store.subscribe(pathOrCallback);\n }\n return this._store.subscribe(pathOrCallback, callback!);\n }\n\n /** Return a snapshot of the current state. Compatible with React's `useSyncExternalStore`. */\n getSnapshot = (): T => {\n return this._store.getSnapshot();\n };\n\n /** Get the async status of an operation by key. Returns `idle` if never started. */\n getStatus(key: K): OperationState {\n return { ...(this._operations.get(key) ?? IDLE_STATE) };\n }\n\n /** Tear down subscriptions and cleanup. */\n destroy(): void {\n this._store.destroy();\n }\n}\n"],"mappings":"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","names":["next","text","options","Connected"]}
|
|
1
|
+
{"version":3,"sources":["../../src/react/index.ts","../../src/react/store.ts","../../src/core/types.ts","../../src/core/trie.ts","../../src/core/structural.ts","../../src/core/computed.ts","../../src/core/store.ts","../../src/core/base.ts"],"sourcesContent":["export { ReactSnapStore as SnapStore } from \"./store.js\";\nexport { setHttpClient, setDefaultHeaders } from \"../core/base.js\";\nexport { asyncStatus } from \"../core/types.js\";\nexport type {\n AsyncStatus,\n AsyncStatusValue,\n OperationState,\n HttpClient,\n HttpRequestInit,\n ApiRequestOptions,\n} from \"../core/types.js\";\n","import {\n useSyncExternalStore,\n useCallback,\n useRef,\n useState,\n useEffect,\n createElement,\n forwardRef,\n} from \"react\";\nimport { SnapStore } from \"../core/base.js\";\nimport { asyncStatus } from \"../core/types.js\";\nimport type { StoreOptions, AsyncStatus, DotPaths, GetByPath } from \"../core/types.js\";\n\ninterface ConnectConfig<S, MappedProps> {\n props: (store: S) => MappedProps;\n setup?: (store: S) => void;\n fetch: (store: S) => Promise<void>;\n cleanup?: (store: S) => void;\n loading?: React.ComponentType;\n error?: React.ComponentType<{ error: string }>;\n}\n\ninterface ConnectPropsConfig<S, MappedProps> {\n props: (store: S) => MappedProps;\n setup?: (store: S) => void;\n cleanup?: (store: S) => void;\n}\n\ntype PickFn<T extends object> = <P extends DotPaths<T>>(path: P) => GetByPath<T, P>;\n\ninterface SelectConnectConfig<T extends object, MappedProps> {\n select: (pick: PickFn<T>) => MappedProps;\n}\n\nfunction shallowEqual(a: Record<string, unknown>, b: Record<string, unknown>): boolean {\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n if (keysA.length !== keysB.length) { return false; }\n for (const key of keysA) {\n if (a[key] !== b[key]) { return false; }\n }\n return true;\n}\n\nexport class ReactSnapStore<T extends object, K extends string = string> extends SnapStore<T, K> {\n constructor(initialState: T, options?: StoreOptions) {\n super(initialState, options);\n }\n\n /** Wire a component to the store, injecting props derived from state via `mapToProps`. */\n connect<P extends object, MappedProps extends Record<string, unknown>>(\n Component: React.ComponentType<P>,\n mapToProps: (store: this) => MappedProps,\n ): React.FC<Omit<P, keyof MappedProps>>;\n /** Wire a component to the store with async data fetching, loading, and error handling. */\n connect<P extends object, MappedProps extends Record<string, unknown>>(\n Component: React.ComponentType<P>,\n config: ConnectConfig<this, MappedProps>,\n ): React.FC<Omit<P, keyof MappedProps | \"status\" | \"error\">>;\n /** Wire a component to the store with props mapping and optional cleanup. */\n connect<P extends object, MappedProps extends Record<string, unknown>>(\n Component: React.ComponentType<P>,\n config: ConnectPropsConfig<this, MappedProps>,\n ): React.FC<Omit<P, keyof MappedProps>>;\n /** Wire a component to the store with granular path-based subscriptions via `select`.\n * Paths are captured once at connect-time — select must use a stable set of paths.\n * For conditional/dynamic path selection, use the `mapToProps` overload instead. */\n connect<P extends object, MappedProps extends Record<string, unknown>>(\n Component: React.ComponentType<P>,\n config: SelectConnectConfig<T, MappedProps>,\n ): React.FC<Omit<P, keyof MappedProps>>;\n connect<P extends object, MappedProps extends Record<string, unknown>>(\n Component: React.ComponentType<P>,\n configOrMapper:\n | ((store: this) => MappedProps)\n | ConnectPropsConfig<this, MappedProps>\n | ConnectConfig<this, MappedProps>\n | SelectConnectConfig<T, MappedProps>,\n ): React.FC<Omit<P, keyof MappedProps>> {\n const store = this;\n\n if (typeof configOrMapper === \"object\" && \"select\" in configOrMapper) {\n return this._connectWithSelect<P, MappedProps>(Component, configOrMapper.select);\n }\n\n const config = typeof configOrMapper === \"function\"\n ? null\n : configOrMapper as ConnectConfig<this, MappedProps>;\n const mapToProps = config ? config.props : configOrMapper as (store: this) => MappedProps;\n const fetchFn = config?.fetch;\n const loadingComponent = config?.loading;\n const errorComponent = config?.error;\n const setupFn = config?.setup;\n const cleanupFn = config?.cleanup;\n\n const Connected = forwardRef<unknown, Omit<P, keyof MappedProps>>(function Connected(ownProps, ref) {\n const cachedRef = useRef<{ revision: number; props: MappedProps } | null>(null);\n const revisionRef = useRef(0);\n\n const subscribe = useCallback(\n (cb: () => void) => store.subscribe(() => {\n revisionRef.current++;\n cb();\n }),\n [store],\n );\n\n const getSnapshot = useCallback(() => {\n const currentRevision = revisionRef.current;\n if (cachedRef.current && cachedRef.current.revision === currentRevision) {\n return cachedRef.current.props;\n }\n const next = mapToProps(store);\n if (cachedRef.current && shallowEqual(cachedRef.current.props, next)) {\n cachedRef.current = { revision: currentRevision, props: cachedRef.current.props };\n return cachedRef.current.props;\n }\n cachedRef.current = { revision: currentRevision, props: next };\n return next;\n }, [store]);\n\n const mappedProps = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n\n const [asyncState, setAsyncState] = useState<{\n status: AsyncStatus;\n error: string | null;\n }>({ status: asyncStatus(\"idle\"), error: null });\n\n const fetchGenRef = useRef(0);\n\n const lifecycleGenRef = useRef(0);\n useEffect(() => {\n if (!setupFn && !cleanupFn) return;\n const gen = ++lifecycleGenRef.current;\n if (setupFn) {\n queueMicrotask(() => {\n if (gen === lifecycleGenRef.current) setupFn(store);\n });\n }\n return () => {\n const teardownGen = lifecycleGenRef.current;\n if (cleanupFn) {\n queueMicrotask(() => {\n if (teardownGen === lifecycleGenRef.current) cleanupFn(store);\n });\n }\n };\n }, []);\n\n useEffect(() => {\n if (!fetchFn) { return; }\n let cancelled = false;\n const gen = ++fetchGenRef.current;\n setAsyncState({ status: asyncStatus(\"loading\"), error: null });\n Promise.resolve()\n .then(() => {\n if (cancelled) { return; }\n return fetchFn(store);\n })\n .then(() => {\n if (gen === fetchGenRef.current) {\n setAsyncState({ status: asyncStatus(\"ready\"), error: null });\n }\n })\n .catch((e) => {\n if (gen === fetchGenRef.current) {\n setAsyncState({\n status: asyncStatus(\"error\"),\n error: e instanceof Error ? e.message : \"Unknown error\",\n });\n }\n });\n return () => { cancelled = true; };\n }, []);\n\n if (fetchFn) {\n if (loadingComponent && (asyncState.status.isIdle || asyncState.status.isLoading)) {\n return createElement(loadingComponent);\n }\n if (errorComponent && asyncState.status.isError) {\n return createElement(errorComponent, { error: asyncState.error! });\n }\n }\n\n return createElement(Component, {\n ...ownProps,\n ...mappedProps,\n ...(fetchFn ? asyncState : {}),\n ref,\n } as unknown as P);\n });\n\n Connected.displayName = `Connect(${Component.displayName || Component.name || \"Component\"})`;\n return Connected as unknown as React.FC<Omit<P, keyof MappedProps>>;\n }\n\n private _connectWithSelect<P extends object, MappedProps extends Record<string, unknown>>(\n Component: React.ComponentType<P>,\n selectFn: (pick: PickFn<T>) => MappedProps,\n ): React.FC<Omit<P, keyof MappedProps>> {\n const store = this;\n\n const resolvePathValue = (path: string): any => {\n const segments = path.split(\".\");\n let val: any = store.getSnapshot();\n for (const seg of segments) {\n if (val == null) { return undefined; }\n val = val[seg];\n }\n return val;\n };\n\n const trackedPaths: string[] = [];\n const trackingPick: PickFn<T> = ((path: string) => {\n trackedPaths.push(path);\n return resolvePathValue(path);\n }) as PickFn<T>;\n selectFn(trackingPick);\n const paths = [...trackedPaths];\n\n const readPick: PickFn<T> = ((path: string) => {\n return resolvePathValue(path);\n }) as PickFn<T>;\n\n const Connected = forwardRef<unknown, Omit<P, keyof MappedProps>>(function Connected(ownProps, ref) {\n const cachedRef = useRef<{ revision: number; props: MappedProps } | null>(null);\n const revisionRef = useRef(0);\n\n const subscribe = useCallback(\n (cb: () => void) => {\n const unsubs = paths.map((p) =>\n store.subscribe(p, () => {\n revisionRef.current++;\n cb();\n }),\n );\n return () => unsubs.forEach((u) => u());\n },\n [store],\n );\n\n const getSnapshot = useCallback(() => {\n const currentRevision = revisionRef.current;\n if (cachedRef.current && cachedRef.current.revision === currentRevision) {\n return cachedRef.current.props;\n }\n const next = selectFn(readPick);\n if (cachedRef.current && shallowEqual(cachedRef.current.props, next)) {\n cachedRef.current = { revision: currentRevision, props: cachedRef.current.props };\n return cachedRef.current.props;\n }\n cachedRef.current = { revision: currentRevision, props: next };\n return next;\n }, [store]);\n\n const mappedProps = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n\n return createElement(Component, {\n ...ownProps,\n ...mappedProps,\n ref,\n } as unknown as P);\n });\n\n Connected.displayName = `Connect(${Component.displayName || Component.name || \"Component\"})`;\n return Connected as unknown as React.FC<Omit<P, keyof MappedProps>>;\n }\n}\n","export type AsyncStatusValue = \"idle\" | \"loading\" | \"ready\" | \"error\";\n\nexport interface AsyncStatus {\n readonly value: AsyncStatusValue;\n readonly isIdle: boolean;\n readonly isLoading: boolean;\n readonly isReady: boolean;\n readonly isError: boolean;\n}\n\nconst _statuses: Record<AsyncStatusValue, AsyncStatus> = {\n idle: Object.freeze({ value: \"idle\", isIdle: true, isLoading: false, isReady: false, isError: false }),\n loading: Object.freeze({ value: \"loading\", isIdle: false, isLoading: true, isReady: false, isError: false }),\n ready: Object.freeze({ value: \"ready\", isIdle: false, isLoading: false, isReady: true, isError: false }),\n error: Object.freeze({ value: \"error\", isIdle: false, isLoading: false, isReady: false, isError: true }),\n};\n\nexport function asyncStatus(value: AsyncStatusValue): AsyncStatus {\n return _statuses[value];\n}\n\n/** Async operation status and error. Tracks the lifecycle of an `api.fetch`/`api.get`/`api.post` call. */\nexport interface OperationState {\n status: AsyncStatus;\n error: string | null;\n}\n\nexport type Path = string & { readonly __brand?: \"Path\" };\n\nexport type Listener = () => void;\n\nexport type Unsubscribe = () => void;\n\n// Union of all valid dot-separated paths into T (for autocomplete)\nexport type DotPaths<T, Prefix extends string = \"\"> = T extends object\n ? { [K in keyof T & string]:\n | `${Prefix}${K}`\n | DotPaths<T[K], `${Prefix}${K}.`>\n }[keyof T & string]\n : never;\n\n// Extract a deeply nested type by dot-separated path\nexport type GetByPath<T, P extends string> = P extends \"\"\n ? T\n : P extends `${infer K}.${infer Rest}`\n ? K extends keyof T\n ? GetByPath<T[K], Rest>\n : never\n : P extends keyof T\n ? T[P]\n : never;\n\nexport type DeepPartial<T> = T extends object\n ? { [K in keyof T]?: DeepPartial<T[K]> }\n : T;\n\nexport type ArrayPaths<T> = {\n [K in keyof T & string]: T[K] extends any[] ? K : never;\n}[keyof T & string];\n\nexport type ObjectArrayPaths<T> = {\n [K in keyof T & string]: T[K] extends (infer V)[]\n ? V extends Date | RegExp | Map<any, any> | Set<any> | Function | any[]\n ? never\n : V extends Record<string, any> ? K : never\n : never;\n}[keyof T & string];\n\nexport type ElementOf<A> = A extends (infer V)[] ? V : never;\n\nexport type Updater<V> = V | ((prev: V) => V);\n\nexport interface StoreOptions {\n /** Auto-batch synchronous sets via microtask (default: true) */\n autoBatch?: boolean;\n}\n\n/** Handle to a computed (derived) value. Call `get()` to read, `destroy()` to stop tracking. */\nexport interface ComputedRef<V> {\n get(): V;\n destroy(): void;\n}\n\n/** Options for an HTTP request (method, body, headers). */\nexport interface HttpRequestInit {\n method?: string;\n body?: unknown;\n headers?: Record<string, string>;\n}\n\n/** Interface for the HTTP layer used by `api.get` and `api.post/put/patch/delete`. */\nexport interface HttpClient {\n request<R = unknown>(url: string, init?: HttpRequestInit): Promise<R>;\n}\n\n/** Options for HTTP verb methods (`api.post`, `api.put`, etc.). */\nexport interface ApiRequestOptions<R = unknown> {\n body?: unknown;\n headers?: Record<string, string>;\n onSuccess?: (data: R) => void;\n onError?: (error: Error) => void;\n}\n\nexport interface Subscribable<T extends object> {\n subscribe(callback: Listener): Unsubscribe;\n getSnapshot(): T;\n}\n\nexport interface StateAccessor<T extends object> {\n get(): T;\n get<P extends DotPaths<T>>(path: P): GetByPath<T, P>;\n set<P extends DotPaths<T>>(path: P, value: Updater<GetByPath<T, P>>): void;\n batch(fn: () => void): void;\n computed<V>(deps: (keyof T & string)[], fn: (state: T) => V): ComputedRef<V>;\n append<P extends ArrayPaths<T>>(path: P, ...items: ElementOf<T[P]>[]): void;\n prepend<P extends ArrayPaths<T>>(path: P, ...items: ElementOf<T[P]>[]): void;\n insertAt<P extends ArrayPaths<T>>(path: P, index: number, ...items: ElementOf<T[P]>[]): void;\n patch<P extends ObjectArrayPaths<T>>(path: P, predicate: (item: ElementOf<T[P]>) => boolean, updates: Partial<ElementOf<T[P]>>): void;\n remove<P extends ArrayPaths<T>>(path: P, predicate: (item: ElementOf<T[P]>) => boolean): void;\n removeAt<P extends ArrayPaths<T>>(path: P, index: number): void;\n at<P extends ArrayPaths<T>>(path: P, index: number): ElementOf<T[P]> | undefined;\n filter<P extends ArrayPaths<T>>(path: P, predicate: (item: ElementOf<T[P]>) => boolean): ElementOf<T[P]>[];\n find<P extends ArrayPaths<T>>(path: P, predicate: (item: ElementOf<T[P]>) => boolean): ElementOf<T[P]> | undefined;\n findIndexOf<P extends ArrayPaths<T>>(path: P, predicate: (item: ElementOf<T[P]>) => boolean): number;\n count<P extends ArrayPaths<T>>(path: P, predicate: (item: ElementOf<T[P]>) => boolean): number;\n}\n\nexport interface ApiAccessor<K extends string> {\n fetch(key: K, fn: () => Promise<void>): Promise<void>;\n get<R = unknown>(key: K, url: string, onSuccess?: (data: R) => void): Promise<void>;\n post<R = unknown>(key: K, url: string, options?: ApiRequestOptions<R>): Promise<void>;\n put<R = unknown>(key: K, url: string, options?: ApiRequestOptions<R>): Promise<void>;\n patch<R = unknown>(key: K, url: string, options?: ApiRequestOptions<R>): Promise<void>;\n delete<R = unknown>(key: K, url: string, options?: ApiRequestOptions<R>): Promise<void>;\n}\n\nexport interface RawStore<T extends object> extends Subscribable<T> {\n get(): T;\n get<P extends DotPaths<T>>(path: P): GetByPath<T, P>;\n\n set<P extends DotPaths<T>>(path: P, value: Updater<GetByPath<T, P>>): void;\n\n batch(fn: () => void): void;\n\n subscribe(callback: Listener): Unsubscribe;\n subscribe(path: string, callback: Listener): Unsubscribe;\n\n getSnapshot(): T;\n\n computed<V>(deps: (keyof T & string)[], fn: (state: T) => V): ComputedRef<V>;\n\n notify(): void;\n\n destroy(): void;\n}\n","import type { Listener, Unsubscribe } from \"./types.js\";\n\nfunction invokeAll(listeners: Set<Listener>): void {\n let firstError: unknown;\n for (const l of listeners) {\n try { l(); } catch (e) { firstError ??= e; }\n }\n if (firstError !== undefined) { throw firstError; }\n}\n\ninterface TrieNode {\n listeners: Set<Listener>;\n children: Map<string, TrieNode>;\n}\n\nfunction createNode(): TrieNode {\n return { listeners: new Set(), children: new Map() };\n}\n\nfunction parsePath(path: string): string[] {\n if (path === \"\") { return []; }\n return path.split(\".\");\n}\n\nexport class SubscriptionTrie {\n private root = createNode();\n private globalListeners = new Set<Listener>();\n\n /** Subscribe to a specific path. Returns unsubscribe function. */\n add(path: string, listener: Listener): Unsubscribe {\n const segments = parsePath(path);\n const parents: { parent: TrieNode; segment: string }[] = [];\n let node = this.root;\n for (const seg of segments) {\n if (!node.children.has(seg)) {\n node.children.set(seg, createNode());\n }\n parents.push({ parent: node, segment: seg });\n node = node.children.get(seg)!;\n }\n node.listeners.add(listener);\n return () => {\n node.listeners.delete(listener);\n for (let i = parents.length - 1; i >= 0; i--) {\n const { parent, segment } = parents[i];\n const child = parent.children.get(segment)!;\n if (child.listeners.size === 0 && child.children.size === 0) {\n parent.children.delete(segment);\n } else {\n break;\n }\n }\n };\n }\n\n /** Subscribe to all changes (no path filter). */\n addGlobal(listener: Listener): Unsubscribe {\n this.globalListeners.add(listener);\n return () => {\n this.globalListeners.delete(listener);\n };\n }\n\n /** Notify listeners for exact path, all ancestors, and all descendants. */\n notify(path: string): void {\n const segments = parsePath(path);\n const collected = new Set<Listener>();\n\n // Collect global listeners\n for (const l of this.globalListeners) collected.add(l);\n\n // Walk down to the target, collecting ancestor listeners\n let node = this.root;\n // Root-level listeners (subscribe to \"\")\n for (const l of node.listeners) collected.add(l);\n\n let matched = true;\n for (const seg of segments) {\n // Check wildcard sibling at this level\n const wildcard = node.children.get(\"*\");\n if (wildcard) {\n for (const l of wildcard.listeners) collected.add(l);\n this.collectDescendants(wildcard, collected);\n }\n\n const child = node.children.get(seg);\n if (!child) {\n matched = false;\n break;\n }\n node = child;\n for (const l of node.listeners) collected.add(l);\n }\n\n // Only collect descendants if we matched the full path\n if (matched) {\n this.collectDescendants(node, collected);\n }\n\n invokeAll(collected);\n }\n\n /** Notify all listeners in the trie. */\n notifyAll(): void {\n const collected = new Set<Listener>();\n for (const l of this.globalListeners) collected.add(l);\n this.collectDescendants(this.root, collected);\n for (const l of this.root.listeners) collected.add(l);\n invokeAll(collected);\n }\n\n private collectDescendants(node: TrieNode, out: Set<Listener>): void {\n for (const child of node.children.values()) {\n for (const l of child.listeners) out.add(l);\n this.collectDescendants(child, out);\n }\n }\n\n clear(): void {\n this.root = createNode();\n this.globalListeners.clear();\n }\n}\n","/**\n * Immutable update with structural sharing.\n * Only clones objects along the changed path; unchanged subtrees keep their references.\n */\nexport function applyUpdate<T extends object>(\n state: T,\n path: string,\n value: unknown,\n): T {\n const segments = path.split(\".\");\n return updateAtPath(state, segments, 0, value) as T;\n}\n\nfunction updateAtPath(\n current: unknown,\n segments: string[],\n index: number,\n value: unknown,\n): unknown {\n if (index === segments.length) {\n // Functional updater support\n if (typeof value === \"function\") {\n return (value as (prev: unknown) => unknown)(current);\n }\n return value;\n }\n\n const key = segments[index];\n\n if (Array.isArray(current)) {\n const i = Number(key);\n const next = updateAtPath(current[i], segments, index + 1, value);\n if (Object.is(next, current[i])) { return current; }\n const copy = current.slice();\n copy[i] = next;\n return copy;\n }\n\n if (current !== null && typeof current === \"object\") {\n const obj = current as Record<string, unknown>;\n const next = updateAtPath(obj[key], segments, index + 1, value);\n if (Object.is(next, obj[key])) { return current; }\n return { ...obj, [key]: next };\n }\n\n // Path doesn't exist yet — create nested objects\n const next = updateAtPath(undefined, segments, index + 1, value);\n return { [key]: next };\n}\n\n/** Read a value at a dot-separated path. */\nexport function getAtPath(state: unknown, path: string): unknown {\n if (path === \"\") { return state; }\n const segments = path.split(\".\");\n let current = state;\n for (const seg of segments) {\n if (current === null || current === undefined) { return undefined; }\n current = (current as Record<string, unknown>)[seg];\n }\n return current;\n}\n","import type { ComputedRef, Listener, Unsubscribe } from \"./types.js\";\n\ninterface ComputedHost {\n getSnapshot(): object;\n subscribe(path: string, callback: Listener): Unsubscribe;\n}\n\nexport function createComputed<T extends object, V>(\n host: ComputedHost,\n deps: string[],\n fn: (state: T) => V,\n): ComputedRef<V> {\n let cachedValue: V;\n let dirty = true;\n const unsubs: Unsubscribe[] = [];\n\n const markDirty = () => {\n dirty = true;\n };\n\n for (const dep of deps) {\n unsubs.push(host.subscribe(dep, markDirty));\n }\n\n // Compute initial value; clean up subscriptions if it throws\n try {\n cachedValue = fn(host.getSnapshot() as T);\n } catch (e) {\n for (const unsub of unsubs) unsub();\n unsubs.length = 0;\n throw e;\n }\n dirty = false;\n\n return {\n get(): V {\n if (dirty) {\n cachedValue = fn(host.getSnapshot() as T);\n dirty = false;\n }\n return cachedValue;\n },\n destroy(): void {\n for (const unsub of unsubs) unsub();\n unsubs.length = 0;\n },\n };\n}\n","import type {\n RawStore,\n StoreOptions,\n Listener,\n Unsubscribe,\n Updater,\n ComputedRef,\n GetByPath,\n} from \"./types.js\";\nimport { SubscriptionTrie } from \"./trie.js\";\nimport { applyUpdate, getAtPath } from \"./structural.js\";\nimport { createComputed } from \"./computed.js\";\n\nexport function createStore<T extends object>(\n initialState: T,\n options: StoreOptions = {},\n): RawStore<T> {\n const { autoBatch = true } = options;\n\n let state: T = initialState;\n const trie = new SubscriptionTrie();\n\n // Batching\n let batchDepth = 0;\n let pendingPaths = new Set<string>();\n let microtaskScheduled = false;\n\n function flushNotifications(): void {\n const paths = pendingPaths;\n pendingPaths = new Set();\n microtaskScheduled = false;\n\n if (paths.size === 0) { return; }\n\n // Deduplicate: if a parent path is present, skip its children\n const sorted = [...paths].sort();\n const deduped: string[] = [];\n for (const p of sorted) {\n const last = deduped[deduped.length - 1];\n if (last !== undefined && p.startsWith(last + \".\")) { continue; }\n deduped.push(p);\n }\n\n for (const path of deduped) {\n trie.notify(path);\n }\n }\n\n function scheduleFlush(): void {\n if (batchDepth > 0) { return; }\n if (autoBatch && !microtaskScheduled) {\n microtaskScheduled = true;\n queueMicrotask(flushNotifications);\n } else if (!autoBatch) {\n flushNotifications();\n }\n }\n\n function get(): T;\n function get<P extends string>(path: P): GetByPath<T, P>;\n function get(path?: string): unknown {\n if (path === undefined || path === \"\") { return state; }\n return getAtPath(state, path);\n }\n\n function set<P extends string>(\n path: P,\n value: Updater<GetByPath<T, P>>,\n ): void {\n if (path === \"\") {\n throw new Error(\"Cannot set with an empty path. Use a specific path to update state.\");\n }\n const prev = state;\n state = applyUpdate(state, path, value);\n if (state !== prev) {\n pendingPaths.add(path);\n scheduleFlush();\n }\n }\n\n function batch(fn: () => void): void {\n batchDepth++;\n try {\n fn();\n } finally {\n batchDepth--;\n if (batchDepth === 0) {\n flushNotifications();\n }\n }\n }\n\n function subscribe(callback: Listener): Unsubscribe;\n function subscribe(path: string, callback: Listener): Unsubscribe;\n function subscribe(\n pathOrCallback: string | Listener,\n callback?: Listener,\n ): Unsubscribe {\n if (typeof pathOrCallback === \"function\") {\n return trie.addGlobal(pathOrCallback);\n }\n return trie.add(pathOrCallback, callback!);\n }\n\n function getSnapshot(): T {\n return state;\n }\n\n function computed<V>(deps: (keyof T & string)[], fn: (state: T) => V): ComputedRef<V> {\n return createComputed<T, V>({ getSnapshot, subscribe }, deps, fn);\n }\n\n function notify(): void {\n trie.notifyAll();\n }\n\n function destroy(): void {\n trie.clear();\n pendingPaths.clear();\n }\n\n return {\n get,\n set,\n batch,\n subscribe,\n getSnapshot,\n computed,\n notify,\n destroy,\n } as RawStore<T>;\n}\n","import type {\n RawStore,\n StoreOptions,\n Listener,\n Unsubscribe,\n OperationState,\n HttpClient,\n StateAccessor,\n ApiAccessor,\n ApiRequestOptions,\n} from \"./types.js\";\nimport { asyncStatus } from \"./types.js\";\nimport { createStore } from \"./store.js\";\n\nconst IDLE_STATE: OperationState = { status: asyncStatus(\"idle\"), error: null };\n\nconst defaultHttpClient: HttpClient = {\n async request(url, init) {\n const fetchInit: RequestInit = { method: init?.method ?? \"GET\" };\n const merged = { ...defaultHeaders, ...init?.headers };\n if (Object.keys(merged).length) { fetchInit.headers = merged; }\n if (init?.body !== undefined) {\n fetchInit.body = JSON.stringify(init.body);\n fetchInit.headers = { \"Content-Type\": \"application/json\", ...merged };\n }\n const res = await fetch(url, fetchInit);\n if (!res.ok) {\n let message = `HTTP ${res.status}`;\n try {\n const text = await res.text();\n if (text) {\n const json = JSON.parse(text);\n message = json.error ?? json.message ?? message;\n }\n } catch {}\n throw new Error(message);\n }\n const text = await res.text();\n return text ? JSON.parse(text) : undefined;\n },\n};\n\nlet httpClient: HttpClient = defaultHttpClient;\nlet defaultHeaders: Record<string, string> = {};\n\n/** Replace the global HTTP client used by `api.get` and `api.post/put/patch/delete`. */\nexport function setHttpClient(client: HttpClient): void {\n httpClient = client;\n}\n\n/** Set default headers merged into every HTTP request. Per-request headers override defaults. */\nexport function setDefaultHeaders(headers: Record<string, string>): void {\n defaultHeaders = headers;\n}\n\nexport class SnapStore<T extends object, K extends string = string> {\n private _store: RawStore<T>;\n private _operations = new Map<K, OperationState>();\n private _generations = new Map<K, number>();\n\n protected readonly state: StateAccessor<T>;\n protected readonly api: ApiAccessor<K>;\n\n constructor(initialState: T, options?: StoreOptions) {\n this._store = createStore(initialState, options);\n\n const store = this._store;\n const operations = this._operations;\n const generations = this._generations;\n\n // takeLatest semantic: if a newer call starts for the same key, the older\n // call's promise resolves silently (no reject, no state update).\n const doFetch = async (key: K, fn: () => Promise<void>): Promise<void> => {\n const gen = (generations.get(key) ?? 0) + 1;\n generations.set(key, gen);\n operations.set(key, { status: asyncStatus(\"loading\"), error: null });\n store.notify();\n try {\n await fn();\n if (generations.get(key) !== gen) { return; }\n operations.set(key, { status: asyncStatus(\"ready\"), error: null });\n } catch (e) {\n if (generations.get(key) !== gen) { return; }\n operations.set(key, {\n status: asyncStatus(\"error\"),\n error: e instanceof Error ? e.message : \"Unknown error\",\n });\n store.notify();\n throw e;\n }\n store.notify();\n };\n\n const doSend = async <R>(key: K, method: string, url: string, options?: ApiRequestOptions<R>): Promise<void> => {\n await doFetch(key, async () => {\n try {\n const data = await httpClient.request<R>(url, {\n method,\n body: options?.body,\n headers: options?.headers,\n });\n options?.onSuccess?.(data);\n } catch (e) {\n options?.onError?.(e instanceof Error ? e : new Error(\"Unknown error\"));\n throw e;\n }\n });\n };\n\n this.state = {\n get: ((path?: string): unknown => {\n if (path === undefined) { return store.get(); }\n return (store.get as (p: string) => unknown)(path);\n }) as StateAccessor<T>[\"get\"],\n\n set: (path, value) => store.set(path, value),\n batch: (fn) => store.batch(fn),\n computed: (deps, fn) => store.computed(deps, fn),\n\n append: (path, ...items) => {\n store.set(path as any, ((prev: any) => [...(prev as any[]), ...items]) as any);\n },\n prepend: (path, ...items) => {\n store.set(path as any, ((prev: any) => [...items, ...(prev as any[])]) as any);\n },\n insertAt: (path, index, ...items) => {\n store.set(path as any, ((prev: any) => {\n const arr = prev as any[];\n return [...arr.slice(0, index), ...items, ...arr.slice(index)];\n }) as any);\n },\n patch: (path, predicate, updates) => {\n store.set(path as any, ((prev: any) => {\n const arr = prev as any[];\n let changed = false;\n const result = arr.map((item: any) => {\n if (item == null) { return item; }\n if (predicate(item)) {\n changed = true;\n return Object.assign(Object.create(Object.getPrototypeOf(item)), item, updates);\n }\n return item;\n });\n return changed ? result : arr;\n }) as any);\n },\n remove: (path, predicate) => {\n store.set(path as any, ((prev: any) => {\n const arr = prev as any[];\n const result = arr.filter((item: any) => !predicate(item));\n return result.length === arr.length ? arr : result;\n }) as any);\n },\n removeAt: (path, index) => {\n store.set(path as any, ((prev: any) => {\n const arr = prev as any[];\n const i = index < 0 ? arr.length + index : index;\n if (i < 0 || i >= arr.length) {\n throw new RangeError(`Index ${index} out of bounds for array of length ${arr.length}`);\n }\n return [...arr.slice(0, i), ...arr.slice(i + 1)];\n }) as any);\n },\n at: (path, index) => {\n return (store.get(path as any) as any[]).at(index);\n },\n filter: (path, predicate) => {\n return (store.get(path as any) as any[]).filter(predicate);\n },\n find: (path, predicate) => {\n return (store.get(path as any) as any[]).find(predicate);\n },\n findIndexOf: (path, predicate) => {\n return (store.get(path as any) as any[]).findIndex(predicate);\n },\n count: (path, predicate) => {\n return (store.get(path as any) as any[]).filter(predicate).length;\n },\n };\n\n this.api = {\n fetch: doFetch,\n get: async <R>(key: K, url: string, onSuccess?: (data: R) => void): Promise<void> => {\n await doFetch(key, async () => {\n const data = await httpClient.request<R>(url);\n onSuccess?.(data);\n });\n },\n post: (key, url, options?) => doSend(key, \"POST\", url, options),\n put: (key, url, options?) => doSend(key, \"PUT\", url, options),\n patch: (key, url, options?) => doSend(key, \"PATCH\", url, options),\n delete: (key, url, options?) => doSend(key, \"DELETE\", url, options),\n };\n }\n\n /** Subscribe to all state changes. Returns an unsubscribe function. */\n subscribe(callback: Listener): Unsubscribe;\n /** Subscribe to changes at a specific dot-separated path. */\n subscribe(path: string, callback: Listener): Unsubscribe;\n subscribe(pathOrCallback: string | Listener, callback?: Listener): Unsubscribe {\n if (typeof pathOrCallback === \"function\") {\n return this._store.subscribe(pathOrCallback);\n }\n return this._store.subscribe(pathOrCallback, callback!);\n }\n\n /** Return a snapshot of the current state. Compatible with React's `useSyncExternalStore`. */\n getSnapshot = (): T => {\n return this._store.getSnapshot();\n };\n\n /** Get the async status of an operation by key. Returns `idle` if never started. */\n getStatus(key: K): OperationState {\n return { ...(this._operations.get(key) ?? IDLE_STATE) };\n }\n\n /** Tear down subscriptions and cleanup. */\n destroy(): void {\n this._store.destroy();\n }\n}\n"],"mappings":"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","names":["next","text","options","Connected"]}
|
package/dist/react/index.d.cts
CHANGED
|
@@ -104,12 +104,19 @@ declare class SnapStore<T extends object, K extends string = string> {
|
|
|
104
104
|
|
|
105
105
|
interface ConnectConfig<S, MappedProps> {
|
|
106
106
|
props: (store: S) => MappedProps;
|
|
107
|
+
setup?: (store: S) => void;
|
|
107
108
|
fetch: (store: S) => Promise<void>;
|
|
109
|
+
cleanup?: (store: S) => void;
|
|
108
110
|
loading?: React.ComponentType;
|
|
109
111
|
error?: React.ComponentType<{
|
|
110
112
|
error: string;
|
|
111
113
|
}>;
|
|
112
114
|
}
|
|
115
|
+
interface ConnectPropsConfig<S, MappedProps> {
|
|
116
|
+
props: (store: S) => MappedProps;
|
|
117
|
+
setup?: (store: S) => void;
|
|
118
|
+
cleanup?: (store: S) => void;
|
|
119
|
+
}
|
|
113
120
|
type PickFn<T extends object> = <P extends DotPaths<T>>(path: P) => GetByPath<T, P>;
|
|
114
121
|
interface SelectConnectConfig<T extends object, MappedProps> {
|
|
115
122
|
select: (pick: PickFn<T>) => MappedProps;
|
|
@@ -120,6 +127,8 @@ declare class ReactSnapStore<T extends object, K extends string = string> extend
|
|
|
120
127
|
connect<P extends object, MappedProps extends Record<string, unknown>>(Component: React.ComponentType<P>, mapToProps: (store: this) => MappedProps): React.FC<Omit<P, keyof MappedProps>>;
|
|
121
128
|
/** Wire a component to the store with async data fetching, loading, and error handling. */
|
|
122
129
|
connect<P extends object, MappedProps extends Record<string, unknown>>(Component: React.ComponentType<P>, config: ConnectConfig<this, MappedProps>): React.FC<Omit<P, keyof MappedProps | "status" | "error">>;
|
|
130
|
+
/** Wire a component to the store with props mapping and optional cleanup. */
|
|
131
|
+
connect<P extends object, MappedProps extends Record<string, unknown>>(Component: React.ComponentType<P>, config: ConnectPropsConfig<this, MappedProps>): React.FC<Omit<P, keyof MappedProps>>;
|
|
123
132
|
/** Wire a component to the store with granular path-based subscriptions via `select`.
|
|
124
133
|
* Paths are captured once at connect-time — select must use a stable set of paths.
|
|
125
134
|
* For conditional/dynamic path selection, use the `mapToProps` overload instead. */
|
package/dist/react/index.d.ts
CHANGED
|
@@ -104,12 +104,19 @@ declare class SnapStore<T extends object, K extends string = string> {
|
|
|
104
104
|
|
|
105
105
|
interface ConnectConfig<S, MappedProps> {
|
|
106
106
|
props: (store: S) => MappedProps;
|
|
107
|
+
setup?: (store: S) => void;
|
|
107
108
|
fetch: (store: S) => Promise<void>;
|
|
109
|
+
cleanup?: (store: S) => void;
|
|
108
110
|
loading?: React.ComponentType;
|
|
109
111
|
error?: React.ComponentType<{
|
|
110
112
|
error: string;
|
|
111
113
|
}>;
|
|
112
114
|
}
|
|
115
|
+
interface ConnectPropsConfig<S, MappedProps> {
|
|
116
|
+
props: (store: S) => MappedProps;
|
|
117
|
+
setup?: (store: S) => void;
|
|
118
|
+
cleanup?: (store: S) => void;
|
|
119
|
+
}
|
|
113
120
|
type PickFn<T extends object> = <P extends DotPaths<T>>(path: P) => GetByPath<T, P>;
|
|
114
121
|
interface SelectConnectConfig<T extends object, MappedProps> {
|
|
115
122
|
select: (pick: PickFn<T>) => MappedProps;
|
|
@@ -120,6 +127,8 @@ declare class ReactSnapStore<T extends object, K extends string = string> extend
|
|
|
120
127
|
connect<P extends object, MappedProps extends Record<string, unknown>>(Component: React.ComponentType<P>, mapToProps: (store: this) => MappedProps): React.FC<Omit<P, keyof MappedProps>>;
|
|
121
128
|
/** Wire a component to the store with async data fetching, loading, and error handling. */
|
|
122
129
|
connect<P extends object, MappedProps extends Record<string, unknown>>(Component: React.ComponentType<P>, config: ConnectConfig<this, MappedProps>): React.FC<Omit<P, keyof MappedProps | "status" | "error">>;
|
|
130
|
+
/** Wire a component to the store with props mapping and optional cleanup. */
|
|
131
|
+
connect<P extends object, MappedProps extends Record<string, unknown>>(Component: React.ComponentType<P>, config: ConnectPropsConfig<this, MappedProps>): React.FC<Omit<P, keyof MappedProps>>;
|
|
123
132
|
/** Wire a component to the store with granular path-based subscriptions via `select`.
|
|
124
133
|
* Paths are captured once at connect-time — select must use a stable set of paths.
|
|
125
134
|
* For conditional/dynamic path selection, use the `mapToProps` overload instead. */
|
package/dist/react/index.js
CHANGED
|
@@ -524,10 +524,13 @@ var ReactSnapStore = class extends SnapStore {
|
|
|
524
524
|
if (typeof configOrMapper === "object" && "select" in configOrMapper) {
|
|
525
525
|
return this._connectWithSelect(Component, configOrMapper.select);
|
|
526
526
|
}
|
|
527
|
-
const
|
|
528
|
-
const
|
|
529
|
-
const
|
|
530
|
-
const
|
|
527
|
+
const config = typeof configOrMapper === "function" ? null : configOrMapper;
|
|
528
|
+
const mapToProps = config ? config.props : configOrMapper;
|
|
529
|
+
const fetchFn = config?.fetch;
|
|
530
|
+
const loadingComponent = config?.loading;
|
|
531
|
+
const errorComponent = config?.error;
|
|
532
|
+
const setupFn = config?.setup;
|
|
533
|
+
const cleanupFn = config?.cleanup;
|
|
531
534
|
const Connected = forwardRef(function Connected2(ownProps, ref) {
|
|
532
535
|
const cachedRef = useRef(null);
|
|
533
536
|
const revisionRef = useRef(0);
|
|
@@ -554,6 +557,24 @@ var ReactSnapStore = class extends SnapStore {
|
|
|
554
557
|
const mappedProps = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
555
558
|
const [asyncState, setAsyncState] = useState({ status: asyncStatus("idle"), error: null });
|
|
556
559
|
const fetchGenRef = useRef(0);
|
|
560
|
+
const lifecycleGenRef = useRef(0);
|
|
561
|
+
useEffect(() => {
|
|
562
|
+
if (!setupFn && !cleanupFn) return;
|
|
563
|
+
const gen = ++lifecycleGenRef.current;
|
|
564
|
+
if (setupFn) {
|
|
565
|
+
queueMicrotask(() => {
|
|
566
|
+
if (gen === lifecycleGenRef.current) setupFn(store);
|
|
567
|
+
});
|
|
568
|
+
}
|
|
569
|
+
return () => {
|
|
570
|
+
const teardownGen = lifecycleGenRef.current;
|
|
571
|
+
if (cleanupFn) {
|
|
572
|
+
queueMicrotask(() => {
|
|
573
|
+
if (teardownGen === lifecycleGenRef.current) cleanupFn(store);
|
|
574
|
+
});
|
|
575
|
+
}
|
|
576
|
+
};
|
|
577
|
+
}, []);
|
|
557
578
|
useEffect(() => {
|
|
558
579
|
if (!fetchFn) {
|
|
559
580
|
return;
|
package/dist/react/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/react/store.ts","../../src/core/types.ts","../../src/core/trie.ts","../../src/core/structural.ts","../../src/core/computed.ts","../../src/core/store.ts","../../src/core/base.ts"],"sourcesContent":["import {\n useSyncExternalStore,\n useCallback,\n useRef,\n useState,\n useEffect,\n createElement,\n forwardRef,\n} from \"react\";\nimport { SnapStore } from \"../core/base.js\";\nimport { asyncStatus } from \"../core/types.js\";\nimport type { StoreOptions, AsyncStatus, DotPaths, GetByPath } from \"../core/types.js\";\n\ninterface ConnectConfig<S, MappedProps> {\n props: (store: S) => MappedProps;\n fetch: (store: S) => Promise<void>;\n loading?: React.ComponentType;\n error?: React.ComponentType<{ error: string }>;\n}\n\ntype PickFn<T extends object> = <P extends DotPaths<T>>(path: P) => GetByPath<T, P>;\n\ninterface SelectConnectConfig<T extends object, MappedProps> {\n select: (pick: PickFn<T>) => MappedProps;\n}\n\nfunction shallowEqual(a: Record<string, unknown>, b: Record<string, unknown>): boolean {\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n if (keysA.length !== keysB.length) { return false; }\n for (const key of keysA) {\n if (a[key] !== b[key]) { return false; }\n }\n return true;\n}\n\nexport class ReactSnapStore<T extends object, K extends string = string> extends SnapStore<T, K> {\n constructor(initialState: T, options?: StoreOptions) {\n super(initialState, options);\n }\n\n /** Wire a component to the store, injecting props derived from state via `mapToProps`. */\n connect<P extends object, MappedProps extends Record<string, unknown>>(\n Component: React.ComponentType<P>,\n mapToProps: (store: this) => MappedProps,\n ): React.FC<Omit<P, keyof MappedProps>>;\n /** Wire a component to the store with async data fetching, loading, and error handling. */\n connect<P extends object, MappedProps extends Record<string, unknown>>(\n Component: React.ComponentType<P>,\n config: ConnectConfig<this, MappedProps>,\n ): React.FC<Omit<P, keyof MappedProps | \"status\" | \"error\">>;\n /** Wire a component to the store with granular path-based subscriptions via `select`.\n * Paths are captured once at connect-time — select must use a stable set of paths.\n * For conditional/dynamic path selection, use the `mapToProps` overload instead. */\n connect<P extends object, MappedProps extends Record<string, unknown>>(\n Component: React.ComponentType<P>,\n config: SelectConnectConfig<T, MappedProps>,\n ): React.FC<Omit<P, keyof MappedProps>>;\n connect<P extends object, MappedProps extends Record<string, unknown>>(\n Component: React.ComponentType<P>,\n configOrMapper:\n | ((store: this) => MappedProps)\n | ConnectConfig<this, MappedProps>\n | SelectConnectConfig<T, MappedProps>,\n ): React.FC<Omit<P, keyof MappedProps>> {\n const store = this;\n\n if (typeof configOrMapper === \"object\" && \"select\" in configOrMapper) {\n return this._connectWithSelect<P, MappedProps>(Component, configOrMapper.select);\n }\n\n const mapToProps =\n typeof configOrMapper === \"function\" ? configOrMapper : configOrMapper.props;\n const fetchFn =\n typeof configOrMapper === \"function\" ? undefined : configOrMapper.fetch;\n const loadingComponent =\n typeof configOrMapper === \"function\" ? undefined : configOrMapper.loading;\n const errorComponent =\n typeof configOrMapper === \"function\" ? undefined : configOrMapper.error;\n\n const Connected = forwardRef<unknown, Omit<P, keyof MappedProps>>(function Connected(ownProps, ref) {\n const cachedRef = useRef<{ revision: number; props: MappedProps } | null>(null);\n const revisionRef = useRef(0);\n\n const subscribe = useCallback(\n (cb: () => void) => store.subscribe(() => {\n revisionRef.current++;\n cb();\n }),\n [store],\n );\n\n const getSnapshot = useCallback(() => {\n const currentRevision = revisionRef.current;\n if (cachedRef.current && cachedRef.current.revision === currentRevision) {\n return cachedRef.current.props;\n }\n const next = mapToProps(store);\n if (cachedRef.current && shallowEqual(cachedRef.current.props, next)) {\n cachedRef.current = { revision: currentRevision, props: cachedRef.current.props };\n return cachedRef.current.props;\n }\n cachedRef.current = { revision: currentRevision, props: next };\n return next;\n }, [store]);\n\n const mappedProps = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n\n const [asyncState, setAsyncState] = useState<{\n status: AsyncStatus;\n error: string | null;\n }>({ status: asyncStatus(\"idle\"), error: null });\n\n const fetchGenRef = useRef(0);\n\n useEffect(() => {\n if (!fetchFn) { return; }\n let cancelled = false;\n const gen = ++fetchGenRef.current;\n setAsyncState({ status: asyncStatus(\"loading\"), error: null });\n Promise.resolve()\n .then(() => {\n if (cancelled) { return; }\n return fetchFn(store);\n })\n .then(() => {\n if (gen === fetchGenRef.current) {\n setAsyncState({ status: asyncStatus(\"ready\"), error: null });\n }\n })\n .catch((e) => {\n if (gen === fetchGenRef.current) {\n setAsyncState({\n status: asyncStatus(\"error\"),\n error: e instanceof Error ? e.message : \"Unknown error\",\n });\n }\n });\n return () => { cancelled = true; };\n }, []);\n\n if (fetchFn) {\n if (loadingComponent && (asyncState.status.isIdle || asyncState.status.isLoading)) {\n return createElement(loadingComponent);\n }\n if (errorComponent && asyncState.status.isError) {\n return createElement(errorComponent, { error: asyncState.error! });\n }\n }\n\n return createElement(Component, {\n ...ownProps,\n ...mappedProps,\n ...(fetchFn ? asyncState : {}),\n ref,\n } as unknown as P);\n });\n\n Connected.displayName = `Connect(${Component.displayName || Component.name || \"Component\"})`;\n return Connected as unknown as React.FC<Omit<P, keyof MappedProps>>;\n }\n\n private _connectWithSelect<P extends object, MappedProps extends Record<string, unknown>>(\n Component: React.ComponentType<P>,\n selectFn: (pick: PickFn<T>) => MappedProps,\n ): React.FC<Omit<P, keyof MappedProps>> {\n const store = this;\n\n const resolvePathValue = (path: string): any => {\n const segments = path.split(\".\");\n let val: any = store.getSnapshot();\n for (const seg of segments) {\n if (val == null) { return undefined; }\n val = val[seg];\n }\n return val;\n };\n\n const trackedPaths: string[] = [];\n const trackingPick: PickFn<T> = ((path: string) => {\n trackedPaths.push(path);\n return resolvePathValue(path);\n }) as PickFn<T>;\n selectFn(trackingPick);\n const paths = [...trackedPaths];\n\n const readPick: PickFn<T> = ((path: string) => {\n return resolvePathValue(path);\n }) as PickFn<T>;\n\n const Connected = forwardRef<unknown, Omit<P, keyof MappedProps>>(function Connected(ownProps, ref) {\n const cachedRef = useRef<{ revision: number; props: MappedProps } | null>(null);\n const revisionRef = useRef(0);\n\n const subscribe = useCallback(\n (cb: () => void) => {\n const unsubs = paths.map((p) =>\n store.subscribe(p, () => {\n revisionRef.current++;\n cb();\n }),\n );\n return () => unsubs.forEach((u) => u());\n },\n [store],\n );\n\n const getSnapshot = useCallback(() => {\n const currentRevision = revisionRef.current;\n if (cachedRef.current && cachedRef.current.revision === currentRevision) {\n return cachedRef.current.props;\n }\n const next = selectFn(readPick);\n if (cachedRef.current && shallowEqual(cachedRef.current.props, next)) {\n cachedRef.current = { revision: currentRevision, props: cachedRef.current.props };\n return cachedRef.current.props;\n }\n cachedRef.current = { revision: currentRevision, props: next };\n return next;\n }, [store]);\n\n const mappedProps = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n\n return createElement(Component, {\n ...ownProps,\n ...mappedProps,\n ref,\n } as unknown as P);\n });\n\n Connected.displayName = `Connect(${Component.displayName || Component.name || \"Component\"})`;\n return Connected as unknown as React.FC<Omit<P, keyof MappedProps>>;\n }\n}\n","export type AsyncStatusValue = \"idle\" | \"loading\" | \"ready\" | \"error\";\n\nexport interface AsyncStatus {\n readonly value: AsyncStatusValue;\n readonly isIdle: boolean;\n readonly isLoading: boolean;\n readonly isReady: boolean;\n readonly isError: boolean;\n}\n\nconst _statuses: Record<AsyncStatusValue, AsyncStatus> = {\n idle: Object.freeze({ value: \"idle\", isIdle: true, isLoading: false, isReady: false, isError: false }),\n loading: Object.freeze({ value: \"loading\", isIdle: false, isLoading: true, isReady: false, isError: false }),\n ready: Object.freeze({ value: \"ready\", isIdle: false, isLoading: false, isReady: true, isError: false }),\n error: Object.freeze({ value: \"error\", isIdle: false, isLoading: false, isReady: false, isError: true }),\n};\n\nexport function asyncStatus(value: AsyncStatusValue): AsyncStatus {\n return _statuses[value];\n}\n\n/** Async operation status and error. Tracks the lifecycle of an `api.fetch`/`api.get`/`api.post` call. */\nexport interface OperationState {\n status: AsyncStatus;\n error: string | null;\n}\n\nexport type Path = string & { readonly __brand?: \"Path\" };\n\nexport type Listener = () => void;\n\nexport type Unsubscribe = () => void;\n\n// Union of all valid dot-separated paths into T (for autocomplete)\nexport type DotPaths<T, Prefix extends string = \"\"> = T extends object\n ? { [K in keyof T & string]:\n | `${Prefix}${K}`\n | DotPaths<T[K], `${Prefix}${K}.`>\n }[keyof T & string]\n : never;\n\n// Extract a deeply nested type by dot-separated path\nexport type GetByPath<T, P extends string> = P extends \"\"\n ? T\n : P extends `${infer K}.${infer Rest}`\n ? K extends keyof T\n ? GetByPath<T[K], Rest>\n : never\n : P extends keyof T\n ? T[P]\n : never;\n\nexport type DeepPartial<T> = T extends object\n ? { [K in keyof T]?: DeepPartial<T[K]> }\n : T;\n\nexport type ArrayPaths<T> = {\n [K in keyof T & string]: T[K] extends any[] ? K : never;\n}[keyof T & string];\n\nexport type ObjectArrayPaths<T> = {\n [K in keyof T & string]: T[K] extends (infer V)[]\n ? V extends Date | RegExp | Map<any, any> | Set<any> | Function | any[]\n ? never\n : V extends Record<string, any> ? K : never\n : never;\n}[keyof T & string];\n\nexport type ElementOf<A> = A extends (infer V)[] ? V : never;\n\nexport type Updater<V> = V | ((prev: V) => V);\n\nexport interface StoreOptions {\n /** Auto-batch synchronous sets via microtask (default: true) */\n autoBatch?: boolean;\n}\n\n/** Handle to a computed (derived) value. Call `get()` to read, `destroy()` to stop tracking. */\nexport interface ComputedRef<V> {\n get(): V;\n destroy(): void;\n}\n\n/** Options for an HTTP request (method, body, headers). */\nexport interface HttpRequestInit {\n method?: string;\n body?: unknown;\n headers?: Record<string, string>;\n}\n\n/** Interface for the HTTP layer used by `api.get` and `api.post/put/patch/delete`. */\nexport interface HttpClient {\n request<R = unknown>(url: string, init?: HttpRequestInit): Promise<R>;\n}\n\n/** Options for HTTP verb methods (`api.post`, `api.put`, etc.). */\nexport interface ApiRequestOptions<R = unknown> {\n body?: unknown;\n headers?: Record<string, string>;\n onSuccess?: (data: R) => void;\n onError?: (error: Error) => void;\n}\n\nexport interface Subscribable<T extends object> {\n subscribe(callback: Listener): Unsubscribe;\n getSnapshot(): T;\n}\n\nexport interface StateAccessor<T extends object> {\n get(): T;\n get<P extends DotPaths<T>>(path: P): GetByPath<T, P>;\n set<P extends DotPaths<T>>(path: P, value: Updater<GetByPath<T, P>>): void;\n batch(fn: () => void): void;\n computed<V>(deps: (keyof T & string)[], fn: (state: T) => V): ComputedRef<V>;\n append<P extends ArrayPaths<T>>(path: P, ...items: ElementOf<T[P]>[]): void;\n prepend<P extends ArrayPaths<T>>(path: P, ...items: ElementOf<T[P]>[]): void;\n insertAt<P extends ArrayPaths<T>>(path: P, index: number, ...items: ElementOf<T[P]>[]): void;\n patch<P extends ObjectArrayPaths<T>>(path: P, predicate: (item: ElementOf<T[P]>) => boolean, updates: Partial<ElementOf<T[P]>>): void;\n remove<P extends ArrayPaths<T>>(path: P, predicate: (item: ElementOf<T[P]>) => boolean): void;\n removeAt<P extends ArrayPaths<T>>(path: P, index: number): void;\n at<P extends ArrayPaths<T>>(path: P, index: number): ElementOf<T[P]> | undefined;\n filter<P extends ArrayPaths<T>>(path: P, predicate: (item: ElementOf<T[P]>) => boolean): ElementOf<T[P]>[];\n find<P extends ArrayPaths<T>>(path: P, predicate: (item: ElementOf<T[P]>) => boolean): ElementOf<T[P]> | undefined;\n findIndexOf<P extends ArrayPaths<T>>(path: P, predicate: (item: ElementOf<T[P]>) => boolean): number;\n count<P extends ArrayPaths<T>>(path: P, predicate: (item: ElementOf<T[P]>) => boolean): number;\n}\n\nexport interface ApiAccessor<K extends string> {\n fetch(key: K, fn: () => Promise<void>): Promise<void>;\n get<R = unknown>(key: K, url: string, onSuccess?: (data: R) => void): Promise<void>;\n post<R = unknown>(key: K, url: string, options?: ApiRequestOptions<R>): Promise<void>;\n put<R = unknown>(key: K, url: string, options?: ApiRequestOptions<R>): Promise<void>;\n patch<R = unknown>(key: K, url: string, options?: ApiRequestOptions<R>): Promise<void>;\n delete<R = unknown>(key: K, url: string, options?: ApiRequestOptions<R>): Promise<void>;\n}\n\nexport interface RawStore<T extends object> extends Subscribable<T> {\n get(): T;\n get<P extends DotPaths<T>>(path: P): GetByPath<T, P>;\n\n set<P extends DotPaths<T>>(path: P, value: Updater<GetByPath<T, P>>): void;\n\n batch(fn: () => void): void;\n\n subscribe(callback: Listener): Unsubscribe;\n subscribe(path: string, callback: Listener): Unsubscribe;\n\n getSnapshot(): T;\n\n computed<V>(deps: (keyof T & string)[], fn: (state: T) => V): ComputedRef<V>;\n\n notify(): void;\n\n destroy(): void;\n}\n","import type { Listener, Unsubscribe } from \"./types.js\";\n\nfunction invokeAll(listeners: Set<Listener>): void {\n let firstError: unknown;\n for (const l of listeners) {\n try { l(); } catch (e) { firstError ??= e; }\n }\n if (firstError !== undefined) { throw firstError; }\n}\n\ninterface TrieNode {\n listeners: Set<Listener>;\n children: Map<string, TrieNode>;\n}\n\nfunction createNode(): TrieNode {\n return { listeners: new Set(), children: new Map() };\n}\n\nfunction parsePath(path: string): string[] {\n if (path === \"\") { return []; }\n return path.split(\".\");\n}\n\nexport class SubscriptionTrie {\n private root = createNode();\n private globalListeners = new Set<Listener>();\n\n /** Subscribe to a specific path. Returns unsubscribe function. */\n add(path: string, listener: Listener): Unsubscribe {\n const segments = parsePath(path);\n const parents: { parent: TrieNode; segment: string }[] = [];\n let node = this.root;\n for (const seg of segments) {\n if (!node.children.has(seg)) {\n node.children.set(seg, createNode());\n }\n parents.push({ parent: node, segment: seg });\n node = node.children.get(seg)!;\n }\n node.listeners.add(listener);\n return () => {\n node.listeners.delete(listener);\n for (let i = parents.length - 1; i >= 0; i--) {\n const { parent, segment } = parents[i];\n const child = parent.children.get(segment)!;\n if (child.listeners.size === 0 && child.children.size === 0) {\n parent.children.delete(segment);\n } else {\n break;\n }\n }\n };\n }\n\n /** Subscribe to all changes (no path filter). */\n addGlobal(listener: Listener): Unsubscribe {\n this.globalListeners.add(listener);\n return () => {\n this.globalListeners.delete(listener);\n };\n }\n\n /** Notify listeners for exact path, all ancestors, and all descendants. */\n notify(path: string): void {\n const segments = parsePath(path);\n const collected = new Set<Listener>();\n\n // Collect global listeners\n for (const l of this.globalListeners) collected.add(l);\n\n // Walk down to the target, collecting ancestor listeners\n let node = this.root;\n // Root-level listeners (subscribe to \"\")\n for (const l of node.listeners) collected.add(l);\n\n let matched = true;\n for (const seg of segments) {\n // Check wildcard sibling at this level\n const wildcard = node.children.get(\"*\");\n if (wildcard) {\n for (const l of wildcard.listeners) collected.add(l);\n this.collectDescendants(wildcard, collected);\n }\n\n const child = node.children.get(seg);\n if (!child) {\n matched = false;\n break;\n }\n node = child;\n for (const l of node.listeners) collected.add(l);\n }\n\n // Only collect descendants if we matched the full path\n if (matched) {\n this.collectDescendants(node, collected);\n }\n\n invokeAll(collected);\n }\n\n /** Notify all listeners in the trie. */\n notifyAll(): void {\n const collected = new Set<Listener>();\n for (const l of this.globalListeners) collected.add(l);\n this.collectDescendants(this.root, collected);\n for (const l of this.root.listeners) collected.add(l);\n invokeAll(collected);\n }\n\n private collectDescendants(node: TrieNode, out: Set<Listener>): void {\n for (const child of node.children.values()) {\n for (const l of child.listeners) out.add(l);\n this.collectDescendants(child, out);\n }\n }\n\n clear(): void {\n this.root = createNode();\n this.globalListeners.clear();\n }\n}\n","/**\n * Immutable update with structural sharing.\n * Only clones objects along the changed path; unchanged subtrees keep their references.\n */\nexport function applyUpdate<T extends object>(\n state: T,\n path: string,\n value: unknown,\n): T {\n const segments = path.split(\".\");\n return updateAtPath(state, segments, 0, value) as T;\n}\n\nfunction updateAtPath(\n current: unknown,\n segments: string[],\n index: number,\n value: unknown,\n): unknown {\n if (index === segments.length) {\n // Functional updater support\n if (typeof value === \"function\") {\n return (value as (prev: unknown) => unknown)(current);\n }\n return value;\n }\n\n const key = segments[index];\n\n if (Array.isArray(current)) {\n const i = Number(key);\n const next = updateAtPath(current[i], segments, index + 1, value);\n if (Object.is(next, current[i])) { return current; }\n const copy = current.slice();\n copy[i] = next;\n return copy;\n }\n\n if (current !== null && typeof current === \"object\") {\n const obj = current as Record<string, unknown>;\n const next = updateAtPath(obj[key], segments, index + 1, value);\n if (Object.is(next, obj[key])) { return current; }\n return { ...obj, [key]: next };\n }\n\n // Path doesn't exist yet — create nested objects\n const next = updateAtPath(undefined, segments, index + 1, value);\n return { [key]: next };\n}\n\n/** Read a value at a dot-separated path. */\nexport function getAtPath(state: unknown, path: string): unknown {\n if (path === \"\") { return state; }\n const segments = path.split(\".\");\n let current = state;\n for (const seg of segments) {\n if (current === null || current === undefined) { return undefined; }\n current = (current as Record<string, unknown>)[seg];\n }\n return current;\n}\n","import type { ComputedRef, Listener, Unsubscribe } from \"./types.js\";\n\ninterface ComputedHost {\n getSnapshot(): object;\n subscribe(path: string, callback: Listener): Unsubscribe;\n}\n\nexport function createComputed<T extends object, V>(\n host: ComputedHost,\n deps: string[],\n fn: (state: T) => V,\n): ComputedRef<V> {\n let cachedValue: V;\n let dirty = true;\n const unsubs: Unsubscribe[] = [];\n\n const markDirty = () => {\n dirty = true;\n };\n\n for (const dep of deps) {\n unsubs.push(host.subscribe(dep, markDirty));\n }\n\n // Compute initial value; clean up subscriptions if it throws\n try {\n cachedValue = fn(host.getSnapshot() as T);\n } catch (e) {\n for (const unsub of unsubs) unsub();\n unsubs.length = 0;\n throw e;\n }\n dirty = false;\n\n return {\n get(): V {\n if (dirty) {\n cachedValue = fn(host.getSnapshot() as T);\n dirty = false;\n }\n return cachedValue;\n },\n destroy(): void {\n for (const unsub of unsubs) unsub();\n unsubs.length = 0;\n },\n };\n}\n","import type {\n RawStore,\n StoreOptions,\n Listener,\n Unsubscribe,\n Updater,\n ComputedRef,\n GetByPath,\n} from \"./types.js\";\nimport { SubscriptionTrie } from \"./trie.js\";\nimport { applyUpdate, getAtPath } from \"./structural.js\";\nimport { createComputed } from \"./computed.js\";\n\nexport function createStore<T extends object>(\n initialState: T,\n options: StoreOptions = {},\n): RawStore<T> {\n const { autoBatch = true } = options;\n\n let state: T = initialState;\n const trie = new SubscriptionTrie();\n\n // Batching\n let batchDepth = 0;\n let pendingPaths = new Set<string>();\n let microtaskScheduled = false;\n\n function flushNotifications(): void {\n const paths = pendingPaths;\n pendingPaths = new Set();\n microtaskScheduled = false;\n\n if (paths.size === 0) { return; }\n\n // Deduplicate: if a parent path is present, skip its children\n const sorted = [...paths].sort();\n const deduped: string[] = [];\n for (const p of sorted) {\n const last = deduped[deduped.length - 1];\n if (last !== undefined && p.startsWith(last + \".\")) { continue; }\n deduped.push(p);\n }\n\n for (const path of deduped) {\n trie.notify(path);\n }\n }\n\n function scheduleFlush(): void {\n if (batchDepth > 0) { return; }\n if (autoBatch && !microtaskScheduled) {\n microtaskScheduled = true;\n queueMicrotask(flushNotifications);\n } else if (!autoBatch) {\n flushNotifications();\n }\n }\n\n function get(): T;\n function get<P extends string>(path: P): GetByPath<T, P>;\n function get(path?: string): unknown {\n if (path === undefined || path === \"\") { return state; }\n return getAtPath(state, path);\n }\n\n function set<P extends string>(\n path: P,\n value: Updater<GetByPath<T, P>>,\n ): void {\n if (path === \"\") {\n throw new Error(\"Cannot set with an empty path. Use a specific path to update state.\");\n }\n const prev = state;\n state = applyUpdate(state, path, value);\n if (state !== prev) {\n pendingPaths.add(path);\n scheduleFlush();\n }\n }\n\n function batch(fn: () => void): void {\n batchDepth++;\n try {\n fn();\n } finally {\n batchDepth--;\n if (batchDepth === 0) {\n flushNotifications();\n }\n }\n }\n\n function subscribe(callback: Listener): Unsubscribe;\n function subscribe(path: string, callback: Listener): Unsubscribe;\n function subscribe(\n pathOrCallback: string | Listener,\n callback?: Listener,\n ): Unsubscribe {\n if (typeof pathOrCallback === \"function\") {\n return trie.addGlobal(pathOrCallback);\n }\n return trie.add(pathOrCallback, callback!);\n }\n\n function getSnapshot(): T {\n return state;\n }\n\n function computed<V>(deps: (keyof T & string)[], fn: (state: T) => V): ComputedRef<V> {\n return createComputed<T, V>({ getSnapshot, subscribe }, deps, fn);\n }\n\n function notify(): void {\n trie.notifyAll();\n }\n\n function destroy(): void {\n trie.clear();\n pendingPaths.clear();\n }\n\n return {\n get,\n set,\n batch,\n subscribe,\n getSnapshot,\n computed,\n notify,\n destroy,\n } as RawStore<T>;\n}\n","import type {\n RawStore,\n StoreOptions,\n Listener,\n Unsubscribe,\n OperationState,\n HttpClient,\n StateAccessor,\n ApiAccessor,\n ApiRequestOptions,\n} from \"./types.js\";\nimport { asyncStatus } from \"./types.js\";\nimport { createStore } from \"./store.js\";\n\nconst IDLE_STATE: OperationState = { status: asyncStatus(\"idle\"), error: null };\n\nconst defaultHttpClient: HttpClient = {\n async request(url, init) {\n const fetchInit: RequestInit = { method: init?.method ?? \"GET\" };\n const merged = { ...defaultHeaders, ...init?.headers };\n if (Object.keys(merged).length) { fetchInit.headers = merged; }\n if (init?.body !== undefined) {\n fetchInit.body = JSON.stringify(init.body);\n fetchInit.headers = { \"Content-Type\": \"application/json\", ...merged };\n }\n const res = await fetch(url, fetchInit);\n if (!res.ok) {\n let message = `HTTP ${res.status}`;\n try {\n const text = await res.text();\n if (text) {\n const json = JSON.parse(text);\n message = json.error ?? json.message ?? message;\n }\n } catch {}\n throw new Error(message);\n }\n const text = await res.text();\n return text ? JSON.parse(text) : undefined;\n },\n};\n\nlet httpClient: HttpClient = defaultHttpClient;\nlet defaultHeaders: Record<string, string> = {};\n\n/** Replace the global HTTP client used by `api.get` and `api.post/put/patch/delete`. */\nexport function setHttpClient(client: HttpClient): void {\n httpClient = client;\n}\n\n/** Set default headers merged into every HTTP request. Per-request headers override defaults. */\nexport function setDefaultHeaders(headers: Record<string, string>): void {\n defaultHeaders = headers;\n}\n\nexport class SnapStore<T extends object, K extends string = string> {\n private _store: RawStore<T>;\n private _operations = new Map<K, OperationState>();\n private _generations = new Map<K, number>();\n\n protected readonly state: StateAccessor<T>;\n protected readonly api: ApiAccessor<K>;\n\n constructor(initialState: T, options?: StoreOptions) {\n this._store = createStore(initialState, options);\n\n const store = this._store;\n const operations = this._operations;\n const generations = this._generations;\n\n // takeLatest semantic: if a newer call starts for the same key, the older\n // call's promise resolves silently (no reject, no state update).\n const doFetch = async (key: K, fn: () => Promise<void>): Promise<void> => {\n const gen = (generations.get(key) ?? 0) + 1;\n generations.set(key, gen);\n operations.set(key, { status: asyncStatus(\"loading\"), error: null });\n store.notify();\n try {\n await fn();\n if (generations.get(key) !== gen) { return; }\n operations.set(key, { status: asyncStatus(\"ready\"), error: null });\n } catch (e) {\n if (generations.get(key) !== gen) { return; }\n operations.set(key, {\n status: asyncStatus(\"error\"),\n error: e instanceof Error ? e.message : \"Unknown error\",\n });\n store.notify();\n throw e;\n }\n store.notify();\n };\n\n const doSend = async <R>(key: K, method: string, url: string, options?: ApiRequestOptions<R>): Promise<void> => {\n await doFetch(key, async () => {\n try {\n const data = await httpClient.request<R>(url, {\n method,\n body: options?.body,\n headers: options?.headers,\n });\n options?.onSuccess?.(data);\n } catch (e) {\n options?.onError?.(e instanceof Error ? e : new Error(\"Unknown error\"));\n throw e;\n }\n });\n };\n\n this.state = {\n get: ((path?: string): unknown => {\n if (path === undefined) { return store.get(); }\n return (store.get as (p: string) => unknown)(path);\n }) as StateAccessor<T>[\"get\"],\n\n set: (path, value) => store.set(path, value),\n batch: (fn) => store.batch(fn),\n computed: (deps, fn) => store.computed(deps, fn),\n\n append: (path, ...items) => {\n store.set(path as any, ((prev: any) => [...(prev as any[]), ...items]) as any);\n },\n prepend: (path, ...items) => {\n store.set(path as any, ((prev: any) => [...items, ...(prev as any[])]) as any);\n },\n insertAt: (path, index, ...items) => {\n store.set(path as any, ((prev: any) => {\n const arr = prev as any[];\n return [...arr.slice(0, index), ...items, ...arr.slice(index)];\n }) as any);\n },\n patch: (path, predicate, updates) => {\n store.set(path as any, ((prev: any) => {\n const arr = prev as any[];\n let changed = false;\n const result = arr.map((item: any) => {\n if (item == null) { return item; }\n if (predicate(item)) {\n changed = true;\n return Object.assign(Object.create(Object.getPrototypeOf(item)), item, updates);\n }\n return item;\n });\n return changed ? result : arr;\n }) as any);\n },\n remove: (path, predicate) => {\n store.set(path as any, ((prev: any) => {\n const arr = prev as any[];\n const result = arr.filter((item: any) => !predicate(item));\n return result.length === arr.length ? arr : result;\n }) as any);\n },\n removeAt: (path, index) => {\n store.set(path as any, ((prev: any) => {\n const arr = prev as any[];\n const i = index < 0 ? arr.length + index : index;\n if (i < 0 || i >= arr.length) {\n throw new RangeError(`Index ${index} out of bounds for array of length ${arr.length}`);\n }\n return [...arr.slice(0, i), ...arr.slice(i + 1)];\n }) as any);\n },\n at: (path, index) => {\n return (store.get(path as any) as any[]).at(index);\n },\n filter: (path, predicate) => {\n return (store.get(path as any) as any[]).filter(predicate);\n },\n find: (path, predicate) => {\n return (store.get(path as any) as any[]).find(predicate);\n },\n findIndexOf: (path, predicate) => {\n return (store.get(path as any) as any[]).findIndex(predicate);\n },\n count: (path, predicate) => {\n return (store.get(path as any) as any[]).filter(predicate).length;\n },\n };\n\n this.api = {\n fetch: doFetch,\n get: async <R>(key: K, url: string, onSuccess?: (data: R) => void): Promise<void> => {\n await doFetch(key, async () => {\n const data = await httpClient.request<R>(url);\n onSuccess?.(data);\n });\n },\n post: (key, url, options?) => doSend(key, \"POST\", url, options),\n put: (key, url, options?) => doSend(key, \"PUT\", url, options),\n patch: (key, url, options?) => doSend(key, \"PATCH\", url, options),\n delete: (key, url, options?) => doSend(key, \"DELETE\", url, options),\n };\n }\n\n /** Subscribe to all state changes. Returns an unsubscribe function. */\n subscribe(callback: Listener): Unsubscribe;\n /** Subscribe to changes at a specific dot-separated path. */\n subscribe(path: string, callback: Listener): Unsubscribe;\n subscribe(pathOrCallback: string | Listener, callback?: Listener): Unsubscribe {\n if (typeof pathOrCallback === \"function\") {\n return this._store.subscribe(pathOrCallback);\n }\n return this._store.subscribe(pathOrCallback, callback!);\n }\n\n /** Return a snapshot of the current state. Compatible with React's `useSyncExternalStore`. */\n getSnapshot = (): T => {\n return this._store.getSnapshot();\n };\n\n /** Get the async status of an operation by key. Returns `idle` if never started. */\n getStatus(key: K): OperationState {\n return { ...(this._operations.get(key) ?? IDLE_STATE) };\n }\n\n /** Tear down subscriptions and cleanup. */\n destroy(): void {\n this._store.destroy();\n }\n}\n"],"mappings":"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","names":["next","text","options","Connected"]}
|
|
1
|
+
{"version":3,"sources":["../../src/react/store.ts","../../src/core/types.ts","../../src/core/trie.ts","../../src/core/structural.ts","../../src/core/computed.ts","../../src/core/store.ts","../../src/core/base.ts"],"sourcesContent":["import {\n useSyncExternalStore,\n useCallback,\n useRef,\n useState,\n useEffect,\n createElement,\n forwardRef,\n} from \"react\";\nimport { SnapStore } from \"../core/base.js\";\nimport { asyncStatus } from \"../core/types.js\";\nimport type { StoreOptions, AsyncStatus, DotPaths, GetByPath } from \"../core/types.js\";\n\ninterface ConnectConfig<S, MappedProps> {\n props: (store: S) => MappedProps;\n setup?: (store: S) => void;\n fetch: (store: S) => Promise<void>;\n cleanup?: (store: S) => void;\n loading?: React.ComponentType;\n error?: React.ComponentType<{ error: string }>;\n}\n\ninterface ConnectPropsConfig<S, MappedProps> {\n props: (store: S) => MappedProps;\n setup?: (store: S) => void;\n cleanup?: (store: S) => void;\n}\n\ntype PickFn<T extends object> = <P extends DotPaths<T>>(path: P) => GetByPath<T, P>;\n\ninterface SelectConnectConfig<T extends object, MappedProps> {\n select: (pick: PickFn<T>) => MappedProps;\n}\n\nfunction shallowEqual(a: Record<string, unknown>, b: Record<string, unknown>): boolean {\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n if (keysA.length !== keysB.length) { return false; }\n for (const key of keysA) {\n if (a[key] !== b[key]) { return false; }\n }\n return true;\n}\n\nexport class ReactSnapStore<T extends object, K extends string = string> extends SnapStore<T, K> {\n constructor(initialState: T, options?: StoreOptions) {\n super(initialState, options);\n }\n\n /** Wire a component to the store, injecting props derived from state via `mapToProps`. */\n connect<P extends object, MappedProps extends Record<string, unknown>>(\n Component: React.ComponentType<P>,\n mapToProps: (store: this) => MappedProps,\n ): React.FC<Omit<P, keyof MappedProps>>;\n /** Wire a component to the store with async data fetching, loading, and error handling. */\n connect<P extends object, MappedProps extends Record<string, unknown>>(\n Component: React.ComponentType<P>,\n config: ConnectConfig<this, MappedProps>,\n ): React.FC<Omit<P, keyof MappedProps | \"status\" | \"error\">>;\n /** Wire a component to the store with props mapping and optional cleanup. */\n connect<P extends object, MappedProps extends Record<string, unknown>>(\n Component: React.ComponentType<P>,\n config: ConnectPropsConfig<this, MappedProps>,\n ): React.FC<Omit<P, keyof MappedProps>>;\n /** Wire a component to the store with granular path-based subscriptions via `select`.\n * Paths are captured once at connect-time — select must use a stable set of paths.\n * For conditional/dynamic path selection, use the `mapToProps` overload instead. */\n connect<P extends object, MappedProps extends Record<string, unknown>>(\n Component: React.ComponentType<P>,\n config: SelectConnectConfig<T, MappedProps>,\n ): React.FC<Omit<P, keyof MappedProps>>;\n connect<P extends object, MappedProps extends Record<string, unknown>>(\n Component: React.ComponentType<P>,\n configOrMapper:\n | ((store: this) => MappedProps)\n | ConnectPropsConfig<this, MappedProps>\n | ConnectConfig<this, MappedProps>\n | SelectConnectConfig<T, MappedProps>,\n ): React.FC<Omit<P, keyof MappedProps>> {\n const store = this;\n\n if (typeof configOrMapper === \"object\" && \"select\" in configOrMapper) {\n return this._connectWithSelect<P, MappedProps>(Component, configOrMapper.select);\n }\n\n const config = typeof configOrMapper === \"function\"\n ? null\n : configOrMapper as ConnectConfig<this, MappedProps>;\n const mapToProps = config ? config.props : configOrMapper as (store: this) => MappedProps;\n const fetchFn = config?.fetch;\n const loadingComponent = config?.loading;\n const errorComponent = config?.error;\n const setupFn = config?.setup;\n const cleanupFn = config?.cleanup;\n\n const Connected = forwardRef<unknown, Omit<P, keyof MappedProps>>(function Connected(ownProps, ref) {\n const cachedRef = useRef<{ revision: number; props: MappedProps } | null>(null);\n const revisionRef = useRef(0);\n\n const subscribe = useCallback(\n (cb: () => void) => store.subscribe(() => {\n revisionRef.current++;\n cb();\n }),\n [store],\n );\n\n const getSnapshot = useCallback(() => {\n const currentRevision = revisionRef.current;\n if (cachedRef.current && cachedRef.current.revision === currentRevision) {\n return cachedRef.current.props;\n }\n const next = mapToProps(store);\n if (cachedRef.current && shallowEqual(cachedRef.current.props, next)) {\n cachedRef.current = { revision: currentRevision, props: cachedRef.current.props };\n return cachedRef.current.props;\n }\n cachedRef.current = { revision: currentRevision, props: next };\n return next;\n }, [store]);\n\n const mappedProps = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n\n const [asyncState, setAsyncState] = useState<{\n status: AsyncStatus;\n error: string | null;\n }>({ status: asyncStatus(\"idle\"), error: null });\n\n const fetchGenRef = useRef(0);\n\n const lifecycleGenRef = useRef(0);\n useEffect(() => {\n if (!setupFn && !cleanupFn) return;\n const gen = ++lifecycleGenRef.current;\n if (setupFn) {\n queueMicrotask(() => {\n if (gen === lifecycleGenRef.current) setupFn(store);\n });\n }\n return () => {\n const teardownGen = lifecycleGenRef.current;\n if (cleanupFn) {\n queueMicrotask(() => {\n if (teardownGen === lifecycleGenRef.current) cleanupFn(store);\n });\n }\n };\n }, []);\n\n useEffect(() => {\n if (!fetchFn) { return; }\n let cancelled = false;\n const gen = ++fetchGenRef.current;\n setAsyncState({ status: asyncStatus(\"loading\"), error: null });\n Promise.resolve()\n .then(() => {\n if (cancelled) { return; }\n return fetchFn(store);\n })\n .then(() => {\n if (gen === fetchGenRef.current) {\n setAsyncState({ status: asyncStatus(\"ready\"), error: null });\n }\n })\n .catch((e) => {\n if (gen === fetchGenRef.current) {\n setAsyncState({\n status: asyncStatus(\"error\"),\n error: e instanceof Error ? e.message : \"Unknown error\",\n });\n }\n });\n return () => { cancelled = true; };\n }, []);\n\n if (fetchFn) {\n if (loadingComponent && (asyncState.status.isIdle || asyncState.status.isLoading)) {\n return createElement(loadingComponent);\n }\n if (errorComponent && asyncState.status.isError) {\n return createElement(errorComponent, { error: asyncState.error! });\n }\n }\n\n return createElement(Component, {\n ...ownProps,\n ...mappedProps,\n ...(fetchFn ? asyncState : {}),\n ref,\n } as unknown as P);\n });\n\n Connected.displayName = `Connect(${Component.displayName || Component.name || \"Component\"})`;\n return Connected as unknown as React.FC<Omit<P, keyof MappedProps>>;\n }\n\n private _connectWithSelect<P extends object, MappedProps extends Record<string, unknown>>(\n Component: React.ComponentType<P>,\n selectFn: (pick: PickFn<T>) => MappedProps,\n ): React.FC<Omit<P, keyof MappedProps>> {\n const store = this;\n\n const resolvePathValue = (path: string): any => {\n const segments = path.split(\".\");\n let val: any = store.getSnapshot();\n for (const seg of segments) {\n if (val == null) { return undefined; }\n val = val[seg];\n }\n return val;\n };\n\n const trackedPaths: string[] = [];\n const trackingPick: PickFn<T> = ((path: string) => {\n trackedPaths.push(path);\n return resolvePathValue(path);\n }) as PickFn<T>;\n selectFn(trackingPick);\n const paths = [...trackedPaths];\n\n const readPick: PickFn<T> = ((path: string) => {\n return resolvePathValue(path);\n }) as PickFn<T>;\n\n const Connected = forwardRef<unknown, Omit<P, keyof MappedProps>>(function Connected(ownProps, ref) {\n const cachedRef = useRef<{ revision: number; props: MappedProps } | null>(null);\n const revisionRef = useRef(0);\n\n const subscribe = useCallback(\n (cb: () => void) => {\n const unsubs = paths.map((p) =>\n store.subscribe(p, () => {\n revisionRef.current++;\n cb();\n }),\n );\n return () => unsubs.forEach((u) => u());\n },\n [store],\n );\n\n const getSnapshot = useCallback(() => {\n const currentRevision = revisionRef.current;\n if (cachedRef.current && cachedRef.current.revision === currentRevision) {\n return cachedRef.current.props;\n }\n const next = selectFn(readPick);\n if (cachedRef.current && shallowEqual(cachedRef.current.props, next)) {\n cachedRef.current = { revision: currentRevision, props: cachedRef.current.props };\n return cachedRef.current.props;\n }\n cachedRef.current = { revision: currentRevision, props: next };\n return next;\n }, [store]);\n\n const mappedProps = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n\n return createElement(Component, {\n ...ownProps,\n ...mappedProps,\n ref,\n } as unknown as P);\n });\n\n Connected.displayName = `Connect(${Component.displayName || Component.name || \"Component\"})`;\n return Connected as unknown as React.FC<Omit<P, keyof MappedProps>>;\n }\n}\n","export type AsyncStatusValue = \"idle\" | \"loading\" | \"ready\" | \"error\";\n\nexport interface AsyncStatus {\n readonly value: AsyncStatusValue;\n readonly isIdle: boolean;\n readonly isLoading: boolean;\n readonly isReady: boolean;\n readonly isError: boolean;\n}\n\nconst _statuses: Record<AsyncStatusValue, AsyncStatus> = {\n idle: Object.freeze({ value: \"idle\", isIdle: true, isLoading: false, isReady: false, isError: false }),\n loading: Object.freeze({ value: \"loading\", isIdle: false, isLoading: true, isReady: false, isError: false }),\n ready: Object.freeze({ value: \"ready\", isIdle: false, isLoading: false, isReady: true, isError: false }),\n error: Object.freeze({ value: \"error\", isIdle: false, isLoading: false, isReady: false, isError: true }),\n};\n\nexport function asyncStatus(value: AsyncStatusValue): AsyncStatus {\n return _statuses[value];\n}\n\n/** Async operation status and error. Tracks the lifecycle of an `api.fetch`/`api.get`/`api.post` call. */\nexport interface OperationState {\n status: AsyncStatus;\n error: string | null;\n}\n\nexport type Path = string & { readonly __brand?: \"Path\" };\n\nexport type Listener = () => void;\n\nexport type Unsubscribe = () => void;\n\n// Union of all valid dot-separated paths into T (for autocomplete)\nexport type DotPaths<T, Prefix extends string = \"\"> = T extends object\n ? { [K in keyof T & string]:\n | `${Prefix}${K}`\n | DotPaths<T[K], `${Prefix}${K}.`>\n }[keyof T & string]\n : never;\n\n// Extract a deeply nested type by dot-separated path\nexport type GetByPath<T, P extends string> = P extends \"\"\n ? T\n : P extends `${infer K}.${infer Rest}`\n ? K extends keyof T\n ? GetByPath<T[K], Rest>\n : never\n : P extends keyof T\n ? T[P]\n : never;\n\nexport type DeepPartial<T> = T extends object\n ? { [K in keyof T]?: DeepPartial<T[K]> }\n : T;\n\nexport type ArrayPaths<T> = {\n [K in keyof T & string]: T[K] extends any[] ? K : never;\n}[keyof T & string];\n\nexport type ObjectArrayPaths<T> = {\n [K in keyof T & string]: T[K] extends (infer V)[]\n ? V extends Date | RegExp | Map<any, any> | Set<any> | Function | any[]\n ? never\n : V extends Record<string, any> ? K : never\n : never;\n}[keyof T & string];\n\nexport type ElementOf<A> = A extends (infer V)[] ? V : never;\n\nexport type Updater<V> = V | ((prev: V) => V);\n\nexport interface StoreOptions {\n /** Auto-batch synchronous sets via microtask (default: true) */\n autoBatch?: boolean;\n}\n\n/** Handle to a computed (derived) value. Call `get()` to read, `destroy()` to stop tracking. */\nexport interface ComputedRef<V> {\n get(): V;\n destroy(): void;\n}\n\n/** Options for an HTTP request (method, body, headers). */\nexport interface HttpRequestInit {\n method?: string;\n body?: unknown;\n headers?: Record<string, string>;\n}\n\n/** Interface for the HTTP layer used by `api.get` and `api.post/put/patch/delete`. */\nexport interface HttpClient {\n request<R = unknown>(url: string, init?: HttpRequestInit): Promise<R>;\n}\n\n/** Options for HTTP verb methods (`api.post`, `api.put`, etc.). */\nexport interface ApiRequestOptions<R = unknown> {\n body?: unknown;\n headers?: Record<string, string>;\n onSuccess?: (data: R) => void;\n onError?: (error: Error) => void;\n}\n\nexport interface Subscribable<T extends object> {\n subscribe(callback: Listener): Unsubscribe;\n getSnapshot(): T;\n}\n\nexport interface StateAccessor<T extends object> {\n get(): T;\n get<P extends DotPaths<T>>(path: P): GetByPath<T, P>;\n set<P extends DotPaths<T>>(path: P, value: Updater<GetByPath<T, P>>): void;\n batch(fn: () => void): void;\n computed<V>(deps: (keyof T & string)[], fn: (state: T) => V): ComputedRef<V>;\n append<P extends ArrayPaths<T>>(path: P, ...items: ElementOf<T[P]>[]): void;\n prepend<P extends ArrayPaths<T>>(path: P, ...items: ElementOf<T[P]>[]): void;\n insertAt<P extends ArrayPaths<T>>(path: P, index: number, ...items: ElementOf<T[P]>[]): void;\n patch<P extends ObjectArrayPaths<T>>(path: P, predicate: (item: ElementOf<T[P]>) => boolean, updates: Partial<ElementOf<T[P]>>): void;\n remove<P extends ArrayPaths<T>>(path: P, predicate: (item: ElementOf<T[P]>) => boolean): void;\n removeAt<P extends ArrayPaths<T>>(path: P, index: number): void;\n at<P extends ArrayPaths<T>>(path: P, index: number): ElementOf<T[P]> | undefined;\n filter<P extends ArrayPaths<T>>(path: P, predicate: (item: ElementOf<T[P]>) => boolean): ElementOf<T[P]>[];\n find<P extends ArrayPaths<T>>(path: P, predicate: (item: ElementOf<T[P]>) => boolean): ElementOf<T[P]> | undefined;\n findIndexOf<P extends ArrayPaths<T>>(path: P, predicate: (item: ElementOf<T[P]>) => boolean): number;\n count<P extends ArrayPaths<T>>(path: P, predicate: (item: ElementOf<T[P]>) => boolean): number;\n}\n\nexport interface ApiAccessor<K extends string> {\n fetch(key: K, fn: () => Promise<void>): Promise<void>;\n get<R = unknown>(key: K, url: string, onSuccess?: (data: R) => void): Promise<void>;\n post<R = unknown>(key: K, url: string, options?: ApiRequestOptions<R>): Promise<void>;\n put<R = unknown>(key: K, url: string, options?: ApiRequestOptions<R>): Promise<void>;\n patch<R = unknown>(key: K, url: string, options?: ApiRequestOptions<R>): Promise<void>;\n delete<R = unknown>(key: K, url: string, options?: ApiRequestOptions<R>): Promise<void>;\n}\n\nexport interface RawStore<T extends object> extends Subscribable<T> {\n get(): T;\n get<P extends DotPaths<T>>(path: P): GetByPath<T, P>;\n\n set<P extends DotPaths<T>>(path: P, value: Updater<GetByPath<T, P>>): void;\n\n batch(fn: () => void): void;\n\n subscribe(callback: Listener): Unsubscribe;\n subscribe(path: string, callback: Listener): Unsubscribe;\n\n getSnapshot(): T;\n\n computed<V>(deps: (keyof T & string)[], fn: (state: T) => V): ComputedRef<V>;\n\n notify(): void;\n\n destroy(): void;\n}\n","import type { Listener, Unsubscribe } from \"./types.js\";\n\nfunction invokeAll(listeners: Set<Listener>): void {\n let firstError: unknown;\n for (const l of listeners) {\n try { l(); } catch (e) { firstError ??= e; }\n }\n if (firstError !== undefined) { throw firstError; }\n}\n\ninterface TrieNode {\n listeners: Set<Listener>;\n children: Map<string, TrieNode>;\n}\n\nfunction createNode(): TrieNode {\n return { listeners: new Set(), children: new Map() };\n}\n\nfunction parsePath(path: string): string[] {\n if (path === \"\") { return []; }\n return path.split(\".\");\n}\n\nexport class SubscriptionTrie {\n private root = createNode();\n private globalListeners = new Set<Listener>();\n\n /** Subscribe to a specific path. Returns unsubscribe function. */\n add(path: string, listener: Listener): Unsubscribe {\n const segments = parsePath(path);\n const parents: { parent: TrieNode; segment: string }[] = [];\n let node = this.root;\n for (const seg of segments) {\n if (!node.children.has(seg)) {\n node.children.set(seg, createNode());\n }\n parents.push({ parent: node, segment: seg });\n node = node.children.get(seg)!;\n }\n node.listeners.add(listener);\n return () => {\n node.listeners.delete(listener);\n for (let i = parents.length - 1; i >= 0; i--) {\n const { parent, segment } = parents[i];\n const child = parent.children.get(segment)!;\n if (child.listeners.size === 0 && child.children.size === 0) {\n parent.children.delete(segment);\n } else {\n break;\n }\n }\n };\n }\n\n /** Subscribe to all changes (no path filter). */\n addGlobal(listener: Listener): Unsubscribe {\n this.globalListeners.add(listener);\n return () => {\n this.globalListeners.delete(listener);\n };\n }\n\n /** Notify listeners for exact path, all ancestors, and all descendants. */\n notify(path: string): void {\n const segments = parsePath(path);\n const collected = new Set<Listener>();\n\n // Collect global listeners\n for (const l of this.globalListeners) collected.add(l);\n\n // Walk down to the target, collecting ancestor listeners\n let node = this.root;\n // Root-level listeners (subscribe to \"\")\n for (const l of node.listeners) collected.add(l);\n\n let matched = true;\n for (const seg of segments) {\n // Check wildcard sibling at this level\n const wildcard = node.children.get(\"*\");\n if (wildcard) {\n for (const l of wildcard.listeners) collected.add(l);\n this.collectDescendants(wildcard, collected);\n }\n\n const child = node.children.get(seg);\n if (!child) {\n matched = false;\n break;\n }\n node = child;\n for (const l of node.listeners) collected.add(l);\n }\n\n // Only collect descendants if we matched the full path\n if (matched) {\n this.collectDescendants(node, collected);\n }\n\n invokeAll(collected);\n }\n\n /** Notify all listeners in the trie. */\n notifyAll(): void {\n const collected = new Set<Listener>();\n for (const l of this.globalListeners) collected.add(l);\n this.collectDescendants(this.root, collected);\n for (const l of this.root.listeners) collected.add(l);\n invokeAll(collected);\n }\n\n private collectDescendants(node: TrieNode, out: Set<Listener>): void {\n for (const child of node.children.values()) {\n for (const l of child.listeners) out.add(l);\n this.collectDescendants(child, out);\n }\n }\n\n clear(): void {\n this.root = createNode();\n this.globalListeners.clear();\n }\n}\n","/**\n * Immutable update with structural sharing.\n * Only clones objects along the changed path; unchanged subtrees keep their references.\n */\nexport function applyUpdate<T extends object>(\n state: T,\n path: string,\n value: unknown,\n): T {\n const segments = path.split(\".\");\n return updateAtPath(state, segments, 0, value) as T;\n}\n\nfunction updateAtPath(\n current: unknown,\n segments: string[],\n index: number,\n value: unknown,\n): unknown {\n if (index === segments.length) {\n // Functional updater support\n if (typeof value === \"function\") {\n return (value as (prev: unknown) => unknown)(current);\n }\n return value;\n }\n\n const key = segments[index];\n\n if (Array.isArray(current)) {\n const i = Number(key);\n const next = updateAtPath(current[i], segments, index + 1, value);\n if (Object.is(next, current[i])) { return current; }\n const copy = current.slice();\n copy[i] = next;\n return copy;\n }\n\n if (current !== null && typeof current === \"object\") {\n const obj = current as Record<string, unknown>;\n const next = updateAtPath(obj[key], segments, index + 1, value);\n if (Object.is(next, obj[key])) { return current; }\n return { ...obj, [key]: next };\n }\n\n // Path doesn't exist yet — create nested objects\n const next = updateAtPath(undefined, segments, index + 1, value);\n return { [key]: next };\n}\n\n/** Read a value at a dot-separated path. */\nexport function getAtPath(state: unknown, path: string): unknown {\n if (path === \"\") { return state; }\n const segments = path.split(\".\");\n let current = state;\n for (const seg of segments) {\n if (current === null || current === undefined) { return undefined; }\n current = (current as Record<string, unknown>)[seg];\n }\n return current;\n}\n","import type { ComputedRef, Listener, Unsubscribe } from \"./types.js\";\n\ninterface ComputedHost {\n getSnapshot(): object;\n subscribe(path: string, callback: Listener): Unsubscribe;\n}\n\nexport function createComputed<T extends object, V>(\n host: ComputedHost,\n deps: string[],\n fn: (state: T) => V,\n): ComputedRef<V> {\n let cachedValue: V;\n let dirty = true;\n const unsubs: Unsubscribe[] = [];\n\n const markDirty = () => {\n dirty = true;\n };\n\n for (const dep of deps) {\n unsubs.push(host.subscribe(dep, markDirty));\n }\n\n // Compute initial value; clean up subscriptions if it throws\n try {\n cachedValue = fn(host.getSnapshot() as T);\n } catch (e) {\n for (const unsub of unsubs) unsub();\n unsubs.length = 0;\n throw e;\n }\n dirty = false;\n\n return {\n get(): V {\n if (dirty) {\n cachedValue = fn(host.getSnapshot() as T);\n dirty = false;\n }\n return cachedValue;\n },\n destroy(): void {\n for (const unsub of unsubs) unsub();\n unsubs.length = 0;\n },\n };\n}\n","import type {\n RawStore,\n StoreOptions,\n Listener,\n Unsubscribe,\n Updater,\n ComputedRef,\n GetByPath,\n} from \"./types.js\";\nimport { SubscriptionTrie } from \"./trie.js\";\nimport { applyUpdate, getAtPath } from \"./structural.js\";\nimport { createComputed } from \"./computed.js\";\n\nexport function createStore<T extends object>(\n initialState: T,\n options: StoreOptions = {},\n): RawStore<T> {\n const { autoBatch = true } = options;\n\n let state: T = initialState;\n const trie = new SubscriptionTrie();\n\n // Batching\n let batchDepth = 0;\n let pendingPaths = new Set<string>();\n let microtaskScheduled = false;\n\n function flushNotifications(): void {\n const paths = pendingPaths;\n pendingPaths = new Set();\n microtaskScheduled = false;\n\n if (paths.size === 0) { return; }\n\n // Deduplicate: if a parent path is present, skip its children\n const sorted = [...paths].sort();\n const deduped: string[] = [];\n for (const p of sorted) {\n const last = deduped[deduped.length - 1];\n if (last !== undefined && p.startsWith(last + \".\")) { continue; }\n deduped.push(p);\n }\n\n for (const path of deduped) {\n trie.notify(path);\n }\n }\n\n function scheduleFlush(): void {\n if (batchDepth > 0) { return; }\n if (autoBatch && !microtaskScheduled) {\n microtaskScheduled = true;\n queueMicrotask(flushNotifications);\n } else if (!autoBatch) {\n flushNotifications();\n }\n }\n\n function get(): T;\n function get<P extends string>(path: P): GetByPath<T, P>;\n function get(path?: string): unknown {\n if (path === undefined || path === \"\") { return state; }\n return getAtPath(state, path);\n }\n\n function set<P extends string>(\n path: P,\n value: Updater<GetByPath<T, P>>,\n ): void {\n if (path === \"\") {\n throw new Error(\"Cannot set with an empty path. Use a specific path to update state.\");\n }\n const prev = state;\n state = applyUpdate(state, path, value);\n if (state !== prev) {\n pendingPaths.add(path);\n scheduleFlush();\n }\n }\n\n function batch(fn: () => void): void {\n batchDepth++;\n try {\n fn();\n } finally {\n batchDepth--;\n if (batchDepth === 0) {\n flushNotifications();\n }\n }\n }\n\n function subscribe(callback: Listener): Unsubscribe;\n function subscribe(path: string, callback: Listener): Unsubscribe;\n function subscribe(\n pathOrCallback: string | Listener,\n callback?: Listener,\n ): Unsubscribe {\n if (typeof pathOrCallback === \"function\") {\n return trie.addGlobal(pathOrCallback);\n }\n return trie.add(pathOrCallback, callback!);\n }\n\n function getSnapshot(): T {\n return state;\n }\n\n function computed<V>(deps: (keyof T & string)[], fn: (state: T) => V): ComputedRef<V> {\n return createComputed<T, V>({ getSnapshot, subscribe }, deps, fn);\n }\n\n function notify(): void {\n trie.notifyAll();\n }\n\n function destroy(): void {\n trie.clear();\n pendingPaths.clear();\n }\n\n return {\n get,\n set,\n batch,\n subscribe,\n getSnapshot,\n computed,\n notify,\n destroy,\n } as RawStore<T>;\n}\n","import type {\n RawStore,\n StoreOptions,\n Listener,\n Unsubscribe,\n OperationState,\n HttpClient,\n StateAccessor,\n ApiAccessor,\n ApiRequestOptions,\n} from \"./types.js\";\nimport { asyncStatus } from \"./types.js\";\nimport { createStore } from \"./store.js\";\n\nconst IDLE_STATE: OperationState = { status: asyncStatus(\"idle\"), error: null };\n\nconst defaultHttpClient: HttpClient = {\n async request(url, init) {\n const fetchInit: RequestInit = { method: init?.method ?? \"GET\" };\n const merged = { ...defaultHeaders, ...init?.headers };\n if (Object.keys(merged).length) { fetchInit.headers = merged; }\n if (init?.body !== undefined) {\n fetchInit.body = JSON.stringify(init.body);\n fetchInit.headers = { \"Content-Type\": \"application/json\", ...merged };\n }\n const res = await fetch(url, fetchInit);\n if (!res.ok) {\n let message = `HTTP ${res.status}`;\n try {\n const text = await res.text();\n if (text) {\n const json = JSON.parse(text);\n message = json.error ?? json.message ?? message;\n }\n } catch {}\n throw new Error(message);\n }\n const text = await res.text();\n return text ? JSON.parse(text) : undefined;\n },\n};\n\nlet httpClient: HttpClient = defaultHttpClient;\nlet defaultHeaders: Record<string, string> = {};\n\n/** Replace the global HTTP client used by `api.get` and `api.post/put/patch/delete`. */\nexport function setHttpClient(client: HttpClient): void {\n httpClient = client;\n}\n\n/** Set default headers merged into every HTTP request. Per-request headers override defaults. */\nexport function setDefaultHeaders(headers: Record<string, string>): void {\n defaultHeaders = headers;\n}\n\nexport class SnapStore<T extends object, K extends string = string> {\n private _store: RawStore<T>;\n private _operations = new Map<K, OperationState>();\n private _generations = new Map<K, number>();\n\n protected readonly state: StateAccessor<T>;\n protected readonly api: ApiAccessor<K>;\n\n constructor(initialState: T, options?: StoreOptions) {\n this._store = createStore(initialState, options);\n\n const store = this._store;\n const operations = this._operations;\n const generations = this._generations;\n\n // takeLatest semantic: if a newer call starts for the same key, the older\n // call's promise resolves silently (no reject, no state update).\n const doFetch = async (key: K, fn: () => Promise<void>): Promise<void> => {\n const gen = (generations.get(key) ?? 0) + 1;\n generations.set(key, gen);\n operations.set(key, { status: asyncStatus(\"loading\"), error: null });\n store.notify();\n try {\n await fn();\n if (generations.get(key) !== gen) { return; }\n operations.set(key, { status: asyncStatus(\"ready\"), error: null });\n } catch (e) {\n if (generations.get(key) !== gen) { return; }\n operations.set(key, {\n status: asyncStatus(\"error\"),\n error: e instanceof Error ? e.message : \"Unknown error\",\n });\n store.notify();\n throw e;\n }\n store.notify();\n };\n\n const doSend = async <R>(key: K, method: string, url: string, options?: ApiRequestOptions<R>): Promise<void> => {\n await doFetch(key, async () => {\n try {\n const data = await httpClient.request<R>(url, {\n method,\n body: options?.body,\n headers: options?.headers,\n });\n options?.onSuccess?.(data);\n } catch (e) {\n options?.onError?.(e instanceof Error ? e : new Error(\"Unknown error\"));\n throw e;\n }\n });\n };\n\n this.state = {\n get: ((path?: string): unknown => {\n if (path === undefined) { return store.get(); }\n return (store.get as (p: string) => unknown)(path);\n }) as StateAccessor<T>[\"get\"],\n\n set: (path, value) => store.set(path, value),\n batch: (fn) => store.batch(fn),\n computed: (deps, fn) => store.computed(deps, fn),\n\n append: (path, ...items) => {\n store.set(path as any, ((prev: any) => [...(prev as any[]), ...items]) as any);\n },\n prepend: (path, ...items) => {\n store.set(path as any, ((prev: any) => [...items, ...(prev as any[])]) as any);\n },\n insertAt: (path, index, ...items) => {\n store.set(path as any, ((prev: any) => {\n const arr = prev as any[];\n return [...arr.slice(0, index), ...items, ...arr.slice(index)];\n }) as any);\n },\n patch: (path, predicate, updates) => {\n store.set(path as any, ((prev: any) => {\n const arr = prev as any[];\n let changed = false;\n const result = arr.map((item: any) => {\n if (item == null) { return item; }\n if (predicate(item)) {\n changed = true;\n return Object.assign(Object.create(Object.getPrototypeOf(item)), item, updates);\n }\n return item;\n });\n return changed ? result : arr;\n }) as any);\n },\n remove: (path, predicate) => {\n store.set(path as any, ((prev: any) => {\n const arr = prev as any[];\n const result = arr.filter((item: any) => !predicate(item));\n return result.length === arr.length ? arr : result;\n }) as any);\n },\n removeAt: (path, index) => {\n store.set(path as any, ((prev: any) => {\n const arr = prev as any[];\n const i = index < 0 ? arr.length + index : index;\n if (i < 0 || i >= arr.length) {\n throw new RangeError(`Index ${index} out of bounds for array of length ${arr.length}`);\n }\n return [...arr.slice(0, i), ...arr.slice(i + 1)];\n }) as any);\n },\n at: (path, index) => {\n return (store.get(path as any) as any[]).at(index);\n },\n filter: (path, predicate) => {\n return (store.get(path as any) as any[]).filter(predicate);\n },\n find: (path, predicate) => {\n return (store.get(path as any) as any[]).find(predicate);\n },\n findIndexOf: (path, predicate) => {\n return (store.get(path as any) as any[]).findIndex(predicate);\n },\n count: (path, predicate) => {\n return (store.get(path as any) as any[]).filter(predicate).length;\n },\n };\n\n this.api = {\n fetch: doFetch,\n get: async <R>(key: K, url: string, onSuccess?: (data: R) => void): Promise<void> => {\n await doFetch(key, async () => {\n const data = await httpClient.request<R>(url);\n onSuccess?.(data);\n });\n },\n post: (key, url, options?) => doSend(key, \"POST\", url, options),\n put: (key, url, options?) => doSend(key, \"PUT\", url, options),\n patch: (key, url, options?) => doSend(key, \"PATCH\", url, options),\n delete: (key, url, options?) => doSend(key, \"DELETE\", url, options),\n };\n }\n\n /** Subscribe to all state changes. Returns an unsubscribe function. */\n subscribe(callback: Listener): Unsubscribe;\n /** Subscribe to changes at a specific dot-separated path. */\n subscribe(path: string, callback: Listener): Unsubscribe;\n subscribe(pathOrCallback: string | Listener, callback?: Listener): Unsubscribe {\n if (typeof pathOrCallback === \"function\") {\n return this._store.subscribe(pathOrCallback);\n }\n return this._store.subscribe(pathOrCallback, callback!);\n }\n\n /** Return a snapshot of the current state. Compatible with React's `useSyncExternalStore`. */\n getSnapshot = (): T => {\n return this._store.getSnapshot();\n };\n\n /** Get the async status of an operation by key. Returns `idle` if never started. */\n getStatus(key: K): OperationState {\n return { ...(this._operations.get(key) ?? IDLE_STATE) };\n }\n\n /** Tear down subscriptions and cleanup. */\n destroy(): void {\n this._store.destroy();\n }\n}\n"],"mappings":"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","names":["next","text","options","Connected"]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thalesfp/snapstate",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "State management for React - testable, extensible, predictable class-based stores",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
7
7
|
"module": "./dist/index.js",
|