posthog-node 3.1.3 → 3.2.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/CHANGELOG.md +9 -0
- package/lib/index.cjs.js +111 -74
- package/lib/index.cjs.js.map +1 -1
- package/lib/index.esm.js +111 -70
- package/lib/index.esm.js.map +1 -1
- package/lib/posthog-core/src/index.d.ts +10 -0
- package/lib/posthog-node/src/feature-flags.d.ts +2 -0
- package/lib/posthog-node/src/fetch.d.ts +11 -1
- package/package.json +2 -2
- package/src/feature-flags.ts +6 -3
- package/src/fetch.ts +38 -17
- package/src/posthog-node.ts +4 -1
- package/test/feature-flags.spec.ts +2 -2
- package/test/posthog-node.spec.ts +2 -2
|
@@ -117,9 +117,19 @@ export declare abstract class PostHogCore extends PostHogCoreStateless {
|
|
|
117
117
|
/***
|
|
118
118
|
* PROPERTIES
|
|
119
119
|
***/
|
|
120
|
+
setPersonPropertiesForFlags(properties: {
|
|
121
|
+
[type: string]: string;
|
|
122
|
+
}): this;
|
|
123
|
+
resetPersonPropertiesForFlags(): void;
|
|
124
|
+
/** @deprecated - Renamed to setPersonPropertiesForFlags */
|
|
120
125
|
personProperties(properties: {
|
|
121
126
|
[type: string]: string;
|
|
122
127
|
}): this;
|
|
128
|
+
setGroupPropertiesForFlags(properties: {
|
|
129
|
+
[type: string]: Record<string, string>;
|
|
130
|
+
}): this;
|
|
131
|
+
resetGroupPropertiesForFlags(): void;
|
|
132
|
+
/** @deprecated - Renamed to setGroupPropertiesForFlags */
|
|
123
133
|
groupProperties(properties: {
|
|
124
134
|
[type: string]: Record<string, string>;
|
|
125
135
|
}): this;
|
|
@@ -14,6 +14,7 @@ declare type FeatureFlagsPollerOptions = {
|
|
|
14
14
|
pollingInterval: number;
|
|
15
15
|
timeout?: number;
|
|
16
16
|
fetch?: (url: string, options: PostHogFetchOptions) => Promise<PostHogFetchResponse>;
|
|
17
|
+
onError?: (error: Error) => void;
|
|
17
18
|
};
|
|
18
19
|
declare class FeatureFlagsPoller {
|
|
19
20
|
pollingInterval: number;
|
|
@@ -29,6 +30,7 @@ declare class FeatureFlagsPoller {
|
|
|
29
30
|
poller?: NodeJS.Timeout;
|
|
30
31
|
fetch: (url: string, options: PostHogFetchOptions) => Promise<PostHogFetchResponse>;
|
|
31
32
|
debugMode: boolean;
|
|
33
|
+
onError?: (error: Error) => void;
|
|
32
34
|
constructor({ pollingInterval, personalApiKey, projectApiKey, timeout, host, ...options }: FeatureFlagsPollerOptions);
|
|
33
35
|
debug(enabled?: boolean): void;
|
|
34
36
|
getFeatureFlag(key: string, distinctId: string, groups?: Record<string, string>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>): Promise<string | boolean | undefined>;
|
|
@@ -1,2 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fetch wrapper
|
|
3
|
+
*
|
|
4
|
+
* We want to polyfill fetch when not available with axios but use it when it is.
|
|
5
|
+
* NOTE: The current version of Axios has an issue when in non-node environments like Clouflare Workers.
|
|
6
|
+
* This is currently solved by using the global fetch if available instead.
|
|
7
|
+
* See https://github.com/PostHog/posthog-js-lite/issues/127 for more info
|
|
8
|
+
*/
|
|
1
9
|
import { PostHogFetchOptions, PostHogFetchResponse } from 'posthog-core/src';
|
|
2
|
-
|
|
10
|
+
declare type FetchLike = (url: string, options: PostHogFetchOptions) => Promise<PostHogFetchResponse>;
|
|
11
|
+
declare const _default: FetchLike;
|
|
12
|
+
export default _default;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "posthog-node",
|
|
3
|
-
"version": "3.1
|
|
3
|
+
"version": "3.2.1",
|
|
4
4
|
"description": "PostHog Node.js integration",
|
|
5
5
|
"repository": "PostHog/posthog-node",
|
|
6
6
|
"scripts": {
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"module": "lib/index.esm.js",
|
|
20
20
|
"types": "lib/index.d.ts",
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"axios": "^1.6.
|
|
22
|
+
"axios": "^1.6.2",
|
|
23
23
|
"rusha": "^0.8.14"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
package/src/feature-flags.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { FeatureFlagCondition, FlagProperty, PostHogFeatureFlag, PropertyGroup }
|
|
|
3
3
|
import { version } from '../package.json'
|
|
4
4
|
import { JsonType, PostHogFetchOptions, PostHogFetchResponse } from 'posthog-core/src'
|
|
5
5
|
import { safeSetTimeout } from 'posthog-core/src/utils'
|
|
6
|
-
import
|
|
6
|
+
import fetch from './fetch'
|
|
7
7
|
|
|
8
8
|
// eslint-disable-next-line
|
|
9
9
|
const LONG_SCALE = 0xfffffffffffffff
|
|
@@ -37,6 +37,7 @@ type FeatureFlagsPollerOptions = {
|
|
|
37
37
|
pollingInterval: number
|
|
38
38
|
timeout?: number
|
|
39
39
|
fetch?: (url: string, options: PostHogFetchOptions) => Promise<PostHogFetchResponse>
|
|
40
|
+
onError?: (error: Error) => void
|
|
40
41
|
}
|
|
41
42
|
|
|
42
43
|
class FeatureFlagsPoller {
|
|
@@ -53,6 +54,7 @@ class FeatureFlagsPoller {
|
|
|
53
54
|
poller?: NodeJS.Timeout
|
|
54
55
|
fetch: (url: string, options: PostHogFetchOptions) => Promise<PostHogFetchResponse>
|
|
55
56
|
debugMode: boolean = false
|
|
57
|
+
onError?: (error: Error) => void
|
|
56
58
|
|
|
57
59
|
constructor({
|
|
58
60
|
pollingInterval,
|
|
@@ -75,6 +77,7 @@ class FeatureFlagsPoller {
|
|
|
75
77
|
this.poller = undefined
|
|
76
78
|
// NOTE: as any is required here as the AbortSignal typing is slightly misaligned but works just fine
|
|
77
79
|
this.fetch = options.fetch || fetch
|
|
80
|
+
this.onError = options.onError
|
|
78
81
|
|
|
79
82
|
void this.loadFeatureFlags()
|
|
80
83
|
}
|
|
@@ -177,7 +180,7 @@ class FeatureFlagsPoller {
|
|
|
177
180
|
if (e instanceof InconclusiveMatchError) {
|
|
178
181
|
// do nothing
|
|
179
182
|
} else if (e instanceof Error) {
|
|
180
|
-
|
|
183
|
+
this.onError?.(new Error(`Error computing flag locally: ${flag.key}: ${e}`))
|
|
181
184
|
}
|
|
182
185
|
fallbackToDecide = true
|
|
183
186
|
}
|
|
@@ -395,7 +398,7 @@ class FeatureFlagsPoller {
|
|
|
395
398
|
// if an error that is not an instance of ClientError is thrown
|
|
396
399
|
// we silently ignore the error when reloading feature flags
|
|
397
400
|
if (err instanceof ClientError) {
|
|
398
|
-
|
|
401
|
+
this.onError?.(err)
|
|
399
402
|
}
|
|
400
403
|
}
|
|
401
404
|
}
|
package/src/fetch.ts
CHANGED
|
@@ -1,22 +1,43 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Fetch wrapper
|
|
3
|
+
*
|
|
4
|
+
* We want to polyfill fetch when not available with axios but use it when it is.
|
|
5
|
+
* NOTE: The current version of Axios has an issue when in non-node environments like Clouflare Workers.
|
|
6
|
+
* This is currently solved by using the global fetch if available instead.
|
|
7
|
+
* See https://github.com/PostHog/posthog-js-lite/issues/127 for more info
|
|
8
|
+
*/
|
|
9
|
+
|
|
2
10
|
import { PostHogFetchOptions, PostHogFetchResponse } from 'posthog-core/src'
|
|
3
11
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
validateStatus: () => true,
|
|
15
|
-
})
|
|
12
|
+
type FetchLike = (url: string, options: PostHogFetchOptions) => Promise<PostHogFetchResponse>
|
|
13
|
+
|
|
14
|
+
let _fetch: FetchLike | undefined =
|
|
15
|
+
// eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error
|
|
16
|
+
// @ts-ignore
|
|
17
|
+
typeof fetch !== 'undefined' ? fetch : typeof global.fetch !== 'undefined' ? global.fetch : undefined
|
|
18
|
+
|
|
19
|
+
if (!_fetch) {
|
|
20
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
21
|
+
const axios = require('axios')
|
|
16
22
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
23
|
+
_fetch = async (url: string, options: PostHogFetchOptions): Promise<PostHogFetchResponse> => {
|
|
24
|
+
const res = await axios.request({
|
|
25
|
+
url,
|
|
26
|
+
headers: options.headers,
|
|
27
|
+
method: options.method.toLowerCase(),
|
|
28
|
+
data: options.body,
|
|
29
|
+
signal: options.signal,
|
|
30
|
+
// fetch only throws on network errors, not on HTTP errors
|
|
31
|
+
validateStatus: () => true,
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
status: res.status,
|
|
36
|
+
text: async () => res.data,
|
|
37
|
+
json: async () => res.data,
|
|
38
|
+
}
|
|
21
39
|
}
|
|
22
40
|
}
|
|
41
|
+
|
|
42
|
+
// NOTE: We have to export this as default, even though we prefer named exports as we are relying on detecting "fetch" in the global scope
|
|
43
|
+
export default _fetch as FetchLike
|
package/src/posthog-node.ts
CHANGED
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
import { PostHogMemoryStorage } from '../../posthog-core/src/storage-memory'
|
|
13
13
|
import { EventMessageV1, GroupIdentifyMessage, IdentifyMessageV1, PostHogNodeV1 } from './types'
|
|
14
14
|
import { FeatureFlagsPoller } from './feature-flags'
|
|
15
|
-
import
|
|
15
|
+
import fetch from './fetch'
|
|
16
16
|
|
|
17
17
|
export type PostHogOptions = PosthogCoreOptions & {
|
|
18
18
|
persistence?: 'memory'
|
|
@@ -56,6 +56,9 @@ export class PostHog extends PostHogCoreStateless implements PostHogNodeV1 {
|
|
|
56
56
|
timeout: options.requestTimeout ?? 10000, // 10 seconds
|
|
57
57
|
host: this.host,
|
|
58
58
|
fetch: options.fetch,
|
|
59
|
+
onError: (err: Error) => {
|
|
60
|
+
this._events.emit('error', err)
|
|
61
|
+
},
|
|
59
62
|
})
|
|
60
63
|
}
|
|
61
64
|
this.distinctIdHasSentFlagCalls = {}
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
import { PostHog as PostHog, PostHogOptions } from '../src/posthog-node'
|
|
4
4
|
import { matchProperty, InconclusiveMatchError } from '../src/feature-flags'
|
|
5
5
|
jest.mock('../src/fetch')
|
|
6
|
-
import
|
|
6
|
+
import fetch from '../src/fetch'
|
|
7
7
|
|
|
8
|
-
jest.spyOn(
|
|
8
|
+
jest.spyOn(console, 'debug').mockImplementation()
|
|
9
9
|
|
|
10
10
|
const mockedFetch = jest.mocked(fetch, true)
|
|
11
11
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// import { PostHog } from '../'
|
|
2
2
|
import { PostHog as PostHog } from '../src/posthog-node'
|
|
3
3
|
jest.mock('../src/fetch')
|
|
4
|
-
import
|
|
4
|
+
import fetch from '../src/fetch'
|
|
5
5
|
import { anyDecideCall, anyLocalEvalCall, apiImplementation } from './feature-flags.spec'
|
|
6
6
|
import { waitForPromises, wait } from '../../posthog-core/test/test-utils/test-utils'
|
|
7
7
|
|
|
@@ -295,7 +295,7 @@ describe('PostHog Node.js', () => {
|
|
|
295
295
|
flushAt: 1,
|
|
296
296
|
})
|
|
297
297
|
|
|
298
|
-
const logSpy = jest.spyOn(
|
|
298
|
+
const logSpy = jest.spyOn(console, 'log').mockImplementation(() => {})
|
|
299
299
|
jest.useRealTimers()
|
|
300
300
|
// using debug mode to check console.log output
|
|
301
301
|
// which tells us when the flush is complete
|