@@ -22,6 +22,7 @@ export interface IEppoClient {
22
22
* @param experimentKey experiment identifier
23
23
* @param subjectAttributes optional attributes associated with the subject, for example name and email.
24
24
* The subject attributes are used for evaluating any targeting rules tied to the experiment.
25
+ * @param assignmentHooks optional interface for pre and post assignment hooks
25
26
* @returns a variation value if the subject is part of the experiment sample, otherwise null
26
27
* @public
27
28
*/
@@ -30,26 +31,8 @@ export interface IEppoClient {
30
31
experimentKey : string ,
31
32
// eslint-disable-next-line @typescript-eslint/no-explicit-any
32
33
subjectAttributes ?: Record < string , any > ,
34
+ assignmentHooks ?: IAssignmentHooks ,
33
35
) : string ;
34
-
35
- /**
36
- * Asynchronously maps a subject to a variation for a given experiment, with pre and post assignment hooks
37
- *
38
- * @param subjectKey an identifier of the experiment subject, for example a user ID.
39
- * @param experimentKey experiment identifier
40
- * @param assignmentHooks interface for pre and post assignment hooks
41
- * @param subjectAttributes optional attributes associated with the subject, for example name and email.
42
- * The subject attributes are used for evaluating any targeting rules tied to the experiment.
43
- * @returns a variation value if the subject is part of the experiment sample, otherwise null
44
- * @public
45
- */
46
- getAssignmentWithHooks (
47
- subjectKey : string ,
48
- experimentKey : string ,
49
- assignmentHooks : IAssignmentHooks ,
50
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
51
- subjectAttributes ?: Record < string , any > ,
52
- ) : Promise < string > ;
53
36
}
54
37
55
38
export default class EppoClient implements IEppoClient {
@@ -58,10 +41,35 @@ export default class EppoClient implements IEppoClient {
58
41
59
42
constructor ( private configurationStore : IConfigurationStore ) { }
60
43
61
- getAssignment ( subjectKey : string , experimentKey : string , subjectAttributes = { } ) : string {
44
+ getAssignment (
45
+ subjectKey : string ,
46
+ experimentKey : string ,
47
+ subjectAttributes = { } ,
48
+ assignmentHooks : IAssignmentHooks = null ,
49
+ ) : string {
62
50
validateNotBlank ( subjectKey , 'Invalid argument: subjectKey cannot be blank' ) ;
63
51
validateNotBlank ( experimentKey , 'Invalid argument: experimentKey cannot be blank' ) ;
64
52
53
+ const assignment = this . getAssignmentInternal (
54
+ subjectKey ,
55
+ experimentKey ,
56
+ subjectAttributes ,
57
+ assignmentHooks ,
58
+ ) ;
59
+ assignmentHooks ?. onPostAssignment ( experimentKey , subjectKey , assignment ) ;
60
+
61
+ if ( assignment !== null )
62
+ this . logAssignment ( experimentKey , assignment , subjectKey , subjectAttributes ) ;
63
+
64
+ return assignment ;
65
+ }
66
+
67
+ private getAssignmentInternal (
68
+ subjectKey : string ,
69
+ experimentKey : string ,
70
+ subjectAttributes = { } ,
71
+ assignmentHooks : IAssignmentHooks = null ,
72
+ ) : string {
65
73
const experimentConfig = this . configurationStore . get < IExperimentConfiguration > ( experimentKey ) ;
66
74
const allowListOverride = this . getSubjectVariationOverride ( subjectKey , experimentConfig ) ;
67
75
@@ -70,6 +78,12 @@ export default class EppoClient implements IEppoClient {
70
78
// Check for disabled flag.
71
79
if ( ! experimentConfig ?. enabled ) return null ;
72
80
81
+ // check for overridden assignment via hook
82
+ const overriddenAssignment = assignmentHooks ?. onPreAssignment ( experimentKey , subjectKey ) ;
83
+ if ( overriddenAssignment !== null && overriddenAssignment !== undefined ) {
84
+ return overriddenAssignment ;
85
+ }
86
+
73
87
// Attempt to match a rule from the list.
74
88
const matchedRule = findMatchingRule ( subjectAttributes || { } , experimentConfig . rules ) ;
75
89
if ( ! matchedRule ) return null ;
@@ -88,27 +102,9 @@ export default class EppoClient implements IEppoClient {
88
102
isShardInRange ( shard , variation . shardRange ) ,
89
103
) . value ;
90
104
91
- // Finally, log assignment and return assignment.
92
- this . logAssignment ( experimentKey , assignedVariation , subjectKey , subjectAttributes ) ;
93
105
return assignedVariation ;
94
106
}
95
107
96
- async getAssignmentWithHooks (
97
- subjectKey : string ,
98
- experimentKey : string ,
99
- assignmentHooks : IAssignmentHooks ,
100
- subjectAttributes = { } ,
101
- ) : Promise < string > {
102
- let assignment = await assignmentHooks ?. onPreAssignment ( subjectKey ) ;
103
- if ( assignment == null ) {
104
- assignment = this . getAssignment ( subjectKey , experimentKey , subjectAttributes ) ;
105
- }
106
-
107
- assignmentHooks ?. onPostAssignment ( assignment ) ;
108
-
109
- return assignment ;
110
- }
111
-
112
108
public setLogger ( logger : IAssignmentLogger ) {
113
109
this . assignmentLogger = logger ;
114
110
this . flushQueuedEvents ( ) ; // log any events that may have been queued while initializing
0 commit comments