posthog-js 1.76.0 → 1.77.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/array.full.js +2 -2
- package/dist/array.full.js.map +1 -1
- package/dist/array.js +2 -2
- package/dist/array.js.map +1 -1
- package/dist/es.js +2 -2
- package/dist/es.js.map +1 -1
- package/dist/module.d.ts +38 -6
- package/dist/module.js +2 -2
- package/dist/module.js.map +1 -1
- package/lib/package.json +8 -6
- package/lib/src/autocapture-utils.d.ts +15 -0
- package/lib/src/autocapture-utils.js +303 -0
- package/lib/src/autocapture-utils.js.map +1 -0
- package/lib/src/autocapture.d.ts +27 -0
- package/lib/src/autocapture.js +290 -0
- package/lib/src/autocapture.js.map +1 -0
- package/lib/src/base-request-queue.d.ts +12 -0
- package/lib/src/base-request-queue.js +33 -0
- package/lib/src/base-request-queue.js.map +1 -0
- package/lib/src/compression.d.ts +3 -0
- package/lib/src/compression.js +35 -0
- package/lib/src/compression.js.map +1 -0
- package/lib/src/config.d.ts +5 -0
- package/lib/src/config.js +9 -0
- package/lib/src/config.js.map +1 -0
- package/lib/src/constants.d.ts +19 -0
- package/lib/src/constants.js +41 -0
- package/lib/src/constants.js.map +1 -0
- package/lib/src/decide.d.ts +8 -0
- package/lib/src/decide.js +118 -0
- package/lib/src/decide.js.map +1 -0
- package/lib/src/extensions/cloud.d.ts +1 -0
- package/lib/src/extensions/cloud.js +2 -0
- package/lib/src/extensions/cloud.js.map +1 -0
- package/lib/src/extensions/exceptions/error-conversion.d.ts +26 -0
- package/lib/src/extensions/exceptions/error-conversion.js +204 -0
- package/lib/src/extensions/exceptions/error-conversion.js.map +1 -0
- package/lib/src/extensions/exceptions/exception-autocapture.d.ts +24 -0
- package/lib/src/extensions/exceptions/exception-autocapture.js +164 -0
- package/lib/src/extensions/exceptions/exception-autocapture.js.map +1 -0
- package/lib/src/extensions/exceptions/stack-trace.d.ts +31 -0
- package/lib/src/extensions/exceptions/stack-trace.js +259 -0
- package/lib/src/extensions/exceptions/stack-trace.js.map +1 -0
- package/lib/src/extensions/exceptions/type-checking.d.ts +10 -0
- package/lib/src/extensions/exceptions/type-checking.js +43 -0
- package/lib/src/extensions/exceptions/type-checking.js.map +1 -0
- package/lib/src/extensions/rageclick.d.ts +10 -0
- package/lib/src/extensions/rageclick.js +33 -0
- package/lib/src/extensions/rageclick.js.map +1 -0
- package/lib/src/extensions/segment-integration.d.ts +44 -0
- package/lib/src/extensions/segment-integration.js +34 -0
- package/lib/src/extensions/segment-integration.js.map +1 -0
- package/lib/src/extensions/sentry-integration.d.ts +30 -0
- package/lib/src/extensions/sentry-integration.js +63 -0
- package/lib/src/extensions/sentry-integration.js.map +1 -0
- package/lib/src/extensions/sessionrecording-utils.d.ts +67 -0
- package/lib/src/extensions/sessionrecording-utils.js +192 -0
- package/lib/src/extensions/sessionrecording-utils.js.map +1 -0
- package/lib/src/extensions/sessionrecording.d.ts +45 -0
- package/lib/src/extensions/sessionrecording.js +430 -0
- package/lib/src/extensions/sessionrecording.js.map +1 -0
- package/lib/src/extensions/toolbar.d.ts +18 -0
- package/lib/src/extensions/toolbar.js +151 -0
- package/lib/src/extensions/toolbar.js.map +1 -0
- package/lib/src/extensions/web-performance.d.ts +20 -0
- package/lib/src/extensions/web-performance.js +245 -0
- package/lib/src/extensions/web-performance.js.map +1 -0
- package/lib/src/gdpr-utils.d.ts +80 -0
- package/lib/src/gdpr-utils.js +236 -0
- package/lib/src/gdpr-utils.js.map +1 -0
- package/lib/src/loader-globals-full.d.ts +1 -0
- package/lib/src/loader-globals-full.js +5 -0
- package/lib/src/loader-globals-full.js.map +1 -0
- package/lib/src/loader-globals.d.ts +1 -0
- package/lib/src/loader-globals.js +3 -0
- package/lib/src/loader-globals.js.map +1 -0
- package/lib/src/loader-module.d.ts +4 -0
- package/lib/src/loader-module.js +6 -0
- package/lib/src/loader-module.js.map +1 -0
- package/lib/src/loader-recorder-v2.d.ts +2 -0
- package/lib/src/loader-recorder-v2.js +15 -0
- package/lib/src/loader-recorder-v2.js.map +1 -0
- package/lib/src/loader-recorder.d.ts +2 -0
- package/lib/src/loader-recorder.js +15 -0
- package/lib/src/loader-recorder.js.map +1 -0
- package/lib/src/page-view.d.ts +38 -0
- package/lib/src/page-view.js +127 -0
- package/lib/src/page-view.js.map +1 -0
- package/lib/src/posthog-core.d.ts +701 -0
- package/lib/src/posthog-core.js +1916 -0
- package/lib/src/posthog-core.js.map +1 -0
- package/lib/src/posthog-featureflags.d.ts +70 -0
- package/lib/src/posthog-featureflags.js +438 -0
- package/lib/src/posthog-featureflags.js.map +1 -0
- package/lib/src/posthog-persistence.d.ts +57 -0
- package/lib/src/posthog-persistence.js +256 -0
- package/lib/src/posthog-persistence.js.map +1 -0
- package/lib/src/posthog-surveys.d.ts +57 -0
- package/lib/src/posthog-surveys.js +76 -0
- package/lib/src/posthog-surveys.js.map +1 -0
- package/lib/src/rate-limiter.d.ts +5 -0
- package/lib/src/rate-limiter.js +66 -0
- package/lib/src/rate-limiter.js.map +1 -0
- package/lib/src/request-queue.d.ts +10 -0
- package/lib/src/request-queue.js +146 -0
- package/lib/src/request-queue.js.map +1 -0
- package/lib/src/retry-queue.d.ts +28 -0
- package/lib/src/retry-queue.js +198 -0
- package/lib/src/retry-queue.js.map +1 -0
- package/lib/src/send-request.d.ts +6 -0
- package/lib/src/send-request.js +125 -0
- package/lib/src/send-request.js.map +1 -0
- package/lib/src/sessionid.d.ts +28 -0
- package/lib/src/sessionid.js +205 -0
- package/lib/src/sessionid.js.map +1 -0
- package/lib/src/storage.d.ts +7 -0
- package/lib/src/storage.js +291 -0
- package/lib/src/storage.js.map +1 -0
- package/lib/src/types.d.ts +294 -0
- package/lib/src/types.js +6 -0
- package/lib/src/types.js.map +1 -0
- package/lib/src/utils.d.ts +89 -0
- package/lib/src/utils.js +868 -0
- package/lib/src/utils.js.map +1 -0
- package/lib/src/uuidv7.d.ts +42 -0
- package/lib/src/uuidv7.js +228 -0
- package/lib/src/uuidv7.js.map +1 -0
- package/package.json +8 -6
- package/CHANGELOG.md +0 -1145
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
var __extends = (this && this.__extends) || (function () {
|
|
2
|
+
var extendStatics = function (d, b) {
|
|
3
|
+
extendStatics = Object.setPrototypeOf ||
|
|
4
|
+
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
5
|
+
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
|
6
|
+
return extendStatics(d, b);
|
|
7
|
+
};
|
|
8
|
+
return function (d, b) {
|
|
9
|
+
if (typeof b !== "function" && b !== null)
|
|
10
|
+
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
|
11
|
+
extendStatics(d, b);
|
|
12
|
+
function __() { this.constructor = d; }
|
|
13
|
+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
14
|
+
};
|
|
15
|
+
})();
|
|
16
|
+
var __assign = (this && this.__assign) || function () {
|
|
17
|
+
__assign = Object.assign || function(t) {
|
|
18
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
19
|
+
s = arguments[i];
|
|
20
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
21
|
+
t[p] = s[p];
|
|
22
|
+
}
|
|
23
|
+
return t;
|
|
24
|
+
};
|
|
25
|
+
return __assign.apply(this, arguments);
|
|
26
|
+
};
|
|
27
|
+
var __read = (this && this.__read) || function (o, n) {
|
|
28
|
+
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
29
|
+
if (!m) return o;
|
|
30
|
+
var i = m.call(o), r, ar = [], e;
|
|
31
|
+
try {
|
|
32
|
+
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
|
33
|
+
}
|
|
34
|
+
catch (error) { e = { error: error }; }
|
|
35
|
+
finally {
|
|
36
|
+
try {
|
|
37
|
+
if (r && !r.done && (m = i["return"])) m.call(i);
|
|
38
|
+
}
|
|
39
|
+
finally { if (e) throw e.error; }
|
|
40
|
+
}
|
|
41
|
+
return ar;
|
|
42
|
+
};
|
|
43
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
44
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
45
|
+
if (ar || !(i in from)) {
|
|
46
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
47
|
+
ar[i] = from[i];
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
51
|
+
};
|
|
52
|
+
import { RequestQueueScaffold } from './base-request-queue';
|
|
53
|
+
import { _each } from './utils';
|
|
54
|
+
var RequestQueue = /** @class */ (function (_super) {
|
|
55
|
+
__extends(RequestQueue, _super);
|
|
56
|
+
function RequestQueue(handlePollRequest, pollInterval) {
|
|
57
|
+
if (pollInterval === void 0) { pollInterval = 3000; }
|
|
58
|
+
var _this = _super.call(this, pollInterval) || this;
|
|
59
|
+
_this.handlePollRequest = handlePollRequest;
|
|
60
|
+
return _this;
|
|
61
|
+
}
|
|
62
|
+
RequestQueue.prototype.enqueue = function (url, data, options) {
|
|
63
|
+
this._event_queue.push({ url: url, data: data, options: options });
|
|
64
|
+
if (!this.isPolling) {
|
|
65
|
+
this.isPolling = true;
|
|
66
|
+
this.poll();
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
RequestQueue.prototype.poll = function () {
|
|
70
|
+
var _this = this;
|
|
71
|
+
clearTimeout(this._poller);
|
|
72
|
+
this._poller = setTimeout(function () {
|
|
73
|
+
if (_this._event_queue.length > 0) {
|
|
74
|
+
var requests = _this.formatQueue();
|
|
75
|
+
var _loop_1 = function (key) {
|
|
76
|
+
var _a = requests[key], url = _a.url, data = _a.data, options = _a.options;
|
|
77
|
+
_each(data, function (_, dataKey) {
|
|
78
|
+
data[dataKey]['offset'] = Math.abs(data[dataKey]['timestamp'] - _this.getTime());
|
|
79
|
+
delete data[dataKey]['timestamp'];
|
|
80
|
+
});
|
|
81
|
+
_this.handlePollRequest(url, data, options);
|
|
82
|
+
};
|
|
83
|
+
for (var key in requests) {
|
|
84
|
+
_loop_1(key);
|
|
85
|
+
}
|
|
86
|
+
_this._event_queue.length = 0; // flush the _event_queue
|
|
87
|
+
_this._empty_queue_count = 0;
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
_this._empty_queue_count++;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* _empty_queue_count will increment each time the queue is polled
|
|
94
|
+
* and it is empty. To avoid empty polling (user went idle, stepped away from comp)
|
|
95
|
+
* we can turn it off with the isPolling flag.
|
|
96
|
+
*
|
|
97
|
+
* Polling will be re enabled when the next time PostHogLib.capture is called with
|
|
98
|
+
* an event that should be added to the event queue.
|
|
99
|
+
*/
|
|
100
|
+
if (_this._empty_queue_count > 4) {
|
|
101
|
+
_this.isPolling = false;
|
|
102
|
+
_this._empty_queue_count = 0;
|
|
103
|
+
}
|
|
104
|
+
if (_this.isPolling) {
|
|
105
|
+
_this.poll();
|
|
106
|
+
}
|
|
107
|
+
}, this._pollInterval);
|
|
108
|
+
};
|
|
109
|
+
RequestQueue.prototype.unload = function () {
|
|
110
|
+
var _this = this;
|
|
111
|
+
clearTimeout(this._poller);
|
|
112
|
+
var requests = this._event_queue.length > 0 ? this.formatQueue() : {};
|
|
113
|
+
this._event_queue.length = 0;
|
|
114
|
+
var requestValues = Object.values(requests);
|
|
115
|
+
// Always force events to be sent before recordings, as events are more important, and recordings are bigger and thus less likely to arrive
|
|
116
|
+
var sortedRequests = __spreadArray(__spreadArray([], __read(requestValues.filter(function (r) { return r.url.indexOf('/e') === 0; })), false), __read(requestValues.filter(function (r) { return r.url.indexOf('/e') !== 0; })), false);
|
|
117
|
+
sortedRequests.map(function (_a) {
|
|
118
|
+
var url = _a.url, data = _a.data, options = _a.options;
|
|
119
|
+
_this.handlePollRequest(url, data, __assign(__assign({}, options), { transport: 'sendBeacon' }));
|
|
120
|
+
});
|
|
121
|
+
};
|
|
122
|
+
RequestQueue.prototype.formatQueue = function () {
|
|
123
|
+
var requests = {};
|
|
124
|
+
_each(this._event_queue, function (request) {
|
|
125
|
+
var url = request.url, data = request.data, options = request.options;
|
|
126
|
+
var key = (options ? options._batchKey : null) || url;
|
|
127
|
+
if (requests[key] === undefined) {
|
|
128
|
+
requests[key] = { data: [], url: url, options: options };
|
|
129
|
+
}
|
|
130
|
+
// :TRICKY: Metrics-only code
|
|
131
|
+
if (options &&
|
|
132
|
+
requests[key].options &&
|
|
133
|
+
requests[key].options._metrics &&
|
|
134
|
+
!requests[key].options._metrics['rrweb_full_snapshot']) {
|
|
135
|
+
;
|
|
136
|
+
requests[key].options._metrics['rrweb_full_snapshot'] =
|
|
137
|
+
options._metrics['rrweb_full_snapshot'];
|
|
138
|
+
}
|
|
139
|
+
requests[key].data.push(data);
|
|
140
|
+
});
|
|
141
|
+
return requests;
|
|
142
|
+
};
|
|
143
|
+
return RequestQueue;
|
|
144
|
+
}(RequestQueueScaffold));
|
|
145
|
+
export { RequestQueue };
|
|
146
|
+
//# sourceMappingURL=request-queue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-queue.js","sourceRoot":"","sources":["../../src/request-queue.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AAC3D,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAG/B;IAAkC,gCAAoB;IAGlD,sBAAY,iBAAgF,EAAE,YAAmB;QAAnB,6BAAA,EAAA,mBAAmB;QAAjH,YACI,kBAAM,YAAY,CAAC,SAEtB;QADG,KAAI,CAAC,iBAAiB,GAAG,iBAAiB,CAAA;;IAC9C,CAAC;IAED,8BAAO,GAAP,UAAQ,GAAW,EAAE,IAAgB,EAAE,OAAmB;QACtD,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,GAAG,KAAA,EAAE,IAAI,MAAA,EAAE,OAAO,SAAA,EAAE,CAAC,CAAA;QAE9C,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE;YACjB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAA;YACrB,IAAI,CAAC,IAAI,EAAE,CAAA;SACd;IACL,CAAC;IAED,2BAAI,GAAJ;QAAA,iBAmCC;QAlCG,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QAC1B,IAAI,CAAC,OAAO,GAAG,UAAU,CAAC;YACtB,IAAI,KAAI,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE;gBAC9B,IAAM,QAAQ,GAAG,KAAI,CAAC,WAAW,EAAE,CAAA;wCACxB,GAAG;oBACJ,IAAA,KAAyB,QAAQ,CAAC,GAAG,CAAC,EAApC,GAAG,SAAA,EAAE,IAAI,UAAA,EAAE,OAAO,aAAkB,CAAA;oBAC5C,KAAK,CAAC,IAAI,EAAE,UAAC,CAAC,EAAE,OAAO;wBACnB,IAAI,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,GAAG,KAAI,CAAC,OAAO,EAAE,CAAC,CAAA;wBAC/E,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,CAAA;oBACrC,CAAC,CAAC,CAAA;oBACF,KAAI,CAAC,iBAAiB,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,CAAC,CAAA;;gBAN9C,KAAK,IAAM,GAAG,IAAI,QAAQ;4BAAf,GAAG;iBAOb;gBACD,KAAI,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAA,CAAC,yBAAyB;gBACtD,KAAI,CAAC,kBAAkB,GAAG,CAAC,CAAA;aAC9B;iBAAM;gBACH,KAAI,CAAC,kBAAkB,EAAE,CAAA;aAC5B;YAED;;;;;;;eAOG;YACH,IAAI,KAAI,CAAC,kBAAkB,GAAG,CAAC,EAAE;gBAC7B,KAAI,CAAC,SAAS,GAAG,KAAK,CAAA;gBACtB,KAAI,CAAC,kBAAkB,GAAG,CAAC,CAAA;aAC9B;YACD,IAAI,KAAI,CAAC,SAAS,EAAE;gBAChB,KAAI,CAAC,IAAI,EAAE,CAAA;aACd;QACL,CAAC,EAAE,IAAI,CAAC,aAAa,CAAkB,CAAA;IAC3C,CAAC;IAED,6BAAM,GAAN;QAAA,iBAcC;QAbG,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QAC1B,IAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;QACvE,IAAI,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAA;QAC5B,IAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;QAE7C,2IAA2I;QAC3I,IAAM,cAAc,0CACb,aAAa,CAAC,MAAM,CAAC,UAAC,CAAC,IAAK,OAAA,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAzB,CAAyB,CAAC,kBACtD,aAAa,CAAC,MAAM,CAAC,UAAC,CAAC,IAAK,OAAA,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAzB,CAAyB,CAAC,SAC5D,CAAA;QACD,cAAc,CAAC,GAAG,CAAC,UAAC,EAAsB;gBAApB,GAAG,SAAA,EAAE,IAAI,UAAA,EAAE,OAAO,aAAA;YACpC,KAAI,CAAC,iBAAiB,CAAC,GAAG,EAAE,IAAI,wBAAO,OAAO,KAAE,SAAS,EAAE,YAAY,IAAG,CAAA;QAC9E,CAAC,CAAC,CAAA;IACN,CAAC;IAED,kCAAW,GAAX;QACI,IAAM,QAAQ,GAAsC,EAAE,CAAA;QACtD,KAAK,CAAC,IAAI,CAAC,YAAY,EAAE,UAAC,OAAO;YACrB,IAAA,GAAG,GAAoB,OAAO,IAA3B,EAAE,IAAI,GAAc,OAAO,KAArB,EAAE,OAAO,GAAK,OAAO,QAAZ,CAAY;YACtC,IAAM,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,GAAG,CAAA;YACvD,IAAI,QAAQ,CAAC,GAAG,CAAC,KAAK,SAAS,EAAE;gBAC7B,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,KAAA,EAAE,OAAO,SAAA,EAAE,CAAA;aAC7C;YAED,6BAA6B;YAC7B,IACI,OAAO;gBACP,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO;gBACrB,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,QAAQ;gBAC9B,CAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,QAAgB,CAAC,qBAAqB,CAAC,EACjE;gBACE,CAAC;gBAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,QAAgB,CAAC,qBAAqB,CAAC;oBAC3D,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAC,CAAA;aAC9C;YACD,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACjC,CAAC,CAAC,CAAA;QACF,OAAO,QAAQ,CAAA;IACnB,CAAC;IACL,mBAAC;AAAD,CAAC,AA7FD,CAAkC,oBAAoB,GA6FrD","sourcesContent":["import { RequestQueueScaffold } from './base-request-queue'\nimport { _each } from './utils'\nimport { Properties, QueuedRequestData, XHROptions } from './types'\n\nexport class RequestQueue extends RequestQueueScaffold {\n handlePollRequest: (url: string, data: Properties, options?: XHROptions) => void\n\n constructor(handlePollRequest: (url: string, data: Properties, options?: XHROptions) => void, pollInterval = 3000) {\n super(pollInterval)\n this.handlePollRequest = handlePollRequest\n }\n\n enqueue(url: string, data: Properties, options: XHROptions): void {\n this._event_queue.push({ url, data, options })\n\n if (!this.isPolling) {\n this.isPolling = true\n this.poll()\n }\n }\n\n poll(): void {\n clearTimeout(this._poller)\n this._poller = setTimeout(() => {\n if (this._event_queue.length > 0) {\n const requests = this.formatQueue()\n for (const key in requests) {\n const { url, data, options } = requests[key]\n _each(data, (_, dataKey) => {\n data[dataKey]['offset'] = Math.abs(data[dataKey]['timestamp'] - this.getTime())\n delete data[dataKey]['timestamp']\n })\n this.handlePollRequest(url, data, options)\n }\n this._event_queue.length = 0 // flush the _event_queue\n this._empty_queue_count = 0\n } else {\n this._empty_queue_count++\n }\n\n /**\n * _empty_queue_count will increment each time the queue is polled\n * and it is empty. To avoid empty polling (user went idle, stepped away from comp)\n * we can turn it off with the isPolling flag.\n *\n * Polling will be re enabled when the next time PostHogLib.capture is called with\n * an event that should be added to the event queue.\n */\n if (this._empty_queue_count > 4) {\n this.isPolling = false\n this._empty_queue_count = 0\n }\n if (this.isPolling) {\n this.poll()\n }\n }, this._pollInterval) as any as number\n }\n\n unload(): void {\n clearTimeout(this._poller)\n const requests = this._event_queue.length > 0 ? this.formatQueue() : {}\n this._event_queue.length = 0\n const requestValues = Object.values(requests)\n\n // Always force events to be sent before recordings, as events are more important, and recordings are bigger and thus less likely to arrive\n const sortedRequests = [\n ...requestValues.filter((r) => r.url.indexOf('/e') === 0),\n ...requestValues.filter((r) => r.url.indexOf('/e') !== 0),\n ]\n sortedRequests.map(({ url, data, options }) => {\n this.handlePollRequest(url, data, { ...options, transport: 'sendBeacon' })\n })\n }\n\n formatQueue(): Record<string, QueuedRequestData> {\n const requests: Record<string, QueuedRequestData> = {}\n _each(this._event_queue, (request) => {\n const { url, data, options } = request\n const key = (options ? options._batchKey : null) || url\n if (requests[key] === undefined) {\n requests[key] = { data: [], url, options }\n }\n\n // :TRICKY: Metrics-only code\n if (\n options &&\n requests[key].options &&\n requests[key].options._metrics &&\n !(requests[key].options._metrics as any)['rrweb_full_snapshot']\n ) {\n ;(requests[key].options._metrics as any)['rrweb_full_snapshot'] =\n options._metrics['rrweb_full_snapshot']\n }\n requests[key].data.push(data)\n })\n return requests\n }\n}\n"]}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { RequestQueueScaffold } from './base-request-queue';
|
|
2
|
+
import { QueuedRequestData, RetryQueueElement } from './types';
|
|
3
|
+
import { RateLimiter } from './rate-limiter';
|
|
4
|
+
/**
|
|
5
|
+
* Generates a jitter-ed exponential backoff delay in milliseconds
|
|
6
|
+
*
|
|
7
|
+
* The base value is 6 seconds, which is doubled with each retry
|
|
8
|
+
* up to the maximum of 30 minutes
|
|
9
|
+
*
|
|
10
|
+
* Each value then has +/- 50% jitter
|
|
11
|
+
*
|
|
12
|
+
* Giving a range of 6 seconds up to 45 minutes
|
|
13
|
+
*/
|
|
14
|
+
export declare function pickNextRetryDelay(retriesPerformedSoFar: number): number;
|
|
15
|
+
export declare class RetryQueue extends RequestQueueScaffold {
|
|
16
|
+
queue: RetryQueueElement[];
|
|
17
|
+
isPolling: boolean;
|
|
18
|
+
areWeOnline: boolean;
|
|
19
|
+
onXHRError: (failedRequest: XMLHttpRequest) => void;
|
|
20
|
+
rateLimiter: RateLimiter;
|
|
21
|
+
constructor(onXHRError: (failedRequest: XMLHttpRequest) => void, rateLimiter: RateLimiter);
|
|
22
|
+
enqueue(requestData: QueuedRequestData): void;
|
|
23
|
+
poll(): void;
|
|
24
|
+
flush(): void;
|
|
25
|
+
unload(): void;
|
|
26
|
+
_executeXhrRequest({ url, data, options, headers, callback, retriesPerformedSoFar }: QueuedRequestData): void;
|
|
27
|
+
_handleWeAreNowOnline(): void;
|
|
28
|
+
}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
var __extends = (this && this.__extends) || (function () {
|
|
2
|
+
var extendStatics = function (d, b) {
|
|
3
|
+
extendStatics = Object.setPrototypeOf ||
|
|
4
|
+
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
5
|
+
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
|
6
|
+
return extendStatics(d, b);
|
|
7
|
+
};
|
|
8
|
+
return function (d, b) {
|
|
9
|
+
if (typeof b !== "function" && b !== null)
|
|
10
|
+
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
|
11
|
+
extendStatics(d, b);
|
|
12
|
+
function __() { this.constructor = d; }
|
|
13
|
+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
14
|
+
};
|
|
15
|
+
})();
|
|
16
|
+
var __assign = (this && this.__assign) || function () {
|
|
17
|
+
__assign = Object.assign || function(t) {
|
|
18
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
19
|
+
s = arguments[i];
|
|
20
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
21
|
+
t[p] = s[p];
|
|
22
|
+
}
|
|
23
|
+
return t;
|
|
24
|
+
};
|
|
25
|
+
return __assign.apply(this, arguments);
|
|
26
|
+
};
|
|
27
|
+
var __values = (this && this.__values) || function(o) {
|
|
28
|
+
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
|
|
29
|
+
if (m) return m.call(o);
|
|
30
|
+
if (o && typeof o.length === "number") return {
|
|
31
|
+
next: function () {
|
|
32
|
+
if (o && i >= o.length) o = void 0;
|
|
33
|
+
return { value: o && o[i++], done: !o };
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
|
37
|
+
};
|
|
38
|
+
import { RequestQueueScaffold } from './base-request-queue';
|
|
39
|
+
import { encodePostData, xhr } from './send-request';
|
|
40
|
+
import Config from './config';
|
|
41
|
+
var thirtyMinutes = 30 * 60 * 1000;
|
|
42
|
+
/**
|
|
43
|
+
* Generates a jitter-ed exponential backoff delay in milliseconds
|
|
44
|
+
*
|
|
45
|
+
* The base value is 6 seconds, which is doubled with each retry
|
|
46
|
+
* up to the maximum of 30 minutes
|
|
47
|
+
*
|
|
48
|
+
* Each value then has +/- 50% jitter
|
|
49
|
+
*
|
|
50
|
+
* Giving a range of 6 seconds up to 45 minutes
|
|
51
|
+
*/
|
|
52
|
+
export function pickNextRetryDelay(retriesPerformedSoFar) {
|
|
53
|
+
var rawBackoffTime = 3000 * Math.pow(2, retriesPerformedSoFar);
|
|
54
|
+
var minBackoff = rawBackoffTime / 2;
|
|
55
|
+
var cappedBackoffTime = Math.min(thirtyMinutes, rawBackoffTime);
|
|
56
|
+
var jitterFraction = Math.random() - 0.5; // A random number between -0.5 and 0.5
|
|
57
|
+
var jitter = jitterFraction * (cappedBackoffTime - minBackoff);
|
|
58
|
+
return Math.ceil(cappedBackoffTime + jitter);
|
|
59
|
+
}
|
|
60
|
+
var RetryQueue = /** @class */ (function (_super) {
|
|
61
|
+
__extends(RetryQueue, _super);
|
|
62
|
+
function RetryQueue(onXHRError, rateLimiter) {
|
|
63
|
+
var _this = _super.call(this) || this;
|
|
64
|
+
_this.isPolling = false;
|
|
65
|
+
_this.queue = [];
|
|
66
|
+
_this.areWeOnline = true;
|
|
67
|
+
_this.onXHRError = onXHRError;
|
|
68
|
+
_this.rateLimiter = rateLimiter;
|
|
69
|
+
if (typeof window !== 'undefined' && 'onLine' in window.navigator) {
|
|
70
|
+
_this.areWeOnline = window.navigator.onLine;
|
|
71
|
+
window.addEventListener('online', function () {
|
|
72
|
+
_this._handleWeAreNowOnline();
|
|
73
|
+
});
|
|
74
|
+
window.addEventListener('offline', function () {
|
|
75
|
+
_this.areWeOnline = false;
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
return _this;
|
|
79
|
+
}
|
|
80
|
+
RetryQueue.prototype.enqueue = function (requestData) {
|
|
81
|
+
var retriesPerformedSoFar = requestData.retriesPerformedSoFar || 0;
|
|
82
|
+
if (retriesPerformedSoFar >= 10) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
var msToNextRetry = pickNextRetryDelay(retriesPerformedSoFar);
|
|
86
|
+
var retryAt = new Date(Date.now() + msToNextRetry);
|
|
87
|
+
this.queue.push({ retryAt: retryAt, requestData: requestData });
|
|
88
|
+
console.warn("Enqueued failed request for retry in ".concat(msToNextRetry));
|
|
89
|
+
if (!this.isPolling) {
|
|
90
|
+
this.isPolling = true;
|
|
91
|
+
this.poll();
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
RetryQueue.prototype.poll = function () {
|
|
95
|
+
var _this = this;
|
|
96
|
+
this._poller && clearTimeout(this._poller);
|
|
97
|
+
this._poller = setTimeout(function () {
|
|
98
|
+
if (_this.areWeOnline && _this.queue.length > 0) {
|
|
99
|
+
_this.flush();
|
|
100
|
+
}
|
|
101
|
+
_this.poll();
|
|
102
|
+
}, this._pollInterval);
|
|
103
|
+
};
|
|
104
|
+
RetryQueue.prototype.flush = function () {
|
|
105
|
+
var e_1, _a;
|
|
106
|
+
// using Date.now to make tests easier, as recommended here https://codewithhugo.com/mocking-the-current-date-in-jest-tests/
|
|
107
|
+
var now = new Date(Date.now());
|
|
108
|
+
var toFlush = this.queue.filter(function (_a) {
|
|
109
|
+
var retryAt = _a.retryAt;
|
|
110
|
+
return retryAt < now;
|
|
111
|
+
});
|
|
112
|
+
if (toFlush.length > 0) {
|
|
113
|
+
this.queue = this.queue.filter(function (_a) {
|
|
114
|
+
var retryAt = _a.retryAt;
|
|
115
|
+
return retryAt >= now;
|
|
116
|
+
});
|
|
117
|
+
try {
|
|
118
|
+
for (var toFlush_1 = __values(toFlush), toFlush_1_1 = toFlush_1.next(); !toFlush_1_1.done; toFlush_1_1 = toFlush_1.next()) {
|
|
119
|
+
var requestData = toFlush_1_1.value.requestData;
|
|
120
|
+
this._executeXhrRequest(requestData);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
124
|
+
finally {
|
|
125
|
+
try {
|
|
126
|
+
if (toFlush_1_1 && !toFlush_1_1.done && (_a = toFlush_1.return)) _a.call(toFlush_1);
|
|
127
|
+
}
|
|
128
|
+
finally { if (e_1) throw e_1.error; }
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
RetryQueue.prototype.unload = function () {
|
|
133
|
+
var e_2, _a;
|
|
134
|
+
if (this._poller) {
|
|
135
|
+
clearTimeout(this._poller);
|
|
136
|
+
this._poller = undefined;
|
|
137
|
+
}
|
|
138
|
+
try {
|
|
139
|
+
for (var _b = __values(this.queue), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
140
|
+
var requestData = _c.value.requestData;
|
|
141
|
+
var url = requestData.url, data = requestData.data, options = requestData.options;
|
|
142
|
+
if (this.rateLimiter.isRateLimited(options._batchKey)) {
|
|
143
|
+
if (Config.DEBUG) {
|
|
144
|
+
console.warn('[PostHog RetryQueue] is quota limited. Dropping request.');
|
|
145
|
+
}
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
try {
|
|
149
|
+
// we've had send beacon in place for at least 2 years
|
|
150
|
+
// eslint-disable-next-line compat/compat
|
|
151
|
+
window.navigator.sendBeacon(url, encodePostData(data, __assign(__assign({}, options), { sendBeacon: true })));
|
|
152
|
+
}
|
|
153
|
+
catch (e) {
|
|
154
|
+
// Note sendBeacon automatically retries, and after the first retry it will lose reference to contextual `this`.
|
|
155
|
+
// This means in some cases `this.getConfig` will be undefined.
|
|
156
|
+
if (Config.DEBUG) {
|
|
157
|
+
console.error(e);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
163
|
+
finally {
|
|
164
|
+
try {
|
|
165
|
+
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
166
|
+
}
|
|
167
|
+
finally { if (e_2) throw e_2.error; }
|
|
168
|
+
}
|
|
169
|
+
this.queue = [];
|
|
170
|
+
};
|
|
171
|
+
RetryQueue.prototype._executeXhrRequest = function (_a) {
|
|
172
|
+
var url = _a.url, data = _a.data, options = _a.options, headers = _a.headers, callback = _a.callback, retriesPerformedSoFar = _a.retriesPerformedSoFar;
|
|
173
|
+
if (this.rateLimiter.isRateLimited(options._batchKey)) {
|
|
174
|
+
if (Config.DEBUG) {
|
|
175
|
+
console.warn('[PostHog RetryQueue] in quota limited mode. Dropping request.');
|
|
176
|
+
}
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
xhr({
|
|
180
|
+
url: url,
|
|
181
|
+
data: data || {},
|
|
182
|
+
options: options || {},
|
|
183
|
+
headers: headers || {},
|
|
184
|
+
retriesPerformedSoFar: retriesPerformedSoFar || 0,
|
|
185
|
+
callback: callback,
|
|
186
|
+
retryQueue: this,
|
|
187
|
+
onXHRError: this.onXHRError,
|
|
188
|
+
onRateLimited: this.rateLimiter.on429Response,
|
|
189
|
+
});
|
|
190
|
+
};
|
|
191
|
+
RetryQueue.prototype._handleWeAreNowOnline = function () {
|
|
192
|
+
this.areWeOnline = true;
|
|
193
|
+
this.flush();
|
|
194
|
+
};
|
|
195
|
+
return RetryQueue;
|
|
196
|
+
}(RequestQueueScaffold));
|
|
197
|
+
export { RetryQueue };
|
|
198
|
+
//# sourceMappingURL=retry-queue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry-queue.js","sourceRoot":"","sources":["../../src/retry-queue.ts"],"names":[],"mappings":"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","sourcesContent":["import { RequestQueueScaffold } from './base-request-queue'\nimport { encodePostData, xhr } from './send-request'\nimport { QueuedRequestData, RetryQueueElement } from './types'\nimport Config from './config'\nimport { RateLimiter } from './rate-limiter'\n\nconst thirtyMinutes = 30 * 60 * 1000\n\n/**\n * Generates a jitter-ed exponential backoff delay in milliseconds\n *\n * The base value is 6 seconds, which is doubled with each retry\n * up to the maximum of 30 minutes\n *\n * Each value then has +/- 50% jitter\n *\n * Giving a range of 6 seconds up to 45 minutes\n */\nexport function pickNextRetryDelay(retriesPerformedSoFar: number): number {\n const rawBackoffTime = 3000 * 2 ** retriesPerformedSoFar\n const minBackoff = rawBackoffTime / 2\n const cappedBackoffTime = Math.min(thirtyMinutes, rawBackoffTime)\n const jitterFraction = Math.random() - 0.5 // A random number between -0.5 and 0.5\n const jitter = jitterFraction * (cappedBackoffTime - minBackoff)\n return Math.ceil(cappedBackoffTime + jitter)\n}\n\nexport class RetryQueue extends RequestQueueScaffold {\n queue: RetryQueueElement[]\n isPolling: boolean\n areWeOnline: boolean\n onXHRError: (failedRequest: XMLHttpRequest) => void\n rateLimiter: RateLimiter\n\n constructor(onXHRError: (failedRequest: XMLHttpRequest) => void, rateLimiter: RateLimiter) {\n super()\n this.isPolling = false\n this.queue = []\n this.areWeOnline = true\n this.onXHRError = onXHRError\n this.rateLimiter = rateLimiter\n\n if (typeof window !== 'undefined' && 'onLine' in window.navigator) {\n this.areWeOnline = window.navigator.onLine\n window.addEventListener('online', () => {\n this._handleWeAreNowOnline()\n })\n window.addEventListener('offline', () => {\n this.areWeOnline = false\n })\n }\n }\n\n enqueue(requestData: QueuedRequestData): void {\n const retriesPerformedSoFar = requestData.retriesPerformedSoFar || 0\n if (retriesPerformedSoFar >= 10) {\n return\n }\n const msToNextRetry = pickNextRetryDelay(retriesPerformedSoFar)\n const retryAt = new Date(Date.now() + msToNextRetry)\n\n this.queue.push({ retryAt, requestData })\n console.warn(`Enqueued failed request for retry in ${msToNextRetry}`)\n if (!this.isPolling) {\n this.isPolling = true\n this.poll()\n }\n }\n\n poll(): void {\n this._poller && clearTimeout(this._poller)\n this._poller = setTimeout(() => {\n if (this.areWeOnline && this.queue.length > 0) {\n this.flush()\n }\n this.poll()\n }, this._pollInterval) as any as number\n }\n\n flush(): void {\n // using Date.now to make tests easier, as recommended here https://codewithhugo.com/mocking-the-current-date-in-jest-tests/\n const now = new Date(Date.now())\n const toFlush = this.queue.filter(({ retryAt }) => retryAt < now)\n if (toFlush.length > 0) {\n this.queue = this.queue.filter(({ retryAt }) => retryAt >= now)\n for (const { requestData } of toFlush) {\n this._executeXhrRequest(requestData)\n }\n }\n }\n\n unload(): void {\n if (this._poller) {\n clearTimeout(this._poller)\n this._poller = undefined\n }\n\n for (const { requestData } of this.queue) {\n const { url, data, options } = requestData\n\n if (this.rateLimiter.isRateLimited(options._batchKey)) {\n if (Config.DEBUG) {\n console.warn('[PostHog RetryQueue] is quota limited. Dropping request.')\n }\n continue\n }\n\n try {\n // we've had send beacon in place for at least 2 years\n // eslint-disable-next-line compat/compat\n window.navigator.sendBeacon(url, encodePostData(data, { ...options, sendBeacon: true }))\n } catch (e) {\n // Note sendBeacon automatically retries, and after the first retry it will lose reference to contextual `this`.\n // This means in some cases `this.getConfig` will be undefined.\n if (Config.DEBUG) {\n console.error(e)\n }\n }\n }\n this.queue = []\n }\n\n _executeXhrRequest({ url, data, options, headers, callback, retriesPerformedSoFar }: QueuedRequestData): void {\n if (this.rateLimiter.isRateLimited(options._batchKey)) {\n if (Config.DEBUG) {\n console.warn('[PostHog RetryQueue] in quota limited mode. Dropping request.')\n }\n return\n }\n\n xhr({\n url,\n data: data || {},\n options: options || {},\n headers: headers || {},\n retriesPerformedSoFar: retriesPerformedSoFar || 0,\n callback,\n retryQueue: this,\n onXHRError: this.onXHRError,\n onRateLimited: this.rateLimiter.on429Response,\n })\n }\n\n _handleWeAreNowOnline(): void {\n this.areWeOnline = true\n this.flush()\n }\n}\n"]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { PostData, XHROptions, XHRParams } from './types';
|
|
2
|
+
export declare const addParamsToURL: (url: string, urlQueryArgs: Record<string, any> | undefined, parameterOptions: {
|
|
3
|
+
ip?: boolean;
|
|
4
|
+
}) => string;
|
|
5
|
+
export declare const encodePostData: (data: PostData | Uint8Array, options: Partial<XHROptions>) => string | BlobPart | null;
|
|
6
|
+
export declare const xhr: ({ url, data, headers, options, callback, retriesPerformedSoFar, retryQueue, onXHRError, timeout, onRateLimited, }: XHRParams) => void;
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
var __values = (this && this.__values) || function(o) {
|
|
2
|
+
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
|
|
3
|
+
if (m) return m.call(o);
|
|
4
|
+
if (o && typeof o.length === "number") return {
|
|
5
|
+
next: function () {
|
|
6
|
+
if (o && i >= o.length) o = void 0;
|
|
7
|
+
return { value: o && o[i++], done: !o };
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
|
11
|
+
};
|
|
12
|
+
import { _each, _HTTPBuildQuery, logger } from './utils';
|
|
13
|
+
import Config from './config';
|
|
14
|
+
export var addParamsToURL = function (url, urlQueryArgs, parameterOptions) {
|
|
15
|
+
var e_1, _a;
|
|
16
|
+
var args = urlQueryArgs || {};
|
|
17
|
+
args['ip'] = parameterOptions['ip'] ? 1 : 0;
|
|
18
|
+
args['_'] = new Date().getTime().toString();
|
|
19
|
+
args['ver'] = Config.LIB_VERSION;
|
|
20
|
+
var halves = url.split('?');
|
|
21
|
+
if (halves.length > 1) {
|
|
22
|
+
var params = halves[1].split('&');
|
|
23
|
+
try {
|
|
24
|
+
for (var params_1 = __values(params), params_1_1 = params_1.next(); !params_1_1.done; params_1_1 = params_1.next()) {
|
|
25
|
+
var p = params_1_1.value;
|
|
26
|
+
var key = p.split('=')[0];
|
|
27
|
+
if (args[key]) {
|
|
28
|
+
delete args[key];
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
33
|
+
finally {
|
|
34
|
+
try {
|
|
35
|
+
if (params_1_1 && !params_1_1.done && (_a = params_1.return)) _a.call(params_1);
|
|
36
|
+
}
|
|
37
|
+
finally { if (e_1) throw e_1.error; }
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
var argSeparator = url.indexOf('?') > -1 ? '&' : '?';
|
|
41
|
+
return url + argSeparator + _HTTPBuildQuery(args);
|
|
42
|
+
};
|
|
43
|
+
export var encodePostData = function (data, options) {
|
|
44
|
+
if (options.blob && data.buffer) {
|
|
45
|
+
return new Blob([data.buffer], { type: 'text/plain' });
|
|
46
|
+
}
|
|
47
|
+
if (options.sendBeacon || options.blob) {
|
|
48
|
+
var body = encodePostData(data, { method: 'POST' });
|
|
49
|
+
return new Blob([body], { type: 'application/x-www-form-urlencoded' });
|
|
50
|
+
}
|
|
51
|
+
if (options.method !== 'POST') {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
var body_data;
|
|
55
|
+
var isUint8Array = function (d) { return Object.prototype.toString.call(d) === '[object Uint8Array]'; };
|
|
56
|
+
if (Array.isArray(data) || isUint8Array(data)) {
|
|
57
|
+
// TODO: eh? passing an Array here?
|
|
58
|
+
body_data = 'data=' + encodeURIComponent(data);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
body_data = 'data=' + encodeURIComponent(data.data);
|
|
62
|
+
}
|
|
63
|
+
if ('compression' in data && data.compression) {
|
|
64
|
+
body_data += '&compression=' + data.compression;
|
|
65
|
+
}
|
|
66
|
+
return body_data;
|
|
67
|
+
};
|
|
68
|
+
export var xhr = function (_a) {
|
|
69
|
+
var url = _a.url, data = _a.data, headers = _a.headers, options = _a.options, callback = _a.callback, retriesPerformedSoFar = _a.retriesPerformedSoFar, retryQueue = _a.retryQueue, onXHRError = _a.onXHRError, _b = _a.timeout, timeout = _b === void 0 ? 10000 : _b, onRateLimited = _a.onRateLimited;
|
|
70
|
+
var req = new XMLHttpRequest();
|
|
71
|
+
req.open(options.method || 'GET', url, true);
|
|
72
|
+
var body = encodePostData(data, options);
|
|
73
|
+
_each(headers, function (headerValue, headerName) {
|
|
74
|
+
req.setRequestHeader(headerName, headerValue);
|
|
75
|
+
});
|
|
76
|
+
if (options.method === 'POST' && !options.blob) {
|
|
77
|
+
req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
|
|
78
|
+
}
|
|
79
|
+
req.timeout = timeout;
|
|
80
|
+
// send the ph_optout cookie
|
|
81
|
+
// withCredentials cannot be modified until after calling .open on Android and Mobile Safari
|
|
82
|
+
req.withCredentials = true;
|
|
83
|
+
req.onreadystatechange = function () {
|
|
84
|
+
if (req.readyState === 4) {
|
|
85
|
+
// XMLHttpRequest.DONE == 4, except in safari 4
|
|
86
|
+
if (req.status === 200) {
|
|
87
|
+
if (callback) {
|
|
88
|
+
var response = void 0;
|
|
89
|
+
try {
|
|
90
|
+
response = JSON.parse(req.responseText);
|
|
91
|
+
}
|
|
92
|
+
catch (e) {
|
|
93
|
+
logger.error(e);
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
callback(response);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
if (typeof onXHRError === 'function') {
|
|
101
|
+
onXHRError(req);
|
|
102
|
+
}
|
|
103
|
+
// don't retry certain errors
|
|
104
|
+
if ([401, 403, 404, 500].indexOf(req.status) < 0) {
|
|
105
|
+
retryQueue.enqueue({
|
|
106
|
+
url: url,
|
|
107
|
+
data: data,
|
|
108
|
+
options: options,
|
|
109
|
+
headers: headers,
|
|
110
|
+
retriesPerformedSoFar: (retriesPerformedSoFar || 0) + 1,
|
|
111
|
+
callback: callback,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
if (req.status === 429) {
|
|
115
|
+
onRateLimited === null || onRateLimited === void 0 ? void 0 : onRateLimited(req);
|
|
116
|
+
}
|
|
117
|
+
if (callback) {
|
|
118
|
+
callback({ status: 0 });
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
req.send(body);
|
|
124
|
+
};
|
|
125
|
+
//# sourceMappingURL=send-request.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"send-request.js","sourceRoot":"","sources":["../../src/send-request.ts"],"names":[],"mappings":"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","sourcesContent":["import { _each, _HTTPBuildQuery, logger } from './utils'\nimport Config from './config'\nimport { PostData, XHROptions, XHRParams } from './types'\n\nexport const addParamsToURL = (\n url: string,\n urlQueryArgs: Record<string, any> | undefined,\n parameterOptions: { ip?: boolean }\n): string => {\n const args = urlQueryArgs || {}\n args['ip'] = parameterOptions['ip'] ? 1 : 0\n args['_'] = new Date().getTime().toString()\n args['ver'] = Config.LIB_VERSION\n\n const halves = url.split('?')\n if (halves.length > 1) {\n const params = halves[1].split('&')\n for (const p of params) {\n const key = p.split('=')[0]\n if (args[key]) {\n delete args[key]\n }\n }\n }\n\n const argSeparator = url.indexOf('?') > -1 ? '&' : '?'\n return url + argSeparator + _HTTPBuildQuery(args)\n}\n\nexport const encodePostData = (data: PostData | Uint8Array, options: Partial<XHROptions>): string | BlobPart | null => {\n if (options.blob && data.buffer) {\n return new Blob([data.buffer], { type: 'text/plain' })\n }\n\n if (options.sendBeacon || options.blob) {\n const body = encodePostData(data, { method: 'POST' }) as BlobPart\n return new Blob([body], { type: 'application/x-www-form-urlencoded' })\n }\n\n if (options.method !== 'POST') {\n return null\n }\n\n let body_data\n const isUint8Array = (d: unknown): d is Uint8Array => Object.prototype.toString.call(d) === '[object Uint8Array]'\n if (Array.isArray(data) || isUint8Array(data)) {\n // TODO: eh? passing an Array here?\n body_data = 'data=' + encodeURIComponent(data as any)\n } else {\n body_data = 'data=' + encodeURIComponent(data.data as string)\n }\n\n if ('compression' in data && data.compression) {\n body_data += '&compression=' + data.compression\n }\n\n return body_data\n}\n\nexport const xhr = ({\n url,\n data,\n headers,\n options,\n callback,\n retriesPerformedSoFar,\n retryQueue,\n onXHRError,\n timeout = 10000,\n onRateLimited,\n}: XHRParams) => {\n const req = new XMLHttpRequest()\n req.open(options.method || 'GET', url, true)\n\n const body = encodePostData(data, options)\n\n _each(headers, function (headerValue, headerName) {\n req.setRequestHeader(headerName, headerValue)\n })\n\n if (options.method === 'POST' && !options.blob) {\n req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')\n }\n\n req.timeout = timeout\n // send the ph_optout cookie\n // withCredentials cannot be modified until after calling .open on Android and Mobile Safari\n req.withCredentials = true\n req.onreadystatechange = () => {\n if (req.readyState === 4) {\n // XMLHttpRequest.DONE == 4, except in safari 4\n if (req.status === 200) {\n if (callback) {\n let response\n try {\n response = JSON.parse(req.responseText)\n } catch (e) {\n logger.error(e)\n return\n }\n callback(response)\n }\n } else {\n if (typeof onXHRError === 'function') {\n onXHRError(req)\n }\n\n // don't retry certain errors\n if ([401, 403, 404, 500].indexOf(req.status) < 0) {\n retryQueue.enqueue({\n url,\n data,\n options,\n headers,\n retriesPerformedSoFar: (retriesPerformedSoFar || 0) + 1,\n callback,\n })\n }\n\n if (req.status === 429) {\n onRateLimited?.(req)\n }\n\n if (callback) {\n callback({ status: 0 })\n }\n }\n }\n }\n req.send(body)\n}\n"]}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { PostHogPersistence } from './posthog-persistence';
|
|
2
|
+
import { PostHogConfig, SessionIdChangedCallback } from './types';
|
|
3
|
+
export declare class SessionIdManager {
|
|
4
|
+
private config;
|
|
5
|
+
private persistence;
|
|
6
|
+
private _windowId;
|
|
7
|
+
private _sessionId;
|
|
8
|
+
private _window_id_storage_key;
|
|
9
|
+
private _primary_window_exists_storage_key;
|
|
10
|
+
private _sessionStartTimestamp;
|
|
11
|
+
private _sessionActivityTimestamp;
|
|
12
|
+
private _sessionTimeoutMs;
|
|
13
|
+
private _sessionIdChangedHandlers;
|
|
14
|
+
constructor(config: Partial<PostHogConfig>, persistence: PostHogPersistence);
|
|
15
|
+
onSessionId(callback: SessionIdChangedCallback): () => void;
|
|
16
|
+
private _canUseSessionStorage;
|
|
17
|
+
private _setWindowId;
|
|
18
|
+
private _getWindowId;
|
|
19
|
+
private _setSessionId;
|
|
20
|
+
private _getSessionId;
|
|
21
|
+
resetSessionId(): void;
|
|
22
|
+
private _listenToReloadWindow;
|
|
23
|
+
checkAndGetSessionAndWindowId(readOnly?: boolean, _timestamp?: number | null): {
|
|
24
|
+
sessionId: string;
|
|
25
|
+
windowId: string;
|
|
26
|
+
sessionStartTimestamp: number;
|
|
27
|
+
};
|
|
28
|
+
}
|