posthog-node 5.14.1 → 5.16.0
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/client.d.ts +44 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +27 -4
- package/dist/client.mjs +28 -5
- package/dist/entrypoints/index.edge.d.ts +1 -0
- package/dist/entrypoints/index.edge.d.ts.map +1 -1
- package/dist/entrypoints/index.edge.js +1 -0
- package/dist/entrypoints/index.edge.mjs +1 -0
- package/dist/entrypoints/index.node.d.ts +2 -0
- package/dist/entrypoints/index.node.d.ts.map +1 -1
- package/dist/entrypoints/index.node.js +7 -0
- package/dist/entrypoints/index.node.mjs +4 -0
- package/dist/extensions/context/context.d.ts +8 -0
- package/dist/extensions/context/context.d.ts.map +1 -0
- package/dist/extensions/context/context.js +60 -0
- package/dist/extensions/context/context.mjs +26 -0
- package/dist/extensions/context/types.d.ts +18 -0
- package/dist/extensions/context/types.d.ts.map +1 -0
- package/dist/extensions/context/types.js +18 -0
- package/dist/extensions/context/types.mjs +0 -0
- package/dist/extensions/error-tracking/autocapture.js +2 -2
- package/dist/extensions/error-tracking/autocapture.mjs +2 -2
- package/dist/extensions/feature-flags/feature-flags.d.ts +0 -1
- package/dist/extensions/feature-flags/feature-flags.d.ts.map +1 -1
- package/dist/extensions/feature-flags/feature-flags.js +6 -13
- package/dist/extensions/feature-flags/feature-flags.mjs +6 -13
- package/dist/types.d.ts +23 -8
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.mjs +1 -1
- package/package.json +2 -2
- package/src/client.ts +89 -6
- package/src/entrypoints/index.edge.ts +4 -0
- package/src/entrypoints/index.node.ts +5 -0
- package/src/extensions/context/context.ts +33 -0
- package/src/extensions/context/types.ts +19 -0
- package/src/extensions/error-tracking/autocapture.ts +2 -2
- package/src/extensions/feature-flags/feature-flags.ts +10 -15
- package/src/types.ts +21 -4
- package/src/version.ts +1 -1
package/dist/client.d.ts
CHANGED
|
@@ -3,12 +3,14 @@ import { EventMessage, GroupIdentifyMessage, IdentifyMessage, IPostHog, PostHogO
|
|
|
3
3
|
import { FeatureFlagValue } from '@posthog/core';
|
|
4
4
|
import ErrorTracking from './extensions/error-tracking';
|
|
5
5
|
import { PostHogEventProperties } from '@posthog/core';
|
|
6
|
+
import { ContextData, ContextOptions, IPostHogContext } from './extensions/context/types';
|
|
6
7
|
export declare abstract class PostHogBackendClient extends PostHogCoreStateless implements IPostHog {
|
|
7
8
|
private _memoryStorage;
|
|
8
9
|
private featureFlagsPoller?;
|
|
9
10
|
protected errorTracking: ErrorTracking;
|
|
10
11
|
private maxCacheSize;
|
|
11
12
|
readonly options: PostHogOptions;
|
|
13
|
+
protected readonly context?: IPostHogContext;
|
|
12
14
|
distinctIdHasSentFlagCalls: Record<string, string[]>;
|
|
13
15
|
/**
|
|
14
16
|
* Initialize a new PostHog client instance.
|
|
@@ -683,6 +685,48 @@ export declare abstract class PostHogBackendClient extends PostHogCoreStateless
|
|
|
683
685
|
* @returns Promise that resolves when flags are reloaded
|
|
684
686
|
*/
|
|
685
687
|
reloadFeatureFlags(): Promise<void>;
|
|
688
|
+
protected abstract initializeContext(): IPostHogContext | undefined;
|
|
689
|
+
/**
|
|
690
|
+
* Run a function with specific context that will be applied to all events captured within that context.
|
|
691
|
+
* It propagates the context to all subsequent calls down the call stack.
|
|
692
|
+
* Context properties like tags and sessionId will be automatically attached to all events.
|
|
693
|
+
*
|
|
694
|
+
* @example
|
|
695
|
+
* ```ts
|
|
696
|
+
* posthog.withContext(
|
|
697
|
+
* { distinctId: 'user_123' },
|
|
698
|
+
* () => {
|
|
699
|
+
* posthog.capture({ event: 'button clicked' })
|
|
700
|
+
* },
|
|
701
|
+
* { fresh: false }
|
|
702
|
+
* )
|
|
703
|
+
* ```
|
|
704
|
+
*
|
|
705
|
+
* {@label Context}
|
|
706
|
+
*
|
|
707
|
+
* @param data - Context data to apply (sessionId, distinctId, properties, enableExceptionAutocapture)
|
|
708
|
+
* @param fn - Function to run with the context
|
|
709
|
+
* @param options - Context options (fresh)
|
|
710
|
+
* @returns The return value of the function
|
|
711
|
+
*/
|
|
712
|
+
withContext<T>(data: Partial<ContextData>, fn: () => T, options?: ContextOptions): T;
|
|
713
|
+
/**
|
|
714
|
+
* Get the current context data.
|
|
715
|
+
*
|
|
716
|
+
* @example
|
|
717
|
+
* ```ts
|
|
718
|
+
* // Get current context within a withContext block
|
|
719
|
+
* posthog.withContext({ distinctId: 'user_123' }, () => {
|
|
720
|
+
* const context = posthog.getContext()
|
|
721
|
+
* console.log(context?.distinctId) // 'user_123'
|
|
722
|
+
* })
|
|
723
|
+
* ```
|
|
724
|
+
*
|
|
725
|
+
* {@label Context}
|
|
726
|
+
*
|
|
727
|
+
* @returns The current context data, or undefined if no context is set
|
|
728
|
+
*/
|
|
729
|
+
getContext(): ContextData | undefined;
|
|
686
730
|
/**
|
|
687
731
|
* Shutdown the PostHog client gracefully.
|
|
688
732
|
*
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,QAAQ,EACR,oBAAoB,EAEpB,mBAAmB,EACnB,oBAAoB,EACpB,+BAA+B,EAC/B,wBAAwB,
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/client.js
CHANGED
|
@@ -48,6 +48,7 @@ class PostHogBackendClient extends core_namespaceObject.PostHogCoreStateless {
|
|
|
48
48
|
constructor(apiKey, options = {}){
|
|
49
49
|
super(apiKey, options), this._memoryStorage = new external_storage_memory_js_namespaceObject.PostHogMemoryStorage();
|
|
50
50
|
this.options = options;
|
|
51
|
+
this.context = this.initializeContext();
|
|
51
52
|
this.options.featureFlagsPollingInterval = 'number' == typeof options.featureFlagsPollingInterval ? Math.max(options.featureFlagsPollingInterval, MINIMUM_POLLING_INTERVAL) : THIRTY_SECONDS;
|
|
52
53
|
if (options.personalApiKey) {
|
|
53
54
|
if (options.personalApiKey.includes('phc_')) throw new Error('Your Personal API key is invalid. These keys are prefixed with "phx_" and can be created in PostHog project settings.');
|
|
@@ -179,6 +180,7 @@ class PostHogBackendClient extends core_namespaceObject.PostHogCoreStateless {
|
|
|
179
180
|
let response = await this.featureFlagsPoller?.getFeatureFlag(key, distinctId, groups, personProperties, groupProperties);
|
|
180
181
|
const flagWasLocallyEvaluated = void 0 !== response;
|
|
181
182
|
let requestId;
|
|
183
|
+
let evaluatedAt;
|
|
182
184
|
let flagDetail;
|
|
183
185
|
if (!flagWasLocallyEvaluated && !onlyEvaluateLocally) {
|
|
184
186
|
const remoteResponse = await super.getFeatureFlagDetailStateless(key, distinctId, groups, personProperties, groupProperties, disableGeoip);
|
|
@@ -186,6 +188,7 @@ class PostHogBackendClient extends core_namespaceObject.PostHogCoreStateless {
|
|
|
186
188
|
flagDetail = remoteResponse.response;
|
|
187
189
|
response = (0, core_namespaceObject.getFeatureFlagValue)(flagDetail);
|
|
188
190
|
requestId = remoteResponse?.requestId;
|
|
191
|
+
evaluatedAt = remoteResponse?.evaluatedAt;
|
|
189
192
|
}
|
|
190
193
|
const featureFlagReportedKey = `${key}_${response}`;
|
|
191
194
|
if (sendFeatureFlagEvents && (!(distinctId in this.distinctIdHasSentFlagCalls) || !this.distinctIdHasSentFlagCalls[distinctId].includes(featureFlagReportedKey))) {
|
|
@@ -205,7 +208,8 @@ class PostHogBackendClient extends core_namespaceObject.PostHogCoreStateless {
|
|
|
205
208
|
$feature_flag_reason: flagDetail?.reason?.description ?? flagDetail?.reason?.code,
|
|
206
209
|
locally_evaluated: flagWasLocallyEvaluated,
|
|
207
210
|
[`$feature/${key}`]: response,
|
|
208
|
-
$feature_flag_request_id: requestId
|
|
211
|
+
$feature_flag_request_id: requestId,
|
|
212
|
+
$feature_flag_evaluated_at: evaluatedAt
|
|
209
213
|
},
|
|
210
214
|
groups,
|
|
211
215
|
disableGeoip
|
|
@@ -299,6 +303,13 @@ class PostHogBackendClient extends core_namespaceObject.PostHogCoreStateless {
|
|
|
299
303
|
async reloadFeatureFlags() {
|
|
300
304
|
await this.featureFlagsPoller?.loadFeatureFlags(true);
|
|
301
305
|
}
|
|
306
|
+
withContext(data, fn, options) {
|
|
307
|
+
if (!this.context) return fn();
|
|
308
|
+
return this.context.run(data, fn, options);
|
|
309
|
+
}
|
|
310
|
+
getContext() {
|
|
311
|
+
return this.context?.get();
|
|
312
|
+
}
|
|
302
313
|
async _shutdown(shutdownTimeoutMs) {
|
|
303
314
|
this.featureFlagsPoller?.stopPoller(shutdownTimeoutMs);
|
|
304
315
|
this.errorTracking.shutdown();
|
|
@@ -410,10 +421,21 @@ class PostHogBackendClient extends core_namespaceObject.PostHogCoreStateless {
|
|
|
410
421
|
}
|
|
411
422
|
async prepareEventMessage(props) {
|
|
412
423
|
const { distinctId, event, properties, groups, sendFeatureFlags, timestamp, disableGeoip, uuid } = props;
|
|
424
|
+
const contextData = this.context?.get();
|
|
425
|
+
let mergedDistinctId = distinctId || contextData?.distinctId;
|
|
426
|
+
const mergedProperties = {
|
|
427
|
+
...contextData?.properties || {},
|
|
428
|
+
...properties || {}
|
|
429
|
+
};
|
|
430
|
+
if (!mergedDistinctId) {
|
|
431
|
+
mergedDistinctId = (0, core_namespaceObject.uuidv7)();
|
|
432
|
+
mergedProperties.$process_person_profile = false;
|
|
433
|
+
}
|
|
434
|
+
if (contextData?.sessionId && !mergedProperties.$session_id) mergedProperties.$session_id = contextData.sessionId;
|
|
413
435
|
const eventMessage = this._runBeforeSend({
|
|
414
|
-
distinctId,
|
|
436
|
+
distinctId: mergedDistinctId,
|
|
415
437
|
event,
|
|
416
|
-
properties,
|
|
438
|
+
properties: mergedProperties,
|
|
417
439
|
groups,
|
|
418
440
|
sendFeatureFlags,
|
|
419
441
|
timestamp,
|
|
@@ -424,8 +446,9 @@ class PostHogBackendClient extends core_namespaceObject.PostHogCoreStateless {
|
|
|
424
446
|
const eventProperties = await Promise.resolve().then(async ()=>{
|
|
425
447
|
if (sendFeatureFlags) {
|
|
426
448
|
const sendFeatureFlagsOptions = 'object' == typeof sendFeatureFlags ? sendFeatureFlags : void 0;
|
|
427
|
-
return await this.getFeatureFlagsForEvent(distinctId, groups, disableGeoip, sendFeatureFlagsOptions);
|
|
449
|
+
return await this.getFeatureFlagsForEvent(eventMessage.distinctId, groups, disableGeoip, sendFeatureFlagsOptions);
|
|
428
450
|
}
|
|
451
|
+
eventMessage.event;
|
|
429
452
|
return {};
|
|
430
453
|
}).then((flags)=>{
|
|
431
454
|
const additionalProperties = {};
|
package/dist/client.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { version } from "./version.mjs";
|
|
2
|
-
import { PostHogCoreStateless, getFeatureFlagValue, isBlockedUA, isPlainObject, safeSetTimeout } from "@posthog/core";
|
|
2
|
+
import { PostHogCoreStateless, getFeatureFlagValue, isBlockedUA, isPlainObject, safeSetTimeout, uuidv7 } from "@posthog/core";
|
|
3
3
|
import { FeatureFlagsPoller, InconclusiveMatchError, RequiresServerEvaluation } from "./extensions/feature-flags/feature-flags.mjs";
|
|
4
4
|
import error_tracking from "./extensions/error-tracking/index.mjs";
|
|
5
5
|
import { PostHogMemoryStorage } from "./storage-memory.mjs";
|
|
@@ -10,6 +10,7 @@ class PostHogBackendClient extends PostHogCoreStateless {
|
|
|
10
10
|
constructor(apiKey, options = {}){
|
|
11
11
|
super(apiKey, options), this._memoryStorage = new PostHogMemoryStorage();
|
|
12
12
|
this.options = options;
|
|
13
|
+
this.context = this.initializeContext();
|
|
13
14
|
this.options.featureFlagsPollingInterval = 'number' == typeof options.featureFlagsPollingInterval ? Math.max(options.featureFlagsPollingInterval, MINIMUM_POLLING_INTERVAL) : THIRTY_SECONDS;
|
|
14
15
|
if (options.personalApiKey) {
|
|
15
16
|
if (options.personalApiKey.includes('phc_')) throw new Error('Your Personal API key is invalid. These keys are prefixed with "phx_" and can be created in PostHog project settings.');
|
|
@@ -141,6 +142,7 @@ class PostHogBackendClient extends PostHogCoreStateless {
|
|
|
141
142
|
let response = await this.featureFlagsPoller?.getFeatureFlag(key, distinctId, groups, personProperties, groupProperties);
|
|
142
143
|
const flagWasLocallyEvaluated = void 0 !== response;
|
|
143
144
|
let requestId;
|
|
145
|
+
let evaluatedAt;
|
|
144
146
|
let flagDetail;
|
|
145
147
|
if (!flagWasLocallyEvaluated && !onlyEvaluateLocally) {
|
|
146
148
|
const remoteResponse = await super.getFeatureFlagDetailStateless(key, distinctId, groups, personProperties, groupProperties, disableGeoip);
|
|
@@ -148,6 +150,7 @@ class PostHogBackendClient extends PostHogCoreStateless {
|
|
|
148
150
|
flagDetail = remoteResponse.response;
|
|
149
151
|
response = getFeatureFlagValue(flagDetail);
|
|
150
152
|
requestId = remoteResponse?.requestId;
|
|
153
|
+
evaluatedAt = remoteResponse?.evaluatedAt;
|
|
151
154
|
}
|
|
152
155
|
const featureFlagReportedKey = `${key}_${response}`;
|
|
153
156
|
if (sendFeatureFlagEvents && (!(distinctId in this.distinctIdHasSentFlagCalls) || !this.distinctIdHasSentFlagCalls[distinctId].includes(featureFlagReportedKey))) {
|
|
@@ -167,7 +170,8 @@ class PostHogBackendClient extends PostHogCoreStateless {
|
|
|
167
170
|
$feature_flag_reason: flagDetail?.reason?.description ?? flagDetail?.reason?.code,
|
|
168
171
|
locally_evaluated: flagWasLocallyEvaluated,
|
|
169
172
|
[`$feature/${key}`]: response,
|
|
170
|
-
$feature_flag_request_id: requestId
|
|
173
|
+
$feature_flag_request_id: requestId,
|
|
174
|
+
$feature_flag_evaluated_at: evaluatedAt
|
|
171
175
|
},
|
|
172
176
|
groups,
|
|
173
177
|
disableGeoip
|
|
@@ -261,6 +265,13 @@ class PostHogBackendClient extends PostHogCoreStateless {
|
|
|
261
265
|
async reloadFeatureFlags() {
|
|
262
266
|
await this.featureFlagsPoller?.loadFeatureFlags(true);
|
|
263
267
|
}
|
|
268
|
+
withContext(data, fn, options) {
|
|
269
|
+
if (!this.context) return fn();
|
|
270
|
+
return this.context.run(data, fn, options);
|
|
271
|
+
}
|
|
272
|
+
getContext() {
|
|
273
|
+
return this.context?.get();
|
|
274
|
+
}
|
|
264
275
|
async _shutdown(shutdownTimeoutMs) {
|
|
265
276
|
this.featureFlagsPoller?.stopPoller(shutdownTimeoutMs);
|
|
266
277
|
this.errorTracking.shutdown();
|
|
@@ -372,10 +383,21 @@ class PostHogBackendClient extends PostHogCoreStateless {
|
|
|
372
383
|
}
|
|
373
384
|
async prepareEventMessage(props) {
|
|
374
385
|
const { distinctId, event, properties, groups, sendFeatureFlags, timestamp, disableGeoip, uuid } = props;
|
|
386
|
+
const contextData = this.context?.get();
|
|
387
|
+
let mergedDistinctId = distinctId || contextData?.distinctId;
|
|
388
|
+
const mergedProperties = {
|
|
389
|
+
...contextData?.properties || {},
|
|
390
|
+
...properties || {}
|
|
391
|
+
};
|
|
392
|
+
if (!mergedDistinctId) {
|
|
393
|
+
mergedDistinctId = uuidv7();
|
|
394
|
+
mergedProperties.$process_person_profile = false;
|
|
395
|
+
}
|
|
396
|
+
if (contextData?.sessionId && !mergedProperties.$session_id) mergedProperties.$session_id = contextData.sessionId;
|
|
375
397
|
const eventMessage = this._runBeforeSend({
|
|
376
|
-
distinctId,
|
|
398
|
+
distinctId: mergedDistinctId,
|
|
377
399
|
event,
|
|
378
|
-
properties,
|
|
400
|
+
properties: mergedProperties,
|
|
379
401
|
groups,
|
|
380
402
|
sendFeatureFlags,
|
|
381
403
|
timestamp,
|
|
@@ -386,8 +408,9 @@ class PostHogBackendClient extends PostHogCoreStateless {
|
|
|
386
408
|
const eventProperties = await Promise.resolve().then(async ()=>{
|
|
387
409
|
if (sendFeatureFlags) {
|
|
388
410
|
const sendFeatureFlagsOptions = 'object' == typeof sendFeatureFlags ? sendFeatureFlags : void 0;
|
|
389
|
-
return await this.getFeatureFlagsForEvent(distinctId, groups, disableGeoip, sendFeatureFlagsOptions);
|
|
411
|
+
return await this.getFeatureFlagsForEvent(eventMessage.distinctId, groups, disableGeoip, sendFeatureFlagsOptions);
|
|
390
412
|
}
|
|
413
|
+
eventMessage.event;
|
|
391
414
|
return {};
|
|
392
415
|
}).then((flags)=>{
|
|
393
416
|
const additionalProperties = {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.edge.d.ts","sourceRoot":"","sources":["../../src/entrypoints/index.edge.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAG1B,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAA;AAchD,qBAAa,OAAQ,SAAQ,oBAAoB;IAC/C,YAAY,IAAI,MAAM;
|
|
1
|
+
{"version":3,"file":"index.edge.d.ts","sourceRoot":"","sources":["../../src/entrypoints/index.edge.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAG1B,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAA;AAchD,qBAAa,OAAQ,SAAQ,oBAAoB;IAC/C,YAAY,IAAI,MAAM;IAItB,SAAS,CAAC,iBAAiB,IAAI,SAAS;CAGzC"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export * from '../exports';
|
|
2
2
|
import { PostHogBackendClient } from '../client';
|
|
3
|
+
import { PostHogContext } from '../extensions/context/context';
|
|
3
4
|
export declare class PostHog extends PostHogBackendClient {
|
|
4
5
|
getLibraryId(): string;
|
|
6
|
+
protected initializeContext(): PostHogContext;
|
|
5
7
|
}
|
|
6
8
|
//# sourceMappingURL=index.node.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.node.d.ts","sourceRoot":"","sources":["../../src/entrypoints/index.node.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAM1B,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"index.node.d.ts","sourceRoot":"","sources":["../../src/entrypoints/index.node.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAM1B,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAA;AAEhD,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAA;AAc9D,qBAAa,OAAQ,SAAQ,oBAAoB;IAC/C,YAAY,IAAI,MAAM;IAItB,SAAS,CAAC,iBAAiB,IAAI,cAAc;CAG9C"}
|
|
@@ -6,6 +6,9 @@ var __webpack_modules__ = {
|
|
|
6
6
|
"../exports": function(module) {
|
|
7
7
|
module.exports = require("../exports.js");
|
|
8
8
|
},
|
|
9
|
+
"../extensions/context/context": function(module) {
|
|
10
|
+
module.exports = require("../extensions/context/context.js");
|
|
11
|
+
},
|
|
9
12
|
"../extensions/error-tracking": function(module) {
|
|
10
13
|
module.exports = require("../extensions/error-tracking/index.js");
|
|
11
14
|
},
|
|
@@ -80,6 +83,7 @@ var __webpack_exports__ = {};
|
|
|
80
83
|
var _extensions_error_tracking__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/ __webpack_require__.n(_extensions_error_tracking__WEBPACK_IMPORTED_MODULE_3__);
|
|
81
84
|
var _client__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__("../client");
|
|
82
85
|
var _posthog_core__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__("@posthog/core");
|
|
86
|
+
var _extensions_context_context__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__("../extensions/context/context");
|
|
83
87
|
_extensions_error_tracking__WEBPACK_IMPORTED_MODULE_3___default().errorPropertiesBuilder = new _posthog_core__WEBPACK_IMPORTED_MODULE_5__.ErrorTracking.ErrorPropertiesBuilder([
|
|
84
88
|
new _posthog_core__WEBPACK_IMPORTED_MODULE_5__.ErrorTracking.EventCoercer(),
|
|
85
89
|
new _posthog_core__WEBPACK_IMPORTED_MODULE_5__.ErrorTracking.ErrorCoercer(),
|
|
@@ -94,6 +98,9 @@ var __webpack_exports__ = {};
|
|
|
94
98
|
getLibraryId() {
|
|
95
99
|
return 'posthog-node';
|
|
96
100
|
}
|
|
101
|
+
initializeContext() {
|
|
102
|
+
return new _extensions_context_context__WEBPACK_IMPORTED_MODULE_6__.PostHogContext();
|
|
103
|
+
}
|
|
97
104
|
}
|
|
98
105
|
})();
|
|
99
106
|
exports.PostHog = __webpack_exports__.PostHog;
|
|
@@ -3,6 +3,7 @@ import { addSourceContext } from "../extensions/error-tracking/modifiers/context
|
|
|
3
3
|
import error_tracking from "../extensions/error-tracking/index.mjs";
|
|
4
4
|
import { PostHogBackendClient } from "../client.mjs";
|
|
5
5
|
import { ErrorTracking } from "@posthog/core";
|
|
6
|
+
import { PostHogContext } from "../extensions/context/context.mjs";
|
|
6
7
|
export * from "../exports.mjs";
|
|
7
8
|
error_tracking.errorPropertiesBuilder = new ErrorTracking.ErrorPropertiesBuilder([
|
|
8
9
|
new ErrorTracking.EventCoercer(),
|
|
@@ -18,5 +19,8 @@ class PostHog extends PostHogBackendClient {
|
|
|
18
19
|
getLibraryId() {
|
|
19
20
|
return 'posthog-node';
|
|
20
21
|
}
|
|
22
|
+
initializeContext() {
|
|
23
|
+
return new PostHogContext();
|
|
24
|
+
}
|
|
21
25
|
}
|
|
22
26
|
export { PostHog };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ContextData, ContextOptions, IPostHogContext } from './types';
|
|
2
|
+
export declare class PostHogContext implements IPostHogContext {
|
|
3
|
+
private storage;
|
|
4
|
+
constructor();
|
|
5
|
+
get(): ContextData | undefined;
|
|
6
|
+
run<T>(context: ContextData, fn: () => T, options?: ContextOptions): T;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../src/extensions/context/context.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAEtE,qBAAa,cAAe,YAAW,eAAe;IACpD,OAAO,CAAC,OAAO,CAAgC;;IAM/C,GAAG,IAAI,WAAW,GAAG,SAAS;IAI9B,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,CAAC;CAkBvE"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_require__ = {};
|
|
3
|
+
(()=>{
|
|
4
|
+
__webpack_require__.d = (exports1, definition)=>{
|
|
5
|
+
for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: definition[key]
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
})();
|
|
11
|
+
(()=>{
|
|
12
|
+
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
13
|
+
})();
|
|
14
|
+
(()=>{
|
|
15
|
+
__webpack_require__.r = (exports1)=>{
|
|
16
|
+
if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
17
|
+
value: 'Module'
|
|
18
|
+
});
|
|
19
|
+
Object.defineProperty(exports1, '__esModule', {
|
|
20
|
+
value: true
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
})();
|
|
24
|
+
var __webpack_exports__ = {};
|
|
25
|
+
__webpack_require__.r(__webpack_exports__);
|
|
26
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
27
|
+
PostHogContext: ()=>PostHogContext
|
|
28
|
+
});
|
|
29
|
+
const external_node_async_hooks_namespaceObject = require("node:async_hooks");
|
|
30
|
+
class PostHogContext {
|
|
31
|
+
constructor(){
|
|
32
|
+
this.storage = new external_node_async_hooks_namespaceObject.AsyncLocalStorage();
|
|
33
|
+
}
|
|
34
|
+
get() {
|
|
35
|
+
return this.storage.getStore();
|
|
36
|
+
}
|
|
37
|
+
run(context, fn, options) {
|
|
38
|
+
const fresh = options?.fresh !== false;
|
|
39
|
+
if (fresh) return this.storage.run(context, fn);
|
|
40
|
+
{
|
|
41
|
+
const currentContext = this.get() || {};
|
|
42
|
+
const mergedContext = {
|
|
43
|
+
distinctId: context.distinctId ?? currentContext.distinctId,
|
|
44
|
+
sessionId: context.sessionId ?? currentContext.sessionId,
|
|
45
|
+
properties: {
|
|
46
|
+
...currentContext.properties || {},
|
|
47
|
+
...context.properties || {}
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
return this.storage.run(mergedContext, fn);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
exports.PostHogContext = __webpack_exports__.PostHogContext;
|
|
55
|
+
for(var __webpack_i__ in __webpack_exports__)if (-1 === [
|
|
56
|
+
"PostHogContext"
|
|
57
|
+
].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
|
|
58
|
+
Object.defineProperty(exports, '__esModule', {
|
|
59
|
+
value: true
|
|
60
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
2
|
+
class PostHogContext {
|
|
3
|
+
constructor(){
|
|
4
|
+
this.storage = new AsyncLocalStorage();
|
|
5
|
+
}
|
|
6
|
+
get() {
|
|
7
|
+
return this.storage.getStore();
|
|
8
|
+
}
|
|
9
|
+
run(context, fn, options) {
|
|
10
|
+
const fresh = options?.fresh !== false;
|
|
11
|
+
if (fresh) return this.storage.run(context, fn);
|
|
12
|
+
{
|
|
13
|
+
const currentContext = this.get() || {};
|
|
14
|
+
const mergedContext = {
|
|
15
|
+
distinctId: context.distinctId ?? currentContext.distinctId,
|
|
16
|
+
sessionId: context.sessionId ?? currentContext.sessionId,
|
|
17
|
+
properties: {
|
|
18
|
+
...currentContext.properties || {},
|
|
19
|
+
...context.properties || {}
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
return this.storage.run(mergedContext, fn);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export { PostHogContext };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface ContextData {
|
|
2
|
+
distinctId?: string;
|
|
3
|
+
sessionId?: string;
|
|
4
|
+
properties?: Record<string, any>;
|
|
5
|
+
}
|
|
6
|
+
export interface ContextOptions {
|
|
7
|
+
/**
|
|
8
|
+
* If true, replaces the current context entirely.
|
|
9
|
+
* If false, merges with the existing context (new values override existing ones).
|
|
10
|
+
* @default true
|
|
11
|
+
*/
|
|
12
|
+
fresh?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export interface IPostHogContext {
|
|
15
|
+
get(): ContextData | undefined;
|
|
16
|
+
run<T>(context: ContextData, fn: () => T, options?: ContextOptions): T;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/extensions/context/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;CACjC;AAED,MAAM,WAAW,cAAc;IAC7B;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,GAAG,IAAI,WAAW,GAAG,SAAS,CAAA;IAC9B,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,CAAC,CAAA;CACvE"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_require__ = {};
|
|
3
|
+
(()=>{
|
|
4
|
+
__webpack_require__.r = (exports1)=>{
|
|
5
|
+
if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
6
|
+
value: 'Module'
|
|
7
|
+
});
|
|
8
|
+
Object.defineProperty(exports1, '__esModule', {
|
|
9
|
+
value: true
|
|
10
|
+
});
|
|
11
|
+
};
|
|
12
|
+
})();
|
|
13
|
+
var __webpack_exports__ = {};
|
|
14
|
+
__webpack_require__.r(__webpack_exports__);
|
|
15
|
+
for(var __webpack_i__ in __webpack_exports__)exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
|
|
16
|
+
Object.defineProperty(exports, '__esModule', {
|
|
17
|
+
value: true
|
|
18
|
+
});
|
|
File without changes
|
|
@@ -47,10 +47,10 @@ function makeUncaughtExceptionHandler(captureFn, onFatalFn) {
|
|
|
47
47
|
});
|
|
48
48
|
}
|
|
49
49
|
function addUncaughtExceptionListener(captureFn, onFatalFn) {
|
|
50
|
-
|
|
50
|
+
globalThis.process?.on('uncaughtException', makeUncaughtExceptionHandler(captureFn, onFatalFn));
|
|
51
51
|
}
|
|
52
52
|
function addUnhandledRejectionListener(captureFn) {
|
|
53
|
-
|
|
53
|
+
globalThis.process?.on('unhandledRejection', (reason)=>captureFn(reason, {
|
|
54
54
|
mechanism: {
|
|
55
55
|
type: 'onunhandledrejection',
|
|
56
56
|
handled: false
|
|
@@ -18,10 +18,10 @@ function makeUncaughtExceptionHandler(captureFn, onFatalFn) {
|
|
|
18
18
|
});
|
|
19
19
|
}
|
|
20
20
|
function addUncaughtExceptionListener(captureFn, onFatalFn) {
|
|
21
|
-
|
|
21
|
+
globalThis.process?.on('uncaughtException', makeUncaughtExceptionHandler(captureFn, onFatalFn));
|
|
22
22
|
}
|
|
23
23
|
function addUnhandledRejectionListener(captureFn) {
|
|
24
|
-
|
|
24
|
+
globalThis.process?.on('unhandledRejection', (reason)=>captureFn(reason, {
|
|
25
25
|
mechanism: {
|
|
26
26
|
type: 'onunhandledrejection',
|
|
27
27
|
handled: false
|
|
@@ -46,7 +46,6 @@ declare class FeatureFlagsPoller {
|
|
|
46
46
|
backOffCount: number;
|
|
47
47
|
onLoad?: (count: number) => void;
|
|
48
48
|
private cacheProvider?;
|
|
49
|
-
private hasAttemptedCacheLoad;
|
|
50
49
|
private loadingPromise?;
|
|
51
50
|
constructor({ pollingInterval, personalApiKey, projectApiKey, timeout, host, customHeaders, ...options }: FeatureFlagsPollerOptions);
|
|
52
51
|
debug(enabled?: boolean): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feature-flags.d.ts","sourceRoot":"","sources":["../../../src/extensions/feature-flags/feature-flags.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAmC,kBAAkB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AACtH,OAAO,KAAK,EAAE,gBAAgB,EAAE,QAAQ,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAA;AAG1G,OAAO,EAAE,2BAA2B,EAA2B,MAAM,SAAS,CAAA;AAQ9E,cAAM,WAAY,SAAQ,KAAK;gBACjB,OAAO,EAAE,MAAM;CAO5B;AAED,cAAM,sBAAuB,SAAQ,KAAK;gBAC5B,OAAO,EAAE,MAAM;CAS5B;AAED,cAAM,wBAAyB,SAAQ,KAAK;gBAC9B,OAAO,EAAE,MAAM;CAS5B;AAED,KAAK,yBAAyB,GAAG;IAC/B,cAAc,EAAE,MAAM,CAAA;IACtB,aAAa,EAAE,MAAM,CAAA;IACrB,IAAI,EAAE,MAAM,CAAA;IACZ,eAAe,EAAE,MAAM,CAAA;IACvB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,KAAK,OAAO,CAAC,oBAAoB,CAAC,CAAA;IACpF,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;IAChC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,aAAa,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAA;IACzC,aAAa,CAAC,EAAE,2BAA2B,CAAA;CAC5C,CAAA;AAED,cAAM,kBAAkB;IACtB,eAAe,EAAE,MAAM,CAAA;IACvB,cAAc,EAAE,MAAM,CAAA;IACtB,aAAa,EAAE,MAAM,CAAA;IACrB,YAAY,EAAE,KAAK,CAAC,kBAAkB,CAAC,CAAA;IACvC,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAA;IACrD,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACxC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;IACtC,sBAAsB,EAAE,OAAO,CAAA;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,yBAAyB,CAAC,MAAM,CAAC,CAAA;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC,OAAO,CAAA;IACvB,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,KAAK,OAAO,CAAC,oBAAoB,CAAC,CAAA;IACnF,SAAS,EAAE,OAAO,CAAQ;IAC1B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;IAChC,aAAa,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAA;IACzC,6BAA6B,EAAE,OAAO,CAAQ;IAC9C,YAAY,EAAE,MAAM,CAAI;IACxB,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,OAAO,CAAC,aAAa,CAAC,CAA6B;IACnD,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"feature-flags.d.ts","sourceRoot":"","sources":["../../../src/extensions/feature-flags/feature-flags.ts"],"names":[],"mappings":"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"}
|
|
@@ -68,7 +68,6 @@ class FeatureFlagsPoller {
|
|
|
68
68
|
this.debugMode = false;
|
|
69
69
|
this.shouldBeginExponentialBackoff = false;
|
|
70
70
|
this.backOffCount = 0;
|
|
71
|
-
this.hasAttemptedCacheLoad = false;
|
|
72
71
|
this.pollingInterval = pollingInterval;
|
|
73
72
|
this.personalApiKey = personalApiKey;
|
|
74
73
|
this.featureFlags = [];
|
|
@@ -296,15 +295,11 @@ class FeatureFlagsPoller {
|
|
|
296
295
|
}
|
|
297
296
|
}
|
|
298
297
|
async loadFeatureFlags(forceReload = false) {
|
|
299
|
-
if (this.
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
if (!this.loadedSuccessfullyOnce || forceReload) {
|
|
305
|
-
this.loadingPromise = this._loadFeatureFlags();
|
|
306
|
-
await this.loadingPromise;
|
|
307
|
-
}
|
|
298
|
+
if (this.loadedSuccessfullyOnce && !forceReload) return;
|
|
299
|
+
if (!this.loadingPromise) this.loadingPromise = this._loadFeatureFlags().catch((err)=>this.logMsgIfDebug(()=>console.debug(`[FEATURE FLAGS] Failed to load feature flags: ${err}`))).finally(()=>{
|
|
300
|
+
this.loadingPromise = void 0;
|
|
301
|
+
});
|
|
302
|
+
return this.loadingPromise;
|
|
308
303
|
}
|
|
309
304
|
isLocalEvaluationReady() {
|
|
310
305
|
return (this.loadedSuccessfullyOnce ?? false) && (this.featureFlags?.length ?? 0) > 0;
|
|
@@ -318,7 +313,7 @@ class FeatureFlagsPoller {
|
|
|
318
313
|
clearTimeout(this.poller);
|
|
319
314
|
this.poller = void 0;
|
|
320
315
|
}
|
|
321
|
-
this.poller = setTimeout(()=>this.
|
|
316
|
+
this.poller = setTimeout(()=>this.loadFeatureFlags(true), this.getPollingInterval());
|
|
322
317
|
try {
|
|
323
318
|
let shouldFetch = true;
|
|
324
319
|
if (this.cacheProvider) try {
|
|
@@ -378,8 +373,6 @@ class FeatureFlagsPoller {
|
|
|
378
373
|
}
|
|
379
374
|
} catch (err) {
|
|
380
375
|
if (err instanceof ClientError) this.onError?.(err);
|
|
381
|
-
} finally{
|
|
382
|
-
this.loadingPromise = void 0;
|
|
383
376
|
}
|
|
384
377
|
}
|
|
385
378
|
getPersonalApiKeyRequestOptions(method = 'GET') {
|
|
@@ -35,7 +35,6 @@ class FeatureFlagsPoller {
|
|
|
35
35
|
this.debugMode = false;
|
|
36
36
|
this.shouldBeginExponentialBackoff = false;
|
|
37
37
|
this.backOffCount = 0;
|
|
38
|
-
this.hasAttemptedCacheLoad = false;
|
|
39
38
|
this.pollingInterval = pollingInterval;
|
|
40
39
|
this.personalApiKey = personalApiKey;
|
|
41
40
|
this.featureFlags = [];
|
|
@@ -263,15 +262,11 @@ class FeatureFlagsPoller {
|
|
|
263
262
|
}
|
|
264
263
|
}
|
|
265
264
|
async loadFeatureFlags(forceReload = false) {
|
|
266
|
-
if (this.
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
if (!this.loadedSuccessfullyOnce || forceReload) {
|
|
272
|
-
this.loadingPromise = this._loadFeatureFlags();
|
|
273
|
-
await this.loadingPromise;
|
|
274
|
-
}
|
|
265
|
+
if (this.loadedSuccessfullyOnce && !forceReload) return;
|
|
266
|
+
if (!this.loadingPromise) this.loadingPromise = this._loadFeatureFlags().catch((err)=>this.logMsgIfDebug(()=>console.debug(`[FEATURE FLAGS] Failed to load feature flags: ${err}`))).finally(()=>{
|
|
267
|
+
this.loadingPromise = void 0;
|
|
268
|
+
});
|
|
269
|
+
return this.loadingPromise;
|
|
275
270
|
}
|
|
276
271
|
isLocalEvaluationReady() {
|
|
277
272
|
return (this.loadedSuccessfullyOnce ?? false) && (this.featureFlags?.length ?? 0) > 0;
|
|
@@ -285,7 +280,7 @@ class FeatureFlagsPoller {
|
|
|
285
280
|
clearTimeout(this.poller);
|
|
286
281
|
this.poller = void 0;
|
|
287
282
|
}
|
|
288
|
-
this.poller = setTimeout(()=>this.
|
|
283
|
+
this.poller = setTimeout(()=>this.loadFeatureFlags(true), this.getPollingInterval());
|
|
289
284
|
try {
|
|
290
285
|
let shouldFetch = true;
|
|
291
286
|
if (this.cacheProvider) try {
|
|
@@ -345,8 +340,6 @@ class FeatureFlagsPoller {
|
|
|
345
340
|
}
|
|
346
341
|
} catch (err) {
|
|
347
342
|
if (err instanceof ClientError) this.onError?.(err);
|
|
348
|
-
} finally{
|
|
349
|
-
this.loadingPromise = void 0;
|
|
350
343
|
}
|
|
351
344
|
}
|
|
352
345
|
getPersonalApiKeyRequestOptions(method = 'GET') {
|
package/dist/types.d.ts
CHANGED
|
@@ -1,30 +1,32 @@
|
|
|
1
1
|
import type { PostHogCoreOptions, FeatureFlagValue, JsonType, PostHogFetchOptions, PostHogFetchResponse } from '@posthog/core';
|
|
2
|
+
import { ContextData, ContextOptions } from './extensions/context/types';
|
|
2
3
|
import type { FlagDefinitionCacheProvider } from './extensions/feature-flags/cache';
|
|
3
|
-
export
|
|
4
|
+
export type IdentifyMessage = {
|
|
4
5
|
distinctId: string;
|
|
5
6
|
properties?: Record<string | number, any>;
|
|
6
7
|
disableGeoip?: boolean;
|
|
7
|
-
}
|
|
8
|
-
export
|
|
8
|
+
};
|
|
9
|
+
export type SendFeatureFlagsOptions = {
|
|
9
10
|
onlyEvaluateLocally?: boolean;
|
|
10
11
|
personProperties?: Record<string, any>;
|
|
11
12
|
groupProperties?: Record<string, Record<string, any>>;
|
|
12
13
|
flagKeys?: string[];
|
|
13
|
-
}
|
|
14
|
-
export
|
|
14
|
+
};
|
|
15
|
+
export type EventMessage = Omit<IdentifyMessage, 'distinctId'> & {
|
|
16
|
+
distinctId?: string;
|
|
15
17
|
event: string;
|
|
16
18
|
groups?: Record<string, string | number>;
|
|
17
19
|
sendFeatureFlags?: boolean | SendFeatureFlagsOptions;
|
|
18
20
|
timestamp?: Date;
|
|
19
21
|
uuid?: string;
|
|
20
|
-
}
|
|
21
|
-
export
|
|
22
|
+
};
|
|
23
|
+
export type GroupIdentifyMessage = {
|
|
22
24
|
groupType: string;
|
|
23
25
|
groupKey: string;
|
|
24
26
|
properties?: Record<string | number, any>;
|
|
25
27
|
distinctId?: string;
|
|
26
28
|
disableGeoip?: boolean;
|
|
27
|
-
}
|
|
29
|
+
};
|
|
28
30
|
export type PropertyGroup = {
|
|
29
31
|
type: 'AND' | 'OR';
|
|
30
32
|
values: PropertyGroup[] | FlagProperty[];
|
|
@@ -294,6 +296,19 @@ export interface IPostHog {
|
|
|
294
296
|
* already polled automatically at a regular interval.
|
|
295
297
|
*/
|
|
296
298
|
reloadFeatureFlags(): Promise<void>;
|
|
299
|
+
/**
|
|
300
|
+
* @description Run a function with specific context that will be applied to all events captured within that context.
|
|
301
|
+
* @param data Context data to apply (sessionId, distinctId, properties, enableExceptionAutocapture)
|
|
302
|
+
* @param fn Function to run with the context
|
|
303
|
+
* @param options Context options (fresh)
|
|
304
|
+
* @returns The return value of the function
|
|
305
|
+
*/
|
|
306
|
+
withContext<T>(data: Partial<ContextData>, fn: () => T, options?: ContextOptions): T;
|
|
307
|
+
/**
|
|
308
|
+
* @description Get the current context data.
|
|
309
|
+
* @returns The current context data, or undefined if no context is set
|
|
310
|
+
*/
|
|
311
|
+
getContext(): ContextData | undefined;
|
|
297
312
|
/**
|
|
298
313
|
* @description Flushes the events still in the queue and clears the feature flags poller to allow for
|
|
299
314
|
* a clean shutdown.
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAClB,gBAAgB,EAChB,QAAQ,EACR,mBAAmB,EACnB,oBAAoB,EACrB,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const version = "5.
|
|
1
|
+
export declare const version = "5.16.0";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/dist/version.js
CHANGED
|
@@ -26,7 +26,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
26
26
|
__webpack_require__.d(__webpack_exports__, {
|
|
27
27
|
version: ()=>version
|
|
28
28
|
});
|
|
29
|
-
const version = '5.
|
|
29
|
+
const version = '5.16.0';
|
|
30
30
|
exports.version = __webpack_exports__.version;
|
|
31
31
|
for(var __webpack_i__ in __webpack_exports__)if (-1 === [
|
|
32
32
|
"version"
|
package/dist/version.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const version = '5.
|
|
1
|
+
const version = '5.16.0';
|
|
2
2
|
export { version };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "posthog-node",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.16.0",
|
|
4
4
|
"description": "PostHog Node.js integration",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"module": "dist/entrypoints/index.node.mjs",
|
|
26
26
|
"types": "dist/entrypoints/index.node.d.ts",
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@posthog/core": "1.
|
|
28
|
+
"@posthog/core": "1.7.0"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@rslib/core": "0.10.6",
|
package/src/client.ts
CHANGED
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
PostHogFetchResponse,
|
|
9
9
|
PostHogFlagsAndPayloadsResponse,
|
|
10
10
|
PostHogPersistedProperty,
|
|
11
|
-
Logger,
|
|
12
11
|
PostHogCaptureOptions,
|
|
13
12
|
isPlainObject,
|
|
14
13
|
isBlockedUA,
|
|
@@ -30,6 +29,8 @@ import {
|
|
|
30
29
|
import ErrorTracking from './extensions/error-tracking'
|
|
31
30
|
import { safeSetTimeout, PostHogEventProperties } from '@posthog/core'
|
|
32
31
|
import { PostHogMemoryStorage } from './storage-memory'
|
|
32
|
+
import { uuidv7 } from '@posthog/core'
|
|
33
|
+
import { ContextData, ContextOptions, IPostHogContext } from './extensions/context/types'
|
|
33
34
|
|
|
34
35
|
// Standard local evaluation rate limit is 600 per minute (10 per second),
|
|
35
36
|
// so the fastest a poller should ever be set is 100ms.
|
|
@@ -45,6 +46,7 @@ export abstract class PostHogBackendClient extends PostHogCoreStateless implemen
|
|
|
45
46
|
protected errorTracking: ErrorTracking
|
|
46
47
|
private maxCacheSize: number
|
|
47
48
|
public readonly options: PostHogOptions
|
|
49
|
+
protected readonly context?: IPostHogContext
|
|
48
50
|
|
|
49
51
|
distinctIdHasSentFlagCalls: Record<string, string[]>
|
|
50
52
|
|
|
@@ -81,6 +83,7 @@ export abstract class PostHogBackendClient extends PostHogCoreStateless implemen
|
|
|
81
83
|
super(apiKey, options)
|
|
82
84
|
|
|
83
85
|
this.options = options
|
|
86
|
+
this.context = this.initializeContext()
|
|
84
87
|
|
|
85
88
|
this.options.featureFlagsPollingInterval =
|
|
86
89
|
typeof options.featureFlagsPollingInterval === 'number'
|
|
@@ -680,6 +683,7 @@ export abstract class PostHogBackendClient extends PostHogCoreStateless implemen
|
|
|
680
683
|
|
|
681
684
|
const flagWasLocallyEvaluated = response !== undefined
|
|
682
685
|
let requestId = undefined
|
|
686
|
+
let evaluatedAt = undefined
|
|
683
687
|
let flagDetail: FeatureFlagDetail | undefined = undefined
|
|
684
688
|
if (!flagWasLocallyEvaluated && !onlyEvaluateLocally) {
|
|
685
689
|
const remoteResponse = await super.getFeatureFlagDetailStateless(
|
|
@@ -698,6 +702,7 @@ export abstract class PostHogBackendClient extends PostHogCoreStateless implemen
|
|
|
698
702
|
flagDetail = remoteResponse.response
|
|
699
703
|
response = getFeatureFlagValue(flagDetail)
|
|
700
704
|
requestId = remoteResponse?.requestId
|
|
705
|
+
evaluatedAt = remoteResponse?.evaluatedAt
|
|
701
706
|
}
|
|
702
707
|
|
|
703
708
|
const featureFlagReportedKey = `${key}_${response}`
|
|
@@ -727,6 +732,7 @@ export abstract class PostHogBackendClient extends PostHogCoreStateless implemen
|
|
|
727
732
|
locally_evaluated: flagWasLocallyEvaluated,
|
|
728
733
|
[`$feature/${key}`]: response,
|
|
729
734
|
$feature_flag_request_id: requestId,
|
|
735
|
+
$feature_flag_evaluated_at: evaluatedAt,
|
|
730
736
|
},
|
|
731
737
|
groups,
|
|
732
738
|
disableGeoip,
|
|
@@ -1159,6 +1165,60 @@ export abstract class PostHogBackendClient extends PostHogCoreStateless implemen
|
|
|
1159
1165
|
await this.featureFlagsPoller?.loadFeatureFlags(true)
|
|
1160
1166
|
}
|
|
1161
1167
|
|
|
1168
|
+
protected abstract initializeContext(): IPostHogContext | undefined
|
|
1169
|
+
|
|
1170
|
+
/**
|
|
1171
|
+
* Run a function with specific context that will be applied to all events captured within that context.
|
|
1172
|
+
* It propagates the context to all subsequent calls down the call stack.
|
|
1173
|
+
* Context properties like tags and sessionId will be automatically attached to all events.
|
|
1174
|
+
*
|
|
1175
|
+
* @example
|
|
1176
|
+
* ```ts
|
|
1177
|
+
* posthog.withContext(
|
|
1178
|
+
* { distinctId: 'user_123' },
|
|
1179
|
+
* () => {
|
|
1180
|
+
* posthog.capture({ event: 'button clicked' })
|
|
1181
|
+
* },
|
|
1182
|
+
* { fresh: false }
|
|
1183
|
+
* )
|
|
1184
|
+
* ```
|
|
1185
|
+
*
|
|
1186
|
+
* {@label Context}
|
|
1187
|
+
*
|
|
1188
|
+
* @param data - Context data to apply (sessionId, distinctId, properties, enableExceptionAutocapture)
|
|
1189
|
+
* @param fn - Function to run with the context
|
|
1190
|
+
* @param options - Context options (fresh)
|
|
1191
|
+
* @returns The return value of the function
|
|
1192
|
+
*/
|
|
1193
|
+
withContext<T>(data: Partial<ContextData>, fn: () => T, options?: ContextOptions): T {
|
|
1194
|
+
if (!this.context) {
|
|
1195
|
+
// Context not supported in this environment (e.g., edge runtime)
|
|
1196
|
+
return fn()
|
|
1197
|
+
}
|
|
1198
|
+
|
|
1199
|
+
return this.context.run(data, fn, options)
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1202
|
+
/**
|
|
1203
|
+
* Get the current context data.
|
|
1204
|
+
*
|
|
1205
|
+
* @example
|
|
1206
|
+
* ```ts
|
|
1207
|
+
* // Get current context within a withContext block
|
|
1208
|
+
* posthog.withContext({ distinctId: 'user_123' }, () => {
|
|
1209
|
+
* const context = posthog.getContext()
|
|
1210
|
+
* console.log(context?.distinctId) // 'user_123'
|
|
1211
|
+
* })
|
|
1212
|
+
* ```
|
|
1213
|
+
*
|
|
1214
|
+
* {@label Context}
|
|
1215
|
+
*
|
|
1216
|
+
* @returns The current context data, or undefined if no context is set
|
|
1217
|
+
*/
|
|
1218
|
+
getContext(): ContextData | undefined {
|
|
1219
|
+
return this.context?.get()
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1162
1222
|
/**
|
|
1163
1223
|
* Shutdown the PostHog client gracefully.
|
|
1164
1224
|
*
|
|
@@ -1439,11 +1499,29 @@ export abstract class PostHogBackendClient extends PostHogCoreStateless implemen
|
|
|
1439
1499
|
const { distinctId, event, properties, groups, sendFeatureFlags, timestamp, disableGeoip, uuid }: EventMessage =
|
|
1440
1500
|
props
|
|
1441
1501
|
|
|
1502
|
+
const contextData = this.context?.get()
|
|
1503
|
+
|
|
1504
|
+
let mergedDistinctId = distinctId || contextData?.distinctId
|
|
1505
|
+
|
|
1506
|
+
const mergedProperties = {
|
|
1507
|
+
...(contextData?.properties || {}),
|
|
1508
|
+
...(properties || {}),
|
|
1509
|
+
}
|
|
1510
|
+
|
|
1511
|
+
if (!mergedDistinctId) {
|
|
1512
|
+
mergedDistinctId = uuidv7()
|
|
1513
|
+
mergedProperties.$process_person_profile = false
|
|
1514
|
+
}
|
|
1515
|
+
|
|
1516
|
+
if (contextData?.sessionId && !mergedProperties.$session_id) {
|
|
1517
|
+
mergedProperties.$session_id = contextData.sessionId
|
|
1518
|
+
}
|
|
1519
|
+
|
|
1442
1520
|
// Run before_send if configured
|
|
1443
1521
|
const eventMessage = this._runBeforeSend({
|
|
1444
|
-
distinctId,
|
|
1522
|
+
distinctId: mergedDistinctId,
|
|
1445
1523
|
event,
|
|
1446
|
-
properties,
|
|
1524
|
+
properties: mergedProperties,
|
|
1447
1525
|
groups,
|
|
1448
1526
|
sendFeatureFlags,
|
|
1449
1527
|
timestamp,
|
|
@@ -1461,10 +1539,15 @@ export abstract class PostHogBackendClient extends PostHogCoreStateless implemen
|
|
|
1461
1539
|
if (sendFeatureFlags) {
|
|
1462
1540
|
// If we are sending feature flags, we evaluate them locally if the user prefers it, otherwise we fall back to remote evaluation
|
|
1463
1541
|
const sendFeatureFlagsOptions = typeof sendFeatureFlags === 'object' ? sendFeatureFlags : undefined
|
|
1464
|
-
return await this.getFeatureFlagsForEvent(
|
|
1542
|
+
return await this.getFeatureFlagsForEvent(
|
|
1543
|
+
eventMessage.distinctId!,
|
|
1544
|
+
groups,
|
|
1545
|
+
disableGeoip,
|
|
1546
|
+
sendFeatureFlagsOptions
|
|
1547
|
+
)
|
|
1465
1548
|
}
|
|
1466
1549
|
|
|
1467
|
-
if (event === '$feature_flag_called') {
|
|
1550
|
+
if (eventMessage.event === '$feature_flag_called') {
|
|
1468
1551
|
// If we're capturing a $feature_flag_called event, we don't want to enrich the event with cached flags that may be out of date.
|
|
1469
1552
|
return {}
|
|
1470
1553
|
}
|
|
@@ -1514,7 +1597,7 @@ export abstract class PostHogBackendClient extends PostHogCoreStateless implemen
|
|
|
1514
1597
|
}
|
|
1515
1598
|
|
|
1516
1599
|
return {
|
|
1517
|
-
distinctId: eventMessage.distinctId
|
|
1600
|
+
distinctId: eventMessage.distinctId!,
|
|
1518
1601
|
event: eventMessage.event,
|
|
1519
1602
|
properties: eventProperties,
|
|
1520
1603
|
options: {
|
|
@@ -6,6 +6,7 @@ import ErrorTracking from '../extensions/error-tracking'
|
|
|
6
6
|
|
|
7
7
|
import { PostHogBackendClient } from '../client'
|
|
8
8
|
import { ErrorTracking as CoreErrorTracking } from '@posthog/core'
|
|
9
|
+
import { PostHogContext } from '../extensions/context/context'
|
|
9
10
|
|
|
10
11
|
ErrorTracking.errorPropertiesBuilder = new CoreErrorTracking.ErrorPropertiesBuilder(
|
|
11
12
|
[
|
|
@@ -23,4 +24,8 @@ export class PostHog extends PostHogBackendClient {
|
|
|
23
24
|
getLibraryId(): string {
|
|
24
25
|
return 'posthog-node'
|
|
25
26
|
}
|
|
27
|
+
|
|
28
|
+
protected initializeContext(): PostHogContext {
|
|
29
|
+
return new PostHogContext()
|
|
30
|
+
}
|
|
26
31
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from 'node:async_hooks'
|
|
2
|
+
import { ContextData, ContextOptions, IPostHogContext } from './types'
|
|
3
|
+
|
|
4
|
+
export class PostHogContext implements IPostHogContext {
|
|
5
|
+
private storage: AsyncLocalStorage<ContextData>
|
|
6
|
+
|
|
7
|
+
constructor() {
|
|
8
|
+
this.storage = new AsyncLocalStorage<ContextData>()
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
get(): ContextData | undefined {
|
|
12
|
+
return this.storage.getStore()
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
run<T>(context: ContextData, fn: () => T, options?: ContextOptions): T {
|
|
16
|
+
const fresh = options?.fresh !== false
|
|
17
|
+
|
|
18
|
+
if (fresh) {
|
|
19
|
+
return this.storage.run(context, fn)
|
|
20
|
+
} else {
|
|
21
|
+
const currentContext = this.get() || {}
|
|
22
|
+
const mergedContext: ContextData = {
|
|
23
|
+
distinctId: context.distinctId ?? currentContext.distinctId,
|
|
24
|
+
sessionId: context.sessionId ?? currentContext.sessionId,
|
|
25
|
+
properties: {
|
|
26
|
+
...(currentContext.properties || {}),
|
|
27
|
+
...(context.properties || {}),
|
|
28
|
+
},
|
|
29
|
+
}
|
|
30
|
+
return this.storage.run(mergedContext, fn)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface ContextData {
|
|
2
|
+
distinctId?: string
|
|
3
|
+
sessionId?: string
|
|
4
|
+
properties?: Record<string, any>
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export interface ContextOptions {
|
|
8
|
+
/**
|
|
9
|
+
* If true, replaces the current context entirely.
|
|
10
|
+
* If false, merges with the existing context (new values override existing ones).
|
|
11
|
+
* @default true
|
|
12
|
+
*/
|
|
13
|
+
fresh?: boolean
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface IPostHogContext {
|
|
17
|
+
get(): ContextData | undefined
|
|
18
|
+
run<T>(context: ContextData, fn: () => T, options?: ContextOptions): T
|
|
19
|
+
}
|
|
@@ -50,13 +50,13 @@ export function addUncaughtExceptionListener(
|
|
|
50
50
|
captureFn: (exception: Error, hint: CoreErrorTracking.EventHint) => void,
|
|
51
51
|
onFatalFn: (exception: Error) => void
|
|
52
52
|
): void {
|
|
53
|
-
|
|
53
|
+
globalThis.process?.on('uncaughtException', makeUncaughtExceptionHandler(captureFn, onFatalFn))
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
export function addUnhandledRejectionListener(
|
|
57
57
|
captureFn: (exception: unknown, hint: CoreErrorTracking.EventHint) => void
|
|
58
58
|
): void {
|
|
59
|
-
|
|
59
|
+
globalThis.process?.on('unhandledRejection', (reason: unknown) => {
|
|
60
60
|
return captureFn(reason, {
|
|
61
61
|
mechanism: {
|
|
62
62
|
type: 'onunhandledrejection',
|
|
@@ -77,7 +77,6 @@ class FeatureFlagsPoller {
|
|
|
77
77
|
backOffCount: number = 0
|
|
78
78
|
onLoad?: (count: number) => void
|
|
79
79
|
private cacheProvider?: FlagDefinitionCacheProvider
|
|
80
|
-
private hasAttemptedCacheLoad: boolean = false
|
|
81
80
|
private loadingPromise?: Promise<void>
|
|
82
81
|
|
|
83
82
|
constructor({
|
|
@@ -582,21 +581,19 @@ class FeatureFlagsPoller {
|
|
|
582
581
|
}
|
|
583
582
|
|
|
584
583
|
async loadFeatureFlags(forceReload = false): Promise<void> {
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
this.hasAttemptedCacheLoad = true
|
|
588
|
-
await this.loadFromCache('Loaded flags from cache')
|
|
584
|
+
if (this.loadedSuccessfullyOnce && !forceReload) {
|
|
585
|
+
return
|
|
589
586
|
}
|
|
590
587
|
|
|
591
|
-
|
|
592
|
-
if (this.loadingPromise) {
|
|
593
|
-
return this.loadingPromise
|
|
594
|
-
}
|
|
595
|
-
|
|
596
|
-
if (!this.loadedSuccessfullyOnce || forceReload) {
|
|
588
|
+
if (!this.loadingPromise) {
|
|
597
589
|
this.loadingPromise = this._loadFeatureFlags()
|
|
598
|
-
|
|
590
|
+
.catch((err) => this.logMsgIfDebug(() => console.debug(`[FEATURE FLAGS] Failed to load feature flags: ${err}`)))
|
|
591
|
+
.finally(() => {
|
|
592
|
+
this.loadingPromise = undefined
|
|
593
|
+
})
|
|
599
594
|
}
|
|
595
|
+
|
|
596
|
+
return this.loadingPromise
|
|
600
597
|
}
|
|
601
598
|
|
|
602
599
|
/**
|
|
@@ -627,7 +624,7 @@ class FeatureFlagsPoller {
|
|
|
627
624
|
this.poller = undefined
|
|
628
625
|
}
|
|
629
626
|
|
|
630
|
-
this.poller = setTimeout(() => this.
|
|
627
|
+
this.poller = setTimeout(() => this.loadFeatureFlags(true), this.getPollingInterval())
|
|
631
628
|
|
|
632
629
|
try {
|
|
633
630
|
let shouldFetch = true
|
|
@@ -764,8 +761,6 @@ class FeatureFlagsPoller {
|
|
|
764
761
|
if (err instanceof ClientError) {
|
|
765
762
|
this.onError?.(err)
|
|
766
763
|
}
|
|
767
|
-
} finally {
|
|
768
|
-
this.loadingPromise = undefined
|
|
769
764
|
}
|
|
770
765
|
}
|
|
771
766
|
|
package/src/types.ts
CHANGED
|
@@ -5,23 +5,25 @@ import type {
|
|
|
5
5
|
PostHogFetchOptions,
|
|
6
6
|
PostHogFetchResponse,
|
|
7
7
|
} from '@posthog/core'
|
|
8
|
+
import { ContextData, ContextOptions } from './extensions/context/types'
|
|
8
9
|
|
|
9
10
|
import type { FlagDefinitionCacheProvider } from './extensions/feature-flags/cache'
|
|
10
11
|
|
|
11
|
-
export
|
|
12
|
+
export type IdentifyMessage = {
|
|
12
13
|
distinctId: string
|
|
13
14
|
properties?: Record<string | number, any>
|
|
14
15
|
disableGeoip?: boolean
|
|
15
16
|
}
|
|
16
17
|
|
|
17
|
-
export
|
|
18
|
+
export type SendFeatureFlagsOptions = {
|
|
18
19
|
onlyEvaluateLocally?: boolean
|
|
19
20
|
personProperties?: Record<string, any>
|
|
20
21
|
groupProperties?: Record<string, Record<string, any>>
|
|
21
22
|
flagKeys?: string[]
|
|
22
23
|
}
|
|
23
24
|
|
|
24
|
-
export
|
|
25
|
+
export type EventMessage = Omit<IdentifyMessage, 'distinctId'> & {
|
|
26
|
+
distinctId?: string // Optional - can be provided via context
|
|
25
27
|
event: string
|
|
26
28
|
groups?: Record<string, string | number> // Mapping of group type to group id
|
|
27
29
|
sendFeatureFlags?: boolean | SendFeatureFlagsOptions
|
|
@@ -29,7 +31,7 @@ export interface EventMessage extends IdentifyMessage {
|
|
|
29
31
|
uuid?: string
|
|
30
32
|
}
|
|
31
33
|
|
|
32
|
-
export
|
|
34
|
+
export type GroupIdentifyMessage = {
|
|
33
35
|
groupType: string
|
|
34
36
|
groupKey: string // Unique identifier for the group
|
|
35
37
|
properties?: Record<string | number, any>
|
|
@@ -335,6 +337,21 @@ export interface IPostHog {
|
|
|
335
337
|
*/
|
|
336
338
|
reloadFeatureFlags(): Promise<void>
|
|
337
339
|
|
|
340
|
+
/**
|
|
341
|
+
* @description Run a function with specific context that will be applied to all events captured within that context.
|
|
342
|
+
* @param data Context data to apply (sessionId, distinctId, properties, enableExceptionAutocapture)
|
|
343
|
+
* @param fn Function to run with the context
|
|
344
|
+
* @param options Context options (fresh)
|
|
345
|
+
* @returns The return value of the function
|
|
346
|
+
*/
|
|
347
|
+
withContext<T>(data: Partial<ContextData>, fn: () => T, options?: ContextOptions): T
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* @description Get the current context data.
|
|
351
|
+
* @returns The current context data, or undefined if no context is set
|
|
352
|
+
*/
|
|
353
|
+
getContext(): ContextData | undefined
|
|
354
|
+
|
|
338
355
|
/**
|
|
339
356
|
* @description Flushes the events still in the queue and clears the feature flags poller to allow for
|
|
340
357
|
* a clean shutdown.
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '5.
|
|
1
|
+
export const version = '5.16.0'
|