posthog-node 3.3.0 → 3.4.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/CHANGELOG.md +5 -0
- package/lib/index.cjs.js +105 -14
- package/lib/index.cjs.js.map +1 -1
- package/lib/index.esm.js +105 -14
- package/lib/index.esm.js.map +1 -1
- package/lib/posthog-node/src/feature-flags.d.ts +2 -1
- package/package.json +1 -1
- package/src/feature-flags.ts +106 -13
- package/test/feature-flags.spec.ts +256 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
# 3.4.0 - 2024-01-09
|
|
2
|
+
|
|
3
|
+
1. Numeric property handling for feature flags now does the expected: When passed in a number, we do a numeric comparison. When passed in a string, we do a string comparison. Previously, we always did a string comparison.
|
|
4
|
+
2. Add support for relative date operators for local evaluation.
|
|
5
|
+
|
|
1
6
|
# 3.3.0 - 2024-01-02
|
|
2
7
|
|
|
3
8
|
1. Adds PostHogSentryIntegration to allow automatic capturing of exceptions reported via the @sentry/node package
|
package/lib/index.cjs.js
CHANGED
|
@@ -158,7 +158,7 @@ function __spreadArray(to, from, pack) {
|
|
|
158
158
|
return to.concat(ar || Array.prototype.slice.call(from));
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
-
var version = "3.
|
|
161
|
+
var version = "3.4.0";
|
|
162
162
|
|
|
163
163
|
var PostHogPersistedProperty;
|
|
164
164
|
(function (PostHogPersistedProperty) {
|
|
@@ -2348,12 +2348,36 @@ function matchProperty(property, propertyValues) {
|
|
|
2348
2348
|
|
|
2349
2349
|
var overrideValue = propertyValues[key];
|
|
2350
2350
|
|
|
2351
|
+
function computeExactMatch(value, overrideValue) {
|
|
2352
|
+
if (Array.isArray(value)) {
|
|
2353
|
+
return value.map(function (val) {
|
|
2354
|
+
return String(val).toLowerCase();
|
|
2355
|
+
}).includes(String(overrideValue).toLowerCase());
|
|
2356
|
+
}
|
|
2357
|
+
|
|
2358
|
+
return String(value).toLowerCase() === String(overrideValue).toLowerCase();
|
|
2359
|
+
}
|
|
2360
|
+
|
|
2361
|
+
function compare(lhs, rhs, operator) {
|
|
2362
|
+
if (operator === 'gt') {
|
|
2363
|
+
return lhs > rhs;
|
|
2364
|
+
} else if (operator === 'gte') {
|
|
2365
|
+
return lhs >= rhs;
|
|
2366
|
+
} else if (operator === 'lt') {
|
|
2367
|
+
return lhs < rhs;
|
|
2368
|
+
} else if (operator === 'lte') {
|
|
2369
|
+
return lhs <= rhs;
|
|
2370
|
+
} else {
|
|
2371
|
+
throw new Error("Invalid operator: ".concat(operator));
|
|
2372
|
+
}
|
|
2373
|
+
}
|
|
2374
|
+
|
|
2351
2375
|
switch (operator) {
|
|
2352
2376
|
case 'exact':
|
|
2353
|
-
return
|
|
2377
|
+
return computeExactMatch(value, overrideValue);
|
|
2354
2378
|
|
|
2355
2379
|
case 'is_not':
|
|
2356
|
-
return
|
|
2380
|
+
return !computeExactMatch(value, overrideValue);
|
|
2357
2381
|
|
|
2358
2382
|
case 'is_set':
|
|
2359
2383
|
return key in propertyValues;
|
|
@@ -2371,24 +2395,53 @@ function matchProperty(property, propertyValues) {
|
|
|
2371
2395
|
return isValidRegex(String(value)) && String(overrideValue).match(String(value)) === null;
|
|
2372
2396
|
|
|
2373
2397
|
case 'gt':
|
|
2374
|
-
return typeof overrideValue == typeof value && overrideValue > value;
|
|
2375
|
-
|
|
2376
2398
|
case 'gte':
|
|
2377
|
-
return typeof overrideValue == typeof value && overrideValue >= value;
|
|
2378
|
-
|
|
2379
2399
|
case 'lt':
|
|
2380
|
-
return typeof overrideValue == typeof value && overrideValue < value;
|
|
2381
|
-
|
|
2382
2400
|
case 'lte':
|
|
2383
|
-
|
|
2401
|
+
{
|
|
2402
|
+
// :TRICKY: We adjust comparison based on the override value passed in,
|
|
2403
|
+
// to make sure we handle both numeric and string comparisons appropriately.
|
|
2404
|
+
var parsedValue = typeof value === 'number' ? value : null;
|
|
2405
|
+
|
|
2406
|
+
if (typeof value === 'string') {
|
|
2407
|
+
try {
|
|
2408
|
+
parsedValue = parseFloat(value);
|
|
2409
|
+
} catch (err) {// pass
|
|
2410
|
+
}
|
|
2411
|
+
}
|
|
2412
|
+
|
|
2413
|
+
if (parsedValue != null && overrideValue != null) {
|
|
2414
|
+
// check both null and undefined
|
|
2415
|
+
if (typeof overrideValue === 'string') {
|
|
2416
|
+
return compare(overrideValue, String(value), operator);
|
|
2417
|
+
} else {
|
|
2418
|
+
return compare(overrideValue, parsedValue, operator);
|
|
2419
|
+
}
|
|
2420
|
+
} else {
|
|
2421
|
+
return compare(String(overrideValue), String(value), operator);
|
|
2422
|
+
}
|
|
2423
|
+
}
|
|
2384
2424
|
|
|
2385
2425
|
case 'is_date_after':
|
|
2386
2426
|
case 'is_date_before':
|
|
2427
|
+
case 'is_relative_date_before':
|
|
2428
|
+
case 'is_relative_date_after':
|
|
2387
2429
|
{
|
|
2388
|
-
var parsedDate =
|
|
2430
|
+
var parsedDate = null;
|
|
2431
|
+
|
|
2432
|
+
if (['is_relative_date_before', 'is_relative_date_after'].includes(operator)) {
|
|
2433
|
+
parsedDate = relativeDateParseForFeatureFlagMatching(String(value));
|
|
2434
|
+
} else {
|
|
2435
|
+
parsedDate = convertToDateTime(value);
|
|
2436
|
+
}
|
|
2437
|
+
|
|
2438
|
+
if (parsedDate == null) {
|
|
2439
|
+
throw new InconclusiveMatchError("Invalid date: ".concat(value));
|
|
2440
|
+
}
|
|
2441
|
+
|
|
2389
2442
|
var overrideDate = convertToDateTime(overrideValue);
|
|
2390
2443
|
|
|
2391
|
-
if (
|
|
2444
|
+
if (['is_date_before', 'is_relative_date_before'].includes(operator)) {
|
|
2392
2445
|
return overrideDate < parsedDate;
|
|
2393
2446
|
}
|
|
2394
2447
|
|
|
@@ -2396,8 +2449,7 @@ function matchProperty(property, propertyValues) {
|
|
|
2396
2449
|
}
|
|
2397
2450
|
|
|
2398
2451
|
default:
|
|
2399
|
-
|
|
2400
|
-
return false;
|
|
2452
|
+
throw new InconclusiveMatchError("Unknown operator: ".concat(operator));
|
|
2401
2453
|
}
|
|
2402
2454
|
}
|
|
2403
2455
|
|
|
@@ -2539,6 +2591,45 @@ function convertToDateTime(value) {
|
|
|
2539
2591
|
}
|
|
2540
2592
|
}
|
|
2541
2593
|
|
|
2594
|
+
function relativeDateParseForFeatureFlagMatching(value) {
|
|
2595
|
+
var regex = /^(?<number>[0-9]+)(?<interval>[a-z])$/;
|
|
2596
|
+
var match = value.match(regex);
|
|
2597
|
+
var parsedDt = new Date(new Date().toISOString());
|
|
2598
|
+
|
|
2599
|
+
if (match) {
|
|
2600
|
+
if (!match.groups) {
|
|
2601
|
+
return null;
|
|
2602
|
+
}
|
|
2603
|
+
|
|
2604
|
+
var number = parseInt(match.groups['number']);
|
|
2605
|
+
|
|
2606
|
+
if (number >= 10000) {
|
|
2607
|
+
// Guard against overflow, disallow numbers greater than 10_000
|
|
2608
|
+
return null;
|
|
2609
|
+
}
|
|
2610
|
+
|
|
2611
|
+
var interval = match.groups['interval'];
|
|
2612
|
+
|
|
2613
|
+
if (interval == 'h') {
|
|
2614
|
+
parsedDt.setUTCHours(parsedDt.getUTCHours() - number);
|
|
2615
|
+
} else if (interval == 'd') {
|
|
2616
|
+
parsedDt.setUTCDate(parsedDt.getUTCDate() - number);
|
|
2617
|
+
} else if (interval == 'w') {
|
|
2618
|
+
parsedDt.setUTCDate(parsedDt.getUTCDate() - number * 7);
|
|
2619
|
+
} else if (interval == 'm') {
|
|
2620
|
+
parsedDt.setUTCMonth(parsedDt.getUTCMonth() - number);
|
|
2621
|
+
} else if (interval == 'y') {
|
|
2622
|
+
parsedDt.setUTCFullYear(parsedDt.getUTCFullYear() - number);
|
|
2623
|
+
} else {
|
|
2624
|
+
return null;
|
|
2625
|
+
}
|
|
2626
|
+
|
|
2627
|
+
return parsedDt;
|
|
2628
|
+
} else {
|
|
2629
|
+
return null;
|
|
2630
|
+
}
|
|
2631
|
+
}
|
|
2632
|
+
|
|
2542
2633
|
var THIRTY_SECONDS = 30 * 1000;
|
|
2543
2634
|
var MAX_CACHE_SIZE = 50 * 1000; // The actual exported Nodejs API.
|
|
2544
2635
|
|