posthog-node 4.3.0 → 4.3.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 +4 -0
- package/lib/index.cjs.js +55 -29
- package/lib/index.cjs.js.map +1 -1
- package/lib/index.esm.js +55 -29
- package/lib/index.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/posthog-node.ts +51 -30
- package/test/posthog-node.spec.ts +35 -2
package/package.json
CHANGED
package/src/posthog-node.ts
CHANGED
|
@@ -294,59 +294,80 @@ export class PostHog extends PostHogCoreStateless implements PostHogNodeV1 {
|
|
|
294
294
|
disableGeoip?: boolean
|
|
295
295
|
}
|
|
296
296
|
): Promise<JsonType | undefined> {
|
|
297
|
-
const { groups, disableGeoip } = options || {}
|
|
298
|
-
let { onlyEvaluateLocally, sendFeatureFlagEvents, personProperties, groupProperties } = options || {}
|
|
297
|
+
const { groups, disableGeoip, onlyEvaluateLocally = false, personProperties, groupProperties } = options || {}
|
|
299
298
|
|
|
300
|
-
const
|
|
299
|
+
const { allPersonProperties, allGroupProperties } = this.addLocalPersonAndGroupProperties(
|
|
301
300
|
distinctId,
|
|
302
301
|
groups,
|
|
303
302
|
personProperties,
|
|
304
303
|
groupProperties
|
|
305
304
|
)
|
|
306
305
|
|
|
307
|
-
|
|
308
|
-
groupProperties = adjustedProperties.allGroupProperties
|
|
309
|
-
|
|
310
|
-
let response = undefined
|
|
311
|
-
|
|
312
|
-
// Try to get match value locally if not provided
|
|
313
|
-
if (!matchValue) {
|
|
306
|
+
if (matchValue === undefined) {
|
|
314
307
|
matchValue = await this.getFeatureFlag(key, distinctId, {
|
|
315
308
|
...options,
|
|
316
309
|
onlyEvaluateLocally: true,
|
|
310
|
+
sendFeatureFlagEvents: false,
|
|
317
311
|
})
|
|
318
312
|
}
|
|
319
313
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
}
|
|
314
|
+
let response: string | boolean | undefined
|
|
315
|
+
let payload: JsonType | undefined
|
|
323
316
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
|
|
317
|
+
if (matchValue) {
|
|
318
|
+
response = matchValue
|
|
319
|
+
payload = await this.featureFlagsPoller?.computeFeatureFlagPayloadLocally(key, matchValue)
|
|
320
|
+
} else {
|
|
321
|
+
response = undefined
|
|
322
|
+
payload = undefined
|
|
330
323
|
}
|
|
331
324
|
|
|
332
|
-
//
|
|
333
|
-
|
|
334
|
-
onlyEvaluateLocally = false
|
|
335
|
-
}
|
|
325
|
+
// Determine if the payload was evaluated locally
|
|
326
|
+
const payloadWasLocallyEvaluated = payload !== undefined
|
|
336
327
|
|
|
337
|
-
|
|
328
|
+
// Fetch final flags and payloads either locally or from the remote server
|
|
329
|
+
let fetchedOrLocalFlags: Record<string, string | boolean> | undefined
|
|
330
|
+
let fetchedOrLocalPayloads: Record<string, JsonType | undefined> | undefined
|
|
338
331
|
|
|
339
|
-
if (
|
|
340
|
-
response
|
|
341
|
-
key
|
|
332
|
+
if (payloadWasLocallyEvaluated || onlyEvaluateLocally) {
|
|
333
|
+
if (response !== undefined) {
|
|
334
|
+
fetchedOrLocalFlags = { [key]: response }
|
|
335
|
+
fetchedOrLocalPayloads = { [key]: payload }
|
|
336
|
+
} else {
|
|
337
|
+
fetchedOrLocalFlags = {}
|
|
338
|
+
fetchedOrLocalPayloads = {}
|
|
339
|
+
}
|
|
340
|
+
} else {
|
|
341
|
+
const fetchedData = await super.getFeatureFlagsAndPayloadsStateless(
|
|
342
342
|
distinctId,
|
|
343
343
|
groups,
|
|
344
|
-
|
|
345
|
-
|
|
344
|
+
allPersonProperties,
|
|
345
|
+
allGroupProperties,
|
|
346
346
|
disableGeoip
|
|
347
347
|
)
|
|
348
|
+
fetchedOrLocalFlags = fetchedData.flags || {}
|
|
349
|
+
fetchedOrLocalPayloads = fetchedData.payloads || {}
|
|
348
350
|
}
|
|
349
|
-
|
|
351
|
+
|
|
352
|
+
const finalResponse = fetchedOrLocalFlags[key]
|
|
353
|
+
const finalPayload = fetchedOrLocalPayloads[key]
|
|
354
|
+
const finalLocallyEvaluated = payloadWasLocallyEvaluated
|
|
355
|
+
|
|
356
|
+
this.capture({
|
|
357
|
+
distinctId,
|
|
358
|
+
event: '$feature_flag_called',
|
|
359
|
+
properties: {
|
|
360
|
+
$feature_flag: key,
|
|
361
|
+
$feature_flag_response: finalResponse,
|
|
362
|
+
$feature_flag_payload: finalPayload,
|
|
363
|
+
locally_evaluated: finalLocallyEvaluated,
|
|
364
|
+
[`$feature/${key}`]: finalResponse,
|
|
365
|
+
},
|
|
366
|
+
groups,
|
|
367
|
+
disableGeoip,
|
|
368
|
+
})
|
|
369
|
+
|
|
370
|
+
return finalPayload
|
|
350
371
|
}
|
|
351
372
|
|
|
352
373
|
async isFeatureEnabled(
|
|
@@ -897,13 +897,18 @@ describe('PostHog Node.js', () => {
|
|
|
897
897
|
rollout_percentage: 100,
|
|
898
898
|
},
|
|
899
899
|
],
|
|
900
|
+
payloads: { true: { variant: 'A' } },
|
|
900
901
|
},
|
|
901
902
|
},
|
|
902
903
|
],
|
|
903
904
|
}
|
|
904
905
|
|
|
905
906
|
mockedFetch.mockImplementation(
|
|
906
|
-
apiImplementation({
|
|
907
|
+
apiImplementation({
|
|
908
|
+
localFlags: flags,
|
|
909
|
+
decideFlags: { 'decide-flag': 'decide-value' },
|
|
910
|
+
decideFlagPayloads: { 'beta-feature': { variant: 'A' } },
|
|
911
|
+
})
|
|
907
912
|
)
|
|
908
913
|
|
|
909
914
|
posthog = new PostHog('TEST_API_KEY', {
|
|
@@ -945,6 +950,34 @@ describe('PostHog Node.js', () => {
|
|
|
945
950
|
)
|
|
946
951
|
mockedFetch.mockClear()
|
|
947
952
|
|
|
953
|
+
expect(
|
|
954
|
+
await posthog.getFeatureFlagPayload('beta-feature', 'some-distinct-id', undefined, {
|
|
955
|
+
personProperties: { region: 'USA', name: 'Aloha' },
|
|
956
|
+
})
|
|
957
|
+
).toEqual({ variant: 'A' })
|
|
958
|
+
|
|
959
|
+
// TRICKY: There's now an extra step before events are queued, so need to wait for that to resolve
|
|
960
|
+
jest.runOnlyPendingTimers()
|
|
961
|
+
await waitForPromises()
|
|
962
|
+
await posthog.flush()
|
|
963
|
+
|
|
964
|
+
expect(mockedFetch).toHaveBeenCalledWith('http://example.com/batch/', expect.any(Object))
|
|
965
|
+
|
|
966
|
+
expect(getLastBatchEvents()?.[0]).toEqual(
|
|
967
|
+
expect.objectContaining({
|
|
968
|
+
distinct_id: 'some-distinct-id',
|
|
969
|
+
event: '$feature_flag_called',
|
|
970
|
+
properties: expect.objectContaining({
|
|
971
|
+
$feature_flag: 'beta-feature',
|
|
972
|
+
$feature_flag_response: true,
|
|
973
|
+
$feature_flag_payload: { variant: 'A' },
|
|
974
|
+
locally_evaluated: true,
|
|
975
|
+
[`$feature/${'beta-feature'}`]: true,
|
|
976
|
+
}),
|
|
977
|
+
})
|
|
978
|
+
)
|
|
979
|
+
mockedFetch.mockClear()
|
|
980
|
+
|
|
948
981
|
// # called again for same user, shouldn't call capture again
|
|
949
982
|
expect(
|
|
950
983
|
await posthog.getFeatureFlag('beta-feature', 'some-distinct-id', {
|
|
@@ -1081,7 +1114,7 @@ describe('PostHog Node.js', () => {
|
|
|
1081
1114
|
expect(mockedFetch).toHaveBeenCalledTimes(0)
|
|
1082
1115
|
|
|
1083
1116
|
await expect(posthog.getFeatureFlagPayload('false-flag', '123', true)).resolves.toEqual(300)
|
|
1084
|
-
expect(mockedFetch).toHaveBeenCalledTimes(
|
|
1117
|
+
expect(mockedFetch).toHaveBeenCalledTimes(1) // this now calls the server, because in this case the flag is not locally evaluated but we have a payload that we need to calculate
|
|
1085
1118
|
})
|
|
1086
1119
|
|
|
1087
1120
|
it('should not double parse json with getFeatureFlagPayloads and server eval', async () => {
|