@featurevisor/sdk 0.36.0 → 0.37.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.
- package/CHANGELOG.md +11 -0
- package/README.md +14 -14
- package/coverage/clover.xml +224 -224
- package/coverage/coverage-final.json +4 -4
- package/coverage/lcov-report/bucket.ts.html +1 -1
- package/coverage/lcov-report/conditions.ts.html +38 -38
- package/coverage/lcov-report/datafileReader.ts.html +1 -1
- package/coverage/lcov-report/emitter.ts.html +1 -1
- package/coverage/lcov-report/feature.ts.html +7 -7
- package/coverage/lcov-report/index.html +1 -1
- package/coverage/lcov-report/instance.ts.html +74 -113
- package/coverage/lcov-report/logger.ts.html +1 -1
- package/coverage/lcov-report/segments.ts.html +10 -10
- package/coverage/lcov.info +391 -391
- package/dist/index.js +1 -1
- package/dist/index.js.gz +0 -0
- package/dist/index.js.map +1 -1
- package/lib/conditions.d.ts +3 -3
- package/lib/conditions.js +35 -35
- package/lib/conditions.js.map +1 -1
- package/lib/feature.d.ts +3 -3
- package/lib/feature.js +5 -5
- package/lib/feature.js.map +1 -1
- package/lib/instance.d.ts +27 -26
- package/lib/instance.js +80 -86
- package/lib/instance.js.map +1 -1
- package/lib/segments.d.ts +3 -3
- package/lib/segments.js +8 -8
- package/lib/segments.js.map +1 -1
- package/package.json +3 -3
- package/src/conditions.ts +37 -37
- package/src/feature.ts +6 -6
- package/src/instance.spec.ts +6 -6
- package/src/instance.ts +70 -83
- package/src/segments.ts +9 -9
|
@@ -109,7 +109,7 @@ export function getBucketedNumber(bucketKey: string): number {
|
|
|
109
109
|
<div class='footer quiet pad2 space-top1 center small'>
|
|
110
110
|
Code coverage generated by
|
|
111
111
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
112
|
-
at 2023-07-
|
|
112
|
+
at 2023-07-14T17:03:15.956Z
|
|
113
113
|
</div>
|
|
114
114
|
<script src="prettify.js"></script>
|
|
115
115
|
<script>
|
|
@@ -281,72 +281,72 @@
|
|
|
281
281
|
<span class="cline-any cline-neutral"> </span>
|
|
282
282
|
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">import { compareVersions } from "compare-versions";
|
|
283
283
|
|
|
284
|
-
import {
|
|
284
|
+
import { Context, Condition, PlainCondition } from "@featurevisor/types";
|
|
285
285
|
|
|
286
|
-
export function conditionIsMatched(condition: PlainCondition,
|
|
286
|
+
export function conditionIsMatched(condition: PlainCondition, context: Context): boolean {
|
|
287
287
|
const { attribute, operator, value } = condition;
|
|
288
288
|
|
|
289
289
|
if (operator === "equals") {
|
|
290
|
-
return
|
|
290
|
+
return context[attribute] === value;
|
|
291
291
|
} else if (operator === "notEquals") {
|
|
292
|
-
return
|
|
292
|
+
return context[attribute] !== value;
|
|
293
293
|
} else if (operator === "before" || operator === "after") {
|
|
294
294
|
// date comparisons
|
|
295
|
-
const
|
|
295
|
+
const valueInContext = context[attribute] as string | Date;
|
|
296
296
|
|
|
297
|
-
const
|
|
298
|
-
|
|
297
|
+
const dateInContext =
|
|
298
|
+
valueInContext instanceof Date ? valueInContext : new Date(valueInContext);
|
|
299
299
|
const dateInCondition = value instanceof Date ? <span class="branch-0 cbranch-no" title="branch not covered" >value </span>: new Date(value as string);
|
|
300
300
|
|
|
301
301
|
return operator === "before"
|
|
302
|
-
?
|
|
303
|
-
:
|
|
304
|
-
} else <span class="missing-if-branch" title="if path not taken" >I</span>if (typeof
|
|
302
|
+
? dateInContext < dateInCondition
|
|
303
|
+
: dateInContext > dateInCondition;
|
|
304
|
+
} else <span class="missing-if-branch" title="if path not taken" >I</span>if (typeof context[attribute] === "string" && Array.isArray(value)) {
|
|
305
305
|
// array
|
|
306
|
-
const
|
|
306
|
+
const valueInContext = <span class="cstat-no" title="statement not covered" >context[attribute] as string;</span>
|
|
307
307
|
|
|
308
308
|
<span class="cstat-no" title="statement not covered" > if (operator === "in") {</span>
|
|
309
|
-
<span class="cstat-no" title="statement not covered" > return value.indexOf(
|
|
309
|
+
<span class="cstat-no" title="statement not covered" > return value.indexOf(valueInContext) !== -1;</span>
|
|
310
310
|
} else <span class="cstat-no" title="statement not covered" ><span class="missing-if-branch" title="if path not taken" >I</span>if (operator === "notIn") {</span>
|
|
311
|
-
<span class="cstat-no" title="statement not covered" > return value.indexOf(
|
|
311
|
+
<span class="cstat-no" title="statement not covered" > return value.indexOf(valueInContext) === -1;</span>
|
|
312
312
|
}
|
|
313
|
-
} else if (typeof
|
|
313
|
+
} else if (typeof context[attribute] === "string" && typeof value === "string") {
|
|
314
314
|
// string
|
|
315
|
-
const
|
|
315
|
+
const valueInContext = context[attribute] as string;
|
|
316
316
|
|
|
317
317
|
<span class="missing-if-branch" title="if path not taken" >I</span>if (operator === "contains") {
|
|
318
|
-
<span class="cstat-no" title="statement not covered" > return
|
|
318
|
+
<span class="cstat-no" title="statement not covered" > return valueInContext.indexOf(value) !== -1;</span>
|
|
319
319
|
} else <span class="missing-if-branch" title="if path not taken" >I</span>if (operator === "notContains") {
|
|
320
|
-
<span class="cstat-no" title="statement not covered" > return
|
|
320
|
+
<span class="cstat-no" title="statement not covered" > return valueInContext.indexOf(value) === -1;</span>
|
|
321
321
|
} else <span class="missing-if-branch" title="if path not taken" >I</span>if (operator === "startsWith") {
|
|
322
|
-
<span class="cstat-no" title="statement not covered" > return
|
|
322
|
+
<span class="cstat-no" title="statement not covered" > return valueInContext.startsWith(value);</span>
|
|
323
323
|
} else <span class="missing-if-branch" title="if path not taken" >I</span>if (operator === "endsWith") {
|
|
324
|
-
<span class="cstat-no" title="statement not covered" > return
|
|
324
|
+
<span class="cstat-no" title="statement not covered" > return valueInContext.endsWith(value);</span>
|
|
325
325
|
} else if (operator === "semverEquals") {
|
|
326
|
-
return compareVersions(
|
|
326
|
+
return compareVersions(valueInContext, value) === 0;
|
|
327
327
|
} else if (operator === "semverNotEquals") {
|
|
328
|
-
return compareVersions(
|
|
328
|
+
return compareVersions(valueInContext, value) !== 0;
|
|
329
329
|
} else if (operator === "semverGreaterThan") {
|
|
330
|
-
return compareVersions(
|
|
330
|
+
return compareVersions(valueInContext, value) === 1;
|
|
331
331
|
} else if (operator === "semverGreaterThanOrEquals") {
|
|
332
|
-
return compareVersions(
|
|
332
|
+
return compareVersions(valueInContext, value) >= 0;
|
|
333
333
|
} else if (operator === "semverLessThan") {
|
|
334
|
-
return compareVersions(
|
|
334
|
+
return compareVersions(valueInContext, value) === -1;
|
|
335
335
|
} else if (operator === "semverLessThanOrEquals") {
|
|
336
|
-
return compareVersions(
|
|
336
|
+
return compareVersions(valueInContext, value) <= 0;
|
|
337
337
|
}
|
|
338
|
-
} else if (typeof
|
|
338
|
+
} else if (typeof context[attribute] === "number" && typeof value === "number") {
|
|
339
339
|
// numeric
|
|
340
|
-
const
|
|
340
|
+
const valueInContext = context[attribute] as number;
|
|
341
341
|
|
|
342
342
|
if (operator === "greaterThan") {
|
|
343
|
-
return
|
|
343
|
+
return valueInContext > value;
|
|
344
344
|
} else <span class="missing-if-branch" title="if path not taken" >I</span>if (operator === "greaterThanOrEquals") {
|
|
345
|
-
<span class="cstat-no" title="statement not covered" > return
|
|
345
|
+
<span class="cstat-no" title="statement not covered" > return valueInContext >= value;</span>
|
|
346
346
|
} else if (operator === "lessThan") {
|
|
347
|
-
return
|
|
347
|
+
return valueInContext < value;
|
|
348
348
|
} else <span class="cstat-no" title="statement not covered" ><span class="missing-if-branch" title="if path not taken" >I</span><span class="missing-if-branch" title="else path not taken" >E</span>if (operator === "lessThanOrEquals") {</span>
|
|
349
|
-
<span class="cstat-no" title="statement not covered" > return
|
|
349
|
+
<span class="cstat-no" title="statement not covered" > return valueInContext <= value;</span>
|
|
350
350
|
}
|
|
351
351
|
}
|
|
352
352
|
|
|
@@ -355,18 +355,18 @@ export function conditionIsMatched(condition: PlainCondition, attributes: Attrib
|
|
|
355
355
|
|
|
356
356
|
export function allConditionsAreMatched(
|
|
357
357
|
conditions: Condition[] | Condition,
|
|
358
|
-
|
|
358
|
+
context: Context,
|
|
359
359
|
): boolean {
|
|
360
360
|
if ("attribute" in conditions) {
|
|
361
|
-
return conditionIsMatched(conditions,
|
|
361
|
+
return conditionIsMatched(conditions, context);
|
|
362
362
|
}
|
|
363
363
|
|
|
364
364
|
if ("and" in conditions && Array.isArray(conditions.and)) {
|
|
365
|
-
return conditions.and.every((c) => allConditionsAreMatched(c,
|
|
365
|
+
return conditions.and.every((c) => allConditionsAreMatched(c, context));
|
|
366
366
|
}
|
|
367
367
|
|
|
368
368
|
if ("or" in conditions && Array.isArray(conditions.or)) {
|
|
369
|
-
return conditions.or.some((c) => allConditionsAreMatched(c,
|
|
369
|
+
return conditions.or.some((c) => allConditionsAreMatched(c, context));
|
|
370
370
|
}
|
|
371
371
|
|
|
372
372
|
if ("not" in conditions && Array.isArray(conditions.not)) {
|
|
@@ -376,13 +376,13 @@ export function allConditionsAreMatched(
|
|
|
376
376
|
{
|
|
377
377
|
and: conditions.not,
|
|
378
378
|
},
|
|
379
|
-
|
|
379
|
+
context,
|
|
380
380
|
) === false,
|
|
381
381
|
);
|
|
382
382
|
}
|
|
383
383
|
|
|
384
384
|
if (Array.isArray(conditions)) {
|
|
385
|
-
return conditions.every((c) => allConditionsAreMatched(c,
|
|
385
|
+
return conditions.every((c) => allConditionsAreMatched(c, context));
|
|
386
386
|
}
|
|
387
387
|
|
|
388
388
|
<span class="cstat-no" title="statement not covered" > return false;</span>
|
|
@@ -394,7 +394,7 @@ export function allConditionsAreMatched(
|
|
|
394
394
|
<div class='footer quiet pad2 space-top1 center small'>
|
|
395
395
|
Code coverage generated by
|
|
396
396
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
397
|
-
at 2023-07-
|
|
397
|
+
at 2023-07-14T17:03:15.956Z
|
|
398
398
|
</div>
|
|
399
399
|
<script src="prettify.js"></script>
|
|
400
400
|
<script>
|
|
@@ -289,7 +289,7 @@ export class DatafileReader {
|
|
|
289
289
|
<div class='footer quiet pad2 space-top1 center small'>
|
|
290
290
|
Code coverage generated by
|
|
291
291
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
292
|
-
at 2023-07-
|
|
292
|
+
at 2023-07-14T17:03:15.956Z
|
|
293
293
|
</div>
|
|
294
294
|
<script src="prettify.js"></script>
|
|
295
295
|
<script>
|
|
@@ -229,7 +229,7 @@ export class Emitter {
|
|
|
229
229
|
<div class='footer quiet pad2 space-top1 center small'>
|
|
230
230
|
Code coverage generated by
|
|
231
231
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
232
|
-
at 2023-07-
|
|
232
|
+
at 2023-07-14T17:03:15.956Z
|
|
233
233
|
</div>
|
|
234
234
|
<script src="prettify.js"></script>
|
|
235
235
|
<script>
|
|
@@ -227,7 +227,7 @@
|
|
|
227
227
|
<span class="cline-any cline-no"> </span>
|
|
228
228
|
<span class="cline-any cline-neutral"> </span>
|
|
229
229
|
<span class="cline-any cline-neutral"> </span>
|
|
230
|
-
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">import { Allocation,
|
|
230
|
+
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">import { Allocation, Context, Traffic, Feature, Force } from "@featurevisor/types";
|
|
231
231
|
import { DatafileReader } from "./datafileReader";
|
|
232
232
|
import { allGroupSegmentsAreMatched } from "./segments";
|
|
233
233
|
import { allConditionsAreMatched } from "./conditions";
|
|
@@ -255,7 +255,7 @@ export interface MatchedTrafficAndAllocation {
|
|
|
255
255
|
|
|
256
256
|
export function getMatchedTrafficAndAllocation(
|
|
257
257
|
traffic: Traffic[],
|
|
258
|
-
|
|
258
|
+
context: Context,
|
|
259
259
|
bucketValue: number,
|
|
260
260
|
datafileReader: DatafileReader,
|
|
261
261
|
logger: Logger,
|
|
@@ -266,7 +266,7 @@ export function getMatchedTrafficAndAllocation(
|
|
|
266
266
|
<span class="missing-if-branch" title="if path not taken" >I</span>if (
|
|
267
267
|
!allGroupSegmentsAreMatched(
|
|
268
268
|
typeof t.segments === "string" && t.segments !== "*" ? <span class="branch-0 cbranch-no" title="branch not covered" >JSON.parse(t.segments) </span>: t.segments,
|
|
269
|
-
|
|
269
|
+
context,
|
|
270
270
|
datafileReader,
|
|
271
271
|
)
|
|
272
272
|
) {
|
|
@@ -290,7 +290,7 @@ export function getMatchedTrafficAndAllocation(
|
|
|
290
290
|
|
|
291
291
|
export function findForceFromFeature(
|
|
292
292
|
feature: Feature,
|
|
293
|
-
|
|
293
|
+
context: Context,
|
|
294
294
|
datafileReader: DatafileReader,
|
|
295
295
|
): Force | undefined {
|
|
296
296
|
if (!feature.force) {
|
|
@@ -299,11 +299,11 @@ export function findForceFromFeature(
|
|
|
299
299
|
|
|
300
300
|
<span class="cstat-no" title="statement not covered" > return feature.force.find(<span class="fstat-no" title="function not covered" >(f</span>: Force) => {</span>
|
|
301
301
|
<span class="cstat-no" title="statement not covered" > <span class="missing-if-branch" title="if path not taken" >I</span>if (f.conditions) {</span>
|
|
302
|
-
<span class="cstat-no" title="statement not covered" > return allConditionsAreMatched(f.conditions,
|
|
302
|
+
<span class="cstat-no" title="statement not covered" > return allConditionsAreMatched(f.conditions, context);</span>
|
|
303
303
|
}
|
|
304
304
|
|
|
305
305
|
<span class="cstat-no" title="statement not covered" > <span class="missing-if-branch" title="if path not taken" >I</span>if (f.segments) {</span>
|
|
306
|
-
<span class="cstat-no" title="statement not covered" > return allGroupSegmentsAreMatched(f.segments,
|
|
306
|
+
<span class="cstat-no" title="statement not covered" > return allGroupSegmentsAreMatched(f.segments, context, datafileReader);</span>
|
|
307
307
|
}
|
|
308
308
|
|
|
309
309
|
<span class="cstat-no" title="statement not covered" > return false;</span>
|
|
@@ -316,7 +316,7 @@ export function findForceFromFeature(
|
|
|
316
316
|
<div class='footer quiet pad2 space-top1 center small'>
|
|
317
317
|
Code coverage generated by
|
|
318
318
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
319
|
-
at 2023-07-
|
|
319
|
+
at 2023-07-14T17:03:15.956Z
|
|
320
320
|
</div>
|
|
321
321
|
<script src="prettify.js"></script>
|
|
322
322
|
<script>
|
|
@@ -206,7 +206,7 @@
|
|
|
206
206
|
<div class='footer quiet pad2 space-top1 center small'>
|
|
207
207
|
Code coverage generated by
|
|
208
208
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
209
|
-
at 2023-07-
|
|
209
|
+
at 2023-07-14T17:03:15.956Z
|
|
210
210
|
</div>
|
|
211
211
|
<script src="prettify.js"></script>
|
|
212
212
|
<script>
|