@naturalcycles/abba 1.15.1 → 1.15.3
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/types.d.ts +20 -2
- package/dist/types.js +20 -1
- package/dist/util.d.ts +3 -3
- package/dist/util.js +33 -22
- package/package.json +2 -2
- package/src/types.ts +26 -2
- package/src/util.ts +33 -19
package/dist/types.d.ts
CHANGED
|
@@ -49,9 +49,27 @@ export declare enum AssignmentStatus {
|
|
|
49
49
|
}
|
|
50
50
|
export interface SegmentationRule {
|
|
51
51
|
key: string;
|
|
52
|
-
operator:
|
|
53
|
-
value: string
|
|
52
|
+
operator: SegmentationRuleOperator;
|
|
53
|
+
value: string;
|
|
54
54
|
}
|
|
55
|
+
export declare enum SegmentationRuleOperator {
|
|
56
|
+
IsSet = "isSet",
|
|
57
|
+
IsNotSet = "isNotSet",
|
|
58
|
+
EqualsText = "equalsText",
|
|
59
|
+
NotEqualsText = "notEqualsText",
|
|
60
|
+
Semver = "semver",
|
|
61
|
+
Regex = "regex",
|
|
62
|
+
Boolean = "boolean",
|
|
63
|
+
/**
|
|
64
|
+
* @deprecated
|
|
65
|
+
*/
|
|
66
|
+
Equals = "==",
|
|
67
|
+
/**
|
|
68
|
+
* @deprecated
|
|
69
|
+
*/
|
|
70
|
+
NotEquals = "!="
|
|
71
|
+
}
|
|
72
|
+
export type SegmentationRuleFn = (segmentationProp: string | boolean | number | null | undefined, ruleValue: SegmentationRule['value']) => boolean;
|
|
55
73
|
export interface AssignmentStatistics {
|
|
56
74
|
sampled: number;
|
|
57
75
|
buckets: {
|
package/dist/types.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.AssignmentStatus = void 0;
|
|
3
|
+
exports.SegmentationRuleOperator = exports.AssignmentStatus = void 0;
|
|
4
4
|
var AssignmentStatus;
|
|
5
5
|
(function (AssignmentStatus) {
|
|
6
6
|
/**
|
|
@@ -16,3 +16,22 @@ var AssignmentStatus;
|
|
|
16
16
|
*/
|
|
17
17
|
AssignmentStatus[AssignmentStatus["Inactive"] = 3] = "Inactive";
|
|
18
18
|
})(AssignmentStatus = exports.AssignmentStatus || (exports.AssignmentStatus = {}));
|
|
19
|
+
var SegmentationRuleOperator;
|
|
20
|
+
(function (SegmentationRuleOperator) {
|
|
21
|
+
SegmentationRuleOperator["IsSet"] = "isSet";
|
|
22
|
+
SegmentationRuleOperator["IsNotSet"] = "isNotSet";
|
|
23
|
+
SegmentationRuleOperator["EqualsText"] = "equalsText";
|
|
24
|
+
SegmentationRuleOperator["NotEqualsText"] = "notEqualsText";
|
|
25
|
+
SegmentationRuleOperator["Semver"] = "semver";
|
|
26
|
+
SegmentationRuleOperator["Regex"] = "regex";
|
|
27
|
+
/* eslint-disable id-blacklist*/
|
|
28
|
+
SegmentationRuleOperator["Boolean"] = "boolean";
|
|
29
|
+
/**
|
|
30
|
+
* @deprecated
|
|
31
|
+
*/
|
|
32
|
+
SegmentationRuleOperator["Equals"] = "==";
|
|
33
|
+
/**
|
|
34
|
+
* @deprecated
|
|
35
|
+
*/
|
|
36
|
+
SegmentationRuleOperator["NotEquals"] = "!=";
|
|
37
|
+
})(SegmentationRuleOperator = exports.SegmentationRuleOperator || (exports.SegmentationRuleOperator = {}));
|
package/dist/util.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Saved } from '@naturalcycles/js-lib';
|
|
2
|
-
import { Bucket, ExclusionSet, Experiment, ExperimentWithBuckets, SegmentationData, SegmentationRule, UserAssignment } from './types';
|
|
2
|
+
import { Bucket, ExclusionSet, Experiment, ExperimentWithBuckets, SegmentationData, SegmentationRule, SegmentationRuleFn, SegmentationRuleOperator, UserAssignment } from './types';
|
|
3
3
|
/**
|
|
4
4
|
* Generate a new assignment for a given user.
|
|
5
5
|
* Doesn't save it.
|
|
@@ -30,9 +30,9 @@ export declare const validateTotalBucketRatio: (buckets: Bucket[]) => void;
|
|
|
30
30
|
*/
|
|
31
31
|
export declare const validateSegmentationRules: (rules: SegmentationRule[], segmentationData: SegmentationData) => boolean;
|
|
32
32
|
/**
|
|
33
|
-
*
|
|
33
|
+
* Map of segmentation rule validators
|
|
34
34
|
*/
|
|
35
|
-
export declare const
|
|
35
|
+
export declare const segmentationRuleMap: Record<SegmentationRuleOperator, SegmentationRuleFn>;
|
|
36
36
|
/**
|
|
37
37
|
* Returns true if an experiment is able to generate new assignments based on status and start/end dates
|
|
38
38
|
*/
|
package/dist/util.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getUserExclusionSet = exports.canGenerateNewAssignments = exports.
|
|
3
|
+
exports.getUserExclusionSet = exports.canGenerateNewAssignments = exports.segmentationRuleMap = exports.validateSegmentationRules = exports.validateTotalBucketRatio = exports.determineBucket = exports.determineAssignment = exports.rollDie = exports.generateUserAssignmentData = void 0;
|
|
4
4
|
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
5
5
|
const semver_1 = require("semver");
|
|
6
6
|
const types_1 = require("./types");
|
|
@@ -81,35 +81,46 @@ exports.validateTotalBucketRatio = validateTotalBucketRatio;
|
|
|
81
81
|
*/
|
|
82
82
|
const validateSegmentationRules = (rules, segmentationData) => {
|
|
83
83
|
for (const rule of rules) {
|
|
84
|
-
|
|
84
|
+
const { key, value, operator } = rule;
|
|
85
|
+
if (!exports.segmentationRuleMap[operator](segmentationData[key], value))
|
|
85
86
|
return false;
|
|
86
87
|
}
|
|
87
88
|
return true;
|
|
88
89
|
};
|
|
89
90
|
exports.validateSegmentationRules = validateSegmentationRules;
|
|
90
91
|
/**
|
|
91
|
-
*
|
|
92
|
+
* Map of segmentation rule validators
|
|
92
93
|
*/
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
94
|
+
exports.segmentationRuleMap = {
|
|
95
|
+
[types_1.SegmentationRuleOperator.IsSet](keyValue) {
|
|
96
|
+
return !!keyValue;
|
|
97
|
+
},
|
|
98
|
+
[types_1.SegmentationRuleOperator.IsNotSet](keyValue) {
|
|
99
|
+
return !keyValue;
|
|
100
|
+
},
|
|
101
|
+
[types_1.SegmentationRuleOperator.EqualsText](keyValue, ruleValue) {
|
|
102
|
+
return keyValue?.toString() === ruleValue.toString();
|
|
103
|
+
},
|
|
104
|
+
[types_1.SegmentationRuleOperator.NotEqualsText](keyValue, ruleValue) {
|
|
105
|
+
return keyValue?.toString() !== ruleValue.toString();
|
|
106
|
+
},
|
|
107
|
+
[types_1.SegmentationRuleOperator.Semver](keyValue, ruleValue) {
|
|
108
|
+
return (0, semver_1.satisfies)(keyValue?.toString() || '', ruleValue.toString());
|
|
109
|
+
},
|
|
110
|
+
[types_1.SegmentationRuleOperator.Regex](keyValue, ruleValue) {
|
|
111
|
+
return new RegExp(`${ruleValue}`).test(keyValue?.toString() || '');
|
|
112
|
+
},
|
|
113
|
+
[types_1.SegmentationRuleOperator.Boolean](keyValue, ruleValue) {
|
|
114
|
+
// If it's true, then must be true
|
|
115
|
+
if (ruleValue === 'true')
|
|
116
|
+
return keyValue === 'true';
|
|
117
|
+
// Anything else cannot be true
|
|
118
|
+
return keyValue !== 'true';
|
|
119
|
+
},
|
|
120
|
+
// Deprecated
|
|
121
|
+
[types_1.SegmentationRuleOperator.Equals]: (keyValue, ruleValue) => keyValue === ruleValue,
|
|
122
|
+
[types_1.SegmentationRuleOperator.NotEquals]: (keyValue, ruleValue) => keyValue !== ruleValue,
|
|
111
123
|
};
|
|
112
|
-
exports.validateSegmentationRule = validateSegmentationRule;
|
|
113
124
|
/**
|
|
114
125
|
* Returns true if an experiment is able to generate new assignments based on status and start/end dates
|
|
115
126
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@naturalcycles/abba",
|
|
3
|
-
"version": "1.15.
|
|
3
|
+
"version": "1.15.3",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"prepare": "husky install",
|
|
6
6
|
"build": "build",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
},
|
|
15
15
|
"devDependencies": {
|
|
16
16
|
"@naturalcycles/dev-lib": "^13.15.0",
|
|
17
|
-
"@types/node": "^
|
|
17
|
+
"@types/node": "^20.2.4",
|
|
18
18
|
"@types/semver": "^7.3.9",
|
|
19
19
|
"jest": "^29.3.1"
|
|
20
20
|
},
|
package/src/types.ts
CHANGED
|
@@ -60,10 +60,34 @@ export enum AssignmentStatus {
|
|
|
60
60
|
|
|
61
61
|
export interface SegmentationRule {
|
|
62
62
|
key: string
|
|
63
|
-
operator:
|
|
64
|
-
value: string
|
|
63
|
+
operator: SegmentationRuleOperator
|
|
64
|
+
value: string
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
+
export enum SegmentationRuleOperator {
|
|
68
|
+
IsSet = 'isSet',
|
|
69
|
+
IsNotSet = 'isNotSet',
|
|
70
|
+
EqualsText = 'equalsText',
|
|
71
|
+
NotEqualsText = 'notEqualsText',
|
|
72
|
+
Semver = 'semver',
|
|
73
|
+
Regex = 'regex',
|
|
74
|
+
/* eslint-disable id-blacklist*/
|
|
75
|
+
Boolean = 'boolean',
|
|
76
|
+
/**
|
|
77
|
+
* @deprecated
|
|
78
|
+
*/
|
|
79
|
+
Equals = '==',
|
|
80
|
+
/**
|
|
81
|
+
* @deprecated
|
|
82
|
+
*/
|
|
83
|
+
NotEquals = '!=',
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export type SegmentationRuleFn = (
|
|
87
|
+
segmentationProp: string | boolean | number | null | undefined,
|
|
88
|
+
ruleValue: SegmentationRule['value'],
|
|
89
|
+
) => boolean
|
|
90
|
+
|
|
67
91
|
export interface AssignmentStatistics {
|
|
68
92
|
sampled: number
|
|
69
93
|
buckets: {
|
package/src/util.ts
CHANGED
|
@@ -8,6 +8,8 @@ import {
|
|
|
8
8
|
ExperimentWithBuckets,
|
|
9
9
|
SegmentationData,
|
|
10
10
|
SegmentationRule,
|
|
11
|
+
SegmentationRuleFn,
|
|
12
|
+
SegmentationRuleOperator,
|
|
11
13
|
UserAssignment,
|
|
12
14
|
} from './types'
|
|
13
15
|
|
|
@@ -99,31 +101,43 @@ export const validateSegmentationRules = (
|
|
|
99
101
|
segmentationData: SegmentationData,
|
|
100
102
|
): boolean => {
|
|
101
103
|
for (const rule of rules) {
|
|
102
|
-
|
|
104
|
+
const { key, value, operator } = rule
|
|
105
|
+
if (!segmentationRuleMap[operator](segmentationData[key], value)) return false
|
|
103
106
|
}
|
|
104
107
|
return true
|
|
105
108
|
}
|
|
106
109
|
|
|
107
110
|
/**
|
|
108
|
-
*
|
|
111
|
+
* Map of segmentation rule validators
|
|
109
112
|
*/
|
|
110
|
-
export const
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
return
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
return
|
|
125
|
-
}
|
|
126
|
-
|
|
113
|
+
export const segmentationRuleMap: Record<SegmentationRuleOperator, SegmentationRuleFn> = {
|
|
114
|
+
[SegmentationRuleOperator.IsSet](keyValue) {
|
|
115
|
+
return !!keyValue
|
|
116
|
+
},
|
|
117
|
+
[SegmentationRuleOperator.IsNotSet](keyValue) {
|
|
118
|
+
return !keyValue
|
|
119
|
+
},
|
|
120
|
+
[SegmentationRuleOperator.EqualsText](keyValue, ruleValue) {
|
|
121
|
+
return keyValue?.toString() === ruleValue.toString()
|
|
122
|
+
},
|
|
123
|
+
[SegmentationRuleOperator.NotEqualsText](keyValue, ruleValue) {
|
|
124
|
+
return keyValue?.toString() !== ruleValue.toString()
|
|
125
|
+
},
|
|
126
|
+
[SegmentationRuleOperator.Semver](keyValue, ruleValue) {
|
|
127
|
+
return satisfies(keyValue?.toString() || '', ruleValue.toString())
|
|
128
|
+
},
|
|
129
|
+
[SegmentationRuleOperator.Regex](keyValue, ruleValue) {
|
|
130
|
+
return new RegExp(`${ruleValue}`).test(keyValue?.toString() || '')
|
|
131
|
+
},
|
|
132
|
+
[SegmentationRuleOperator.Boolean](keyValue, ruleValue) {
|
|
133
|
+
// If it's true, then must be true
|
|
134
|
+
if (ruleValue === 'true') return keyValue === 'true'
|
|
135
|
+
// Anything else cannot be true
|
|
136
|
+
return keyValue !== 'true'
|
|
137
|
+
},
|
|
138
|
+
// Deprecated
|
|
139
|
+
[SegmentationRuleOperator.Equals]: (keyValue, ruleValue) => keyValue === ruleValue,
|
|
140
|
+
[SegmentationRuleOperator.NotEquals]: (keyValue, ruleValue) => keyValue !== ruleValue,
|
|
127
141
|
}
|
|
128
142
|
|
|
129
143
|
/**
|