react-native-onyx
Version:
State management for React Native
176 lines (175 loc) • 6.77 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const IDB = __importStar(require("idb-keyval"));
const utils_1 = __importDefault(require("../../../utils"));
const createStore_1 = __importDefault(require("./createStore"));
const DB_NAME = 'OnyxDB';
const STORE_NAME = 'keyvaluepairs';
const provider = {
// We don't want to initialize the store while the JS bundle loads as idb-keyval will try to use global.indexedDB
// which might not be available in certain environments that load the bundle (e.g. electron main process).
store: undefined,
/**
* The name of the provider that can be printed to the logs
*/
name: 'IDBKeyValProvider',
/**
* Initializes the storage provider
*/
init() {
const newIdbKeyValStore = (0, createStore_1.default)(DB_NAME, STORE_NAME);
if (newIdbKeyValStore == null) {
throw Error('IDBKeyVal store could not be created');
}
provider.store = newIdbKeyValStore;
},
setItem(key, value) {
if (!provider.store) {
throw new Error('Store not initialized!');
}
if (value === null) {
return provider.removeItem(key);
}
return IDB.set(key, value, provider.store);
},
multiGet(keysParam) {
if (!provider.store) {
throw new Error('Store not initialized!');
}
return IDB.getMany(keysParam, provider.store).then((values) => values.map((value, index) => [keysParam[index], value]));
},
multiMerge(pairs) {
if (!provider.store) {
throw new Error('Store not initialized!');
}
return provider.store('readwrite', (store) => {
// Note: we are using the manual store transaction here, to fit the read and update
// of the items in one transaction to achieve best performance.
const getValues = Promise.all(pairs.map(([key]) => IDB.promisifyRequest(store.get(key))));
return getValues.then((values) => {
for (const [index, [key, value]] of pairs.entries()) {
if (value === null) {
store.delete(key);
}
else {
const newValue = utils_1.default.fastMerge(values[index], value, {
shouldRemoveNestedNulls: true,
objectRemovalMode: 'replace',
}).result;
store.put(newValue, key);
}
}
return IDB.promisifyRequest(store.transaction);
});
});
},
mergeItem(key, change) {
// Since Onyx already merged the existing value with the changes, we can just set the value directly.
return provider.multiMerge([[key, change]]);
},
multiSet(pairs) {
if (!provider.store) {
throw new Error('Store not initialized!');
}
return provider.store('readwrite', (store) => {
for (const [key, value] of pairs) {
if (value === null) {
store.delete(key);
}
else {
store.put(value, key);
}
}
return IDB.promisifyRequest(store.transaction);
});
},
clear() {
if (!provider.store) {
throw new Error('Store not initialized!');
}
return IDB.clear(provider.store);
},
getAllKeys() {
if (!provider.store) {
throw new Error('Store not initialized!');
}
return IDB.keys(provider.store);
},
getItem(key) {
if (!provider.store) {
throw new Error('Store not initialized!');
}
return (IDB.get(key, provider.store)
// idb-keyval returns undefined for missing items, but this needs to return null so that idb-keyval does the same thing as SQLiteStorage.
.then((val) => (val === undefined ? null : val)));
},
removeItem(key) {
if (!provider.store) {
throw new Error('Store not initialized!');
}
return IDB.del(key, provider.store);
},
removeItems(keysParam) {
if (!provider.store) {
throw new Error('Store not initialized!');
}
return IDB.delMany(keysParam, provider.store);
},
getDatabaseSize() {
if (!provider.store) {
throw new Error('Store is not initialized!');
}
if (!window.navigator || !window.navigator.storage) {
throw new Error('StorageManager browser API unavailable');
}
return window.navigator.storage
.estimate()
.then((value) => {
var _a, _b, _c;
return ({
bytesUsed: (_a = value.usage) !== null && _a !== void 0 ? _a : 0,
bytesRemaining: ((_b = value.quota) !== null && _b !== void 0 ? _b : 0) - ((_c = value.usage) !== null && _c !== void 0 ? _c : 0),
});
})
.catch((error) => {
throw new Error(`Unable to estimate web storage quota. Original error: ${error}`);
});
},
};
exports.default = provider;