rescript-relay 3.1.0 → 3.3.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.
@@ -41,6 +41,24 @@ type dataId
41
41
 
42
42
  type dataIdObject = {id: dataId}
43
43
 
44
+ /** A module for results originating from the @catch directive. */
45
+ module CatchResult: {
46
+ /** The shape of an error caught via @catch. */
47
+ type catchError = Js.Json.t
48
+
49
+ /** The result type for @catch. */
50
+ @tag("ok")
51
+ type t<'value> =
52
+ | @as(true) Ok({value: 'value})
53
+ | @as(false) Error({errors: array<catchError>})
54
+
55
+ /** Convert a @catch result to option. */
56
+ let toOption: t<'value> => option<'value>
57
+
58
+ /** Convert a @catch result to result. */
59
+ let toResult: t<'value> => result<'value, array<catchError>>
60
+ }
61
+
44
62
  module SuspenseSentinel: {
45
63
  type t
46
64
 
@@ -76,12 +94,56 @@ external makeUploadables: Js.Dict.t<'file> => uploadables = "%identity"
76
94
  /**Unwraps `uploadables` into a Js.Dict.t with your expected file type, so you can use that dict to attach the provided files to your request.*/
77
95
  external unwrapUploadables: uploadables => Js.Dict.t<'file> = "%identity"
78
96
 
79
- /**This generates a `dataId` for use on the _client_ side. However, this is farily low level, and what you're probably really looking for is `generateUniqueClientID` that'll let you generate a new, unique `dataId` that you can use for client side only records (like when doing optimistic updates).*/
97
+ /**
98
+ Generates a client-side `dataId` derived from an existing record.
99
+
100
+ This is a low-level function for creating deterministic client IDs. For most use cases,
101
+ prefer `generateUniqueClientID` which creates globally unique identifiers.
102
+
103
+ ## Parameters
104
+ - `dataId`: The base record ID to derive from
105
+ - `storageKey`: A unique key for this derived record
106
+ - `index`: Optional index for array-like derived records
107
+
108
+ ## Examples
109
+
110
+ ```rescript
111
+ // Create a client ID for a cached query result
112
+ let derivedId = RescriptRelay.generateClientID(
113
+ ~dataId=user.__id,
114
+ ~storageKey="cached_search_results",
115
+ )
116
+ ```
117
+ */
80
118
  @module("relay-runtime")
81
119
  external generateClientID: (~dataId: dataId, ~storageKey: string, ~index: int=?) => dataId =
82
120
  "generateClientID"
83
121
 
84
- /**This generates a unique `dataId` that's safe to use on the _client_ side. Useful when doing optimistic updates and you need to create IDs that the optimistic update can use.*/
122
+ /**
123
+ Generates a globally unique client-side `dataId`.
124
+
125
+ Creates a new unique identifier safe for client-side records. Primarily used for
126
+ optimistic updates where you need temporary IDs before server confirmation.
127
+
128
+ ## Examples
129
+
130
+ ```rescript
131
+ // Use in optimistic response
132
+ mutate(
133
+ ~variables={...},
134
+ ~optimisticResponse={
135
+ userCreated: Some({
136
+ user: {
137
+ id: RescriptRelay.generateUniqueClientID(),
138
+ name: "New User",
139
+ __typename: #User,
140
+ }
141
+ })
142
+ }
143
+ )
144
+
145
+ ```
146
+ */
85
147
  @module("relay-runtime")
86
148
  external generateUniqueClientID: unit => dataId = "generateUniqueClientID"
87
149
 
@@ -153,15 +215,70 @@ module RecordProxy: {
153
215
  /**Read the following section on working with the Relay store: https://relay.dev/docs/en/relay-store*/
154
216
  type t
155
217
 
156
- /**Copies all fields from one `RecordProxy` to another.*/
218
+ /**
219
+ Copies all fields from a source record to the current record.
220
+
221
+ Performs a shallow copy of all field values from the source record to the target record.
222
+ Useful for duplicating record data or applying bulk updates.
223
+
224
+ ⚠️ **Note**: This is a low-level, non-type-safe API. Use with caution and prefer higher-level operations when possible.
225
+
226
+ ## Parameters
227
+ - `sourceRecord`: The record to copy fields from
228
+
229
+ ## Examples
230
+
231
+ ```rescript
232
+ // Copy from newUser to existing user record
233
+ userRecord->RescriptRelay.RecordProxy.copyFieldsFrom(~sourceRecord=newUser)
234
+ ```
235
+ */
157
236
  @send
158
237
  external copyFieldsFrom: (t, ~sourceRecord: t) => unit = "copyFieldsFrom"
159
238
 
160
- /**Gets the `dataId` for a particular record.*/
239
+ /**
240
+ Gets the unique identifier for this record.
241
+
242
+ Returns the `dataId` that Relay uses to identify this record in the store.
243
+ Every record in Relay has a unique `dataId`.
244
+
245
+ ⚠️ **Note**: This is a low-level, non-type-safe API. Use with caution and prefer higher-level operations when possible.
246
+
247
+ ## Examples
248
+
249
+ ```rescript
250
+ let userId = userRecord->RescriptRelay.RecordProxy.getDataId
251
+ Console.log("User ID: " ++ RescriptRelay.dataIdToString(userId))
252
+ ```
253
+ */
161
254
  @send
162
255
  external getDataId: t => dataId = "getDataID"
163
256
 
164
- /**Gets a single linked record. A linked record is another object in the store, and not a scalar field like an int or float.*/
257
+ /**
258
+ Gets a linked record (object) field.
259
+
260
+ Retrieves another record that is linked from this record. Returns `None` if
261
+ the field doesn't exist or is null.
262
+
263
+ ⚠️ **Note**: This is a low-level, non-type-safe API. Use with caution and prefer higher-level operations when possible.
264
+
265
+ ## Parameters
266
+ - `name`: The field name to retrieve
267
+ - `arguments`: Optional arguments for parameterized fields
268
+
269
+ ## Examples
270
+
271
+ ```rescript
272
+ // Get user's profile
273
+ let profile = userRecord->RescriptRelay.RecordProxy.getLinkedRecord(~name="profile")
274
+
275
+ // Get user's post with specific ID
276
+ let post = userRecord->RescriptRelay.RecordProxy.getLinkedRecord(
277
+ ~name="post",
278
+ ~arguments=RescriptRelay.makeArguments({"id": postId})
279
+ )
280
+ ```
281
+ */
165
282
  @send
166
283
  @return(nullable)
167
284
  external getLinkedRecord: (t, ~name: string, ~arguments: arguments=?) => option<t> =
@@ -240,12 +357,56 @@ module RecordProxy: {
240
357
  ~arguments: arguments=?,
241
358
  ) => option<array<option<bool>>> = "getValue"
242
359
 
243
- /**Sets a `RecordProxy.t` as the linked record for a particular field.*/
360
+ /**
361
+ Sets a linked record for a field.
362
+
363
+ Links another record to this record at the specified field. The linked record
364
+ must already exist in the store.
365
+
366
+ ⚠️ **Note**: This is a low-level, non-type-safe API. Use with caution and prefer higher-level operations when possible.
367
+
368
+ ## Parameters
369
+ - `record`: The record to link
370
+ - `name`: The field name to set
371
+ - `arguments`: Optional arguments for parameterized fields
372
+
373
+ ## Examples
374
+
375
+ ```rescript
376
+ // Link a profile to a user
377
+ let _ = userRecord->RescriptRelay.RecordProxy.setLinkedRecord(
378
+ ~record=profileRecord,
379
+ ~name="profile"
380
+ )
381
+ ```
382
+ */
244
383
  @send
245
384
  external setLinkedRecord: (t, ~record: t, ~name: string, ~arguments: arguments=?) => t =
246
385
  "setLinkedRecord"
247
386
 
248
- /**Sets an array of `RecordProxy.t` as the linked records for a particular field.*/
387
+ /**
388
+ Sets an array of linked records for a field.
389
+
390
+ Links multiple records to this record at the specified field. Use `None` for
391
+ null entries in the array.
392
+
393
+ ⚠️ **Note**: This is a low-level, non-type-safe API. Use with caution and prefer higher-level operations when possible.
394
+
395
+ ## Parameters
396
+ - `records`: Array of records to link (with optional null entries)
397
+ - `name`: The field name to set
398
+ - `arguments`: Optional arguments for parameterized fields
399
+
400
+ ## Examples
401
+
402
+ ```rescript
403
+ // Set user's posts
404
+ let _ = userRecord->RescriptRelay.RecordProxy.setLinkedRecords(
405
+ ~records=[Some(post1), None, Some(post3)],
406
+ ~name="posts"
407
+ )
408
+ ```
409
+ */
249
410
  @send
250
411
  external setLinkedRecords: (
251
412
  t,
@@ -371,15 +532,78 @@ module RecordSourceSelectorProxy: {
371
532
  @send
372
533
  external batchLiveStateUpdates: (t, unit => unit) => unit = "batchLiveStateUpdates"
373
534
 
374
- /**Creates a new `RecordProxy`.*/
535
+ /**
536
+ Creates a new record in the store.
537
+
538
+ Creates a new record with the specified ID and type. The record will be empty
539
+ initially - use `RecordProxy` methods to populate its fields.
540
+
541
+ ⚠️ **Note**: This is a low-level, non-type-safe API. Use with caution and prefer higher-level operations when possible.
542
+
543
+ ## Parameters
544
+ - `dataId`: Unique identifier for the new record
545
+ - `typeName`: GraphQL type name for the record
546
+
547
+ ## Examples
548
+
549
+ ```rescript
550
+ // Create optimistic user record
551
+ let newUser = store->RescriptRelay.RecordSourceSelectorProxy.create(
552
+ ~dataId=RescriptRelay.generateUniqueClientID(),
553
+ ~typeName="User"
554
+ )
555
+
556
+ let _ = newUser->RescriptRelay.RecordProxy.setValueString(~value="John Doe", ~name="name")
557
+ ```
558
+ */
375
559
  @send
376
560
  external create: (t, ~dataId: dataId, ~typeName: string) => RecordProxy.t = "create"
377
561
 
378
- /**Deletes the `RecordProxy` with the provided `dataId`.*/
562
+ /**
563
+ Deletes a record from the store.
564
+
565
+ Removes the record with the specified ID from the store. Any references to
566
+ this record from other records will become null.
567
+
568
+ ⚠️ **Note**: This is a low-level, non-type-safe API. Use with caution and prefer higher-level operations when possible.
569
+
570
+ ## Parameters
571
+ - `dataId`: The ID of the record to delete
572
+
573
+ ## Examples
574
+
575
+ ```rescript
576
+ // Delete a user record
577
+ store->RescriptRelay.RecordSourceSelectorProxy.delete(~dataId=userId)
578
+ ```
579
+ */
379
580
  @send
380
581
  external delete: (t, ~dataId: dataId) => unit = "delete"
381
582
 
382
- /**Returns the `RecordProxy` with the provided `dataId`, if it exists.*/
583
+ /**
584
+ Gets a record from the store by ID.
585
+
586
+ Retrieves an existing record from the store. Returns `None` if the record
587
+ doesn't exist.
588
+
589
+ ⚠️ **Note**: This is a low-level, non-type-safe API. Use with caution and prefer higher-level operations when possible.
590
+
591
+ ## Parameters
592
+ - `dataId`: The ID of the record to retrieve
593
+
594
+ ## Examples
595
+
596
+ ```rescript
597
+ switch store->RescriptRelay.RecordSourceSelectorProxy.get(~dataId=userId) {
598
+ | Some(userRecord) =>
599
+ // Work with the user record
600
+ let _ = userRecord->RescriptRelay.RecordProxy.setValueBool(~value=true, ~name="isActive")
601
+ | None =>
602
+ // Record doesn't exist
603
+ ()
604
+ }
605
+ ```
606
+ */
383
607
  @send
384
608
  @return(nullable)
385
609
  external get: (t, ~dataId: dataId) => option<RecordProxy.t> = "get"
@@ -505,9 +729,37 @@ module MissingFieldHandler: {
505
729
  ) => t
506
730
  }
507
731
 
508
- /**Read the Relay docs section on [ConnectionHandler](https://relay.dev/docs/en/relay-store#connectionhandler)*/
732
+ /**
733
+ Utilities for working with Relay connections.
734
+
735
+ Connections are Relay's way of handling paginated lists. These utilities help you
736
+ manipulate connection data in the store, such as adding/removing edges and getting
737
+ connection records.
738
+
739
+ Read the [Relay ConnectionHandler docs](https://relay.dev/docs/en/relay-store#connectionhandler) for more details.
740
+ */
509
741
  module ConnectionHandler: {
510
- /**For a `RecordProxy`, returns the `RecordProxy` that is at the connection config provided.*/
742
+ /**
743
+ Gets a connection record from a parent record.
744
+
745
+ Retrieves the connection record for a specific connection key and optional filters.
746
+ Returns `None` if the connection doesn't exist.
747
+
748
+ ## Parameters
749
+ - `record`: The parent record containing the connection
750
+ - `key`: The connection key (from `@connection(key: "...")`)
751
+ - `filters`: Optional filter arguments used in the connection
752
+
753
+ ## Examples
754
+
755
+ ```rescript
756
+ // Get user's friends connection
757
+ let friendsConnection = RescriptRelay.ConnectionHandler.getConnection(
758
+ ~record=userRecord,
759
+ ~key=UserFriends_user_graphql.connectionKey,
760
+ )
761
+ ```
762
+ */
511
763
  @module("relay-runtime")
512
764
  @scope("ConnectionHandler")
513
765
  @return(nullable)
@@ -517,7 +769,32 @@ module ConnectionHandler: {
517
769
  ~filters: arguments=?,
518
770
  ) => option<RecordProxy.t> = "getConnection"
519
771
 
520
- /**Creates an edge for a particular connection.*/
772
+ /**
773
+ Creates an edge record for a connection.
774
+
775
+ Creates a new edge that can be inserted into a connection. The edge wraps
776
+ a node and provides cursor information for pagination.
777
+
778
+ 💡 **Tip**: For most cases, prefer using declarative directives like `@appendNode` or `@prependNode` in your mutations instead of manually managing edges.
779
+
780
+ ## Parameters
781
+ - `store`: The store to create the edge in
782
+ - `connection`: The connection this edge belongs to
783
+ - `node`: The node (record) to wrap in this edge
784
+ - `edgeType`: The GraphQL type name for the edge
785
+
786
+ ## Examples
787
+
788
+ ```rescript
789
+ // Create edge for new friend
790
+ let newEdge = RescriptRelay.ConnectionHandler.createEdge(
791
+ ~store,
792
+ ~connection=friendsConnection,
793
+ ~node=newFriendRecord,
794
+ ~edgeType="UserEdge"
795
+ )
796
+ ```
797
+ */
521
798
  @module("relay-runtime")
522
799
  @scope("ConnectionHandler")
523
800
  external createEdge: (
@@ -527,7 +804,36 @@ module ConnectionHandler: {
527
804
  ~edgeType: string,
528
805
  ) => RecordProxy.t = "createEdge"
529
806
 
530
- /**Inserts an edge into a connection _before_ the provided cursor. If no cursor is provided, it inserts the edge at the start of the connection list.*/
807
+ /**
808
+ Inserts an edge before a specific cursor or at the beginning.
809
+
810
+ Adds an edge to the connection before the specified cursor position.
811
+ If no cursor is provided, the edge is inserted at the start of the list.
812
+
813
+ 💡 **Tip**: For most cases, prefer using declarative directives like `@prependEdge` in your mutations instead of manually inserting edges.
814
+
815
+ ## Parameters
816
+ - `connection`: The connection to insert into
817
+ - `newEdge`: The edge to insert
818
+ - `cursor`: Optional cursor to insert before
819
+
820
+ ## Examples
821
+
822
+ ```rescript
823
+ // Insert at beginning
824
+ RescriptRelay.ConnectionHandler.insertEdgeBefore(
825
+ ~connection=friendsConnection,
826
+ ~newEdge=friendEdge
827
+ )
828
+
829
+ // Insert before specific cursor
830
+ RescriptRelay.ConnectionHandler.insertEdgeBefore(
831
+ ~connection=friendsConnection,
832
+ ~newEdge=friendEdge,
833
+ ~cursor="cursor123"
834
+ )
835
+ ```
836
+ */
531
837
  @module("relay-runtime")
532
838
  @scope("ConnectionHandler")
533
839
  external insertEdgeBefore: (
@@ -536,7 +842,29 @@ module ConnectionHandler: {
536
842
  ~cursor: string=?,
537
843
  ) => unit = "insertEdgeBefore"
538
844
 
539
- /**Inserts an edge into a connection _after_ the provided cursor. If no cursor is provided, it inserts the edge at the end of the connection list.*/
845
+ /**
846
+ Inserts an edge after a specific cursor or at the end.
847
+
848
+ Adds an edge to the connection after the specified cursor position.
849
+ If no cursor is provided, the edge is inserted at the end of the list.
850
+
851
+ 💡 **Tip**: For most cases, prefer using declarative directives like `@appendEdge` in your mutations instead of manually inserting edges.
852
+
853
+ ## Parameters
854
+ - `connection`: The connection to insert into
855
+ - `newEdge`: The edge to insert
856
+ - `cursor`: Optional cursor to insert after
857
+
858
+ ## Examples
859
+
860
+ ```rescript
861
+ // Insert at end
862
+ RescriptRelay.ConnectionHandler.insertEdgeAfter(
863
+ ~connection=friendsConnection,
864
+ ~newEdge=friendEdge
865
+ )
866
+ ```
867
+ */
540
868
  @module("relay-runtime")
541
869
  @scope("ConnectionHandler")
542
870
  external insertEdgeAfter: (
@@ -545,12 +873,59 @@ module ConnectionHandler: {
545
873
  ~cursor: string=?,
546
874
  ) => unit = "insertEdgeAfter"
547
875
 
548
- /**Deletes any edge from the connection where the node of the edge has the provided `dataId`. Please not that this _will not_ remove the actual node from the store. Use `RecordSourceSelectorProxy.delete` for that.*/
876
+ /**
877
+ Removes a node from a connection by its ID.
878
+
879
+ Deletes any edge from the connection where the edge's node has the specified ID.
880
+ Note: This only removes the edge, not the actual node record from the store.
881
+
882
+ 💡 **Tip**: For most cases, prefer using declarative directives like `@deleteEdge` in your mutations instead of manually removing edges.
883
+
884
+ ## Parameters
885
+ - `connection`: The connection to remove from
886
+ - `nodeId`: The ID of the node to remove
887
+
888
+ ## Examples
889
+
890
+ ```rescript
891
+ // Remove friend from connection
892
+ RescriptRelay.ConnectionHandler.deleteNode(
893
+ ~connection=friendsConnection,
894
+ ~nodeId=friendId
895
+ )
896
+ ```
897
+ */
549
898
  @module("relay-runtime")
550
899
  @scope("ConnectionHandler")
551
900
  external deleteNode: (~connection: RecordProxy.t, ~nodeId: dataId) => unit = "deleteNode"
552
901
 
553
- /**Constructs a `dataId` targeting a specific connection at a specific parent. Note that the generated module for every fragment with a `@connection` will have a `<moduleName>.Utils.connectionKey` representing the connection key of that particular `@connection`, that you should use with this.*/
902
+ /**
903
+ Generates a connection's unique data ID.
904
+
905
+ Constructs the internal ID that Relay uses to identify a specific connection
906
+ on a specific parent with specific filters.
907
+
908
+ 💡 **Tip**: For connections with arguments, the generated fragment module includes a type-safe `getConnectionId` function. For example, `UserPosts_user_graphql.getConnectionId(~status="PUBLISHED")`.
909
+
910
+ ## Parameters
911
+ - Parent record's data ID
912
+ - Connection key string
913
+ - Filter arguments object
914
+
915
+ ## Examples
916
+
917
+ ```rescript
918
+ // Get connection ID for user's filtered posts
919
+ let connectionId = RescriptRelay.ConnectionHandler.getConnectionID(
920
+ userId,
921
+ UserPosts_user_graphql.connectionKey,
922
+ {"status": "PUBLISHED"}
923
+ )
924
+
925
+ // A type-safe version is also available for each fragment defined. Prefer using that.
926
+ let connectionId = UserPosts_user_graphql.getConnectionId(~status=PUBLISHED)
927
+ ```
928
+ */
554
929
  @module("relay-runtime")
555
930
  @scope("ConnectionHandler")
556
931
  external getConnectionID: (dataId, string, 'filters) => dataId = "getConnectionID"
@@ -612,28 +987,73 @@ module Observable: {
612
987
  /**Ignore this subscription.*/ external ignoreSubscription: subscription => unit = "%ignore"
613
988
  }
614
989
 
615
- /**Represents the network layer.*/
990
+ /**
991
+ Network layer configuration for Relay.
992
+
993
+ The network layer defines how Relay makes requests to your GraphQL server.
994
+ You must provide fetch and optionally subscription functions to handle
995
+ queries, mutations, and subscriptions.
996
+ */
616
997
  module Network: {
617
998
  type codesplitsMetadata = (string, unit => unit)
618
999
 
619
1000
  type operationMetadata = {codesplits?: array<codesplitsMetadata>}
620
1001
 
621
- /**The type representing an instantiated `NetworkLayer`.*/
1002
+ /**The type representing an instantiated network layer.*/
622
1003
  type t
623
1004
 
624
- /**The operation fed to the `NetworkLayer` when Relay wants to make a request. Please note that if you're using persisted queries, `id` will exist but `text` won't, and vice versa when not using persisted queries.*/
1005
+ /**
1006
+ Information about a GraphQL operation being executed.
1007
+
1008
+ Contains the operation details that your fetch function will receive.
1009
+ For persisted queries, `id` exists but `text` is empty. For regular queries,
1010
+ `text` contains the query string but `id` is empty.
1011
+
1012
+ ## Fields
1013
+ - `id`: Persisted query ID (if using persisted queries)
1014
+ - `text`: GraphQL query text (if not using persisted queries)
1015
+ - `name`: Operation name
1016
+ - `operationKind`: "query", "mutation", or "subscription"
1017
+ - `metadata`: Optional operation metadata
1018
+ */
625
1019
  type operation = {
626
- id: string,
627
- text: string,
1020
+ /** The operation ID. Set if persisted queries are enabled, otherwise not set. */
1021
+ id: Js.Nullable.t<string>,
1022
+ /** The operation text. Not set for persisted queries, or if this is a client-only query that will not make a network request. */
1023
+ text: Js.Nullable.t<string>,
1024
+ /** The operation name. */
628
1025
  name: string,
1026
+ /** The operation kind. */
629
1027
  operationKind: string,
1028
+ /** Optional operation metadata. */
630
1029
  metadata: Js.Nullable.t<operationMetadata>,
631
1030
  }
632
1031
 
633
- /**The shape of the function Relay expects for creating a subscription.*/
1032
+ /**
1033
+ Function signature for handling GraphQL subscriptions.
1034
+
1035
+ ## Parameters
1036
+ - `operation`: The subscription operation details
1037
+ - `variables`: JSON variables for the subscription
1038
+ - `cacheConfig`: Cache configuration options
1039
+
1040
+ ## Returns
1041
+ Observable that emits subscription data over time
1042
+ */
634
1043
  type subscribeFn = (operation, Js.Json.t, cacheConfig) => Observable.t<Js.Json.t>
635
1044
 
636
- /**The shape of the function responsible for fetching data if you want to return a promise rather than an `Observable`.*/
1045
+ /**
1046
+ Function signature for fetching data using promises.
1047
+
1048
+ ## Parameters
1049
+ - `operation`: The operation details
1050
+ - `variables`: JSON variables for the operation
1051
+ - `cacheConfig`: Cache configuration options
1052
+ - `uploadables`: Optional file uploads
1053
+
1054
+ ## Returns
1055
+ Promise that resolves to the GraphQL response
1056
+ */
637
1057
  type fetchFunctionPromise = (
638
1058
  operation,
639
1059
  Js.Json.t,
@@ -641,7 +1061,18 @@ module Network: {
641
1061
  Js.Nullable.t<uploadables>,
642
1062
  ) => Js.Promise.t<Js.Json.t>
643
1063
 
644
- /**The shape of the function responsible for fetching data if you want to return an `Observable`.*/
1064
+ /**
1065
+ Function signature for fetching data using observables.
1066
+
1067
+ ## Parameters
1068
+ - `operation`: The operation details
1069
+ - `variables`: JSON variables for the operation
1070
+ - `cacheConfig`: Cache configuration options
1071
+ - `uploadables`: Optional file uploads
1072
+
1073
+ ## Returns
1074
+ Observable that emits the GraphQL response
1075
+ */
645
1076
  type fetchFunctionObservable = (
646
1077
  operation,
647
1078
  Js.Json.t,
@@ -649,7 +1080,16 @@ module Network: {
649
1080
  Js.Nullable.t<uploadables>,
650
1081
  ) => Observable.t<Js.Json.t>
651
1082
 
652
- /**Create a new `NetworkLayer` using a fetch function that returns a promise.*/
1083
+ /**
1084
+ Creates a network layer using a promise-based fetch function.
1085
+
1086
+ Most common way to create a network layer. Your fetch function should
1087
+ make HTTP requests to your GraphQL endpoint and return promises.
1088
+
1089
+ ## Parameters
1090
+ - `fetchFunction`: Function that returns promises for GraphQL requests
1091
+ - `subscriptionFunction`: Optional function for handling subscriptions
1092
+ */
653
1093
  @module("relay-runtime")
654
1094
  @scope("Network")
655
1095
  external makePromiseBased: (
@@ -657,7 +1097,16 @@ module Network: {
657
1097
  ~subscriptionFunction: subscribeFn=?,
658
1098
  ) => t = "create"
659
1099
 
660
- /**Create a new `NetworkLayer` using a fetch function that returns an `Observable`.*/
1100
+ /**
1101
+ Creates a network layer using an observable-based fetch function.
1102
+
1103
+ Use this when you need more control over the request lifecycle or want to
1104
+ handle streaming responses like `@defer` and `@stream`.
1105
+
1106
+ ## Parameters
1107
+ - `observableFunction`: Function that returns observables for GraphQL requests
1108
+ - `subscriptionFunction`: Optional function for handling subscriptions
1109
+ */
661
1110
  @module("relay-runtime")
662
1111
  @scope("Network")
663
1112
  external makeObservableBased: (
@@ -665,62 +1114,200 @@ module Network: {
665
1114
  ~subscriptionFunction: subscribeFn=?,
666
1115
  ) => t = "create"
667
1116
 
1117
+ /**
1118
+ Preloads resources based on operation response.
1119
+
1120
+ Internal function for resource preloading. Used by Relay's code splitting
1121
+ and resource preloading features.
1122
+ */
668
1123
  let preloadResources: (~operation: operation, ~variables: Js.Json.t, ~response: Js.Json.t) => unit
669
1124
  }
670
1125
 
671
- /**RecordSource is the source of records used by the store. Can be initiated with or without prior records; eg. hydrating the store with prior data.*/
1126
+ /**
1127
+ The RecordSource - storage for normalized GraphQL records.
1128
+
1129
+ RecordSource is the underlying storage mechanism that holds normalized GraphQL
1130
+ records. It can be initialized empty or with existing data for hydration scenarios
1131
+ like SSR. The store uses a RecordSource to persist and retrieve cached data.
1132
+ */
672
1133
  module RecordSource: {
673
- /**The type representing an instantiated `RecordSource`.*/
1134
+ /**The type representing a RecordSource instance.*/
674
1135
  type t
675
1136
 
676
- /**Create a new `RecordSource`. Here's where you pass an existing `recordSourceRecords` if you have existing records you want to hydrate the store with, when doing SSR or similar.*/
1137
+ /**
1138
+ Creates a new RecordSource.
1139
+
1140
+ Can be initialized empty or with existing record data for hydration.
1141
+ When doing SSR, you'll typically create an empty RecordSource on the server,
1142
+ populate it with data, serialize it, and then recreate it on the client.
1143
+
1144
+ ## Parameters
1145
+ - `records`: Optional existing records to initialize with
1146
+
1147
+ ## Examples
1148
+
1149
+ ```rescript
1150
+ // Create empty RecordSource
1151
+ let source = RescriptRelay.RecordSource.make()
1152
+
1153
+ // Create RecordSource with existing data (e.g., from SSR)
1154
+ let hydratedSource = RescriptRelay.RecordSource.make(
1155
+ ~records=serverSideRecords
1156
+ )
1157
+ ```
1158
+ */
677
1159
  @module("relay-runtime")
678
1160
  @new
679
1161
  external make: (~records: recordSourceRecords=?) => t = "RecordSource"
680
1162
 
681
- /**Serializes the `RecordSource` into `recordSourceRecords` that you can use to rehydrate another store. Typically used for SSR.*/
1163
+ /**
1164
+ Serializes the RecordSource to JSON.
1165
+
1166
+ Converts all records in the source to a JSON representation that can be
1167
+ transmitted or stored. Commonly used for SSR to send server-side cached
1168
+ data to the client.
1169
+
1170
+ ## Returns
1171
+ JSON object containing all normalized records
1172
+
1173
+ ## Examples
1174
+
1175
+ ```rescript
1176
+ // Serialize for SSR
1177
+ let serverRecords = recordSource->RescriptRelay.RecordSource.toJSON
1178
+
1179
+ // Send to client or store in localStorage
1180
+ let serialized = Js.Json.stringify(serverRecords)
1181
+ ```
1182
+ */
682
1183
  @send
683
1184
  external toJSON: t => recordSourceRecords = "toJSON"
684
1185
  }
685
1186
 
686
- /**The actual store module, with configuration for the store.*/
1187
+ /**
1188
+ The Relay Store - manages normalized GraphQL data caching.
1189
+
1190
+ The Store handles data normalization, caching, garbage collection, and provides
1191
+ interfaces for reading and writing data. It works with a RecordSource to persist
1192
+ the actual record data.
1193
+ */
687
1194
  module Store: {
688
- /**The type representing an instantiated `Store`.*/
1195
+ /**The type representing a Relay store instance.*/
689
1196
  type t
690
1197
 
691
- /**Creates a new `Store`.*/
1198
+ /**
1199
+ Creates a new standard Relay store.
1200
+
1201
+ The store manages normalized data and provides caching with configurable
1202
+ garbage collection and TTL settings.
1203
+
1204
+ ## Parameters
1205
+ - `source`: RecordSource containing the initial data
1206
+ - `gcReleaseBufferSize`: Number of queries to keep cached (default: 10)
1207
+ - `queryCacheExpirationTime`: TTL in milliseconds for cached queries (default: no TTL)
1208
+
1209
+ ## Examples
1210
+
1211
+ ```rescript
1212
+ let store = RescriptRelay.Store.make(
1213
+ ~source=RescriptRelay.RecordSource.make(),
1214
+ ~gcReleaseBufferSize=20, // Keep 20 queries cached
1215
+ ~queryCacheExpirationTime=5 * 60 * 1000, // 5 minute TTL
1216
+ )
1217
+ ```
1218
+ */
692
1219
  let make: (
693
1220
  ~source: RecordSource.t,
694
- ~gcReleaseBufferSize: /* `gcReleaseBufferSize` controls how many queries are allowed to be cached by default. Increase this to increase the size of the cache. */
695
- int=?,
1221
+ ~gcReleaseBufferSize: int=?,
696
1222
  ~queryCacheExpirationTime: int=?,
697
- ) => /* `queryCacheExpirationTime` sets a TTL (time to live) for all queries. If that time passes, the data is considered stale and is evicted from the store. Default is no TTL. */
698
- t
1223
+ ) => t
1224
+
1225
+ /**
1226
+ Creates a new live store with real-time capabilities.
1227
+
1228
+ Similar to the standard store but with enhanced support for live queries
1229
+ and real-time data updates. Only needed if you're using Relay Resolvers.
1230
+
1231
+ ℹ️ **Note**: Use this only when you need Relay Resolvers. For most applications, the standard `make` function is sufficient.
1232
+
1233
+ ## Parameters
1234
+ - `source`: RecordSource containing the initial data
1235
+ - `gcReleaseBufferSize`: Number of queries to keep cached (default: 10)
1236
+ - `queryCacheExpirationTime`: TTL in milliseconds for cached queries (default: no TTL)
1237
+
1238
+ ## Examples
699
1239
 
700
- /**Creates a new `LiveStore`.*/
1240
+ ```rescript
1241
+ let liveStore = RescriptRelay.Store.makeLiveStore(
1242
+ ~source=RescriptRelay.RecordSource.make(),
1243
+ ~gcReleaseBufferSize=15,
1244
+ )
1245
+ ```
1246
+ */
701
1247
  let makeLiveStore: (
702
1248
  ~source: RecordSource.t,
703
- ~gcReleaseBufferSize: /* `gcReleaseBufferSize` controls how many queries are allowed to be cached by default. Increase this to increase the size of the cache. */
704
- int=?,
1249
+ ~gcReleaseBufferSize: int=?,
705
1250
  ~queryCacheExpirationTime: int=?,
706
- ) => /* `queryCacheExpirationTime` sets a TTL (time to live) for all queries. If that time passes, the data is considered stale and is evicted from the store. Default is no TTL. */
707
- t
1251
+ ) => t
708
1252
 
1253
+ /**Internal CommonJS version of makeLiveStore. Use `makeLiveStore` instead.*/
709
1254
  let _makeLiveStoreCjs: (
710
1255
  ~source: RecordSource.t,
711
1256
  ~gcReleaseBufferSize: int=?,
712
1257
  ~queryCacheExpirationTime: int=?,
713
1258
  ) => t
714
1259
 
715
- /**Gets the `RecordSource` for this `Store`.*/
1260
+ /**
1261
+ Gets the RecordSource from this store.
1262
+
1263
+ Provides access to the underlying record source for advanced operations
1264
+ like serialization or direct record access.
1265
+
1266
+ ## Examples
1267
+
1268
+ ```rescript
1269
+ let source = store->RescriptRelay.Store.getSource
1270
+ let serialized = source->RescriptRelay.RecordSource.toJSON
1271
+ ```
1272
+ */
716
1273
  @send
717
1274
  external getSource: t => RecordSource.t = "getSource"
718
1275
 
719
- /**Publishes _new_ records to this store. This is useful in particular with frameworks like Next.js where routes could preload data needed and then serialize that (using `RecordSource.toJSON`) and send it over the wire, but you already have a store instantiated client side. This will then allow you to publish those records into your existing store.*/
1276
+ /**
1277
+ Publishes new records to the store.
1278
+
1279
+ Merges new record data into the existing store. Particularly useful for
1280
+ SSR scenarios where you need to hydrate client-side stores with server data.
1281
+
1282
+ ## Parameters
1283
+ - `source`: RecordSource containing new records to publish
1284
+
1285
+ ## Examples
1286
+
1287
+ ```rescript
1288
+ // Hydrate client store with server data
1289
+ let serverRecords = RescriptRelay.RecordSource.make(~records=serverData)
1290
+ store->RescriptRelay.Store.publish(serverRecords)
1291
+ ```
1292
+ */
720
1293
  @send
721
1294
  external publish: (t, RecordSource.t) => unit = "publish"
722
1295
 
723
- /**Informes the store to stop its normal garbage collection processes. This prevents data being lost between calling relay's `fetchQuery` any serialization process (eg: toJSON)*/
1296
+ /**
1297
+ Temporarily disables garbage collection.
1298
+
1299
+ Prevents the store from cleaning up cached data. Useful when you need to
1300
+ ensure data persistence during operations like serialization.
1301
+
1302
+ ## Examples
1303
+
1304
+ ```rescript
1305
+ // Hold GC during serialization
1306
+ store->RescriptRelay.Store.holdGC
1307
+ let serialized = store->RescriptRelay.Store.getSource->RescriptRelay.RecordSource.toJSON
1308
+ // GC will resume automatically
1309
+ ```
1310
+ */
724
1311
  @send
725
1312
  external holdGC: t => unit = "holdGC"
726
1313
  }
@@ -768,12 +1355,45 @@ module RelayFieldLogger: {
768
1355
  type t = arg => unit
769
1356
  }
770
1357
 
771
- /**Module representing the environment, which you'll need to use and pass to various functions. Takes a few configuration options like store and network layer.*/
1358
+ /**
1359
+ The Relay Environment - the central hub for Relay operations.
1360
+
1361
+ The Environment coordinates between the network layer, store, and other Relay
1362
+ components. It manages data fetching, caching, and normalization. You typically
1363
+ create one Environment per application and pass it to Relay components.
1364
+ */
772
1365
  module Environment: {
773
- /**The type representing an instantiated `Environment`.*/
1366
+ /**The type representing a Relay environment instance.*/
774
1367
  type t
775
1368
 
776
- /**Create a new `Environment`.*/
1369
+ /**
1370
+ Creates a new Relay Environment.
1371
+
1372
+ The Environment requires a network layer and store at minimum. Additional
1373
+ configuration options allow you to customize caching, error handling,
1374
+ and data normalization behavior.
1375
+
1376
+ ## Parameters
1377
+ - `network`: Network layer for making GraphQL requests
1378
+ - `store`: Store for caching normalized data
1379
+ - `getDataID`: Optional custom function for generating record IDs
1380
+ - `treatMissingFieldsAsNull`: Whether missing fields should be treated as null
1381
+ - `missingFieldHandlers`: Array of handlers for filling in missing data
1382
+ - `relayFieldLogger`: Optional logger for field-level events
1383
+ - `isServer`: Whether this environment is running on the server
1384
+
1385
+ ## Examples
1386
+
1387
+ ```rescript
1388
+ let environment = RescriptRelay.Environment.make(
1389
+ ~network=myNetworkLayer,
1390
+ ~store=RescriptRelay.Store.make(
1391
+ ~source=RescriptRelay.RecordSource.make()
1392
+ ),
1393
+ ~treatMissingFieldsAsNull=false,
1394
+ )
1395
+ ```
1396
+ */
777
1397
  let make: (
778
1398
  ~network: Network.t,
779
1399
  ~store: Store.t,
@@ -787,24 +1407,118 @@ module Environment: {
787
1407
  ~isServer: bool=?,
788
1408
  ) => t
789
1409
 
790
- /**Get the `Store` for this `Environment`.*/
1410
+ /**
1411
+ Gets the store instance from this environment.
1412
+
1413
+ Provides access to the underlying store for advanced store operations
1414
+ like publishing records or holding garbage collection.
1415
+
1416
+ ## Examples
1417
+
1418
+ ```rescript
1419
+ let store = environment->RescriptRelay.Environment.getStore
1420
+ store->RescriptRelay.Store.holdGC // Prevent garbage collection
1421
+ ```
1422
+ */
791
1423
  @send
792
1424
  external getStore: t => Store.t = "getStore"
793
1425
 
794
- /**Given an `operationDescriptor`, commits the corresponding payload.*/
1426
+ /**
1427
+ Commits a GraphQL response payload to the store.
1428
+
1429
+ Low-level function for manually committing operation results. Most users
1430
+ should use higher-level APIs like queries and mutations instead.
1431
+
1432
+ ## Parameters
1433
+ - `operationDescriptor`: The operation that produced this payload
1434
+ - `payload`: The GraphQL response data to commit
1435
+ */
795
1436
  @send
796
1437
  external commitPayload: (t, operationDescriptor, 'payload) => unit = "commitPayload"
797
1438
 
798
- /**Given an `operationDescriptor`, retains the corresponding operation so any data referenced by it isn't garbage collected.
799
- You should use the generated `Query.retain` function on your queries instead of using this directly.*/
1439
+ /**
1440
+ Retains an operation to prevent garbage collection.
1441
+
1442
+ Keeps the data for an operation in the store by preventing Relay's garbage
1443
+ collector from cleaning it up. Returns a disposable that releases the retain
1444
+ when disposed.
1445
+
1446
+ Note: Use the generated `Query.retain` functions instead of calling this directly.
1447
+
1448
+ ## Parameters
1449
+ - `operationDescriptor`: The operation to retain
1450
+
1451
+ ## Returns
1452
+ Disposable that releases the retain when disposed
1453
+ */
800
1454
  @send
801
1455
  external retain: (t, operationDescriptor) => Disposable.t = "retain"
802
1456
 
803
- /**Find all connection IDs for a specific connection and on a specific object. Useful together with `@deleteEdge` and similar where you want to remove something from all connection configurations. */
1457
+ /**
1458
+ Finds all connection IDs for a specific connection key on a parent record.
1459
+
1460
+ Useful for operations that need to affect all instances of a connection,
1461
+ such as when using `@deleteEdge` or bulk connection updates.
1462
+
1463
+ ## Parameters
1464
+ - `connectionKey`: The connection key to search for
1465
+ - `parentId`: The parent record containing the connections
1466
+
1467
+ ## Returns
1468
+ Array of connection data IDs
1469
+
1470
+ ## Examples
1471
+
1472
+ ```rescript
1473
+ // Find all friend list connections for a user
1474
+ let connectionIds = environment->RescriptRelay.Environment.findAllConnectionIds(
1475
+ ~connectionKey=UserFriends_user_graphql.connectionKey,
1476
+ ~parentId=userId
1477
+ )
1478
+ ```
1479
+ */
804
1480
  let findAllConnectionIds: (t, ~connectionKey: string, ~parentId: dataId) => array<dataId>
805
1481
 
806
- /**Invalidates all connection configurations of `connectionKey` on `parentId`.*/
807
- let invalidateAllOfConnection: (t, ~connectionKey: string, ~parentId: dataId) => unit
1482
+ /**
1483
+ Invalidates all connection configurations of `connectionKey` on `parentId`.
1484
+
1485
+ This function invalidates all cached data for connections with the specified key on the given parent record.
1486
+ When connections are invalidated, any queries that depend on this connection data will be considered stale
1487
+ and will need to be refetched the next time they are accessed.
1488
+
1489
+ ## Parameters
1490
+ - `environment`: The Relay environment
1491
+ - `connectionKey`: The connection key used in the `@connection(key: "...")` directive
1492
+ - `parentId`: The data ID of the parent record that holds the connection
1493
+ - `excludedIds`: Optional array of connection data IDs to exclude from invalidation
1494
+
1495
+ ## Examples
1496
+
1497
+ ### Basic Usage
1498
+ ```rescript
1499
+ // Invalidate all connections for a user's friends
1500
+ environment->RescriptRelay.Environment.invalidateAllOfConnection(
1501
+ ~connectionKey=UserProfile_friends_graphql.connectionKey,
1502
+ ~parentId=user.__id,
1503
+ )
1504
+ ```
1505
+
1506
+ ### With Excluded IDs
1507
+ ```rescript
1508
+ environment->RescriptRelay.Environment.invalidateAllOfConnection(
1509
+ ~connectionKey=UserProfile_friends_graphql.connectionKey,
1510
+ ~parentId=user.__id,
1511
+ // Invalidate all of this connection except for the currently rendered one.
1512
+ ~excludedIds=[currentConnection.__id],
1513
+ )
1514
+ ```
1515
+ */
1516
+ let invalidateAllOfConnection: (
1517
+ t,
1518
+ ~connectionKey: string,
1519
+ ~parentId: dataId,
1520
+ ~excludedIds: array<dataId>=?,
1521
+ ) => unit
808
1522
  }
809
1523
 
810
1524
  /**fetchPolicy controls how you want Relay to resolve your data.*/
@@ -865,14 +1579,72 @@ let useEnvironmentFromContext: unit => Environment.t
865
1579
 
866
1580
  /**An exception detailing that a mutation failed.*/ exception Mutation_failed(array<mutationError>)
867
1581
 
868
- /**A way of committing a local update to the store.*/
1582
+ /**
1583
+ Commits a local update to the Relay store.
1584
+
1585
+ Performs imperative updates to the store without triggering network requests.
1586
+ Use this for client-side only changes like toggling UI state or updating
1587
+ local fields that don't need server synchronization.
1588
+
1589
+ ## Parameters
1590
+ - `environment`: The Relay environment
1591
+ - `updater`: Function that receives the store and performs updates
1592
+
1593
+ ## Examples
1594
+
1595
+ ```rescript
1596
+ // Toggle a local UI state
1597
+ RescriptRelay.commitLocalUpdate(
1598
+ ~environment,
1599
+ ~updater=store => {
1600
+ let user = store->RescriptRelay.RecordSourceSelectorProxy.get(~dataId=userId)
1601
+ switch user {
1602
+ | Some(userRecord) =>
1603
+ let _ = userRecord->RescriptRelay.RecordProxy.setValueBool(
1604
+ ~value=!isExpanded,
1605
+ ~name="isExpanded"
1606
+ )
1607
+ | None => ()
1608
+ }
1609
+ }
1610
+ )
1611
+ ```
1612
+ */
869
1613
  @module("relay-runtime")
870
1614
  external commitLocalUpdate: (
871
1615
  ~environment: Environment.t,
872
1616
  ~updater: RecordSourceSelectorProxy.t => unit,
873
1617
  ) => unit = "commitLocalUpdate"
874
1618
 
875
- /**Allows you to subscribe to when a record, connection, or even the store itself is invalidated, and then react to that.*/
1619
+ /**
1620
+ Subscribes to invalidation events for specific records.
1621
+
1622
+ Executes a callback whenever any of the specified records are invalidated.
1623
+ Useful for triggering refetches or UI updates when cached data becomes stale.
1624
+
1625
+ ## Parameters
1626
+ - Array of `dataId`s to watch for invalidation
1627
+ - Callback function executed when any watched record is invalidated
1628
+
1629
+ ## Examples
1630
+
1631
+ ```rescript
1632
+ // Watch for user invalidation and refetch
1633
+ let disposable = RescriptRelay.useSubscribeToInvalidationState(
1634
+ [user.__id],
1635
+ () => {
1636
+ // Refetch user data when invalidated
1637
+ UserQuery.fetchPromised(~environment, ~variables={id: user.id})
1638
+ ->Promise.done
1639
+ }
1640
+ )
1641
+
1642
+ // Clean up subscription
1643
+ React.useEffect1(() => {
1644
+ Some(() => disposable->RescriptRelay.Disposable.dispose)
1645
+ }, [disposable])
1646
+ ```
1647
+ */
876
1648
  @module("react-relay")
877
1649
  external useSubscribeToInvalidationState: (array<dataId>, unit => unit) => Disposable.t =
878
1650
  "useSubscribeToInvalidationState"