@nkzw/fate 1.4.0 → 1.5.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.
Files changed (189) hide show
  1. package/README.md +326 -0
  2. package/docs/api/classes/FateClient.md +51 -199
  3. package/docs/api/functions/clientRoot.md +1 -1
  4. package/docs/api/functions/createClient.md +1 -1
  5. package/docs/api/functions/createGraphQLTransport.md +1 -1
  6. package/docs/api/functions/createHTTPTransport.md +1 -1
  7. package/docs/api/functions/createTRPCTransport.md +5 -1
  8. package/docs/api/functions/defer.md +1 -1
  9. package/docs/api/functions/getDeferredMetadata.md +1 -1
  10. package/docs/api/functions/getListEntries.md +1 -1
  11. package/docs/api/functions/getSelectionPlan.md +1 -1
  12. package/docs/api/functions/graphqlMutation.md +1 -1
  13. package/docs/api/functions/isDeferred.md +1 -1
  14. package/docs/api/functions/isRecord.md +1 -1
  15. package/docs/api/functions/isViewTag.md +1 -1
  16. package/docs/api/functions/liveConnectionTopic.md +1 -1
  17. package/docs/api/functions/liveEntityTopic.md +1 -1
  18. package/docs/api/functions/liveGlobalConnectionTopic.md +1 -1
  19. package/docs/api/functions/mutation.md +1 -1
  20. package/docs/api/functions/toEntityId.md +1 -1
  21. package/docs/api/functions/view.md +1 -1
  22. package/docs/api/index.md +4 -1
  23. package/docs/api/interfaces/FateThenable.md +3 -3
  24. package/docs/api/interfaces/Persistence.md +23 -0
  25. package/docs/api/interfaces/PersistenceSession.md +109 -0
  26. package/docs/api/interfaces/Transport.md +46 -7
  27. package/docs/api/server/classes/FateRequestError.md +5 -5
  28. package/docs/api/server/drizzle/functions/createDrizzleFate.md +1 -1
  29. package/docs/api/server/drizzle/functions/createDrizzleSourceAdapter.md +1 -1
  30. package/docs/api/server/drizzle/functions/createDrizzleSourceRegistry.md +1 -1
  31. package/docs/api/server/drizzle/type-aliases/DrizzleManyToManyConfig.md +1 -1
  32. package/docs/api/server/drizzle/type-aliases/DrizzleManyToManyInput.md +1 -1
  33. package/docs/api/server/drizzle/type-aliases/DrizzleQueryExtra.md +3 -3
  34. package/docs/api/server/drizzle/type-aliases/DrizzleSourceAdapter.md +9 -9
  35. package/docs/api/server/drizzle/type-aliases/DrizzleViewConfig.md +1 -1
  36. package/docs/api/server/functions/bindSourceProcedures.md +1 -1
  37. package/docs/api/server/functions/computed.md +1 -1
  38. package/docs/api/server/functions/count.md +1 -1
  39. package/docs/api/server/functions/createFateFetchHandler.md +1 -1
  40. package/docs/api/server/functions/createFateServer.md +1 -1
  41. package/docs/api/server/functions/createHonoFateHandler.md +1 -1
  42. package/docs/api/server/functions/createLiveEventBus.md +1 -1
  43. package/docs/api/server/functions/createNestedSourcePlan.md +1 -1
  44. package/docs/api/server/functions/createResolver.md +1 -1
  45. package/docs/api/server/functions/createSourcePlan.md +1 -1
  46. package/docs/api/server/functions/createSourceProcedures.md +1 -1
  47. package/docs/api/server/functions/dataView.md +1 -1
  48. package/docs/api/server/functions/field.md +1 -1
  49. package/docs/api/server/functions/getNestedSelection.md +1 -1
  50. package/docs/api/server/functions/getScopedArgs.md +1 -1
  51. package/docs/api/server/functions/hasNestedSelection.md +1 -1
  52. package/docs/api/server/functions/list.md +1 -1
  53. package/docs/api/server/functions/refetchSourceById.md +1 -1
  54. package/docs/api/server/functions/resolveSourceById.md +1 -1
  55. package/docs/api/server/functions/resolveSourceByIds.md +1 -1
  56. package/docs/api/server/functions/resolveSourceConnection.md +1 -1
  57. package/docs/api/server/functions/resolver.md +1 -1
  58. package/docs/api/server/functions/toPrismaSelect.md +1 -1
  59. package/docs/api/server/functions/withConnection.md +1 -1
  60. package/docs/api/server/prisma/functions/createPrismaFate.md +1 -1
  61. package/docs/api/server/prisma/functions/createPrismaSourceAdapter.md +1 -1
  62. package/docs/api/server/prisma/functions/createPrismaSourceRegistry.md +1 -1
  63. package/docs/api/server/prisma/functions/prismaConnectionArgs.md +1 -1
  64. package/docs/api/server/prisma/type-aliases/PrismaDelegate.md +4 -4
  65. package/docs/api/server/prisma/type-aliases/PrismaQueryExtra.md +1 -1
  66. package/docs/api/server/prisma/type-aliases/PrismaSourceAdapter.md +9 -9
  67. package/docs/api/server/prisma/type-aliases/PrismaViewConfig.md +1 -1
  68. package/docs/api/server/type-aliases/ComputedField.md +5 -5
  69. package/docs/api/server/type-aliases/ComputedSelection.md +1 -1
  70. package/docs/api/server/type-aliases/ConnectionItem.md +3 -3
  71. package/docs/api/server/type-aliases/ConnectionPagination.md +5 -5
  72. package/docs/api/server/type-aliases/ConnectionResult.md +3 -3
  73. package/docs/api/server/type-aliases/CountSelection.md +4 -4
  74. package/docs/api/server/type-aliases/CountWhere.md +1 -1
  75. package/docs/api/server/type-aliases/DataViewListOptions.md +2 -2
  76. package/docs/api/server/type-aliases/DataViewOrderBy.md +1 -1
  77. package/docs/api/server/type-aliases/DataViewOrderDirection.md +1 -1
  78. package/docs/api/server/type-aliases/DataViewResult.md +1 -1
  79. package/docs/api/server/type-aliases/Entity.md +1 -1
  80. package/docs/api/server/type-aliases/FateServer.md +5 -5
  81. package/docs/api/server/type-aliases/FateServerManifest.md +1 -1
  82. package/docs/api/server/type-aliases/FieldSelection.md +3 -3
  83. package/docs/api/server/type-aliases/LiveConnectionEventType.md +1 -1
  84. package/docs/api/server/type-aliases/LiveConnectionSourceEvent.md +1 -1
  85. package/docs/api/server/type-aliases/LiveEventBus.md +1 -1
  86. package/docs/api/server/type-aliases/LiveEventType.md +1 -1
  87. package/docs/api/server/type-aliases/LiveSourceEvent.md +1 -1
  88. package/docs/api/server/type-aliases/NativeFateAPI.md +4 -4
  89. package/docs/api/server/type-aliases/OrderDirection.md +1 -1
  90. package/docs/api/server/type-aliases/SourceConfig.md +6 -6
  91. package/docs/api/server/type-aliases/SourceDefinition.md +6 -6
  92. package/docs/api/server/type-aliases/SourceOrder.md +1 -1
  93. package/docs/api/server/type-aliases/SourceOrderField.md +3 -3
  94. package/docs/api/server/type-aliases/SourcePlan.md +1 -1
  95. package/docs/api/server/type-aliases/SourcePlanNode.md +1 -1
  96. package/docs/api/server/type-aliases/SourceRegistry.md +1 -1
  97. package/docs/api/server/type-aliases/SourceRelation.md +1 -1
  98. package/docs/api/server/type-aliases/SourceRelationConfig.md +1 -1
  99. package/docs/api/server/variables/byIdInput.md +1 -1
  100. package/docs/api/server/variables/connectionArgs.md +1 -1
  101. package/docs/api/type-aliases/ConnectionMetadata.md +1 -1
  102. package/docs/api/type-aliases/ConnectionRef.md +1 -1
  103. package/docs/api/type-aliases/Deferred.md +1 -1
  104. package/docs/api/type-aliases/DeferredMetadata.md +1 -1
  105. package/docs/api/type-aliases/DeferredSelection.md +1 -1
  106. package/docs/api/type-aliases/DeferredSnapshot.md +1 -1
  107. package/docs/api/type-aliases/Entity.md +2 -2
  108. package/docs/api/type-aliases/EntityId.md +1 -1
  109. package/docs/api/type-aliases/FateDehydratedState.md +1 -1
  110. package/docs/api/type-aliases/FateLiveConnectionEvent.md +1 -1
  111. package/docs/api/type-aliases/FateLiveEvent.md +1 -1
  112. package/docs/api/type-aliases/FateMutations.md +1 -1
  113. package/docs/api/type-aliases/FateOperation.md +2 -2
  114. package/docs/api/type-aliases/FateProtocolRequest.md +1 -1
  115. package/docs/api/type-aliases/FateProtocolResponse.md +1 -1
  116. package/docs/api/type-aliases/FateRecord.md +1 -1
  117. package/docs/api/type-aliases/FateRoots.md +1 -1
  118. package/docs/api/type-aliases/GraphQLMutationDefinition.md +1 -1
  119. package/docs/api/type-aliases/GraphQLMutationInput.md +1 -1
  120. package/docs/api/type-aliases/GraphQLMutationMap.md +1 -1
  121. package/docs/api/type-aliases/GraphQLMutationOutput.md +1 -1
  122. package/docs/api/type-aliases/GraphQLTransportOptions.md +19 -11
  123. package/docs/api/type-aliases/HydrateOptions.md +1 -1
  124. package/docs/api/type-aliases/HydrationLimits.md +1 -1
  125. package/docs/api/type-aliases/InferFateAPI.md +1 -1
  126. package/docs/api/type-aliases/List.md +1 -1
  127. package/docs/api/type-aliases/ListEntry.md +1 -1
  128. package/docs/api/type-aliases/ListItem.md +1 -1
  129. package/docs/api/type-aliases/Mask.md +1 -1
  130. package/docs/api/type-aliases/MutationDefinition.md +1 -1
  131. package/docs/api/type-aliases/MutationEntity.md +1 -1
  132. package/docs/api/type-aliases/MutationIdentifier.md +1 -1
  133. package/docs/api/type-aliases/MutationIdentity.md +7 -0
  134. package/docs/api/type-aliases/MutationInput.md +1 -1
  135. package/docs/api/type-aliases/MutationResult.md +1 -1
  136. package/docs/api/type-aliases/NodesItem.md +1 -1
  137. package/docs/api/type-aliases/Pagination.md +5 -5
  138. package/docs/api/type-aliases/PersistenceSnapshot.md +5 -0
  139. package/docs/api/type-aliases/Request.md +1 -1
  140. package/docs/api/type-aliases/RequestMode.md +1 -1
  141. package/docs/api/type-aliases/RequestOptions.md +2 -2
  142. package/docs/api/type-aliases/RequestResult.md +1 -1
  143. package/docs/api/type-aliases/Selection.md +1 -1
  144. package/docs/api/type-aliases/TypeConfig.md +4 -4
  145. package/docs/api/type-aliases/View.md +1 -1
  146. package/docs/api/type-aliases/ViewData.md +1 -1
  147. package/docs/api/type-aliases/ViewEntity.md +1 -1
  148. package/docs/api/type-aliases/ViewEntityName.md +1 -1
  149. package/docs/api/type-aliases/ViewRef.md +1 -1
  150. package/docs/api/type-aliases/ViewSelection.md +1 -1
  151. package/docs/api/type-aliases/ViewSnapshot.md +1 -1
  152. package/docs/api/type-aliases/ViewTag.md +1 -1
  153. package/docs/api/variables/ConnectionTag.md +1 -1
  154. package/docs/api/variables/DeferTag.md +1 -1
  155. package/docs/api/variables/DeferredTag.md +1 -1
  156. package/docs/guide/getting-started.md +2 -0
  157. package/docs/guide/persistence.md +323 -0
  158. package/lib/{liveTopics-uVP0LG-Q.mjs → args-CRLIRl_v.mjs} +1 -59
  159. package/lib/{executor-BRudKWDY.d.mts → executor-DoiTBiVv.d.mts} +1 -1
  160. package/lib/{graphqlTransport-BDR1pnUQ.d.mts → graphqlTransport-DGLYyRxL.d.mts} +3 -2
  161. package/lib/{graphqlTransport-DSBVS2Fq.mjs → graphqlTransport-DmheG3AO.mjs} +3 -2
  162. package/lib/graphqlTransport.d.mts +1 -1
  163. package/lib/graphqlTransport.mjs +1 -1
  164. package/lib/hydration-DPZRJgnu.mjs +273 -0
  165. package/lib/idempotency-types-CqA-BFpn.d.mts +15 -0
  166. package/lib/idempotency.d.mts +26 -0
  167. package/lib/idempotency.mjs +34 -0
  168. package/lib/index.d.mts +5 -5
  169. package/lib/index.mjs +265 -1567
  170. package/lib/{list-Bb1SeABn.d.mts → list-BRT1VtiT.d.mts} +1 -1
  171. package/lib/list.d.mts +1 -1
  172. package/lib/liveTopics-DuFkDZQm.mjs +17 -0
  173. package/lib/persistence.d.mts +38 -0
  174. package/lib/persistence.mjs +1529 -0
  175. package/lib/protocol-DS5sf6sd.mjs +44 -0
  176. package/lib/{record-BTUXkHQU.d.mts → record-DITM4zb_.d.mts} +8 -4
  177. package/lib/server/drizzle.d.mts +2 -2
  178. package/lib/server/drizzle.mjs +1 -1
  179. package/lib/server/prisma.d.mts +2 -2
  180. package/lib/server/prisma.mjs +1 -6
  181. package/lib/server.d.mts +3 -3
  182. package/lib/server.mjs +19 -7
  183. package/lib/sortObjectKeys-yhuitEQZ.mjs +9 -0
  184. package/lib/{sourceRouter-DSaADXSf.mjs → sourceRouter-51POBlEE.mjs} +9 -6
  185. package/lib/store-CeatPJeK.mjs +1350 -0
  186. package/lib/{transport-Bo1Jgo9R.d.mts → transport-DqjhjLfC.d.mts} +594 -412
  187. package/lib/vite.mjs +18 -10
  188. package/package.json +12 -2
  189. package/docs/api/type-aliases/Snapshot.md +0 -7
@@ -555,368 +555,6 @@ interface Router<TRoot extends AnyRootTypes, TRecord extends RouterRecord> {
555
555
  }
556
556
  type AnyRouter = Router<any, any>;
557
557
  //#endregion
558
- //#region src/cache.d.ts
559
- declare class ViewDataCache {
560
- private readonly isEnabled;
561
- constructor(isEnabled?: () => boolean);
562
- private cache;
563
- private rootDependencies;
564
- private dependencyIndex;
565
- clear(): void;
566
- get<T extends Entity, S extends Selection<T>, V extends View<T, S>>(entityId: EntityId, view: V, ref: ViewRef<T['__typename']>): FateThenable<ViewSnapshot<T, S>> | null;
567
- set<T extends Entity, S extends Selection<T>, V extends View<T, S>>(entityId: EntityId, view: V, ref: ViewRef<T['__typename']>, thenable: FateThenable<ViewSnapshot<T, S>>, dependencies: ReadonlySet<EntityId>): void;
568
- invalidate(entityId: EntityId): void;
569
- private invalidateDependents;
570
- private delete;
571
- }
572
- //#endregion
573
- //#region src/store.d.ts
574
- type List = Readonly<{
575
- backwardPageLimit?: number;
576
- cursors?: ReadonlyArray<string | undefined>;
577
- forwardPageLimit?: number;
578
- ids: ReadonlyArray<EntityId>;
579
- liveAfterIds?: ReadonlyArray<EntityId>;
580
- liveBeforeIds?: ReadonlyArray<EntityId>;
581
- pagination?: Pagination;
582
- pendingAfterIds?: ReadonlyArray<EntityId>;
583
- pendingBeforeIds?: ReadonlyArray<EntityId>;
584
- }>;
585
- type StoreHydrationState = Readonly<{
586
- coverage: ReadonlyArray<readonly [EntityId, ReadonlyArray<string>]>;
587
- lists: ReadonlyArray<readonly [string, List]>;
588
- records: ReadonlyArray<readonly [EntityId, AnyRecord]>;
589
- }>;
590
- declare class Store {
591
- private readonly onRebase?;
592
- private coverage;
593
- private listKeysByOwnerField;
594
- private listKeysByReferencedEntity;
595
- private lists;
596
- private recordReferenceFields;
597
- private recordReferencesByTarget;
598
- private records;
599
- private subscriptions;
600
- private listSubscriptions;
601
- private readonly optimisticLayers;
602
- private readonly optimisticBase;
603
- private recordingLayer;
604
- private rebase;
605
- constructor(onRebase?: ((ids: ReadonlySet<EntityId>) => void) | undefined);
606
- get hasOptimisticUpdates(): boolean;
607
- get isRebasing(): boolean;
608
- /** Apply a synchronous cache update beneath the pending optimistic layers. */
609
- update<T>(apply: () => T): T;
610
- private getRebaseChanges;
611
- /** Returns an idempotent settlement function; omit its update to roll back. */
612
- optimisticUpdate(apply: () => void): (commit?: () => void) => void;
613
- private getPendingOverlap;
614
- private captureRecord;
615
- private captureList;
616
- dehydrate(): StoreHydrationState;
617
- hydrate(state: StoreHydrationState, mode: 'preserve-existing' | 'replace', options?: {
618
- deferNotifications?: boolean;
619
- }): () => void;
620
- private rebuildIndexes;
621
- read(id: EntityId): AnyRecord | undefined;
622
- merge(id: EntityId, partial: AnyRecord, paths: Iterable<string>): void;
623
- private mergeInternal;
624
- deleteRecord(id: EntityId): void;
625
- missingForSelection(id: EntityId, paths: Iterable<string>): Set<string>;
626
- subscribe(id: EntityId, selection: ReadonlySet<string> | null, fn: () => void): () => void;
627
- subscribe(id: EntityId, fn: () => void): () => void;
628
- private notify;
629
- private notifyListSubscribers;
630
- getList(key: string): ReadonlyArray<EntityId> | undefined;
631
- getListState(key: string): List | undefined;
632
- getListsForField(ownerId: EntityId, field: string): Array<readonly [string, List]>;
633
- setList(key: string, state: List): void;
634
- replaceListEntityId(previousId: EntityId, nextId: EntityId): void;
635
- restoreList(key: string, list?: List): void;
636
- collectGarbage(markedRecords: ReadonlySet<EntityId>, markedLists: ReadonlySet<string>, options?: {
637
- onRecordDeleted?: (id: EntityId) => void;
638
- }): {
639
- lists: Set<string>;
640
- records: Set<EntityId>;
641
- };
642
- private deleteList;
643
- subscribeList(key: string, fn: () => void): () => void;
644
- removeReferencesTo(targetId: EntityId, viewDataCache: ViewDataCache): void;
645
- private restore;
646
- private addListIndexes;
647
- private removeListIndexes;
648
- private getListReferencedEntityIds;
649
- private getRecordFieldReferences;
650
- private addRecordFieldReferenceIndex;
651
- private removeRecordFieldReferenceIndex;
652
- private addRecordReferenceIndexes;
653
- private removeRecordReferenceIndexes;
654
- private updateRecordReferenceIndexes;
655
- }
656
- //#endregion
657
- //#region src/hydration.d.ts
658
- /** JSON-safe opaque value contained in a dehydrated fate snapshot. */
659
- type FateSerializedValue = null | boolean | number | string | ReadonlyArray<FateSerializedValue> | Readonly<{
660
- [key: string]: FateSerializedValue;
661
- }>;
662
- /** Versioned, JSON-safe durable cache snapshot produced by `FateClient.dehydrate()`. */
663
- declare const hydrationScopeBrand: unique symbol;
664
- type FateDehydratedState<Scope extends string = string> = Readonly<{
665
- data: FateSerializedValue;
666
- readonly [hydrationScopeBrand]?: Scope;
667
- scope: Scope;
668
- version: 1;
669
- }>;
670
- /** Controls how `FateClient.hydrate()` reconciles a snapshot with browser cache state. */
671
- type HydrateOptions = Readonly<{
672
- /**
673
- * `preserve-existing` keeps browser values and list windows when conflicts
674
- * occur. `replace` treats the snapshot as authoritative.
675
- *
676
- * @defaultValue 'preserve-existing'
677
- */
678
- merge?: 'preserve-existing' | 'replace';
679
- }>;
680
- /** Resource limits applied while encoding and decoding hydration snapshots. */
681
- type HydrationLimits = Readonly<{
682
- /** Maximum number of entries in any encoded array or object. */
683
- maxCollectionLength: number;
684
- /** Maximum number of encoded values in a hydration snapshot. */
685
- maxNodes: number;
686
- /** Maximum length of an encoded string, object key, or bigint payload. */
687
- maxStringLength: number;
688
- }>;
689
- //#endregion
690
- //#region src/selection.d.ts
691
- /**
692
- * Representation of a composed selection including hashed args and the
693
- * flat set of field paths to read or fetch.
694
- */
695
- type SelectionPlan = {
696
- readonly args: Map<string, Readonly<{
697
- hash: string;
698
- ignoreKeys?: ReadonlySet<string>;
699
- value: AnyRecord;
700
- }>>;
701
- readonly live: Map<string, ConnectionLivePolicy>;
702
- readonly paths: Set<string>;
703
- };
704
- /**
705
- * Flattens a view into a `SelectionPlan`, expanding composed views and
706
- * partitioning nested args so the client can fetch exactly what is declared.
707
- */
708
- declare const getSelectionPlan: <T extends Entity, S extends Selection<T>, V extends View<T, S>>(viewComposition: V, ref: ViewRef<T['__typename']> | null) => SelectionPlan;
709
- //#endregion
710
- //#region src/operation-lifetime.d.ts
711
- type RetainHandle = Readonly<{
712
- dispose(): void;
713
- }>;
714
- //#endregion
715
- //#region src/client.d.ts
716
- /**
717
- * Strategy used when resolving a request.
718
- */
719
- type RequestMode =
720
- /** (default) Use cached data if present, otherwise fetch. */
721
- 'cache-first' |
722
- /** Show cached data immediately and refresh in the background. */
723
- 'stale-while-revalidate' |
724
- /** Always fetch from the network and ignore cached entries. */
725
- 'network-only';
726
- /**
727
- * Request options that affect how requests are fetched and retained.
728
- */
729
- type RequestOptions = Readonly<{
730
- mode?: RequestMode;
731
- }>;
732
- type DeferredSnapshot<T> = Readonly<{
733
- coverage: ReadonlyArray<readonly [id: EntityId, paths: ReadonlySet<string>]>;
734
- data: T;
735
- }>;
736
- type FateClientOptions<Roots extends FateRoots, Mutations extends FateMutations, HydrationScope extends string> = {
737
- /**
738
- * Number of recently released requests to keep retained before their records
739
- * and lists are eligible for garbage collection.
740
- *
741
- * @defaultValue 10
742
- */
743
- gcReleaseBufferSize?: number;
744
- /**
745
- * Bounds hydration snapshot encoding and decoding work.
746
- */
747
- hydrationLimits?: Partial<HydrationLimits>;
748
- /**
749
- * Identifies snapshots compatible with this client. Change this value when
750
- * deploying an incompatible cache schema or separating cache namespaces.
751
- */
752
- hydrationScope?: HydrationScope;
753
- mutations?: Mutations;
754
- onLiveError?: (error: unknown) => void;
755
- roots: Roots;
756
- transport: Transport<MutationMapFromDefinitions<Mutations>>;
757
- types: ReadonlyArray<Omit<TypeConfig, 'getId'> & Partial<{
758
- getId: TypeConfig['getId'];
759
- }>>;
760
- };
761
- /**
762
- * Core client that normalizes records, manages the view cache, and coordinates
763
- * data fetching.
764
- */
765
- declare class FateClient<Roots extends FateRoots, Mutations extends FateMutations, HydrationScope extends string = string> {
766
- private readonly mutationMap;
767
- private readonly parentLists;
768
- private readonly rootLists;
769
- private readonly pending;
770
- private readonly pendingDeferred;
771
- private readonly pendingOptimisticMutations;
772
- private readonly optimisticEntityResolutions;
773
- private readonly onLiveError;
774
- private readonly liveSubscriptions;
775
- private readonly liveConnectionInvalidations;
776
- private readonly stableRefs;
777
- private readonly requests;
778
- private readonly rootRequests;
779
- private readonly stalledRequests;
780
- private gcPending;
781
- private gcScheduled;
782
- private pendingNetworkRequests;
783
- readonly store: Store;
784
- private readonly operationLifetime;
785
- private readonly hydrationLimits;
786
- private readonly hydrationScope;
787
- private readonly types;
788
- private readonly transport;
789
- private readonly viewDataCache;
790
- private liveConnectionInvalidationToken;
791
- readonly actions: MutationActionsFor<Mutations>;
792
- readonly mutations: MutationFunctionsFor<Mutations>;
793
- readonly roots: Roots;
794
- constructor(options: FateClientOptions<Roots, Mutations, HydrationScope>);
795
- private initializeParentLists;
796
- /**
797
- * Exports the durable normalized cache as an opaque JSON-safe value for SSR
798
- * transfer or persistence. Runtime requests, subscriptions, retainers, and
799
- * optimistic state are intentionally excluded.
800
- */
801
- dehydrate(): FateDehydratedState<HydrationScope>;
802
- /**
803
- * Restores a durable normalized cache snapshot without restoring runtime
804
- * request handles, retainers, subscriptions, or optimistic update state.
805
- * Hydrate before rendering SSR content. Replaying the same snapshot is safe.
806
- */
807
- hydrate(state: FateDehydratedState<HydrationScope>, options?: HydrateOptions): void;
808
- private registerRootList;
809
- private applyListInsert;
810
- private insertIntoRootLists;
811
- getTypeConfig(type: string): TypeConfig;
812
- private getListNodeType;
813
- executeMutation(key: string, input: unknown, select: Set<string>, options?: {
814
- args?: AnyRecord;
815
- plan?: SelectionPlan;
816
- }): Promise<unknown>;
817
- write(type: string, data: AnyRecord, select: ReadonlySet<string>, plan?: SelectionPlan, insert?: InsertPosition): string;
818
- deleteRecord(type: string, id: string | number): void;
819
- private stableRefWithViewNames;
820
- ref<T extends Entity>(type: T['__typename'], id: string | number, view: View<T, Selection<T>>): ViewRef<T['__typename']>;
821
- rootListRef(entityId: EntityId, rootView: View<any, any>): Readonly<{
822
- __typename: string;
823
- id: string | number;
824
- [ViewsTag]: Set<string>;
825
- }>;
826
- readView<T extends Entity, S extends Selection<T>, V extends View<T, S>>(view: V, ref: ViewRef<T['__typename']>): FateThenable<ViewSnapshot<T, S>>;
827
- readDeferred<T>(deferred: Deferred<T>): PromiseLike<DeferredSnapshot<T>>;
828
- assertLiveViewSupport(): void;
829
- assertLiveConnectionSupport(): void;
830
- subscribeLiveView<T extends Entity, S extends Selection<T>, V extends View<T, S>>(view: V, ref: ViewRef<T['__typename']>): () => void;
831
- subscribeLiveListView<V extends View<any, any>>(view: V, connection: ConnectionMetadata): () => void;
832
- private applyLiveConnectionEvent;
833
- private invalidateLiveConnection;
834
- private deleteConnectionEdge;
835
- private insertConnectionEdge;
836
- private syncNestedConnectionOwnerField;
837
- private getConnectionInsertIndex;
838
- private removeEntityFromListState;
839
- private mergeListState;
840
- registerPendingOptimisticMutation(entityId: EntityId, promise: Promise<unknown>): void;
841
- resolveOptimisticEntity(optimisticEntityId: EntityId, resolvedEntityId: EntityId): void;
842
- private getPendingOptimisticMutations;
843
- loadConnection<V extends View<any, any>>(view: V, connection: ConnectionMetadata, args: Record<string, unknown>, options?: {
844
- direction?: 'forward' | 'backward';
845
- }): Promise<Readonly<{
846
- backwardPageLimit?: number;
847
- cursors?: ReadonlyArray<string | undefined>;
848
- forwardPageLimit?: number;
849
- ids: ReadonlyArray<EntityId>;
850
- liveAfterIds?: ReadonlyArray<EntityId>;
851
- liveBeforeIds?: ReadonlyArray<EntityId>;
852
- pagination?: Pagination;
853
- pendingAfterIds?: ReadonlyArray<EntityId>;
854
- pendingBeforeIds?: ReadonlyArray<EntityId>;
855
- }> | undefined>;
856
- private loadConnectionInternal;
857
- request<R extends Request$1>(request: R, options?: RequestOptions): Promise<RequestResult<Roots, R>>;
858
- requestForRender<R extends Request$1>(request: R, options?: RequestOptions): Promise<RequestResult<Roots, R>>;
859
- prepareRequestForRender<R extends Request$1>(request: R, options: RequestOptions | undefined): Readonly<{
860
- promise: Promise<RequestResult<Roots, R>>;
861
- requestKey: string;
862
- }>;
863
- private requestWithDescriptor;
864
- releaseRequest(request: Request$1, mode: RequestMode): void;
865
- releaseRequestKey(requestKey: string, mode: RequestMode): void;
866
- retainRequestKey(requestKey: string, mode?: RequestMode): RetainHandle;
867
- /**
868
- * Keeps the records and lists reachable from a request alive until the
869
- * returned handle is disposed.
870
- *
871
- * `useRequest` calls this automatically while the component is mounted.
872
- * Use it directly for non-React request lifetimes, tests, or preloaded data
873
- * that must survive manual garbage collection.
874
- */
875
- retain(request: Request$1): RetainHandle;
876
- private scheduleGarbageCollection;
877
- /**
878
- * Removes records and lists that are not reachable from retained requests or
879
- * the release buffer.
880
- *
881
- * Garbage collection is scheduled automatically when retained requests are
882
- * released. Calling this method manually is mainly useful in tests and custom
883
- * memory-management flows.
884
- */
885
- gc(): void;
886
- private executeRequestHandle;
887
- private markRecordReferences;
888
- private hasActiveOptimisticUpdates;
889
- private hasPendingRequests;
890
- trackPendingRequest<T>(request: () => Promise<T>): Promise<T>;
891
- private runPendingGarbageCollection;
892
- private handleStoreAndNetworkRequest;
893
- private getRootType;
894
- private createRequestDescriptor;
895
- getRequestKey(request: Request$1): string;
896
- private hasRootListData;
897
- private executeRequest;
898
- private hasRequestData;
899
- getRequestResult<R extends Request$1>(request: R): RequestResult<Roots, R>;
900
- private getRequestResultFromDescriptor;
901
- private fetchByIdAndNormalize;
902
- private fetchQueryAndNormalize;
903
- private fetchListAndNormalize;
904
- private writeEntity;
905
- private linkParentLists;
906
- private readViewSelection;
907
- private clearStalledRequestsForEntity;
908
- private pendingPrefix;
909
- private pendingKey;
910
- private deferredPendingKey;
911
- private deferredSelectionSignature;
912
- private hasMissingDeferredList;
913
- private liveSubscriptionKey;
914
- private liveConnectionSubscriptionKey;
915
- private releaseLiveSubscription;
916
- private reportLiveError;
917
- }
918
- declare function createClient<T extends [FateRoots, FateMutations] = [Record<never, RootDefinition<any, any>>, Record<never, MutationDefinition<any, any, any>>], HydrationScope extends string = string>(options: FateClientOptions<T[0], T[1], HydrationScope>): FateClient<T[0], T[1], HydrationScope>;
919
- //#endregion
920
558
  //#region src/mutation.d.ts
921
559
  /**
922
560
  * Defines a mutation for a given entity type, preserving the input and output
@@ -939,6 +577,8 @@ type MutationOptions<Identifier extends MutationIdentifier<any, any, any>> = {
939
577
  insert?: InsertPosition;
940
578
  /** Optional optimistic update to apply immediately. */
941
579
  optimistic?: OptimisticUpdate<MutationResult<Identifier>>;
580
+ /** Skip durable delivery for this call, even when persistence is configured. */
581
+ persist?: boolean;
942
582
  /** Optional view specifying which fields to select from the server. */
943
583
  view?: View<MutationEntity<Identifier>, Selection<MutationEntity<Identifier>>>;
944
584
  };
@@ -980,6 +620,17 @@ type FateMutations = Record<string, MutationDefinition<any, any, any>>;
980
620
  type MutationTreeFromRecord<Mutations extends FateMutations, ValueMap extends Record<string, unknown>> = [keyof Mutations] extends [never] ? object : UnionToIntersection<{ [K in keyof Mutations & string]: NestedValue<K, ValueMap[K]>; }[keyof Mutations & string]>;
981
621
  type MutationFunctionsFor<Mutations extends FateMutations> = MutationTreeFromRecord<Mutations, { [K in keyof Mutations & string]: MutationFunction<MutationIdentifierFor<K, Mutations[K]>>; }>;
982
622
  type MutationActionsFor<Mutations extends FateMutations> = MutationTreeFromRecord<Mutations, { [K in keyof Mutations & string]: MutationAction<MutationIdentifierFor<K, Mutations[K]>>; }>;
623
+ /** @internal Serializable input to a live or restored mutation. */
624
+ type MutationCommand = {
625
+ args?: AnyRecord;
626
+ delete?: boolean;
627
+ entity: string;
628
+ input: AnyRecord;
629
+ insert: InsertPosition;
630
+ key: string;
631
+ optimistic?: AnyRecord;
632
+ plan?: SelectionPlan;
633
+ };
983
634
  //#endregion
984
635
  //#region src/types.d.ts
985
636
  /** Canonical runtime name for an entity type as returned by the server. */
@@ -1261,59 +912,584 @@ type ListResult<Item extends AnyRequestItem, Type extends TypeName, Result> = It
1261
912
  pagination?: Pagination;
1262
913
  }> : Array<ViewRef<Type>> : never;
1263
914
  /**
1264
- * The result of a `FateClient.request` and `useRequest` call, mapping each
1265
- * request key to its corresponding result.
915
+ * The result of a `FateClient.request` and `useRequest` call, mapping each
916
+ * request key to its corresponding result.
917
+ */
918
+ type RequestResult<R extends FateRoots, Q extends AnyRequest> = { [K in keyof Q]: K extends keyof R ? ListResult<Q[K], RootType<R[K]>, RootResult<R[K]>> : never; };
919
+ /** Brand used on root definitions to mark their identity in the d.ts output. */
920
+ declare const RootKind = "__fate__root";
921
+ /** Brand used on mutation definitions to mark their identity in the d.ts output. */
922
+ declare const MutationKind = "__fate__mutation";
923
+ /** Metadata describing a root query for a particular entity and result shape. */
924
+ type RootDefinition<Type extends TypeName, Result> = Readonly<{
925
+ [RootKind]: true;
926
+ type: Type;
927
+ }> & __RootResultAnchor<Result> & __RootTypeAnchor<Type>;
928
+ /** Minimal root description used for typing root maps. */
929
+ type FateRoots = Record<string, RootDefinition<TypeName, unknown>>;
930
+ /** Extracts the entity type name from a root definition. */
931
+ type RootType<R> = R extends __RootTypeAnchor<infer T> ? T : never;
932
+ /** Extracts the result type from a root definition. */
933
+ type RootResult<R> = R extends __RootResultAnchor<infer Data> ? Data : never;
934
+ /** Metadata describing a mutation for a particular entity, input, and output. */
935
+ type MutationDefinition<T extends Entity, I, R> = Readonly<{
936
+ entity: T['__typename'];
937
+ [MutationKind]: true;
938
+ }> & __MutationEntityAnchor<T> & __MutationInputAnchor<I> & __MutationResultAnchor<R>;
939
+ type MutationIdentifier<T extends Entity, I, R> = MutationDefinition<T, I, R> & Readonly<{
940
+ key: string;
941
+ }>;
942
+ /** Extracts the input type from a mutation definition or identifier. */
943
+ type MutationInput<M> = M extends __MutationInputAnchor<infer I> ? I : never;
944
+ /** Extracts the result type from a mutation definition or identifier. */
945
+ type MutationResult<M> = M extends __MutationResultAnchor<infer R> ? R : never;
946
+ /** Extracts the entity type from a mutation definition or identifier. */
947
+ type MutationEntity<M> = M extends __MutationEntityAnchor<infer E> ? E : never;
948
+ /** Minimal mutation description used for transport typing. */
949
+ type MutationShape = {
950
+ input: unknown;
951
+ output: unknown;
952
+ };
953
+ /**
954
+ * Convenience helper that maps mutation definitions to their input/output
955
+ * shapes for use by transports.
956
+ */
957
+ type MutationMapFromDefinitions<D extends FateMutations> = { [K in keyof D]: {
958
+ input: MutationInput<D[K]>;
959
+ output: MutationResult<D[K]>;
960
+ }; };
961
+ type OptimisticUpdateValue<T> = T extends ReadonlyArray<infer U> ? Array<OptimisticUpdateValue<U>> : NonNullish<T> extends AnyRecord ? OptimisticUpdate<NonNullish<T>> | Nullish<T> : NonNullish<T> | Nullish<T>;
962
+ /** Shape used to describe optimistic updates for mutations. */
963
+ type OptimisticUpdate<T> = { [K in keyof T]?: OptimisticUpdateValue<T[K]>; };
964
+ /** Promise-like value returned by cache reads that already have a resolved payload for React `use`. */
965
+ interface FateThenable<T> extends PromiseLike<T> {
966
+ status: 'fulfilled';
967
+ value: T;
968
+ }
969
+ //#endregion
970
+ //#region src/selection.d.ts
971
+ /**
972
+ * Representation of a composed selection including hashed args and the
973
+ * flat set of field paths to read or fetch.
974
+ */
975
+ type SelectionPlan = {
976
+ readonly args: Map<string, Readonly<{
977
+ hash: string;
978
+ ignoreKeys?: ReadonlySet<string>;
979
+ value: AnyRecord;
980
+ }>>;
981
+ readonly live: Map<string, ConnectionLivePolicy>;
982
+ readonly paths: Set<string>;
983
+ };
984
+ /**
985
+ * Flattens a view into a `SelectionPlan`, expanding composed views and
986
+ * partitioning nested args so the client can fetch exactly what is declared.
987
+ */
988
+ declare const getSelectionPlan: <T extends Entity, S extends Selection<T>, V extends View<T, S>>(viewComposition: V, ref: ViewRef<T['__typename']> | null) => SelectionPlan;
989
+ //#endregion
990
+ //#region src/request-descriptor.d.ts
991
+ type NodeRequestDescriptor = Readonly<{
992
+ ids: ReadonlyArray<string | number>;
993
+ kind: 'node' | 'nodes';
994
+ name: string;
995
+ plan: SelectionPlan;
996
+ refViewNames: ReadonlySet<string>;
997
+ type: string;
998
+ viewSignature: string;
999
+ }>;
1000
+ type QueryRequestDescriptor = Readonly<{
1001
+ argsPayload: ResolvedArgsPayload | undefined;
1002
+ kind: 'query';
1003
+ name: string;
1004
+ plan: SelectionPlan;
1005
+ queryKey: string;
1006
+ refViewNames: ReadonlySet<string>;
1007
+ type: string;
1008
+ viewSignature: string;
1009
+ }>;
1010
+ type ListRequestDescriptor = Readonly<{
1011
+ argsPayload: ResolvedArgsPayload | undefined;
1012
+ hasItems: boolean;
1013
+ kind: 'list';
1014
+ listKey: string;
1015
+ name: string;
1016
+ nodeRefViewNames: ReadonlySet<string>;
1017
+ plan: SelectionPlan;
1018
+ type: string;
1019
+ viewSignature: string;
1020
+ }>;
1021
+ type RequestItemDescriptor = NodeRequestDescriptor | QueryRequestDescriptor | ListRequestDescriptor;
1022
+ type RequestDescriptor = Readonly<{
1023
+ items: ReadonlyArray<RequestItemDescriptor>;
1024
+ key: string;
1025
+ }>;
1026
+ //#endregion
1027
+ //#region src/cache.d.ts
1028
+ declare class ViewDataCache {
1029
+ private readonly isEnabled;
1030
+ constructor(isEnabled?: () => boolean);
1031
+ private cache;
1032
+ private rootDependencies;
1033
+ private dependencyIndex;
1034
+ clear(): void;
1035
+ get<T extends Entity, S extends Selection<T>, V extends View<T, S>>(entityId: EntityId, view: V, ref: ViewRef<T['__typename']>): FateThenable<ViewSnapshot<T, S>> | null;
1036
+ set<T extends Entity, S extends Selection<T>, V extends View<T, S>>(entityId: EntityId, view: V, ref: ViewRef<T['__typename']>, thenable: FateThenable<ViewSnapshot<T, S>>, dependencies: ReadonlySet<EntityId>): void;
1037
+ invalidate(entityId: EntityId): void;
1038
+ private invalidateDependents;
1039
+ private delete;
1040
+ }
1041
+ //#endregion
1042
+ //#region src/store.d.ts
1043
+ type List = Readonly<{
1044
+ backwardPageLimit?: number;
1045
+ cursors?: ReadonlyArray<string | undefined>;
1046
+ forwardPageLimit?: number;
1047
+ ids: ReadonlyArray<EntityId>;
1048
+ liveAfterIds?: ReadonlyArray<EntityId>;
1049
+ liveBeforeIds?: ReadonlyArray<EntityId>;
1050
+ pagination?: Pagination;
1051
+ pendingAfterIds?: ReadonlyArray<EntityId>;
1052
+ pendingBeforeIds?: ReadonlyArray<EntityId>;
1053
+ }>;
1054
+ type StoreHydrationState = Readonly<{
1055
+ coverage: ReadonlyArray<readonly [EntityId, ReadonlyArray<string>]>;
1056
+ lists: ReadonlyArray<readonly [string, List]>;
1057
+ records: ReadonlyArray<readonly [EntityId, AnyRecord]>;
1058
+ }>;
1059
+ declare class Store {
1060
+ private readonly onRebase?;
1061
+ private readonly onChange?;
1062
+ private coverage;
1063
+ private listKeysByOwnerField;
1064
+ private listKeysByReferencedEntity;
1065
+ private lists;
1066
+ private recordReferenceFields;
1067
+ private recordReferencesByTarget;
1068
+ private records;
1069
+ private subscriptions;
1070
+ private listSubscriptions;
1071
+ private readonly optimisticLayers;
1072
+ private readonly optimisticBase;
1073
+ private recordingLayer;
1074
+ private rebase;
1075
+ constructor(onRebase?: ((ids: ReadonlySet<EntityId>) => void) | undefined, onChange?: ((kind: 'record' | 'list', key: string, paths?: Iterable<string>, previousList?: List) => void) | undefined);
1076
+ get hasOptimisticUpdates(): boolean;
1077
+ get isRebasing(): boolean;
1078
+ /** Apply a synchronous cache update beneath the pending optimistic layers. */
1079
+ update<T>(apply: () => T): T;
1080
+ private getRebaseChanges;
1081
+ /** Returns an idempotent settlement function; omit its update to roll back. */
1082
+ optimisticUpdate(apply: () => void, durable?: boolean): (commit?: () => void) => void;
1083
+ private getPendingOverlap;
1084
+ private captureRecord;
1085
+ private captureList;
1086
+ get hasTransientOptimisticUpdates(): boolean;
1087
+ getOptimisticRoots(): {
1088
+ baseRecords: AnyRecord[];
1089
+ lists: string[];
1090
+ records: string[];
1091
+ };
1092
+ /** @internal Indexed owners needed for mutation rollback. */
1093
+ getPersistenceOwners(id: EntityId): {
1094
+ lists: string[];
1095
+ records: string[];
1096
+ };
1097
+ /** @internal Read one confirmed record without copying the cache. */
1098
+ readConfirmed(id: EntityId): {
1099
+ paths: string[];
1100
+ record: AnyRecord;
1101
+ } | undefined;
1102
+ /** @internal */
1103
+ readConfirmedList(key: string): Readonly<{
1104
+ backwardPageLimit?: number;
1105
+ cursors?: ReadonlyArray<string | undefined>;
1106
+ forwardPageLimit?: number;
1107
+ ids: ReadonlyArray<EntityId>;
1108
+ liveAfterIds?: ReadonlyArray<EntityId>;
1109
+ liveBeforeIds?: ReadonlyArray<EntityId>;
1110
+ pagination?: Pagination;
1111
+ pendingAfterIds?: ReadonlyArray<EntityId>;
1112
+ pendingBeforeIds?: ReadonlyArray<EntityId>;
1113
+ }> | undefined;
1114
+ dehydrateConfirmed(): StoreHydrationState;
1115
+ dehydrate(): StoreHydrationState;
1116
+ hydrate(state: StoreHydrationState, mode: 'preserve-existing' | 'replace', options?: {
1117
+ deferNotifications?: boolean;
1118
+ }): () => void;
1119
+ private rebuildIndexes;
1120
+ read(id: EntityId): AnyRecord | undefined;
1121
+ merge(id: EntityId, partial: AnyRecord, paths: Iterable<string>): void;
1122
+ private mergeInternal;
1123
+ deleteRecord(id: EntityId): void;
1124
+ missingForSelection(id: EntityId, paths: Iterable<string>): Set<string>;
1125
+ subscribe(id: EntityId, selection: ReadonlySet<string> | null, fn: () => void): () => void;
1126
+ subscribe(id: EntityId, fn: () => void): () => void;
1127
+ private notify;
1128
+ private notifyListSubscribers;
1129
+ getList(key: string): ReadonlyArray<EntityId> | undefined;
1130
+ getListState(key: string): List | undefined;
1131
+ getListsForField(ownerId: EntityId, field: string): Array<readonly [string, List]>;
1132
+ setList(key: string, state: List): void;
1133
+ replaceListEntityId(previousId: EntityId, nextId: EntityId): void;
1134
+ restoreList(key: string, list?: List): void;
1135
+ collectGarbage(markedRecords: ReadonlySet<EntityId>, markedLists: ReadonlySet<string>, options?: {
1136
+ onRecordDeleted?: (id: EntityId) => void;
1137
+ }): {
1138
+ lists: Set<string>;
1139
+ records: Set<EntityId>;
1140
+ };
1141
+ private deleteList;
1142
+ subscribeList(key: string, fn: () => void): () => void;
1143
+ removeReferencesTo(targetId: EntityId, viewDataCache: ViewDataCache): void;
1144
+ private restore;
1145
+ private addListIndexes;
1146
+ private removeListIndexes;
1147
+ private getListReferencedEntityIds;
1148
+ private getRecordFieldReferences;
1149
+ private addRecordFieldReferenceIndex;
1150
+ private removeRecordFieldReferenceIndex;
1151
+ private addRecordReferenceIndexes;
1152
+ private removeRecordReferenceIndexes;
1153
+ private updateRecordReferenceIndexes;
1154
+ }
1155
+ //#endregion
1156
+ //#region src/hydration.d.ts
1157
+ /** JSON-safe opaque value contained in a dehydrated fate snapshot. */
1158
+ type FateSerializedValue = null | boolean | number | string | ReadonlyArray<FateSerializedValue> | Readonly<{
1159
+ [key: string]: FateSerializedValue;
1160
+ }>;
1161
+ /** Versioned, JSON-safe durable cache snapshot produced by `FateClient.dehydrate()`. */
1162
+ declare const hydrationScopeBrand: unique symbol;
1163
+ type FateDehydratedState<Scope extends string = string> = Readonly<{
1164
+ data: FateSerializedValue;
1165
+ readonly [hydrationScopeBrand]?: Scope;
1166
+ scope: Scope;
1167
+ version: 1;
1168
+ }>;
1169
+ /** Controls how `FateClient.hydrate()` reconciles a snapshot with browser cache state. */
1170
+ type HydrateOptions = Readonly<{
1171
+ /**
1172
+ * `preserve-existing` keeps browser values and list windows when conflicts
1173
+ * occur. `replace` treats the snapshot as authoritative.
1174
+ *
1175
+ * @defaultValue 'preserve-existing'
1176
+ */
1177
+ merge?: 'preserve-existing' | 'replace';
1178
+ }>;
1179
+ /** Resource limits applied while encoding and decoding hydration snapshots. */
1180
+ type HydrationLimits = Readonly<{
1181
+ /** Maximum number of entries in any encoded array or object. */
1182
+ maxCollectionLength: number;
1183
+ /** Maximum number of encoded values in a hydration snapshot. */
1184
+ maxNodes: number;
1185
+ /** Maximum length of an encoded string, object key, or bigint payload. */
1186
+ maxStringLength: number;
1187
+ }>;
1188
+ type ClientHydrationState = Readonly<{
1189
+ rootLists: ReadonlyArray<readonly [string, ReadonlyArray<string>]>;
1190
+ rootRequests: ReadonlyArray<readonly [string, string | null]>;
1191
+ store: StoreHydrationState;
1192
+ }>;
1193
+ declare const encodeHydrationValue: (value: unknown, limits?: Partial<HydrationLimits>) => FateSerializedValue;
1194
+ //#endregion
1195
+ //#region src/operation-lifetime.d.ts
1196
+ type RetainHandle = Readonly<{
1197
+ dispose(): void;
1198
+ }>;
1199
+ //#endregion
1200
+ //#region src/client.d.ts
1201
+ /**
1202
+ * Strategy used when resolving a request.
1203
+ */
1204
+ type RequestMode =
1205
+ /** (default) Use cached data if present, otherwise fetch. */
1206
+ 'cache-first' |
1207
+ /** Show cached data immediately and refresh in the background. */
1208
+ 'stale-while-revalidate' |
1209
+ /** Always fetch from the network and ignore cached entries. */
1210
+ 'network-only';
1211
+ /**
1212
+ * Request options that affect how requests are fetched and retained.
1266
1213
  */
1267
- type RequestResult<R extends FateRoots, Q extends AnyRequest> = { [K in keyof Q]: K extends keyof R ? ListResult<Q[K], RootType<R[K]>, RootResult<R[K]>> : never; };
1268
- /** Brand used on root definitions to mark their identity in the d.ts output. */
1269
- declare const RootKind = "__fate__root";
1270
- /** Brand used on mutation definitions to mark their identity in the d.ts output. */
1271
- declare const MutationKind = "__fate__mutation";
1272
- /** Metadata describing a root query for a particular entity and result shape. */
1273
- type RootDefinition<Type extends TypeName, Result> = Readonly<{
1274
- [RootKind]: true;
1275
- type: Type;
1276
- }> & __RootResultAnchor<Result> & __RootTypeAnchor<Type>;
1277
- /** Minimal root description used for typing root maps. */
1278
- type FateRoots = Record<string, RootDefinition<TypeName, unknown>>;
1279
- /** Extracts the entity type name from a root definition. */
1280
- type RootType<R> = R extends __RootTypeAnchor<infer T> ? T : never;
1281
- /** Extracts the result type from a root definition. */
1282
- type RootResult<R> = R extends __RootResultAnchor<infer Data> ? Data : never;
1283
- /** Metadata describing a mutation for a particular entity, input, and output. */
1284
- type MutationDefinition<T extends Entity, I, R> = Readonly<{
1285
- entity: T['__typename'];
1286
- [MutationKind]: true;
1287
- }> & __MutationEntityAnchor<T> & __MutationInputAnchor<I> & __MutationResultAnchor<R>;
1288
- type MutationIdentifier<T extends Entity, I, R> = MutationDefinition<T, I, R> & Readonly<{
1289
- key: string;
1214
+ type RequestOptions = Readonly<{
1215
+ mode?: RequestMode;
1216
+ /** Override disk retention in milliseconds; only used with persistence. */
1217
+ persist?: {
1218
+ maxAge: number;
1219
+ };
1290
1220
  }>;
1291
- /** Extracts the input type from a mutation definition or identifier. */
1292
- type MutationInput<M> = M extends __MutationInputAnchor<infer I> ? I : never;
1293
- /** Extracts the result type from a mutation definition or identifier. */
1294
- type MutationResult<M> = M extends __MutationResultAnchor<infer R> ? R : never;
1295
- /** Extracts the entity type from a mutation definition or identifier. */
1296
- type MutationEntity<M> = M extends __MutationEntityAnchor<infer E> ? E : never;
1297
- /** Minimal mutation description used for transport typing. */
1298
- type MutationShape = {
1299
- input: unknown;
1300
- output: unknown;
1221
+ type DeferredSnapshot<T> = Readonly<{
1222
+ coverage: ReadonlyArray<readonly [id: EntityId, paths: ReadonlySet<string>]>;
1223
+ data: T;
1224
+ }>;
1225
+ type FateClientOptions<Roots extends FateRoots, Mutations extends FateMutations, HydrationScope extends string> = {
1226
+ /**
1227
+ * Number of recently released requests to keep retained before their records
1228
+ * and lists are eligible for garbage collection.
1229
+ *
1230
+ * @defaultValue 10
1231
+ */
1232
+ gcReleaseBufferSize?: number;
1233
+ /**
1234
+ * Bounds hydration snapshot encoding and decoding work.
1235
+ */
1236
+ hydrationLimits?: Partial<HydrationLimits>;
1237
+ /**
1238
+ * Identifies snapshots compatible with this client. Change this value when
1239
+ * deploying an incompatible cache schema or separating cache namespaces.
1240
+ */
1241
+ hydrationScope?: HydrationScope;
1242
+ mutations?: Mutations;
1243
+ onLiveError?: (error: unknown) => void;
1244
+ persistence?: Persistence;
1245
+ roots: Roots;
1246
+ transport: Transport<MutationMapFromDefinitions<Mutations>>;
1247
+ types: ReadonlyArray<Omit<TypeConfig, 'getId'> & Partial<{
1248
+ getId: TypeConfig['getId'];
1249
+ }>>;
1301
1250
  };
1302
1251
  /**
1303
- * Convenience helper that maps mutation definitions to their input/output
1304
- * shapes for use by transports.
1252
+ * Core client that normalizes records, manages the view cache, and coordinates
1253
+ * data fetching.
1305
1254
  */
1306
- type MutationMapFromDefinitions<D extends FateMutations> = { [K in keyof D]: {
1307
- input: MutationInput<D[K]>;
1308
- output: MutationResult<D[K]>;
1309
- }; };
1310
- type OptimisticUpdateValue<T> = T extends ReadonlyArray<infer U> ? Array<OptimisticUpdateValue<U>> : NonNullish<T> extends AnyRecord ? OptimisticUpdate<NonNullish<T>> | Nullish<T> : NonNullish<T> | Nullish<T>;
1311
- /** Shape used to describe optimistic updates for mutations. */
1312
- type OptimisticUpdate<T> = { [K in keyof T]?: OptimisticUpdateValue<T[K]>; };
1313
- /** Promise-like value returned by cache reads that already have a resolved payload for React `use`. */
1314
- interface FateThenable<T> extends PromiseLike<T> {
1315
- status: 'fulfilled';
1316
- value: T;
1255
+ declare class FateClient<Roots extends FateRoots, Mutations extends FateMutations, HydrationScope extends string = string> {
1256
+ private readonly mutationEntities?;
1257
+ private readonly mutationMap;
1258
+ private readonly parentLists;
1259
+ private readonly rootLists;
1260
+ private readonly pending;
1261
+ private readonly pendingDeferred;
1262
+ private readonly pendingOptimisticMutations;
1263
+ private readonly optimisticEntityResolutions;
1264
+ private readonly onLiveError;
1265
+ private readonly liveSubscriptions;
1266
+ private readonly liveConnectionInvalidations;
1267
+ private readonly stableRefs;
1268
+ private readonly requests;
1269
+ private readonly requestExecutionOptions;
1270
+ private readonly rootRequests;
1271
+ private readonly stalledRequests;
1272
+ private gcPending;
1273
+ private gcScheduled;
1274
+ private pendingNetworkRequests;
1275
+ private readonly persistenceDisposal?;
1276
+ readonly store: Store;
1277
+ private readonly operationLifetime;
1278
+ private readonly hydrationLimits;
1279
+ private readonly hydrationScope;
1280
+ private readonly types;
1281
+ private readonly transport;
1282
+ private readonly viewDataCache;
1283
+ private liveConnectionInvalidationToken;
1284
+ readonly persistence?: PersistenceSession;
1285
+ readonly actions: MutationActionsFor<Mutations>;
1286
+ readonly mutations: MutationFunctionsFor<Mutations>;
1287
+ readonly roots: Roots;
1288
+ constructor(options: FateClientOptions<Roots, Mutations, HydrationScope>);
1289
+ private initializeParentLists;
1290
+ /**
1291
+ * Exports the durable normalized cache as an opaque JSON-safe value for SSR
1292
+ * transfer or persistence. Runtime requests, subscriptions, retainers, and
1293
+ * optimistic state are intentionally excluded.
1294
+ */
1295
+ dehydrate(): FateDehydratedState<HydrationScope>;
1296
+ /**
1297
+ * Restores a durable normalized cache snapshot without restoring runtime
1298
+ * request handles, retainers, subscriptions, or optimistic update state.
1299
+ * Hydrate before rendering SSR content. Replaying the same snapshot is safe.
1300
+ */
1301
+ hydrate(state: FateDehydratedState<HydrationScope>, options?: HydrateOptions): void;
1302
+ /** @internal */
1303
+ exportPersistenceState(): FateDehydratedState<HydrationScope>;
1304
+ /** @internal */
1305
+ retainPersistenceRequest(request: RequestDescriptor): Readonly<{
1306
+ dispose(): void;
1307
+ }>;
1308
+ /** @internal */
1309
+ getPersistenceScope(): HydrationScope;
1310
+ /** @internal */
1311
+ getPersistenceRootLists(type: string): Set<string>;
1312
+ /** @internal */
1313
+ getPersistenceQuery(key: string): string | null | undefined;
1314
+ /** @internal Merge a small disk read beneath optimistic layers. */
1315
+ restorePersistenceData(state: ClientHydrationState): void;
1316
+ /** @internal */
1317
+ getRetainedRequests(): readonly Readonly<{
1318
+ items: ReadonlyArray<RequestItemDescriptor>;
1319
+ key: string;
1320
+ }>[];
1321
+ /** @internal */
1322
+ restoreRetainedRequests(requests: ReadonlyArray<RequestDescriptor>): void;
1323
+ /** @internal */
1324
+ hasMutation(key: string, entity: string): boolean;
1325
+ private registerRootList;
1326
+ private applyListInsert;
1327
+ private insertIntoRootLists;
1328
+ getTypeConfig(type: string): TypeConfig;
1329
+ private getListNodeType;
1330
+ /** @internal Validates local wiring without requiring network connectivity. */
1331
+ validatePersistence(): void;
1332
+ /** @internal */
1333
+ assertPersistenceActive(): void;
1334
+ /** @internal */
1335
+ disposePersistence(): void;
1336
+ private requireDurableMutationTransport;
1337
+ executeMutation(key: string, input: unknown, select: Set<string>, options?: {
1338
+ args?: AnyRecord;
1339
+ identity?: MutationIdentity;
1340
+ plan?: SelectionPlan;
1341
+ }): Promise<unknown>;
1342
+ write(type: string, data: AnyRecord, select: ReadonlySet<string>, plan?: SelectionPlan, insert?: InsertPosition): string;
1343
+ deleteRecord(type: string, id: string | number): void;
1344
+ private stableRefWithViewNames;
1345
+ ref<T extends Entity>(type: T['__typename'], id: string | number, view: View<T, Selection<T>>): ViewRef<T['__typename']>;
1346
+ rootListRef(entityId: EntityId, rootView: View<any, any>): Readonly<{
1347
+ __typename: string;
1348
+ id: string | number;
1349
+ [ViewsTag]: Set<string>;
1350
+ }>;
1351
+ readView<T extends Entity, S extends Selection<T>, V extends View<T, S>>(view: V, ref: ViewRef<T['__typename']>): FateThenable<ViewSnapshot<T, S>>;
1352
+ readDeferred<T>(deferred: Deferred<T>): PromiseLike<DeferredSnapshot<T>>;
1353
+ assertLiveViewSupport(): void;
1354
+ assertLiveConnectionSupport(): void;
1355
+ subscribeLiveView<T extends Entity, S extends Selection<T>, V extends View<T, S>>(view: V, ref: ViewRef<T['__typename']>): () => void;
1356
+ subscribeLiveListView<V extends View<any, any>>(view: V, connection: ConnectionMetadata): () => void;
1357
+ private applyLiveConnectionEvent;
1358
+ private invalidateLiveConnection;
1359
+ private deleteConnectionEdge;
1360
+ private insertConnectionEdge;
1361
+ private syncNestedConnectionOwnerField;
1362
+ private getConnectionInsertIndex;
1363
+ private removeEntityFromListState;
1364
+ private mergeListState;
1365
+ registerPendingOptimisticMutation(entityId: EntityId, promise: Promise<unknown>): void;
1366
+ resolveOptimisticEntity(optimisticEntityId: EntityId, resolvedEntityId: EntityId): void;
1367
+ private getPendingOptimisticMutations;
1368
+ loadConnection<V extends View<any, any>>(view: V, connection: ConnectionMetadata, args: Record<string, unknown>, options?: {
1369
+ direction?: 'forward' | 'backward';
1370
+ }): Promise<Readonly<{
1371
+ backwardPageLimit?: number;
1372
+ cursors?: ReadonlyArray<string | undefined>;
1373
+ forwardPageLimit?: number;
1374
+ ids: ReadonlyArray<EntityId>;
1375
+ liveAfterIds?: ReadonlyArray<EntityId>;
1376
+ liveBeforeIds?: ReadonlyArray<EntityId>;
1377
+ pagination?: Pagination;
1378
+ pendingAfterIds?: ReadonlyArray<EntityId>;
1379
+ pendingBeforeIds?: ReadonlyArray<EntityId>;
1380
+ }> | undefined>;
1381
+ private loadConnectionInternal;
1382
+ request<R extends Request$1>(request: R, options?: RequestOptions): Promise<RequestResult<Roots, R>>;
1383
+ requestForRender<R extends Request$1>(request: R, options?: RequestOptions): Promise<RequestResult<Roots, R>>;
1384
+ prepareRequestForRender<R extends Request$1>(request: R, options: RequestOptions | undefined): Readonly<{
1385
+ promise: Promise<RequestResult<Roots, R>>;
1386
+ requestKey: string;
1387
+ }>;
1388
+ private requestWithDescriptor;
1389
+ releaseRequest(request: Request$1, mode: RequestMode): void;
1390
+ releaseRequestKey(requestKey: string, mode: RequestMode): void;
1391
+ retainRequestKey(requestKey: string, mode?: RequestMode): RetainHandle;
1392
+ /**
1393
+ * Keeps the records and lists reachable from a request alive until the
1394
+ * returned handle is disposed.
1395
+ *
1396
+ * `useRequest` calls this automatically while the component is mounted.
1397
+ * Use it directly for non-React request lifetimes, tests, or preloaded data
1398
+ * that must survive manual garbage collection.
1399
+ */
1400
+ retain(request: Request$1): RetainHandle;
1401
+ private scheduleGarbageCollection;
1402
+ /**
1403
+ * Removes records and lists that are not reachable from retained requests or
1404
+ * the release buffer.
1405
+ *
1406
+ * Garbage collection is scheduled automatically when retained requests are
1407
+ * released. Calling this method manually is mainly useful in tests and custom
1408
+ * memory-management flows.
1409
+ */
1410
+ gc(): void;
1411
+ private executeRequestHandle;
1412
+ private markRecordReferences;
1413
+ private hasActiveOptimisticUpdates;
1414
+ private hasPendingRequests;
1415
+ /** @internal */
1416
+ withPersistenceLifecycle<T>(request: () => Promise<T>): Promise<T>;
1417
+ trackPendingRequest<T>(request: () => Promise<T>): Promise<T>;
1418
+ private runPendingGarbageCollection;
1419
+ private handleStoreAndNetworkRequest;
1420
+ private getRootType;
1421
+ private createRequestDescriptor;
1422
+ getRequestKey(request: Request$1): string;
1423
+ private hasRootListData;
1424
+ private executeRequest;
1425
+ private hasRequestData;
1426
+ getRequestResult<R extends Request$1>(request: R): RequestResult<Roots, R>;
1427
+ private getRequestResultFromDescriptor;
1428
+ private fetchByIdAndNormalize;
1429
+ private fetchQueryAndNormalize;
1430
+ private fetchListAndNormalize;
1431
+ private writeEntity;
1432
+ private linkParentLists;
1433
+ private readViewSelection;
1434
+ private clearStalledRequestsForEntity;
1435
+ private pendingPrefix;
1436
+ private pendingKey;
1437
+ private deferredPendingKey;
1438
+ private deferredSelectionSignature;
1439
+ private hasMissingDeferredList;
1440
+ private liveSubscriptionKey;
1441
+ private liveConnectionSubscriptionKey;
1442
+ private releaseLiveSubscription;
1443
+ private reportLiveError;
1444
+ }
1445
+ declare function createClient<T extends [FateRoots, FateMutations] = [Record<never, RootDefinition<any, any>>, Record<never, MutationDefinition<any, any, any>>], HydrationScope extends string = string>(options: FateClientOptions<T[0], T[1], HydrationScope>): FateClient<T[0], T[1], HydrationScope>;
1446
+ //#endregion
1447
+ //#region src/persistence-types.d.ts
1448
+ /** Identity of one logical mutation, reused across every delivery attempt. */
1449
+ type MutationIdentity = Readonly<{
1450
+ id: string;
1451
+ replayOnly?: true;
1452
+ /** Return an existing receipt; never execute a new mutation. */ scope: string;
1453
+ }>;
1454
+ /** A persistence integration. Implementations are imported separately from Fate core. */
1455
+ interface Persistence {
1456
+ attach(client: FateClient<any, any, any>): PersistenceSession;
1457
+ }
1458
+ type PersistedMutationStatus = Readonly<{
1459
+ error?: string;
1460
+ id: string;
1461
+ input: unknown;
1462
+ name: string;
1463
+ status: 'queued' | 'sending' | 'failed';
1464
+ }>;
1465
+ type PersistenceSnapshot = Readonly<{
1466
+ error?: Error;
1467
+ mutations: ReadonlyArray<PersistedMutationStatus>;
1468
+ status: 'restoring' | 'ready' | 'error' | 'disposed';
1469
+ }>;
1470
+ type RequestPersistenceOptions = Readonly<{
1471
+ maxAge: number;
1472
+ }>;
1473
+ /** Observability and lifecycle of an attached persistence integration. */
1474
+ interface PersistenceSession {
1475
+ /** @internal */
1476
+ changed(kind?: 'record' | 'list', key?: string, paths?: Iterable<string>, previousList?: List): void;
1477
+ clearCache(): Promise<void>;
1478
+ discard(id: string): Promise<void>;
1479
+ dispose(): void;
1480
+ /** @internal */
1481
+ fetched(request: RequestDescriptor, options?: RequestPersistenceOptions): void;
1482
+ flush(): Promise<void>;
1483
+ getSnapshot(): PersistenceSnapshot;
1484
+ /** @internal */
1485
+ mutate(command: MutationCommand): Promise<unknown>;
1486
+ readonly ready: Promise<void>;
1487
+ /** @internal */
1488
+ restoreRequest(request: RequestDescriptor): Promise<void>;
1489
+ retry(): void;
1490
+ subscribe(listener: () => void): () => void;
1491
+ /** @internal */
1492
+ used(request: RequestDescriptor, options?: RequestPersistenceOptions): void;
1317
1493
  }
1318
1494
  //#endregion
1319
1495
  //#region src/transport.d.ts
@@ -1373,6 +1549,11 @@ interface Transport<Mutations extends TransportMutations = EmptyTransportMutatio
1373
1549
  }>;
1374
1550
  fetchQuery?(proc: string, select: Iterable<string>, args?: ResolvedArgsPayload): Promise<unknown>;
1375
1551
  mutate?<K extends Extract<keyof Mutations, string>>(proc: K, input: Mutations[K]['input'], select: Set<string>): Promise<Mutations[K]['output']>;
1552
+ /**
1553
+ * Deliver through an endpoint that durably deduplicates this identity. Required
1554
+ * for persisted mutations; never falls back to ordinary mutate.
1555
+ */
1556
+ mutateDurably?<K extends Extract<keyof Mutations, string>>(proc: K, input: Mutations[K]['input'], select: Set<string>, identity: MutationIdentity): Promise<Mutations[K]['output']>;
1376
1557
  subscribeById?(type: string, id: string | number, select: Iterable<string>, args: ResolvedArgsPayload | undefined, handlers: LiveEventHandlers): () => void;
1377
1558
  subscribeConnection?(procedure: string, type: string, args: ResolvedArgsPayload | undefined, select: Iterable<string>, selectionArgs: ResolvedArgsPayload | undefined, handlers: LiveConnectionEventHandlers): () => void;
1378
1559
  }
@@ -1409,12 +1590,13 @@ type EmptyMutationResolvers<AppRouter extends AnyRouter> = Record<never, Mutatio
1409
1590
  * Builds a `Transport` backed by a tRPC client using the configured resolvers
1410
1591
  * for by-id queries, lists, and mutations.
1411
1592
  */
1412
- declare function createTRPCTransport<AppRouter extends AnyRouter, Mutations extends TRPCMutationResolvers<AppRouter> = EmptyMutationResolvers<AppRouter>>({ byId, client, lists, mutations, queries }: {
1593
+ declare function createTRPCTransport<AppRouter extends AnyRouter, Mutations extends TRPCMutationResolvers<AppRouter> = EmptyMutationResolvers<AppRouter>>({ byId, client, lists, mutateDurably, mutations, queries }: {
1413
1594
  byId: TRPCByIdResolvers<AppRouter>;
1414
1595
  client: TRPCClient<AppRouter>;
1415
1596
  lists?: TRPCListResolvers<AppRouter>;
1597
+ mutateDurably?: Transport<MutationMapFromResolvers<Mutations>>['mutateDurably'];
1416
1598
  mutations?: Mutations;
1417
1599
  queries?: TRPCQueryResolvers<AppRouter>;
1418
1600
  }): Transport<MutationMapFromResolvers<Mutations>>;
1419
1601
  //#endregion
1420
- export { HydrationLimits as $, TypeConfig as A, __FateEntityBrand as B, MutationShape as C, RequestResult as D, Request$1 as E, ViewEntityName as F, DeferredSnapshot as G, isViewTag as H, ViewRef as I, RequestOptions as J, FateClient as K, ViewSelection as L, View as M, ViewData as N, RootDefinition as O, ViewEntity as P, HydrateOptions as Q, ViewSnapshot as R, MutationResult as S, Pagination as T, FateMutations as U, __FateSelectionBrand as V, mutation as W, getSelectionPlan as X, createClient as Y, FateDehydratedState as Z, Mask as _, ConnectionRef as a, MutationIdentifier as b, Deferred as c, DeferredTag as d, List as et, Entity as f, ListItem as g, FateThenable as h, ConnectionMetadata as i, TypeName as j, Selection as k, DeferredMetadata as l, FateRoots as m, createTRPCTransport as n, QueryProcedure as nt, ConnectionTag as o, EntityId as p, RequestMode as q, AnyRecord as r, DeferTag as s, Transport as t, AnyProcedure as tt, DeferredSelection as u, MutationDefinition as v, NodesItem as w, MutationInput as x, MutationEntity as y, ViewTag as z };
1602
+ export { ViewSnapshot as $, FateThenable as A, Pagination as B, Deferred as C, Entity as D, DeferredTag as E, MutationIdentifier as F, TypeConfig as G, RequestResult as H, MutationInput as I, ViewData as J, TypeName as K, MutationResult as L, Mask as M, MutationDefinition as N, EntityId as O, MutationEntity as P, ViewSelection as Q, MutationShape as R, DeferTag as S, DeferredSelection as T, RootDefinition as U, Request$1 as V, Selection as W, ViewEntityName as X, ViewEntity as Y, ViewRef as Z, getSelectionPlan as _, PersistenceSession as a, mutation as at, ConnectionRef as b, FateClient as c, createClient as d, ViewTag as et, FateDehydratedState as f, List as g, encodeHydrationValue as h, Persistence as i, FateMutations as it, ListItem as j, FateRoots as k, RequestMode as l, HydrationLimits as m, createTRPCTransport as n, __FateSelectionBrand as nt, PersistenceSnapshot as o, AnyProcedure as ot, HydrateOptions as p, View as q, MutationIdentity as r, isViewTag as rt, DeferredSnapshot as s, QueryProcedure as st, Transport as t, __FateEntityBrand as tt, RequestOptions as u, AnyRecord as v, DeferredMetadata as w, ConnectionTag as x, ConnectionMetadata as y, NodesItem as z };