mirror of
https://github.com/Kong/insomnia.git
synced 2026-10-24 23:59:16 -04:00
Segment Queueable Events for App Started (#4383)
This commit is contained in:
1 parent
35c451b803
commit
24b610ffeb
7 files changed
+170
-143
No files matched your search
@@ -34,7 +34,7 @@ describe('init()', () => {
|
||||
});
|
||||
expect(settings.enableAnalytics).toBe(false);
|
||||
expect(electron.net.request.mock.calls).toEqual([]);
|
||||
await _trackEvent(true, 'Foo', 'Bar');
|
||||
await _trackEvent({ interactive: true, category: 'Foo', action: 'Bar' });
|
||||
jest.runAllTimers();
|
||||
expect(electron.net.request.mock.calls).toEqual([]);
|
||||
});
|
||||
@@ -46,7 +46,7 @@ describe('init()', () => {
|
||||
});
|
||||
expect(settings.enableAnalytics).toBe(true);
|
||||
expect(electron.net.request.mock.calls).toEqual([]);
|
||||
await _trackEvent(true, 'Foo', 'Bar');
|
||||
await _trackEvent({ interactive: true, category: 'Foo', action: 'Bar' });
|
||||
jest.runAllTimers();
|
||||
expect(electron.net.request.mock.calls).toEqual([
|
||||
[
|
||||
@@ -79,7 +79,7 @@ describe('init()', () => {
|
||||
deviceId: 'device',
|
||||
enableAnalytics: true,
|
||||
});
|
||||
await _trackEvent(false, 'Foo', 'Bar');
|
||||
await _trackEvent({ interactive: false, category: 'Foo', action: 'Bar' });
|
||||
jest.runAllTimers();
|
||||
expect(electron.net.request.mock.calls).toEqual([
|
||||
[
|
||||
@@ -146,7 +146,13 @@ describe('init()', () => {
|
||||
});
|
||||
await _trackPageView('/my/path');
|
||||
jest.runAllTimers();
|
||||
await _trackEvent(true, 'cat', 'act', 'lab', 'val');
|
||||
await _trackEvent({
|
||||
interactive: true,
|
||||
category: 'cat',
|
||||
action: 'act',
|
||||
label: 'lab',
|
||||
value: 'val',
|
||||
});
|
||||
expect(electron.net.request.mock.calls).toEqual([
|
||||
[
|
||||
'https://www.google-analytics.com/collect?' +
|
||||
|
||||
@@ -52,41 +52,13 @@ export function trackEvent(
|
||||
value?: string | null,
|
||||
) {
|
||||
process.nextTick(async () => {
|
||||
await _trackEvent(true, category, action, label, value);
|
||||
});
|
||||
}
|
||||
|
||||
export function trackNonInteractiveEvent(
|
||||
category: string,
|
||||
action: string,
|
||||
label?: string | null,
|
||||
value?: string | null,
|
||||
) {
|
||||
process.nextTick(async () => {
|
||||
await _trackEvent(false, category, action, label, value, false);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Tracks an analytics event but queues it for later if analytics are
|
||||
* currently disabled. Once analytics setting is enabled, any queued
|
||||
* events will be sent automatically.
|
||||
*
|
||||
* This should be used sparingly!
|
||||
*
|
||||
* @param category
|
||||
* @param action
|
||||
* @param label
|
||||
* @param value
|
||||
*/
|
||||
export function trackNonInteractiveEventQueueable(
|
||||
category: string,
|
||||
action: string,
|
||||
label?: string | null,
|
||||
value?: string | null,
|
||||
) {
|
||||
process.nextTick(async () => {
|
||||
await _trackEvent(false, category, action, label, value, true);
|
||||
await _trackEvent({
|
||||
interactive: true,
|
||||
category,
|
||||
action,
|
||||
label,
|
||||
value,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -115,6 +87,7 @@ export async function getDeviceId() {
|
||||
let segmentClient: Analytics | null = null;
|
||||
|
||||
export enum SegmentEvent {
|
||||
appStarted = 'App Started',
|
||||
collectionCreate = 'Collection Created',
|
||||
documentCreate = 'Document Created',
|
||||
requestCreate = 'Request Created',
|
||||
@@ -149,10 +122,60 @@ export function vcsSegmentEventProperties(
|
||||
};
|
||||
}
|
||||
|
||||
export async function trackSegmentEvent(event: SegmentEvent, properties?: Record<string, any>) {
|
||||
interface QueuedSegmentEvent {
|
||||
event: SegmentEvent;
|
||||
properties?: Record<string, any>;
|
||||
/**
|
||||
* timestamps are required for Queued Segment Events so that when/if the event is enventually fired, it's fired with the timestamp when the event actually occurred.
|
||||
* see: https://segment.com/docs/connections/spec/common
|
||||
*/
|
||||
timestamp: Date;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush any analytics events that were built up when analytics were disabled.
|
||||
*/
|
||||
let queuedEvents: QueuedSegmentEvent[] = [];
|
||||
|
||||
async function flushQueuedEvents() {
|
||||
console.log(`[segment] Flushing ${queuedEvents.length} queued events`, queuedEvents);
|
||||
const events = [...queuedEvents];
|
||||
|
||||
// Clear queue before we even start sending to prevent races
|
||||
queuedEvents = [];
|
||||
|
||||
await Promise.all(events.map(({ event, properties, timestamp }) => (
|
||||
trackSegmentEvent(event, properties, { timestamp })
|
||||
)));
|
||||
}
|
||||
|
||||
interface TrackSegmentEventOptions {
|
||||
/**
|
||||
* Tracks an analytics event but queues it for later if analytics are currently disabled
|
||||
* Once analytics setting is enabled, any queued events will be sent automatically, all at once.
|
||||
*/
|
||||
queueable?: boolean;
|
||||
|
||||
timestamp?: Date;
|
||||
}
|
||||
|
||||
export async function trackSegmentEvent(
|
||||
event: SegmentEvent,
|
||||
properties?: Record<string, any>,
|
||||
{ queueable, timestamp }: TrackSegmentEventOptions = {},
|
||||
) {
|
||||
const settings = await models.settings.getOrCreate();
|
||||
|
||||
if (!settings.enableAnalytics) {
|
||||
if (queueable) {
|
||||
const queuedEvent: QueuedSegmentEvent = {
|
||||
event,
|
||||
properties,
|
||||
timestamp: new Date(),
|
||||
};
|
||||
console.log('[segment] Queued event', queuedEvent);
|
||||
queuedEvents.push(queuedEvent);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -177,6 +200,7 @@ export async function trackSegmentEvent(event: SegmentEvent, properties?: Record
|
||||
userId,
|
||||
event,
|
||||
properties,
|
||||
...(timestamp ? { timestamp } : {}),
|
||||
context: {
|
||||
app: {
|
||||
name: getAppName(),
|
||||
@@ -187,9 +211,13 @@ export async function trackSegmentEvent(event: SegmentEvent, properties?: Record
|
||||
version: process.getSystemVersion(),
|
||||
},
|
||||
},
|
||||
}, error => {
|
||||
if (error) {
|
||||
console.warn('[analytics] Error sending segment event', error);
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
console.warn('[analytics] Error sending segment event', err);
|
||||
} catch (error: unknown) {
|
||||
console.warn('[analytics] Unexpected error while sending segment event', error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,14 +240,19 @@ function _getOsName() {
|
||||
}
|
||||
|
||||
// Exported for testing
|
||||
export async function _trackEvent(
|
||||
interactive: boolean,
|
||||
category: string,
|
||||
action: string,
|
||||
label?: string | null,
|
||||
value?: string | null,
|
||||
queueable?: boolean | null,
|
||||
) {
|
||||
export async function _trackEvent({
|
||||
interactive,
|
||||
category,
|
||||
action,
|
||||
label,
|
||||
value,
|
||||
}: {
|
||||
interactive: boolean;
|
||||
category: string;
|
||||
action: string;
|
||||
label?: string | null;
|
||||
value?: string | null;
|
||||
}) {
|
||||
const prefix = interactive ? '[ga] Event' : '[ga] Non-interactive';
|
||||
console.log(prefix, [category, action, label, value].filter(Boolean).join(', '));
|
||||
const params = [
|
||||
@@ -235,24 +268,24 @@ export async function _trackEvent(
|
||||
name: KEY_EVENT_ACTION,
|
||||
value: action,
|
||||
},
|
||||
];
|
||||
!interactive &&
|
||||
params.push({
|
||||
|
||||
...(!interactive ? [{
|
||||
name: KEY_NON_INTERACTION,
|
||||
value: '1',
|
||||
});
|
||||
label &&
|
||||
params.push({
|
||||
}] : []),
|
||||
|
||||
...(label ? [{
|
||||
name: KEY_EVENT_LABEL,
|
||||
value: label,
|
||||
});
|
||||
value &&
|
||||
params.push({
|
||||
}] : []),
|
||||
|
||||
...(value ? [{
|
||||
name: KEY_EVENT_VALUE,
|
||||
value: value,
|
||||
});
|
||||
// @ts-expect-error -- TSCONVERSION appears to be a genuine error
|
||||
await _sendToGoogle(params, !!queueable);
|
||||
}] : []),
|
||||
];
|
||||
|
||||
await _sendToGoogle({ params });
|
||||
}
|
||||
|
||||
export async function _trackPageView(location: string) {
|
||||
@@ -264,8 +297,7 @@ export async function _trackPageView(location: string) {
|
||||
value: 'pageview',
|
||||
},
|
||||
];
|
||||
// @ts-expect-error -- TSCONVERSION appears to be a genuine error
|
||||
await _sendToGoogle(params, false);
|
||||
await _sendToGoogle({ params });
|
||||
}
|
||||
|
||||
async function _getDefaultParams(): Promise<RequestParameter[]> {
|
||||
@@ -274,6 +306,9 @@ async function _getDefaultParams(): Promise<RequestParameter[]> {
|
||||
const ua = String(window?.navigator?.userAgent)
|
||||
.replace(new RegExp(`${getAppId()}\\/\\d+\\.\\d+\\.\\d+ `), '')
|
||||
.replace(/Electron\/\d+\.\d+\.\d+ /, '');
|
||||
|
||||
const viewport = getViewportSize();
|
||||
|
||||
const params = [
|
||||
{
|
||||
name: KEY_VERSION,
|
||||
@@ -331,50 +366,40 @@ async function _getDefaultParams(): Promise<RequestParameter[]> {
|
||||
name: KEY_APPLICATION_VERSION,
|
||||
value: getAppVersion(),
|
||||
},
|
||||
];
|
||||
const viewport = getViewportSize();
|
||||
viewport &&
|
||||
params.push({
|
||||
...(viewport ? [{
|
||||
name: KEY_VIEWPORT_SIZE,
|
||||
value: viewport,
|
||||
});
|
||||
global.document &&
|
||||
params.push({
|
||||
}] : []),
|
||||
...(global.document ? [{
|
||||
name: KEY_DOCUMENT_ENCODING,
|
||||
value: global.document.inputEncoding,
|
||||
});
|
||||
}] : []),
|
||||
];
|
||||
return params;
|
||||
}
|
||||
|
||||
// Monitor database changes to see if analytics gets enabled. If analytics
|
||||
// become enabled, flush any queued events.
|
||||
// Monitor database changes to see if analytics gets enabled.
|
||||
// If analytics become enabled, flush any queued events.
|
||||
db.onChange(async changes => {
|
||||
for (const change of changes) {
|
||||
const [event, doc] = change;
|
||||
|
||||
if (isSettings(doc) && event === 'update') {
|
||||
if (doc.enableAnalytics) {
|
||||
await _flushQueuedEvents();
|
||||
await flushQueuedEvents();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
async function _sendToGoogle(params: RequestParameter, queueable: boolean) {
|
||||
async function _sendToGoogle({ params }: { params: RequestParameter[] }) {
|
||||
const settings = await models.settings.getOrCreate();
|
||||
|
||||
if (!settings.enableAnalytics) {
|
||||
if (queueable) {
|
||||
console.log('[ga] Queued event', params);
|
||||
|
||||
_queuedEvents.push(params);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const baseParams = await _getDefaultParams();
|
||||
// @ts-expect-error -- TSCONVERSION appears to be a genuine error
|
||||
const allParams = [...baseParams, ...params];
|
||||
const qs = buildQueryStringFromParams(allParams);
|
||||
const baseUrl = isDevelopment()
|
||||
@@ -427,23 +452,3 @@ async function _sendToGoogle(params: RequestParameter, queueable: boolean) {
|
||||
});
|
||||
request.end();
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush any analytics events that were built up when analytics
|
||||
* were disabled.
|
||||
* @returns {Promise<void>}
|
||||
* @private
|
||||
*/
|
||||
let _queuedEvents: RequestParameter[] = [];
|
||||
|
||||
async function _flushQueuedEvents() {
|
||||
console.log(`[ga] Flushing ${_queuedEvents.length} queued events`);
|
||||
const tmp = [..._queuedEvents];
|
||||
// Clear queue before we even start sending to prevent races
|
||||
_queuedEvents = [];
|
||||
|
||||
for (const params of tmp) {
|
||||
console.log('[ga] Flushing queued event', params);
|
||||
await _sendToGoogle(params, false);
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ import installExtension, { REACT_DEVELOPER_TOOLS, REDUX_DEVTOOLS } from 'electro
|
||||
import path from 'path';
|
||||
|
||||
import appConfig from '../config/config.json';
|
||||
import { trackNonInteractiveEventQueueable } from './common/analytics';
|
||||
import { SegmentEvent, trackSegmentEvent } from './common/analytics';
|
||||
import { changelogUrl, getAppVersion, isDevelopment, isMac } from './common/constants';
|
||||
import { database } from './common/database';
|
||||
import { disableSpellcheckerDownload, exitAppFailure } from './common/electron-helpers';
|
||||
@@ -200,21 +200,14 @@ async function _trackStats() {
|
||||
lastVersion: oldStats.currentVersion,
|
||||
launches: oldStats.launches + 1,
|
||||
});
|
||||
// Update Stats Object
|
||||
const firstLaunch = stats.launches === 1;
|
||||
const justUpdated = !firstLaunch && stats.currentVersion !== stats.lastVersion;
|
||||
|
||||
if (firstLaunch) {
|
||||
trackNonInteractiveEventQueueable('General', 'First Launch', stats.currentVersion);
|
||||
} else if (justUpdated) {
|
||||
trackNonInteractiveEventQueueable('General', 'Updated', stats.currentVersion);
|
||||
} else {
|
||||
trackNonInteractiveEventQueueable('General', 'Launched', stats.currentVersion);
|
||||
}
|
||||
trackSegmentEvent(SegmentEvent.appStarted, {}, { queueable: true });
|
||||
|
||||
ipcMain.once('window-ready', () => {
|
||||
const { currentVersion } = stats;
|
||||
const { currentVersion, launches, lastVersion } = stats;
|
||||
|
||||
const firstLaunch = launches === 1;
|
||||
const justUpdated = !firstLaunch && currentVersion !== lastVersion;
|
||||
if (!justUpdated || !currentVersion) {
|
||||
return;
|
||||
}
|
||||
|
||||
Generated
+32
-12
@@ -5500,9 +5500,9 @@
|
||||
"integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw=="
|
||||
},
|
||||
"@types/analytics-node": {
|
||||
"version": "3.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/analytics-node/-/analytics-node-3.1.4.tgz",
|
||||
"integrity": "sha512-i6cqjFotMq1dEwXxyXRqnzp/HmWPCskptrVUQ1UzRIGs/zICFWM2bIJyLt6f9A9/+qE98wls1AHWPQ4WXYS0HA==",
|
||||
"version": "3.1.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/analytics-node/-/analytics-node-3.1.7.tgz",
|
||||
"integrity": "sha512-qoBHCXqFqC22Up8dus8YIloZ2t1f8MJx9b3E08ZBK04yJ/ai8U2WuFUnaIBiD1okw4VtuNjqKn9mgLHnLxb5OQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/anymatch": {
|
||||
@@ -7178,18 +7178,38 @@
|
||||
"dev": true
|
||||
},
|
||||
"analytics-node": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/analytics-node/-/analytics-node-4.0.1.tgz",
|
||||
"integrity": "sha512-+zXOOTB+eTRW6R9+pfvPfk1dHraFJzhNnAyZiYJIDGOjHQgfk9qfqgoJX9MfR4qY0J/E1YJ3FBncrLGadTDW1A==",
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/analytics-node/-/analytics-node-6.0.0.tgz",
|
||||
"integrity": "sha512-qhwB5Fl/ps7VTg1/RnD3qJohceSHUjzTBqNn3DCmQZu/AdgPbGPeNFYu2o3xIuIyq+xZElrv0Do0b/zuGxBL9g==",
|
||||
"requires": {
|
||||
"@segment/loosely-validate-event": "^2.0.0",
|
||||
"axios": "^0.21.1",
|
||||
"axios-retry": "^3.0.2",
|
||||
"axios": "^0.21.4",
|
||||
"axios-retry": "3.2.0",
|
||||
"lodash.isstring": "^4.0.1",
|
||||
"md5": "^2.2.1",
|
||||
"ms": "^2.0.0",
|
||||
"remove-trailing-slash": "^0.1.0",
|
||||
"uuid": "^3.2.1"
|
||||
"uuid": "^8.3.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": {
|
||||
"version": "0.21.4",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz",
|
||||
"integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==",
|
||||
"requires": {
|
||||
"follow-redirects": "^1.14.0"
|
||||
}
|
||||
},
|
||||
"follow-redirects": {
|
||||
"version": "1.14.7",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.7.tgz",
|
||||
"integrity": "sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ=="
|
||||
},
|
||||
"uuid": {
|
||||
"version": "8.3.2",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"ansi-align": {
|
||||
@@ -7790,9 +7810,9 @@
|
||||
}
|
||||
},
|
||||
"axios-retry": {
|
||||
"version": "3.1.9",
|
||||
"resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-3.1.9.tgz",
|
||||
"integrity": "sha512-NFCoNIHq8lYkJa6ku4m+V1837TP6lCa7n79Iuf8/AqATAHYB0ISaAS1eyIenDOfHOLtym34W65Sjke2xjg2fsA==",
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-3.2.0.tgz",
|
||||
"integrity": "sha512-RK2cLMgIsAQBDhlIsJR5dOhODPigvel18XUv1dDXW+4k1FzebyfRk+C+orot6WPZOYFKSfhLwHPwVmTVOODQ5w==",
|
||||
"requires": {
|
||||
"is-retry-allowed": "^1.1.0"
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
"@hapi/hawk": "^8.0.0",
|
||||
"@hot-loader/react-dom": "^16.8.6",
|
||||
"@stoplight/spectral": "^5.9.0",
|
||||
"analytics-node": "^4.0.1",
|
||||
"analytics-node": "^6.0.0",
|
||||
"aws4": "^1.9.0",
|
||||
"axios": "^0.21.2",
|
||||
"class-autobind-decorator": "^3.0.1",
|
||||
@@ -189,7 +189,7 @@
|
||||
"@testing-library/react": "^11.2.6",
|
||||
"@testing-library/react-hooks": "^5.1.2",
|
||||
"@testing-library/user-event": "^14.0.0-beta.7",
|
||||
"@types/analytics-node": "^3.1.4",
|
||||
"@types/analytics-node": "^3.1.7",
|
||||
"@types/aws4": "^1.5.1",
|
||||
"@types/clone": "^2.1.0",
|
||||
"@types/codemirror": "^5.60.2",
|
||||
|
||||
+16
-13
@@ -361,24 +361,27 @@
|
||||
}
|
||||
},
|
||||
"analytics-node": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/analytics-node/-/analytics-node-4.0.1.tgz",
|
||||
"integrity": "sha512-+zXOOTB+eTRW6R9+pfvPfk1dHraFJzhNnAyZiYJIDGOjHQgfk9qfqgoJX9MfR4qY0J/E1YJ3FBncrLGadTDW1A==",
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/analytics-node/-/analytics-node-6.0.0.tgz",
|
||||
"integrity": "sha512-qhwB5Fl/ps7VTg1/RnD3qJohceSHUjzTBqNn3DCmQZu/AdgPbGPeNFYu2o3xIuIyq+xZElrv0Do0b/zuGxBL9g==",
|
||||
"requires": {
|
||||
"@segment/loosely-validate-event": "^2.0.0",
|
||||
"axios": "^0.21.1",
|
||||
"axios-retry": "^3.0.2",
|
||||
"axios": "^0.21.4",
|
||||
"axios-retry": "3.2.0",
|
||||
"lodash.isstring": "^4.0.1",
|
||||
"md5": "^2.2.1",
|
||||
"ms": "^2.0.0",
|
||||
"remove-trailing-slash": "^0.1.0",
|
||||
"uuid": "^3.2.1"
|
||||
"uuid": "^8.3.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"uuid": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
||||
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
|
||||
"axios": {
|
||||
"version": "0.21.4",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz",
|
||||
"integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==",
|
||||
"requires": {
|
||||
"follow-redirects": "^1.14.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -511,9 +514,9 @@
|
||||
}
|
||||
},
|
||||
"axios-retry": {
|
||||
"version": "3.1.9",
|
||||
"resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-3.1.9.tgz",
|
||||
"integrity": "sha512-NFCoNIHq8lYkJa6ku4m+V1837TP6lCa7n79Iuf8/AqATAHYB0ISaAS1eyIenDOfHOLtym34W65Sjke2xjg2fsA==",
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-3.2.0.tgz",
|
||||
"integrity": "sha512-RK2cLMgIsAQBDhlIsJR5dOhODPigvel18XUv1dDXW+4k1FzebyfRk+C+orot6WPZOYFKSfhLwHPwVmTVOODQ5w==",
|
||||
"requires": {
|
||||
"is-retry-allowed": "^1.1.0"
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"dependencies": {
|
||||
"@hapi/hawk": "^8.0.0",
|
||||
"@stoplight/spectral": "^5.9.0",
|
||||
"analytics-node": "^4.0.1",
|
||||
"analytics-node": "^6.0.0",
|
||||
"aws4": "^1.10.0",
|
||||
"axios": "^0.21.2",
|
||||
"clone": "^2.1.2",
|
||||
|
||||
Reference in new issue
Block a user