File size: 3,070 Bytes
d9494a5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import { isNonEmptyArray, isNonEmptyString } from '@sniptt/guards';
import { Parser } from 'expr-eval-fork';

import { isDefined } from '../validation/isDefined';

import { safeGetNestedProperty } from './safeGetNestedProperty';

type ArrayMethod = 'every' | 'some';

const createArrayPropCheck = (
  method: ArrayMethod,
  predicate: (value: unknown) => boolean,
) => {
  return (array: unknown, prop: string) => {
    if (!isNonEmptyArray(array)) {
      return false;
    }

    return array[method]((item) =>
      predicate(safeGetNestedProperty(item, prop)),
    );
  };
};

const createArrayPropValueCheck = (
  method: ArrayMethod,
  predicate: (value: unknown, target: unknown) => boolean,
) => {
  return (array: unknown, prop: string, value: unknown) => {
    if (!isNonEmptyArray(array)) {
      return false;
    }

    return array[method]((item) =>
      predicate(safeGetNestedProperty(item, prop), value),
    );
  };
};

export const conditionalAvailabilityParser = new Parser();

conditionalAvailabilityParser.functions.isDefined = (value: unknown) =>
  isDefined(value);

conditionalAvailabilityParser.functions.isNonEmptyString = (value: unknown) =>
  isNonEmptyString(value);

conditionalAvailabilityParser.functions.includes = (
  array: unknown,
  value: unknown,
) => Array.isArray(array) && array.includes(value);

conditionalAvailabilityParser.functions.arrayLength = (value: unknown) =>
  Array.isArray(value) ? value.length : 0;

conditionalAvailabilityParser.functions.every = createArrayPropCheck(
  'every',
  Boolean,
);

conditionalAvailabilityParser.functions.everyDefined = createArrayPropCheck(
  'every',
  isDefined,
);

conditionalAvailabilityParser.functions.some = createArrayPropCheck(
  'some',
  Boolean,
);

conditionalAvailabilityParser.functions.someDefined = createArrayPropCheck(
  'some',
  isDefined,
);

conditionalAvailabilityParser.functions.someNonEmptyString =
  createArrayPropCheck('some', isNonEmptyString);

conditionalAvailabilityParser.functions.none = createArrayPropCheck(
  'every',
  (value) => !Boolean(value),
);

conditionalAvailabilityParser.functions.noneDefined = createArrayPropCheck(
  'every',
  (value) => !isDefined(value),
);

conditionalAvailabilityParser.functions.everyEquals = createArrayPropValueCheck(
  'every',
  (a, b) => a === b,
);

conditionalAvailabilityParser.functions.someEquals = createArrayPropValueCheck(
  'some',
  (a, b) => a === b,
);

conditionalAvailabilityParser.functions.noneEquals = createArrayPropValueCheck(
  'every',
  (a, b) => a !== b,
);

conditionalAvailabilityParser.functions.includesEvery =
  createArrayPropValueCheck(
    'every',
    (array, value) => Array.isArray(array) && array.includes(value),
  );

conditionalAvailabilityParser.functions.includesSome =
  createArrayPropValueCheck(
    'some',
    (array, value) => Array.isArray(array) && array.includes(value),
  );

conditionalAvailabilityParser.functions.includesNone =
  createArrayPropValueCheck(
    'every',
    (array, value) => Array.isArray(array) && !array.includes(value),
  );