react-native-onyx 3.0.26 → 3.0.28

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/dist/OnyxUtils.js CHANGED
@@ -699,7 +699,7 @@ function addKeyToRecentlyAccessedIfNeeded(key) {
699
699
  function getCollectionDataAndSendAsObject(matchingKeys, mapping) {
700
700
  multiGet(matchingKeys).then((dataMap) => {
701
701
  const data = Object.fromEntries(dataMap.entries());
702
- sendDataToConnection(mapping, data, undefined);
702
+ sendDataToConnection(mapping, data, mapping.key);
703
703
  });
704
704
  }
705
705
  /**
@@ -961,9 +961,10 @@ function subscribeToKey(connectOptions) {
961
961
  if (mapping.key) {
962
962
  OnyxCache_1.default.addNullishStorageKey(mapping.key);
963
963
  }
964
+ const matchedKey = isCollectionKey(mapping.key) && mapping.waitForCollectionCallback ? mapping.key : undefined;
964
965
  // Here we cannot use batching because the nullish value is expected to be set immediately for default props
965
966
  // or they will be undefined.
966
- sendDataToConnection(mapping, null, undefined);
967
+ sendDataToConnection(mapping, null, matchedKey);
967
968
  return;
968
969
  }
969
970
  // When using a callback subscriber we will either trigger the provided callback for each key we find or combine all values
@@ -17,7 +17,7 @@ declare const InstanceSync: {
17
17
  /**
18
18
  * @param {Function} onStorageKeyChanged Storage synchronization mechanism keeping all opened tabs in sync
19
19
  */
20
- init: (onStorageKeyChanged: OnStorageKeyChanged, store: StorageProvider) => void;
20
+ init: (onStorageKeyChanged: OnStorageKeyChanged, store: StorageProvider<unknown>) => void;
21
21
  setItem: typeof raiseStorageSyncEvent;
22
22
  removeItem: typeof raiseStorageSyncEvent;
23
23
  removeItems: typeof raiseStorageSyncManyKeysEvent;
@@ -15,7 +15,6 @@ declare const StorageMock: {
15
15
  bytesRemaining: number;
16
16
  }>, [], any>;
17
17
  keepInstancesSync: jest.Mock<any, any, any>;
18
- mockSet: (key: import("../..").OnyxKey, value: import("../..").OnyxValue<import("../..").OnyxKey>) => Promise<unknown>;
19
18
  getMockStore: jest.Mock<{
20
19
  [x: string]: unknown;
21
20
  }, [], any>;
@@ -50,7 +50,6 @@ const StorageMock = {
50
50
  getAllKeys: jest.fn(MemoryOnlyProvider_1.default.getAllKeys),
51
51
  getDatabaseSize: jest.fn(MemoryOnlyProvider_1.default.getDatabaseSize),
52
52
  keepInstancesSync: jest.fn(),
53
- mockSet: MemoryOnlyProvider_1.mockSet,
54
53
  getMockStore: jest.fn(() => MemoryOnlyProvider_1.mockStore),
55
54
  setMockStore: jest.fn((data) => (0, MemoryOnlyProvider_1.setMockStore)(data)),
56
55
  };
@@ -1,6 +1,6 @@
1
1
  import type StorageProvider from './providers/types';
2
2
  type Storage = {
3
- getStorageProvider: () => StorageProvider;
4
- } & Omit<StorageProvider, 'name'>;
3
+ getStorageProvider: () => StorageProvider<unknown>;
4
+ } & Omit<StorageProvider<unknown>, 'name' | 'store'>;
5
5
  declare const storage: Storage;
6
6
  export default storage;
@@ -1,6 +1,39 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  Object.defineProperty(exports, "__esModule", { value: true });
3
- const idb_keyval_1 = require("idb-keyval");
36
+ const IDB = __importStar(require("idb-keyval"));
4
37
  const Logger_1 = require("../../../Logger");
5
38
  // This is a copy of the createStore function from idb-keyval, we need a custom implementation
6
39
  // because we need to create the database manually in order to ensure that the store exists before we use it.
@@ -13,7 +46,7 @@ function createStore(dbName, storeName) {
13
46
  return dbp;
14
47
  const request = indexedDB.open(dbName);
15
48
  request.onupgradeneeded = () => request.result.createObjectStore(storeName);
16
- dbp = (0, idb_keyval_1.promisifyRequest)(request);
49
+ dbp = IDB.promisifyRequest(request);
17
50
  dbp.then((db) => {
18
51
  // It seems like Safari sometimes likes to just close the connection.
19
52
  // It's supposed to fire this event when that happens. Let's hope it does!
@@ -42,7 +75,7 @@ function createStore(dbName, storeName) {
42
75
  (0, Logger_1.logInfo)(`Creating store ${storeName} in database ${dbName}.`);
43
76
  updatedDatabase.createObjectStore(storeName);
44
77
  };
45
- dbp = (0, idb_keyval_1.promisifyRequest)(request);
78
+ dbp = IDB.promisifyRequest(request);
46
79
  return dbp;
47
80
  };
48
81
  return (txMode, callback) => getDB()
@@ -1,3 +1,4 @@
1
+ import type { UseStore } from 'idb-keyval';
1
2
  import type StorageProvider from '../types';
2
- declare const provider: StorageProvider;
3
+ declare const provider: StorageProvider<UseStore | undefined>;
3
4
  export default provider;
@@ -1,17 +1,50 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
37
  };
5
38
  Object.defineProperty(exports, "__esModule", { value: true });
6
- const idb_keyval_1 = require("idb-keyval");
39
+ const IDB = __importStar(require("idb-keyval"));
7
40
  const utils_1 = __importDefault(require("../../../utils"));
8
41
  const createStore_1 = __importDefault(require("./createStore"));
9
- // We don't want to initialize the store while the JS bundle loads as idb-keyval will try to use global.indexedDB
10
- // which might not be available in certain environments that load the bundle (e.g. electron main process).
11
- let idbKeyValStore;
12
42
  const DB_NAME = 'OnyxDB';
13
43
  const STORE_NAME = 'keyvaluepairs';
14
44
  const provider = {
45
+ // We don't want to initialize the store while the JS bundle loads as idb-keyval will try to use global.indexedDB
46
+ // which might not be available in certain environments that load the bundle (e.g. electron main process).
47
+ store: undefined,
15
48
  /**
16
49
  * The name of the provider that can be printed to the logs
17
50
  */
@@ -24,60 +57,104 @@ const provider = {
24
57
  if (newIdbKeyValStore == null) {
25
58
  throw Error('IDBKeyVal store could not be created');
26
59
  }
27
- idbKeyValStore = newIdbKeyValStore;
60
+ provider.store = newIdbKeyValStore;
28
61
  },
29
- setItem: (key, value) => {
62
+ setItem(key, value) {
63
+ if (!provider.store) {
64
+ throw new Error('Store not initialized!');
65
+ }
30
66
  if (value === null) {
31
- provider.removeItem(key);
67
+ return provider.removeItem(key);
32
68
  }
33
- return (0, idb_keyval_1.set)(key, value, idbKeyValStore);
69
+ return IDB.set(key, value, provider.store);
34
70
  },
35
- multiGet: (keysParam) => (0, idb_keyval_1.getMany)(keysParam, idbKeyValStore).then((values) => values.map((value, index) => [keysParam[index], value])),
36
- multiMerge: (pairs) => idbKeyValStore('readwrite', (store) => {
37
- // Note: we are using the manual store transaction here, to fit the read and update
38
- // of the items in one transaction to achieve best performance.
39
- const getValues = Promise.all(pairs.map(([key]) => (0, idb_keyval_1.promisifyRequest)(store.get(key))));
40
- return getValues.then((values) => {
41
- const pairsWithoutNull = pairs.filter(([key, value]) => {
42
- if (value === null) {
43
- provider.removeItem(key);
44
- return false;
71
+ multiGet(keysParam) {
72
+ if (!provider.store) {
73
+ throw new Error('Store not initialized!');
74
+ }
75
+ return IDB.getMany(keysParam, provider.store).then((values) => values.map((value, index) => [keysParam[index], value]));
76
+ },
77
+ multiMerge(pairs) {
78
+ if (!provider.store) {
79
+ throw new Error('Store not initialized!');
80
+ }
81
+ return provider.store('readwrite', (store) => {
82
+ // Note: we are using the manual store transaction here, to fit the read and update
83
+ // of the items in one transaction to achieve best performance.
84
+ const getValues = Promise.all(pairs.map(([key]) => IDB.promisifyRequest(store.get(key))));
85
+ return getValues.then((values) => {
86
+ for (const [index, [key, value]] of pairs.entries()) {
87
+ if (value === null) {
88
+ store.delete(key);
89
+ }
90
+ else {
91
+ const newValue = utils_1.default.fastMerge(values[index], value, {
92
+ shouldRemoveNestedNulls: true,
93
+ objectRemovalMode: 'replace',
94
+ }).result;
95
+ store.put(newValue, key);
96
+ }
45
97
  }
46
- return true;
47
- });
48
- const upsertMany = pairsWithoutNull.map(([key, value], index) => {
49
- const prev = values[index];
50
- const newValue = utils_1.default.fastMerge(prev, value, {
51
- shouldRemoveNestedNulls: true,
52
- objectRemovalMode: 'replace',
53
- }).result;
54
- return (0, idb_keyval_1.promisifyRequest)(store.put(newValue, key));
98
+ return IDB.promisifyRequest(store.transaction);
55
99
  });
56
- return Promise.all(upsertMany);
57
100
  });
58
- }).then(() => undefined),
101
+ },
59
102
  mergeItem(key, change) {
60
103
  // Since Onyx already merged the existing value with the changes, we can just set the value directly.
61
104
  return provider.multiMerge([[key, change]]);
62
105
  },
63
- multiSet: (pairs) => {
64
- const pairsWithoutNull = pairs.filter(([key, value]) => {
65
- if (value === null) {
66
- provider.removeItem(key);
67
- return false;
106
+ multiSet(pairs) {
107
+ if (!provider.store) {
108
+ throw new Error('Store not initialized!');
109
+ }
110
+ return provider.store('readwrite', (store) => {
111
+ for (const [key, value] of pairs) {
112
+ if (value === null) {
113
+ store.delete(key);
114
+ }
115
+ else {
116
+ store.put(value, key);
117
+ }
68
118
  }
69
- return true;
119
+ return IDB.promisifyRequest(store.transaction);
70
120
  });
71
- return (0, idb_keyval_1.setMany)(pairsWithoutNull, idbKeyValStore);
72
121
  },
73
- clear: () => (0, idb_keyval_1.clear)(idbKeyValStore),
74
- getAllKeys: () => (0, idb_keyval_1.keys)(idbKeyValStore),
75
- getItem: (key) => (0, idb_keyval_1.get)(key, idbKeyValStore)
76
- // idb-keyval returns undefined for missing items, but this needs to return null so that idb-keyval does the same thing as SQLiteStorage.
77
- .then((val) => (val === undefined ? null : val)),
78
- removeItem: (key) => (0, idb_keyval_1.del)(key, idbKeyValStore),
79
- removeItems: (keysParam) => (0, idb_keyval_1.delMany)(keysParam, idbKeyValStore),
122
+ clear() {
123
+ if (!provider.store) {
124
+ throw new Error('Store not initialized!');
125
+ }
126
+ return IDB.clear(provider.store);
127
+ },
128
+ getAllKeys() {
129
+ if (!provider.store) {
130
+ throw new Error('Store not initialized!');
131
+ }
132
+ return IDB.keys(provider.store);
133
+ },
134
+ getItem(key) {
135
+ if (!provider.store) {
136
+ throw new Error('Store not initialized!');
137
+ }
138
+ return (IDB.get(key, provider.store)
139
+ // idb-keyval returns undefined for missing items, but this needs to return null so that idb-keyval does the same thing as SQLiteStorage.
140
+ .then((val) => (val === undefined ? null : val)));
141
+ },
142
+ removeItem(key) {
143
+ if (!provider.store) {
144
+ throw new Error('Store not initialized!');
145
+ }
146
+ return IDB.del(key, provider.store);
147
+ },
148
+ removeItems(keysParam) {
149
+ if (!provider.store) {
150
+ throw new Error('Store not initialized!');
151
+ }
152
+ return IDB.delMany(keysParam, provider.store);
153
+ },
80
154
  getDatabaseSize() {
155
+ if (!provider.store) {
156
+ throw new Error('Store is not initialized!');
157
+ }
81
158
  if (!window.navigator || !window.navigator.storage) {
82
159
  throw new Error('StorageManager browser API unavailable');
83
160
  }
@@ -1,9 +1,9 @@
1
- import type StorageProvider from './types';
2
1
  import type { OnyxKey, OnyxValue } from '../../types';
2
+ import type StorageProvider from './types';
3
3
  type Store = Record<OnyxKey, OnyxValue<OnyxKey>>;
4
- declare let store: Store;
4
+ declare const storeInternal: Store;
5
5
  declare const set: (key: OnyxKey, value: OnyxValue<OnyxKey>) => Promise<unknown>;
6
- declare const provider: StorageProvider;
6
+ declare const provider: StorageProvider<Store>;
7
7
  declare const setMockStore: (data: Store) => void;
8
8
  export default provider;
9
- export { store as mockStore, set as mockSet, setMockStore };
9
+ export { set as mockSet, storeInternal as mockStore, setMockStore };
@@ -3,20 +3,21 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.setMockStore = exports.mockSet = exports.mockStore = void 0;
6
+ exports.setMockStore = exports.mockStore = exports.mockSet = void 0;
7
7
  const underscore_1 = __importDefault(require("underscore"));
8
8
  const utils_1 = __importDefault(require("../../utils"));
9
9
  // eslint-disable-next-line import/no-mutable-exports
10
- let store = {};
11
- exports.mockStore = store;
10
+ const storeInternal = {};
11
+ exports.mockStore = storeInternal;
12
12
  const setInternal = (key, value) => {
13
- store[key] = value;
13
+ storeInternal[key] = value;
14
14
  return Promise.resolve(value);
15
15
  };
16
16
  const isJestRunning = typeof jest !== 'undefined';
17
17
  const set = isJestRunning ? jest.fn(setInternal) : setInternal;
18
18
  exports.mockSet = set;
19
19
  const provider = {
20
+ store: storeInternal,
20
21
  /**
21
22
  * The name of the provider that can be printed to the logs
22
23
  */
@@ -31,7 +32,7 @@ const provider = {
31
32
  * Get the value of a given key or return `null` if it's not available in memory
32
33
  */
33
34
  getItem(key) {
34
- const value = store[key];
35
+ const value = provider.store[key];
35
36
  return Promise.resolve(value === undefined ? null : value);
36
37
  },
37
38
  /**
@@ -39,7 +40,7 @@ const provider = {
39
40
  */
40
41
  multiGet(keys) {
41
42
  const getPromises = underscore_1.default.map(keys, (key) => new Promise((resolve) => {
42
- this.getItem(key).then((value) => resolve([key, value]));
43
+ provider.getItem(key).then((value) => resolve([key, value]));
43
44
  }));
44
45
  return Promise.all(getPromises);
45
46
  },
@@ -54,7 +55,7 @@ const provider = {
54
55
  * Stores multiple key-value pairs in a batch
55
56
  */
56
57
  multiSet(pairs) {
57
- const setPromises = underscore_1.default.map(pairs, ([key, value]) => this.setItem(key, value));
58
+ const setPromises = underscore_1.default.map(pairs, ([key, value]) => provider.setItem(key, value));
58
59
  return Promise.all(setPromises).then(() => undefined);
59
60
  },
60
61
  /**
@@ -62,7 +63,7 @@ const provider = {
62
63
  */
63
64
  mergeItem(key, change) {
64
65
  // Since Onyx already merged the existing value with the changes, we can just set the value directly.
65
- return this.multiMerge([[key, change]]);
66
+ return provider.multiMerge([[key, change]]);
66
67
  },
67
68
  /**
68
69
  * Multiple merging of existing and new values in a batch
@@ -70,7 +71,7 @@ const provider = {
70
71
  */
71
72
  multiMerge(pairs) {
72
73
  underscore_1.default.forEach(pairs, ([key, value]) => {
73
- const existingValue = store[key];
74
+ const existingValue = provider.store[key];
74
75
  const newValue = utils_1.default.fastMerge(existingValue, value, {
75
76
  shouldRemoveNestedNulls: true,
76
77
  objectRemovalMode: 'replace',
@@ -83,7 +84,7 @@ const provider = {
83
84
  * Remove given key and it's value from memory
84
85
  */
85
86
  removeItem(key) {
86
- delete store[key];
87
+ delete provider.store[key];
87
88
  return Promise.resolve();
88
89
  },
89
90
  /**
@@ -91,7 +92,7 @@ const provider = {
91
92
  */
92
93
  removeItems(keys) {
93
94
  underscore_1.default.each(keys, (key) => {
94
- delete store[key];
95
+ delete provider.store[key];
95
96
  });
96
97
  return Promise.resolve();
97
98
  },
@@ -99,14 +100,17 @@ const provider = {
99
100
  * Clear everything from memory
100
101
  */
101
102
  clear() {
102
- exports.mockStore = store = {};
103
+ // Remove all keys without changing the root object reference.
104
+ for (const key of Object.keys(provider.store)) {
105
+ delete provider.store[key];
106
+ }
103
107
  return Promise.resolve();
104
108
  },
105
109
  /**
106
110
  * Returns all keys available in memory
107
111
  */
108
112
  getAllKeys() {
109
- return Promise.resolve(underscore_1.default.keys(store));
113
+ return Promise.resolve(underscore_1.default.keys(provider.store));
110
114
  },
111
115
  /**
112
116
  * Gets the total bytes of the store.
@@ -117,7 +121,11 @@ const provider = {
117
121
  },
118
122
  };
119
123
  const setMockStore = (data) => {
120
- exports.mockStore = store = data;
124
+ // Replace keys without changing the root object reference.
125
+ for (const key of Object.keys(storeInternal)) {
126
+ delete storeInternal[key];
127
+ }
128
+ Object.assign(storeInternal, data);
121
129
  };
122
130
  exports.setMockStore = setMockStore;
123
131
  exports.default = provider;
@@ -1,3 +1,3 @@
1
1
  import type StorageProvider from './types';
2
- declare const provider: StorageProvider;
2
+ declare const provider: StorageProvider<unknown>;
3
3
  export default provider;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const provider = {
4
+ store: undefined,
4
5
  /**
5
6
  * The name of the provider that can be printed to the logs
6
7
  */
@@ -1,3 +1,8 @@
1
+ /**
2
+ * The SQLiteStorage provider stores everything in a key/value store by
3
+ * converting the value to a JSON string
4
+ */
5
+ import type { NitroSQLiteConnection } from 'react-native-nitro-sqlite';
1
6
  import type StorageProvider from './types';
2
7
  /**
3
8
  * The type of the key-value pair stored in the SQLite database
@@ -8,6 +13,6 @@ type OnyxSQLiteKeyValuePair = {
8
13
  record_key: string;
9
14
  valueJSON: string;
10
15
  };
11
- declare const provider: StorageProvider;
16
+ declare const provider: StorageProvider<NitroSQLiteConnection | undefined>;
12
17
  export default provider;
13
18
  export type { OnyxSQLiteKeyValuePair };
@@ -13,7 +13,6 @@ const utils_1 = __importDefault(require("../../utils"));
13
13
  // https://github.com/margelo/react-native-nitro-sqlite#sending-and-receiving-nullish-values
14
14
  (0, react_native_nitro_sqlite_1.enableSimpleNullHandling)();
15
15
  const DB_NAME = 'OnyxDB';
16
- let db;
17
16
  /**
18
17
  * Prevents the stringifying of the object markers.
19
18
  */
@@ -33,6 +32,7 @@ function generateJSONReplaceSQLQueries(key, patches) {
33
32
  return queries;
34
33
  }
35
34
  const provider = {
35
+ store: undefined,
36
36
  /**
37
37
  * The name of the provider that can be printed to the logs
38
38
  */
@@ -41,16 +41,19 @@ const provider = {
41
41
  * Initializes the storage provider
42
42
  */
43
43
  init() {
44
- db = (0, react_native_nitro_sqlite_1.open)({ name: DB_NAME });
45
- db.execute('CREATE TABLE IF NOT EXISTS keyvaluepairs (record_key TEXT NOT NULL PRIMARY KEY , valueJSON JSON NOT NULL) WITHOUT ROWID;');
44
+ provider.store = (0, react_native_nitro_sqlite_1.open)({ name: DB_NAME });
45
+ provider.store.execute('CREATE TABLE IF NOT EXISTS keyvaluepairs (record_key TEXT NOT NULL PRIMARY KEY , valueJSON JSON NOT NULL) WITHOUT ROWID;');
46
46
  // All of the 3 pragmas below were suggested by SQLite team.
47
47
  // You can find more info about them here: https://www.sqlite.org/pragma.html
48
- db.execute('PRAGMA CACHE_SIZE=-20000;');
49
- db.execute('PRAGMA synchronous=NORMAL;');
50
- db.execute('PRAGMA journal_mode=WAL;');
48
+ provider.store.execute('PRAGMA CACHE_SIZE=-20000;');
49
+ provider.store.execute('PRAGMA synchronous=NORMAL;');
50
+ provider.store.execute('PRAGMA journal_mode=WAL;');
51
51
  },
52
52
  getItem(key) {
53
- return db.executeAsync('SELECT record_key, valueJSON FROM keyvaluepairs WHERE record_key = ?;', [key]).then(({ rows }) => {
53
+ if (!provider.store) {
54
+ throw new Error('Store is not initialized!');
55
+ }
56
+ return provider.store.executeAsync('SELECT record_key, valueJSON FROM keyvaluepairs WHERE record_key = ?;', [key]).then(({ rows }) => {
54
57
  if (!rows || (rows === null || rows === void 0 ? void 0 : rows.length) === 0) {
55
58
  return null;
56
59
  }
@@ -62,26 +65,38 @@ const provider = {
62
65
  });
63
66
  },
64
67
  multiGet(keys) {
68
+ if (!provider.store) {
69
+ throw new Error('Store is not initialized!');
70
+ }
65
71
  const placeholders = keys.map(() => '?').join(',');
66
72
  const command = `SELECT record_key, valueJSON FROM keyvaluepairs WHERE record_key IN (${placeholders});`;
67
- return db.executeAsync(command, keys).then(({ rows }) => {
73
+ return provider.store.executeAsync(command, keys).then(({ rows }) => {
68
74
  // eslint-disable-next-line no-underscore-dangle
69
75
  const result = rows === null || rows === void 0 ? void 0 : rows._array.map((row) => [row.record_key, JSON.parse(row.valueJSON)]);
70
76
  return (result !== null && result !== void 0 ? result : []);
71
77
  });
72
78
  },
73
79
  setItem(key, value) {
74
- return db.executeAsync('REPLACE INTO keyvaluepairs (record_key, valueJSON) VALUES (?, ?);', [key, JSON.stringify(value)]).then(() => undefined);
80
+ if (!provider.store) {
81
+ throw new Error('Store is not initialized!');
82
+ }
83
+ return provider.store.executeAsync('REPLACE INTO keyvaluepairs (record_key, valueJSON) VALUES (?, ?);', [key, JSON.stringify(value)]).then(() => undefined);
75
84
  },
76
85
  multiSet(pairs) {
86
+ if (!provider.store) {
87
+ throw new Error('Store is not initialized!');
88
+ }
77
89
  const query = 'REPLACE INTO keyvaluepairs (record_key, valueJSON) VALUES (?, json(?));';
78
90
  const params = pairs.map((pair) => [pair[0], JSON.stringify(pair[1] === undefined ? null : pair[1])]);
79
91
  if (utils_1.default.isEmptyObject(params)) {
80
92
  return Promise.resolve();
81
93
  }
82
- return db.executeBatchAsync([{ query, params }]).then(() => undefined);
94
+ return provider.store.executeBatchAsync([{ query, params }]).then(() => undefined);
83
95
  },
84
96
  multiMerge(pairs) {
97
+ if (!provider.store) {
98
+ throw new Error('Store is not initialized!');
99
+ }
85
100
  const commands = [];
86
101
  // Query to merge the change into the DB value.
87
102
  const patchQuery = `INSERT INTO keyvaluepairs (record_key, valueJSON)
@@ -112,26 +127,47 @@ const provider = {
112
127
  if (replaceQueryArguments.length > 0) {
113
128
  commands.push({ query: replaceQuery, params: replaceQueryArguments });
114
129
  }
115
- return db.executeBatchAsync(commands).then(() => undefined);
130
+ return provider.store.executeBatchAsync(commands).then(() => undefined);
116
131
  },
117
132
  mergeItem(key, change, replaceNullPatches) {
118
133
  // Since Onyx already merged the existing value with the changes, we can just set the value directly.
119
- return this.multiMerge([[key, change, replaceNullPatches]]);
134
+ return provider.multiMerge([[key, change, replaceNullPatches]]);
135
+ },
136
+ getAllKeys() {
137
+ if (!provider.store) {
138
+ throw new Error('Store is not initialized!');
139
+ }
140
+ return provider.store.executeAsync('SELECT record_key FROM keyvaluepairs;').then(({ rows }) => {
141
+ // eslint-disable-next-line no-underscore-dangle
142
+ const result = rows === null || rows === void 0 ? void 0 : rows._array.map((row) => row.record_key);
143
+ return (result !== null && result !== void 0 ? result : []);
144
+ });
145
+ },
146
+ removeItem(key) {
147
+ if (!provider.store) {
148
+ throw new Error('Store is not initialized!');
149
+ }
150
+ return provider.store.executeAsync('DELETE FROM keyvaluepairs WHERE record_key = ?;', [key]).then(() => undefined);
120
151
  },
121
- getAllKeys: () => db.executeAsync('SELECT record_key FROM keyvaluepairs;').then(({ rows }) => {
122
- // eslint-disable-next-line no-underscore-dangle
123
- const result = rows === null || rows === void 0 ? void 0 : rows._array.map((row) => row.record_key);
124
- return (result !== null && result !== void 0 ? result : []);
125
- }),
126
- removeItem: (key) => db.executeAsync('DELETE FROM keyvaluepairs WHERE record_key = ?;', [key]).then(() => undefined),
127
- removeItems: (keys) => {
152
+ removeItems(keys) {
153
+ if (!provider.store) {
154
+ throw new Error('Store is not initialized!');
155
+ }
128
156
  const placeholders = keys.map(() => '?').join(',');
129
157
  const query = `DELETE FROM keyvaluepairs WHERE record_key IN (${placeholders});`;
130
- return db.executeAsync(query, keys).then(() => undefined);
158
+ return provider.store.executeAsync(query, keys).then(() => undefined);
159
+ },
160
+ clear() {
161
+ if (!provider.store) {
162
+ throw new Error('Store is not initialized!');
163
+ }
164
+ return provider.store.executeAsync('DELETE FROM keyvaluepairs;', []).then(() => undefined);
131
165
  },
132
- clear: () => db.executeAsync('DELETE FROM keyvaluepairs;', []).then(() => undefined),
133
166
  getDatabaseSize() {
134
- return Promise.all([db.executeAsync('PRAGMA page_size;'), db.executeAsync('PRAGMA page_count;'), (0, react_native_device_info_1.getFreeDiskStorage)()]).then(([pageSizeResult, pageCountResult, bytesRemaining]) => {
167
+ if (!provider.store) {
168
+ throw new Error('Store is not initialized!');
169
+ }
170
+ return Promise.all([provider.store.executeAsync('PRAGMA page_size;'), provider.store.executeAsync('PRAGMA page_count;'), (0, react_native_device_info_1.getFreeDiskStorage)()]).then(([pageSizeResult, pageCountResult, bytesRemaining]) => {
135
171
  var _a, _b, _c, _d, _e, _f;
136
172
  const pageSize = (_c = (_b = (_a = pageSizeResult.rows) === null || _a === void 0 ? void 0 : _a.item(0)) === null || _b === void 0 ? void 0 : _b.page_size) !== null && _c !== void 0 ? _c : 0;
137
173
  const pageCount = (_f = (_e = (_d = pageCountResult.rows) === null || _d === void 0 ? void 0 : _d.item(0)) === null || _e === void 0 ? void 0 : _e.page_count) !== null && _f !== void 0 ? _f : 0;
@@ -7,7 +7,8 @@ type DatabaseSize = {
7
7
  bytesRemaining: number;
8
8
  };
9
9
  type OnStorageKeyChanged = <TKey extends OnyxKey>(key: TKey, value: OnyxValue<TKey>) => void;
10
- type StorageProvider = {
10
+ type StorageProvider<TStore> = {
11
+ store: TStore;
11
12
  /**
12
13
  * The name of the provider that can be printed to the logs
13
14
  */
package/dist/utils.js CHANGED
@@ -14,10 +14,10 @@ function fastMerge(target, source, options, metadata, basePath = []) {
14
14
  replaceNullPatches: [],
15
15
  };
16
16
  }
17
- // We have to ignore arrays and nullish values here,
17
+ // We have to ignore arrays, primitives and nullish values here,
18
18
  // otherwise "mergeObject" will throw an error,
19
19
  // because it expects an object as "source"
20
- if (Array.isArray(source) || source === null || source === undefined) {
20
+ if (!isMergeableObject(source)) {
21
21
  return { result: source, replaceNullPatches: metadata.replaceNullPatches };
22
22
  }
23
23
  const optionsWithDefaults = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-onyx",
3
- "version": "3.0.26",
3
+ "version": "3.0.28",
4
4
  "author": "Expensify, Inc.",
5
5
  "homepage": "https://expensify.com",
6
6
  "description": "State management for React Native",
@@ -78,6 +78,7 @@
78
78
  "eslint-plugin-import": "^2.29.1",
79
79
  "eslint-plugin-jsx-a11y": "^6.8.0",
80
80
  "eslint-plugin-react": "^7.31.10",
81
+ "fake-indexeddb": "^6.2.5",
81
82
  "idb-keyval": "^6.2.1",
82
83
  "jest": "^29.7.0",
83
84
  "jest-cli": "^29.7.0",