1- import { IConfig , IConfigsResponse , ISplitChangesResponse , ISplitCondition } from '../../../dtos/types' ;
2- import { IFetchSplitChanges , IResponse } from '../../../services/types' ;
1+ import { ISplit , ISplitChangesResponse , ISplitCondition , ISplitMatcher } from '../../../dtos/types' ;
2+ import { IFetchDefinitionChanges , IResponse } from '../../../services/types' ;
33import { ISplitChangesFetcher } from './types' ;
4+ import SplitIO from '../../../../types/splitio' ;
5+
6+ type IConfigMatcher = {
7+ type : 'IS_EQUAL_TO' ;
8+ data : { type : 'NUMBER' ; number : number } ;
9+ attribute ?: string ;
10+ } | {
11+ type : 'WHITELIST' ;
12+ data : { strings : string [ ] } ;
13+ attribute ?: string ;
14+ }
15+
16+ type IConfig = {
17+ name : string ;
18+ variants : Array < {
19+ name : string ;
20+ definition : SplitIO . JsonObject ;
21+ } > ;
22+ defaultVariant : string ;
23+ changeNumber ?: number ;
24+ targeting ?: {
25+ conditions ?: Array < {
26+ variant : string ;
27+ label : string ;
28+ matchers : Array < IConfigMatcher > ;
29+ } >
30+ } ;
31+ }
32+
33+ /** Interface of the parsed JSON response of `/configs` */
34+ export type IConfigsResponse = {
35+ t : number ,
36+ s ?: number ,
37+ d : IConfig [ ]
38+ }
439
540/**
641 * Factory of Configs fetcher.
742 * Configs fetcher is a wrapper around `configs` API service that parses the response and handle errors.
843 */
9- export function configsFetcherFactory ( fetchConfigs : IFetchSplitChanges ) : ISplitChangesFetcher {
44+ export function configsFetcherFactory ( fetchConfigs : IFetchDefinitionChanges ) : ISplitChangesFetcher {
1045
1146 return function configsFetcher (
1247 since : number ,
1348 noCache ?: boolean ,
1449 till ?: number ,
1550 rbSince ?: number ,
16- // Optional decorator for `fetchSplitChanges ` promise, such as timeout or time tracker
51+ // Optional decorator for `fetchConfigs ` promise, such as timeout or time tracker
1752 decorator ?: ( promise : Promise < IResponse > ) => Promise < IResponse >
1853 ) : Promise < ISplitChangesResponse > {
1954
2055 let configsPromise = fetchConfigs ( since , noCache , till , rbSince ) ;
2156 if ( decorator ) configsPromise = decorator ( configsPromise ) ;
2257
2358 return configsPromise
24- . then ( ( resp : IResponse ) => resp . json ( ) )
25- . then ( convertConfigsResponseToSplitChangesResponse ) ;
59+ . then < IConfigsResponse > ( ( resp : IResponse ) => resp . json ( ) )
60+ . then ( convertConfigsResponseToDefinitionChangesResponse ) ;
2661 } ;
2762
2863}
@@ -43,28 +78,64 @@ function defaultCondition(treatment: string): ISplitCondition {
4378 } ;
4479}
4580
46- function convertConfigToDefinitionDTO ( config : IConfig ) {
47- const defaultTreatment = config . defaultTreatment || 'default' ;
81+ function convertMatcher ( matcher : IConfigMatcher ) : ISplitMatcher {
82+ const keySelector = matcher . attribute ? { trafficType : 'user' , attribute : matcher . attribute } : null ;
83+
84+ switch ( matcher . type ) {
85+ case 'IS_EQUAL_TO' :
86+ return {
87+ matcherType : 'EQUAL_TO' ,
88+ negate : false ,
89+ keySelector,
90+ unaryNumericMatcherData : { dataType : matcher . data . type , value : matcher . data . number } ,
91+ } ;
92+ case 'WHITELIST' :
93+ return {
94+ matcherType : 'WHITELIST' ,
95+ negate : false ,
96+ keySelector,
97+ whitelistMatcherData : { whitelist : matcher . data . strings } ,
98+ } ;
99+ }
100+ }
101+
102+ function convertConfigToDefinition ( config : IConfig ) : ISplit {
103+ const defaultTreatment = config . defaultVariant || ( config . variants && config . variants [ 0 ] ?. name ) || 'control' ;
104+
105+ const configurations : Record < string , SplitIO . JsonObject > = { } ;
106+ config . variants . forEach ( variant => configurations [ variant . name ] = variant . definition ) ;
107+
108+ const conditions : ISplitCondition [ ] = config . targeting ?. conditions ?. map ( condition => ( {
109+ conditionType : condition . matchers . some ( ( m : IConfigMatcher ) => m . type === 'WHITELIST' ) ? 'WHITELIST' : 'ROLLOUT' ,
110+ label : condition . label ,
111+ matcherGroup : {
112+ combiner : 'AND' ,
113+ matchers : condition . matchers . map ( convertMatcher ) ,
114+ } ,
115+ partitions : [ { treatment : condition . variant , size : 100 } ] ,
116+ } ) ) || [ ] ;
117+
118+ conditions . push ( defaultCondition ( defaultTreatment ) ) ;
48119
49120 return {
50- ...config ,
121+ name : config . name ,
122+ changeNumber : config . changeNumber || 0 ,
123+ status : 'ACTIVE' ,
124+ conditions,
125+ killed : false ,
51126 defaultTreatment,
52- trafficTypeName : config . trafficTypeName || 'user' ,
53- conditions : config . conditions && config . conditions . length > 0 ? config . conditions : [ defaultCondition ( defaultTreatment ) ] ,
54- killed : config . killed || false ,
55- seed : config . seed || 0 ,
56- trafficAllocation : config . trafficAllocation || 100 ,
57- trafficAllocationSeed : config . trafficAllocationSeed || 0 ,
127+ trafficTypeName : 'user' ,
128+ seed : 0 ,
129+ configurations,
58130 } ;
59131}
60132
61- function convertConfigsResponseToSplitChangesResponse ( configs : IConfigsResponse ) : ISplitChangesResponse {
133+ export function convertConfigsResponseToDefinitionChangesResponse ( configs : IConfigsResponse ) : ISplitChangesResponse {
62134 return {
63- ...configs ,
64- ff : configs . configs ? {
65- ...configs . configs ,
66- d : configs . configs . d ?. map ( convertConfigToDefinitionDTO )
67- } : undefined ,
68- rbs : configs . rbs
135+ ff : {
136+ s : configs . s ,
137+ t : configs . t ,
138+ d : configs . d . map ( convertConfigToDefinition ) ,
139+ } ,
69140 } ;
70141}
0 commit comments