Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 20s
Build & Deploy / 🧪 QA (push) Failing after 34s
Build & Deploy / 🏗️ Build (push) Has started running
Build & Deploy / 🚀 Deploy (push) Has been cancelled
Build & Deploy / 🧪 Smoke Test (push) Has been cancelled
Build & Deploy / ⚡ Lighthouse (push) Has been cancelled
Build & Deploy / 🔔 Notify (push) Has been cancelled
169 lines
4.7 KiB
Plaintext
169 lines
4.7 KiB
Plaintext
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
|
const core = require('@sentry/core');
|
|
const helpers = require('../helpers.js');
|
|
const fetch = require('./fetch.js');
|
|
|
|
// 'Store', 'promisifyRequest' and 'createStore' were originally copied from the 'idb-keyval' package before being
|
|
// modified and simplified: https://github.com/jakearchibald/idb-keyval
|
|
//
|
|
// At commit: 0420a704fd6cbb4225429c536b1f61112d012fca
|
|
// Original license:
|
|
|
|
// Copyright 2016, Jake Archibald
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
function promisifyRequest(request) {
|
|
return new Promise((resolve, reject) => {
|
|
// @ts-expect-error - file size hacks
|
|
request.oncomplete = request.onsuccess = () => resolve(request.result);
|
|
// @ts-expect-error - file size hacks
|
|
request.onabort = request.onerror = () => reject(request.error);
|
|
});
|
|
}
|
|
|
|
/** Create or open an IndexedDb store */
|
|
function createStore(dbName, storeName) {
|
|
const request = indexedDB.open(dbName);
|
|
request.onupgradeneeded = () => request.result.createObjectStore(storeName);
|
|
const dbp = promisifyRequest(request);
|
|
|
|
return callback => dbp.then(db => callback(db.transaction(storeName, 'readwrite').objectStore(storeName)));
|
|
}
|
|
|
|
function keys(store) {
|
|
return promisifyRequest(store.getAllKeys() );
|
|
}
|
|
|
|
/** Insert into the end of the store */
|
|
function push(store, value, maxQueueSize) {
|
|
return store(store => {
|
|
return keys(store).then(keys => {
|
|
if (keys.length >= maxQueueSize) {
|
|
return;
|
|
}
|
|
|
|
// We insert with an incremented key so that the entries are popped in order
|
|
store.put(value, Math.max(...keys, 0) + 1);
|
|
return promisifyRequest(store.transaction);
|
|
});
|
|
});
|
|
}
|
|
|
|
/** Insert into the front of the store */
|
|
function unshift(store, value, maxQueueSize) {
|
|
return store(store => {
|
|
return keys(store).then(keys => {
|
|
if (keys.length >= maxQueueSize) {
|
|
return;
|
|
}
|
|
|
|
// We insert with an decremented key so that the entries are popped in order
|
|
store.put(value, Math.min(...keys, 0) - 1);
|
|
return promisifyRequest(store.transaction);
|
|
});
|
|
});
|
|
}
|
|
|
|
/** Pop the oldest value from the store */
|
|
function shift(store) {
|
|
return store(store => {
|
|
return keys(store).then(keys => {
|
|
const firstKey = keys[0];
|
|
if (firstKey == null) {
|
|
return undefined;
|
|
}
|
|
|
|
return promisifyRequest(store.get(firstKey)).then(value => {
|
|
store.delete(firstKey);
|
|
return promisifyRequest(store.transaction).then(() => value);
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
function createIndexedDbStore(options) {
|
|
let store;
|
|
|
|
// Lazily create the store only when it's needed
|
|
function getStore() {
|
|
if (store == undefined) {
|
|
store = createStore(options.dbName || 'sentry-offline', options.storeName || 'queue');
|
|
}
|
|
|
|
return store;
|
|
}
|
|
|
|
return {
|
|
push: async (env) => {
|
|
try {
|
|
const serialized = await core.serializeEnvelope(env);
|
|
await push(getStore(), serialized, options.maxQueueSize || 30);
|
|
} catch {
|
|
//
|
|
}
|
|
},
|
|
unshift: async (env) => {
|
|
try {
|
|
const serialized = await core.serializeEnvelope(env);
|
|
await unshift(getStore(), serialized, options.maxQueueSize || 30);
|
|
} catch {
|
|
//
|
|
}
|
|
},
|
|
shift: async () => {
|
|
try {
|
|
const deserialized = await shift(getStore());
|
|
if (deserialized) {
|
|
return core.parseEnvelope(deserialized);
|
|
}
|
|
} catch {
|
|
//
|
|
}
|
|
|
|
return undefined;
|
|
},
|
|
};
|
|
}
|
|
|
|
function makeIndexedDbOfflineTransport(
|
|
createTransport,
|
|
) {
|
|
return options => {
|
|
const transport = createTransport({ ...options, createStore: createIndexedDbStore });
|
|
|
|
helpers.WINDOW.addEventListener('online', async _ => {
|
|
await transport.flush();
|
|
});
|
|
|
|
return transport;
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Creates a transport that uses IndexedDb to store events when offline.
|
|
*/
|
|
function makeBrowserOfflineTransport(
|
|
createTransport = fetch.makeFetchTransport,
|
|
) {
|
|
return makeIndexedDbOfflineTransport(core.makeOfflineTransport(createTransport));
|
|
}
|
|
|
|
exports.createStore = createStore;
|
|
exports.makeBrowserOfflineTransport = makeBrowserOfflineTransport;
|
|
exports.push = push;
|
|
exports.shift = shift;
|
|
exports.unshift = unshift;
|
|
//# sourceMappingURL=offline.js.map
|