@featurevisor/sdk 1.35.2 → 2.0.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.
Files changed (86) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +2 -381
  3. package/coverage/clover.xml +707 -643
  4. package/coverage/coverage-final.json +11 -9
  5. package/coverage/lcov-report/{segments.ts.html → bucketer.ts.html} +155 -77
  6. package/coverage/lcov-report/child.ts.html +940 -0
  7. package/coverage/lcov-report/conditions.ts.html +107 -158
  8. package/coverage/lcov-report/datafileReader.ts.html +763 -103
  9. package/coverage/lcov-report/emitter.ts.html +77 -59
  10. package/coverage/lcov-report/evaluate.ts.html +689 -416
  11. package/coverage/lcov-report/events.ts.html +334 -0
  12. package/coverage/lcov-report/helpers.ts.html +184 -0
  13. package/coverage/lcov-report/{feature.ts.html → hooks.ts.html} +90 -237
  14. package/coverage/lcov-report/index.html +119 -89
  15. package/coverage/lcov-report/instance.ts.html +341 -773
  16. package/coverage/lcov-report/logger.ts.html +64 -64
  17. package/coverage/lcov.info +1433 -1223
  18. package/dist/bucketer.d.ts +11 -0
  19. package/dist/child.d.ts +26 -0
  20. package/dist/compareVersions.d.ts +4 -0
  21. package/dist/conditions.d.ts +4 -4
  22. package/dist/datafileReader.d.ts +26 -6
  23. package/dist/emitter.d.ts +8 -9
  24. package/dist/evaluate.d.ts +31 -29
  25. package/dist/events.d.ts +5 -0
  26. package/dist/helpers.d.ts +5 -0
  27. package/dist/hooks.d.ts +45 -0
  28. package/dist/index.d.ts +3 -2
  29. package/dist/index.js +1 -1
  30. package/dist/index.js.map +1 -1
  31. package/dist/index.mjs +1 -1
  32. package/dist/index.mjs.gz +0 -0
  33. package/dist/index.mjs.map +1 -1
  34. package/dist/instance.d.ts +40 -72
  35. package/dist/logger.d.ts +6 -5
  36. package/dist/murmurhash.d.ts +1 -0
  37. package/jest.config.js +2 -0
  38. package/lib/bucketer.d.ts +11 -0
  39. package/lib/child.d.ts +26 -0
  40. package/lib/compareVersions.d.ts +4 -0
  41. package/lib/conditions.d.ts +4 -4
  42. package/lib/datafileReader.d.ts +26 -6
  43. package/lib/emitter.d.ts +8 -9
  44. package/lib/evaluate.d.ts +31 -29
  45. package/lib/events.d.ts +5 -0
  46. package/lib/helpers.d.ts +5 -0
  47. package/lib/hooks.d.ts +45 -0
  48. package/lib/index.d.ts +3 -2
  49. package/lib/instance.d.ts +40 -72
  50. package/lib/logger.d.ts +6 -5
  51. package/lib/murmurhash.d.ts +1 -0
  52. package/package.json +3 -5
  53. package/src/bucketer.spec.ts +165 -0
  54. package/src/bucketer.ts +84 -0
  55. package/src/child.spec.ts +267 -0
  56. package/src/child.ts +285 -0
  57. package/src/compareVersions.ts +93 -0
  58. package/src/conditions.spec.ts +563 -353
  59. package/src/conditions.ts +46 -63
  60. package/src/datafileReader.spec.ts +396 -84
  61. package/src/datafileReader.ts +280 -60
  62. package/src/emitter.spec.ts +27 -86
  63. package/src/emitter.ts +38 -32
  64. package/src/evaluate.ts +349 -258
  65. package/src/events.spec.ts +154 -0
  66. package/src/events.ts +83 -0
  67. package/src/helpers.ts +33 -0
  68. package/src/hooks.ts +88 -0
  69. package/src/index.ts +3 -2
  70. package/src/instance.spec.ts +305 -489
  71. package/src/instance.ts +247 -391
  72. package/src/logger.spec.ts +212 -134
  73. package/src/logger.ts +36 -36
  74. package/src/murmurhash.ts +71 -0
  75. package/coverage/lcov-report/bucket.ts.html +0 -502
  76. package/dist/bucket.d.ts +0 -30
  77. package/dist/feature.d.ts +0 -16
  78. package/dist/segments.d.ts +0 -5
  79. package/lib/bucket.d.ts +0 -30
  80. package/lib/feature.d.ts +0 -16
  81. package/lib/segments.d.ts +0 -5
  82. package/src/bucket.spec.ts +0 -37
  83. package/src/bucket.ts +0 -139
  84. package/src/feature.ts +0 -137
  85. package/src/segments.spec.ts +0 -468
  86. package/src/segments.ts +0 -58
@@ -23,30 +23,30 @@
23
23
  <div class='clearfix'>
24
24
 
25
25
  <div class='fl pad1y space-right2'>
26
- <span class="strong">97.5% </span>
26
+ <span class="strong">90.59% </span>
27
27
  <span class="quiet">Statements</span>
28
- <span class='fraction'>39/40</span>
28
+ <span class='fraction'>106/117</span>
29
29
  </div>
30
30
 
31
31
 
32
32
  <div class='fl pad1y space-right2'>
33
- <span class="strong">100% </span>
33
+ <span class="strong">91.66% </span>
34
34
  <span class="quiet">Branches</span>
35
- <span class='fraction'>7/7</span>
35
+ <span class='fraction'>55/60</span>
36
36
  </div>
37
37
 
38
38
 
39
39
  <div class='fl pad1y space-right2'>
40
40
  <span class="strong">100% </span>
41
41
  <span class="quiet">Functions</span>
42
- <span class='fraction'>13/13</span>
42
+ <span class='fraction'>27/27</span>
43
43
  </div>
44
44
 
45
45
 
46
46
  <div class='fl pad1y space-right2'>
47
- <span class="strong">97.5% </span>
47
+ <span class="strong">90.26% </span>
48
48
  <span class="quiet">Lines</span>
49
- <span class='fraction'>39/40</span>
49
+ <span class='fraction'>102/113</span>
50
50
  </div>
51
51
 
52
52
 
@@ -169,7 +169,243 @@
169
169
  <a name='L104'></a><a href='#L104'>104</a>
170
170
  <a name='L105'></a><a href='#L105'>105</a>
171
171
  <a name='L106'></a><a href='#L106'>106</a>
172
- <a name='L107'></a><a href='#L107'>107</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
172
+ <a name='L107'></a><a href='#L107'>107</a>
173
+ <a name='L108'></a><a href='#L108'>108</a>
174
+ <a name='L109'></a><a href='#L109'>109</a>
175
+ <a name='L110'></a><a href='#L110'>110</a>
176
+ <a name='L111'></a><a href='#L111'>111</a>
177
+ <a name='L112'></a><a href='#L112'>112</a>
178
+ <a name='L113'></a><a href='#L113'>113</a>
179
+ <a name='L114'></a><a href='#L114'>114</a>
180
+ <a name='L115'></a><a href='#L115'>115</a>
181
+ <a name='L116'></a><a href='#L116'>116</a>
182
+ <a name='L117'></a><a href='#L117'>117</a>
183
+ <a name='L118'></a><a href='#L118'>118</a>
184
+ <a name='L119'></a><a href='#L119'>119</a>
185
+ <a name='L120'></a><a href='#L120'>120</a>
186
+ <a name='L121'></a><a href='#L121'>121</a>
187
+ <a name='L122'></a><a href='#L122'>122</a>
188
+ <a name='L123'></a><a href='#L123'>123</a>
189
+ <a name='L124'></a><a href='#L124'>124</a>
190
+ <a name='L125'></a><a href='#L125'>125</a>
191
+ <a name='L126'></a><a href='#L126'>126</a>
192
+ <a name='L127'></a><a href='#L127'>127</a>
193
+ <a name='L128'></a><a href='#L128'>128</a>
194
+ <a name='L129'></a><a href='#L129'>129</a>
195
+ <a name='L130'></a><a href='#L130'>130</a>
196
+ <a name='L131'></a><a href='#L131'>131</a>
197
+ <a name='L132'></a><a href='#L132'>132</a>
198
+ <a name='L133'></a><a href='#L133'>133</a>
199
+ <a name='L134'></a><a href='#L134'>134</a>
200
+ <a name='L135'></a><a href='#L135'>135</a>
201
+ <a name='L136'></a><a href='#L136'>136</a>
202
+ <a name='L137'></a><a href='#L137'>137</a>
203
+ <a name='L138'></a><a href='#L138'>138</a>
204
+ <a name='L139'></a><a href='#L139'>139</a>
205
+ <a name='L140'></a><a href='#L140'>140</a>
206
+ <a name='L141'></a><a href='#L141'>141</a>
207
+ <a name='L142'></a><a href='#L142'>142</a>
208
+ <a name='L143'></a><a href='#L143'>143</a>
209
+ <a name='L144'></a><a href='#L144'>144</a>
210
+ <a name='L145'></a><a href='#L145'>145</a>
211
+ <a name='L146'></a><a href='#L146'>146</a>
212
+ <a name='L147'></a><a href='#L147'>147</a>
213
+ <a name='L148'></a><a href='#L148'>148</a>
214
+ <a name='L149'></a><a href='#L149'>149</a>
215
+ <a name='L150'></a><a href='#L150'>150</a>
216
+ <a name='L151'></a><a href='#L151'>151</a>
217
+ <a name='L152'></a><a href='#L152'>152</a>
218
+ <a name='L153'></a><a href='#L153'>153</a>
219
+ <a name='L154'></a><a href='#L154'>154</a>
220
+ <a name='L155'></a><a href='#L155'>155</a>
221
+ <a name='L156'></a><a href='#L156'>156</a>
222
+ <a name='L157'></a><a href='#L157'>157</a>
223
+ <a name='L158'></a><a href='#L158'>158</a>
224
+ <a name='L159'></a><a href='#L159'>159</a>
225
+ <a name='L160'></a><a href='#L160'>160</a>
226
+ <a name='L161'></a><a href='#L161'>161</a>
227
+ <a name='L162'></a><a href='#L162'>162</a>
228
+ <a name='L163'></a><a href='#L163'>163</a>
229
+ <a name='L164'></a><a href='#L164'>164</a>
230
+ <a name='L165'></a><a href='#L165'>165</a>
231
+ <a name='L166'></a><a href='#L166'>166</a>
232
+ <a name='L167'></a><a href='#L167'>167</a>
233
+ <a name='L168'></a><a href='#L168'>168</a>
234
+ <a name='L169'></a><a href='#L169'>169</a>
235
+ <a name='L170'></a><a href='#L170'>170</a>
236
+ <a name='L171'></a><a href='#L171'>171</a>
237
+ <a name='L172'></a><a href='#L172'>172</a>
238
+ <a name='L173'></a><a href='#L173'>173</a>
239
+ <a name='L174'></a><a href='#L174'>174</a>
240
+ <a name='L175'></a><a href='#L175'>175</a>
241
+ <a name='L176'></a><a href='#L176'>176</a>
242
+ <a name='L177'></a><a href='#L177'>177</a>
243
+ <a name='L178'></a><a href='#L178'>178</a>
244
+ <a name='L179'></a><a href='#L179'>179</a>
245
+ <a name='L180'></a><a href='#L180'>180</a>
246
+ <a name='L181'></a><a href='#L181'>181</a>
247
+ <a name='L182'></a><a href='#L182'>182</a>
248
+ <a name='L183'></a><a href='#L183'>183</a>
249
+ <a name='L184'></a><a href='#L184'>184</a>
250
+ <a name='L185'></a><a href='#L185'>185</a>
251
+ <a name='L186'></a><a href='#L186'>186</a>
252
+ <a name='L187'></a><a href='#L187'>187</a>
253
+ <a name='L188'></a><a href='#L188'>188</a>
254
+ <a name='L189'></a><a href='#L189'>189</a>
255
+ <a name='L190'></a><a href='#L190'>190</a>
256
+ <a name='L191'></a><a href='#L191'>191</a>
257
+ <a name='L192'></a><a href='#L192'>192</a>
258
+ <a name='L193'></a><a href='#L193'>193</a>
259
+ <a name='L194'></a><a href='#L194'>194</a>
260
+ <a name='L195'></a><a href='#L195'>195</a>
261
+ <a name='L196'></a><a href='#L196'>196</a>
262
+ <a name='L197'></a><a href='#L197'>197</a>
263
+ <a name='L198'></a><a href='#L198'>198</a>
264
+ <a name='L199'></a><a href='#L199'>199</a>
265
+ <a name='L200'></a><a href='#L200'>200</a>
266
+ <a name='L201'></a><a href='#L201'>201</a>
267
+ <a name='L202'></a><a href='#L202'>202</a>
268
+ <a name='L203'></a><a href='#L203'>203</a>
269
+ <a name='L204'></a><a href='#L204'>204</a>
270
+ <a name='L205'></a><a href='#L205'>205</a>
271
+ <a name='L206'></a><a href='#L206'>206</a>
272
+ <a name='L207'></a><a href='#L207'>207</a>
273
+ <a name='L208'></a><a href='#L208'>208</a>
274
+ <a name='L209'></a><a href='#L209'>209</a>
275
+ <a name='L210'></a><a href='#L210'>210</a>
276
+ <a name='L211'></a><a href='#L211'>211</a>
277
+ <a name='L212'></a><a href='#L212'>212</a>
278
+ <a name='L213'></a><a href='#L213'>213</a>
279
+ <a name='L214'></a><a href='#L214'>214</a>
280
+ <a name='L215'></a><a href='#L215'>215</a>
281
+ <a name='L216'></a><a href='#L216'>216</a>
282
+ <a name='L217'></a><a href='#L217'>217</a>
283
+ <a name='L218'></a><a href='#L218'>218</a>
284
+ <a name='L219'></a><a href='#L219'>219</a>
285
+ <a name='L220'></a><a href='#L220'>220</a>
286
+ <a name='L221'></a><a href='#L221'>221</a>
287
+ <a name='L222'></a><a href='#L222'>222</a>
288
+ <a name='L223'></a><a href='#L223'>223</a>
289
+ <a name='L224'></a><a href='#L224'>224</a>
290
+ <a name='L225'></a><a href='#L225'>225</a>
291
+ <a name='L226'></a><a href='#L226'>226</a>
292
+ <a name='L227'></a><a href='#L227'>227</a>
293
+ <a name='L228'></a><a href='#L228'>228</a>
294
+ <a name='L229'></a><a href='#L229'>229</a>
295
+ <a name='L230'></a><a href='#L230'>230</a>
296
+ <a name='L231'></a><a href='#L231'>231</a>
297
+ <a name='L232'></a><a href='#L232'>232</a>
298
+ <a name='L233'></a><a href='#L233'>233</a>
299
+ <a name='L234'></a><a href='#L234'>234</a>
300
+ <a name='L235'></a><a href='#L235'>235</a>
301
+ <a name='L236'></a><a href='#L236'>236</a>
302
+ <a name='L237'></a><a href='#L237'>237</a>
303
+ <a name='L238'></a><a href='#L238'>238</a>
304
+ <a name='L239'></a><a href='#L239'>239</a>
305
+ <a name='L240'></a><a href='#L240'>240</a>
306
+ <a name='L241'></a><a href='#L241'>241</a>
307
+ <a name='L242'></a><a href='#L242'>242</a>
308
+ <a name='L243'></a><a href='#L243'>243</a>
309
+ <a name='L244'></a><a href='#L244'>244</a>
310
+ <a name='L245'></a><a href='#L245'>245</a>
311
+ <a name='L246'></a><a href='#L246'>246</a>
312
+ <a name='L247'></a><a href='#L247'>247</a>
313
+ <a name='L248'></a><a href='#L248'>248</a>
314
+ <a name='L249'></a><a href='#L249'>249</a>
315
+ <a name='L250'></a><a href='#L250'>250</a>
316
+ <a name='L251'></a><a href='#L251'>251</a>
317
+ <a name='L252'></a><a href='#L252'>252</a>
318
+ <a name='L253'></a><a href='#L253'>253</a>
319
+ <a name='L254'></a><a href='#L254'>254</a>
320
+ <a name='L255'></a><a href='#L255'>255</a>
321
+ <a name='L256'></a><a href='#L256'>256</a>
322
+ <a name='L257'></a><a href='#L257'>257</a>
323
+ <a name='L258'></a><a href='#L258'>258</a>
324
+ <a name='L259'></a><a href='#L259'>259</a>
325
+ <a name='L260'></a><a href='#L260'>260</a>
326
+ <a name='L261'></a><a href='#L261'>261</a>
327
+ <a name='L262'></a><a href='#L262'>262</a>
328
+ <a name='L263'></a><a href='#L263'>263</a>
329
+ <a name='L264'></a><a href='#L264'>264</a>
330
+ <a name='L265'></a><a href='#L265'>265</a>
331
+ <a name='L266'></a><a href='#L266'>266</a>
332
+ <a name='L267'></a><a href='#L267'>267</a>
333
+ <a name='L268'></a><a href='#L268'>268</a>
334
+ <a name='L269'></a><a href='#L269'>269</a>
335
+ <a name='L270'></a><a href='#L270'>270</a>
336
+ <a name='L271'></a><a href='#L271'>271</a>
337
+ <a name='L272'></a><a href='#L272'>272</a>
338
+ <a name='L273'></a><a href='#L273'>273</a>
339
+ <a name='L274'></a><a href='#L274'>274</a>
340
+ <a name='L275'></a><a href='#L275'>275</a>
341
+ <a name='L276'></a><a href='#L276'>276</a>
342
+ <a name='L277'></a><a href='#L277'>277</a>
343
+ <a name='L278'></a><a href='#L278'>278</a>
344
+ <a name='L279'></a><a href='#L279'>279</a>
345
+ <a name='L280'></a><a href='#L280'>280</a>
346
+ <a name='L281'></a><a href='#L281'>281</a>
347
+ <a name='L282'></a><a href='#L282'>282</a>
348
+ <a name='L283'></a><a href='#L283'>283</a>
349
+ <a name='L284'></a><a href='#L284'>284</a>
350
+ <a name='L285'></a><a href='#L285'>285</a>
351
+ <a name='L286'></a><a href='#L286'>286</a>
352
+ <a name='L287'></a><a href='#L287'>287</a>
353
+ <a name='L288'></a><a href='#L288'>288</a>
354
+ <a name='L289'></a><a href='#L289'>289</a>
355
+ <a name='L290'></a><a href='#L290'>290</a>
356
+ <a name='L291'></a><a href='#L291'>291</a>
357
+ <a name='L292'></a><a href='#L292'>292</a>
358
+ <a name='L293'></a><a href='#L293'>293</a>
359
+ <a name='L294'></a><a href='#L294'>294</a>
360
+ <a name='L295'></a><a href='#L295'>295</a>
361
+ <a name='L296'></a><a href='#L296'>296</a>
362
+ <a name='L297'></a><a href='#L297'>297</a>
363
+ <a name='L298'></a><a href='#L298'>298</a>
364
+ <a name='L299'></a><a href='#L299'>299</a>
365
+ <a name='L300'></a><a href='#L300'>300</a>
366
+ <a name='L301'></a><a href='#L301'>301</a>
367
+ <a name='L302'></a><a href='#L302'>302</a>
368
+ <a name='L303'></a><a href='#L303'>303</a>
369
+ <a name='L304'></a><a href='#L304'>304</a>
370
+ <a name='L305'></a><a href='#L305'>305</a>
371
+ <a name='L306'></a><a href='#L306'>306</a>
372
+ <a name='L307'></a><a href='#L307'>307</a>
373
+ <a name='L308'></a><a href='#L308'>308</a>
374
+ <a name='L309'></a><a href='#L309'>309</a>
375
+ <a name='L310'></a><a href='#L310'>310</a>
376
+ <a name='L311'></a><a href='#L311'>311</a>
377
+ <a name='L312'></a><a href='#L312'>312</a>
378
+ <a name='L313'></a><a href='#L313'>313</a>
379
+ <a name='L314'></a><a href='#L314'>314</a>
380
+ <a name='L315'></a><a href='#L315'>315</a>
381
+ <a name='L316'></a><a href='#L316'>316</a>
382
+ <a name='L317'></a><a href='#L317'>317</a>
383
+ <a name='L318'></a><a href='#L318'>318</a>
384
+ <a name='L319'></a><a href='#L319'>319</a>
385
+ <a name='L320'></a><a href='#L320'>320</a>
386
+ <a name='L321'></a><a href='#L321'>321</a>
387
+ <a name='L322'></a><a href='#L322'>322</a>
388
+ <a name='L323'></a><a href='#L323'>323</a>
389
+ <a name='L324'></a><a href='#L324'>324</a>
390
+ <a name='L325'></a><a href='#L325'>325</a>
391
+ <a name='L326'></a><a href='#L326'>326</a>
392
+ <a name='L327'></a><a href='#L327'>327</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
393
+ <span class="cline-any cline-neutral">&nbsp;</span>
394
+ <span class="cline-any cline-neutral">&nbsp;</span>
395
+ <span class="cline-any cline-neutral">&nbsp;</span>
396
+ <span class="cline-any cline-neutral">&nbsp;</span>
397
+ <span class="cline-any cline-neutral">&nbsp;</span>
398
+ <span class="cline-any cline-neutral">&nbsp;</span>
399
+ <span class="cline-any cline-neutral">&nbsp;</span>
400
+ <span class="cline-any cline-neutral">&nbsp;</span>
401
+ <span class="cline-any cline-neutral">&nbsp;</span>
402
+ <span class="cline-any cline-neutral">&nbsp;</span>
403
+ <span class="cline-any cline-neutral">&nbsp;</span>
404
+ <span class="cline-any cline-neutral">&nbsp;</span>
405
+ <span class="cline-any cline-neutral">&nbsp;</span>
406
+ <span class="cline-any cline-yes">5x</span>
407
+ <span class="cline-any cline-neutral">&nbsp;</span>
408
+ <span class="cline-any cline-neutral">&nbsp;</span>
173
409
  <span class="cline-any cline-neutral">&nbsp;</span>
174
410
  <span class="cline-any cline-neutral">&nbsp;</span>
175
411
  <span class="cline-any cline-neutral">&nbsp;</span>
@@ -180,19 +416,13 @@
180
416
  <span class="cline-any cline-neutral">&nbsp;</span>
181
417
  <span class="cline-any cline-neutral">&nbsp;</span>
182
418
  <span class="cline-any cline-neutral">&nbsp;</span>
183
- <span class="cline-any cline-yes">3x</span>
184
- <span class="cline-any cline-yes">137x</span>
185
- <span class="cline-any cline-yes">10x</span>
186
- <span class="cline-any cline-yes">10x</span>
187
419
  <span class="cline-any cline-neutral">&nbsp;</span>
188
- <span class="cline-any cline-no">&nbsp;</span>
189
420
  <span class="cline-any cline-neutral">&nbsp;</span>
421
+ <span class="cline-any cline-yes">5x</span>
190
422
  <span class="cline-any cline-neutral">&nbsp;</span>
191
423
  <span class="cline-any cline-neutral">&nbsp;</span>
192
- <span class="cline-any cline-yes">137x</span>
193
424
  <span class="cline-any cline-neutral">&nbsp;</span>
194
425
  <span class="cline-any cline-neutral">&nbsp;</span>
195
- <span class="cline-any cline-yes">3x</span>
196
426
  <span class="cline-any cline-neutral">&nbsp;</span>
197
427
  <span class="cline-any cline-neutral">&nbsp;</span>
198
428
  <span class="cline-any cline-neutral">&nbsp;</span>
@@ -201,148 +431,345 @@
201
431
  <span class="cline-any cline-neutral">&nbsp;</span>
202
432
  <span class="cline-any cline-neutral">&nbsp;</span>
203
433
  <span class="cline-any cline-neutral">&nbsp;</span>
204
- <span class="cline-any cline-yes">31x</span>
205
- <span class="cline-any cline-yes">31x</span>
206
434
  <span class="cline-any cline-neutral">&nbsp;</span>
207
- <span class="cline-any cline-yes">31x</span>
435
+ <span class="cline-any cline-neutral">&nbsp;</span>
436
+ <span class="cline-any cline-yes">47x</span>
437
+ <span class="cline-any cline-neutral">&nbsp;</span>
438
+ <span class="cline-any cline-yes">47x</span>
439
+ <span class="cline-any cline-neutral">&nbsp;</span>
440
+ <span class="cline-any cline-yes">47x</span>
441
+ <span class="cline-any cline-yes">47x</span>
442
+ <span class="cline-any cline-neutral">&nbsp;</span>
443
+ <span class="cline-any cline-yes">47x</span>
444
+ <span class="cline-any cline-yes">47x</span>
445
+ <span class="cline-any cline-neutral">&nbsp;</span>
446
+ <span class="cline-any cline-yes">47x</span>
447
+ <span class="cline-any cline-neutral">&nbsp;</span>
448
+ <span class="cline-any cline-neutral">&nbsp;</span>
449
+ <span class="cline-any cline-neutral">&nbsp;</span>
450
+ <span class="cline-any cline-yes">9x</span>
451
+ <span class="cline-any cline-neutral">&nbsp;</span>
452
+ <span class="cline-any cline-neutral">&nbsp;</span>
208
453
  <span class="cline-any cline-neutral">&nbsp;</span>
209
454
  <span class="cline-any cline-yes">1x</span>
210
455
  <span class="cline-any cline-neutral">&nbsp;</span>
456
+ <span class="cline-any cline-neutral">&nbsp;</span>
457
+ <span class="cline-any cline-neutral">&nbsp;</span>
458
+ <span class="cline-any cline-yes">210x</span>
459
+ <span class="cline-any cline-neutral">&nbsp;</span>
460
+ <span class="cline-any cline-yes">210x</span>
211
461
  <span class="cline-any cline-yes">1x</span>
462
+ <span class="cline-any cline-neutral">&nbsp;</span>
463
+ <span class="cline-any cline-neutral">&nbsp;</span>
464
+ <span class="cline-any cline-yes">209x</span>
465
+ <span class="cline-any cline-neutral">&nbsp;</span>
466
+ <span class="cline-any cline-yes">209x</span>
467
+ <span class="cline-any cline-neutral">&nbsp;</span>
468
+ <span class="cline-any cline-neutral">&nbsp;</span>
469
+ <span class="cline-any cline-neutral">&nbsp;</span>
470
+ <span class="cline-any cline-yes">10x</span>
471
+ <span class="cline-any cline-neutral">&nbsp;</span>
472
+ <span class="cline-any cline-neutral">&nbsp;</span>
473
+ <span class="cline-any cline-neutral">&nbsp;</span>
474
+ <span class="cline-any cline-yes">208x</span>
475
+ <span class="cline-any cline-neutral">&nbsp;</span>
476
+ <span class="cline-any cline-neutral">&nbsp;</span>
477
+ <span class="cline-any cline-neutral">&nbsp;</span>
478
+ <span class="cline-any cline-yes">4x</span>
479
+ <span class="cline-any cline-neutral">&nbsp;</span>
480
+ <span class="cline-any cline-yes">4x</span>
481
+ <span class="cline-any cline-no">&nbsp;</span>
482
+ <span class="cline-any cline-neutral">&nbsp;</span>
483
+ <span class="cline-any cline-neutral">&nbsp;</span>
484
+ <span class="cline-any cline-yes">4x</span>
485
+ <span class="cline-any cline-neutral">&nbsp;</span>
486
+ <span class="cline-any cline-neutral">&nbsp;</span>
487
+ <span class="cline-any cline-neutral">&nbsp;</span>
488
+ <span class="cline-any cline-yes">4x</span>
489
+ <span class="cline-any cline-neutral">&nbsp;</span>
490
+ <span class="cline-any cline-yes">4x</span>
491
+ <span class="cline-any cline-no">&nbsp;</span>
492
+ <span class="cline-any cline-neutral">&nbsp;</span>
493
+ <span class="cline-any cline-neutral">&nbsp;</span>
494
+ <span class="cline-any cline-yes">4x</span>
495
+ <span class="cline-any cline-neutral">&nbsp;</span>
496
+ <span class="cline-any cline-neutral">&nbsp;</span>
497
+ <span class="cline-any cline-neutral">&nbsp;</span>
498
+ <span class="cline-any cline-yes">18x</span>
499
+ <span class="cline-any cline-yes">18x</span>
500
+ <span class="cline-any cline-neutral">&nbsp;</span>
501
+ <span class="cline-any cline-yes">18x</span>
502
+ <span class="cline-any cline-yes">16x</span>
503
+ <span class="cline-any cline-neutral">&nbsp;</span>
504
+ <span class="cline-any cline-neutral">&nbsp;</span>
505
+ <span class="cline-any cline-yes">2x</span>
506
+ <span class="cline-any cline-yes">2x</span>
507
+ <span class="cline-any cline-neutral">&nbsp;</span>
508
+ <span class="cline-any cline-yes">2x</span>
509
+ <span class="cline-any cline-neutral">&nbsp;</span>
510
+ <span class="cline-any cline-neutral">&nbsp;</span>
511
+ <span class="cline-any cline-neutral">&nbsp;</span>
512
+ <span class="cline-any cline-yes">1506x</span>
513
+ <span class="cline-any cline-yes">2x</span>
212
514
  <span class="cline-any cline-yes">1x</span>
515
+ <span class="cline-any cline-neutral">&nbsp;</span>
516
+ <span class="cline-any cline-neutral">&nbsp;</span>
213
517
  <span class="cline-any cline-yes">1x</span>
214
518
  <span class="cline-any cline-neutral">&nbsp;</span>
215
519
  <span class="cline-any cline-neutral">&nbsp;</span>
216
- <span class="cline-any cline-yes">30x</span>
520
+ <span class="cline-any cline-yes">1504x</span>
521
+ <span class="cline-any cline-yes">18x</span>
217
522
  <span class="cline-any cline-neutral">&nbsp;</span>
218
- <span class="cline-any cline-yes">30x</span>
219
- <span class="cline-any cline-yes">30x</span>
220
- <span class="cline-any cline-yes">6x</span>
523
+ <span class="cline-any cline-yes">1504x</span>
524
+ <span class="cline-any cline-yes">745x</span>
525
+ <span class="cline-any cline-yes">745x</span>
221
526
  <span class="cline-any cline-neutral">&nbsp;</span>
527
+ <span class="cline-any cline-no">&nbsp;</span>
222
528
  <span class="cline-any cline-neutral">&nbsp;</span>
223
- <span class="cline-any cline-yes">30x</span>
224
- <span class="cline-any cline-yes">30x</span>
225
- <span class="cline-any cline-yes">17x</span>
226
529
  <span class="cline-any cline-neutral">&nbsp;</span>
227
530
  <span class="cline-any cline-neutral">&nbsp;</span>
228
- <span class="cline-any cline-yes">30x</span>
229
- <span class="cline-any cline-yes">30x</span>
230
- <span class="cline-any cline-yes">27x</span>
231
- <span class="cline-any cline-yes">2x</span>
232
- <span class="cline-any cline-yes">9x</span>
531
+ <span class="cline-any cline-neutral">&nbsp;</span>
532
+ <span class="cline-any cline-neutral">&nbsp;</span>
533
+ <span class="cline-any cline-neutral">&nbsp;</span>
534
+ <span class="cline-any cline-neutral">&nbsp;</span>
535
+ <span class="cline-any cline-no">&nbsp;</span>
536
+ <span class="cline-any cline-neutral">&nbsp;</span>
537
+ <span class="cline-any cline-neutral">&nbsp;</span>
538
+ <span class="cline-any cline-neutral">&nbsp;</span>
539
+ <span class="cline-any cline-yes">759x</span>
540
+ <span class="cline-any cline-yes">37x</span>
541
+ <span class="cline-any cline-neutral">&nbsp;</span>
542
+ <span class="cline-any cline-neutral">&nbsp;</span>
543
+ <span class="cline-any cline-yes">736x</span>
544
+ <span class="cline-any cline-yes">38x</span>
545
+ <span class="cline-any cline-neutral">&nbsp;</span>
546
+ <span class="cline-any cline-neutral">&nbsp;</span>
547
+ <span class="cline-any cline-yes">714x</span>
548
+ <span class="cline-any cline-yes">6x</span>
549
+ <span class="cline-any cline-neutral">&nbsp;</span>
233
550
  <span class="cline-any cline-yes">9x</span>
234
551
  <span class="cline-any cline-neutral">&nbsp;</span>
235
552
  <span class="cline-any cline-neutral">&nbsp;</span>
236
553
  <span class="cline-any cline-neutral">&nbsp;</span>
237
- <span class="cline-any cline-yes">27x</span>
238
554
  <span class="cline-any cline-neutral">&nbsp;</span>
239
555
  <span class="cline-any cline-neutral">&nbsp;</span>
240
556
  <span class="cline-any cline-neutral">&nbsp;</span>
241
557
  <span class="cline-any cline-neutral">&nbsp;</span>
242
558
  <span class="cline-any cline-neutral">&nbsp;</span>
243
- <span class="cline-any cline-yes">3x</span>
559
+ <span class="cline-any cline-yes">708x</span>
560
+ <span class="cline-any cline-yes">711x</span>
244
561
  <span class="cline-any cline-neutral">&nbsp;</span>
245
562
  <span class="cline-any cline-neutral">&nbsp;</span>
563
+ <span class="cline-any cline-no">&nbsp;</span>
246
564
  <span class="cline-any cline-neutral">&nbsp;</span>
247
- <span class="cline-any cline-yes">2x</span>
248
565
  <span class="cline-any cline-neutral">&nbsp;</span>
249
566
  <span class="cline-any cline-neutral">&nbsp;</span>
567
+ <span class="cline-any cline-yes">207x</span>
250
568
  <span class="cline-any cline-neutral">&nbsp;</span>
251
- <span class="cline-any cline-yes">3x</span>
252
569
  <span class="cline-any cline-neutral">&nbsp;</span>
253
- <span class="cline-any cline-yes">3x</span>
254
- <span class="cline-any cline-yes">4x</span>
255
570
  <span class="cline-any cline-neutral">&nbsp;</span>
256
571
  <span class="cline-any cline-neutral">&nbsp;</span>
257
- <span class="cline-any cline-yes">3x</span>
258
572
  <span class="cline-any cline-neutral">&nbsp;</span>
259
573
  <span class="cline-any cline-neutral">&nbsp;</span>
574
+ <span class="cline-any cline-yes">506x</span>
575
+ <span class="cline-any cline-yes">100x</span>
260
576
  <span class="cline-any cline-neutral">&nbsp;</span>
261
- <span class="cline-any cline-yes">2x</span>
577
+ <span class="cline-any cline-neutral">&nbsp;</span>
578
+ <span class="cline-any cline-yes">406x</span>
579
+ <span class="cline-any cline-yes">207x</span>
580
+ <span class="cline-any cline-neutral">&nbsp;</span>
581
+ <span class="cline-any cline-yes">207x</span>
582
+ <span class="cline-any cline-yes">207x</span>
583
+ <span class="cline-any cline-neutral">&nbsp;</span>
584
+ <span class="cline-any cline-neutral">&nbsp;</span>
585
+ <span class="cline-any cline-no">&nbsp;</span>
586
+ <span class="cline-any cline-neutral">&nbsp;</span>
587
+ <span class="cline-any cline-neutral">&nbsp;</span>
588
+ <span class="cline-any cline-yes">199x</span>
589
+ <span class="cline-any cline-yes">199x</span>
590
+ <span class="cline-any cline-yes">15x</span>
591
+ <span class="cline-any cline-yes">24x</span>
592
+ <span class="cline-any cline-neutral">&nbsp;</span>
593
+ <span class="cline-any cline-neutral">&nbsp;</span>
594
+ <span class="cline-any cline-neutral">&nbsp;</span>
595
+ <span class="cline-any cline-yes">184x</span>
596
+ <span class="cline-any cline-yes">8x</span>
597
+ <span class="cline-any cline-yes">12x</span>
262
598
  <span class="cline-any cline-neutral">&nbsp;</span>
263
599
  <span class="cline-any cline-neutral">&nbsp;</span>
264
600
  <span class="cline-any cline-neutral">&nbsp;</span>
265
- <span class="cline-any cline-yes">139x</span>
601
+ <span class="cline-any cline-yes">176x</span>
602
+ <span class="cline-any cline-yes">10x</span>
603
+ <span class="cline-any cline-yes">10x</span>
604
+ <span class="cline-any cline-neutral">&nbsp;</span>
605
+ <span class="cline-any cline-neutral">&nbsp;</span>
606
+ <span class="cline-any cline-neutral">&nbsp;</span>
607
+ <span class="cline-any cline-neutral">&nbsp;</span>
608
+ <span class="cline-any cline-yes">166x</span>
609
+ <span class="cline-any cline-yes">166x</span>
610
+ <span class="cline-any cline-yes">177x</span>
611
+ <span class="cline-any cline-neutral">&nbsp;</span>
612
+ <span class="cline-any cline-neutral">&nbsp;</span>
613
+ <span class="cline-any cline-neutral">&nbsp;</span>
614
+ <span class="cline-any cline-no">&nbsp;</span>
615
+ <span class="cline-any cline-neutral">&nbsp;</span>
616
+ <span class="cline-any cline-neutral">&nbsp;</span>
617
+ <span class="cline-any cline-neutral">&nbsp;</span>
618
+ <span class="cline-any cline-yes">165x</span>
619
+ <span class="cline-any cline-yes">228x</span>
620
+ <span class="cline-any cline-yes">67x</span>
621
+ <span class="cline-any cline-neutral">&nbsp;</span>
622
+ <span class="cline-any cline-neutral">&nbsp;</span>
623
+ <span class="cline-any cline-yes">161x</span>
624
+ <span class="cline-any cline-neutral">&nbsp;</span>
625
+ <span class="cline-any cline-neutral">&nbsp;</span>
626
+ <span class="cline-any cline-neutral">&nbsp;</span>
627
+ <span class="cline-any cline-neutral">&nbsp;</span>
628
+ <span class="cline-any cline-yes">72x</span>
629
+ <span class="cline-any cline-no">&nbsp;</span>
630
+ <span class="cline-any cline-neutral">&nbsp;</span>
631
+ <span class="cline-any cline-neutral">&nbsp;</span>
632
+ <span class="cline-any cline-yes">72x</span>
633
+ <span class="cline-any cline-yes">132x</span>
634
+ <span class="cline-any cline-neutral">&nbsp;</span>
635
+ <span class="cline-any cline-yes">132x</span>
636
+ <span class="cline-any cline-yes">70x</span>
637
+ <span class="cline-any cline-neutral">&nbsp;</span>
638
+ <span class="cline-any cline-neutral">&nbsp;</span>
266
639
  <span class="cline-any cline-neutral">&nbsp;</span>
267
- <span class="cline-any cline-yes">139x</span>
268
640
  <span class="cline-any cline-yes">2x</span>
269
641
  <span class="cline-any cline-neutral">&nbsp;</span>
270
642
  <span class="cline-any cline-neutral">&nbsp;</span>
271
- <span class="cline-any cline-yes">137x</span>
643
+ <span class="cline-any cline-neutral">&nbsp;</span>
644
+ <span class="cline-any cline-yes">178x</span>
645
+ <span class="cline-any cline-neutral">&nbsp;</span>
646
+ <span class="cline-any cline-neutral">&nbsp;</span>
647
+ <span class="cline-any cline-neutral">&nbsp;</span>
648
+ <span class="cline-any cline-neutral">&nbsp;</span>
649
+ <span class="cline-any cline-yes">178x</span>
650
+ <span class="cline-any cline-neutral">&nbsp;</span>
651
+ <span class="cline-any cline-yes">178x</span>
652
+ <span class="cline-any cline-yes">49x</span>
653
+ <span class="cline-any cline-neutral">&nbsp;</span>
654
+ <span class="cline-any cline-neutral">&nbsp;</span>
655
+ <span class="cline-any cline-yes">129x</span>
656
+ <span class="cline-any cline-yes">369x</span>
657
+ <span class="cline-any cline-neutral">&nbsp;</span>
658
+ <span class="cline-any cline-yes">369x</span>
659
+ <span class="cline-any cline-neutral">&nbsp;</span>
660
+ <span class="cline-any cline-neutral">&nbsp;</span>
661
+ <span class="cline-any cline-neutral">&nbsp;</span>
272
662
  <span class="cline-any cline-neutral">&nbsp;</span>
273
663
  <span class="cline-any cline-neutral">&nbsp;</span>
274
664
  <span class="cline-any cline-neutral">&nbsp;</span>
275
- <span class="cline-any cline-yes">120x</span>
665
+ <span class="cline-any cline-yes">13x</span>
666
+ <span class="cline-any cline-yes">13x</span>
667
+ <span class="cline-any cline-yes">13x</span>
276
668
  <span class="cline-any cline-neutral">&nbsp;</span>
277
669
  <span class="cline-any cline-neutral">&nbsp;</span>
278
- <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import {
670
+ <span class="cline-any cline-yes">356x</span>
671
+ <span class="cline-any cline-neutral">&nbsp;</span>
672
+ <span class="cline-any cline-neutral">&nbsp;</span>
673
+ <span class="cline-any cline-neutral">&nbsp;</span>
674
+ <span class="cline-any cline-yes">1x</span>
675
+ <span class="cline-any cline-yes">1x</span>
676
+ <span class="cline-any cline-yes">1x</span>
677
+ <span class="cline-any cline-neutral">&nbsp;</span>
678
+ <span class="cline-any cline-neutral">&nbsp;</span>
679
+ <span class="cline-any cline-neutral">&nbsp;</span>
680
+ <span class="cline-any cline-yes">129x</span>
681
+ <span class="cline-any cline-neutral">&nbsp;</span>
682
+ <span class="cline-any cline-neutral">&nbsp;</span>
683
+ <span class="cline-any cline-neutral">&nbsp;</span>
684
+ <span class="cline-any cline-yes">573x</span>
685
+ <span class="cline-any cline-neutral">&nbsp;</span>
686
+ <span class="cline-any cline-yes">563x</span>
687
+ <span class="cline-any cline-neutral">&nbsp;</span>
688
+ <span class="cline-any cline-neutral">&nbsp;</span>
689
+ <span class="cline-any cline-yes">10x</span>
690
+ <span class="cline-any cline-neutral">&nbsp;</span>
691
+ <span class="cline-any cline-no">&nbsp;</span>
692
+ <span class="cline-any cline-neutral">&nbsp;</span>
693
+ <span class="cline-any cline-neutral">&nbsp;</span>
694
+ <span class="cline-any cline-yes">10x</span>
695
+ <span class="cline-any cline-yes">10x</span>
696
+ <span class="cline-any cline-neutral">&nbsp;</span>
697
+ <span class="cline-any cline-no">&nbsp;</span>
698
+ <span class="cline-any cline-neutral">&nbsp;</span>
699
+ <span class="cline-any cline-neutral">&nbsp;</span>
700
+ <span class="cline-any cline-neutral">&nbsp;</span>
701
+ <span class="cline-any cline-neutral">&nbsp;</span>
702
+ <span class="cline-any cline-neutral">&nbsp;</span>
703
+ <span class="cline-any cline-neutral">&nbsp;</span>
704
+ <span class="cline-any cline-no">&nbsp;</span>
705
+ <span class="cline-any cline-neutral">&nbsp;</span>
706
+ <span class="cline-any cline-neutral">&nbsp;</span>
707
+ <span class="cline-any cline-neutral">&nbsp;</span>
708
+ <span class="cline-any cline-neutral">&nbsp;</span>
709
+ <span class="cline-any cline-neutral">&nbsp;</span>
710
+ <span class="cline-any cline-neutral">&nbsp;</span>
711
+ <span class="cline-any cline-yes">242x</span>
712
+ <span class="cline-any cline-yes">5x</span>
713
+ <span class="cline-any cline-neutral">&nbsp;</span>
714
+ <span class="cline-any cline-neutral">&nbsp;</span>
715
+ <span class="cline-any cline-yes">237x</span>
716
+ <span class="cline-any cline-neutral">&nbsp;</span>
717
+ <span class="cline-any cline-neutral">&nbsp;</span>
718
+ <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import type {
279
719
  Feature,
280
720
  Segment,
281
- DatafileContentV1,
282
- DatafileContentV2,
283
- Attribute,
284
- AttributeKey,
721
+ DatafileContent,
285
722
  SegmentKey,
286
723
  FeatureKey,
724
+ Context,
725
+ Traffic,
726
+ Allocation,
727
+ GroupSegment,
728
+ Condition,
729
+ Force,
287
730
  } from "@featurevisor/types";
288
731
  &nbsp;
289
- export function parseJsonConditionsIfStringified&lt;T&gt;(record: T, key: string): T {
290
- if (typeof record[key] === "string" &amp;&amp; record[key] !== "*") {
291
- try {
292
- record[key] = JSON.parse(record[key]);
293
- } catch (e) {
294
- <span class="cstat-no" title="statement not covered" > console.error("Error parsing JSON", e);</span>
295
- }
296
- }
732
+ import { conditionIsMatched } from "./conditions";
733
+ import { Logger } from "./logger";
297
734
  &nbsp;
298
- return record;
735
+ export type GetRegex = (regexString: string, regexFlags: string) =&gt; RegExp;
736
+ &nbsp;
737
+ export interface DatafileReaderOptions {
738
+ datafile: DatafileContent;
739
+ logger: Logger;
740
+ }
741
+ &nbsp;
742
+ export interface ForceResult {
743
+ force?: Force;
744
+ forceIndex?: number;
299
745
  }
300
746
  &nbsp;
301
747
  export class DatafileReader {
302
748
  private schemaVersion: string;
303
749
  private revision: string;
304
750
  &nbsp;
305
- private attributes: Record&lt;AttributeKey, Attribute&gt;;
306
751
  private segments: Record&lt;SegmentKey, Segment&gt;;
307
752
  private features: Record&lt;FeatureKey, Feature&gt;;
308
753
  &nbsp;
309
- constructor(datafileJson: DatafileContentV1 | DatafileContentV2) {
310
- this.schemaVersion = datafileJson.schemaVersion;
311
- this.revision = datafileJson.revision;
754
+ private logger: Logger;
312
755
  &nbsp;
313
- if (this.schemaVersion === "2") {
314
- // v2
315
- const datafileJsonV2 = datafileJson as DatafileContentV2;
756
+ // done to avoid creating new RegExp objects for the same regex string and flags.
757
+ // kept here to avoid memory leaks.
758
+ // if datafile is reset, this cache will be cleared.
759
+ private regexCache: Record&lt;string, RegExp&gt;;
316
760
  &nbsp;
317
- this.attributes = datafileJsonV2.attributes;
318
- this.segments = datafileJsonV2.segments;
319
- this.features = datafileJsonV2.features;
320
- } else {
321
- // v1
322
- const datafileJsonV1 = datafileJson as DatafileContentV1;
761
+ constructor(options: DatafileReaderOptions) {
762
+ const { datafile, logger } = options;
323
763
  &nbsp;
324
- this.attributes = {};
325
- datafileJsonV1.attributes.forEach((a) =&gt; {
326
- this.attributes[a.key] = a;
327
- });
764
+ this.logger = logger;
328
765
  &nbsp;
329
- this.segments = {};
330
- datafileJsonV1.segments.forEach((s) =&gt; {
331
- this.segments[s.key] = s;
332
- });
766
+ this.schemaVersion = datafile.schemaVersion;
767
+ this.revision = datafile.revision;
333
768
  &nbsp;
334
- this.features = {};
335
- datafileJsonV1.features.forEach((f) =&gt; {
336
- if (Array.isArray(f.variablesSchema)) {
337
- f.variablesSchema = f.variablesSchema.reduce((acc, variable) =&gt; {
338
- acc[variable.key] = variable;
339
- return acc;
340
- }, {});
341
- }
769
+ this.segments = datafile.segments;
770
+ this.features = datafile.features;
342
771
  &nbsp;
343
- this.features[f.key] = f;
344
- });
345
- }
772
+ this.regexCache = {};
346
773
  }
347
774
  &nbsp;
348
775
  getRevision(): string {
@@ -353,32 +780,265 @@ export class DatafileReader {
353
780
  return this.schemaVersion;
354
781
  }
355
782
  &nbsp;
356
- getAllAttributes(): Attribute[] {
357
- const result: Attribute[] = [];
783
+ getSegment(segmentKey: SegmentKey): Segment | undefined {
784
+ const segment = this.segments[segmentKey];
785
+ &nbsp;
786
+ if (!segment) {
787
+ return undefined;
788
+ }
789
+ &nbsp;
790
+ segment.conditions = this.parseConditionsIfStringified(segment.conditions);
791
+ &nbsp;
792
+ return segment;
793
+ }
794
+ &nbsp;
795
+ getFeatureKeys(): string[] {
796
+ return Object.keys(this.features);
797
+ }
798
+ &nbsp;
799
+ getFeature(featureKey: FeatureKey): Feature | undefined {
800
+ return this.features[featureKey];
801
+ }
802
+ &nbsp;
803
+ getVariableKeys(featureKey: FeatureKey): string[] {
804
+ const feature = this.getFeature(featureKey);
805
+ &nbsp;
806
+ <span class="missing-if-branch" title="if path not taken" >I</span>if (!feature) {
807
+ <span class="cstat-no" title="statement not covered" > return [];</span>
808
+ }
809
+ &nbsp;
810
+ return Object.keys(feature.variablesSchema || {});
811
+ }
812
+ &nbsp;
813
+ hasVariations(featureKey: FeatureKey): boolean {
814
+ const feature = this.getFeature(featureKey);
358
815
  &nbsp;
359
- Object.keys(this.attributes).forEach((key) =&gt; {
360
- result.push(this.attributes[key]);
816
+ <span class="missing-if-branch" title="if path not taken" >I</span>if (!feature) {
817
+ <span class="cstat-no" title="statement not covered" > return false;</span>
818
+ }
819
+ &nbsp;
820
+ return Array.isArray(feature.variations) &amp;&amp; feature.variations.length &gt; 0;
821
+ }
822
+ &nbsp;
823
+ getRegex(regexString: string, regexFlags?: string): RegExp {
824
+ const flags = regexFlags || "";
825
+ const cacheKey = `${regexString}-${flags}`;
826
+ &nbsp;
827
+ if (this.regexCache[cacheKey]) {
828
+ return this.regexCache[cacheKey];
829
+ }
830
+ &nbsp;
831
+ const regex = new RegExp(regexString, flags);
832
+ this.regexCache[cacheKey] = regex;
833
+ &nbsp;
834
+ return regex;
835
+ }
836
+ &nbsp;
837
+ allConditionsAreMatched(conditions: Condition[] | Condition, context: Context): boolean {
838
+ if (typeof conditions === "string") {
839
+ if (conditions === "*") {
840
+ return true;
841
+ }
842
+ &nbsp;
843
+ return false;
844
+ }
845
+ &nbsp;
846
+ const getRegex = (regexString: string, regexFlags: string) =&gt;
847
+ this.getRegex(regexString, regexFlags);
848
+ &nbsp;
849
+ if ("attribute" in conditions) {
850
+ try {
851
+ return conditionIsMatched(conditions, context, getRegex);
852
+ } catch (e) {
853
+ <span class="cstat-no" title="statement not covered" > this.logger.warn(e.message, {</span>
854
+ error: e,
855
+ details: {
856
+ condition: conditions,
857
+ context,
858
+ },
859
+ });
860
+ &nbsp;
861
+ <span class="cstat-no" title="statement not covered" > return false;</span>
862
+ }
863
+ }
864
+ &nbsp;
865
+ if ("and" in conditions &amp;&amp; Array.isArray(conditions.and)) {
866
+ return conditions.and.every((c) =&gt; this.allConditionsAreMatched(c, context));
867
+ }
868
+ &nbsp;
869
+ if ("or" in conditions &amp;&amp; Array.isArray(conditions.or)) {
870
+ return conditions.or.some((c) =&gt; this.allConditionsAreMatched(c, context));
871
+ }
872
+ &nbsp;
873
+ if ("not" in conditions &amp;&amp; Array.isArray(conditions.not)) {
874
+ return conditions.not.every(
875
+ () =&gt;
876
+ this.allConditionsAreMatched(
877
+ {
878
+ and: conditions.not,
879
+ },
880
+ context,
881
+ ) === false,
882
+ );
883
+ }
884
+ &nbsp;
885
+ if (Array.isArray(conditions)) {
886
+ return conditions.every((c) =&gt; this.allConditionsAreMatched(c, context));
887
+ }
888
+ &nbsp;
889
+ <span class="cstat-no" title="statement not covered" > return false;</span>
890
+ }
891
+ &nbsp;
892
+ segmentIsMatched(segment: Segment, context: Context): boolean {
893
+ return this.allConditionsAreMatched(segment.conditions as Condition | Condition[], context);
894
+ }
895
+ &nbsp;
896
+ allSegmentsAreMatched(
897
+ groupSegments: GroupSegment | GroupSegment[] | "*",
898
+ context: Context,
899
+ ): boolean {
900
+ if (groupSegments === "*") {
901
+ return true;
902
+ }
903
+ &nbsp;
904
+ if (typeof groupSegments === "string") {
905
+ const segment = this.getSegment(groupSegments);
906
+ &nbsp;
907
+ if (segment) {
908
+ return this.segmentIsMatched(segment, context);
909
+ }
910
+ &nbsp;
911
+ <span class="cstat-no" title="statement not covered" > return false;</span>
912
+ }
913
+ &nbsp;
914
+ if (typeof groupSegments === "object") {
915
+ if ("and" in groupSegments &amp;&amp; Array.isArray(groupSegments.and)) {
916
+ return groupSegments.and.every((groupSegment) =&gt;
917
+ this.allSegmentsAreMatched(groupSegment, context),
918
+ );
919
+ }
920
+ &nbsp;
921
+ if ("or" in groupSegments &amp;&amp; Array.isArray(groupSegments.or)) {
922
+ return groupSegments.or.some((groupSegment) =&gt;
923
+ this.allSegmentsAreMatched(groupSegment, context),
924
+ );
925
+ }
926
+ &nbsp;
927
+ if ("not" in groupSegments &amp;&amp; Array.isArray(groupSegments.not)) {
928
+ return groupSegments.not.every(
929
+ (groupSegment) =&gt; this.allSegmentsAreMatched(groupSegment, context) === false,
930
+ );
931
+ }
932
+ }
933
+ &nbsp;
934
+ if (Array.isArray(groupSegments)) {
935
+ return groupSegments.every((groupSegment) =&gt;
936
+ this.allSegmentsAreMatched(groupSegment, context),
937
+ );
938
+ }
939
+ &nbsp;
940
+ <span class="cstat-no" title="statement not covered" > return false;</span>
941
+ }
942
+ &nbsp;
943
+ getMatchedTraffic(traffic: Traffic[], context: Context): Traffic | undefined {
944
+ return traffic.find((t) =&gt; {
945
+ if (!this.allSegmentsAreMatched(this.parseSegmentsIfStringified(t.segments), context)) {
946
+ return false;
947
+ }
948
+ &nbsp;
949
+ return true;
361
950
  });
951
+ }
362
952
  &nbsp;
363
- return result;
953
+ getMatchedAllocation(traffic: Traffic, bucketValue: number): Allocation | undefined {
954
+ <span class="missing-if-branch" title="if path not taken" >I</span>if (!traffic.allocation) {
955
+ <span class="cstat-no" title="statement not covered" > return undefined;</span>
956
+ }
957
+ &nbsp;
958
+ for (const allocation of traffic.allocation) {
959
+ const [start, end] = allocation.range;
960
+ &nbsp;
961
+ if (allocation.range &amp;&amp; start &lt;= bucketValue &amp;&amp; end &gt;= bucketValue) {
962
+ return allocation;
963
+ }
964
+ }
965
+ &nbsp;
966
+ return undefined;
364
967
  }
365
968
  &nbsp;
366
- getAttribute(attributeKey: AttributeKey): Attribute | undefined {
367
- return this.attributes[attributeKey];
969
+ getMatchedForce(featureKey: FeatureKey | Feature, context: Context): ForceResult {
970
+ const result: ForceResult = {
971
+ force: undefined,
972
+ forceIndex: undefined,
973
+ };
974
+ &nbsp;
975
+ const feature = typeof featureKey === "string" ? <span class="branch-0 cbranch-no" title="branch not covered" >this.getFeature(featureKey) </span>: featureKey;
976
+ &nbsp;
977
+ if (!feature || !feature.force) {
978
+ return result;
979
+ }
980
+ &nbsp;
981
+ for (let i = 0; i &lt; feature.force.length; i++) {
982
+ const currentForce = feature.force[i];
983
+ &nbsp;
984
+ if (
985
+ currentForce.conditions &amp;&amp;
986
+ this.allConditionsAreMatched(
987
+ this.parseConditionsIfStringified(currentForce.conditions),
988
+ context,
989
+ )
990
+ ) {
991
+ result.force = currentForce;
992
+ result.forceIndex = i;
993
+ break;
994
+ }
995
+ &nbsp;
996
+ if (
997
+ currentForce.segments &amp;&amp;
998
+ this.allSegmentsAreMatched(this.parseSegmentsIfStringified(currentForce.segments), context)
999
+ ) {
1000
+ result.force = currentForce;
1001
+ result.forceIndex = i;
1002
+ break;
1003
+ }
1004
+ }
1005
+ &nbsp;
1006
+ return result;
368
1007
  }
369
1008
  &nbsp;
370
- getSegment(segmentKey: SegmentKey): Segment | undefined {
371
- const segment = this.segments[segmentKey];
1009
+ parseConditionsIfStringified(conditions: Condition | Condition[]): Condition | Condition[] {
1010
+ if (typeof conditions !== "string") {
1011
+ // already parsed
1012
+ return conditions;
1013
+ }
372
1014
  &nbsp;
373
- if (!segment) {
374
- return undefined;
1015
+ <span class="missing-if-branch" title="if path not taken" >I</span>if (conditions === "*") {
1016
+ // everyone
1017
+ <span class="cstat-no" title="statement not covered" > return conditions;</span>
375
1018
  }
376
1019
  &nbsp;
377
- return parseJsonConditionsIfStringified(segment, "conditions");
1020
+ try {
1021
+ return JSON.parse(conditions);
1022
+ } catch (e) {
1023
+ <span class="cstat-no" title="statement not covered" > this.logger.error("Error parsing conditions", {</span>
1024
+ error: e,
1025
+ details: {
1026
+ conditions,
1027
+ },
1028
+ });
1029
+ &nbsp;
1030
+ <span class="cstat-no" title="statement not covered" > return conditions;</span>
1031
+ }
378
1032
  }
379
1033
  &nbsp;
380
- getFeature(featureKey: FeatureKey): Feature | undefined {
381
- return this.features[featureKey];
1034
+ parseSegmentsIfStringified(
1035
+ segments: GroupSegment | GroupSegment[],
1036
+ ): GroupSegment | GroupSegment[] {
1037
+ if (typeof segments === "string" &amp;&amp; (segments.startsWith("{") || segments.startsWith("["))) {
1038
+ return JSON.parse(segments);
1039
+ }
1040
+ &nbsp;
1041
+ return segments;
382
1042
  }
383
1043
  }
384
1044
  &nbsp;</pre></td></tr></table></pre>
@@ -388,7 +1048,7 @@ export class DatafileReader {
388
1048
  <div class='footer quiet pad2 space-top1 center small'>
389
1049
  Code coverage generated by
390
1050
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
391
- at 2025-03-31T21:26:29.644Z
1051
+ at 2025-07-13T22:31:55.309Z
392
1052
  </div>
393
1053
  <script src="prettify.js"></script>
394
1054
  <script>