react-mnemonic 0.1.1-alpha.0 → 1.1.0-beta0
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 +399 -96
- package/dist/index.cjs +1672 -471
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +963 -45
- package/dist/index.d.ts +963 -45
- package/dist/index.js +1663 -473
- package/dist/index.js.map +1 -1
- package/package.json +9 -1
package/dist/index.d.cts
CHANGED
|
@@ -149,6 +149,8 @@ declare function createCodec<T>(encode: (value: T) => string, decode: (encoded:
|
|
|
149
149
|
* | `WRITE_SCHEMA_REQUIRED` | Strict mode requires a schema to write, but none was found. |
|
|
150
150
|
* | `MIGRATION_PATH_NOT_FOUND` | No contiguous migration path between the stored and latest version. |
|
|
151
151
|
* | `MIGRATION_FAILED` | A migration step threw during execution. |
|
|
152
|
+
* | `MIGRATION_GRAPH_INVALID` | The schema registry helper received an ambiguous or cyclic migration graph. |
|
|
153
|
+
* | `RECONCILE_FAILED` | A read-time reconciliation hook threw or returned an unpersistable value. |
|
|
152
154
|
* | `SCHEMA_REGISTRATION_CONFLICT` | `registerSchema` was called with a conflicting definition. |
|
|
153
155
|
* | `TYPE_MISMATCH` | The decoded value failed JSON Schema validation. |
|
|
154
156
|
* | `MODE_CONFIGURATION_INVALID` | The schema mode requires a capability the registry doesn't provide. |
|
|
@@ -170,7 +172,7 @@ declare class SchemaError extends Error {
|
|
|
170
172
|
/**
|
|
171
173
|
* Machine-readable code identifying the category of schema failure.
|
|
172
174
|
*/
|
|
173
|
-
readonly code: "INVALID_ENVELOPE" | "SCHEMA_NOT_FOUND" | "WRITE_SCHEMA_REQUIRED" | "MIGRATION_PATH_NOT_FOUND" | "MIGRATION_FAILED" | "SCHEMA_REGISTRATION_CONFLICT" | "TYPE_MISMATCH" | "MODE_CONFIGURATION_INVALID";
|
|
175
|
+
readonly code: "INVALID_ENVELOPE" | "SCHEMA_NOT_FOUND" | "WRITE_SCHEMA_REQUIRED" | "MIGRATION_PATH_NOT_FOUND" | "MIGRATION_FAILED" | "MIGRATION_GRAPH_INVALID" | "RECONCILE_FAILED" | "SCHEMA_REGISTRATION_CONFLICT" | "TYPE_MISMATCH" | "MODE_CONFIGURATION_INVALID";
|
|
174
176
|
/**
|
|
175
177
|
* The underlying error that caused this failure, if any.
|
|
176
178
|
*/
|
|
@@ -302,6 +304,51 @@ declare function compileSchema(schema: JsonSchema): CompiledValidator;
|
|
|
302
304
|
*/
|
|
303
305
|
declare function validateJsonSchema(value: unknown, schema: JsonSchema, path?: string): JsonSchemaValidationError[];
|
|
304
306
|
|
|
307
|
+
declare const typedSchemaBrand: unique symbol;
|
|
308
|
+
declare const optionalSchemaBrand: unique symbol;
|
|
309
|
+
type JsonPrimitive = string | number | boolean | null;
|
|
310
|
+
type JsonConstValue = JsonPrimitive | readonly JsonConstValue[] | {
|
|
311
|
+
readonly [key: string]: JsonConstValue;
|
|
312
|
+
};
|
|
313
|
+
type TypedJsonSchema<T> = JsonSchema & {
|
|
314
|
+
readonly [typedSchemaBrand]?: T;
|
|
315
|
+
};
|
|
316
|
+
type OptionalTypedJsonSchema<T> = TypedJsonSchema<T> & {
|
|
317
|
+
readonly [optionalSchemaBrand]: true;
|
|
318
|
+
};
|
|
319
|
+
type InferJsonSchemaValue<TSchema> = TSchema extends TypedJsonSchema<infer TValue> ? TValue : unknown;
|
|
320
|
+
type ObjectValueFromSchemas<TShape extends Record<string, TypedJsonSchema<unknown> | OptionalTypedJsonSchema<unknown>>> = {
|
|
321
|
+
[K in keyof TShape as TShape[K] extends OptionalTypedJsonSchema<unknown> ? never : K]: InferJsonSchemaValue<TShape[K]>;
|
|
322
|
+
} & {
|
|
323
|
+
[K in keyof TShape as TShape[K] extends OptionalTypedJsonSchema<unknown> ? K : never]?: InferJsonSchemaValue<TShape[K]>;
|
|
324
|
+
};
|
|
325
|
+
type StringSchemaOptions = Pick<JsonSchema, "minLength" | "maxLength">;
|
|
326
|
+
type NumberSchemaOptions = Pick<JsonSchema, "minimum" | "maximum" | "exclusiveMinimum" | "exclusiveMaximum">;
|
|
327
|
+
type ArraySchemaOptions = Pick<JsonSchema, "minItems" | "maxItems">;
|
|
328
|
+
type ObjectSchemaOptions = Pick<JsonSchema, "additionalProperties">;
|
|
329
|
+
/**
|
|
330
|
+
* Builder helpers for strongly typed schemas backed by Mnemonic's built-in
|
|
331
|
+
* JSON Schema subset.
|
|
332
|
+
*
|
|
333
|
+
* The returned schemas are plain `JsonSchema` objects at runtime, so they can
|
|
334
|
+
* be registered directly in `createSchemaRegistry(...)` while also carrying a
|
|
335
|
+
* phantom TypeScript type for inference.
|
|
336
|
+
*/
|
|
337
|
+
declare const mnemonicSchema: {
|
|
338
|
+
string(options?: StringSchemaOptions): TypedJsonSchema<string>;
|
|
339
|
+
number(options?: NumberSchemaOptions): TypedJsonSchema<number>;
|
|
340
|
+
integer(options?: NumberSchemaOptions): TypedJsonSchema<number>;
|
|
341
|
+
boolean(): TypedJsonSchema<boolean>;
|
|
342
|
+
nullValue(): TypedJsonSchema<null>;
|
|
343
|
+
literal<const TValue extends JsonConstValue>(value: TValue): TypedJsonSchema<TValue>;
|
|
344
|
+
enum<const TValues extends readonly [JsonPrimitive, ...JsonPrimitive[]]>(values: TValues): TypedJsonSchema<TValues[number]>;
|
|
345
|
+
optional<T>(schema: TypedJsonSchema<T>): OptionalTypedJsonSchema<T>;
|
|
346
|
+
nullable<T>(schema: TypedJsonSchema<T>): TypedJsonSchema<T | null>;
|
|
347
|
+
array<TItemSchema extends TypedJsonSchema<unknown>>(itemSchema: TItemSchema, options?: ArraySchemaOptions): TypedJsonSchema<InferJsonSchemaValue<TItemSchema>[]>;
|
|
348
|
+
object<TShape extends Record<string, TypedJsonSchema<unknown> | OptionalTypedJsonSchema<unknown>>>(shape: TShape, options?: ObjectSchemaOptions): TypedJsonSchema<ObjectValueFromSchemas<TShape>>;
|
|
349
|
+
record<TValueSchema extends TypedJsonSchema<unknown>>(valueSchema: TValueSchema): TypedJsonSchema<Record<string, InferJsonSchemaValue<TValueSchema>>>;
|
|
350
|
+
};
|
|
351
|
+
|
|
305
352
|
/**
|
|
306
353
|
* @fileoverview Type definitions for the Mnemonic library.
|
|
307
354
|
*
|
|
@@ -309,6 +356,7 @@ declare function validateJsonSchema(value: unknown, schema: JsonSchema, path?: s
|
|
|
309
356
|
* library for type-safe, persistent state management in React applications.
|
|
310
357
|
*/
|
|
311
358
|
|
|
359
|
+
declare const keySchemaValueBrand: unique symbol;
|
|
312
360
|
/**
|
|
313
361
|
* Codec for encoding and decoding values to and from storage.
|
|
314
362
|
*
|
|
@@ -386,7 +434,8 @@ interface MnemonicProviderOptions {
|
|
|
386
434
|
* Storage backend to use for persistence.
|
|
387
435
|
*
|
|
388
436
|
* Defaults to `window.localStorage` in browser environments. You can provide
|
|
389
|
-
* a custom implementation (e.g., sessionStorage,
|
|
437
|
+
* a synchronous custom implementation (e.g., sessionStorage, an in-memory
|
|
438
|
+
* cache facade over IndexedDB, or a mock for testing).
|
|
390
439
|
*
|
|
391
440
|
* @default window.localStorage
|
|
392
441
|
*
|
|
@@ -407,8 +456,13 @@ interface MnemonicProviderOptions {
|
|
|
407
456
|
/**
|
|
408
457
|
* Enable DevTools debugging interface.
|
|
409
458
|
*
|
|
410
|
-
* When enabled,
|
|
411
|
-
*
|
|
459
|
+
* When enabled, registers this provider in the global
|
|
460
|
+
* `window.__REACT_MNEMONIC_DEVTOOLS__` registry.
|
|
461
|
+
*
|
|
462
|
+
* The registry stores providers as weak references and exposes:
|
|
463
|
+
* - `resolve(namespace)` to strengthen a provider reference and access
|
|
464
|
+
* inspection methods.
|
|
465
|
+
* - `list()` to enumerate provider availability.
|
|
412
466
|
*
|
|
413
467
|
* @default false
|
|
414
468
|
*
|
|
@@ -418,9 +472,10 @@ interface MnemonicProviderOptions {
|
|
|
418
472
|
* enableDevTools: process.env.NODE_ENV === 'development'
|
|
419
473
|
*
|
|
420
474
|
* // Then in browser console:
|
|
421
|
-
* window.__REACT_MNEMONIC_DEVTOOLS__
|
|
422
|
-
*
|
|
423
|
-
*
|
|
475
|
+
* const provider = window.__REACT_MNEMONIC_DEVTOOLS__?.resolve('myApp')
|
|
476
|
+
* provider?.dump()
|
|
477
|
+
* provider?.get('user')
|
|
478
|
+
* provider?.set('user', { name: 'Test' })
|
|
424
479
|
* ```
|
|
425
480
|
*/
|
|
426
481
|
enableDevTools?: boolean;
|
|
@@ -458,6 +513,24 @@ interface MnemonicProviderOptions {
|
|
|
458
513
|
* @see {@link KeySchema} - Schema definition stored in the registry
|
|
459
514
|
*/
|
|
460
515
|
schemaRegistry?: SchemaRegistry;
|
|
516
|
+
/**
|
|
517
|
+
* Server-rendering and hydration defaults for descendant hooks.
|
|
518
|
+
*
|
|
519
|
+
* Provider-level SSR settings establish the default hydration strategy for
|
|
520
|
+
* all `useMnemonicKey(...)` calls in this namespace. Individual hooks may
|
|
521
|
+
* still override the strategy when a specific key needs different behavior.
|
|
522
|
+
*
|
|
523
|
+
* @example
|
|
524
|
+
* ```tsx
|
|
525
|
+
* <MnemonicProvider
|
|
526
|
+
* namespace="app"
|
|
527
|
+
* ssr={{ hydration: "client-only" }}
|
|
528
|
+
* >
|
|
529
|
+
* <App />
|
|
530
|
+
* </MnemonicProvider>
|
|
531
|
+
* ```
|
|
532
|
+
*/
|
|
533
|
+
ssr?: MnemonicProviderSSRConfig;
|
|
461
534
|
}
|
|
462
535
|
/**
|
|
463
536
|
* Controls how the provider enforces versioned schemas on stored values.
|
|
@@ -491,6 +564,163 @@ interface MnemonicProviderOptions {
|
|
|
491
564
|
* @see {@link KeySchema} - Individual schema definition
|
|
492
565
|
*/
|
|
493
566
|
type SchemaMode = "strict" | "default" | "autoschema";
|
|
567
|
+
/**
|
|
568
|
+
* Controls when a hook should read persisted storage during client rendering.
|
|
569
|
+
*
|
|
570
|
+
* - `"immediate"` — Default. The server snapshot is used during SSR/hydration,
|
|
571
|
+
* and the hook reads persisted storage as soon as React switches to the
|
|
572
|
+
* client snapshot.
|
|
573
|
+
*
|
|
574
|
+
* - `"client-only"` — Defers all storage reads until after the component has
|
|
575
|
+
* mounted on the client. This is useful when you want a deterministic server
|
|
576
|
+
* placeholder and prefer the persisted value to appear only after hydration
|
|
577
|
+
* completes.
|
|
578
|
+
*/
|
|
579
|
+
type MnemonicHydrationMode = "immediate" | "client-only";
|
|
580
|
+
/**
|
|
581
|
+
* Provider-level SSR defaults shared by descendant hooks.
|
|
582
|
+
*/
|
|
583
|
+
interface MnemonicProviderSSRConfig {
|
|
584
|
+
/**
|
|
585
|
+
* Default hydration strategy for descendant `useMnemonicKey(...)` hooks.
|
|
586
|
+
*
|
|
587
|
+
* @default "immediate"
|
|
588
|
+
*/
|
|
589
|
+
hydration?: MnemonicHydrationMode;
|
|
590
|
+
}
|
|
591
|
+
/**
|
|
592
|
+
* Hook-level SSR controls for `useMnemonicKey(...)`.
|
|
593
|
+
*
|
|
594
|
+
* Lets a key render a deterministic server snapshot and optionally delay
|
|
595
|
+
* reading persisted storage until after client mount.
|
|
596
|
+
*
|
|
597
|
+
* @template T - The decoded value type for the key
|
|
598
|
+
*/
|
|
599
|
+
interface MnemonicKeySSRConfig<T> {
|
|
600
|
+
/**
|
|
601
|
+
* Value to expose during SSR and hydration instead of `defaultValue`.
|
|
602
|
+
*
|
|
603
|
+
* This value is not persisted automatically. Once hydration completes,
|
|
604
|
+
* the hook transitions to the stored value (if any) or back to
|
|
605
|
+
* `defaultValue`.
|
|
606
|
+
*
|
|
607
|
+
* Factory functions should be deterministic across server render and
|
|
608
|
+
* client hydration to avoid markup mismatches.
|
|
609
|
+
*/
|
|
610
|
+
serverValue?: T | (() => T);
|
|
611
|
+
/**
|
|
612
|
+
* Hydration strategy for this key.
|
|
613
|
+
*
|
|
614
|
+
* When omitted, inherits the provider default.
|
|
615
|
+
*/
|
|
616
|
+
hydration?: MnemonicHydrationMode;
|
|
617
|
+
}
|
|
618
|
+
/**
|
|
619
|
+
* Weak-reference shape used by the devtools registry.
|
|
620
|
+
*
|
|
621
|
+
* Matches the standard `WeakRef` API while keeping the public type surface
|
|
622
|
+
* compatible with ES2020 TypeScript lib targets.
|
|
623
|
+
*/
|
|
624
|
+
interface MnemonicDevToolsWeakRef<T extends object> {
|
|
625
|
+
/**
|
|
626
|
+
* Attempts to strengthen the weak reference.
|
|
627
|
+
*
|
|
628
|
+
* @returns The live object, or undefined if it was garbage-collected.
|
|
629
|
+
*/
|
|
630
|
+
deref: () => T | undefined;
|
|
631
|
+
}
|
|
632
|
+
/**
|
|
633
|
+
* Provider inspection API exposed through devtools registry resolution.
|
|
634
|
+
*
|
|
635
|
+
* Resolve a provider from the registry, then invoke these methods for manual
|
|
636
|
+
* inspection/mutation from the browser console.
|
|
637
|
+
*/
|
|
638
|
+
interface MnemonicDevToolsProviderApi {
|
|
639
|
+
/** Access the underlying store instance. */
|
|
640
|
+
getStore: () => Mnemonic;
|
|
641
|
+
/** Dump all raw key-value pairs for the provider namespace. */
|
|
642
|
+
dump: () => Record<string, string>;
|
|
643
|
+
/** Read decoded value for an unprefixed key. */
|
|
644
|
+
get: (key: string) => unknown;
|
|
645
|
+
/** Write value for an unprefixed key (JSON-encoded). */
|
|
646
|
+
set: (key: string, value: unknown) => void;
|
|
647
|
+
/** Remove a single unprefixed key. */
|
|
648
|
+
remove: (key: string) => void;
|
|
649
|
+
/** Remove all keys in this provider namespace. */
|
|
650
|
+
clear: () => void;
|
|
651
|
+
/** List all unprefixed keys in this provider namespace. */
|
|
652
|
+
keys: () => string[];
|
|
653
|
+
}
|
|
654
|
+
/**
|
|
655
|
+
* Registry entry for a single provider namespace.
|
|
656
|
+
*/
|
|
657
|
+
interface MnemonicDevToolsProviderEntry {
|
|
658
|
+
/** Namespace key for this provider entry. */
|
|
659
|
+
namespace: string;
|
|
660
|
+
/** Weak reference to the provider inspection API. */
|
|
661
|
+
weakRef: MnemonicDevToolsWeakRef<MnemonicDevToolsProviderApi>;
|
|
662
|
+
/** Timestamp when this namespace was registered. */
|
|
663
|
+
registeredAt: number;
|
|
664
|
+
/** Timestamp when provider was last confirmed live. */
|
|
665
|
+
lastSeenAt: number;
|
|
666
|
+
/** Timestamp when provider was first observed unavailable, or null when live. */
|
|
667
|
+
staleSince: number | null;
|
|
668
|
+
}
|
|
669
|
+
/**
|
|
670
|
+
* Lightweight provider status returned by `list()`.
|
|
671
|
+
*/
|
|
672
|
+
interface MnemonicDevToolsProviderDescriptor {
|
|
673
|
+
/** Namespace registered by the provider. */
|
|
674
|
+
namespace: string;
|
|
675
|
+
/** Whether the provider can currently be resolved to a live API instance. */
|
|
676
|
+
available: boolean;
|
|
677
|
+
/** Timestamp when the provider namespace was first registered. */
|
|
678
|
+
registeredAt: number;
|
|
679
|
+
/** Timestamp when the provider was last observed as live. */
|
|
680
|
+
lastSeenAt: number;
|
|
681
|
+
/** Timestamp when the provider first became unavailable, or `null` when live. */
|
|
682
|
+
staleSince: number | null;
|
|
683
|
+
}
|
|
684
|
+
/**
|
|
685
|
+
* Environment capabilities reported by devtools registry.
|
|
686
|
+
*/
|
|
687
|
+
interface MnemonicDevToolsCapabilities {
|
|
688
|
+
/** Whether the runtime supports `WeakRef`. */
|
|
689
|
+
weakRef: boolean;
|
|
690
|
+
/** Whether the runtime supports `FinalizationRegistry`. */
|
|
691
|
+
finalizationRegistry: boolean;
|
|
692
|
+
}
|
|
693
|
+
/**
|
|
694
|
+
* Polling metadata for extension synchronization.
|
|
695
|
+
*/
|
|
696
|
+
interface MnemonicDevToolsMeta {
|
|
697
|
+
/** Monotonic registry version incremented on register and mutation events. */
|
|
698
|
+
version: number;
|
|
699
|
+
/** Timestamp of the most recent registry update. */
|
|
700
|
+
lastUpdated: number;
|
|
701
|
+
/** Short label describing the most recent registry change. */
|
|
702
|
+
lastChange: string;
|
|
703
|
+
}
|
|
704
|
+
/**
|
|
705
|
+
* Global devtools registry contract available on window.
|
|
706
|
+
*
|
|
707
|
+
* This is an advanced public API used by the browser console integration and
|
|
708
|
+
* extension tooling. Direct namespace access
|
|
709
|
+
* (`window.__REACT_MNEMONIC_DEVTOOLS__.myNamespace`) is not part of the
|
|
710
|
+
* public API.
|
|
711
|
+
*/
|
|
712
|
+
interface MnemonicDevToolsRegistry {
|
|
713
|
+
/** Provider entries keyed by namespace. */
|
|
714
|
+
providers: Record<string, MnemonicDevToolsProviderEntry>;
|
|
715
|
+
/** Resolve a namespace to a live provider API when one is available. */
|
|
716
|
+
resolve: (namespace: string) => MnemonicDevToolsProviderApi | null;
|
|
717
|
+
/** List provider availability without strengthening weak references manually. */
|
|
718
|
+
list: () => MnemonicDevToolsProviderDescriptor[];
|
|
719
|
+
/** Runtime capabilities relevant to the registry implementation. */
|
|
720
|
+
capabilities: MnemonicDevToolsCapabilities;
|
|
721
|
+
/** Versioning metadata used by polling devtools integrations. */
|
|
722
|
+
__meta: MnemonicDevToolsMeta;
|
|
723
|
+
}
|
|
494
724
|
/**
|
|
495
725
|
* Schema definition for a single key at a specific version.
|
|
496
726
|
*
|
|
@@ -521,11 +751,11 @@ type SchemaMode = "strict" | "default" | "autoschema";
|
|
|
521
751
|
* @see {@link MigrationRule} - How values migrate between schema versions
|
|
522
752
|
* @see {@link JsonSchema} - The JSON Schema subset used for validation
|
|
523
753
|
*/
|
|
524
|
-
type KeySchema = {
|
|
754
|
+
type KeySchema<TValue = unknown, K extends string = string, TSchema extends JsonSchema = JsonSchema> = {
|
|
525
755
|
/**
|
|
526
756
|
* The unprefixed storage key this schema applies to.
|
|
527
757
|
*/
|
|
528
|
-
key:
|
|
758
|
+
key: K;
|
|
529
759
|
/**
|
|
530
760
|
* The version number for this schema.
|
|
531
761
|
*
|
|
@@ -538,7 +768,15 @@ type KeySchema = {
|
|
|
538
768
|
* Only the subset of JSON Schema keywords defined in {@link JsonSchema}
|
|
539
769
|
* are supported. An empty schema `{}` accepts any value.
|
|
540
770
|
*/
|
|
541
|
-
schema:
|
|
771
|
+
schema: TSchema;
|
|
772
|
+
/**
|
|
773
|
+
* Phantom type linking this runtime schema to its decoded TypeScript value.
|
|
774
|
+
*
|
|
775
|
+
* This field is never set at runtime. It exists only so helpers such as
|
|
776
|
+
* `defineKeySchema(...)`, `defineMnemonicKey(...)`, and `defineMigration(...)`
|
|
777
|
+
* can preserve a single source of truth between schema shape and value type.
|
|
778
|
+
*/
|
|
779
|
+
readonly [keySchemaValueBrand]?: TValue;
|
|
542
780
|
};
|
|
543
781
|
/**
|
|
544
782
|
* A single migration step that transforms data from one schema version to
|
|
@@ -581,11 +819,11 @@ type KeySchema = {
|
|
|
581
819
|
* @see {@link SchemaRegistry.getMigrationPath} - How the path is resolved
|
|
582
820
|
* @see {@link SchemaRegistry.getWriteMigration} - How write-time normalizers are resolved
|
|
583
821
|
*/
|
|
584
|
-
type MigrationRule = {
|
|
822
|
+
type MigrationRule<TFrom = unknown, TTo = unknown, K extends string = string> = {
|
|
585
823
|
/**
|
|
586
824
|
* The unprefixed storage key this rule applies to.
|
|
587
825
|
*/
|
|
588
|
-
key:
|
|
826
|
+
key: K;
|
|
589
827
|
/**
|
|
590
828
|
* The version the stored data is migrating **from**.
|
|
591
829
|
*
|
|
@@ -609,7 +847,7 @@ type MigrationRule = {
|
|
|
609
847
|
* @param value - The decoded value at `fromVersion`
|
|
610
848
|
* @returns The transformed value for `toVersion`
|
|
611
849
|
*/
|
|
612
|
-
migrate
|
|
850
|
+
migrate(value: TFrom): TTo;
|
|
613
851
|
};
|
|
614
852
|
/**
|
|
615
853
|
* An ordered sequence of {@link MigrationRule} steps that upgrades stored
|
|
@@ -623,7 +861,36 @@ type MigrationRule = {
|
|
|
623
861
|
* @see {@link MigrationRule} - Individual migration step
|
|
624
862
|
* @see {@link SchemaRegistry.getMigrationPath} - Resolves a path between versions
|
|
625
863
|
*/
|
|
626
|
-
type MigrationPath = MigrationRule[];
|
|
864
|
+
type MigrationPath<K extends string = string> = MigrationRule<unknown, unknown, K>[];
|
|
865
|
+
/**
|
|
866
|
+
* Input options for {@link createSchemaRegistry}.
|
|
867
|
+
*
|
|
868
|
+
* Use this helper when your registry contents are known up front and do not
|
|
869
|
+
* need runtime mutation. The returned registry is immutable and optimized for
|
|
870
|
+
* the common `"default"` / `"strict"` setup.
|
|
871
|
+
*
|
|
872
|
+
* For most apps, this should be your default entry point for schema-managed
|
|
873
|
+
* persistence. Implement {@link SchemaRegistry} manually only when you need
|
|
874
|
+
* custom lookup behavior or runtime schema registration beyond autoschema mode.
|
|
875
|
+
*/
|
|
876
|
+
interface CreateSchemaRegistryOptions {
|
|
877
|
+
/**
|
|
878
|
+
* Versioned schemas to index by key and version.
|
|
879
|
+
*
|
|
880
|
+
* Duplicate `key + version` pairs are rejected up front with
|
|
881
|
+
* `SchemaError("SCHEMA_REGISTRATION_CONFLICT")`.
|
|
882
|
+
*/
|
|
883
|
+
schemas?: readonly KeySchema[];
|
|
884
|
+
/**
|
|
885
|
+
* Migration rules to index by key and version edge.
|
|
886
|
+
*
|
|
887
|
+
* Write-time normalizers (`fromVersion === toVersion`) are indexed
|
|
888
|
+
* separately from read-time migration edges. Ambiguous outgoing edges,
|
|
889
|
+
* backward migrations, and duplicate write normalizers are rejected up
|
|
890
|
+
* front with `SchemaError("MIGRATION_GRAPH_INVALID")`.
|
|
891
|
+
*/
|
|
892
|
+
migrations?: readonly MigrationRule[];
|
|
893
|
+
}
|
|
627
894
|
/**
|
|
628
895
|
* Lookup and registration API for key schemas and migration paths.
|
|
629
896
|
*
|
|
@@ -637,15 +904,19 @@ type MigrationPath = MigrationRule[];
|
|
|
637
904
|
* read/write hot paths fast. `"autoschema"` remains mutable to support
|
|
638
905
|
* inferred schema registration.
|
|
639
906
|
*
|
|
907
|
+
* Most applications should prefer {@link createSchemaRegistry} instead of
|
|
908
|
+
* implementing this interface manually. Manual implementations are mainly for
|
|
909
|
+
* advanced cases such as custom backing stores, dynamic schema discovery, or
|
|
910
|
+
* adapter layers around an existing registry system.
|
|
911
|
+
*
|
|
640
912
|
* @example
|
|
641
913
|
* ```typescript
|
|
642
|
-
* const registry
|
|
643
|
-
*
|
|
644
|
-
*
|
|
645
|
-
*
|
|
646
|
-
*
|
|
647
|
-
*
|
|
648
|
-
* };
|
|
914
|
+
* const registry = createSchemaRegistry({
|
|
915
|
+
* schemas: [
|
|
916
|
+
* { key: "settings", version: 1, schema: { type: "object", required: ["theme"] } },
|
|
917
|
+
* ],
|
|
918
|
+
* migrations: [],
|
|
919
|
+
* });
|
|
649
920
|
*
|
|
650
921
|
* <MnemonicProvider namespace="app" schemaRegistry={registry} schemaMode="strict">
|
|
651
922
|
* <App />
|
|
@@ -717,12 +988,17 @@ interface SchemaRegistry {
|
|
|
717
988
|
registerSchema?(schema: KeySchema): void;
|
|
718
989
|
}
|
|
719
990
|
/**
|
|
720
|
-
* Storage interface compatible with localStorage and custom storage implementations.
|
|
991
|
+
* Storage interface compatible with localStorage and synchronous custom storage implementations.
|
|
721
992
|
*
|
|
722
993
|
* Defines the minimum contract required for a storage backend. Compatible with
|
|
723
994
|
* browser Storage API (localStorage, sessionStorage) and custom implementations
|
|
724
995
|
* for testing or alternative storage solutions.
|
|
725
996
|
*
|
|
997
|
+
* All methods in this contract are intentionally synchronous. Promise-returning
|
|
998
|
+
* adapters such as React Native `AsyncStorage` are not directly supported by
|
|
999
|
+
* `StorageLike`; instead, keep a synchronous in-memory cache and flush to async
|
|
1000
|
+
* persistence outside the hook contract.
|
|
1001
|
+
*
|
|
726
1002
|
* @remarks
|
|
727
1003
|
* **Error handling contract**
|
|
728
1004
|
*
|
|
@@ -746,6 +1022,10 @@ interface SchemaRegistry {
|
|
|
746
1022
|
* In all error cases the library falls back to its in-memory cache, so
|
|
747
1023
|
* components continue to function when the storage backend is unavailable.
|
|
748
1024
|
*
|
|
1025
|
+
* Promise-returning `getItem`, `setItem`, or `removeItem` implementations are
|
|
1026
|
+
* treated as an invalid contract at runtime. Mnemonic logs the misuse once and
|
|
1027
|
+
* falls back to its in-memory cache for safety.
|
|
1028
|
+
*
|
|
749
1029
|
* @example
|
|
750
1030
|
* ```typescript
|
|
751
1031
|
* // In-memory storage for testing
|
|
@@ -767,6 +1047,8 @@ type StorageLike = {
|
|
|
767
1047
|
*
|
|
768
1048
|
* @param key - The storage key to retrieve
|
|
769
1049
|
* @returns The stored value as a string, or null if not found
|
|
1050
|
+
*
|
|
1051
|
+
* @remarks Must return synchronously. Returning a Promise is unsupported.
|
|
770
1052
|
*/
|
|
771
1053
|
getItem(key: string): string | null;
|
|
772
1054
|
/**
|
|
@@ -774,12 +1056,16 @@ type StorageLike = {
|
|
|
774
1056
|
*
|
|
775
1057
|
* @param key - The storage key
|
|
776
1058
|
* @param value - The string value to store
|
|
1059
|
+
*
|
|
1060
|
+
* @remarks Must complete synchronously. Returning a Promise is unsupported.
|
|
777
1061
|
*/
|
|
778
1062
|
setItem(key: string, value: string): void;
|
|
779
1063
|
/**
|
|
780
1064
|
* Removes a key-value pair from storage.
|
|
781
1065
|
*
|
|
782
1066
|
* @param key - The storage key to remove
|
|
1067
|
+
*
|
|
1068
|
+
* @remarks Must complete synchronously. Returning a Promise is unsupported.
|
|
783
1069
|
*/
|
|
784
1070
|
removeItem(key: string): void;
|
|
785
1071
|
/**
|
|
@@ -824,6 +1110,318 @@ type StorageLike = {
|
|
|
824
1110
|
*/
|
|
825
1111
|
onExternalChange?: (callback: (changedKeys?: string[]) => void) => () => void;
|
|
826
1112
|
};
|
|
1113
|
+
/**
|
|
1114
|
+
* Function type for unsubscribing from event listeners.
|
|
1115
|
+
*
|
|
1116
|
+
* Call this function to remove a subscription and stop receiving updates.
|
|
1117
|
+
*
|
|
1118
|
+
* @example
|
|
1119
|
+
* ```typescript
|
|
1120
|
+
* const unsubscribe = store.subscribeRaw('user', () => console.log('Updated!'));
|
|
1121
|
+
* // Later...
|
|
1122
|
+
* unsubscribe(); // Stop listening
|
|
1123
|
+
* ```
|
|
1124
|
+
*/
|
|
1125
|
+
type Unsubscribe = () => void;
|
|
1126
|
+
/**
|
|
1127
|
+
* Callback function invoked when a subscribed value changes.
|
|
1128
|
+
*
|
|
1129
|
+
* Used by the external store contract to notify React when state updates.
|
|
1130
|
+
*/
|
|
1131
|
+
type Listener = () => void;
|
|
1132
|
+
/**
|
|
1133
|
+
* Low-level Mnemonic store API provided via React Context.
|
|
1134
|
+
*
|
|
1135
|
+
* This interface powers `MnemonicProvider` internally and is also exposed to
|
|
1136
|
+
* advanced consumers through `MnemonicDevToolsProviderApi.getStore()`. Typical
|
|
1137
|
+
* application code should still prefer `useMnemonicKey`.
|
|
1138
|
+
*
|
|
1139
|
+
* All keys passed to these methods should be **unprefixed**. The store
|
|
1140
|
+
* automatically applies the namespace prefix internally.
|
|
1141
|
+
*
|
|
1142
|
+
* @remarks
|
|
1143
|
+
* This implements the React `useSyncExternalStore` contract for efficient,
|
|
1144
|
+
* tearing-free state synchronization. Most application code should still
|
|
1145
|
+
* prefer `useMnemonicKey`; this type mainly appears in the DevTools API via
|
|
1146
|
+
* `MnemonicDevToolsProviderApi.getStore()`.
|
|
1147
|
+
*/
|
|
1148
|
+
type Mnemonic = {
|
|
1149
|
+
/**
|
|
1150
|
+
* The namespace prefix applied to all keys in storage.
|
|
1151
|
+
*
|
|
1152
|
+
* Keys are stored as `${prefix}${key}` in the underlying storage backend.
|
|
1153
|
+
*/
|
|
1154
|
+
prefix: string;
|
|
1155
|
+
/**
|
|
1156
|
+
* Whether the active storage backend can enumerate keys in this namespace.
|
|
1157
|
+
*
|
|
1158
|
+
* This is `true` for `localStorage`-like backends that implement both
|
|
1159
|
+
* `length` and `key(index)`. Namespace-wide recovery helpers rely on this
|
|
1160
|
+
* capability unless the caller supplies an explicit key list.
|
|
1161
|
+
*/
|
|
1162
|
+
canEnumerateKeys: boolean;
|
|
1163
|
+
/**
|
|
1164
|
+
* Subscribe to changes for a specific key.
|
|
1165
|
+
*
|
|
1166
|
+
* Follows the React external store subscription contract. The listener
|
|
1167
|
+
* will be called whenever the value for this key changes.
|
|
1168
|
+
*
|
|
1169
|
+
* @param key - The unprefixed storage key to subscribe to
|
|
1170
|
+
* @param listener - Callback invoked when the value changes
|
|
1171
|
+
* @returns Unsubscribe function to stop listening
|
|
1172
|
+
*
|
|
1173
|
+
* @example
|
|
1174
|
+
* ```typescript
|
|
1175
|
+
* const unsubscribe = store.subscribeRaw('user', () => {
|
|
1176
|
+
* console.log('User changed:', store.getRawSnapshot('user'));
|
|
1177
|
+
* });
|
|
1178
|
+
* ```
|
|
1179
|
+
*/
|
|
1180
|
+
subscribeRaw: (key: string, listener: Listener) => Unsubscribe;
|
|
1181
|
+
/**
|
|
1182
|
+
* Get the current raw string value for a key.
|
|
1183
|
+
*
|
|
1184
|
+
* This is part of the external store snapshot contract. Values are
|
|
1185
|
+
* cached in memory for stable snapshots.
|
|
1186
|
+
*
|
|
1187
|
+
* @param key - The unprefixed storage key
|
|
1188
|
+
* @returns The raw string value, or null if not present
|
|
1189
|
+
*/
|
|
1190
|
+
getRawSnapshot: (key: string) => string | null;
|
|
1191
|
+
/**
|
|
1192
|
+
* Write a raw string value to storage.
|
|
1193
|
+
*
|
|
1194
|
+
* Updates both the in-memory cache and the underlying storage backend,
|
|
1195
|
+
* then notifies all subscribers for this key.
|
|
1196
|
+
*
|
|
1197
|
+
* @param key - The unprefixed storage key
|
|
1198
|
+
* @param raw - The raw string value to store
|
|
1199
|
+
*/
|
|
1200
|
+
setRaw: (key: string, raw: string) => void;
|
|
1201
|
+
/**
|
|
1202
|
+
* Remove a key from storage.
|
|
1203
|
+
*
|
|
1204
|
+
* Clears the value from both the cache and the underlying storage,
|
|
1205
|
+
* then notifies all subscribers.
|
|
1206
|
+
*
|
|
1207
|
+
* @param key - The unprefixed storage key to remove
|
|
1208
|
+
*/
|
|
1209
|
+
removeRaw: (key: string) => void;
|
|
1210
|
+
/**
|
|
1211
|
+
* Enumerate all keys in this namespace.
|
|
1212
|
+
*
|
|
1213
|
+
* Returns unprefixed keys that belong to this store's namespace.
|
|
1214
|
+
*
|
|
1215
|
+
* @returns Array of unprefixed key names
|
|
1216
|
+
*/
|
|
1217
|
+
keys: () => string[];
|
|
1218
|
+
/**
|
|
1219
|
+
* Dump all key-value pairs in this namespace.
|
|
1220
|
+
*
|
|
1221
|
+
* Useful for debugging and DevTools integration.
|
|
1222
|
+
*
|
|
1223
|
+
* @returns Object mapping unprefixed keys to raw string values
|
|
1224
|
+
*/
|
|
1225
|
+
dump: () => Record<string, string>;
|
|
1226
|
+
/**
|
|
1227
|
+
* The active schema enforcement mode for this provider.
|
|
1228
|
+
*
|
|
1229
|
+
* Propagated from the `schemaMode` provider option. Hooks read this
|
|
1230
|
+
* to determine how to handle versioned envelopes.
|
|
1231
|
+
*
|
|
1232
|
+
* @see {@link SchemaMode}
|
|
1233
|
+
*/
|
|
1234
|
+
schemaMode: SchemaMode;
|
|
1235
|
+
/**
|
|
1236
|
+
* Default hydration strategy inherited by descendant hooks.
|
|
1237
|
+
*/
|
|
1238
|
+
ssrHydration: MnemonicHydrationMode;
|
|
1239
|
+
/**
|
|
1240
|
+
* How this provider can observe external changes from other tabs/processes.
|
|
1241
|
+
*
|
|
1242
|
+
* Hooks use this for development diagnostics when callers opt into
|
|
1243
|
+
* cross-tab synchronization on a backend that cannot actually deliver it.
|
|
1244
|
+
*
|
|
1245
|
+
* When omitted, consumers should treat this as equivalent to `"none"`.
|
|
1246
|
+
*/
|
|
1247
|
+
crossTabSyncMode?: "browser-storage-event" | "custom-external-change" | "none";
|
|
1248
|
+
/**
|
|
1249
|
+
* The schema registry for this provider, if one was supplied.
|
|
1250
|
+
*
|
|
1251
|
+
* Hooks use this to look up schemas, resolve migration paths, and
|
|
1252
|
+
* (in autoschema mode) register inferred schemas.
|
|
1253
|
+
*
|
|
1254
|
+
* @see {@link SchemaRegistry}
|
|
1255
|
+
*/
|
|
1256
|
+
schemaRegistry?: SchemaRegistry;
|
|
1257
|
+
};
|
|
1258
|
+
/**
|
|
1259
|
+
* Recovery action names emitted by {@link useMnemonicRecovery}.
|
|
1260
|
+
*/
|
|
1261
|
+
type MnemonicRecoveryAction = "clear-all" | "clear-keys" | "clear-matching";
|
|
1262
|
+
/**
|
|
1263
|
+
* Recovery event payload emitted after a namespace recovery action completes.
|
|
1264
|
+
*/
|
|
1265
|
+
interface MnemonicRecoveryEvent {
|
|
1266
|
+
/**
|
|
1267
|
+
* Recovery action that just ran.
|
|
1268
|
+
*/
|
|
1269
|
+
action: MnemonicRecoveryAction;
|
|
1270
|
+
/**
|
|
1271
|
+
* Namespace where the recovery action ran.
|
|
1272
|
+
*/
|
|
1273
|
+
namespace: string;
|
|
1274
|
+
/**
|
|
1275
|
+
* Unprefixed keys cleared by the action.
|
|
1276
|
+
*/
|
|
1277
|
+
clearedKeys: string[];
|
|
1278
|
+
}
|
|
1279
|
+
/**
|
|
1280
|
+
* Options for {@link useMnemonicRecovery}.
|
|
1281
|
+
*/
|
|
1282
|
+
interface UseMnemonicRecoveryOptions {
|
|
1283
|
+
/**
|
|
1284
|
+
* Optional callback invoked after a recovery action completes.
|
|
1285
|
+
*
|
|
1286
|
+
* Useful for analytics, audit trails, support diagnostics, or user-facing
|
|
1287
|
+
* confirmation toasts.
|
|
1288
|
+
*/
|
|
1289
|
+
onRecover?: (event: MnemonicRecoveryEvent) => void;
|
|
1290
|
+
}
|
|
1291
|
+
/**
|
|
1292
|
+
* Namespace-scoped recovery helpers returned by {@link useMnemonicRecovery}.
|
|
1293
|
+
*
|
|
1294
|
+
* These helpers operate on the current provider namespace and are intended for
|
|
1295
|
+
* user-facing recovery UX such as "reset app data" or "clear stale filters".
|
|
1296
|
+
*/
|
|
1297
|
+
interface MnemonicRecoveryHook {
|
|
1298
|
+
/**
|
|
1299
|
+
* Current provider namespace without the trailing storage prefix dot.
|
|
1300
|
+
*/
|
|
1301
|
+
namespace: string;
|
|
1302
|
+
/**
|
|
1303
|
+
* Whether namespace keys can be enumerated automatically.
|
|
1304
|
+
*
|
|
1305
|
+
* `clearAll()` and `clearMatching()` require this to be `true`. If it is
|
|
1306
|
+
* `false`, prefer `clearKeys([...])` with an explicit durable-key list.
|
|
1307
|
+
*/
|
|
1308
|
+
canEnumerateKeys: boolean;
|
|
1309
|
+
/**
|
|
1310
|
+
* Lists all unprefixed keys currently visible in this namespace.
|
|
1311
|
+
*
|
|
1312
|
+
* Returns an empty array when no keys exist or when the storage backend
|
|
1313
|
+
* cannot enumerate keys.
|
|
1314
|
+
*/
|
|
1315
|
+
listKeys: () => string[];
|
|
1316
|
+
/**
|
|
1317
|
+
* Clears every key in the current namespace.
|
|
1318
|
+
*
|
|
1319
|
+
* @throws {Error} When the storage backend cannot enumerate namespace keys
|
|
1320
|
+
*/
|
|
1321
|
+
clearAll: () => string[];
|
|
1322
|
+
/**
|
|
1323
|
+
* Clears a specific set of unprefixed keys in the current namespace.
|
|
1324
|
+
*
|
|
1325
|
+
* Duplicate keys are ignored.
|
|
1326
|
+
*/
|
|
1327
|
+
clearKeys: (keys: readonly string[]) => string[];
|
|
1328
|
+
/**
|
|
1329
|
+
* Clears namespace keys whose names match the supplied predicate.
|
|
1330
|
+
*
|
|
1331
|
+
* @throws {Error} When the storage backend cannot enumerate namespace keys
|
|
1332
|
+
*/
|
|
1333
|
+
clearMatching: (predicate: (key: string) => boolean) => string[];
|
|
1334
|
+
}
|
|
1335
|
+
/**
|
|
1336
|
+
* Return shape from {@link useMnemonicKey}.
|
|
1337
|
+
*
|
|
1338
|
+
* This mirrors the familiar `useState` mental model while making the storage
|
|
1339
|
+
* semantics explicit:
|
|
1340
|
+
*
|
|
1341
|
+
* - `set(...)` writes a new persisted value
|
|
1342
|
+
* - `reset()` writes `defaultValue` back into storage
|
|
1343
|
+
* - `remove()` deletes the key entirely so reads fall back to `defaultValue`
|
|
1344
|
+
*
|
|
1345
|
+
* See the
|
|
1346
|
+
* [Clearable Persisted Values guide](https://thirtytwobits.github.io/react-mnemonic/docs/guides/clearable-persisted-values)
|
|
1347
|
+
* for the semantic differences between clearing, resetting, and removing a key.
|
|
1348
|
+
*
|
|
1349
|
+
* @template T - The decoded value type for the key
|
|
1350
|
+
*
|
|
1351
|
+
* @see {@link UseMnemonicKeyOptions} - Hook configuration and lifecycle details
|
|
1352
|
+
*/
|
|
1353
|
+
interface MnemonicKeyState<T> {
|
|
1354
|
+
/**
|
|
1355
|
+
* Current decoded value, or the default when the key is absent or invalid.
|
|
1356
|
+
*/
|
|
1357
|
+
value: T;
|
|
1358
|
+
/**
|
|
1359
|
+
* Persist a new value.
|
|
1360
|
+
*
|
|
1361
|
+
* Accepts either a direct replacement value or an updater function that
|
|
1362
|
+
* receives the current decoded value.
|
|
1363
|
+
*/
|
|
1364
|
+
set: (next: T | ((current: T) => T)) => void;
|
|
1365
|
+
/**
|
|
1366
|
+
* Reset the key back to `defaultValue` and persist that default.
|
|
1367
|
+
*/
|
|
1368
|
+
reset: () => void;
|
|
1369
|
+
/**
|
|
1370
|
+
* Delete the key from storage entirely.
|
|
1371
|
+
*
|
|
1372
|
+
* Future reads will fall back to `defaultValue` until the key is written
|
|
1373
|
+
* again.
|
|
1374
|
+
*/
|
|
1375
|
+
remove: () => void;
|
|
1376
|
+
}
|
|
1377
|
+
/**
|
|
1378
|
+
* Reusable, importable contract for a single persisted key.
|
|
1379
|
+
*
|
|
1380
|
+
* Descriptors package the key name and its `useMnemonicKey(...)` options into
|
|
1381
|
+
* a stable object that can be defined once at module scope and reused across
|
|
1382
|
+
* components. This helps keep persistence behavior explicit and consistent,
|
|
1383
|
+
* especially when the same key appears in multiple parts of an application.
|
|
1384
|
+
*
|
|
1385
|
+
* @template T - The decoded value type for the key
|
|
1386
|
+
* @template K - The literal key name
|
|
1387
|
+
*
|
|
1388
|
+
* @example
|
|
1389
|
+
* ```typescript
|
|
1390
|
+
* const themeKey = defineMnemonicKey("theme", {
|
|
1391
|
+
* defaultValue: "light" as "light" | "dark",
|
|
1392
|
+
* listenCrossTab: true,
|
|
1393
|
+
* });
|
|
1394
|
+
*
|
|
1395
|
+
* const { value, set } = useMnemonicKey(themeKey);
|
|
1396
|
+
* ```
|
|
1397
|
+
*
|
|
1398
|
+
* @see {@link defineMnemonicKey} - Helper for creating descriptors
|
|
1399
|
+
* @see {@link useMnemonicKey} - Hook that consumes descriptors
|
|
1400
|
+
*/
|
|
1401
|
+
interface MnemonicKeyDescriptor<T, K extends string = string> {
|
|
1402
|
+
/**
|
|
1403
|
+
* Unprefixed storage key name.
|
|
1404
|
+
*/
|
|
1405
|
+
readonly key: K;
|
|
1406
|
+
/**
|
|
1407
|
+
* Canonical options for this key.
|
|
1408
|
+
*/
|
|
1409
|
+
readonly options: UseMnemonicKeyOptions<T>;
|
|
1410
|
+
}
|
|
1411
|
+
/**
|
|
1412
|
+
* Key descriptor options inferred from a typed key schema.
|
|
1413
|
+
*
|
|
1414
|
+
* This mirrors `UseMnemonicKeyOptions<T>` but intentionally omits the `schema`
|
|
1415
|
+
* override so the descriptor stays pinned to the supplied key schema version.
|
|
1416
|
+
*/
|
|
1417
|
+
type SchemaBoundKeyOptions<T> = Omit<UseMnemonicKeyOptions<T>, "schema">;
|
|
1418
|
+
/**
|
|
1419
|
+
* Typed key schema shape inferred from a schema helper or branded JSON Schema.
|
|
1420
|
+
*
|
|
1421
|
+
* Useful when you want a versioned schema object to carry its decoded
|
|
1422
|
+
* TypeScript value through registries, descriptors, and migration helpers.
|
|
1423
|
+
*/
|
|
1424
|
+
type TypedKeySchema<TSchema extends JsonSchema, K extends string = string> = KeySchema<InferJsonSchemaValue<TSchema>, K, TSchema>;
|
|
827
1425
|
/**
|
|
828
1426
|
* Configuration options for the useMnemonicKey hook.
|
|
829
1427
|
*
|
|
@@ -921,6 +1519,42 @@ type UseMnemonicKeyOptions<T> = {
|
|
|
921
1519
|
* ```
|
|
922
1520
|
*/
|
|
923
1521
|
codec?: Codec<T>;
|
|
1522
|
+
/**
|
|
1523
|
+
* Optional read-time reconciliation hook for persisted values.
|
|
1524
|
+
*
|
|
1525
|
+
* Runs after a stored value has been decoded and any read-time migrations
|
|
1526
|
+
* have completed, but before the hook exposes the value to React. This is
|
|
1527
|
+
* useful for selectively enforcing newly shipped defaults or normalizing
|
|
1528
|
+
* legacy persisted values without discarding the whole key.
|
|
1529
|
+
*
|
|
1530
|
+
* If the reconciled value would persist differently from the pre-reconcile
|
|
1531
|
+
* value, the hook rewrites storage once using the normal write path.
|
|
1532
|
+
*
|
|
1533
|
+
* @remarks
|
|
1534
|
+
* Prefer schema migrations for structural changes that must always happen
|
|
1535
|
+
* between explicit versions. Use `reconcile` for conditional, field-level
|
|
1536
|
+
* adjustments that depend on application policy rather than a strict schema
|
|
1537
|
+
* upgrade step.
|
|
1538
|
+
*
|
|
1539
|
+
* See the Schema Migration guide for migration-vs-reconciliation guidance:
|
|
1540
|
+
* https://thirtytwobits.github.io/react-mnemonic/docs/guides/schema-migration
|
|
1541
|
+
*
|
|
1542
|
+
* If `reconcile` throws a `SchemaError`, that error is preserved and passed
|
|
1543
|
+
* to `defaultValue`. Any other thrown error is wrapped as
|
|
1544
|
+
* `SchemaError("RECONCILE_FAILED")`.
|
|
1545
|
+
*
|
|
1546
|
+
* @param value - The decoded persisted value
|
|
1547
|
+
* @param context - Metadata about the stored and latest schema versions
|
|
1548
|
+
*
|
|
1549
|
+
* @example
|
|
1550
|
+
* ```typescript
|
|
1551
|
+
* reconcile: (value, { persistedVersion }) => ({
|
|
1552
|
+
* ...value,
|
|
1553
|
+
* theme: persistedVersion < 2 ? "dark" : value.theme,
|
|
1554
|
+
* })
|
|
1555
|
+
* ```
|
|
1556
|
+
*/
|
|
1557
|
+
reconcile?: (value: T, context: ReconcileContext) => T;
|
|
924
1558
|
/**
|
|
925
1559
|
* Callback invoked once when the hook is first mounted.
|
|
926
1560
|
*
|
|
@@ -979,6 +1613,22 @@ type UseMnemonicKeyOptions<T> = {
|
|
|
979
1613
|
* automatically via React's state management.
|
|
980
1614
|
*/
|
|
981
1615
|
listenCrossTab?: boolean;
|
|
1616
|
+
/**
|
|
1617
|
+
* Server-rendering controls for this key.
|
|
1618
|
+
*
|
|
1619
|
+
* Use this when the server should render a value other than
|
|
1620
|
+
* `defaultValue`, or when persisted storage should only be read after the
|
|
1621
|
+
* component has mounted on the client.
|
|
1622
|
+
*
|
|
1623
|
+
* @example
|
|
1624
|
+
* ```typescript
|
|
1625
|
+
* ssr: {
|
|
1626
|
+
* serverValue: { theme: "system" },
|
|
1627
|
+
* hydration: "client-only",
|
|
1628
|
+
* }
|
|
1629
|
+
* ```
|
|
1630
|
+
*/
|
|
1631
|
+
ssr?: MnemonicKeySSRConfig<T>;
|
|
982
1632
|
/**
|
|
983
1633
|
* Optional schema controls for this key.
|
|
984
1634
|
*
|
|
@@ -1011,6 +1661,23 @@ type UseMnemonicKeyOptions<T> = {
|
|
|
1011
1661
|
version?: number;
|
|
1012
1662
|
};
|
|
1013
1663
|
};
|
|
1664
|
+
/**
|
|
1665
|
+
* Metadata passed to `UseMnemonicKeyOptions.reconcile`.
|
|
1666
|
+
*/
|
|
1667
|
+
type ReconcileContext = {
|
|
1668
|
+
/**
|
|
1669
|
+
* The unprefixed storage key being reconciled.
|
|
1670
|
+
*/
|
|
1671
|
+
key: string;
|
|
1672
|
+
/**
|
|
1673
|
+
* The version found in the persisted envelope that was read.
|
|
1674
|
+
*/
|
|
1675
|
+
persistedVersion: number;
|
|
1676
|
+
/**
|
|
1677
|
+
* The latest registered schema version for the key, when available.
|
|
1678
|
+
*/
|
|
1679
|
+
latestVersion?: number;
|
|
1680
|
+
};
|
|
1014
1681
|
|
|
1015
1682
|
/**
|
|
1016
1683
|
* Props for the MnemonicProvider component.
|
|
@@ -1020,11 +1687,11 @@ type UseMnemonicKeyOptions<T> = {
|
|
|
1020
1687
|
* @see {@link MnemonicProviderOptions} - Configuration options
|
|
1021
1688
|
* @see {@link MnemonicProvider} - Provider component
|
|
1022
1689
|
*/
|
|
1023
|
-
interface MnemonicProviderProps extends MnemonicProviderOptions {
|
|
1690
|
+
interface MnemonicProviderProps extends Readonly<MnemonicProviderOptions> {
|
|
1024
1691
|
/**
|
|
1025
1692
|
* React children to render within the provider.
|
|
1026
1693
|
*/
|
|
1027
|
-
children: ReactNode;
|
|
1694
|
+
readonly children: ReactNode;
|
|
1028
1695
|
}
|
|
1029
1696
|
/**
|
|
1030
1697
|
* React Context provider for namespace-isolated persistent state.
|
|
@@ -1039,10 +1706,11 @@ interface MnemonicProviderProps extends MnemonicProviderOptions {
|
|
|
1039
1706
|
* @param props - Provider configuration and children
|
|
1040
1707
|
* @param props.children - React children to render within the provider
|
|
1041
1708
|
* @param props.namespace - Unique namespace for isolating storage keys
|
|
1042
|
-
* @param props.storage - Optional custom storage backend (defaults to localStorage)
|
|
1709
|
+
* @param props.storage - Optional synchronous custom storage backend (defaults to localStorage)
|
|
1043
1710
|
* @param props.enableDevTools - Enable DevTools debugging interface (defaults to false)
|
|
1044
1711
|
* @param props.schemaMode - Schema enforcement mode (default: "default")
|
|
1045
1712
|
* @param props.schemaRegistry - Optional schema registry for storing schemas and migrations
|
|
1713
|
+
* @param props.ssr - Optional SSR defaults for descendant hooks
|
|
1046
1714
|
*
|
|
1047
1715
|
* @example
|
|
1048
1716
|
* ```tsx
|
|
@@ -1058,7 +1726,7 @@ interface MnemonicProviderProps extends MnemonicProviderOptions {
|
|
|
1058
1726
|
*
|
|
1059
1727
|
* @example
|
|
1060
1728
|
* ```tsx
|
|
1061
|
-
* // With custom storage backend
|
|
1729
|
+
* // With a synchronous custom storage backend
|
|
1062
1730
|
* function App() {
|
|
1063
1731
|
* return (
|
|
1064
1732
|
* <MnemonicProvider
|
|
@@ -1086,9 +1754,10 @@ interface MnemonicProviderProps extends MnemonicProviderOptions {
|
|
|
1086
1754
|
* }
|
|
1087
1755
|
*
|
|
1088
1756
|
* // Then in browser console:
|
|
1089
|
-
* window.__REACT_MNEMONIC_DEVTOOLS__.myApp
|
|
1090
|
-
*
|
|
1091
|
-
*
|
|
1757
|
+
* const dt = window.__REACT_MNEMONIC_DEVTOOLS__.resolve('myApp')
|
|
1758
|
+
* dt?.dump()
|
|
1759
|
+
* dt?.get('user')
|
|
1760
|
+
* dt?.set('theme', 'dark')
|
|
1092
1761
|
* ```
|
|
1093
1762
|
*
|
|
1094
1763
|
* @example
|
|
@@ -1106,17 +1775,34 @@ interface MnemonicProviderProps extends MnemonicProviderOptions {
|
|
|
1106
1775
|
* }
|
|
1107
1776
|
* ```
|
|
1108
1777
|
*
|
|
1778
|
+
* @example
|
|
1779
|
+
* ```tsx
|
|
1780
|
+
* // Delay persisted storage reads until after client mount
|
|
1781
|
+
* function App() {
|
|
1782
|
+
* return (
|
|
1783
|
+
* <MnemonicProvider
|
|
1784
|
+
* namespace="myApp"
|
|
1785
|
+
* ssr={{ hydration: "client-only" }}
|
|
1786
|
+
* >
|
|
1787
|
+
* <MyComponents />
|
|
1788
|
+
* </MnemonicProvider>
|
|
1789
|
+
* );
|
|
1790
|
+
* }
|
|
1791
|
+
* ```
|
|
1792
|
+
*
|
|
1109
1793
|
* @remarks
|
|
1110
1794
|
* - Creates a stable store instance that only recreates when namespace, storage, or enableDevTools change
|
|
1111
1795
|
* - All storage operations are cached in memory for fast reads
|
|
1112
1796
|
* - Storage failures are handled gracefully (logged but not thrown)
|
|
1113
|
-
* -
|
|
1797
|
+
* - `StorageLike` is intentionally synchronous for v1; async persistence must sit behind a sync facade
|
|
1798
|
+
* - In SSR environments, the provider is safe by default: hooks render
|
|
1799
|
+
* `defaultValue` unless configured with an explicit `ssr.serverValue`
|
|
1114
1800
|
* - The store implements React's useSyncExternalStore contract for efficient updates
|
|
1115
1801
|
*
|
|
1116
1802
|
* @see {@link useMnemonicKey} - Hook for using persistent state
|
|
1117
1803
|
* @see {@link MnemonicProviderOptions} - Configuration options
|
|
1118
1804
|
*/
|
|
1119
|
-
declare function MnemonicProvider({ children, namespace, storage, enableDevTools, schemaMode, schemaRegistry, }: MnemonicProviderProps): react_jsx_runtime.JSX.Element;
|
|
1805
|
+
declare function MnemonicProvider({ children, namespace, storage, enableDevTools, schemaMode, schemaRegistry, ssr, }: MnemonicProviderProps): react_jsx_runtime.JSX.Element;
|
|
1120
1806
|
|
|
1121
1807
|
/**
|
|
1122
1808
|
* React hook for persistent, type-safe state management.
|
|
@@ -1128,24 +1814,256 @@ declare function MnemonicProvider({ children, namespace, storage, enableDevTools
|
|
|
1128
1814
|
* Must be used within a `MnemonicProvider`. Uses React's `useSyncExternalStore`
|
|
1129
1815
|
* internally for efficient, tearing-free state synchronization.
|
|
1130
1816
|
*
|
|
1817
|
+
* Read lifecycle, in order:
|
|
1818
|
+
* 1. Load the raw stored envelope for `key`
|
|
1819
|
+
* 2. Decode the payload (codec or schema-managed JSON)
|
|
1820
|
+
* 3. Validate and migrate when schemas are registered
|
|
1821
|
+
* 4. Run `reconcile(...)` if provided
|
|
1822
|
+
* 5. Fall back to `defaultValue` when the key is absent or invalid
|
|
1823
|
+
*
|
|
1824
|
+
* Write semantics:
|
|
1825
|
+
* - `set(...)` persists a new value
|
|
1826
|
+
* - `reset()` persists `defaultValue`
|
|
1827
|
+
* - `remove()` deletes the key entirely so future reads fall back to `defaultValue`
|
|
1828
|
+
*
|
|
1829
|
+
* For guide-level background, see the
|
|
1830
|
+
* [Schema Migration guide](https://thirtytwobits.github.io/react-mnemonic/docs/guides/schema-migration)
|
|
1831
|
+
* and the
|
|
1832
|
+
* [Clearable Persisted Values guide](https://thirtytwobits.github.io/react-mnemonic/docs/guides/clearable-persisted-values).
|
|
1833
|
+
*
|
|
1131
1834
|
* @template T - The TypeScript type of the stored value
|
|
1132
1835
|
*
|
|
1133
|
-
* @
|
|
1134
|
-
* @param options - Configuration options controlling persistence, encoding, and behavior
|
|
1836
|
+
* @returns Persistent state handle with the current value and mutation helpers
|
|
1135
1837
|
*
|
|
1136
|
-
* @
|
|
1838
|
+
* @see {@link UseMnemonicKeyOptions} - Hook configuration and lifecycle details
|
|
1137
1839
|
*
|
|
1138
1840
|
* @throws {Error} If used outside of a MnemonicProvider
|
|
1139
1841
|
*/
|
|
1140
|
-
declare function useMnemonicKey<T>(
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1842
|
+
declare function useMnemonicKey<T, K extends string>(descriptor: MnemonicKeyDescriptor<T, K>): MnemonicKeyState<T>;
|
|
1843
|
+
declare function useMnemonicKey<T>(key: string, options: UseMnemonicKeyOptions<T>): MnemonicKeyState<T>;
|
|
1844
|
+
|
|
1845
|
+
/**
|
|
1846
|
+
* Hook for namespace-scoped recovery actions such as hard reset and selective clear.
|
|
1847
|
+
*
|
|
1848
|
+
* Applications can use this to offer self-service recovery UX for corrupt or
|
|
1849
|
+
* legacy persisted state. The hook operates on the current provider namespace.
|
|
1850
|
+
*
|
|
1851
|
+
* See the
|
|
1852
|
+
* [Reset and Recovery guide](https://thirtytwobits.github.io/react-mnemonic/docs/guides/reset-and-recovery)
|
|
1853
|
+
* for soft-reset and hard-reset patterns.
|
|
1854
|
+
*
|
|
1855
|
+
* @param options - Optional recovery callback for telemetry/auditing
|
|
1856
|
+
* @returns Namespace recovery helpers
|
|
1857
|
+
*
|
|
1858
|
+
* @throws {Error} If used outside of a MnemonicProvider
|
|
1859
|
+
*/
|
|
1860
|
+
declare function useMnemonicRecovery(options?: UseMnemonicRecoveryOptions): MnemonicRecoveryHook;
|
|
1861
|
+
|
|
1862
|
+
/**
|
|
1863
|
+
* Define a reusable, importable contract for a persisted key.
|
|
1864
|
+
*
|
|
1865
|
+
* This packages the storage key and the canonical `useMnemonicKey(...)`
|
|
1866
|
+
* options into a single object that can be shared across components, docs,
|
|
1867
|
+
* and generated code.
|
|
1868
|
+
*
|
|
1869
|
+
* @template K - The literal storage key name
|
|
1870
|
+
* @template T - The decoded value type for the key
|
|
1871
|
+
*
|
|
1872
|
+
* @param key - The unprefixed storage key
|
|
1873
|
+
* @param options - Canonical hook options for the key
|
|
1874
|
+
* @returns A descriptor that can be passed directly to `useMnemonicKey(...)`
|
|
1875
|
+
*
|
|
1876
|
+
* @example
|
|
1877
|
+
* ```typescript
|
|
1878
|
+
* const themeKey = defineMnemonicKey("theme", {
|
|
1879
|
+
* defaultValue: "light" as "light" | "dark",
|
|
1880
|
+
* listenCrossTab: true,
|
|
1881
|
+
* });
|
|
1882
|
+
*
|
|
1883
|
+
* const { value, set } = useMnemonicKey(themeKey);
|
|
1884
|
+
* ```
|
|
1885
|
+
*/
|
|
1886
|
+
declare function defineMnemonicKey<const K extends string, T>(key: K, options: UseMnemonicKeyOptions<T>): MnemonicKeyDescriptor<T, K>;
|
|
1887
|
+
declare function defineMnemonicKey<const K extends string, TSchema extends KeySchema<unknown, K, JsonSchema>>(keySchema: TSchema, options: SchemaBoundKeyOptions<TSchema extends KeySchema<infer TValue, string, JsonSchema> ? TValue : never>): MnemonicKeyDescriptor<TSchema extends KeySchema<infer TValue, string, JsonSchema> ? TValue : never, TSchema["key"]>;
|
|
1888
|
+
|
|
1889
|
+
/**
|
|
1890
|
+
* Create an immutable schema registry for common default/strict-mode setups.
|
|
1891
|
+
*
|
|
1892
|
+
* The helper indexes schemas and migrations up front, validates duplicate and
|
|
1893
|
+
* ambiguous definitions, and returns a {@link SchemaRegistry} ready to pass to
|
|
1894
|
+
* `MnemonicProvider`.
|
|
1895
|
+
*
|
|
1896
|
+
* Most applications should prefer this helper over manually implementing
|
|
1897
|
+
* {@link SchemaRegistry}.
|
|
1898
|
+
*
|
|
1899
|
+
* See the
|
|
1900
|
+
* [Schema Migration guide](https://thirtytwobits.github.io/react-mnemonic/docs/guides/schema-migration)
|
|
1901
|
+
* for end-to-end registry and migration patterns.
|
|
1902
|
+
*
|
|
1903
|
+
* @param options - Initial schema and migration definitions
|
|
1904
|
+
* @returns An indexed immutable schema registry
|
|
1905
|
+
*
|
|
1906
|
+
* @throws {SchemaError} With `SCHEMA_REGISTRATION_CONFLICT` for duplicate
|
|
1907
|
+
* schemas, or `MIGRATION_GRAPH_INVALID` for invalid migration graphs
|
|
1908
|
+
*/
|
|
1909
|
+
declare function createSchemaRegistry(options?: CreateSchemaRegistryOptions): SchemaRegistry;
|
|
1910
|
+
|
|
1911
|
+
/**
|
|
1912
|
+
* Create a versioned key schema that preserves the decoded value type inferred
|
|
1913
|
+
* from a typed schema helper.
|
|
1914
|
+
*/
|
|
1915
|
+
declare function defineKeySchema<const K extends string, TSchema extends JsonSchema>(key: K, version: number, schema: TSchema): KeySchema<InferJsonSchemaValue<TSchema>, K, TSchema>;
|
|
1916
|
+
/**
|
|
1917
|
+
* Create a typed migration rule between two key schema versions.
|
|
1918
|
+
*
|
|
1919
|
+
* The `migrate(...)` callback is inferred from the source and target schemas,
|
|
1920
|
+
* which keeps migration logic aligned with the registered runtime schemas.
|
|
1921
|
+
*/
|
|
1922
|
+
declare function defineMigration<const K extends string, TFrom, TTo>(fromSchema: KeySchema<TFrom, K>, toSchema: KeySchema<TTo, K>, migrate: (value: TFrom) => TTo): MigrationRule<TFrom, TTo, K>;
|
|
1923
|
+
/**
|
|
1924
|
+
* Create a typed write-time normalization rule for a single key schema.
|
|
1925
|
+
*/
|
|
1926
|
+
declare function defineWriteMigration<const K extends string, TValue>(schema: KeySchema<TValue, K>, migrate: (value: TValue) => TValue): MigrationRule<TValue, TValue, K>;
|
|
1927
|
+
|
|
1928
|
+
/**
|
|
1929
|
+
* Adapter functions for structural migration helpers.
|
|
1930
|
+
*
|
|
1931
|
+
* These helpers assume tree-like data, but not a specific node shape. Supply a
|
|
1932
|
+
* `StructuralTreeHelpers<T>` when your nodes use custom field names. When your
|
|
1933
|
+
* nodes already look like `{ id, children }`, the exported helpers work without
|
|
1934
|
+
* any adapter configuration.
|
|
1935
|
+
*
|
|
1936
|
+
* @template T - Tree node type
|
|
1937
|
+
*/
|
|
1938
|
+
interface StructuralTreeHelpers<T> {
|
|
1939
|
+
/**
|
|
1940
|
+
* Returns the stable identifier for a node.
|
|
1941
|
+
*/
|
|
1942
|
+
getId: (node: T) => string;
|
|
1943
|
+
/**
|
|
1944
|
+
* Returns the node's child list, or `undefined` when it has no children.
|
|
1945
|
+
*/
|
|
1946
|
+
getChildren: (node: T) => readonly T[] | undefined;
|
|
1947
|
+
/**
|
|
1948
|
+
* Returns a copy of the node with a new child list.
|
|
1949
|
+
*/
|
|
1950
|
+
withChildren: (node: T, children: T[]) => T;
|
|
1951
|
+
/**
|
|
1952
|
+
* Returns a copy of the node with a new identifier.
|
|
1953
|
+
*/
|
|
1954
|
+
withId: (node: T, id: string) => T;
|
|
1955
|
+
}
|
|
1956
|
+
/**
|
|
1957
|
+
* Default tree node shape supported by the structural migration helpers.
|
|
1958
|
+
*
|
|
1959
|
+
* If your nodes already use `id` and `children`, you can call the helpers
|
|
1960
|
+
* directly without supplying `StructuralTreeHelpers`.
|
|
1961
|
+
*
|
|
1962
|
+
* @template T - Tree node type
|
|
1963
|
+
*/
|
|
1964
|
+
interface StructuralNode<T> {
|
|
1965
|
+
/**
|
|
1966
|
+
* Stable node identifier used for lookup and rename operations.
|
|
1967
|
+
*/
|
|
1968
|
+
id: string;
|
|
1969
|
+
/**
|
|
1970
|
+
* Optional child nodes.
|
|
1971
|
+
*/
|
|
1972
|
+
children?: readonly T[];
|
|
1973
|
+
}
|
|
1974
|
+
/**
|
|
1975
|
+
* Finds the first node with the requested id using depth-first traversal.
|
|
1976
|
+
*
|
|
1977
|
+
* @template T - Tree node type (must extend `{ id: string; children?: readonly T[] }` when `helpers` is omitted)
|
|
1978
|
+
* @param root - Root node to search
|
|
1979
|
+
* @param id - Target node id
|
|
1980
|
+
* @returns The matching node, or `undefined`
|
|
1981
|
+
*/
|
|
1982
|
+
declare function findNodeById<T extends StructuralNode<T>>(root: T, id: string): T | undefined;
|
|
1983
|
+
/**
|
|
1984
|
+
* Finds the first node with the requested id using depth-first traversal.
|
|
1985
|
+
*
|
|
1986
|
+
* @template T - Tree node type
|
|
1987
|
+
* @param root - Root node to search
|
|
1988
|
+
* @param id - Target node id
|
|
1989
|
+
* @param helpers - Adapter for custom node shapes
|
|
1990
|
+
* @returns The matching node, or `undefined`
|
|
1991
|
+
*/
|
|
1992
|
+
declare function findNodeById<T>(root: T, id: string, helpers: StructuralTreeHelpers<T>): T | undefined;
|
|
1993
|
+
/**
|
|
1994
|
+
* Inserts a child under the target parent when none of that parent's existing
|
|
1995
|
+
* direct children share the same id. Returns the original tree when the parent
|
|
1996
|
+
* is missing or the child is already present as a direct child.
|
|
1997
|
+
*
|
|
1998
|
+
* @template T - Tree node type (must extend `{ id: string; children?: readonly T[] }` when `helpers` is omitted)
|
|
1999
|
+
* @param root - Root node to update
|
|
2000
|
+
* @param parentId - Parent node that should receive the child
|
|
2001
|
+
* @param child - Child node to append
|
|
2002
|
+
* @returns Updated tree with the child inserted once
|
|
2003
|
+
*/
|
|
2004
|
+
declare function insertChildIfMissing<T extends StructuralNode<T>>(root: T, parentId: string, child: T): T;
|
|
2005
|
+
/**
|
|
2006
|
+
* Inserts a child under the target parent when no existing child shares the
|
|
2007
|
+
* same id. Returns the original tree when the parent is missing or the child is
|
|
2008
|
+
* already present.
|
|
2009
|
+
*
|
|
2010
|
+
* @template T - Tree node type
|
|
2011
|
+
* @param root - Root node to update
|
|
2012
|
+
* @param parentId - Parent node that should receive the child
|
|
2013
|
+
* @param child - Child node to append
|
|
2014
|
+
* @param helpers - Adapter for custom node shapes
|
|
2015
|
+
* @returns Updated tree with the child inserted once
|
|
2016
|
+
*/
|
|
2017
|
+
declare function insertChildIfMissing<T>(root: T, parentId: string, child: T, helpers: StructuralTreeHelpers<T>): T;
|
|
2018
|
+
/**
|
|
2019
|
+
* Renames every node with the source id while preserving tree structure.
|
|
2020
|
+
* Returns the original tree when the source id is missing or the target id
|
|
2021
|
+
* already exists elsewhere.
|
|
2022
|
+
*
|
|
2023
|
+
* @template T - Tree node type (must extend `{ id: string; children?: readonly T[] }` when `helpers` is omitted)
|
|
2024
|
+
* @param root - Root node to update
|
|
2025
|
+
* @param currentId - Existing id to rename
|
|
2026
|
+
* @param nextId - Replacement id
|
|
2027
|
+
* @returns Updated tree with matching node ids renamed
|
|
2028
|
+
*/
|
|
2029
|
+
declare function renameNode<T extends StructuralNode<T>>(root: T, currentId: string, nextId: string): T;
|
|
2030
|
+
/**
|
|
2031
|
+
* Renames every node with the source id while preserving tree structure.
|
|
2032
|
+
* Returns the original tree when the source id is missing or the target id
|
|
2033
|
+
* already exists elsewhere.
|
|
2034
|
+
*
|
|
2035
|
+
* @template T - Tree node type
|
|
2036
|
+
* @param root - Root node to update
|
|
2037
|
+
* @param currentId - Existing id to rename
|
|
2038
|
+
* @param nextId - Replacement id
|
|
2039
|
+
* @param helpers - Adapter for custom node shapes
|
|
2040
|
+
* @returns Updated tree with matching node ids renamed
|
|
2041
|
+
*/
|
|
2042
|
+
declare function renameNode<T>(root: T, currentId: string, nextId: string, helpers: StructuralTreeHelpers<T>): T;
|
|
2043
|
+
/**
|
|
2044
|
+
* Deduplicates each node's immediate children while preserving the first child
|
|
2045
|
+
* encountered for each key. The helper traverses the full tree and returns the
|
|
2046
|
+
* original root when no duplicates are removed.
|
|
2047
|
+
*
|
|
2048
|
+
* @template T - Tree node type (must extend `{ id: string; children?: readonly T[] }` when `helpers` is omitted)
|
|
2049
|
+
* @template K - Deduplication key type
|
|
2050
|
+
* @param root - Root node to normalize
|
|
2051
|
+
* @param getKey - Function that computes a dedupe key for each child
|
|
2052
|
+
* @returns Updated tree with duplicate siblings removed
|
|
2053
|
+
*/
|
|
2054
|
+
declare function dedupeChildrenBy<T extends StructuralNode<T>, K>(root: T, getKey: (node: T) => K): T;
|
|
2055
|
+
/**
|
|
2056
|
+
* Deduplicates each node's immediate children while preserving the first child
|
|
2057
|
+
* encountered for each key. The helper traverses the full tree and returns the
|
|
2058
|
+
* original root when no duplicates are removed.
|
|
2059
|
+
*
|
|
2060
|
+
* @template T - Tree node type
|
|
2061
|
+
* @template K - Deduplication key type
|
|
2062
|
+
* @param root - Root node to normalize
|
|
2063
|
+
* @param getKey - Function that computes a dedupe key for each child
|
|
2064
|
+
* @param helpers - Adapter for custom node shapes
|
|
2065
|
+
* @returns Updated tree with duplicate siblings removed
|
|
2066
|
+
*/
|
|
2067
|
+
declare function dedupeChildrenBy<T, K>(root: T, getKey: (node: T) => K, helpers: StructuralTreeHelpers<T>): T;
|
|
1150
2068
|
|
|
1151
|
-
export { type Codec, CodecError, type CompiledValidator, JSONCodec, type JsonSchema, type JsonSchemaType, type JsonSchemaValidationError, type KeySchema, type MigrationPath, type MigrationRule, MnemonicProvider, type MnemonicProviderOptions, type MnemonicProviderProps, SchemaError, type SchemaMode, type SchemaRegistry, type StorageLike, type UseMnemonicKeyOptions, compileSchema, createCodec, useMnemonicKey, validateJsonSchema };
|
|
2069
|
+
export { type Codec, CodecError, type CompiledValidator, type CreateSchemaRegistryOptions, type InferJsonSchemaValue, JSONCodec, type JsonSchema, type JsonSchemaType, type JsonSchemaValidationError, type KeySchema, type Listener, type MigrationPath, type MigrationRule, type Mnemonic, type MnemonicDevToolsCapabilities, type MnemonicDevToolsMeta, type MnemonicDevToolsProviderApi, type MnemonicDevToolsProviderDescriptor, type MnemonicDevToolsProviderEntry, type MnemonicDevToolsRegistry, type MnemonicDevToolsWeakRef, type MnemonicHydrationMode, type MnemonicKeyDescriptor, type MnemonicKeySSRConfig, type MnemonicKeyState, MnemonicProvider, type MnemonicProviderOptions, type MnemonicProviderProps, type MnemonicProviderSSRConfig, type MnemonicRecoveryAction, type MnemonicRecoveryEvent, type MnemonicRecoveryHook, type ReconcileContext, type SchemaBoundKeyOptions, SchemaError, type SchemaMode, type SchemaRegistry, type StorageLike, type StructuralNode, type StructuralTreeHelpers, type TypedJsonSchema, type TypedKeySchema, type Unsubscribe, type UseMnemonicKeyOptions, type UseMnemonicRecoveryOptions, compileSchema, createCodec, createSchemaRegistry, dedupeChildrenBy, defineKeySchema, defineMigration, defineMnemonicKey, defineWriteMigration, findNodeById, insertChildIfMissing, mnemonicSchema, renameNode, useMnemonicKey, useMnemonicRecovery, validateJsonSchema };
|