compat.js 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. import safariFix from 'safari-14-idb-fix';
  2. function promisifyRequest(request) {
  3. return new Promise(function (resolve, reject) {
  4. // @ts-ignore - file size hacks
  5. request.oncomplete = request.onsuccess = function () {
  6. return resolve(request.result);
  7. }; // @ts-ignore - file size hacks
  8. request.onabort = request.onerror = function () {
  9. return reject(request.error);
  10. };
  11. });
  12. }
  13. function createStore(dbName, storeName) {
  14. var dbp = safariFix().then(function () {
  15. var request = indexedDB.open(dbName);
  16. request.onupgradeneeded = function () {
  17. return request.result.createObjectStore(storeName);
  18. };
  19. return promisifyRequest(request);
  20. });
  21. return function (txMode, callback) {
  22. return dbp.then(function (db) {
  23. return callback(db.transaction(storeName, txMode).objectStore(storeName));
  24. });
  25. };
  26. }
  27. var defaultGetStoreFunc;
  28. function defaultGetStore() {
  29. if (!defaultGetStoreFunc) {
  30. defaultGetStoreFunc = createStore('keyval-store', 'keyval');
  31. }
  32. return defaultGetStoreFunc;
  33. }
  34. /**
  35. * Get a value by its key.
  36. *
  37. * @param key
  38. * @param customStore Method to get a custom store. Use with caution (see the docs).
  39. */
  40. function get(key) {
  41. var customStore = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : defaultGetStore();
  42. return customStore('readonly', function (store) {
  43. return promisifyRequest(store.get(key));
  44. });
  45. }
  46. /**
  47. * Set a value with a key.
  48. *
  49. * @param key
  50. * @param value
  51. * @param customStore Method to get a custom store. Use with caution (see the docs).
  52. */
  53. function set(key, value) {
  54. var customStore = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : defaultGetStore();
  55. return customStore('readwrite', function (store) {
  56. store.put(value, key);
  57. return promisifyRequest(store.transaction);
  58. });
  59. }
  60. /**
  61. * Set multiple values at once. This is faster than calling set() multiple times.
  62. * It's also atomic – if one of the pairs can't be added, none will be added.
  63. *
  64. * @param entries Array of entries, where each entry is an array of `[key, value]`.
  65. * @param customStore Method to get a custom store. Use with caution (see the docs).
  66. */
  67. function setMany(entries) {
  68. var customStore = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : defaultGetStore();
  69. return customStore('readwrite', function (store) {
  70. entries.forEach(function (entry) {
  71. return store.put(entry[1], entry[0]);
  72. });
  73. return promisifyRequest(store.transaction);
  74. });
  75. }
  76. /**
  77. * Get multiple values by their keys
  78. *
  79. * @param keys
  80. * @param customStore Method to get a custom store. Use with caution (see the docs).
  81. */
  82. function getMany(keys) {
  83. var customStore = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : defaultGetStore();
  84. return customStore('readonly', function (store) {
  85. return Promise.all(keys.map(function (key) {
  86. return promisifyRequest(store.get(key));
  87. }));
  88. });
  89. }
  90. /**
  91. * Update a value. This lets you see the old value and update it as an atomic operation.
  92. *
  93. * @param key
  94. * @param updater A callback that takes the old value and returns a new value.
  95. * @param customStore Method to get a custom store. Use with caution (see the docs).
  96. */
  97. function update(key, updater) {
  98. var customStore = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : defaultGetStore();
  99. return customStore('readwrite', function (store) {
  100. return (// Need to create the promise manually.
  101. // If I try to chain promises, the transaction closes in browsers
  102. // that use a promise polyfill (IE10/11).
  103. new Promise(function (resolve, reject) {
  104. store.get(key).onsuccess = function () {
  105. try {
  106. store.put(updater(this.result), key);
  107. resolve(promisifyRequest(store.transaction));
  108. } catch (err) {
  109. reject(err);
  110. }
  111. };
  112. })
  113. );
  114. });
  115. }
  116. /**
  117. * Delete a particular key from the store.
  118. *
  119. * @param key
  120. * @param customStore Method to get a custom store. Use with caution (see the docs).
  121. */
  122. function del(key) {
  123. var customStore = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : defaultGetStore();
  124. return customStore('readwrite', function (store) {
  125. store.delete(key);
  126. return promisifyRequest(store.transaction);
  127. });
  128. }
  129. /**
  130. * Delete multiple keys at once.
  131. *
  132. * @param keys List of keys to delete.
  133. * @param customStore Method to get a custom store. Use with caution (see the docs).
  134. */
  135. function delMany(keys) {
  136. var customStore = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : defaultGetStore();
  137. return customStore('readwrite', function (store) {
  138. keys.forEach(function (key) {
  139. return store.delete(key);
  140. });
  141. return promisifyRequest(store.transaction);
  142. });
  143. }
  144. /**
  145. * Clear all values in the store.
  146. *
  147. * @param customStore Method to get a custom store. Use with caution (see the docs).
  148. */
  149. function clear() {
  150. var customStore = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : defaultGetStore();
  151. return customStore('readwrite', function (store) {
  152. store.clear();
  153. return promisifyRequest(store.transaction);
  154. });
  155. }
  156. function eachCursor(customStore, callback) {
  157. return customStore('readonly', function (store) {
  158. // This would be store.getAllKeys(), but it isn't supported by Edge or Safari.
  159. // And openKeyCursor isn't supported by Safari.
  160. store.openCursor().onsuccess = function () {
  161. if (!this.result) return;
  162. callback(this.result);
  163. this.result.continue();
  164. };
  165. return promisifyRequest(store.transaction);
  166. });
  167. }
  168. /**
  169. * Get all keys in the store.
  170. *
  171. * @param customStore Method to get a custom store. Use with caution (see the docs).
  172. */
  173. function keys() {
  174. var customStore = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : defaultGetStore();
  175. var items = [];
  176. return eachCursor(customStore, function (cursor) {
  177. return items.push(cursor.key);
  178. }).then(function () {
  179. return items;
  180. });
  181. }
  182. /**
  183. * Get all values in the store.
  184. *
  185. * @param customStore Method to get a custom store. Use with caution (see the docs).
  186. */
  187. function values() {
  188. var customStore = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : defaultGetStore();
  189. var items = [];
  190. return eachCursor(customStore, function (cursor) {
  191. return items.push(cursor.value);
  192. }).then(function () {
  193. return items;
  194. });
  195. }
  196. /**
  197. * Get all entries in the store. Each entry is an array of `[key, value]`.
  198. *
  199. * @param customStore Method to get a custom store. Use with caution (see the docs).
  200. */
  201. function entries() {
  202. var customStore = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : defaultGetStore();
  203. var items = [];
  204. return eachCursor(customStore, function (cursor) {
  205. return items.push([cursor.key, cursor.value]);
  206. }).then(function () {
  207. return items;
  208. });
  209. }
  210. export { clear, createStore, del, delMany, entries, get, getMany, keys, promisifyRequest, set, setMany, update, values };