rescript-relay 3.0.0 → 3.1.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.
- package/CHANGELOG.md +11 -2
- package/README.md +2 -2
- package/package.json +6 -6
- package/ppx-linux +0 -0
- package/ppx-macos-arm64 +0 -0
- package/ppx-macos-latest +0 -0
- package/ppx-windows-latest +0 -0
- package/relay-compiler-linux-musl/relay +0 -0
- package/relay-compiler-linux-x64/relay +0 -0
- package/relay-compiler-macos-arm64/relay +0 -0
- package/relay-compiler-macos-x64/relay +0 -0
- package/relay-compiler-win-x64/relay.exe +0 -0
- package/src/RescriptRelay.bs.js +44 -6
- package/src/RescriptRelay.res +58 -4
- package/src/RescriptRelay.resi +22 -2
- package/src/RescriptRelay_Fragment.bs.js +7 -0
- package/src/RescriptRelay_Fragment.res +17 -0
- package/src/RescriptRelay_Fragment.resi +7 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
# master
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
# 3.1.0
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
- **Upgrade versions**: `react-relay` and `relay-runtime` to `18.2.0`.
|
|
6
|
+
- Add support for `Fragment.waitForFragmentData`, a new API in Relay 18.2 that lets you wait for fragment data outside of React.
|
|
7
|
+
- Experimental: Add a "non React" mode to the PPX, which makes sure only APIs that don't rely on React directly are exposed. This is intended to be a way to simplify using RescriptRelay without React. Activate by passing `-non-react` to the PPX, like `"ppx-flags": [["rescript-relay/ppx", "-non-react"]]`.
|
|
8
|
+
|
|
9
|
+
# 3.0.1
|
|
10
|
+
|
|
11
|
+
- Add `Environment.findAllConnectionIds` for finding all IDs of all connection instances for a specific connection, regardless of what configs that connection has been fetched (and cached) with.
|
|
12
|
+
- Add `RecordSourceSelectorProxy.invalidateRecordsByIds` for invalidating multilple records at the same time.
|
|
13
|
+
- Allow configuring input unions via `inputUnions` in `relay.config.js` as an escape hatch for when `@oneOf` support on your server is tricky to set up.
|
|
14
|
+
- Move `@rescript/react` to `>=0.13.0`.
|
|
6
15
|
|
|
7
16
|
# 3.0.0 stable
|
|
8
17
|
|
package/README.md
CHANGED
|
@@ -103,8 +103,8 @@ let make = () => {
|
|
|
103
103
|
There's plenty of work ongoing to bring RescriptRelay to full ReScript v11 support, including uncurried mode. Here's the versioning scheme that'll be followed going forward:
|
|
104
104
|
|
|
105
105
|
- 1.x will receive critical bug fixes etc, but new features won't be added
|
|
106
|
-
- 2.x will
|
|
107
|
-
- 3.x
|
|
106
|
+
- 2.x will focus on compatibility with ReScript v11, and uncurried mode (uncurried mode will be optional). This is intended to make the transition to v11+ smooth
|
|
107
|
+
- 3.x is fully embracing uncurried mode (no curried mode available), and adds a bunch of new stuff + change existing APIs to make them better and more ergonomic
|
|
108
108
|
|
|
109
109
|
## Examples
|
|
110
110
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rescript-relay",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"main": "src/RescriptRelay.res",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Gabriel Nordeborn",
|
|
@@ -49,14 +49,14 @@
|
|
|
49
49
|
"node-fetch": "^2.6.0",
|
|
50
50
|
"react": "18.2.0",
|
|
51
51
|
"react-dom": "18.2.0",
|
|
52
|
-
"react-relay": "
|
|
53
|
-
"relay-runtime": "
|
|
52
|
+
"react-relay": "18.2.0",
|
|
53
|
+
"relay-runtime": "18.2.0",
|
|
54
54
|
"rescript": "11.1.1"
|
|
55
55
|
},
|
|
56
56
|
"peerDependencies": {
|
|
57
|
-
"@rescript/react": "
|
|
58
|
-
"react-relay": "
|
|
59
|
-
"relay-runtime": "
|
|
57
|
+
"@rescript/react": ">=0.13.0",
|
|
58
|
+
"react-relay": "18.2.0",
|
|
59
|
+
"relay-runtime": "18.2.0",
|
|
60
60
|
"rescript": "^11.0.0"
|
|
61
61
|
},
|
|
62
62
|
"dependencies": {
|
package/ppx-linux
CHANGED
|
Binary file
|
package/ppx-macos-arm64
CHANGED
|
Binary file
|
package/ppx-macos-latest
CHANGED
|
Binary file
|
package/ppx-windows-latest
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/src/RescriptRelay.bs.js
CHANGED
|
@@ -3,13 +3,15 @@
|
|
|
3
3
|
|
|
4
4
|
var React = require("react");
|
|
5
5
|
var Utils = require("./utils");
|
|
6
|
+
var Js_dict = require("rescript/lib/js/js_dict.js");
|
|
6
7
|
var Belt_Array = require("rescript/lib/js/belt_Array.js");
|
|
8
|
+
var Belt_Option = require("rescript/lib/js/belt_Option.js");
|
|
7
9
|
var Caml_option = require("rescript/lib/js/caml_option.js");
|
|
8
10
|
var ReactRelay = require("react-relay");
|
|
9
11
|
var RelayRuntime = require("relay-runtime");
|
|
10
12
|
var Caml_exceptions = require("rescript/lib/js/caml_exceptions.js");
|
|
11
|
-
var LiveResolverStore = require("relay-runtime/lib/store/
|
|
12
|
-
var LiveResolverStore$1 = require("relay-runtime/lib/store/
|
|
13
|
+
var LiveResolverStore = require("relay-runtime/lib/store/live-resolvers/LiveResolverStore").default;
|
|
14
|
+
var LiveResolverStore$1 = require("relay-runtime/lib/store/live-resolvers/LiveResolverStore");
|
|
13
15
|
|
|
14
16
|
var SuspenseSentinel = {};
|
|
15
17
|
|
|
@@ -42,8 +44,17 @@ function getPluralRootField(t, fieldName) {
|
|
|
42
44
|
return optArrayOfNullableToOptArrayOfOpt(Caml_option.nullable_to_opt(t.getPluralRootField(fieldName)));
|
|
43
45
|
}
|
|
44
46
|
|
|
47
|
+
function invalidateRecordsByIds(store, recordIds) {
|
|
48
|
+
recordIds.forEach(function (dataId) {
|
|
49
|
+
Belt_Option.forEach(Caml_option.nullable_to_opt(store.get(dataId)), (function (r) {
|
|
50
|
+
r.invalidateRecord();
|
|
51
|
+
}));
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
45
55
|
var RecordSourceSelectorProxy = {
|
|
46
|
-
getPluralRootField: getPluralRootField
|
|
56
|
+
getPluralRootField: getPluralRootField,
|
|
57
|
+
invalidateRecordsByIds: invalidateRecordsByIds
|
|
47
58
|
};
|
|
48
59
|
|
|
49
60
|
var ReadOnlyRecordSourceProxy = {};
|
|
@@ -198,14 +209,14 @@ function make(source, gcReleaseBufferSize, queryCacheExpirationTime) {
|
|
|
198
209
|
}
|
|
199
210
|
|
|
200
211
|
function makeLiveStore(source, gcReleaseBufferSize, queryCacheExpirationTime) {
|
|
201
|
-
return new LiveResolverStore
|
|
212
|
+
return new LiveResolverStore(source, {
|
|
202
213
|
gcReleaseBufferSize: gcReleaseBufferSize,
|
|
203
214
|
queryCacheExpirationTime: queryCacheExpirationTime
|
|
204
215
|
});
|
|
205
216
|
}
|
|
206
217
|
|
|
207
218
|
function _makeLiveStoreCjs(source, gcReleaseBufferSize, queryCacheExpirationTime) {
|
|
208
|
-
return new LiveResolverStore(source, {
|
|
219
|
+
return new LiveResolverStore$1(source, {
|
|
209
220
|
gcReleaseBufferSize: gcReleaseBufferSize,
|
|
210
221
|
queryCacheExpirationTime: queryCacheExpirationTime
|
|
211
222
|
});
|
|
@@ -231,8 +242,35 @@ function make$1(network, store, getDataID, treatMissingFieldsAsNull, missingFiel
|
|
|
231
242
|
});
|
|
232
243
|
}
|
|
233
244
|
|
|
245
|
+
function findAllConnectionIds(environment, connectionKey, parentId) {
|
|
246
|
+
var ids = [];
|
|
247
|
+
var value = environment.getStore().getSource()._records.get(parentId);
|
|
248
|
+
if (value !== undefined) {
|
|
249
|
+
Js_dict.entries(value).forEach(function (param) {
|
|
250
|
+
if (param[0].startsWith("__" + connectionKey + "_connection")) {
|
|
251
|
+
ids.push(param[1].__ref);
|
|
252
|
+
return ;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
return ids;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function invalidateAllOfConnection(environment, connectionKey, parentId) {
|
|
261
|
+
RelayRuntime.commitLocalUpdate(environment, (function (store) {
|
|
262
|
+
findAllConnectionIds(environment, connectionKey, parentId).forEach(function (dataId) {
|
|
263
|
+
Belt_Option.forEach(Caml_option.nullable_to_opt(store.get(dataId)), (function (r) {
|
|
264
|
+
r.invalidateRecord();
|
|
265
|
+
}));
|
|
266
|
+
});
|
|
267
|
+
}));
|
|
268
|
+
}
|
|
269
|
+
|
|
234
270
|
var Environment = {
|
|
235
|
-
make: make$1
|
|
271
|
+
make: make$1,
|
|
272
|
+
findAllConnectionIds: findAllConnectionIds,
|
|
273
|
+
invalidateAllOfConnection: invalidateAllOfConnection
|
|
236
274
|
};
|
|
237
275
|
|
|
238
276
|
function RescriptRelay$Context$Provider(props) {
|
package/src/RescriptRelay.res
CHANGED
|
@@ -312,6 +312,12 @@ module RecordSourceSelectorProxy = {
|
|
|
312
312
|
getPluralRootField(t, ~fieldName)->optArrayOfNullableToOptArrayOfOpt
|
|
313
313
|
|
|
314
314
|
@send external invalidateStore: t => unit = "invalidateStore"
|
|
315
|
+
|
|
316
|
+
let invalidateRecordsByIds: (t, array<dataId>) => unit = (store, recordIds) => {
|
|
317
|
+
recordIds->Js.Array2.forEach(dataId => {
|
|
318
|
+
store->get(~dataId)->Belt.Option.forEach(r => r->RecordProxy.invalidateRecord)
|
|
319
|
+
})
|
|
320
|
+
}
|
|
315
321
|
}
|
|
316
322
|
|
|
317
323
|
module ReadOnlyRecordSourceProxy = {
|
|
@@ -637,9 +643,9 @@ module Store = {
|
|
|
637
643
|
|
|
638
644
|
@module @new
|
|
639
645
|
external makeLiveStoreCjs: (RecordSource.t, storeConfig) => t =
|
|
640
|
-
"relay-runtime/lib/store/
|
|
646
|
+
"relay-runtime/lib/store/live-resolvers/LiveResolverStore"
|
|
641
647
|
|
|
642
|
-
@module("relay-runtime/lib/store/
|
|
648
|
+
@module("relay-runtime/lib/store/live-resolvers/LiveResolverStore") @new
|
|
643
649
|
external makeLiveStore: (RecordSource.t, storeConfig) => t = "default"
|
|
644
650
|
|
|
645
651
|
@module("relay-runtime") @new
|
|
@@ -680,8 +686,19 @@ module Store = {
|
|
|
680
686
|
module RelayFieldLogger = {
|
|
681
687
|
@tag("kind")
|
|
682
688
|
type arg =
|
|
683
|
-
| @as("
|
|
684
|
-
| @as("
|
|
689
|
+
| @as("missing_required_field.log") MissingRequiredFieldLog({owner: string, fieldPath: string})
|
|
690
|
+
| @as("missing_required_field.throw")
|
|
691
|
+
MissingRequiredFieldThrow({
|
|
692
|
+
owner: string,
|
|
693
|
+
fieldPath: string,
|
|
694
|
+
})
|
|
695
|
+
| @as("missing_expected_data.log") MissingExpectedData({owner: string, fieldPath: string})
|
|
696
|
+
| @as("missing_expected_data.throw")
|
|
697
|
+
MissingExpectedDataThrow({
|
|
698
|
+
owner: string,
|
|
699
|
+
fieldPath: string,
|
|
700
|
+
handled: bool,
|
|
701
|
+
})
|
|
685
702
|
| @as("relay_resolver.error")
|
|
686
703
|
RelayResolverError({
|
|
687
704
|
owner: string,
|
|
@@ -734,6 +751,43 @@ module Environment = {
|
|
|
734
751
|
@send
|
|
735
752
|
external commitPayload: (t, operationDescriptor, 'payload) => unit = "commitPayload"
|
|
736
753
|
@send external retain: (t, operationDescriptor) => Disposable.t = "retain"
|
|
754
|
+
|
|
755
|
+
@module("relay-runtime")
|
|
756
|
+
external commitLocalUpdate: (t, ~updater: RecordSourceSelectorProxy.t => unit) => unit =
|
|
757
|
+
"commitLocalUpdate"
|
|
758
|
+
|
|
759
|
+
@send external mapGet: (Js.Map.t<'key, 'value>, 'key) => option<'value> = "get"
|
|
760
|
+
|
|
761
|
+
type recordValue = {__ref: dataId}
|
|
762
|
+
@get external _records: RecordSource.t => Js.Map.t<string, Js.Dict.t<recordValue>> = "_records"
|
|
763
|
+
|
|
764
|
+
let findAllConnectionIds = (environment: t, ~connectionKey: string, ~parentId: dataId) => {
|
|
765
|
+
let ids = []
|
|
766
|
+
switch environment->getStore->Store.getSource->_records->mapGet(parentId->dataIdToString) {
|
|
767
|
+
| Some(value) =>
|
|
768
|
+
value
|
|
769
|
+
->Js.Dict.entries
|
|
770
|
+
->Js.Array2.forEach(((key, v)) => {
|
|
771
|
+
if key->Js.String2.startsWith("__" ++ connectionKey ++ "_connection") {
|
|
772
|
+
let _ = ids->Js.Array2.push(v.__ref)
|
|
773
|
+
}
|
|
774
|
+
})
|
|
775
|
+
| _ => ()
|
|
776
|
+
}
|
|
777
|
+
ids
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
let invalidateAllOfConnection = (environment: t, ~connectionKey: string, ~parentId: dataId) => {
|
|
781
|
+
environment->commitLocalUpdate(~updater=store => {
|
|
782
|
+
environment
|
|
783
|
+
->findAllConnectionIds(~connectionKey, ~parentId)
|
|
784
|
+
->Js.Array2.forEach(dataId => {
|
|
785
|
+
store
|
|
786
|
+
->RecordSourceSelectorProxy.get(~dataId)
|
|
787
|
+
->Belt.Option.forEach(r => r->RecordProxy.invalidateRecord)
|
|
788
|
+
})
|
|
789
|
+
})
|
|
790
|
+
}
|
|
737
791
|
}
|
|
738
792
|
|
|
739
793
|
module Context = {
|
package/src/RescriptRelay.resi
CHANGED
|
@@ -399,6 +399,9 @@ module RecordSourceSelectorProxy: {
|
|
|
399
399
|
/**Invalidates the entire store. This means that _at the next render_, the entire store will be treated as empty, meaning Relay will refetch everything it needs to show the view it's to show.*/
|
|
400
400
|
@send
|
|
401
401
|
external invalidateStore: t => unit = "invalidateStore"
|
|
402
|
+
|
|
403
|
+
/**Invalidates each of the provided records by their ID, if they exist. */
|
|
404
|
+
let invalidateRecordsByIds: (t, array<dataId>) => unit
|
|
402
405
|
}
|
|
403
406
|
|
|
404
407
|
/**ReadOnlyRecordSourceProxy is the store, but in read-only mode.*/
|
|
@@ -741,8 +744,19 @@ module Disposable: {
|
|
|
741
744
|
module RelayFieldLogger: {
|
|
742
745
|
@tag("kind")
|
|
743
746
|
type arg =
|
|
744
|
-
| @as("
|
|
745
|
-
| @as("
|
|
747
|
+
| @as("missing_required_field.log") MissingRequiredFieldLog({owner: string, fieldPath: string})
|
|
748
|
+
| @as("missing_required_field.throw")
|
|
749
|
+
MissingRequiredFieldThrow({
|
|
750
|
+
owner: string,
|
|
751
|
+
fieldPath: string,
|
|
752
|
+
})
|
|
753
|
+
| @as("missing_expected_data.log") MissingExpectedData({owner: string, fieldPath: string})
|
|
754
|
+
| @as("missing_expected_data.throw")
|
|
755
|
+
MissingExpectedDataThrow({
|
|
756
|
+
owner: string,
|
|
757
|
+
fieldPath: string,
|
|
758
|
+
handled: bool,
|
|
759
|
+
})
|
|
746
760
|
| @as("relay_resolver.error")
|
|
747
761
|
RelayResolverError({
|
|
748
762
|
owner: string,
|
|
@@ -785,6 +799,12 @@ module Environment: {
|
|
|
785
799
|
You should use the generated `Query.retain` function on your queries instead of using this directly.*/
|
|
786
800
|
@send
|
|
787
801
|
external retain: (t, operationDescriptor) => Disposable.t = "retain"
|
|
802
|
+
|
|
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. */
|
|
804
|
+
let findAllConnectionIds: (t, ~connectionKey: string, ~parentId: dataId) => array<dataId>
|
|
805
|
+
|
|
806
|
+
/**Invalidates all connection configurations of `connectionKey` on `parentId`.*/
|
|
807
|
+
let invalidateAllOfConnection: (t, ~connectionKey: string, ~parentId: dataId) => unit
|
|
788
808
|
}
|
|
789
809
|
|
|
790
810
|
/**fetchPolicy controls how you want Relay to resolve your data.*/
|
|
@@ -5,6 +5,7 @@ var React = require("react");
|
|
|
5
5
|
var Caml_option = require("rescript/lib/js/caml_option.js");
|
|
6
6
|
var ReactRelay = require("react-relay");
|
|
7
7
|
var RescriptRelay_Internal = require("./RescriptRelay_Internal.bs.js");
|
|
8
|
+
var Experimental = require("relay-runtime/experimental");
|
|
8
9
|
var ResolverFragments = require("relay-runtime/lib/store/ResolverFragments");
|
|
9
10
|
var UseBlockingPaginationFragment = require("react-relay/lib/relay-hooks/legacy/useBlockingPaginationFragment").default;
|
|
10
11
|
|
|
@@ -112,6 +113,11 @@ function useRefetchableFragment(node, convertFragment, convertRefetchVariables,
|
|
|
112
113
|
];
|
|
113
114
|
}
|
|
114
115
|
|
|
116
|
+
async function waitForFragmentData(environment, node, convertFragment, fRef) {
|
|
117
|
+
var fragmentData = await Experimental.waitForFragmentData(environment, node, fRef);
|
|
118
|
+
return convertFragment(fragmentData);
|
|
119
|
+
}
|
|
120
|
+
|
|
115
121
|
exports.useFragment = useFragment;
|
|
116
122
|
exports.useFragmentOpt = useFragmentOpt;
|
|
117
123
|
exports.readInlineData = readInlineData;
|
|
@@ -119,4 +125,5 @@ exports.read = read;
|
|
|
119
125
|
exports.usePaginationFragment = usePaginationFragment;
|
|
120
126
|
exports.useBlockingPaginationFragment = useBlockingPaginationFragment;
|
|
121
127
|
exports.useRefetchableFragment = useRefetchableFragment;
|
|
128
|
+
exports.waitForFragmentData = waitForFragmentData;
|
|
122
129
|
/* react Not a pure module */
|
|
@@ -241,3 +241,20 @@ let useRefetchableFragment = (
|
|
|
241
241
|
),
|
|
242
242
|
)
|
|
243
243
|
}
|
|
244
|
+
|
|
245
|
+
@module("relay-runtime/experimental")
|
|
246
|
+
external waitForFragmentData_: (
|
|
247
|
+
Environment.t,
|
|
248
|
+
fragmentNode<'node>,
|
|
249
|
+
'fragmentRef,
|
|
250
|
+
) => promise<'fragment> = "waitForFragmentData"
|
|
251
|
+
|
|
252
|
+
let waitForFragmentData = async (
|
|
253
|
+
~environment,
|
|
254
|
+
~node,
|
|
255
|
+
~convertFragment: 'fragment => 'fragment,
|
|
256
|
+
~fRef,
|
|
257
|
+
) => {
|
|
258
|
+
let fragmentData = await waitForFragmentData_(environment, node, fRef)
|
|
259
|
+
convertFragment(fragmentData)
|
|
260
|
+
}
|
|
@@ -83,3 +83,10 @@ let useRefetchableFragment: (
|
|
|
83
83
|
~onComplete: option<Js.Exn.t> => unit=?,
|
|
84
84
|
) => Disposable.t,
|
|
85
85
|
)
|
|
86
|
+
|
|
87
|
+
let waitForFragmentData: (
|
|
88
|
+
~environment: Environment.t,
|
|
89
|
+
~node: fragmentNode<'a>,
|
|
90
|
+
~convertFragment: 'fragment => 'fragment,
|
|
91
|
+
~fRef: 'b,
|
|
92
|
+
) => promise<'fragment>
|