@pomwik/afterdb-react 0.0.0-stage → 0.20.2
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/CHANGES-FROM-UPSTREAM.md +59 -0
- package/LICENSE +177 -0
- package/NOTICE +9 -0
- package/README.md +10 -2
- package/dist/RealmContext.d.ts +153 -0
- package/dist/RealmContext.d.ts.map +1 -0
- package/dist/RealmProvider.d.ts +95 -0
- package/dist/RealmProvider.d.ts.map +1 -0
- package/dist/cachedCollection.d.ts +58 -0
- package/dist/cachedCollection.d.ts.map +1 -0
- package/dist/cachedObject.d.ts +48 -0
- package/dist/cachedObject.d.ts.map +1 -0
- package/dist/helpers.d.ts +22 -0
- package/dist/helpers.d.ts.map +1 -0
- package/dist/index.cjs +2818 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +100 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2809 -0
- package/dist/index.js.map +1 -0
- package/dist/tsconfig.types.tsbuildinfo +1 -0
- package/dist/types.d.ts +64 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/useObject.d.ts +30 -0
- package/dist/useObject.d.ts.map +1 -0
- package/dist/useQuery.d.ts +31 -0
- package/dist/useQuery.d.ts.map +1 -0
- package/dist/useRealm.d.ts +12 -0
- package/dist/useRealm.d.ts.map +1 -0
- package/package.json +117 -4
- package/src/RealmContext.ts +196 -0
- package/src/RealmProvider.tsx +251 -0
- package/src/__tests__/RealmProvider.test.tsx +583 -0
- package/src/__tests__/createRealmTestContext.ts +68 -0
- package/src/__tests__/helpers.ts +35 -0
- package/src/__tests__/mocks.ts +154 -0
- package/src/__tests__/profileHook.tsx +76 -0
- package/src/__tests__/setup.ts +22 -0
- package/src/__tests__/tsconfig.json +14 -0
- package/src/__tests__/useObjectHook.test.tsx +158 -0
- package/src/__tests__/useObjectRender.test.tsx +630 -0
- package/src/__tests__/useQueryHook.test.tsx +209 -0
- package/src/__tests__/useQueryRender.test.tsx +463 -0
- package/src/cachedCollection.ts +210 -0
- package/src/cachedObject.ts +164 -0
- package/src/helpers.ts +60 -0
- package/src/index.tsx +130 -0
- package/src/runtime.d.ts +31 -0
- package/src/types.ts +92 -0
- package/src/useObject.tsx +227 -0
- package/src/useQuery.tsx +205 -0
- package/src/useRealm.tsx +41 -0
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
//
|
|
3
|
+
// Copyright 2024 Realm Inc.
|
|
4
|
+
//
|
|
5
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
// you may not use this file except in compliance with the License.
|
|
7
|
+
// You may obtain a copy of the License at
|
|
8
|
+
//
|
|
9
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
//
|
|
11
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
// See the License for the specific language governing permissions and
|
|
15
|
+
// limitations under the License.
|
|
16
|
+
//
|
|
17
|
+
////////////////////////////////////////////////////////////////////////////
|
|
18
|
+
|
|
19
|
+
import { createUseObject } from "./useObject";
|
|
20
|
+
import { createUseQuery } from "./useQuery";
|
|
21
|
+
import { createUseRealm } from "./useRealm";
|
|
22
|
+
import {
|
|
23
|
+
DynamicRealmProvider,
|
|
24
|
+
RealmProviderFromConfiguration,
|
|
25
|
+
RealmProviderFromRealm,
|
|
26
|
+
createRealmProvider,
|
|
27
|
+
} from "./RealmProvider";
|
|
28
|
+
import { createContext } from "react";
|
|
29
|
+
import Realm from "realm";
|
|
30
|
+
|
|
31
|
+
export type RealmContext<RealmProvider = DynamicRealmProvider> = {
|
|
32
|
+
/**
|
|
33
|
+
* The Provider component that is required to wrap any component using
|
|
34
|
+
* the Realm hooks.
|
|
35
|
+
* @example
|
|
36
|
+
* ```
|
|
37
|
+
* const AppRoot = () => {
|
|
38
|
+
* const syncConfig = {
|
|
39
|
+
* flexible: true,
|
|
40
|
+
* user: currentUser
|
|
41
|
+
* };
|
|
42
|
+
*
|
|
43
|
+
* return (
|
|
44
|
+
* <RealmProvider schema={[Task, User]} path={"data.realm"} sync={syncConfig}>
|
|
45
|
+
* <App/>
|
|
46
|
+
* </RealmProvider>
|
|
47
|
+
* )
|
|
48
|
+
* }
|
|
49
|
+
* ```
|
|
50
|
+
* @param props - The {@link Realm.Configuration} or {@link Realm} of the provider
|
|
51
|
+
* are set based on the options passed to `createRealmProvider`. When using a
|
|
52
|
+
* {@link Realm.Configuration}, individual config keys can be overridden when
|
|
53
|
+
* creating a `<RealmProvider>` by passing them as props. For example, to override
|
|
54
|
+
* the `path` config value, use a prop named `path` e.g., `path="newPath.realm"` an
|
|
55
|
+
* attribute of the same key.
|
|
56
|
+
*/
|
|
57
|
+
RealmProvider: RealmProvider;
|
|
58
|
+
/**
|
|
59
|
+
* Returns the instance of the {@link Realm} opened by the `RealmProvider`.
|
|
60
|
+
* @example
|
|
61
|
+
* ```
|
|
62
|
+
* const realm = useRealm();
|
|
63
|
+
* ```
|
|
64
|
+
* @returns a realm instance
|
|
65
|
+
*/
|
|
66
|
+
useRealm: ReturnType<typeof createUseRealm>;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Returns a {@link Realm.Collection} of {@link Realm.Object}s from a given type.
|
|
70
|
+
* The hook will update on any changes to any object in the collection.
|
|
71
|
+
*
|
|
72
|
+
* The result of this can be consumed directly by the `data` argument of any React Native
|
|
73
|
+
* VirtualizedList or FlatList. If the component used for the list's `renderItem` prop is {@link React.Memo}ized,
|
|
74
|
+
* then only the modified object will re-render.
|
|
75
|
+
* @example
|
|
76
|
+
* ```tsx
|
|
77
|
+
* // Return all collection items
|
|
78
|
+
* const collection = useQuery({ type: Object });
|
|
79
|
+
*
|
|
80
|
+
* // Return all collection items sorted by name and filtered by category
|
|
81
|
+
* const filteredAndSorted = useQuery({
|
|
82
|
+
* type: Object,
|
|
83
|
+
* query: (collection) => collection.filtered('category == $0',category).sorted('name'),
|
|
84
|
+
* }, [category]);
|
|
85
|
+
*
|
|
86
|
+
* // Return all collection items sorted by name and filtered by category, triggering re-renders only if "name" changes
|
|
87
|
+
* const filteredAndSorted = useQuery({
|
|
88
|
+
* type: Object,
|
|
89
|
+
* query: (collection) => collection.filtered('category == $0',category).sorted('name'),
|
|
90
|
+
* keyPaths: ["name"]
|
|
91
|
+
* }, [category]);
|
|
92
|
+
* ```
|
|
93
|
+
* @param options
|
|
94
|
+
* @param options.type - The object type, depicted by a string or a class extending Realm.Object
|
|
95
|
+
* @param options.query - A function that takes a {@link Realm.Collection} and returns a {@link Realm.Collection} of the same type. This allows for filtering and sorting of the collection, before it is returned.
|
|
96
|
+
* @param options.keyPaths - Indicates a lower bound on the changes relevant for the hook. This is a lower bound, since if multiple hooks add listeners (each with their own `keyPaths`) the union of these key-paths will determine the changes that are considered relevant for all listeners registered on the collection. In other words: A listener might fire and cause a re-render more than the key-paths specify, if other listeners with different key-paths are present.
|
|
97
|
+
* @param deps - An array of dependencies that will be passed to {@link React.useMemo}
|
|
98
|
+
* @returns a collection of realm objects or an empty array
|
|
99
|
+
*/
|
|
100
|
+
useQuery: ReturnType<typeof createUseQuery>;
|
|
101
|
+
/**
|
|
102
|
+
* Returns a {@link Realm.Object} from a given type and value of primary key.
|
|
103
|
+
* The hook will update on any changes to the properties on the returned object
|
|
104
|
+
* and return null if it either doesn't exists or has been deleted.
|
|
105
|
+
* @example
|
|
106
|
+
* ```
|
|
107
|
+
* const object = useObject(ObjectClass, objectId);
|
|
108
|
+
* ```
|
|
109
|
+
* @param type - The object type, depicted by a string or a class extending {@link Realm.Object}
|
|
110
|
+
* @param primaryKey - The primary key of the desired object which will be retrieved using {@link Realm.objectForPrimaryKey}
|
|
111
|
+
* @param keyPaths - Indicates a lower bound on the changes relevant for the hook. This is a lower bound, since if multiple hooks add listeners (each with their own `keyPaths`) the union of these key-paths will determine the changes that are considered relevant for all listeners registered on the object. In other words: A listener might fire and cause a re-render more than the key-paths specify, if other listeners with different key-paths are present.
|
|
112
|
+
* @returns either the desired {@link Realm.Object} or `null` in the case of it being deleted or not existing.
|
|
113
|
+
*/
|
|
114
|
+
useObject: ReturnType<typeof createUseObject>;
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Creates Realm React hooks and Provider component for a given Realm configuration
|
|
119
|
+
* @example
|
|
120
|
+
* ```
|
|
121
|
+
*class Task extends Realm.Object {
|
|
122
|
+
* ...
|
|
123
|
+
*
|
|
124
|
+
* static schema: ObjectSchema = {
|
|
125
|
+
* name: 'Task',
|
|
126
|
+
* primaryKey: '_id',
|
|
127
|
+
* properties: {
|
|
128
|
+
* ...
|
|
129
|
+
* },
|
|
130
|
+
* };
|
|
131
|
+
*}
|
|
132
|
+
*
|
|
133
|
+
*const {useRealm, useQuery, useObject, RealmProvider} = createRealmContext({schema: [Task]});
|
|
134
|
+
* ```
|
|
135
|
+
* @param realmConfig - {@link Realm.Configuration} used to open the Realm
|
|
136
|
+
* @returns An object containing a `RealmProvider` component, and `useRealm`, `useQuery` and `useObject` hooks
|
|
137
|
+
*/
|
|
138
|
+
export function createRealmContext(realmConfig: Realm.Configuration): RealmContext<RealmProviderFromConfiguration>;
|
|
139
|
+
/**
|
|
140
|
+
* Creates Realm React hooks and Provider component for a given Realm instance.
|
|
141
|
+
*
|
|
142
|
+
* **Note:** the hooks returned from `createRealmContext` using an existing Realm can be used outside of the scope of the provider.
|
|
143
|
+
* @example
|
|
144
|
+
* ```
|
|
145
|
+
* const realm = new Realm({ schema: [...] });
|
|
146
|
+
* const {useRealm, useQuery, useObject, RealmProvider} = createRealmContext(realm);
|
|
147
|
+
* ```
|
|
148
|
+
* @param realm - {@link Realm} instance
|
|
149
|
+
* @returns An object containing a `RealmProvider` component, and `useRealm`, `useQuery` and `useObject` hooks
|
|
150
|
+
*/
|
|
151
|
+
export function createRealmContext(realm: Realm): RealmContext<RealmProviderFromRealm>;
|
|
152
|
+
/**
|
|
153
|
+
* Creates Realm React hooks and Provider component.
|
|
154
|
+
* @example
|
|
155
|
+
* ```
|
|
156
|
+
* class Task extends Realm.Object {
|
|
157
|
+
* ...
|
|
158
|
+
* static schema: ObjectSchema = {
|
|
159
|
+
* name: 'Task',
|
|
160
|
+
* primaryKey: '_id',
|
|
161
|
+
* properties: {
|
|
162
|
+
* ...
|
|
163
|
+
* },
|
|
164
|
+
* };
|
|
165
|
+
* }
|
|
166
|
+
* const {useRealm, useQuery, useObject, RealmProvider} = createRealmContext();
|
|
167
|
+
* ...
|
|
168
|
+
* <RealmProvider schema={[Task]}></RealmProvider>
|
|
169
|
+
* ```
|
|
170
|
+
* @example
|
|
171
|
+
* ```
|
|
172
|
+
* const realm = await Realm.open({ path: "example.realm", schema: [Task] });
|
|
173
|
+
* const {RealmProvider} = createRealmContext();
|
|
174
|
+
* ...
|
|
175
|
+
* <RealmProvider realm={realm}></RealmProvider>
|
|
176
|
+
* ```
|
|
177
|
+
* @returns An object containing a `RealmProvider` component, and `useRealm`, `useQuery` and `useObject` hooks
|
|
178
|
+
*/
|
|
179
|
+
export function createRealmContext(): RealmContext<DynamicRealmProvider>;
|
|
180
|
+
export function createRealmContext(
|
|
181
|
+
realmOrConfig?: Realm | Realm.Configuration,
|
|
182
|
+
): RealmContext<RealmProviderFromConfiguration | RealmProviderFromRealm | DynamicRealmProvider> {
|
|
183
|
+
const RealmContext = createContext<Realm | null>(realmOrConfig instanceof Realm ? realmOrConfig : null);
|
|
184
|
+
const RealmProvider = createRealmProvider(realmOrConfig, RealmContext);
|
|
185
|
+
|
|
186
|
+
const useRealm = createUseRealm(RealmContext);
|
|
187
|
+
const useQuery = createUseQuery(useRealm);
|
|
188
|
+
const useObject = createUseObject(useRealm);
|
|
189
|
+
|
|
190
|
+
return {
|
|
191
|
+
RealmProvider,
|
|
192
|
+
useRealm,
|
|
193
|
+
useQuery,
|
|
194
|
+
useObject,
|
|
195
|
+
};
|
|
196
|
+
}
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
//
|
|
3
|
+
// Copyright 2021 Realm Inc.
|
|
4
|
+
//
|
|
5
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
// you may not use this file except in compliance with the License.
|
|
7
|
+
// You may obtain a copy of the License at
|
|
8
|
+
//
|
|
9
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
//
|
|
11
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
// See the License for the specific language governing permissions and
|
|
15
|
+
// limitations under the License.
|
|
16
|
+
//
|
|
17
|
+
////////////////////////////////////////////////////////////////////////////
|
|
18
|
+
|
|
19
|
+
import React, { useContext, useEffect, useRef, useState } from "react";
|
|
20
|
+
import Realm from "realm";
|
|
21
|
+
import isEqual from "lodash.isequal";
|
|
22
|
+
|
|
23
|
+
import { RestrictivePick } from "./helpers";
|
|
24
|
+
|
|
25
|
+
type PartialRealmConfiguration = Partial<Realm.Configuration>;
|
|
26
|
+
|
|
27
|
+
export type RealmProviderFallback = React.ComponentType;
|
|
28
|
+
|
|
29
|
+
/** Props used for a configuration-based Realm provider */
|
|
30
|
+
type RealmProviderConfigurationProps = {
|
|
31
|
+
/**
|
|
32
|
+
* If false, Realm will not be closed when the component unmounts.
|
|
33
|
+
* @default true
|
|
34
|
+
*/
|
|
35
|
+
closeOnUnmount?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* A ref to the Realm instance. This is useful if you need to access the Realm
|
|
38
|
+
* instance outside of a component that uses the Realm hooks.
|
|
39
|
+
*/
|
|
40
|
+
realmRef?: React.MutableRefObject<Realm | null>;
|
|
41
|
+
/**
|
|
42
|
+
* The fallback component to render if the Realm is not open.
|
|
43
|
+
*/
|
|
44
|
+
fallback?: RealmProviderFallback | React.ComponentType | React.ReactElement | null | undefined;
|
|
45
|
+
children: React.ReactNode;
|
|
46
|
+
} & PartialRealmConfiguration;
|
|
47
|
+
|
|
48
|
+
/** Props used for a Realm instance-based Realm provider */
|
|
49
|
+
type RealmProviderRealmProps = {
|
|
50
|
+
/**
|
|
51
|
+
* The Realm instance to be used by the provider.
|
|
52
|
+
*/
|
|
53
|
+
realm: Realm;
|
|
54
|
+
children: React.ReactNode;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
type RealmProviderProps = RealmProviderConfigurationProps & RealmProviderRealmProps;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Represents the provider returned from `createRealmContext` with a Realm instance i.e. `createRealmContext(new Realm(...))`.
|
|
61
|
+
* Omits "realm" as it gets set at creation and cannot be changed.
|
|
62
|
+
|
|
63
|
+
* **Note:** the hooks returned from `createRealmContext` using an existing Realm can be used outside of the scope of the provider.
|
|
64
|
+
*/
|
|
65
|
+
export type RealmProviderFromRealm = React.FC<Omit<RealmProviderRealmProps, "realm">>;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Represents the provider returned from `createRealmContext` with a configuration, i.e. `createRealmContext({schema: [...]})`.
|
|
69
|
+
*/
|
|
70
|
+
export type RealmProviderFromConfiguration = React.FC<RealmProviderConfigurationProps>;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Represents properties of a {@link DynamicRealmProvider} where Realm instance props are set and Configuration props are disallowed.
|
|
74
|
+
*/
|
|
75
|
+
export type DynamicRealmProviderWithRealmProps = RestrictivePick<RealmProviderProps, keyof RealmProviderRealmProps>;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Represents properties of a {@link DynamicRealmProvider} where Realm configuration props are set and Realm instance props are disallowed.
|
|
79
|
+
*/
|
|
80
|
+
export type DynamicRealmProviderWithConfigurationProps = RestrictivePick<
|
|
81
|
+
RealmProviderProps,
|
|
82
|
+
keyof RealmProviderConfigurationProps
|
|
83
|
+
>;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Represents the provider returned from creating context with no arguments (including the default context).
|
|
87
|
+
* Supports either {@link RealmProviderRealmProps} or {@link RealmProviderConfigurationProps}.
|
|
88
|
+
*/
|
|
89
|
+
export type DynamicRealmProvider = React.FC<
|
|
90
|
+
DynamicRealmProviderWithRealmProps | DynamicRealmProviderWithConfigurationProps
|
|
91
|
+
>;
|
|
92
|
+
|
|
93
|
+
export function createRealmProviderFromRealm(
|
|
94
|
+
realm: Realm,
|
|
95
|
+
RealmContext: React.Context<Realm | null>,
|
|
96
|
+
): RealmProviderFromRealm {
|
|
97
|
+
return ({ children }) => {
|
|
98
|
+
return <RealmContext.Provider value={realm} children={children} />;
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Generates a `RealmProvider` given a {@link Realm.Configuration} and {@link React.Context}.
|
|
104
|
+
* @param realmConfig - The configuration of the Realm to be instantiated
|
|
105
|
+
* @param RealmContext - The context that will contain the Realm instance
|
|
106
|
+
* @returns a RealmProvider component that provides context to all context hooks
|
|
107
|
+
*/
|
|
108
|
+
export function createRealmProviderFromConfig(
|
|
109
|
+
realmConfig: Realm.Configuration,
|
|
110
|
+
RealmContext: React.Context<Realm | null>,
|
|
111
|
+
): RealmProviderFromConfiguration {
|
|
112
|
+
return ({ children, fallback: Fallback, closeOnUnmount = true, realmRef, ...restProps }) => {
|
|
113
|
+
const [realm, setRealm] = useState<Realm | null>(() =>
|
|
114
|
+
realmConfig.sync === undefined && restProps.sync === undefined
|
|
115
|
+
? new Realm(mergeRealmConfiguration(realmConfig, restProps))
|
|
116
|
+
: null,
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
// We increment `configVersion` when a config override passed as a prop
|
|
120
|
+
// changes, which triggers a `useEffect` to re-open the Realm with the
|
|
121
|
+
// new config
|
|
122
|
+
const [configVersion, setConfigVersion] = useState(0);
|
|
123
|
+
|
|
124
|
+
// We put realm in a ref to avoid have an endless loop of updates when the realm is updated
|
|
125
|
+
const currentRealm = useRef(realm);
|
|
126
|
+
|
|
127
|
+
// This will merge the configuration provided by createRealmContext and any configuration properties
|
|
128
|
+
// set directly on the RealmProvider component. Any settings on the component will override the original configuration.
|
|
129
|
+
const configuration = useRef<Realm.Configuration>(mergeRealmConfiguration(realmConfig, restProps));
|
|
130
|
+
|
|
131
|
+
// Merge and set the configuration again and increment the version if any
|
|
132
|
+
// of the RealmProvider properties change.
|
|
133
|
+
useEffect(() => {
|
|
134
|
+
const combinedConfig = mergeRealmConfiguration(realmConfig, restProps);
|
|
135
|
+
|
|
136
|
+
if (!areConfigurationsIdentical(configuration.current, combinedConfig)) {
|
|
137
|
+
configuration.current = combinedConfig;
|
|
138
|
+
// Only rerender if realm has already been configured
|
|
139
|
+
if (currentRealm.current != null) {
|
|
140
|
+
setConfigVersion((x) => x + 1);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}, [restProps]);
|
|
144
|
+
|
|
145
|
+
useEffect(() => {
|
|
146
|
+
currentRealm.current = realm;
|
|
147
|
+
if (realmRef) {
|
|
148
|
+
realmRef.current = realm;
|
|
149
|
+
}
|
|
150
|
+
}, [realm]);
|
|
151
|
+
|
|
152
|
+
useEffect(() => {
|
|
153
|
+
const realmRef = currentRealm.current;
|
|
154
|
+
// Check if we currently have an open Realm. If we do not (i.e. it is the first
|
|
155
|
+
// render, or the Realm has been closed due to a config change), then we
|
|
156
|
+
// need to open a new Realm.
|
|
157
|
+
const shouldInitRealm = realmRef === null;
|
|
158
|
+
const initRealm = async () => {
|
|
159
|
+
const openRealm = await Realm.open(configuration.current);
|
|
160
|
+
setRealm(openRealm);
|
|
161
|
+
};
|
|
162
|
+
if (shouldInitRealm) {
|
|
163
|
+
initRealm().catch(console.error);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return () => {
|
|
167
|
+
if (realm) {
|
|
168
|
+
if (closeOnUnmount) {
|
|
169
|
+
realm.close();
|
|
170
|
+
}
|
|
171
|
+
setRealm(null);
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
}, [configVersion, realm, setRealm, closeOnUnmount]);
|
|
175
|
+
|
|
176
|
+
if (!realm) {
|
|
177
|
+
if (typeof Fallback === "function") {
|
|
178
|
+
return <Fallback />;
|
|
179
|
+
}
|
|
180
|
+
return <>{Fallback}</>;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return <RealmContext.Provider value={realm} children={children} />;
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Generates a `RealmProvider` which is either based on a configuration
|
|
189
|
+
* or based on a realm, depending on its props.
|
|
190
|
+
* @param RealmContext - The context that will contain the Realm instance
|
|
191
|
+
* @returns a RealmProvider component that provides context to all context hooks
|
|
192
|
+
*/
|
|
193
|
+
export function createDynamicRealmProvider(RealmContext: React.Context<Realm | null>): DynamicRealmProvider {
|
|
194
|
+
const RealmProviderFromConfig = createRealmProviderFromConfig({}, RealmContext);
|
|
195
|
+
return ({ realm, children, ...config }) => {
|
|
196
|
+
if (realm) {
|
|
197
|
+
if (Object.keys(config).length > 0) {
|
|
198
|
+
throw new Error("Cannot use configuration props when using an existing Realm instance.");
|
|
199
|
+
}
|
|
200
|
+
return <RealmContext.Provider value={realm} children={children} />;
|
|
201
|
+
} else {
|
|
202
|
+
return <RealmProviderFromConfig {...config} children={children} />;
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Generates the appropriate `RealmProvider` based on whether there is a config, realm, or neither given.
|
|
209
|
+
* @param realmOrConfig - A Realm instance, a configuration, or undefined (including default provider).
|
|
210
|
+
* @param RealmContext - The context that will contain the Realm instance
|
|
211
|
+
* @returns a RealmProvider component that provides context to all context hooks
|
|
212
|
+
*/
|
|
213
|
+
export function createRealmProvider(
|
|
214
|
+
realmOrConfig: Realm.Configuration | Realm | undefined,
|
|
215
|
+
RealmContext: React.Context<Realm | null>,
|
|
216
|
+
): RealmProviderFromConfiguration | RealmProviderFromRealm | DynamicRealmProvider {
|
|
217
|
+
if (!realmOrConfig) {
|
|
218
|
+
return createDynamicRealmProvider(RealmContext);
|
|
219
|
+
} else if (realmOrConfig instanceof Realm) {
|
|
220
|
+
return createRealmProviderFromRealm(realmOrConfig, RealmContext);
|
|
221
|
+
} else {
|
|
222
|
+
return createRealmProviderFromConfig(realmOrConfig, RealmContext);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Merge two configurations, creating a configuration using `configA` as the default,
|
|
228
|
+
* merged with `configB`, with properties in `configB` overriding `configA`.
|
|
229
|
+
* @param configA - The default config object
|
|
230
|
+
* @param configB - Config overrides object
|
|
231
|
+
* @returns Merged config object
|
|
232
|
+
*/
|
|
233
|
+
export function mergeRealmConfiguration(
|
|
234
|
+
configA: PartialRealmConfiguration,
|
|
235
|
+
configB: PartialRealmConfiguration,
|
|
236
|
+
): Realm.Configuration {
|
|
237
|
+
return {
|
|
238
|
+
...configA,
|
|
239
|
+
...configB,
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Utility function that does a deep comparison (key: value) of object a with object b
|
|
245
|
+
* @param a - Object to compare
|
|
246
|
+
* @param b - Object to compare
|
|
247
|
+
* @returns True if the objects are identical
|
|
248
|
+
*/
|
|
249
|
+
export function areConfigurationsIdentical(a: Realm.Configuration, b: Realm.Configuration): boolean {
|
|
250
|
+
return isEqual(a, b);
|
|
251
|
+
}
|