forked from off-topic/apps.apple.com
init commit
This commit is contained in:
64
shared/logger/node_modules/@sentry/browser/esm/transports/fetch.js
generated
vendored
Normal file
64
shared/logger/node_modules/@sentry/browser/esm/transports/fetch.js
generated
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
import { createTransport } from '@sentry/core';
|
||||
import { rejectedSyncPromise } from '@sentry/utils';
|
||||
import { getNativeFetchImplementation, clearCachedFetchImplementation } from './utils.js';
|
||||
|
||||
/**
|
||||
* Creates a Transport that uses the Fetch API to send events to Sentry.
|
||||
*/
|
||||
function makeFetchTransport(
|
||||
options,
|
||||
nativeFetch = getNativeFetchImplementation(),
|
||||
) {
|
||||
let pendingBodySize = 0;
|
||||
let pendingCount = 0;
|
||||
|
||||
function makeRequest(request) {
|
||||
const requestSize = request.body.length;
|
||||
pendingBodySize += requestSize;
|
||||
pendingCount++;
|
||||
|
||||
const requestOptions = {
|
||||
body: request.body,
|
||||
method: 'POST',
|
||||
referrerPolicy: 'origin',
|
||||
headers: options.headers,
|
||||
// Outgoing requests are usually cancelled when navigating to a different page, causing a "TypeError: Failed to
|
||||
// fetch" error and sending a "network_error" client-outcome - in Chrome, the request status shows "(cancelled)".
|
||||
// The `keepalive` flag keeps outgoing requests alive, even when switching pages. We want this since we're
|
||||
// frequently sending events right before the user is switching pages (eg. whenfinishing navigation transactions).
|
||||
// Gotchas:
|
||||
// - `keepalive` isn't supported by Firefox
|
||||
// - As per spec (https://fetch.spec.whatwg.org/#http-network-or-cache-fetch):
|
||||
// If the sum of contentLength and inflightKeepaliveBytes is greater than 64 kibibytes, then return a network error.
|
||||
// We will therefore only activate the flag when we're below that limit.
|
||||
// There is also a limit of requests that can be open at the same time, so we also limit this to 15
|
||||
// See https://github.com/getsentry/sentry-javascript/pull/7553 for details
|
||||
keepalive: pendingBodySize <= 60000 && pendingCount < 15,
|
||||
...options.fetchOptions,
|
||||
};
|
||||
|
||||
try {
|
||||
return nativeFetch(options.url, requestOptions).then(response => {
|
||||
pendingBodySize -= requestSize;
|
||||
pendingCount--;
|
||||
return {
|
||||
statusCode: response.status,
|
||||
headers: {
|
||||
'x-sentry-rate-limits': response.headers.get('X-Sentry-Rate-Limits'),
|
||||
'retry-after': response.headers.get('Retry-After'),
|
||||
},
|
||||
};
|
||||
});
|
||||
} catch (e) {
|
||||
clearCachedFetchImplementation();
|
||||
pendingBodySize -= requestSize;
|
||||
pendingCount--;
|
||||
return rejectedSyncPromise(e);
|
||||
}
|
||||
}
|
||||
|
||||
return createTransport(options, makeRequest);
|
||||
}
|
||||
|
||||
export { makeFetchTransport };
|
||||
//# sourceMappingURL=fetch.js.map
|
||||
133
shared/logger/node_modules/@sentry/browser/esm/transports/offline.js
generated
vendored
Normal file
133
shared/logger/node_modules/@sentry/browser/esm/transports/offline.js
generated
vendored
Normal file
@@ -0,0 +1,133 @@
|
||||
import { makeOfflineTransport } from '@sentry/core';
|
||||
import { serializeEnvelope, parseEnvelope } from '@sentry/utils';
|
||||
|
||||
// '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 licence:
|
||||
|
||||
// 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-ignore - file size hacks
|
||||
request.oncomplete = request.onsuccess = () => resolve(request.result);
|
||||
// @ts-ignore - 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 store */
|
||||
function insert(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);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/** Pop the oldest value from the store */
|
||||
function pop(store) {
|
||||
return store(store => {
|
||||
return keys(store).then(keys => {
|
||||
if (keys.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return promisifyRequest(store.get(keys[0])).then(value => {
|
||||
store.delete(keys[0]);
|
||||
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 {
|
||||
insert: async (env) => {
|
||||
try {
|
||||
const serialized = await serializeEnvelope(env, options.textEncoder);
|
||||
await insert(getStore(), serialized, options.maxQueueSize || 30);
|
||||
} catch (_) {
|
||||
//
|
||||
}
|
||||
},
|
||||
pop: async () => {
|
||||
try {
|
||||
const deserialized = await pop(getStore());
|
||||
if (deserialized) {
|
||||
return parseEnvelope(
|
||||
deserialized,
|
||||
options.textEncoder || new TextEncoder(),
|
||||
options.textDecoder || new TextDecoder(),
|
||||
);
|
||||
}
|
||||
} catch (_) {
|
||||
//
|
||||
}
|
||||
|
||||
return undefined;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function makeIndexedDbOfflineTransport(
|
||||
createTransport,
|
||||
) {
|
||||
return options => createTransport({ ...options, createStore: createIndexedDbStore });
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a transport that uses IndexedDb to store events when offline.
|
||||
*/
|
||||
function makeBrowserOfflineTransport(
|
||||
createTransport,
|
||||
) {
|
||||
return makeIndexedDbOfflineTransport(makeOfflineTransport(createTransport));
|
||||
}
|
||||
|
||||
export { createStore, insert, makeBrowserOfflineTransport, pop };
|
||||
//# sourceMappingURL=offline.js.map
|
||||
85
shared/logger/node_modules/@sentry/browser/esm/transports/utils.js
generated
vendored
Normal file
85
shared/logger/node_modules/@sentry/browser/esm/transports/utils.js
generated
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
import { isNativeFetch, logger } from '@sentry/utils';
|
||||
import { WINDOW } from '../helpers.js';
|
||||
|
||||
let cachedFetchImpl = undefined;
|
||||
|
||||
/**
|
||||
* A special usecase for incorrectly wrapped Fetch APIs in conjunction with ad-blockers.
|
||||
* Whenever someone wraps the Fetch API and returns the wrong promise chain,
|
||||
* this chain becomes orphaned and there is no possible way to capture it's rejections
|
||||
* other than allowing it bubble up to this very handler. eg.
|
||||
*
|
||||
* const f = window.fetch;
|
||||
* window.fetch = function () {
|
||||
* const p = f.apply(this, arguments);
|
||||
*
|
||||
* p.then(function() {
|
||||
* console.log('hi.');
|
||||
* });
|
||||
*
|
||||
* return p;
|
||||
* }
|
||||
*
|
||||
* `p.then(function () { ... })` is producing a completely separate promise chain,
|
||||
* however, what's returned is `p` - the result of original `fetch` call.
|
||||
*
|
||||
* This mean, that whenever we use the Fetch API to send our own requests, _and_
|
||||
* some ad-blocker blocks it, this orphaned chain will _always_ reject,
|
||||
* effectively causing another event to be captured.
|
||||
* This makes a whole process become an infinite loop, which we need to somehow
|
||||
* deal with, and break it in one way or another.
|
||||
*
|
||||
* To deal with this issue, we are making sure that we _always_ use the real
|
||||
* browser Fetch API, instead of relying on what `window.fetch` exposes.
|
||||
* The only downside to this would be missing our own requests as breadcrumbs,
|
||||
* but because we are already not doing this, it should be just fine.
|
||||
*
|
||||
* Possible failed fetch error messages per-browser:
|
||||
*
|
||||
* Chrome: Failed to fetch
|
||||
* Edge: Failed to Fetch
|
||||
* Firefox: NetworkError when attempting to fetch resource
|
||||
* Safari: resource blocked by content blocker
|
||||
*/
|
||||
function getNativeFetchImplementation() {
|
||||
if (cachedFetchImpl) {
|
||||
return cachedFetchImpl;
|
||||
}
|
||||
|
||||
/* eslint-disable @typescript-eslint/unbound-method */
|
||||
|
||||
// Fast path to avoid DOM I/O
|
||||
if (isNativeFetch(WINDOW.fetch)) {
|
||||
return (cachedFetchImpl = WINDOW.fetch.bind(WINDOW));
|
||||
}
|
||||
|
||||
const document = WINDOW.document;
|
||||
let fetchImpl = WINDOW.fetch;
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
if (document && typeof document.createElement === 'function') {
|
||||
try {
|
||||
const sandbox = document.createElement('iframe');
|
||||
sandbox.hidden = true;
|
||||
document.head.appendChild(sandbox);
|
||||
const contentWindow = sandbox.contentWindow;
|
||||
if (contentWindow && contentWindow.fetch) {
|
||||
fetchImpl = contentWindow.fetch;
|
||||
}
|
||||
document.head.removeChild(sandbox);
|
||||
} catch (e) {
|
||||
(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) &&
|
||||
logger.warn('Could not create sandbox iframe for pure fetch check, bailing to window.fetch: ', e);
|
||||
}
|
||||
}
|
||||
|
||||
return (cachedFetchImpl = fetchImpl.bind(WINDOW));
|
||||
/* eslint-enable @typescript-eslint/unbound-method */
|
||||
}
|
||||
|
||||
/** Clears cached fetch impl */
|
||||
function clearCachedFetchImplementation() {
|
||||
cachedFetchImpl = undefined;
|
||||
}
|
||||
|
||||
export { clearCachedFetchImplementation, getNativeFetchImplementation };
|
||||
//# sourceMappingURL=utils.js.map
|
||||
52
shared/logger/node_modules/@sentry/browser/esm/transports/xhr.js
generated
vendored
Normal file
52
shared/logger/node_modules/@sentry/browser/esm/transports/xhr.js
generated
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
import { createTransport } from '@sentry/core';
|
||||
import { SyncPromise } from '@sentry/utils';
|
||||
|
||||
/**
|
||||
* The DONE ready state for XmlHttpRequest
|
||||
*
|
||||
* Defining it here as a constant b/c XMLHttpRequest.DONE is not always defined
|
||||
* (e.g. during testing, it is `undefined`)
|
||||
*
|
||||
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/readyState}
|
||||
*/
|
||||
const XHR_READYSTATE_DONE = 4;
|
||||
|
||||
/**
|
||||
* Creates a Transport that uses the XMLHttpRequest API to send events to Sentry.
|
||||
*/
|
||||
function makeXHRTransport(options) {
|
||||
function makeRequest(request) {
|
||||
return new SyncPromise((resolve, reject) => {
|
||||
const xhr = new XMLHttpRequest();
|
||||
|
||||
xhr.onerror = reject;
|
||||
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState === XHR_READYSTATE_DONE) {
|
||||
resolve({
|
||||
statusCode: xhr.status,
|
||||
headers: {
|
||||
'x-sentry-rate-limits': xhr.getResponseHeader('X-Sentry-Rate-Limits'),
|
||||
'retry-after': xhr.getResponseHeader('Retry-After'),
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
xhr.open('POST', options.url);
|
||||
|
||||
for (const header in options.headers) {
|
||||
if (Object.prototype.hasOwnProperty.call(options.headers, header)) {
|
||||
xhr.setRequestHeader(header, options.headers[header]);
|
||||
}
|
||||
}
|
||||
|
||||
xhr.send(request.body);
|
||||
});
|
||||
}
|
||||
|
||||
return createTransport(options, makeRequest);
|
||||
}
|
||||
|
||||
export { makeXHRTransport };
|
||||
//# sourceMappingURL=xhr.js.map
|
||||
Reference in New Issue
Block a user