offline.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. Object.defineProperty(exports, '__esModule', { value: true });
  2. const core = require('@sentry/core');
  3. const utils = require('@sentry/utils');
  4. // 'Store', 'promisifyRequest' and 'createStore' were originally copied from the 'idb-keyval' package before being
  5. // modified and simplified: https://github.com/jakearchibald/idb-keyval
  6. //
  7. // At commit: 0420a704fd6cbb4225429c536b1f61112d012fca
  8. // Original licence:
  9. // Copyright 2016, Jake Archibald
  10. //
  11. // Licensed under the Apache License, Version 2.0 (the "License");
  12. // you may not use this file except in compliance with the License.
  13. // You may obtain a copy of the License at
  14. //
  15. // http://www.apache.org/licenses/LICENSE-2.0
  16. //
  17. // Unless required by applicable law or agreed to in writing, software
  18. // distributed under the License is distributed on an "AS IS" BASIS,
  19. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  20. // See the License for the specific language governing permissions and
  21. // limitations under the License.
  22. function promisifyRequest(request) {
  23. return new Promise((resolve, reject) => {
  24. // @ts-expect-error - file size hacks
  25. request.oncomplete = request.onsuccess = () => resolve(request.result);
  26. // @ts-expect-error - file size hacks
  27. request.onabort = request.onerror = () => reject(request.error);
  28. });
  29. }
  30. /** Create or open an IndexedDb store */
  31. function createStore(dbName, storeName) {
  32. const request = indexedDB.open(dbName);
  33. request.onupgradeneeded = () => request.result.createObjectStore(storeName);
  34. const dbp = promisifyRequest(request);
  35. return callback => dbp.then(db => callback(db.transaction(storeName, 'readwrite').objectStore(storeName)));
  36. }
  37. function keys(store) {
  38. return promisifyRequest(store.getAllKeys() );
  39. }
  40. /** Insert into the store */
  41. function insert(store, value, maxQueueSize) {
  42. return store(store => {
  43. return keys(store).then(keys => {
  44. if (keys.length >= maxQueueSize) {
  45. return;
  46. }
  47. // We insert with an incremented key so that the entries are popped in order
  48. store.put(value, Math.max(...keys, 0) + 1);
  49. return promisifyRequest(store.transaction);
  50. });
  51. });
  52. }
  53. /** Pop the oldest value from the store */
  54. function pop(store) {
  55. return store(store => {
  56. return keys(store).then(keys => {
  57. if (keys.length === 0) {
  58. return undefined;
  59. }
  60. return promisifyRequest(store.get(keys[0])).then(value => {
  61. store.delete(keys[0]);
  62. return promisifyRequest(store.transaction).then(() => value);
  63. });
  64. });
  65. });
  66. }
  67. function createIndexedDbStore(options) {
  68. let store;
  69. // Lazily create the store only when it's needed
  70. function getStore() {
  71. if (store == undefined) {
  72. store = createStore(options.dbName || 'sentry-offline', options.storeName || 'queue');
  73. }
  74. return store;
  75. }
  76. return {
  77. insert: async (env) => {
  78. try {
  79. const serialized = await utils.serializeEnvelope(env, options.textEncoder);
  80. await insert(getStore(), serialized, options.maxQueueSize || 30);
  81. } catch (_) {
  82. //
  83. }
  84. },
  85. pop: async () => {
  86. try {
  87. const deserialized = await pop(getStore());
  88. if (deserialized) {
  89. return utils.parseEnvelope(
  90. deserialized,
  91. options.textEncoder || new TextEncoder(),
  92. options.textDecoder || new TextDecoder(),
  93. );
  94. }
  95. } catch (_) {
  96. //
  97. }
  98. return undefined;
  99. },
  100. };
  101. }
  102. function makeIndexedDbOfflineTransport(
  103. createTransport,
  104. ) {
  105. return options => createTransport({ ...options, createStore: createIndexedDbStore });
  106. }
  107. /**
  108. * Creates a transport that uses IndexedDb to store events when offline.
  109. */
  110. function makeBrowserOfflineTransport(
  111. createTransport,
  112. ) {
  113. return makeIndexedDbOfflineTransport(core.makeOfflineTransport(createTransport));
  114. }
  115. exports.createStore = createStore;
  116. exports.insert = insert;
  117. exports.makeBrowserOfflineTransport = makeBrowserOfflineTransport;
  118. exports.pop = pop;
  119. //# sourceMappingURL=offline.js.map