@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
@@ -3,7 +3,7 @@
3
3
  <html lang="en">
4
4
 
5
5
  <head>
6
- <title>Code coverage report for feature.ts</title>
6
+ <title>Code coverage report for hooks.ts</title>
7
7
  <meta charset="utf-8" />
8
8
  <link rel="stylesheet" href="prettify.css" />
9
9
  <link rel="stylesheet" href="base.css" />
@@ -19,34 +19,34 @@
19
19
  <body>
20
20
  <div class='wrapper'>
21
21
  <div class='pad1'>
22
- <h1><a href="index.html">All files</a> feature.ts</h1>
22
+ <h1><a href="index.html">All files</a> hooks.ts</h1>
23
23
  <div class='clearfix'>
24
24
 
25
25
  <div class='fl pad1y space-right2'>
26
- <span class="strong">97.67% </span>
26
+ <span class="strong">62.5% </span>
27
27
  <span class="quiet">Statements</span>
28
- <span class='fraction'>42/43</span>
28
+ <span class='fraction'>10/16</span>
29
29
  </div>
30
30
 
31
31
 
32
32
  <div class='fl pad1y space-right2'>
33
- <span class="strong">95% </span>
33
+ <span class="strong">50% </span>
34
34
  <span class="quiet">Branches</span>
35
- <span class='fraction'>19/20</span>
35
+ <span class='fraction'>1/2</span>
36
36
  </div>
37
37
 
38
38
 
39
39
  <div class='fl pad1y space-right2'>
40
- <span class="strong">100% </span>
40
+ <span class="strong">50% </span>
41
41
  <span class="quiet">Functions</span>
42
- <span class='fraction'>7/7</span>
42
+ <span class='fraction'>4/8</span>
43
43
  </div>
44
44
 
45
45
 
46
46
  <div class='fl pad1y space-right2'>
47
- <span class="strong">97.61% </span>
47
+ <span class="strong">71.42% </span>
48
48
  <span class="quiet">Lines</span>
49
- <span class='fraction'>41/42</span>
49
+ <span class='fraction'>10/14</span>
50
50
  </div>
51
51
 
52
52
 
@@ -61,7 +61,7 @@
61
61
  </div>
62
62
  </template>
63
63
  </div>
64
- <div class='status-line high'></div>
64
+ <div class='status-line medium'></div>
65
65
  <pre><table class="coverage">
66
66
  <tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
67
67
  <a name='L2'></a><a href='#L2'>2</a>
@@ -151,92 +151,16 @@
151
151
  <a name='L86'></a><a href='#L86'>86</a>
152
152
  <a name='L87'></a><a href='#L87'>87</a>
153
153
  <a name='L88'></a><a href='#L88'>88</a>
154
- <a name='L89'></a><a href='#L89'>89</a>
155
- <a name='L90'></a><a href='#L90'>90</a>
156
- <a name='L91'></a><a href='#L91'>91</a>
157
- <a name='L92'></a><a href='#L92'>92</a>
158
- <a name='L93'></a><a href='#L93'>93</a>
159
- <a name='L94'></a><a href='#L94'>94</a>
160
- <a name='L95'></a><a href='#L95'>95</a>
161
- <a name='L96'></a><a href='#L96'>96</a>
162
- <a name='L97'></a><a href='#L97'>97</a>
163
- <a name='L98'></a><a href='#L98'>98</a>
164
- <a name='L99'></a><a href='#L99'>99</a>
165
- <a name='L100'></a><a href='#L100'>100</a>
166
- <a name='L101'></a><a href='#L101'>101</a>
167
- <a name='L102'></a><a href='#L102'>102</a>
168
- <a name='L103'></a><a href='#L103'>103</a>
169
- <a name='L104'></a><a href='#L104'>104</a>
170
- <a name='L105'></a><a href='#L105'>105</a>
171
- <a name='L106'></a><a href='#L106'>106</a>
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></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
204
- <span class="cline-any cline-neutral">&nbsp;</span>
205
- <span class="cline-any cline-yes">1x</span>
206
- <span class="cline-any cline-yes">1x</span>
207
- <span class="cline-any cline-neutral">&nbsp;</span>
208
- <span class="cline-any cline-neutral">&nbsp;</span>
209
- <span class="cline-any cline-yes">1x</span>
210
- <span class="cline-any cline-neutral">&nbsp;</span>
211
- <span class="cline-any cline-neutral">&nbsp;</span>
212
- <span class="cline-any cline-neutral">&nbsp;</span>
213
- <span class="cline-any cline-yes">39x</span>
214
- <span class="cline-any cline-yes">65x</span>
215
- <span class="cline-any cline-neutral">&nbsp;</span>
216
- <span class="cline-any cline-yes">65x</span>
217
- <span class="cline-any cline-yes">37x</span>
154
+ <a name='L89'></a><a href='#L89'>89</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
218
155
  <span class="cline-any cline-neutral">&nbsp;</span>
219
156
  <span class="cline-any cline-neutral">&nbsp;</span>
220
157
  <span class="cline-any cline-neutral">&nbsp;</span>
221
- <span class="cline-any cline-yes">2x</span>
222
- <span class="cline-any cline-neutral">&nbsp;</span>
223
- <span class="cline-any cline-neutral">&nbsp;</span>
224
- <span class="cline-any cline-yes">1x</span>
225
- <span class="cline-any cline-yes">147x</span>
226
- <span class="cline-any cline-yes">5x</span>
227
- <span class="cline-any cline-neutral">&nbsp;</span>
228
- <span class="cline-any cline-neutral">&nbsp;</span>
229
- <span class="cline-any cline-yes">142x</span>
230
- <span class="cline-any cline-neutral">&nbsp;</span>
231
158
  <span class="cline-any cline-neutral">&nbsp;</span>
232
- <span class="cline-any cline-yes">1x</span>
233
159
  <span class="cline-any cline-neutral">&nbsp;</span>
234
160
  <span class="cline-any cline-neutral">&nbsp;</span>
235
161
  <span class="cline-any cline-neutral">&nbsp;</span>
236
162
  <span class="cline-any cline-neutral">&nbsp;</span>
237
163
  <span class="cline-any cline-neutral">&nbsp;</span>
238
- <span class="cline-any cline-yes">56x</span>
239
- <span class="cline-any cline-yes">81x</span>
240
164
  <span class="cline-any cline-neutral">&nbsp;</span>
241
165
  <span class="cline-any cline-neutral">&nbsp;</span>
242
166
  <span class="cline-any cline-neutral">&nbsp;</span>
@@ -244,17 +168,12 @@
244
168
  <span class="cline-any cline-neutral">&nbsp;</span>
245
169
  <span class="cline-any cline-neutral">&nbsp;</span>
246
170
  <span class="cline-any cline-neutral">&nbsp;</span>
247
- <span class="cline-any cline-yes">29x</span>
248
171
  <span class="cline-any cline-neutral">&nbsp;</span>
249
172
  <span class="cline-any cline-neutral">&nbsp;</span>
250
- <span class="cline-any cline-yes">52x</span>
251
173
  <span class="cline-any cline-neutral">&nbsp;</span>
252
174
  <span class="cline-any cline-neutral">&nbsp;</span>
253
- <span class="cline-any cline-yes">56x</span>
254
- <span class="cline-any cline-yes">51x</span>
255
175
  <span class="cline-any cline-neutral">&nbsp;</span>
256
176
  <span class="cline-any cline-neutral">&nbsp;</span>
257
- <span class="cline-any cline-yes">5x</span>
258
177
  <span class="cline-any cline-neutral">&nbsp;</span>
259
178
  <span class="cline-any cline-neutral">&nbsp;</span>
260
179
  <span class="cline-any cline-neutral">&nbsp;</span>
@@ -262,15 +181,12 @@
262
181
  <span class="cline-any cline-neutral">&nbsp;</span>
263
182
  <span class="cline-any cline-neutral">&nbsp;</span>
264
183
  <span class="cline-any cline-neutral">&nbsp;</span>
265
- <span class="cline-any cline-yes">1x</span>
266
184
  <span class="cline-any cline-neutral">&nbsp;</span>
267
185
  <span class="cline-any cline-neutral">&nbsp;</span>
268
186
  <span class="cline-any cline-neutral">&nbsp;</span>
269
187
  <span class="cline-any cline-neutral">&nbsp;</span>
270
188
  <span class="cline-any cline-neutral">&nbsp;</span>
271
189
  <span class="cline-any cline-neutral">&nbsp;</span>
272
- <span class="cline-any cline-yes">39x</span>
273
- <span class="cline-any cline-yes">59x</span>
274
190
  <span class="cline-any cline-neutral">&nbsp;</span>
275
191
  <span class="cline-any cline-neutral">&nbsp;</span>
276
192
  <span class="cline-any cline-neutral">&nbsp;</span>
@@ -278,201 +194,138 @@
278
194
  <span class="cline-any cline-neutral">&nbsp;</span>
279
195
  <span class="cline-any cline-neutral">&nbsp;</span>
280
196
  <span class="cline-any cline-neutral">&nbsp;</span>
281
- <span class="cline-any cline-yes">39x</span>
282
- <span class="cline-any cline-no">&nbsp;</span>
283
- <span class="cline-any cline-neutral">&nbsp;</span>
284
- <span class="cline-any cline-neutral">&nbsp;</span>
285
- <span class="cline-any cline-neutral">&nbsp;</span>
286
- <span class="cline-any cline-neutral">&nbsp;</span>
287
- <span class="cline-any cline-neutral">&nbsp;</span>
288
- <span class="cline-any cline-yes">39x</span>
289
- <span class="cline-any cline-neutral">&nbsp;</span>
290
- <span class="cline-any cline-yes">39x</span>
291
- <span class="cline-any cline-neutral">&nbsp;</span>
292
- <span class="cline-any cline-neutral">&nbsp;</span>
293
- <span class="cline-any cline-neutral">&nbsp;</span>
294
197
  <span class="cline-any cline-neutral">&nbsp;</span>
295
198
  <span class="cline-any cline-neutral">&nbsp;</span>
296
199
  <span class="cline-any cline-neutral">&nbsp;</span>
297
200
  <span class="cline-any cline-neutral">&nbsp;</span>
298
201
  <span class="cline-any cline-neutral">&nbsp;</span>
299
202
  <span class="cline-any cline-neutral">&nbsp;</span>
203
+ <span class="cline-any cline-yes">2x</span>
204
+ <span class="cline-any cline-yes">19x</span>
300
205
  <span class="cline-any cline-neutral">&nbsp;</span>
301
- <span class="cline-any cline-yes">1x</span>
302
206
  <span class="cline-any cline-neutral">&nbsp;</span>
303
207
  <span class="cline-any cline-neutral">&nbsp;</span>
208
+ <span class="cline-any cline-yes">19x</span>
304
209
  <span class="cline-any cline-neutral">&nbsp;</span>
210
+ <span class="cline-any cline-yes">19x</span>
211
+ <span class="cline-any cline-yes">19x</span>
212
+ <span class="cline-any cline-yes">6x</span>
305
213
  <span class="cline-any cline-neutral">&nbsp;</span>
306
214
  <span class="cline-any cline-neutral">&nbsp;</span>
307
- <span class="cline-any cline-yes">108x</span>
308
215
  <span class="cline-any cline-neutral">&nbsp;</span>
309
216
  <span class="cline-any cline-neutral">&nbsp;</span>
310
217
  <span class="cline-any cline-neutral">&nbsp;</span>
218
+ <span class="cline-any cline-yes">6x</span>
219
+ <span class="cline-any cline-no">&nbsp;</span>
311
220
  <span class="cline-any cline-neutral">&nbsp;</span>
312
- <span class="cline-any cline-yes">108x</span>
313
- <span class="cline-any cline-yes">51x</span>
314
221
  <span class="cline-any cline-neutral">&nbsp;</span>
315
222
  <span class="cline-any cline-neutral">&nbsp;</span>
316
- <span class="cline-any cline-yes">57x</span>
317
- <span class="cline-any cline-yes">153x</span>
318
223
  <span class="cline-any cline-neutral">&nbsp;</span>
319
- <span class="cline-any cline-yes">153x</span>
224
+ <span class="cline-any cline-no">&nbsp;</span>
320
225
  <span class="cline-any cline-neutral">&nbsp;</span>
321
226
  <span class="cline-any cline-neutral">&nbsp;</span>
227
+ <span class="cline-any cline-yes">6x</span>
322
228
  <span class="cline-any cline-neutral">&nbsp;</span>
323
- <span class="cline-any cline-yes">13x</span>
324
- <span class="cline-any cline-yes">13x</span>
325
- <span class="cline-any cline-yes">13x</span>
229
+ <span class="cline-any cline-yes">6x</span>
230
+ <span class="cline-any cline-no">&nbsp;</span>
326
231
  <span class="cline-any cline-neutral">&nbsp;</span>
327
232
  <span class="cline-any cline-neutral">&nbsp;</span>
328
- <span class="cline-any cline-yes">140x</span>
329
233
  <span class="cline-any cline-neutral">&nbsp;</span>
330
234
  <span class="cline-any cline-neutral">&nbsp;</span>
235
+ <span class="cline-any cline-no">&nbsp;</span>
331
236
  <span class="cline-any cline-neutral">&nbsp;</span>
332
- <span class="cline-any cline-yes">1x</span>
333
- <span class="cline-any cline-yes">1x</span>
334
- <span class="cline-any cline-yes">1x</span>
335
237
  <span class="cline-any cline-neutral">&nbsp;</span>
336
238
  <span class="cline-any cline-neutral">&nbsp;</span>
239
+ <span class="cline-any cline-yes">415x</span>
337
240
  <span class="cline-any cline-neutral">&nbsp;</span>
338
- <span class="cline-any cline-yes">57x</span>
339
241
  <span class="cline-any cline-neutral">&nbsp;</span>
340
- <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import { Allocation, Context, Traffic, Feature, Force } from "@featurevisor/types";
341
- import { DatafileReader } from "./datafileReader";
342
- import { allGroupSegmentsAreMatched } from "./segments";
343
- import { allConditionsAreMatched } from "./conditions";
344
- import { Logger } from "./logger";
242
+ <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import type { BucketBy, BucketKey, BucketValue, Context, FeatureKey } from "@featurevisor/types";
345
243
  &nbsp;
346
- export function getMatchedAllocation(
347
- traffic: Traffic,
348
- bucketValue: number,
349
- ): Allocation | undefined {
350
- for (const allocation of traffic.allocation) {
351
- const [start, end] = allocation.range;
244
+ import type { EvaluateOptions, Evaluation } from "./evaluate";
245
+ import type { Logger } from "./logger";
352
246
  &nbsp;
353
- if (allocation.range &amp;&amp; start &lt;= bucketValue &amp;&amp; end &gt;= bucketValue) {
354
- return allocation;
355
- }
356
- }
357
- &nbsp;
358
- return undefined;
247
+ /**
248
+ * bucketKey
249
+ */
250
+ export interface ConfigureBucketKeyOptions {
251
+ featureKey: FeatureKey;
252
+ context: Context;
253
+ bucketBy: BucketBy;
254
+ bucketKey: string; // the initial bucket key, which can be modified by hooks
359
255
  }
360
256
  &nbsp;
361
- export function parseFromStringifiedSegments(value) {
362
- if (typeof value === "string" &amp;&amp; (value.startsWith("{") || value.startsWith("["))) {
363
- return JSON.parse(value);
364
- }
257
+ export type ConfigureBucketKey = (options: ConfigureBucketKeyOptions) =&gt; BucketKey;
365
258
  &nbsp;
366
- return value;
259
+ /**
260
+ * bucketValue
261
+ */
262
+ export interface ConfigureBucketValueOptions {
263
+ featureKey: FeatureKey;
264
+ bucketKey: string;
265
+ context: Context;
266
+ bucketValue: number; // the initial bucket value, which can be modified by hooks
367
267
  }
368
268
  &nbsp;
369
- export function getMatchedTraffic(
370
- traffic: Traffic[],
371
- context: Context,
372
- datafileReader: DatafileReader,
373
- logger: Logger,
374
- ): Traffic | undefined {
375
- const matchedTraffic = traffic.find((t) =&gt; {
376
- if (
377
- !allGroupSegmentsAreMatched(
378
- parseFromStringifiedSegments(t.segments),
379
- context,
380
- datafileReader,
381
- logger,
382
- )
383
- ) {
384
- return false;
385
- }
269
+ export type ConfigureBucketValue = (options: ConfigureBucketValueOptions) =&gt; BucketValue;
386
270
  &nbsp;
387
- return true;
388
- });
271
+ /**
272
+ * Hooks
273
+ */
274
+ export interface Hook {
275
+ name: string;
389
276
  &nbsp;
390
- if (matchedTraffic &amp;&amp; matchedTraffic.percentage &gt; 0) {
391
- return matchedTraffic;
392
- }
277
+ before?: (options: EvaluateOptions) =&gt; EvaluateOptions;
393
278
  &nbsp;
394
- return;
395
- }
396
- &nbsp;
397
- export interface MatchedTrafficAndAllocation {
398
- matchedTraffic: Traffic | undefined;
399
- matchedAllocation: Allocation | undefined;
400
- }
279
+ bucketKey?: ConfigureBucketKey;
401
280
  &nbsp;
402
- export function getMatchedTrafficAndAllocation(
403
- traffic: Traffic[],
404
- context: Context,
405
- bucketValue: number,
406
- datafileReader: DatafileReader,
407
- logger: Logger,
408
- ): MatchedTrafficAndAllocation {
409
- const matchedTraffic = traffic.find((t) =&gt; {
410
- return allGroupSegmentsAreMatched(
411
- parseFromStringifiedSegments(t.segments),
412
- context,
413
- datafileReader,
414
- logger,
415
- );
416
- });
281
+ bucketValue?: ConfigureBucketValue;
417
282
  &nbsp;
418
- <span class="missing-if-branch" title="if path not taken" >I</span>if (!matchedTraffic) {
419
- <span class="cstat-no" title="statement not covered" > return {</span>
420
- matchedTraffic: undefined,
421
- matchedAllocation: undefined,
422
- };
423
- }
424
- &nbsp;
425
- const matchedAllocation = getMatchedAllocation(matchedTraffic, bucketValue);
426
- &nbsp;
427
- return {
428
- matchedTraffic,
429
- matchedAllocation,
430
- };
283
+ after?: (evaluation: Evaluation, options: EvaluateOptions) =&gt; Evaluation;
431
284
  }
432
285
  &nbsp;
433
- export interface ForceResult {
434
- force?: Force;
435
- forceIndex?: number;
286
+ export interface HooksManagerOptions {
287
+ hooks?: Hook[];
288
+ logger: Logger;
436
289
  }
437
290
  &nbsp;
438
- export function findForceFromFeature(
439
- feature: Feature,
440
- context: Context,
441
- datafileReader: DatafileReader,
442
- logger: Logger,
443
- ): ForceResult {
444
- const result: ForceResult = {
445
- force: undefined,
446
- forceIndex: undefined,
447
- };
291
+ export class HooksManager {
292
+ private hooks: Hook[] = [];
293
+ private logger: Logger;
294
+ &nbsp;
295
+ constructor(options: HooksManagerOptions) {
296
+ this.logger = options.logger;
448
297
  &nbsp;
449
- if (!feature.force) {
450
- return result;
298
+ if (options.hooks) {
299
+ options.hooks.forEach((hook) =&gt; {
300
+ this.add(hook);
301
+ });
302
+ }
451
303
  }
452
304
  &nbsp;
453
- for (let i = 0; i &lt; feature.force.length; i++) {
454
- const currentForce = feature.force[i];
305
+ add(hook: Hook): (() =&gt; void) | undefined {
306
+ <span class="missing-if-branch" title="if path not taken" >I</span>if (this.hooks.some(<span class="fstat-no" title="function not covered" >(e</span>xistingHook) =&gt; <span class="cstat-no" title="statement not covered" >existingHook.name === hook.name)</span>) {
307
+ <span class="cstat-no" title="statement not covered" > this.logger.error(`Hook with name "${hook.name}" already exists.`, {</span>
308
+ name: hook.name,
309
+ hook: hook,
310
+ });
455
311
  &nbsp;
456
- if (
457
- currentForce.conditions &amp;&amp;
458
- allConditionsAreMatched(currentForce.conditions, context, logger)
459
- ) {
460
- result.force = currentForce;
461
- result.forceIndex = i;
462
- break;
312
+ <span class="cstat-no" title="statement not covered" > return;</span>
463
313
  }
464
314
  &nbsp;
465
- if (
466
- currentForce.segments &amp;&amp;
467
- allGroupSegmentsAreMatched(currentForce.segments, context, datafileReader, logger)
468
- ) {
469
- result.force = currentForce;
470
- result.forceIndex = i;
471
- break;
472
- }
315
+ this.hooks.push(hook);
316
+ &nbsp;
317
+ return <span class="fstat-no" title="function not covered" >() =</span>&gt; {
318
+ <span class="cstat-no" title="statement not covered" > this.remove(hook.name);</span>
319
+ };
473
320
  }
474
321
  &nbsp;
475
- return result;
322
+ <span class="fstat-no" title="function not covered" > remove(</span>name: string): void {
323
+ <span class="cstat-no" title="statement not covered" > this.hooks = this.hooks.filter(<span class="fstat-no" title="function not covered" >(h</span>ook) =&gt; <span class="cstat-no" title="statement not covered" >hook.name !== name)</span>;</span>
324
+ }
325
+ &nbsp;
326
+ getAll(): Hook[] {
327
+ return this.hooks;
328
+ }
476
329
  }
477
330
  &nbsp;</pre></td></tr></table></pre>
478
331
 
@@ -481,7 +334,7 @@ export function findForceFromFeature(
481
334
  <div class='footer quiet pad2 space-top1 center small'>
482
335
  Code coverage generated by
483
336
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
484
- at 2025-03-31T21:26:29.644Z
337
+ at 2025-07-13T22:31:55.309Z
485
338
  </div>
486
339
  <script src="prettify.js"></script>
487
340
  <script>