react-native-onyx 2.0.21 → 2.0.23
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/API.md +49 -64
- package/dist/DevTools.js +0 -1
- package/dist/Onyx.d.ts +49 -258
- package/dist/Onyx.js +192 -1165
- package/dist/OnyxCache.d.ts +14 -15
- package/dist/OnyxUtils.d.ts +320 -0
- package/dist/OnyxUtils.js +1061 -0
- package/dist/PerformanceUtils.d.ts +3 -5
- package/dist/index.d.ts +3 -2
- package/dist/storage/InstanceSync/index.d.ts +14 -0
- package/dist/storage/InstanceSync/index.js +20 -0
- package/dist/storage/InstanceSync/index.web.d.ts +27 -0
- package/dist/storage/InstanceSync/index.web.js +59 -0
- package/dist/storage/__mocks__/index.d.ts +15 -13
- package/dist/storage/__mocks__/index.js +43 -81
- package/dist/storage/index.d.ts +6 -2
- package/dist/storage/index.js +170 -2
- package/dist/storage/platforms/index.d.ts +2 -0
- package/dist/storage/{NativeStorage.js → platforms/index.js} +2 -2
- package/dist/storage/platforms/index.native.d.ts +2 -0
- package/dist/storage/{index.native.js → platforms/index.native.js} +2 -2
- package/dist/storage/providers/{IDBKeyVal.js → IDBKeyValProvider.js} +23 -19
- package/dist/storage/providers/MemoryOnlyProvider.d.ts +9 -0
- package/dist/storage/providers/MemoryOnlyProvider.js +124 -0
- package/dist/storage/providers/NoopProvider.js +85 -0
- package/dist/storage/providers/SQLiteProvider.d.ts +3 -0
- package/dist/storage/providers/{SQLiteStorage.js → SQLiteProvider.js} +17 -11
- package/dist/storage/providers/types.d.ts +17 -14
- package/dist/types.d.ts +128 -55
- package/dist/types.js +2 -0
- package/dist/useOnyx.js +11 -10
- package/dist/utils.d.ts +2 -2
- package/dist/utils.js +29 -16
- package/dist/withOnyx.js +6 -5
- package/package.json +1 -1
- package/dist/storage/NativeStorage.d.ts +0 -2
- package/dist/storage/WebStorage.d.ts +0 -3
- package/dist/storage/WebStorage.js +0 -62
- package/dist/storage/index.native.d.ts +0 -2
- /package/dist/storage/providers/{IDBKeyVal.d.ts → IDBKeyValProvider.d.ts} +0 -0
- /package/dist/storage/providers/{SQLiteStorage.d.ts → NoopProvider.d.ts} +0 -0
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.setMockStore = exports.mockSet = exports.mockStore = void 0;
|
|
7
|
+
const underscore_1 = __importDefault(require("underscore"));
|
|
8
|
+
const utils_1 = __importDefault(require("../../utils"));
|
|
9
|
+
// eslint-disable-next-line import/no-mutable-exports
|
|
10
|
+
let store = {};
|
|
11
|
+
exports.mockStore = store;
|
|
12
|
+
const setInternal = (key, value) => {
|
|
13
|
+
store[key] = value;
|
|
14
|
+
return Promise.resolve(value);
|
|
15
|
+
};
|
|
16
|
+
const isJestRunning = typeof jest !== 'undefined';
|
|
17
|
+
const set = isJestRunning ? jest.fn(setInternal) : setInternal;
|
|
18
|
+
exports.mockSet = set;
|
|
19
|
+
const provider = {
|
|
20
|
+
/**
|
|
21
|
+
* The name of the provider that can be printed to the logs
|
|
22
|
+
*/
|
|
23
|
+
name: 'MemoryOnlyProvider',
|
|
24
|
+
/**
|
|
25
|
+
* Initializes the storage provider
|
|
26
|
+
*/
|
|
27
|
+
init() {
|
|
28
|
+
// do nothing
|
|
29
|
+
},
|
|
30
|
+
/**
|
|
31
|
+
* Get the value of a given key or return `null` if it's not available in memory
|
|
32
|
+
*/
|
|
33
|
+
getItem(key) {
|
|
34
|
+
const value = store[key];
|
|
35
|
+
return Promise.resolve(value === undefined ? null : value);
|
|
36
|
+
},
|
|
37
|
+
/**
|
|
38
|
+
* Get multiple key-value pairs for the give array of keys in a batch.
|
|
39
|
+
*/
|
|
40
|
+
multiGet(keys) {
|
|
41
|
+
const getPromises = underscore_1.default.map(keys, (key) => new Promise((resolve) => {
|
|
42
|
+
this.getItem(key).then((value) => resolve([key, value]));
|
|
43
|
+
}));
|
|
44
|
+
return Promise.all(getPromises);
|
|
45
|
+
},
|
|
46
|
+
/**
|
|
47
|
+
* Sets the value for a given key. The only requirement is that the value should be serializable to JSON string
|
|
48
|
+
*/
|
|
49
|
+
setItem(key, value) {
|
|
50
|
+
set(key, value);
|
|
51
|
+
return Promise.resolve();
|
|
52
|
+
},
|
|
53
|
+
/**
|
|
54
|
+
* Stores multiple key-value pairs in a batch
|
|
55
|
+
*/
|
|
56
|
+
multiSet(pairs) {
|
|
57
|
+
const setPromises = underscore_1.default.map(pairs, ([key, value]) => this.setItem(key, value));
|
|
58
|
+
return new Promise((resolve) => {
|
|
59
|
+
Promise.all(setPromises).then(() => {
|
|
60
|
+
resolve(undefined);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
},
|
|
64
|
+
/**
|
|
65
|
+
* Merging an existing value with a new one
|
|
66
|
+
*/
|
|
67
|
+
mergeItem(key, _changes, modifiedData) {
|
|
68
|
+
// Since Onyx already merged the existing value with the changes, we can just set the value directly
|
|
69
|
+
return this.setItem(key, modifiedData);
|
|
70
|
+
},
|
|
71
|
+
/**
|
|
72
|
+
* Multiple merging of existing and new values in a batch
|
|
73
|
+
* This function also removes all nested null values from an object.
|
|
74
|
+
*/
|
|
75
|
+
multiMerge(pairs) {
|
|
76
|
+
underscore_1.default.forEach(pairs, ([key, value]) => {
|
|
77
|
+
const existingValue = store[key];
|
|
78
|
+
const newValue = utils_1.default.fastMerge(existingValue, value);
|
|
79
|
+
set(key, newValue);
|
|
80
|
+
});
|
|
81
|
+
return Promise.resolve([]);
|
|
82
|
+
},
|
|
83
|
+
/**
|
|
84
|
+
* Remove given key and it's value from memory
|
|
85
|
+
*/
|
|
86
|
+
removeItem(key) {
|
|
87
|
+
delete store[key];
|
|
88
|
+
return Promise.resolve();
|
|
89
|
+
},
|
|
90
|
+
/**
|
|
91
|
+
* Remove given keys and their values from memory
|
|
92
|
+
*/
|
|
93
|
+
removeItems(keys) {
|
|
94
|
+
underscore_1.default.each(keys, (key) => {
|
|
95
|
+
delete store[key];
|
|
96
|
+
});
|
|
97
|
+
return Promise.resolve();
|
|
98
|
+
},
|
|
99
|
+
/**
|
|
100
|
+
* Clear everything from memory
|
|
101
|
+
*/
|
|
102
|
+
clear() {
|
|
103
|
+
exports.mockStore = store = {};
|
|
104
|
+
return Promise.resolve();
|
|
105
|
+
},
|
|
106
|
+
/**
|
|
107
|
+
* Returns all keys available in memory
|
|
108
|
+
*/
|
|
109
|
+
getAllKeys() {
|
|
110
|
+
return Promise.resolve(underscore_1.default.keys(store));
|
|
111
|
+
},
|
|
112
|
+
/**
|
|
113
|
+
* Gets the total bytes of the store.
|
|
114
|
+
* `bytesRemaining` will always be `Number.POSITIVE_INFINITY` since we don't have a hard limit on memory.
|
|
115
|
+
*/
|
|
116
|
+
getDatabaseSize() {
|
|
117
|
+
return Promise.resolve({ bytesRemaining: Number.POSITIVE_INFINITY, bytesUsed: 0 });
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
const setMockStore = (data) => {
|
|
121
|
+
exports.mockStore = store = data;
|
|
122
|
+
};
|
|
123
|
+
exports.setMockStore = setMockStore;
|
|
124
|
+
exports.default = provider;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const provider = {
|
|
4
|
+
/**
|
|
5
|
+
* The name of the provider that can be printed to the logs
|
|
6
|
+
*/
|
|
7
|
+
name: 'NoopProvider',
|
|
8
|
+
/**
|
|
9
|
+
* Initializes the storage provider
|
|
10
|
+
*/
|
|
11
|
+
init() {
|
|
12
|
+
// do nothing
|
|
13
|
+
},
|
|
14
|
+
/**
|
|
15
|
+
* Get the value of a given key or return `null` if it's not available in memory
|
|
16
|
+
* @param {String} key
|
|
17
|
+
* @return {Promise<*>}
|
|
18
|
+
*/
|
|
19
|
+
getItem() {
|
|
20
|
+
return Promise.resolve(null);
|
|
21
|
+
},
|
|
22
|
+
/**
|
|
23
|
+
* Get multiple key-value pairs for the give array of keys in a batch.
|
|
24
|
+
*/
|
|
25
|
+
multiGet() {
|
|
26
|
+
return Promise.resolve([]);
|
|
27
|
+
},
|
|
28
|
+
/**
|
|
29
|
+
* Sets the value for a given key. The only requirement is that the value should be serializable to JSON string
|
|
30
|
+
*/
|
|
31
|
+
setItem() {
|
|
32
|
+
return Promise.resolve();
|
|
33
|
+
},
|
|
34
|
+
/**
|
|
35
|
+
* Stores multiple key-value pairs in a batch
|
|
36
|
+
*/
|
|
37
|
+
multiSet() {
|
|
38
|
+
return Promise.resolve();
|
|
39
|
+
},
|
|
40
|
+
/**
|
|
41
|
+
* Merging an existing value with a new one
|
|
42
|
+
*/
|
|
43
|
+
mergeItem() {
|
|
44
|
+
return Promise.resolve();
|
|
45
|
+
},
|
|
46
|
+
/**
|
|
47
|
+
* Multiple merging of existing and new values in a batch
|
|
48
|
+
* This function also removes all nested null values from an object.
|
|
49
|
+
*/
|
|
50
|
+
multiMerge() {
|
|
51
|
+
return Promise.resolve([]);
|
|
52
|
+
},
|
|
53
|
+
/**
|
|
54
|
+
* Remove given key and it's value from memory
|
|
55
|
+
*/
|
|
56
|
+
removeItem() {
|
|
57
|
+
return Promise.resolve();
|
|
58
|
+
},
|
|
59
|
+
/**
|
|
60
|
+
* Remove given keys and their values from memory
|
|
61
|
+
*/
|
|
62
|
+
removeItems() {
|
|
63
|
+
return Promise.resolve();
|
|
64
|
+
},
|
|
65
|
+
/**
|
|
66
|
+
* Clear everything from memory
|
|
67
|
+
*/
|
|
68
|
+
clear() {
|
|
69
|
+
return Promise.resolve();
|
|
70
|
+
},
|
|
71
|
+
/**
|
|
72
|
+
* Returns all keys available in memory
|
|
73
|
+
*/
|
|
74
|
+
getAllKeys() {
|
|
75
|
+
return Promise.resolve([]);
|
|
76
|
+
},
|
|
77
|
+
/**
|
|
78
|
+
* Gets the total bytes of the store.
|
|
79
|
+
* `bytesRemaining` will always be `Number.POSITIVE_INFINITY` since we don't have a hard limit on memory.
|
|
80
|
+
*/
|
|
81
|
+
getDatabaseSize() {
|
|
82
|
+
return Promise.resolve({ bytesRemaining: Number.POSITIVE_INFINITY, bytesUsed: 0 });
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
exports.default = provider;
|
|
@@ -7,14 +7,24 @@ const react_native_quick_sqlite_1 = require("react-native-quick-sqlite");
|
|
|
7
7
|
const react_native_device_info_1 = require("react-native-device-info");
|
|
8
8
|
const utils_1 = __importDefault(require("../../utils"));
|
|
9
9
|
const DB_NAME = 'OnyxDB';
|
|
10
|
-
|
|
11
|
-
db.execute('CREATE TABLE IF NOT EXISTS keyvaluepairs (record_key TEXT NOT NULL PRIMARY KEY , valueJSON JSON NOT NULL) WITHOUT ROWID;');
|
|
12
|
-
// All of the 3 pragmas below were suggested by SQLite team.
|
|
13
|
-
// You can find more info about them here: https://www.sqlite.org/pragma.html
|
|
14
|
-
db.execute('PRAGMA CACHE_SIZE=-20000;');
|
|
15
|
-
db.execute('PRAGMA synchronous=NORMAL;');
|
|
16
|
-
db.execute('PRAGMA journal_mode=WAL;');
|
|
10
|
+
let db;
|
|
17
11
|
const provider = {
|
|
12
|
+
/**
|
|
13
|
+
* The name of the provider that can be printed to the logs
|
|
14
|
+
*/
|
|
15
|
+
name: 'SQLiteProvider',
|
|
16
|
+
/**
|
|
17
|
+
* Initializes the storage provider
|
|
18
|
+
*/
|
|
19
|
+
init() {
|
|
20
|
+
db = (0, react_native_quick_sqlite_1.open)({ name: DB_NAME });
|
|
21
|
+
db.execute('CREATE TABLE IF NOT EXISTS keyvaluepairs (record_key TEXT NOT NULL PRIMARY KEY , valueJSON JSON NOT NULL) WITHOUT ROWID;');
|
|
22
|
+
// All of the 3 pragmas below were suggested by SQLite team.
|
|
23
|
+
// You can find more info about them here: https://www.sqlite.org/pragma.html
|
|
24
|
+
db.execute('PRAGMA CACHE_SIZE=-20000;');
|
|
25
|
+
db.execute('PRAGMA synchronous=NORMAL;');
|
|
26
|
+
db.execute('PRAGMA journal_mode=WAL;');
|
|
27
|
+
},
|
|
18
28
|
getItem(key) {
|
|
19
29
|
return db.executeAsync('SELECT record_key, valueJSON FROM keyvaluepairs WHERE record_key = ?;', [key]).then(({ rows }) => {
|
|
20
30
|
if (!rows || (rows === null || rows === void 0 ? void 0 : rows.length) === 0) {
|
|
@@ -84,9 +94,5 @@ const provider = {
|
|
|
84
94
|
};
|
|
85
95
|
});
|
|
86
96
|
},
|
|
87
|
-
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
88
|
-
setMemoryOnlyKeys: () => { },
|
|
89
|
-
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
90
|
-
keepInstancesSync: () => { },
|
|
91
97
|
};
|
|
92
98
|
exports.default = provider;
|
|
@@ -1,15 +1,22 @@
|
|
|
1
1
|
import type { BatchQueryResult, QueryResult } from 'react-native-quick-sqlite';
|
|
2
|
-
type
|
|
3
|
-
type
|
|
4
|
-
type
|
|
5
|
-
type KeyList = Key[];
|
|
2
|
+
import type { OnyxKey, OnyxValue } from '../../types';
|
|
3
|
+
type KeyValuePair = [OnyxKey, OnyxValue<OnyxKey>];
|
|
4
|
+
type KeyList = OnyxKey[];
|
|
6
5
|
type KeyValuePairList = KeyValuePair[];
|
|
7
|
-
type OnStorageKeyChanged = (key:
|
|
6
|
+
type OnStorageKeyChanged = <TKey extends OnyxKey>(key: TKey, value: OnyxValue<TKey> | null) => void;
|
|
8
7
|
type StorageProvider = {
|
|
8
|
+
/**
|
|
9
|
+
* The name of the provider that can be printed to the logs
|
|
10
|
+
*/
|
|
11
|
+
name: string;
|
|
12
|
+
/**
|
|
13
|
+
* Initializes the storage provider
|
|
14
|
+
*/
|
|
15
|
+
init: () => void;
|
|
9
16
|
/**
|
|
10
17
|
* Gets the value of a given key or return `null` if it's not available in storage
|
|
11
18
|
*/
|
|
12
|
-
getItem: (key:
|
|
19
|
+
getItem: <TKey extends OnyxKey>(key: TKey) => Promise<OnyxValue<TKey> | null>;
|
|
13
20
|
/**
|
|
14
21
|
* Get multiple key-value pairs for the given array of keys in a batch
|
|
15
22
|
*/
|
|
@@ -17,7 +24,7 @@ type StorageProvider = {
|
|
|
17
24
|
/**
|
|
18
25
|
* Sets the value for a given key. The only requirement is that the value should be serializable to JSON string
|
|
19
26
|
*/
|
|
20
|
-
setItem: (key:
|
|
27
|
+
setItem: <TKey extends OnyxKey>(key: TKey, value: OnyxValue<TKey>) => Promise<QueryResult | void>;
|
|
21
28
|
/**
|
|
22
29
|
* Stores multiple key-value pairs in a batch
|
|
23
30
|
*/
|
|
@@ -31,7 +38,7 @@ type StorageProvider = {
|
|
|
31
38
|
* @param changes - the delta for a specific key
|
|
32
39
|
* @param modifiedData - the pre-merged data from `Onyx.applyMerge`
|
|
33
40
|
*/
|
|
34
|
-
mergeItem: (key:
|
|
41
|
+
mergeItem: <TKey extends OnyxKey>(key: TKey, changes: OnyxValue<TKey>, modifiedData: OnyxValue<TKey>) => Promise<BatchQueryResult | void>;
|
|
35
42
|
/**
|
|
36
43
|
* Returns all keys available in storage
|
|
37
44
|
*/
|
|
@@ -39,7 +46,7 @@ type StorageProvider = {
|
|
|
39
46
|
/**
|
|
40
47
|
* Removes given key and its value from storage
|
|
41
48
|
*/
|
|
42
|
-
removeItem: (key:
|
|
49
|
+
removeItem: (key: OnyxKey) => Promise<QueryResult | void>;
|
|
43
50
|
/**
|
|
44
51
|
* Removes given keys and their values from storage
|
|
45
52
|
*/
|
|
@@ -48,10 +55,6 @@ type StorageProvider = {
|
|
|
48
55
|
* Clears absolutely everything from storage
|
|
49
56
|
*/
|
|
50
57
|
clear: () => Promise<QueryResult | void>;
|
|
51
|
-
/**
|
|
52
|
-
* Sets memory only keys
|
|
53
|
-
*/
|
|
54
|
-
setMemoryOnlyKeys: () => void;
|
|
55
58
|
/**
|
|
56
59
|
* Gets the total bytes of the database file
|
|
57
60
|
*/
|
|
@@ -65,4 +68,4 @@ type StorageProvider = {
|
|
|
65
68
|
keepInstancesSync?: (onStorageKeyChanged: OnStorageKeyChanged) => void;
|
|
66
69
|
};
|
|
67
70
|
export default StorageProvider;
|
|
68
|
-
export type {
|
|
71
|
+
export type { KeyList, KeyValuePair, KeyValuePairList, OnStorageKeyChanged };
|
package/dist/types.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
1
|
+
import type { Component } from 'react';
|
|
2
|
+
import type { Merge } from 'type-fest';
|
|
3
|
+
import type { BuiltIns } from 'type-fest/source/internal';
|
|
4
|
+
import type OnyxUtils from './OnyxUtils';
|
|
4
5
|
/**
|
|
5
6
|
* Represents a deeply nested record. It maps keys to values,
|
|
6
7
|
* and those values can either be of type `TValue` or further nested `DeepRecord` instances.
|
|
@@ -8,7 +9,6 @@ import {BuiltIns} from 'type-fest/source/internal';
|
|
|
8
9
|
type DeepRecord<TKey extends string | number | symbol, TValue> = {
|
|
9
10
|
[key: string]: TValue | DeepRecord<TKey, TValue>;
|
|
10
11
|
};
|
|
11
|
-
|
|
12
12
|
/**
|
|
13
13
|
* Represents type options to configure all Onyx methods.
|
|
14
14
|
* It's a combination of predefined options with user-provided options (CustomTypeOptions).
|
|
@@ -21,15 +21,11 @@ type DeepRecord<TKey extends string | number | symbol, TValue> = {
|
|
|
21
21
|
* The user-defined options (CustomTypeOptions) are merged into these predefined options.
|
|
22
22
|
* In case of conflicting properties, the ones from CustomTypeOptions are prioritized.
|
|
23
23
|
*/
|
|
24
|
-
type TypeOptions = Merge<
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
},
|
|
30
|
-
CustomTypeOptions
|
|
31
|
-
>;
|
|
32
|
-
|
|
24
|
+
type TypeOptions = Merge<{
|
|
25
|
+
keys: string;
|
|
26
|
+
collectionKeys: string;
|
|
27
|
+
values: Record<string, unknown>;
|
|
28
|
+
}, CustomTypeOptions>;
|
|
33
29
|
/**
|
|
34
30
|
* Represents the user-defined options to configure all Onyx methods.
|
|
35
31
|
*
|
|
@@ -76,34 +72,29 @@ type TypeOptions = Merge<
|
|
|
76
72
|
* }
|
|
77
73
|
* ```
|
|
78
74
|
*/
|
|
79
|
-
interface CustomTypeOptions {
|
|
80
|
-
|
|
75
|
+
interface CustomTypeOptions {
|
|
76
|
+
}
|
|
81
77
|
/**
|
|
82
78
|
* Represents a string union of all Onyx normal keys.
|
|
83
79
|
*/
|
|
84
80
|
type Key = TypeOptions['keys'];
|
|
85
|
-
|
|
86
81
|
/**
|
|
87
82
|
* Represents a string union of all Onyx collection keys.
|
|
88
83
|
*/
|
|
89
84
|
type CollectionKeyBase = TypeOptions['collectionKeys'];
|
|
90
|
-
|
|
91
85
|
/**
|
|
92
86
|
* Represents a literal string union of all Onyx collection keys.
|
|
93
87
|
* It allows appending a string after each collection key e.g. `report_some-id`.
|
|
94
88
|
*/
|
|
95
89
|
type CollectionKey = `${CollectionKeyBase}${string}`;
|
|
96
|
-
|
|
97
90
|
/**
|
|
98
91
|
* Represents a string union of all Onyx normal and collection keys.
|
|
99
92
|
*/
|
|
100
93
|
type OnyxKey = Key | CollectionKey;
|
|
101
|
-
|
|
102
94
|
/**
|
|
103
95
|
* Represents a Onyx value that can be either a single entry or a collection of entries, depending on the `TKey` provided.
|
|
104
96
|
*/
|
|
105
|
-
type OnyxValue<TKey extends OnyxKey> = TKey extends CollectionKeyBase ? OnyxCollection<KeyValueMapping[TKey]> : OnyxEntry<KeyValueMapping[TKey]>;
|
|
106
|
-
|
|
97
|
+
type OnyxValue<TKey extends OnyxKey> = string extends TKey ? unknown : TKey extends CollectionKeyBase ? OnyxCollection<KeyValueMapping[TKey]> : OnyxEntry<KeyValueMapping[TKey]>;
|
|
107
98
|
/**
|
|
108
99
|
* Represents a mapping of Onyx keys to values, where keys are either normal or collection Onyx keys
|
|
109
100
|
* and values are the corresponding values in Onyx's state.
|
|
@@ -116,7 +107,14 @@ type OnyxValue<TKey extends OnyxKey> = TKey extends CollectionKeyBase ? OnyxColl
|
|
|
116
107
|
type KeyValueMapping = {
|
|
117
108
|
[TKey in keyof TypeOptions['values'] as TKey extends CollectionKeyBase ? `${TKey}${string}` : TKey]: TypeOptions['values'][TKey];
|
|
118
109
|
};
|
|
119
|
-
|
|
110
|
+
/**
|
|
111
|
+
* Represents a mapping object where each `OnyxKey` maps to either a value of its corresponding type in `KeyValueMapping` or `null`.
|
|
112
|
+
*
|
|
113
|
+
* It's very similar to `KeyValueMapping` but this type accepts using `null` as well.
|
|
114
|
+
*/
|
|
115
|
+
type NullableKeyValueMapping = {
|
|
116
|
+
[TKey in OnyxKey]: OnyxValue<TKey>;
|
|
117
|
+
};
|
|
120
118
|
/**
|
|
121
119
|
* Represents a selector function type which operates based on the provided `TKey` and `ReturnType`.
|
|
122
120
|
*
|
|
@@ -127,7 +125,6 @@ type KeyValueMapping = {
|
|
|
127
125
|
* `TReturnType` is the type of the returned value from the selector function.
|
|
128
126
|
*/
|
|
129
127
|
type Selector<TKey extends OnyxKey, TOnyxProps, TReturnType> = (value: OnyxEntry<KeyValueMapping[TKey]>, state: WithOnyxInstanceState<TOnyxProps>) => TReturnType;
|
|
130
|
-
|
|
131
128
|
/**
|
|
132
129
|
* Represents a single Onyx entry, that can be either `TOnyxValue` or `null` if it doesn't exist.
|
|
133
130
|
*
|
|
@@ -157,7 +154,6 @@ type Selector<TKey extends OnyxKey, TOnyxProps, TReturnType> = (value: OnyxEntry
|
|
|
157
154
|
* ```
|
|
158
155
|
*/
|
|
159
156
|
type OnyxEntry<TOnyxValue> = TOnyxValue | null;
|
|
160
|
-
|
|
161
157
|
/**
|
|
162
158
|
* Represents an Onyx collection of entries, that can be either a record of `TOnyxValue`s or `null` if it is empty or doesn't exist.
|
|
163
159
|
*
|
|
@@ -187,20 +183,9 @@ type OnyxEntry<TOnyxValue> = TOnyxValue | null;
|
|
|
187
183
|
* ```
|
|
188
184
|
*/
|
|
189
185
|
type OnyxCollection<TOnyxValue> = OnyxEntry<Record<string, TOnyxValue | null>>;
|
|
190
|
-
|
|
191
186
|
/** Utility type to extract `TOnyxValue` from `OnyxCollection<TOnyxValue>` */
|
|
192
187
|
type ExtractOnyxCollectionValue<TOnyxCollection> = TOnyxCollection extends NonNullable<OnyxCollection<infer U>> ? U : never;
|
|
193
|
-
|
|
194
|
-
type NonTransformableTypes =
|
|
195
|
-
| BuiltIns
|
|
196
|
-
| ((...args: any[]) => unknown)
|
|
197
|
-
| Map<unknown, unknown>
|
|
198
|
-
| Set<unknown>
|
|
199
|
-
| ReadonlyMap<unknown, unknown>
|
|
200
|
-
| ReadonlySet<unknown>
|
|
201
|
-
| unknown[]
|
|
202
|
-
| readonly unknown[];
|
|
203
|
-
|
|
188
|
+
type NonTransformableTypes = BuiltIns | ((...args: any[]) => unknown) | Map<unknown, unknown> | Set<unknown> | ReadonlyMap<unknown, unknown> | ReadonlySet<unknown> | unknown[] | readonly unknown[];
|
|
204
189
|
/**
|
|
205
190
|
* Create a type from another type with all keys and nested keys set to optional or null.
|
|
206
191
|
*
|
|
@@ -221,32 +206,120 @@ type NonTransformableTypes =
|
|
|
221
206
|
* settings = applySavedSettings({textEditor: {fontWeight: 500, fontColor: null}});
|
|
222
207
|
*/
|
|
223
208
|
type NullishDeep<T> = T extends NonTransformableTypes ? T : T extends object ? NullishObjectDeep<T> : unknown;
|
|
224
|
-
|
|
225
209
|
/**
|
|
226
210
|
* Same as `NullishDeep`, but accepts only `object`s as inputs. Internal helper for `NullishDeep`.
|
|
227
211
|
*/
|
|
228
212
|
type NullishObjectDeep<ObjectType extends object> = {
|
|
229
213
|
[KeyType in keyof ObjectType]?: NullishDeep<ObjectType[KeyType]> | null;
|
|
230
214
|
};
|
|
231
|
-
|
|
232
215
|
/**
|
|
233
216
|
* Represents withOnyx's internal state, containing the Onyx props and a `loading` flag.
|
|
234
217
|
*/
|
|
235
|
-
type WithOnyxInstanceState<TOnyxProps> = (TOnyxProps & {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
218
|
+
type WithOnyxInstanceState<TOnyxProps> = (TOnyxProps & {
|
|
219
|
+
loading: boolean;
|
|
220
|
+
}) | undefined;
|
|
221
|
+
/**
|
|
222
|
+
* Represents a mapping between Onyx collection keys and their respective values.
|
|
223
|
+
*
|
|
224
|
+
* It helps to enforce that a Onyx collection key should not be without suffix (e.g. should always be of the form `${TKey}${string}`),
|
|
225
|
+
* and to map each Onyx collection key with suffix to a value of type `TValue`.
|
|
226
|
+
*
|
|
227
|
+
* Also, the `TMap` type is inferred automatically in `mergeCollection()` method and represents
|
|
228
|
+
* the object of collection keys/values specified in the second parameter of the method.
|
|
229
|
+
*/
|
|
230
|
+
type Collection<TKey extends CollectionKeyBase, TMap, TValue> = {
|
|
231
|
+
[MapK in keyof TMap]: MapK extends `${TKey}${string}` ? MapK extends `${TKey}` ? never : TValue : never;
|
|
232
|
+
};
|
|
233
|
+
type WithOnyxInstance = Component<unknown, WithOnyxInstanceState<NullableKeyValueMapping>> & {
|
|
234
|
+
setStateProxy: (cb: (state: NullableKeyValueMapping) => OnyxValue<OnyxKey>) => void;
|
|
235
|
+
setWithOnyxState: (statePropertyName: OnyxKey, value: OnyxValue<OnyxKey>) => void;
|
|
236
|
+
};
|
|
237
|
+
/** Represents the base options used in `Onyx.connect()` method. */
|
|
238
|
+
type BaseConnectOptions = {
|
|
239
|
+
statePropertyName?: string;
|
|
240
|
+
withOnyxInstance?: Component;
|
|
241
|
+
initWithStoredValues?: boolean;
|
|
242
|
+
};
|
|
243
|
+
/**
|
|
244
|
+
* Represents the options used in `Onyx.connect()` method.
|
|
245
|
+
* The type is built from `BaseConnectOptions` and extended to handle key/callback related options.
|
|
246
|
+
* It includes two different forms, depending on whether we are waiting for a collection callback or not.
|
|
247
|
+
*
|
|
248
|
+
* If `waitForCollectionCallback` is `true`, it expects `key` to be a Onyx collection key and `callback` will be triggered with the whole collection
|
|
249
|
+
* and will pass `value` as an `OnyxCollection`.
|
|
250
|
+
*
|
|
251
|
+
*
|
|
252
|
+
* If `waitForCollectionCallback` is `false` or not specified, the `key` can be any Onyx key and `callback` will be triggered with updates of each collection item
|
|
253
|
+
* and will pass `value` as an `OnyxEntry`.
|
|
254
|
+
*/
|
|
255
|
+
type ConnectOptions<TKey extends OnyxKey> = BaseConnectOptions & ({
|
|
256
|
+
key: TKey extends CollectionKeyBase ? TKey : never;
|
|
257
|
+
callback?: (value: OnyxCollection<KeyValueMapping[TKey]>) => void;
|
|
258
|
+
waitForCollectionCallback: true;
|
|
259
|
+
} | {
|
|
260
|
+
key: TKey;
|
|
261
|
+
callback?: (value: OnyxEntry<KeyValueMapping[TKey]>, key: TKey) => void;
|
|
262
|
+
waitForCollectionCallback?: false;
|
|
263
|
+
});
|
|
264
|
+
type Mapping<TKey extends OnyxKey> = ConnectOptions<TKey> & {
|
|
265
|
+
connectionID: number;
|
|
266
|
+
statePropertyName: string;
|
|
267
|
+
displayName: string;
|
|
268
|
+
};
|
|
269
|
+
/**
|
|
270
|
+
* Represents different kinds of updates that can be passed to `Onyx.update()` method. It is a discriminated union of
|
|
271
|
+
* different update methods (`SET`, `MERGE`, `MERGE_COLLECTION`), each with their own key and value structure.
|
|
272
|
+
*/
|
|
273
|
+
type OnyxUpdate = {
|
|
274
|
+
[TKey in OnyxKey]: {
|
|
275
|
+
onyxMethod: typeof OnyxUtils.METHOD.SET;
|
|
276
|
+
key: TKey;
|
|
277
|
+
value: OnyxEntry<KeyValueMapping[TKey]>;
|
|
278
|
+
} | {
|
|
279
|
+
onyxMethod: typeof OnyxUtils.METHOD.MERGE;
|
|
280
|
+
key: TKey;
|
|
281
|
+
value: OnyxEntry<NullishDeep<KeyValueMapping[TKey]>>;
|
|
282
|
+
} | {
|
|
283
|
+
onyxMethod: typeof OnyxUtils.METHOD.MULTI_SET;
|
|
284
|
+
key: TKey;
|
|
285
|
+
value: Partial<NullableKeyValueMapping>;
|
|
286
|
+
} | {
|
|
287
|
+
onyxMethod: typeof OnyxUtils.METHOD.CLEAR;
|
|
288
|
+
key: TKey;
|
|
289
|
+
value?: undefined;
|
|
290
|
+
};
|
|
291
|
+
}[OnyxKey] | {
|
|
292
|
+
[TKey in CollectionKeyBase]: {
|
|
293
|
+
onyxMethod: typeof OnyxUtils.METHOD.MERGE_COLLECTION;
|
|
294
|
+
key: TKey;
|
|
295
|
+
value: Record<`${TKey}${string}`, NullishDeep<KeyValueMapping[TKey]>>;
|
|
296
|
+
};
|
|
297
|
+
}[CollectionKeyBase];
|
|
298
|
+
/**
|
|
299
|
+
* Represents the options used in `Onyx.init()` method.
|
|
300
|
+
*/
|
|
301
|
+
type InitOptions = {
|
|
302
|
+
/** `ONYXKEYS` constants object */
|
|
303
|
+
keys?: DeepRecord<string, OnyxKey>;
|
|
304
|
+
/** initial data to set when `init()` and `clear()` is called */
|
|
305
|
+
initialKeyStates?: Partial<NullableKeyValueMapping>;
|
|
306
|
+
/**
|
|
307
|
+
* This is an array of keys (individual or collection patterns) that when provided to Onyx are flagged
|
|
308
|
+
* as "safe" for removal. Any components subscribing to these keys must also implement a canEvict option. See the README for more info.
|
|
309
|
+
*/
|
|
310
|
+
safeEvictionKeys?: OnyxKey[];
|
|
311
|
+
/**
|
|
312
|
+
* Sets how many recent keys should we try to keep in cache
|
|
313
|
+
* Setting this to 0 would practically mean no cache
|
|
314
|
+
* We try to free cache when we connect to a safe eviction key
|
|
315
|
+
*/
|
|
316
|
+
maxCachedKeysCount?: number;
|
|
317
|
+
/**
|
|
318
|
+
* Auto synchronize storage events between multiple instances
|
|
319
|
+
* of Onyx running in different tabs/windows. Defaults to true for platforms that support local storage (web/desktop)
|
|
320
|
+
*/
|
|
321
|
+
shouldSyncMultipleInstances?: boolean;
|
|
322
|
+
/** Enables debugging setState() calls to connected components */
|
|
323
|
+
debugSetState?: boolean;
|
|
252
324
|
};
|
|
325
|
+
export type { CollectionKey, CollectionKeyBase, CustomTypeOptions, DeepRecord, Key, KeyValueMapping, NullableKeyValueMapping, OnyxCollection, OnyxEntry, OnyxKey, OnyxValue, Selector, NullishDeep, WithOnyxInstanceState, ExtractOnyxCollectionValue, Collection, WithOnyxInstance, BaseConnectOptions, ConnectOptions, Mapping, OnyxUpdate, InitOptions, };
|
package/dist/types.js
ADDED
package/dist/useOnyx.js
CHANGED
|
@@ -5,11 +5,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const fast_equals_1 = require("fast-equals");
|
|
7
7
|
const react_1 = require("react");
|
|
8
|
-
const
|
|
8
|
+
const OnyxUtils_1 = __importDefault(require("./OnyxUtils"));
|
|
9
9
|
const useLiveRef_1 = __importDefault(require("./useLiveRef"));
|
|
10
10
|
const usePrevious_1 = __importDefault(require("./usePrevious"));
|
|
11
|
+
const Onyx_1 = __importDefault(require("./Onyx"));
|
|
11
12
|
function getCachedValue(key, selector) {
|
|
12
|
-
return
|
|
13
|
+
return OnyxUtils_1.default.tryGetCachedValue(key, { selector });
|
|
13
14
|
}
|
|
14
15
|
function useOnyx(key, options) {
|
|
15
16
|
const connectionIDRef = (0, react_1.useRef)(null);
|
|
@@ -37,9 +38,9 @@ function useOnyx(key, options) {
|
|
|
37
38
|
return;
|
|
38
39
|
}
|
|
39
40
|
try {
|
|
40
|
-
const previousCollectionKey =
|
|
41
|
-
const collectionKey =
|
|
42
|
-
if (
|
|
41
|
+
const previousCollectionKey = OnyxUtils_1.default.splitCollectionMemberKey(previousKey)[0];
|
|
42
|
+
const collectionKey = OnyxUtils_1.default.splitCollectionMemberKey(key)[0];
|
|
43
|
+
if (OnyxUtils_1.default.isCollectionMemberKey(previousCollectionKey, previousKey) && OnyxUtils_1.default.isCollectionMemberKey(collectionKey, key) && previousCollectionKey === collectionKey) {
|
|
43
44
|
return;
|
|
44
45
|
}
|
|
45
46
|
}
|
|
@@ -61,7 +62,7 @@ function useOnyx(key, options) {
|
|
|
61
62
|
// If we have pending merge operations for the key during the first connection, we set the new value to `undefined`
|
|
62
63
|
// and fetch status to `loading` to simulate that it is still being loaded until we have the most updated data.
|
|
63
64
|
// If `allowStaleData` is `true` this logic will be ignored and cached value will be used, even if it's stale data.
|
|
64
|
-
if (isFirstConnectionRef.current &&
|
|
65
|
+
if (isFirstConnectionRef.current && OnyxUtils_1.default.hasPendingMergeForKey(key) && !(options === null || options === void 0 ? void 0 : options.allowStaleData)) {
|
|
65
66
|
newValue = undefined;
|
|
66
67
|
newFetchStatus = 'loading';
|
|
67
68
|
}
|
|
@@ -90,7 +91,7 @@ function useOnyx(key, options) {
|
|
|
90
91
|
onStoreChange();
|
|
91
92
|
},
|
|
92
93
|
initWithStoredValues: options === null || options === void 0 ? void 0 : options.initWithStoredValues,
|
|
93
|
-
waitForCollectionCallback:
|
|
94
|
+
waitForCollectionCallback: OnyxUtils_1.default.isCollectionKey(key),
|
|
94
95
|
});
|
|
95
96
|
return () => {
|
|
96
97
|
if (!connectionIDRef.current) {
|
|
@@ -105,14 +106,14 @@ function useOnyx(key, options) {
|
|
|
105
106
|
if ((options === null || options === void 0 ? void 0 : options.canEvict) === undefined || !connectionIDRef.current) {
|
|
106
107
|
return;
|
|
107
108
|
}
|
|
108
|
-
if (!
|
|
109
|
+
if (!OnyxUtils_1.default.isSafeEvictionKey(key)) {
|
|
109
110
|
throw new Error(`canEvict can't be used on key '${key}'. This key must explicitly be flagged as safe for removal by adding it to Onyx.init({safeEvictionKeys: []}).`);
|
|
110
111
|
}
|
|
111
112
|
if (options.canEvict) {
|
|
112
|
-
|
|
113
|
+
OnyxUtils_1.default.removeFromEvictionBlockList(key, connectionIDRef.current);
|
|
113
114
|
}
|
|
114
115
|
else {
|
|
115
|
-
|
|
116
|
+
OnyxUtils_1.default.addToEvictionBlockList(key, connectionIDRef.current);
|
|
116
117
|
}
|
|
117
118
|
}, [key, options === null || options === void 0 ? void 0 : options.canEvict]);
|
|
118
119
|
const result = (0, react_1.useSyncExternalStore)(subscribe, getSnapshot);
|
package/dist/utils.d.ts
CHANGED
|
@@ -10,9 +10,9 @@ declare function isEmptyObject<T>(obj: T | EmptyValue): obj is EmptyValue;
|
|
|
10
10
|
* On native, when merging an existing value with new changes, SQLite will use JSON_PATCH, which removes top-level nullish values.
|
|
11
11
|
* To be consistent with the behaviour for merge, we'll also want to remove null values for "set" operations.
|
|
12
12
|
*/
|
|
13
|
-
declare function fastMerge<
|
|
13
|
+
declare function fastMerge<TObject extends Record<string, unknown>>(target: TObject | null, source: TObject | null, shouldRemoveNullObjectValues?: boolean): TObject | null;
|
|
14
14
|
/** Deep removes the nested null values from the given value. */
|
|
15
|
-
declare function removeNestedNullValues(value: unknown[] | Record<string, unknown>): Record<string, unknown> | unknown[];
|
|
15
|
+
declare function removeNestedNullValues(value: unknown[] | Record<string, unknown>): Record<string, unknown> | unknown[] | null;
|
|
16
16
|
/** Formats the action name by uppercasing and adding the key if provided. */
|
|
17
17
|
declare function formatActionName(method: string, key?: OnyxKey): string;
|
|
18
18
|
declare const _default: {
|