@nkzw/fate 0.1.2 → 1.0.0-rc.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 (170) hide show
  1. package/README.md +810 -129
  2. package/docs/api/classes/FateClient.md +832 -0
  3. package/docs/api/functions/clientRoot.md +27 -0
  4. package/docs/api/functions/createClient.md +21 -0
  5. package/docs/api/functions/createHTTPTransport.md +51 -0
  6. package/docs/api/functions/createTRPCTransport.md +46 -0
  7. package/docs/api/functions/getListEntries.md +15 -0
  8. package/docs/api/functions/getSelectionPlan.md +36 -0
  9. package/docs/api/functions/isRecord.md +15 -0
  10. package/docs/api/functions/isViewTag.md +17 -0
  11. package/docs/api/functions/liveConnectionTopic.md +19 -0
  12. package/docs/api/functions/liveEntityTopic.md +19 -0
  13. package/docs/api/functions/liveGlobalConnectionTopic.md +15 -0
  14. package/docs/api/functions/mutation.md +32 -0
  15. package/docs/api/functions/toEntityId.md +21 -0
  16. package/docs/api/functions/view.md +26 -0
  17. package/docs/api/index.md +81 -0
  18. package/docs/api/interfaces/FateThenable.md +31 -0
  19. package/docs/api/interfaces/Transport.md +199 -0
  20. package/docs/api/server/classes/FateRequestError.md +67 -0
  21. package/docs/api/server/drizzle/functions/createDrizzleFate.md +431 -0
  22. package/docs/api/server/drizzle/functions/createDrizzleSourceAdapter.md +21 -0
  23. package/docs/api/server/drizzle/functions/createDrizzleSourceRegistry.md +21 -0
  24. package/docs/api/server/drizzle/index.md +23 -0
  25. package/docs/api/server/drizzle/type-aliases/DrizzleManyToManyConfig.md +15 -0
  26. package/docs/api/server/drizzle/type-aliases/DrizzleManyToManyInput.md +5 -0
  27. package/docs/api/server/drizzle/type-aliases/DrizzleQueryExtra.md +21 -0
  28. package/docs/api/server/drizzle/type-aliases/DrizzleSourceAdapter.md +337 -0
  29. package/docs/api/server/drizzle/type-aliases/DrizzleViewConfig.md +29 -0
  30. package/docs/api/server/functions/bindSourceProcedures.md +32 -0
  31. package/docs/api/server/functions/computed.md +43 -0
  32. package/docs/api/server/functions/count.md +21 -0
  33. package/docs/api/server/functions/createFateFetchHandler.md +21 -0
  34. package/docs/api/server/functions/createFateServer.md +41 -0
  35. package/docs/api/server/functions/createHonoFateHandler.md +21 -0
  36. package/docs/api/server/functions/createLiveEventBus.md +17 -0
  37. package/docs/api/server/functions/createNestedSourcePlan.md +103 -0
  38. package/docs/api/server/functions/createResolver.md +74 -0
  39. package/docs/api/server/functions/createSourcePlan.md +95 -0
  40. package/docs/api/server/functions/createSourceProcedures.md +46 -0
  41. package/docs/api/server/functions/dataView.md +32 -0
  42. package/docs/api/server/functions/field.md +15 -0
  43. package/docs/api/server/functions/getNestedSelection.md +19 -0
  44. package/docs/api/server/functions/getScopedArgs.md +21 -0
  45. package/docs/api/server/functions/hasNestedSelection.md +19 -0
  46. package/docs/api/server/functions/list.md +28 -0
  47. package/docs/api/server/functions/refetchSourceById.md +55 -0
  48. package/docs/api/server/functions/resolveSourceById.md +55 -0
  49. package/docs/api/server/functions/resolveSourceByIds.md +55 -0
  50. package/docs/api/server/functions/resolveSourceConnection.md +67 -0
  51. package/docs/api/server/functions/resolver.md +42 -0
  52. package/docs/api/server/functions/toPrismaSelect.md +25 -0
  53. package/docs/api/server/functions/withConnection.md +24 -0
  54. package/docs/api/server/index.md +109 -0
  55. package/docs/api/server/prisma/functions/createPrismaFate.md +435 -0
  56. package/docs/api/server/prisma/functions/createPrismaSourceAdapter.md +21 -0
  57. package/docs/api/server/prisma/functions/createPrismaSourceRegistry.md +21 -0
  58. package/docs/api/server/prisma/functions/prismaConnectionArgs.md +57 -0
  59. package/docs/api/server/prisma/index.md +23 -0
  60. package/docs/api/server/prisma/type-aliases/PrismaDelegate.md +59 -0
  61. package/docs/api/server/prisma/type-aliases/PrismaQueryExtra.md +5 -0
  62. package/docs/api/server/prisma/type-aliases/PrismaSourceAdapter.md +343 -0
  63. package/docs/api/server/prisma/type-aliases/PrismaViewConfig.md +31 -0
  64. package/docs/api/server/type-aliases/ComputedField.md +55 -0
  65. package/docs/api/server/type-aliases/ComputedSelection.md +5 -0
  66. package/docs/api/server/type-aliases/ConnectionItem.md +29 -0
  67. package/docs/api/server/type-aliases/ConnectionPagination.md +39 -0
  68. package/docs/api/server/type-aliases/ConnectionResult.md +29 -0
  69. package/docs/api/server/type-aliases/CountSelection.md +29 -0
  70. package/docs/api/server/type-aliases/CountWhere.md +5 -0
  71. package/docs/api/server/type-aliases/DataViewListOptions.md +13 -0
  72. package/docs/api/server/type-aliases/DataViewOrderBy.md +5 -0
  73. package/docs/api/server/type-aliases/DataViewOrderDirection.md +5 -0
  74. package/docs/api/server/type-aliases/DataViewResult.md +11 -0
  75. package/docs/api/server/type-aliases/Entity.md +21 -0
  76. package/docs/api/server/type-aliases/FateServer.md +75 -0
  77. package/docs/api/server/type-aliases/FateServerManifest.md +5 -0
  78. package/docs/api/server/type-aliases/FieldSelection.md +21 -0
  79. package/docs/api/server/type-aliases/LiveConnectionEventType.md +5 -0
  80. package/docs/api/server/type-aliases/LiveConnectionSourceEvent.md +5 -0
  81. package/docs/api/server/type-aliases/LiveEventBus.md +5 -0
  82. package/docs/api/server/type-aliases/LiveEventType.md +5 -0
  83. package/docs/api/server/type-aliases/LiveSourceEvent.md +5 -0
  84. package/docs/api/server/type-aliases/NativeFateAPI.md +47 -0
  85. package/docs/api/server/type-aliases/OrderDirection.md +5 -0
  86. package/docs/api/server/type-aliases/SourceConfig.md +55 -0
  87. package/docs/api/server/type-aliases/SourceDefinition.md +55 -0
  88. package/docs/api/server/type-aliases/SourceOrder.md +5 -0
  89. package/docs/api/server/type-aliases/SourceOrderField.md +21 -0
  90. package/docs/api/server/type-aliases/SourcePlan.md +29 -0
  91. package/docs/api/server/type-aliases/SourcePlanNode.md +29 -0
  92. package/docs/api/server/type-aliases/SourceRegistry.md +11 -0
  93. package/docs/api/server/type-aliases/SourceRelation.md +15 -0
  94. package/docs/api/server/type-aliases/SourceRelationConfig.md +23 -0
  95. package/docs/api/server/variables/byIdInput.md +5 -0
  96. package/docs/api/server/variables/connectionArgs.md +7 -0
  97. package/docs/api/type-aliases/ConnectionMetadata.md +7 -0
  98. package/docs/api/type-aliases/ConnectionRef.md +13 -0
  99. package/docs/api/type-aliases/Entity.md +15 -0
  100. package/docs/api/type-aliases/EntityId.md +7 -0
  101. package/docs/api/type-aliases/FateLiveConnectionEvent.md +5 -0
  102. package/docs/api/type-aliases/FateLiveEvent.md +5 -0
  103. package/docs/api/type-aliases/FateMutations.md +7 -0
  104. package/docs/api/type-aliases/FateOperation.md +5 -0
  105. package/docs/api/type-aliases/FateProtocolRequest.md +5 -0
  106. package/docs/api/type-aliases/FateProtocolResponse.md +5 -0
  107. package/docs/api/type-aliases/FateRecord.md +7 -0
  108. package/docs/api/type-aliases/FateRoots.md +7 -0
  109. package/docs/api/type-aliases/InferFateAPI.md +11 -0
  110. package/docs/api/type-aliases/List.md +5 -0
  111. package/docs/api/type-aliases/ListEntry.md +5 -0
  112. package/docs/api/type-aliases/ListItem.md +13 -0
  113. package/docs/api/type-aliases/Mask.md +15 -0
  114. package/docs/api/type-aliases/MutationDefinition.md +21 -0
  115. package/docs/api/type-aliases/MutationEntity.md +13 -0
  116. package/docs/api/type-aliases/MutationIdentifier.md +19 -0
  117. package/docs/api/type-aliases/MutationInput.md +13 -0
  118. package/docs/api/type-aliases/MutationResult.md +13 -0
  119. package/docs/api/type-aliases/NodesItem.md +13 -0
  120. package/docs/api/type-aliases/Pagination.md +39 -0
  121. package/docs/api/type-aliases/Request.md +7 -0
  122. package/docs/api/type-aliases/RequestMode.md +7 -0
  123. package/docs/api/type-aliases/RequestOptions.md +7 -0
  124. package/docs/api/type-aliases/RequestResult.md +18 -0
  125. package/docs/api/type-aliases/Selection.md +13 -0
  126. package/docs/api/type-aliases/Snapshot.md +7 -0
  127. package/docs/api/type-aliases/TypeConfig.md +41 -0
  128. package/docs/api/type-aliases/View.md +17 -0
  129. package/docs/api/type-aliases/ViewData.md +18 -0
  130. package/docs/api/type-aliases/ViewEntity.md +13 -0
  131. package/docs/api/type-aliases/ViewEntityName.md +13 -0
  132. package/docs/api/type-aliases/ViewRef.md +13 -0
  133. package/docs/api/type-aliases/ViewSelection.md +13 -0
  134. package/docs/api/type-aliases/ViewSnapshot.md +18 -0
  135. package/docs/api/type-aliases/ViewTag.md +7 -0
  136. package/docs/api/variables/ConnectionTag.md +7 -0
  137. package/docs/guide/actions.md +263 -0
  138. package/docs/guide/core-concepts.md +22 -0
  139. package/docs/guide/getting-started.md +57 -0
  140. package/docs/guide/list-views.md +86 -0
  141. package/docs/guide/live-views.md +245 -0
  142. package/docs/guide/requests.md +130 -0
  143. package/docs/guide/server-integration.md +630 -0
  144. package/docs/guide/views.md +278 -0
  145. package/docs/guide/void-integration.md +167 -0
  146. package/docs/index.md +4 -0
  147. package/lib/cli.mjs +17 -250
  148. package/lib/clientStub.d.mts +6 -0
  149. package/lib/clientStub.mjs +6 -0
  150. package/lib/executor-BqwHdN3n.d.mts +468 -0
  151. package/lib/index.d.mts +64 -3
  152. package/lib/index.mjs +1965 -559
  153. package/lib/list-4wRNSVgI.d.mts +10 -0
  154. package/lib/list-C_mi6GnE.mjs +16 -0
  155. package/lib/list.d.mts +2 -0
  156. package/lib/list.mjs +2 -0
  157. package/lib/liveTopics-DzNtJaBD.mjs +197 -0
  158. package/lib/{record-DnhZuvUe.mjs → record-AeZJC9fd.mjs} +1 -2
  159. package/lib/record-ENh92gyb.d.mts +315 -0
  160. package/lib/server/drizzle.d.mts +304 -0
  161. package/lib/server/drizzle.mjs +688 -0
  162. package/lib/server/prisma.d.mts +309 -0
  163. package/lib/server/prisma.mjs +345 -0
  164. package/lib/server.d.mts +82 -184
  165. package/lib/server.mjs +870 -416
  166. package/lib/sourceRouter-Bwpkr062.mjs +972 -0
  167. package/lib/{types-Djlh7mMH.d.mts → types-Dz46PXr3.d.mts} +327 -197
  168. package/lib/vite.d.mts +17 -0
  169. package/lib/vite.mjs +592 -0
  170. package/package.json +44 -6
@@ -0,0 +1,15 @@
1
+ # Type Alias: Mask\<T, S\>
2
+
3
+ > **Mask**\<`T`, `S`\> = `WithNullish`\<`T`, `MaskNonNullish`\<`NonNullish`\<`T`\>, `S`\>\>
4
+
5
+ Defined in: [packages/fate/src/types.ts:300](https://github.com/nkzw-tech/fate/blob/d972c17c02c8292194208ab53c91f9216703a5a7/packages/fate/src/types.ts#L300)
6
+
7
+ ## Type Parameters
8
+
9
+ ### T
10
+
11
+ `T`
12
+
13
+ ### S
14
+
15
+ `S`
@@ -0,0 +1,21 @@
1
+ # Type Alias: MutationDefinition\<T, I, R\>
2
+
3
+ > **MutationDefinition**\<`T`, `I`, `R`\> = `Readonly`\<\{ `__fate__mutation`: `true`; `entity`: `T`\[`"__typename"`\]; \}\> & `__MutationEntityAnchor`\<`T`\> & `__MutationInputAnchor`\<`I`\> & `__MutationResultAnchor`\<`R`\>
4
+
5
+ Defined in: [packages/fate/src/types.ts:434](https://github.com/nkzw-tech/fate/blob/d972c17c02c8292194208ab53c91f9216703a5a7/packages/fate/src/types.ts#L434)
6
+
7
+ Metadata describing a mutation for a particular entity, input, and output.
8
+
9
+ ## Type Parameters
10
+
11
+ ### T
12
+
13
+ `T` *extends* [`Entity`](Entity.md)
14
+
15
+ ### I
16
+
17
+ `I`
18
+
19
+ ### R
20
+
21
+ `R`
@@ -0,0 +1,13 @@
1
+ # Type Alias: MutationEntity\<M\>
2
+
3
+ > **MutationEntity**\<`M`\> = `M` *extends* `__MutationEntityAnchor`\<infer E\> ? `E` : `never`
4
+
5
+ Defined in: [packages/fate/src/types.ts:452](https://github.com/nkzw-tech/fate/blob/d972c17c02c8292194208ab53c91f9216703a5a7/packages/fate/src/types.ts#L452)
6
+
7
+ Extracts the entity type from a mutation definition or identifier.
8
+
9
+ ## Type Parameters
10
+
11
+ ### M
12
+
13
+ `M`
@@ -0,0 +1,19 @@
1
+ # Type Alias: MutationIdentifier\<T, I, R\>
2
+
3
+ > **MutationIdentifier**\<`T`, `I`, `R`\> = [`MutationDefinition`](MutationDefinition.md)\<`T`, `I`, `R`\> & `Readonly`\<\{ `key`: `string`; \}\>
4
+
5
+ Defined in: [packages/fate/src/types.ts:442](https://github.com/nkzw-tech/fate/blob/d972c17c02c8292194208ab53c91f9216703a5a7/packages/fate/src/types.ts#L442)
6
+
7
+ ## Type Parameters
8
+
9
+ ### T
10
+
11
+ `T` *extends* [`Entity`](Entity.md)
12
+
13
+ ### I
14
+
15
+ `I`
16
+
17
+ ### R
18
+
19
+ `R`
@@ -0,0 +1,13 @@
1
+ # Type Alias: MutationInput\<M\>
2
+
3
+ > **MutationInput**\<`M`\> = `M` *extends* `__MutationInputAnchor`\<infer I\> ? `I` : `never`
4
+
5
+ Defined in: [packages/fate/src/types.ts:446](https://github.com/nkzw-tech/fate/blob/d972c17c02c8292194208ab53c91f9216703a5a7/packages/fate/src/types.ts#L446)
6
+
7
+ Extracts the input type from a mutation definition or identifier.
8
+
9
+ ## Type Parameters
10
+
11
+ ### M
12
+
13
+ `M`
@@ -0,0 +1,13 @@
1
+ # Type Alias: MutationResult\<M\>
2
+
3
+ > **MutationResult**\<`M`\> = `M` *extends* `__MutationResultAnchor`\<infer R\> ? `R` : `never`
4
+
5
+ Defined in: [packages/fate/src/types.ts:449](https://github.com/nkzw-tech/fate/blob/d972c17c02c8292194208ab53c91f9216703a5a7/packages/fate/src/types.ts#L449)
6
+
7
+ Extracts the result type from a mutation definition or identifier.
8
+
9
+ ## Type Parameters
10
+
11
+ ### M
12
+
13
+ `M`
@@ -0,0 +1,13 @@
1
+ # Type Alias: NodesItem\<V\>
2
+
3
+ > **NodesItem**\<`V`\> = `Readonly`\<\{ `ids`: `ReadonlyArray`\<`string` \| `number`\>; `view`: `V`; \}\>
4
+
5
+ Defined in: [packages/fate/src/types.ts:334](https://github.com/nkzw-tech/fate/blob/d972c17c02c8292194208ab53c91f9216703a5a7/packages/fate/src/types.ts#L334)
6
+
7
+ Definition of a node request with explicit IDs for fetching data from the backend.
8
+
9
+ ## Type Parameters
10
+
11
+ ### V
12
+
13
+ `V` *extends* [`View`](View.md)\<`any`, `any`\>
@@ -0,0 +1,39 @@
1
+ # Type Alias: Pagination
2
+
3
+ > **Pagination** = `object`
4
+
5
+ Defined in: [packages/fate/src/types.ts:124](https://github.com/nkzw-tech/fate/blob/d972c17c02c8292194208ab53c91f9216703a5a7/packages/fate/src/types.ts#L124)
6
+
7
+ Pagination state returned alongside connection lists.
8
+
9
+ ## Properties
10
+
11
+ ### hasNext
12
+
13
+ > **hasNext**: `boolean`
14
+
15
+ Defined in: [packages/fate/src/types.ts:125](https://github.com/nkzw-tech/fate/blob/d972c17c02c8292194208ab53c91f9216703a5a7/packages/fate/src/types.ts#L125)
16
+
17
+ ***
18
+
19
+ ### hasPrevious
20
+
21
+ > **hasPrevious**: `boolean`
22
+
23
+ Defined in: [packages/fate/src/types.ts:126](https://github.com/nkzw-tech/fate/blob/d972c17c02c8292194208ab53c91f9216703a5a7/packages/fate/src/types.ts#L126)
24
+
25
+ ***
26
+
27
+ ### nextCursor?
28
+
29
+ > `optional` **nextCursor?**: `string`
30
+
31
+ Defined in: [packages/fate/src/types.ts:127](https://github.com/nkzw-tech/fate/blob/d972c17c02c8292194208ab53c91f9216703a5a7/packages/fate/src/types.ts#L127)
32
+
33
+ ***
34
+
35
+ ### previousCursor?
36
+
37
+ > `optional` **previousCursor?**: `string`
38
+
39
+ Defined in: [packages/fate/src/types.ts:128](https://github.com/nkzw-tech/fate/blob/d972c17c02c8292194208ab53c91f9216703a5a7/packages/fate/src/types.ts#L128)
@@ -0,0 +1,7 @@
1
+ # Type Alias: Request
2
+
3
+ > **Request** = `Record`\<`string`, `RequestItem`\>
4
+
5
+ Defined in: [packages/fate/src/types.ts:346](https://github.com/nkzw-tech/fate/blob/d972c17c02c8292194208ab53c91f9216703a5a7/packages/fate/src/types.ts#L346)
6
+
7
+ Collection of node and list requests describing the data a screen needs.
@@ -0,0 +1,7 @@
1
+ # Type Alias: RequestMode
2
+
3
+ > **RequestMode** = `"cache-first"` \| `"stale-while-revalidate"` \| `"network-only"`
4
+
5
+ Defined in: [packages/fate/src/client.ts:73](https://github.com/nkzw-tech/fate/blob/d972c17c02c8292194208ab53c91f9216703a5a7/packages/fate/src/client.ts#L73)
6
+
7
+ Strategy used when resolving a request.
@@ -0,0 +1,7 @@
1
+ # Type Alias: RequestOptions
2
+
3
+ > **RequestOptions** = `Readonly`\<\{ `mode?`: [`RequestMode`](RequestMode.md); \}\>
4
+
5
+ Defined in: [packages/fate/src/client.ts:84](https://github.com/nkzw-tech/fate/blob/d972c17c02c8292194208ab53c91f9216703a5a7/packages/fate/src/client.ts#L84)
6
+
7
+ Request options that affect how requests are fetched and retained.
@@ -0,0 +1,18 @@
1
+ # Type Alias: RequestResult\<R, Q\>
2
+
3
+ > **RequestResult**\<`R`, `Q`\> = `{ [K in keyof Q]: K extends keyof R ? ListResult<Q[K], RootType<R[K]>, RootResult<R[K]>> : never }`
4
+
5
+ Defined in: [packages/fate/src/types.ts:392](https://github.com/nkzw-tech/fate/blob/d972c17c02c8292194208ab53c91f9216703a5a7/packages/fate/src/types.ts#L392)
6
+
7
+ The result of a `FateClient.request` and `useRequest` call, mapping each
8
+ request key to its corresponding result.
9
+
10
+ ## Type Parameters
11
+
12
+ ### R
13
+
14
+ `R` *extends* [`FateRoots`](FateRoots.md)
15
+
16
+ ### Q
17
+
18
+ `Q` *extends* `AnyRequest`
@@ -0,0 +1,13 @@
1
+ # Type Alias: Selection\<T\>
2
+
3
+ > **Selection**\<`T`\> = `SelectionShape`\<`T`\> & `SelectionViewSpread`\<`T`\>
4
+
5
+ Defined in: [packages/fate/src/types.ts:199](https://github.com/nkzw-tech/fate/blob/d972c17c02c8292194208ab53c91f9216703a5a7/packages/fate/src/types.ts#L199)
6
+
7
+ Declarative selection of the fields a view needs from an entity.
8
+
9
+ ## Type Parameters
10
+
11
+ ### T
12
+
13
+ `T` *extends* [`Entity`](Entity.md)
@@ -0,0 +1,7 @@
1
+ # Type Alias: Snapshot
2
+
3
+ > **Snapshot** = `Readonly`\<\{ `mask?`: `FieldMask`; `record?`: [`FateRecord`](FateRecord.md); \}\>
4
+
5
+ Defined in: [packages/fate/src/types.ts:481](https://github.com/nkzw-tech/fate/blob/d972c17c02c8292194208ab53c91f9216703a5a7/packages/fate/src/types.ts#L481)
6
+
7
+ Snapshot captured before mutating the cache, used to roll back on errors.
@@ -0,0 +1,41 @@
1
+ # Type Alias: TypeConfig
2
+
3
+ > **TypeConfig** = `object`
4
+
5
+ Defined in: [packages/fate/src/types.ts:117](https://github.com/nkzw-tech/fate/blob/d972c17c02c8292194208ab53c91f9216703a5a7/packages/fate/src/types.ts#L117)
6
+
7
+ Configuration for a server entity type used by the client cache.
8
+
9
+ ## Properties
10
+
11
+ ### fields?
12
+
13
+ > `optional` **fields?**: `Record`\<`string`, `RelationDescriptor`\>
14
+
15
+ Defined in: [packages/fate/src/types.ts:118](https://github.com/nkzw-tech/fate/blob/d972c17c02c8292194208ab53c91f9216703a5a7/packages/fate/src/types.ts#L118)
16
+
17
+ ***
18
+
19
+ ### getId
20
+
21
+ > **getId**: (`record`) => `string` \| `number`
22
+
23
+ Defined in: [packages/fate/src/types.ts:119](https://github.com/nkzw-tech/fate/blob/d972c17c02c8292194208ab53c91f9216703a5a7/packages/fate/src/types.ts#L119)
24
+
25
+ #### Parameters
26
+
27
+ ##### record
28
+
29
+ `unknown`
30
+
31
+ #### Returns
32
+
33
+ `string` \| `number`
34
+
35
+ ***
36
+
37
+ ### type
38
+
39
+ > **type**: `string`
40
+
41
+ Defined in: [packages/fate/src/types.ts:120](https://github.com/nkzw-tech/fate/blob/d972c17c02c8292194208ab53c91f9216703a5a7/packages/fate/src/types.ts#L120)
@@ -0,0 +1,17 @@
1
+ # Type Alias: View\<T, S\>
2
+
3
+ > **View**\<`T`, `S`\> = `Readonly`\<\{\[`viewTag`: `` `__fate-view__${string}` ``\]: `Readonly`\<\{ `[ViewKind]`: `true`; `select`: `S`; \}\>; \}\> & `__ViewEntityAnchor`\<`T`\> & `__ViewSelectionAnchor`\<`S`\>
4
+
5
+ Defined in: [packages/fate/src/types.ts:215](https://github.com/nkzw-tech/fate/blob/d972c17c02c8292194208ab53c91f9216703a5a7/packages/fate/src/types.ts#L215)
6
+
7
+ Definition of a view over an entity type, including the selection of fields.
8
+
9
+ ## Type Parameters
10
+
11
+ ### T
12
+
13
+ `T` *extends* [`Entity`](Entity.md)
14
+
15
+ ### S
16
+
17
+ `S` *extends* [`Selection`](Selection.md)\<`T`\> = [`Selection`](Selection.md)\<`T`\>
@@ -0,0 +1,18 @@
1
+ # Type Alias: ViewData\<T, S\>
2
+
3
+ > **ViewData**\<`T`, `S`\> = `Readonly`\<`S` *extends* [`Selection`](Selection.md)\<`T`\> ? [`Mask`](Mask.md)\<`T`, `S`\> : `T` & `object`\>
4
+
5
+ Defined in: [packages/fate/src/types.ts:231](https://github.com/nkzw-tech/fate/blob/d972c17c02c8292194208ab53c91f9216703a5a7/packages/fate/src/types.ts#L231)
6
+
7
+ Data returned from a resolved view with masking applied and view tags
8
+ attached for downstream composition.
9
+
10
+ ## Type Parameters
11
+
12
+ ### T
13
+
14
+ `T` *extends* [`Entity`](Entity.md)
15
+
16
+ ### S
17
+
18
+ `S` *extends* [`Selection`](Selection.md)\<`T`\>
@@ -0,0 +1,13 @@
1
+ # Type Alias: ViewEntity\<V\>
2
+
3
+ > **ViewEntity**\<`V`\> = `V` *extends* [`View`](View.md)\<infer T, `any`\> ? `T` : `never`
4
+
5
+ Defined in: [packages/fate/src/types.ts:303](https://github.com/nkzw-tech/fate/blob/d972c17c02c8292194208ab53c91f9216703a5a7/packages/fate/src/types.ts#L303)
6
+
7
+ Entity type captured from a view definition.
8
+
9
+ ## Type Parameters
10
+
11
+ ### V
12
+
13
+ `V`
@@ -0,0 +1,13 @@
1
+ # Type Alias: ViewEntityName\<V\>
2
+
3
+ > **ViewEntityName**\<`V`\> = [`ViewEntity`](ViewEntity.md)\<`V`\>\[`"__typename"`\] & `string`
4
+
5
+ Defined in: [packages/fate/src/types.ts:306](https://github.com/nkzw-tech/fate/blob/d972c17c02c8292194208ab53c91f9216703a5a7/packages/fate/src/types.ts#L306)
6
+
7
+ Name of the entity type captured from a view definition.
8
+
9
+ ## Type Parameters
10
+
11
+ ### V
12
+
13
+ `V`
@@ -0,0 +1,13 @@
1
+ # Type Alias: ViewRef\<TName\>
2
+
3
+ > **ViewRef**\<`TName`\> = `Readonly`\<\{ `__typename`: `TName`; `[ViewsTag]`: `Set`\<`string`\>; `id`: `string` \| `number`; \}\>
4
+
5
+ Defined in: [packages/fate/src/types.ts:101](https://github.com/nkzw-tech/fate/blob/d972c17c02c8292194208ab53c91f9216703a5a7/packages/fate/src/types.ts#L101)
6
+
7
+ Reference to a normalized entity instance that can be resolved against one or more view tags.
8
+
9
+ ## Type Parameters
10
+
11
+ ### TName
12
+
13
+ `TName` *extends* `string`
@@ -0,0 +1,13 @@
1
+ # Type Alias: ViewSelection\<V\>
2
+
3
+ > **ViewSelection**\<`V`\> = `V` *extends* `object` ? `S` : `never`
4
+
5
+ Defined in: [packages/fate/src/types.ts:309](https://github.com/nkzw-tech/fate/blob/d972c17c02c8292194208ab53c91f9216703a5a7/packages/fate/src/types.ts#L309)
6
+
7
+ Selection captured from a view definition.
8
+
9
+ ## Type Parameters
10
+
11
+ ### V
12
+
13
+ `V`
@@ -0,0 +1,18 @@
1
+ # Type Alias: ViewSnapshot\<T, S\>
2
+
3
+ > **ViewSnapshot**\<`T`, `S`\> = `Readonly`\<\{ `coverage`: `ReadonlyArray`\<readonly \[[`EntityId`](EntityId.md), `ReadonlySet`\<`string`\>\]\>; `data`: [`ViewData`](ViewData.md)\<`T`, `S`\>; \}\>
4
+
5
+ Defined in: [packages/fate/src/types.ts:241](https://github.com/nkzw-tech/fate/blob/d972c17c02c8292194208ab53c91f9216703a5a7/packages/fate/src/types.ts#L241)
6
+
7
+ Snapshot returned by the cache for a view, including the masked data and all
8
+ referenced entity IDs.
9
+
10
+ ## Type Parameters
11
+
12
+ ### T
13
+
14
+ `T` *extends* [`Entity`](Entity.md)
15
+
16
+ ### S
17
+
18
+ `S` *extends* [`Selection`](Selection.md)\<`T`\>
@@ -0,0 +1,7 @@
1
+ # Type Alias: ViewTag
2
+
3
+ > **ViewTag** = `` `__fate-view__${string}` ``
4
+
5
+ Defined in: [packages/fate/src/types.ts:49](https://github.com/nkzw-tech/fate/blob/d972c17c02c8292194208ab53c91f9216703a5a7/packages/fate/src/types.ts#L49)
6
+
7
+ Unique key that identifies a view composition entry inside a selection or reference.
@@ -0,0 +1,7 @@
1
+ # Variable: ConnectionTag
2
+
3
+ > `const` **ConnectionTag**: *typeof* `ConnectionTag`
4
+
5
+ Defined in: [packages/fate/src/types.ts:20](https://github.com/nkzw-tech/fate/blob/d972c17c02c8292194208ab53c91f9216703a5a7/packages/fate/src/types.ts#L20)
6
+
7
+ Symbol attached to connection results so pagination helpers can find their metadata.
@@ -0,0 +1,263 @@
1
+ # Actions
2
+
3
+ fate does not provide hooks for mutations like traditional data fetching libraries do. Instead, mutations are exposed in two ways:
4
+
5
+ - `fate.actions` for use with [`useActionState`](https://react.dev/reference/react/useActionState) and React Actions.
6
+ - `fate.mutations` for traditional imperative mutation calls.
7
+
8
+ Mutations in your tRPC backend are made available as actions and mutations by fate's generated client.
9
+
10
+ Let's assume that our `Post` entity has a tRPC mutation for liking a post called `post.like`. A `LikeButton` component using fate Actions and an async component library could then look like this:
11
+
12
+ ```tsx
13
+ import { useActionState } from 'react';
14
+ import { useFateClient } from 'react-fate';
15
+
16
+ const LikeButton = ({ post }: { post: { id: string; likes: number } }) => {
17
+ const fate = useFateClient();
18
+ const [result, like] = useActionState(fate.actions.post.like, null);
19
+
20
+ return (
21
+ <Button action={() => like({ input: { id: post.id } })}>
22
+ {result?.error ? 'Oops!' : 'Like'}
23
+ </Button>
24
+ );
25
+ };
26
+ ```
27
+
28
+ If you are not using an async component library, you can use React's `useTransition` to start the action in a transition:
29
+
30
+ ```tsx
31
+ const LikeButton = ({ post }: { post: { id: string; likes: number } }) => {
32
+ const fate = useFateClient();
33
+ const [, startTransition] = useTransition();
34
+ const [result, like, isPending] = useActionState(fate.actions.post.like, null);
35
+
36
+ return (
37
+ <button
38
+ disabled={isPending}
39
+ onClick={() => {
40
+ startTransition(() =>
41
+ like({
42
+ input: { id: post.id },
43
+ }),
44
+ );
45
+ }}
46
+ >
47
+ {result?.error ? 'Oops!' : 'Like'}
48
+ </button>
49
+ );
50
+ };
51
+ ```
52
+
53
+ By using `useActionState`, fate Actions integrate with Suspense and concurrent rendering.
54
+
55
+ ## Optimistic Updates
56
+
57
+ fate Actions support optimistic updates out of the box. For example, to update the post's like count optimistically, you can pass an `optimistic` object to the action call. This will immediately update the cache with the new like count and re-render all views that select the `likes` field:
58
+
59
+ ```tsx
60
+ like({
61
+ input: { id: post.id },
62
+ optimistic: { likes: post.likes + 1 },
63
+ });
64
+ ```
65
+
66
+ When data changes through optimistic updates or otherwise, fate only re-renders the views that select the changed fields. In the above example, only views that select the `likes` field will re-render. If a view only selects the `title` field, it won't re-render when the `likes` field changes.
67
+
68
+ If a mutation fails, the cache will be rolled back to its previous state and any views depending on the mutated data will be updated.
69
+
70
+ ## Inserting New Objects
71
+
72
+ When a mutation inserts a new object, you can provide an optimistic object with a temporary ID to represent the new object in the cache until the server responds with the actual ID. For example, to add a new comment to a post optimistically, you can do the following:
73
+
74
+ ```tsx
75
+ const content = 'New Comment text';
76
+ addComment({
77
+ input: { content, postId: post.id },
78
+ optimistic: {
79
+ author: { id: user.id, name: user.name },
80
+ content,
81
+ id: `optimistic:${Date.now().toString(36)}`,
82
+ post: { commentCount: post.commentCount + 1, id: post.id },
83
+ },
84
+ });
85
+ ```
86
+
87
+ By default, fate inserts new records after existing items in matching root lists and nested lists. For a newest-first list, pass `insert: 'before'` so optimistic records appear at the beginning:
88
+
89
+ ```tsx
90
+ addComment({
91
+ input: { content, postId: post.id },
92
+ insert: 'before',
93
+ optimistic: {
94
+ content,
95
+ id: `optimistic:${Date.now().toString(36)}`,
96
+ post: { id: post.id },
97
+ },
98
+ });
99
+ ```
100
+
101
+ Insertion respects pagination boundaries. If you append to a list that still has a next page, fate keeps the new record attached to the unresolved trailing edge instead of mixing it into the loaded page. As you load more pages, the inserted record stays at the end until the server returns the canonical item or the list reaches the edge. The same behavior applies to prepends while `hasPrevious` is true.
102
+
103
+ Multiple pending optimistic inserts keep their visible order. For example, two `insert: 'before'` calls on a newest-first feed show the second optimistic item before the first, matching what users expect from newly created content.
104
+
105
+ ## Selecting a View with Actions
106
+
107
+ Mutations may change data that is not directly specified in the mutation result. For example, adding a comment increases the post's comment count. For such cases, you can provide a `view` to an action that specifies which fields to fetch as part of the mutation:
108
+
109
+ ```tsx
110
+ addComment({
111
+ input: { content: 'New Comment text', postId: post.id },
112
+ view: view<Comment>()({
113
+ ...CommentView,
114
+ post: { commentCount: true },
115
+ }),
116
+ });
117
+ ```
118
+
119
+ The server will return the selected fields and fate updates the cache and re-renders all views that depend on the changed data. The action result contains the newly added comment with the selected fields:
120
+
121
+ ```tsx
122
+ const [result, addComment] = useActionState(fate.actions.comment.add, null);
123
+
124
+ const newComment = result?.result;
125
+ if (newComment) {
126
+ // All the fields selected in the view are available on `newComment`:
127
+ console.log(newComment.post.commentCount);
128
+ }
129
+ ```
130
+
131
+ ## Mutations
132
+
133
+ fate Actions are the recommended way to execute server mutations in React components. However, there are cases where you might want to call mutations imperatively, outside of React components, or without waiting for previous actions to finish like `useActionState` does. For such cases, you can use `fate.mutations` to call mutations imperatively:
134
+
135
+ ```tsx
136
+ const result = await fate.mutations.comment.add({
137
+ input: { content, postId: post.id },
138
+ });
139
+ ```
140
+
141
+ You can call mutations from anywhere, and without waiting for previous mutations to finish. The mutation API matches the API of fate Actions, including optimistic updates and view selection. With mutations, you'll need to handle loading states and errors manually, and the result is returned as a promise.
142
+
143
+ ## Mutation Server Implementation
144
+
145
+ fate Actions & Mutations are backed by regular tRPC mutations on the server. Here is an example implementation of the `like` mutation in the `postRouter`.
146
+
147
+ ```tsx
148
+ import { z } from 'zod';
149
+ import { connectionArgs, createResolver } from '@nkzw/fate/server';
150
+ import { procedure, router } from '../init.ts';
151
+ import { postDataView, PostItem } from '../views.ts';
152
+
153
+ export const postRouter = router({
154
+ like: procedure
155
+ .input(
156
+ z.object({
157
+ args: connectionArgs,
158
+ id: z.string().min(1, 'Post id is required.'),
159
+ select: z.array(z.string()),
160
+ }),
161
+ )
162
+ .mutation(async ({ ctx, input }) => {
163
+ const { resolve, select } = createResolver({
164
+ ...input,
165
+ ctx,
166
+ view: postDataView,
167
+ });
168
+
169
+ return resolve(
170
+ await ctx.prisma.post.update({
171
+ data: {
172
+ likes: {
173
+ increment: 1,
174
+ },
175
+ },
176
+ select,
177
+ where: { id: input.id },
178
+ } as PostUpdateArgs),
179
+ );
180
+ }),
181
+ });
182
+ ```
183
+
184
+ See the [Server Integration](#server-integration) section for more details on how to integrate tRPC routers with fate.
185
+
186
+ ## Action & Mutation Error Handling
187
+
188
+ fate Actions & Mutations separate error handling into two scopes: "call site" and "boundary". Call site errors are expected to be handled at the location where the action or mutation is called. Boundary errors are unexpected errors that should be handled by a higher-level error boundary.
189
+
190
+ If your server returns a `NOT_FOUND` error with code `404`, the result of an Action or Mutation will contain an error object that you can handle at the call site:
191
+
192
+ ```tsx
193
+ const [result] = useActionState(fate.actions.post.delete, null);
194
+
195
+ if (result?.error) {
196
+ if (result.error.code === 'NOT_FOUND') {
197
+ // Handle not found error at call site.
198
+ } else {
199
+ // Handle other *expected* errors.
200
+ }
201
+ }
202
+ ```
203
+
204
+ However, if an `INTERNAL_SERVER_ERROR` error with code `500` occurs, it will be thrown and can be caught by the nearest React error boundary:
205
+
206
+ ```tsx
207
+ <ErrorBoundary FallbackComponent={ErrorComponent}>
208
+ <Suspense fallback={<div>Loading…</div>}>
209
+ <PostPage postId={postId} />
210
+ </Suspense>
211
+ </ErrorBoundary>
212
+ ```
213
+
214
+ You can find the error classification behavior in [`mutation.ts`](https://github.com/nkzw-tech/fate/blob/main/packages/fate/src/mutation.ts#L227-L254).
215
+
216
+ ## Deleting Records
217
+
218
+ When you want to delete a record using fate Actions, you can pass a `delete: true` flag to the action call. This flag removes the object from the cache and re-renders all views that depend on the deleted data:
219
+
220
+ ```tsx
221
+ const [result, deleteAction] = useActionState(fate.actions.post.delete, null);
222
+
223
+ deleteAction({
224
+ input: { id: post.id },
225
+ delete: true,
226
+ });
227
+ ```
228
+
229
+ ## Resetting Action State
230
+
231
+ When using `useActionState`, the result of the action is cached until the component using the action is unmounted. When a mutation fails with an error, you might want to clear the error state without invoking the action again. fate Actions take a `'reset'` token to reset the action state:
232
+
233
+ ```tsx
234
+ const [result, like] = useActionState(fate.actions.post.like, null);
235
+
236
+ useEffect(() => {
237
+ if (result?.error) {
238
+ // Reset the action state after 3 seconds.
239
+ const timeout = setTimeout(() => startTransition(() => like('reset')), 3000);
240
+ return () => clearTimeout(timeout);
241
+ }
242
+ }, [like, result]);
243
+ ```
244
+
245
+ ## Controlling List Insertion Behavior
246
+
247
+ When inserting new objects into lists, the default behavior is to append the new object to the list. You can provide an `insert` option with `before`, `after` or `none` values to customize this behavior and specify where the new object should be inserted in the list:
248
+
249
+ ```tsx
250
+ addComment({
251
+ input: { content: 'New Comment text', postId: post.id },
252
+ insert: 'before', // Insert the new comment at the beginning of the list.
253
+ });
254
+ ```
255
+
256
+ Or, use the `none` option if you want to ignore inserting the new object into any lists:
257
+
258
+ ```tsx
259
+ addComment({
260
+ input: { content: 'New Comment text', postId: post.id },
261
+ insert: 'none', // Do not insert the new comment into any lists.
262
+ });
263
+ ```