Skip to content

Commit 55a35cf

Browse files
committed
More cleanup
1 parent 1ebce2c commit 55a35cf

File tree

3 files changed

+110
-9
lines changed

3 files changed

+110
-9
lines changed

packages/vercel-flags-core/src/evaluate.test.ts

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1813,6 +1813,94 @@ describe('evaluate', () => {
18131813
entities: { user: { id: null } },
18141814
result: false,
18151815
},
1816+
1817+
// ---- ci flag is ignored for non-string comparators ----
1818+
1819+
{
1820+
name: `${Comparator.EXISTS} ci ignored (still matches)`,
1821+
condition: [['user', 'id'], Comparator.EXISTS, undefined, { ci: true }],
1822+
entities: { user: { id: 'uid1' } },
1823+
result: true,
1824+
},
1825+
{
1826+
name: `${Comparator.NOT_EXISTS} ci ignored (still matches)`,
1827+
condition: [
1828+
['user', 'id'],
1829+
Comparator.NOT_EXISTS,
1830+
undefined,
1831+
{ ci: true },
1832+
],
1833+
entities: { user: {} },
1834+
result: true,
1835+
},
1836+
{
1837+
name: `${Comparator.GT} ci ignored (numeric comparison unchanged)`,
1838+
condition: [['user', 'age'], Comparator.GT, 20, { ci: true }],
1839+
entities: { user: { age: 30 } },
1840+
result: true,
1841+
},
1842+
{
1843+
name: `${Comparator.LT} ci ignored (numeric comparison unchanged)`,
1844+
condition: [['user', 'age'], Comparator.LT, 40, { ci: true }],
1845+
entities: { user: { age: 30 } },
1846+
result: true,
1847+
},
1848+
{
1849+
name: `${Comparator.GTE} ci ignored (numeric comparison unchanged)`,
1850+
condition: [['user', 'age'], Comparator.GTE, 30, { ci: true }],
1851+
entities: { user: { age: 30 } },
1852+
result: true,
1853+
},
1854+
{
1855+
name: `${Comparator.LTE} ci ignored (numeric comparison unchanged)`,
1856+
condition: [['user', 'age'], Comparator.LTE, 30, { ci: true }],
1857+
entities: { user: { age: 30 } },
1858+
result: true,
1859+
},
1860+
{
1861+
name: `${Comparator.REGEX} ci ignored (uses raw values)`,
1862+
condition: [
1863+
['user', 'id'],
1864+
Comparator.REGEX,
1865+
{ type: 'regex', pattern: '^joe', flags: '' },
1866+
{ ci: true },
1867+
],
1868+
entities: { user: { id: 'joewilkinson' } },
1869+
result: true,
1870+
},
1871+
{
1872+
name: `${Comparator.NOT_REGEX} ci ignored (uses raw values)`,
1873+
condition: [
1874+
['user', 'id'],
1875+
Comparator.NOT_REGEX,
1876+
{ type: 'regex', pattern: '^joe', flags: '' },
1877+
{ ci: true },
1878+
],
1879+
entities: { user: { id: 'joewilkinson' } },
1880+
result: false,
1881+
},
1882+
{
1883+
name: `${Comparator.BEFORE} ci ignored (date comparison unchanged)`,
1884+
condition: [
1885+
['user', 'createdAt'],
1886+
Comparator.BEFORE,
1887+
'2025-01-02',
1888+
{ ci: true },
1889+
],
1890+
entities: { user: { createdAt: '2025-01-01' } },
1891+
result: true,
1892+
},
1893+
{
1894+
name: `${Comparator.AFTER} ci ignored (date comparison unchanged)`,
1895+
condition: [
1896+
['user', 'createdAt'],
1897+
Comparator.AFTER,
1898+
'2024-12-31',
1899+
{ ci: true },
1900+
],
1901+
entities: { user: { createdAt: '2025-01-01' } },
1902+
result: true,
1903+
},
18161904
])('should evaluate comparator $name', ({ condition, entities, result }) => {
18171905
expect(
18181906
evaluate({

packages/vercel-flags-core/src/evaluate.ts

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ import {
88
ResolutionReason,
99
} from './types';
1010

11-
const MAX_REGEX_INPUT_LENGTH = 10_000;
12-
1311
type PathArray = (string | number)[];
1412

13+
const MAX_REGEX_INPUT_LENGTH = 10_000;
14+
1515
function exhaustivenessCheck(_: never): never {
1616
throw new Error('Exhaustiveness check failed');
1717
}
@@ -154,19 +154,23 @@ function matchConditions<T>(
154154
case Comparator.ONE_OF:
155155
return isArray(rhs) && rhs.includes(lhs);
156156
case Comparator.NOT_ONE_OF:
157-
// lhs is undefined when the entity value was not provided, in which
157+
// lhs would be undefined when the value was not provided, in which
158158
// case we should not match the rule
159-
if (!isArray(rhs) || typeof lhs === 'undefined') return false;
160-
return !rhs.includes(lhs);
159+
return (
160+
isArray(rhs) && typeof lhs !== 'undefined' && !rhs.includes(lhs)
161+
);
161162
case Comparator.CONTAINS_ALL_OF: {
162163
if (!Array.isArray(rhs) || !Array.isArray(lhs)) return false;
163164

164165
const lhsSet = new Set(lhs.filter(isString));
165166

167+
// try to use a set if the lhs is a list of strings - O(1)
168+
// otherwise we need to iterate over the values - O(n)
166169
if (lhsSet.size === lhs.length) {
167170
return rhs.filter(isString).every((item) => lhsSet.has(item));
168171
}
169172

173+
// this shouldn't happen since we only allow string[] on the lhs
170174
return rhs.every((item) => lhs.includes(item));
171175
}
172176
case Comparator.CONTAINS_ANY_OF: {
@@ -175,19 +179,26 @@ function matchConditions<T>(
175179
const rhsSet = new Set(rhs.filter(isString));
176180
return lhs.some(
177181
rhsSet.size === rhs.length
178-
? (item) => rhsSet.has(item)
179-
: (item) => rhs.includes(item),
182+
? // try to use a set if the rhs is a list of strings - O(1)
183+
(item) => rhsSet.has(item)
184+
: // otherwise we need to iterate over the values - O(n)
185+
(item) => rhs.includes(item),
180186
);
181187
}
182188
case Comparator.CONTAINS_NONE_OF: {
189+
// if the rhs is not an array something went wrong and we should not match
183190
if (!Array.isArray(rhs)) return false;
191+
192+
// if it's not an array it doesn't contain any of the values
184193
if (!Array.isArray(lhs)) return true;
185194

186195
const rhsSet = new Set(rhs.filter(isString));
187196
return lhs.every(
188197
rhsSet.size === rhs.length
189-
? (item) => !rhsSet.has(item)
190-
: (item) => !rhs.includes(item),
198+
? // try to use a set if the rhs is a list of strings - O(1)
199+
(item) => !rhsSet.has(item)
200+
: // otherwise we need to iterate over the values - O(n)
201+
(item) => !rhs.includes(item),
191202
);
192203
}
193204
case Comparator.STARTS_WITH:

packages/vercel-flags-core/src/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,8 @@ export namespace Original {
512512
lhs: LHS;
513513
cmp: Comparator;
514514
rhs: RHS;
515+
/** When true, string comparisons are case-insensitive. */
516+
ci?: boolean;
515517
};
516518

517519
export type Rule = {

0 commit comments

Comments
 (0)