@humanspeak/svelte-keyed
Version:
A powerful writable derived store for Svelte that enables deep object and array manipulation with TypeScript support
55 lines (54 loc) • 2.56 kB
TypeScript
import { type Writable } from 'svelte/store';
import type { Get } from 'type-fest';
/**
* Converts a string path with array notation into an array of tokens.
* Optimized version that avoids unnecessary string operations and uses a single pass.
*
* @param key - The path string to tokenize (e.g., "users[0].name" or "deeply.nested.property")
* @returns An array of string tokens representing each path segment
*
* @example
* ```ts
* getTokens('users[0].name') // returns ['users', '0', 'name']
* getTokens('deeply.nested.property') // returns ['deeply', 'nested', 'property']
* ```
*/
export declare const getTokens: (key: string) => string[];
/**
* Creates a derived writable store that represents a nested value within a parent store.
* The derived store maintains reactivity with the parent store while allowing direct
* manipulation of the nested value.
*
* @param parent - The parent writable store containing the nested value
* @param path - The path to the nested value, using dot notation or array indices
* @returns A writable store for the nested value that syncs with the parent store
*
* @throws {Error} If the path contains '__proto__' to prevent prototype pollution
*
* @example
* ```ts
* const user = writable({
* profile: {
* name: 'Alice',
* settings: { theme: 'dark' }
* }
* });
*
* // Create a store for just the theme
* const theme = keyed(user, 'profile.settings.theme');
*
* // Subscribe to changes
* theme.subscribe(value => console.log('Theme:', value)); // logs: "Theme: dark"
*
* // Update the nested value directly
* theme.set('light'); // Updates user store with new theme
* ```
*/
export declare function keyed<Parent extends object, Path extends string>(parent: Writable<Parent>, path: Path | KeyPath<Parent>): Writable<Get<Parent, Path>>;
export declare function keyed<Parent extends object, Path extends string>(parent: Writable<Parent | undefined | null>, path: Path | KeyPath<Parent>): Writable<Get<Parent, Path> | undefined>;
type KeyPath<T, D extends number = 3> = KeyPath_<T, D, []>;
type KeyPath_<T, D extends number, S extends unknown[]> = D extends S['length'] ? never : T extends object ? {
[K in keyof T]-?: K extends string ? `${K}` | Join<K, KeyPath_<T[K], D, [never, ...S]>> : K extends number ? `[${K}]` | Join<`[${K}]`, KeyPath_<T[K], D, [never, ...S]>> : never;
}[keyof T] : '';
type Join<K, P> = K extends string | number ? P extends string | number ? P extends `[${string}` ? `${K}${P}` : `${K}${'' extends P ? '' : '.'}${P}` : never : never;
export {};