@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
@@ -0,0 +1,44 @@
1
+ //#region src/protocol.ts
2
+ var FateRequestError = class extends Error {
3
+ constructor(code, message, options = {}) {
4
+ super(message);
5
+ this.name = "FateRequestError";
6
+ this.code = code;
7
+ this.issues = options.issues;
8
+ this.status = options.status ?? statusFromErrorCode(code);
9
+ }
10
+ };
11
+ const statusFromErrorCode = (code) => {
12
+ switch (code) {
13
+ case "BAD_REQUEST":
14
+ case "VALIDATION_ERROR": return 400;
15
+ case "UNAUTHORIZED": return 401;
16
+ case "FORBIDDEN": return 403;
17
+ case "NOT_FOUND": return 404;
18
+ case "INTERNAL_ERROR": return 500;
19
+ }
20
+ };
21
+ const errorCodeFromStatus = (status) => {
22
+ if (status === 400) return "BAD_REQUEST";
23
+ if (status === 401) return "UNAUTHORIZED";
24
+ if (status === 403) return "FORBIDDEN";
25
+ if (status === 404) return "NOT_FOUND";
26
+ return "INTERNAL_ERROR";
27
+ };
28
+ const toProtocolError = (error) => {
29
+ if (error instanceof FateRequestError) return {
30
+ code: error.code,
31
+ issues: error.issues,
32
+ message: error.message
33
+ };
34
+ if (error instanceof Error) return {
35
+ code: "INTERNAL_ERROR",
36
+ message: "Internal server error."
37
+ };
38
+ return {
39
+ code: "INTERNAL_ERROR",
40
+ message: "Internal server error."
41
+ };
42
+ };
43
+ //#endregion
44
+ export { errorCodeFromStatus as n, toProtocolError as r, FateRequestError as t };
@@ -1,5 +1,6 @@
1
- import { r as AnyRecord } from "./transport-Bo1Jgo9R.mjs";
2
- import { N as DataViewResult, S as ConnectionResult, k as DataView, l as SourceDefinition, t as SourceRegistry } from "./executor-BRudKWDY.mjs";
1
+ import { r as MutationIdentity, v as AnyRecord } from "./transport-DqjhjLfC.mjs";
2
+ import { t as MutationIdempotency } from "./idempotency-types-CqA-BFpn.mjs";
3
+ import { N as DataViewResult, S as ConnectionResult, k as DataView, l as SourceDefinition, t as SourceRegistry } from "./executor-DoiTBiVv.mjs";
3
4
  //#region src/liveTopics.d.ts
4
5
  declare const liveEntityTopic: (type: string, id: string | number) => string;
5
6
  declare const liveConnectionTopic: (procedure: string, args?: Record<string, unknown>) => string;
@@ -153,6 +154,7 @@ type ContextOptions<AdapterContext> = {
153
154
  };
154
155
  type FateServerOptions<Context, Roots extends RootMap, Queries extends Record<string, QueryDefinition<Context, any, any>>, Lists extends Record<string, ListDefinition<Context, any, any>>, Mutations extends Record<string, MutationDefinition<Context, any, any>>, AdapterContext> = {
155
156
  context?: (options: ContextOptions<AdapterContext>) => MaybePromise<Context>;
157
+ idempotency?: MutationIdempotency<Context>;
156
158
  lists?: Lists;
157
159
  live?: false | LiveConfig;
158
160
  mutations?: Mutations;
@@ -219,7 +221,7 @@ type FateServerManifest = Readonly<{
219
221
  }>;
220
222
  types: Record<string, true>;
221
223
  }>;
222
- declare function createFateServer<Context = unknown, Roots extends RootMap = RootMap, Queries extends Record<string, QueryDefinition<Context, any, any>> = Record<never, never>, Lists extends Record<string, ListDefinition<Context, any, any>> = Record<never, never>, Mutations extends Record<string, MutationDefinition<Context, any, any>> = Record<never, never>, AdapterContext = unknown>({ context, lists, live, mutations, queries, roots, sources }: FateServerOptions<Context, Roots, Queries, Lists, Mutations, AdapterContext>): FateServer<NativeFateAPI<Roots, Queries, Lists, Mutations>, AdapterContext>;
224
+ declare function createFateServer<Context = unknown, Roots extends RootMap = RootMap, Queries extends Record<string, QueryDefinition<Context, any, any>> = Record<never, never>, Lists extends Record<string, ListDefinition<Context, any, any>> = Record<never, never>, Mutations extends Record<string, MutationDefinition<Context, any, any>> = Record<never, never>, AdapterContext = unknown>({ context, idempotency, lists, live, mutations, queries, roots, sources }: FateServerOptions<Context, Roots, Queries, Lists, Mutations, AdapterContext>): FateServer<NativeFateAPI<Roots, Queries, Lists, Mutations>, AdapterContext>;
223
225
  declare function createFateFetchHandler<AdapterContext>(server: FateServer<unknown, AdapterContext>): (request: Request, adapterContext?: AdapterContext) => Promise<Response>;
224
226
  declare function createHonoFateHandler<Context>(server: FateServer<unknown, Context>): (context: Context & {
225
227
  req: {
@@ -228,7 +230,8 @@ declare function createHonoFateHandler<Context>(server: FateServer<unknown, Cont
228
230
  }) => Promise<Response>;
229
231
  //#endregion
230
232
  //#region src/protocol.d.ts
231
- type FateProtocolVersion = 1;
233
+ /** Version 2 requires support for durable mutation identities and receipt-only recovery. */
234
+ type FateProtocolVersion = 1 | 2;
232
235
  type FateOperationKind = 'byId' | 'list' | 'mutation' | 'query';
233
236
  type FateOperation = Readonly<{
234
237
  args?: Record<string, unknown>;
@@ -236,6 +239,7 @@ type FateOperation = Readonly<{
236
239
  ids?: Array<string | number>;
237
240
  input?: unknown;
238
241
  kind: FateOperationKind;
242
+ mutation?: MutationIdentity;
239
243
  name?: string;
240
244
  select: Array<string>;
241
245
  type?: string;
@@ -1,5 +1,5 @@
1
- import { nt as QueryProcedure, r as AnyRecord } from "../transport-Bo1Jgo9R.mjs";
2
- import { S as ConnectionResult, c as SourceConfig, f as SourcePlan, k as DataView, l as SourceDefinition, o as DataViewModule, p as SourcePlanNode, t as SourceRegistry } from "../executor-BRudKWDY.mjs";
1
+ import { st as QueryProcedure, v as AnyRecord } from "../transport-DqjhjLfC.mjs";
2
+ import { S as ConnectionResult, c as SourceConfig, f as SourcePlan, k as DataView, l as SourceDefinition, o as DataViewModule, p as SourcePlanNode, t as SourceRegistry } from "../executor-DoiTBiVv.mjs";
3
3
  import { AnyColumn, SQLWrapper, Table } from "drizzle-orm";
4
4
  //#region src/server/drizzle.d.ts
5
5
  type SourceTarget<Item extends AnyRecord = AnyRecord> = DataView<Item> | SourceDefinition<Item, unknown>;
@@ -1,5 +1,5 @@
1
1
  import { t as isRecord } from "../record-B07VwXd-.mjs";
2
- import { O as withConnection, S as isDataView, c as resolveSourceConnection, d as createSourceDefinitions, f as createSourcePlan, g as attachComputedState, i as createSourceRegistry, l as collectDataViewConfigs, o as resolveSourceById, p as getDataViewSourceConfig, s as resolveSourceByIds, t as bindSourceProcedures } from "../sourceRouter-DSaADXSf.mjs";
2
+ import { S as isDataView, c as resolveSourceConnection, d as createSourceDefinitions, f as createSourcePlan, g as attachComputedState, i as createSourceRegistry, k as withConnection, l as collectDataViewConfigs, o as resolveSourceById, p as getDataViewSourceConfig, s as resolveSourceByIds, t as bindSourceProcedures } from "../sourceRouter-51POBlEE.mjs";
3
3
  import { Many, and, asc, createTableRelationsHelpers, desc, eq, extractTablesRelationalConfig, getTableColumns, gt, inArray, is, isTable, lt, normalizeRelation, or, sql } from "drizzle-orm";
4
4
  //#region src/server/drizzle.ts
5
5
  /**
@@ -1,5 +1,5 @@
1
- import { nt as QueryProcedure, r as AnyRecord } from "../transport-Bo1Jgo9R.mjs";
2
- import { S as ConnectionResult, c as SourceConfig, f as SourcePlan, k as DataView, l as SourceDefinition, o as DataViewModule, p as SourcePlanNode, s as OrderDirection, t as SourceRegistry } from "../executor-BRudKWDY.mjs";
1
+ import { st as QueryProcedure, v as AnyRecord } from "../transport-DqjhjLfC.mjs";
2
+ import { S as ConnectionResult, c as SourceConfig, f as SourcePlan, k as DataView, l as SourceDefinition, o as DataViewModule, p as SourcePlanNode, s as OrderDirection, t as SourceRegistry } from "../executor-DoiTBiVv.mjs";
3
3
  //#region src/server/prisma.d.ts
4
4
  type PrismaDelegate = {
5
5
  findMany?: (args: any) => Promise<Array<AnyRecord>>;
@@ -1,5 +1,5 @@
1
1
  import { t as isRecord } from "../record-B07VwXd-.mjs";
2
- import { O as withConnection, S as isDataView, T as toPrismaSelect, c as resolveSourceConnection, d as createSourceDefinitions, f as createSourcePlan, g as attachComputedState, i as createSourceRegistry, l as collectDataViewConfigs, o as resolveSourceById, p as getDataViewSourceConfig, s as resolveSourceByIds, t as bindSourceProcedures } from "../sourceRouter-DSaADXSf.mjs";
2
+ import { E as stableStringify, S as isDataView, T as toPrismaSelect, c as resolveSourceConnection, d as createSourceDefinitions, f as createSourcePlan, g as attachComputedState, i as createSourceRegistry, k as withConnection, l as collectDataViewConfigs, o as resolveSourceById, p as getDataViewSourceConfig, s as resolveSourceByIds, t as bindSourceProcedures } from "../sourceRouter-51POBlEE.mjs";
3
3
  //#region src/server/prisma.ts
4
4
  /**
5
5
  * fate's Prisma integration.
@@ -50,11 +50,6 @@ const inferPrismaRelation = ({ field, kind, source, target }) => {
50
50
  localKey: source.id
51
51
  };
52
52
  };
53
- const stableStringify = (value) => {
54
- if (Array.isArray(value)) return `[${value.map((entry) => stableStringify(entry)).join(",")}]`;
55
- if (isRecord(value)) return `{${Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, entry]) => `${JSON.stringify(key)}:${stableStringify(entry)}`).join(",")}}`;
56
- return JSON.stringify(value);
57
- };
58
53
  const resolveSourceReference = (source) => typeof source === "function" ? source() : source;
59
54
  const isSourceDefinition = (target) => "view" in target && "id" in target;
60
55
  const toPrismaOrderBy = (orderBy) => orderBy.map((entry) => ({ [entry.field]: entry.direction }));
package/lib/server.d.mts CHANGED
@@ -1,6 +1,6 @@
1
- import { r as AnyRecord$1, tt as AnyProcedure } from "./transport-Bo1Jgo9R.mjs";
2
- import { C as liveGlobalConnectionTopic, S as liveEntityTopic, _ as LiveEventBus, b as createLiveEventBus, c as FateServer, d as NativeFateAPI, f as createFateFetchHandler, g as LiveConnectionSourceEvent, h as LiveConnectionEventType, l as FateServerManifest, m as createHonoFateHandler, p as createFateServer, s as FateRequestError, t as isRecord, u as InferFateAPI, v as LiveEventType, x as liveConnectionTopic, y as LiveSourceEvent } from "./record-BTUXkHQU.mjs";
3
- import { A as DataViewListOptions, B as dataView, C as connectionArgs, D as CountSelection, E as ComputedSelection, F as FieldSelection, H as list$1, I as ViewPlan, L as computed, M as DataViewOrderDirection, N as DataViewResult, O as CountWhere, P as Entity, R as count, S as ConnectionResult, T as ComputedField, U as resolver, V as field, _ as createSourcePlan, a as resolveSourceConnection, b as ConnectionItem, c as SourceConfig, d as SourceOrderField, f as SourcePlan, g as createNestedSourcePlan, h as SourceRelationConfig, i as resolveSourceByIds, j as DataViewOrderBy, l as SourceDefinition, m as SourceRelation, n as refetchSourceById, p as SourcePlanNode, r as resolveSourceById, s as OrderDirection, t as SourceRegistry, u as SourceOrder, v as getNestedSelection, w as withConnection, x as ConnectionPagination, y as hasNestedSelection, z as createResolver } from "./executor-BRudKWDY.mjs";
1
+ import { ot as AnyProcedure, v as AnyRecord$1 } from "./transport-DqjhjLfC.mjs";
2
+ import { C as liveGlobalConnectionTopic, S as liveEntityTopic, _ as LiveEventBus, b as createLiveEventBus, c as FateServer, d as NativeFateAPI, f as createFateFetchHandler, g as LiveConnectionSourceEvent, h as LiveConnectionEventType, l as FateServerManifest, m as createHonoFateHandler, p as createFateServer, s as FateRequestError, t as isRecord, u as InferFateAPI, v as LiveEventType, x as liveConnectionTopic, y as LiveSourceEvent } from "./record-DITM4zb_.mjs";
3
+ import { A as DataViewListOptions, B as dataView, C as connectionArgs, D as CountSelection, E as ComputedSelection, F as FieldSelection, H as list$1, I as ViewPlan, L as computed, M as DataViewOrderDirection, N as DataViewResult, O as CountWhere, P as Entity, R as count, S as ConnectionResult, T as ComputedField, U as resolver, V as field, _ as createSourcePlan, a as resolveSourceConnection, b as ConnectionItem, c as SourceConfig, d as SourceOrderField, f as SourcePlan, g as createNestedSourcePlan, h as SourceRelationConfig, i as resolveSourceByIds, j as DataViewOrderBy, l as SourceDefinition, m as SourceRelation, n as refetchSourceById, p as SourcePlanNode, r as resolveSourceById, s as OrderDirection, t as SourceRegistry, u as SourceOrder, v as getNestedSelection, w as withConnection, x as ConnectionPagination, y as hasNestedSelection, z as createResolver } from "./executor-DoiTBiVv.mjs";
4
4
  import { z } from "zod";
5
5
  //#region src/server/input.d.ts
6
6
  declare const byIdInput: z.ZodObject<{
package/lib/server.mjs CHANGED
@@ -1,6 +1,8 @@
1
1
  import { t as isRecord } from "./record-B07VwXd-.mjs";
2
- import { d as hashArgs, i as FateRequestError, n as liveEntityTopic, o as toProtocolError, r as liveGlobalConnectionTopic, t as liveConnectionTopic, u as filterConnectionArgs } from "./liveTopics-uVP0LG-Q.mjs";
3
- import { C as list, D as resolveConnection, E as connectionArgs, O as withConnection, S as isDataView, T as toPrismaSelect, _ as computed, a as refetchSourceById, b as dataView, c as resolveSourceConnection, f as createSourcePlan, h as hasNestedSelection, k as getScopedArgs, m as getNestedSelection, n as createSourceProcedures, o as resolveSourceById, r as byIdInput, s as resolveSourceByIds, t as bindSourceProcedures, u as createNestedSourcePlan, v as count, w as resolver, x as field, y as createResolver } from "./sourceRouter-DSaADXSf.mjs";
2
+ import { a as hashArgs, i as filterConnectionArgs } from "./args-CRLIRl_v.mjs";
3
+ import { r as toProtocolError, t as FateRequestError } from "./protocol-DS5sf6sd.mjs";
4
+ import { n as liveEntityTopic, r as liveGlobalConnectionTopic, t as liveConnectionTopic } from "./liveTopics-DuFkDZQm.mjs";
5
+ import { A as getScopedArgs, C as list, D as connectionArgs, O as resolveConnection, S as isDataView, T as toPrismaSelect, _ as computed, a as refetchSourceById, b as dataView, c as resolveSourceConnection, f as createSourcePlan, h as hasNestedSelection, k as withConnection, m as getNestedSelection, n as createSourceProcedures, o as resolveSourceById, r as byIdInput, s as resolveSourceByIds, t as bindSourceProcedures, u as createNestedSourcePlan, v as count, w as resolver, x as field, y as createResolver } from "./sourceRouter-51POBlEE.mjs";
4
6
  import { EventEmitter, on } from "node:events";
5
7
  //#region src/server/live.ts
6
8
  const eventName = (type, id) => `${type}:${String(id)}`;
@@ -288,9 +290,10 @@ const operationKinds = /* @__PURE__ */ new Set([
288
290
  "query"
289
291
  ]);
290
292
  const assertProtocolRequest = (value) => {
291
- if (!isRecord(value) || value.version !== 1 || !Array.isArray(value.operations)) throw new FateRequestError("BAD_REQUEST", "Invalid Fate protocol request.");
293
+ if (!isRecord(value) || value.version !== 1 && value.version !== 2 || !Array.isArray(value.operations)) throw new FateRequestError("BAD_REQUEST", "Invalid Fate protocol request.");
292
294
  for (const operation of value.operations) {
293
295
  if (!isRecord(operation) || typeof operation.id !== "string" || typeof operation.kind !== "string" || !operationKinds.has(operation.kind) || !isStringArray(operation.select) || "args" in operation && operation.args !== void 0 && !isRecord(operation.args)) throw new FateRequestError("BAD_REQUEST", "Invalid Fate protocol operation.");
296
+ if (operation.mutation !== void 0 && (value.version !== 2 || operation.kind !== "mutation" || !isRecord(operation.mutation) || operation.mutation.replayOnly !== void 0 && operation.mutation.replayOnly !== true || typeof operation.mutation.id !== "string" || !operation.mutation.id || operation.mutation.id.length > 256 || typeof operation.mutation.scope !== "string" || operation.mutation.scope.length > 1024)) throw new FateRequestError("BAD_REQUEST", "Invalid durable mutation metadata.");
294
297
  if (operation.kind === "byId" && (typeof operation.type !== "string" || !Array.isArray(operation.ids) || !operation.ids.every(isProtocolId))) throw new FateRequestError("BAD_REQUEST", "Invalid Fate byId operation.");
295
298
  if ((operation.kind === "list" || operation.kind === "mutation" || operation.kind === "query") && typeof operation.name !== "string") throw new FateRequestError("BAD_REQUEST", "Invalid Fate named operation.");
296
299
  }
@@ -371,7 +374,7 @@ const liveConnectionPayload = (event, node) => {
371
374
  }
372
375
  };
373
376
  const sourceScore = (source) => Object.keys(source.view.fields).length + Object.keys(source.relations ?? {}).length;
374
- function createFateServer({ context, lists, live, mutations, queries, roots, sources }) {
377
+ function createFateServer({ context, idempotency, lists, live, mutations, queries, roots, sources }) {
375
378
  const rootLists = /* @__PURE__ */ new Map();
376
379
  const rootQueries = /* @__PURE__ */ new Map();
377
380
  const sourcesByType = /* @__PURE__ */ new Map();
@@ -475,12 +478,21 @@ function createFateServer({ context, lists, live, mutations, queries, roots, sou
475
478
  }
476
479
  const mutation = mutations?.[operation.name];
477
480
  if (!mutation) throw new FateRequestError("NOT_FOUND", `No mutation registered for '${operation.name}'.`);
481
+ const resolve = async (context) => mutation.resolve({
482
+ ctx: context,
483
+ input: await parseInput(mutation.input, operation.input),
484
+ select: operation.select
485
+ });
486
+ if (operation.mutation && !idempotency) throw new FateRequestError("BAD_REQUEST", "fate: Configure createFateServer({ idempotency: createMutationIdempotency({ scope, store }) }) to accept persisted mutations. The store must commit mutation effects and receipts in the same database transaction.");
478
487
  return {
479
- data: await mutation.resolve({
488
+ data: operation.mutation ? await idempotency.execute({
480
489
  ctx,
481
- input: await parseInput(mutation.input, operation.input),
490
+ identity: operation.mutation,
491
+ input: operation.input,
492
+ name: operation.name,
493
+ resolve,
482
494
  select: operation.select
483
- }),
495
+ }) : await resolve(ctx),
484
496
  id: operation.id,
485
497
  ok: true
486
498
  };
@@ -0,0 +1,9 @@
1
+ //#region src/sortObjectKeys.ts
2
+ /** Recursively sorts plain-object keys, preserving array order and non-plain values. */
3
+ const sortObjectKeys = (value) => {
4
+ if (Array.isArray(value)) return value.map(sortObjectKeys);
5
+ if (value && typeof value === "object" && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null)) return Object.fromEntries(Object.keys(value).sort().map((key) => [key, sortObjectKeys(value[key])]));
6
+ return value;
7
+ };
8
+ //#endregion
9
+ export { sortObjectKeys as t };
@@ -217,6 +217,14 @@ function withConnection(procedure) {
217
217
  };
218
218
  }
219
219
  //#endregion
220
+ //#region src/server/stableStringify.ts
221
+ /** Serializes values with sorted object keys, including undefined properties. */
222
+ const stableStringify = (value) => {
223
+ if (Array.isArray(value)) return `[${value.map(stableStringify).join(",")}]`;
224
+ if (value && typeof value === "object") return `{${Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, entry]) => `${JSON.stringify(key)}:${stableStringify(entry)}`).join(",")}}`;
225
+ return JSON.stringify(value);
226
+ };
227
+ //#endregion
220
228
  //#region src/server/prismaSelect.ts
221
229
  const toPrismaOrderBy = (orderBy) => orderBy.map((entry) => ({ [entry.field]: entry.direction }));
222
230
  const mergeObject = (target, source) => {
@@ -229,11 +237,6 @@ const mergeObject = (target, source) => {
229
237
  target[key] = value;
230
238
  }
231
239
  };
232
- const stableStringify = (value) => {
233
- if (Array.isArray(value)) return `[${value.map((entry) => stableStringify(entry)).join(",")}]`;
234
- if (value && typeof value === "object") return `{${Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, entry]) => `${JSON.stringify(key)}:${stableStringify(entry)}`).join(",")}}`;
235
- return JSON.stringify(value);
236
- };
237
240
  const getConflictingCountRelations = (node) => {
238
241
  const signaturesByRelation = /* @__PURE__ */ new Map();
239
242
  for (const computed of node.computeds.values()) {
@@ -973,4 +976,4 @@ function bindSourceProcedures(defaults) {
973
976
  });
974
977
  }
975
978
  //#endregion
976
- export { list as C, resolveConnection as D, connectionArgs as E, withConnection as O, isDataView as S, toPrismaSelect as T, computed as _, refetchSourceById as a, dataView as b, resolveSourceConnection as c, createSourceDefinitions as d, createSourcePlan as f, attachComputedState as g, hasNestedSelection as h, createSourceRegistry as i, getScopedArgs as k, collectDataViewConfigs as l, getNestedSelection as m, createSourceProcedures as n, resolveSourceById as o, getDataViewSourceConfig as p, byIdInput as r, resolveSourceByIds as s, bindSourceProcedures as t, createNestedSourcePlan as u, count as v, resolver as w, field as x, createResolver as y };
979
+ export { getScopedArgs as A, list as C, connectionArgs as D, stableStringify as E, resolveConnection as O, isDataView as S, toPrismaSelect as T, computed as _, refetchSourceById as a, dataView as b, resolveSourceConnection as c, createSourceDefinitions as d, createSourcePlan as f, attachComputedState as g, hasNestedSelection as h, createSourceRegistry as i, withConnection as k, collectDataViewConfigs as l, getNestedSelection as m, createSourceProcedures as n, resolveSourceById as o, getDataViewSourceConfig as p, byIdInput as r, resolveSourceByIds as s, bindSourceProcedures as t, createNestedSourcePlan as u, count as v, resolver as w, field as x, createResolver as y };