@frontegg/entitlements-javascript-commons 1.0.0-alpha.4 → 1.0.0-alpha.5

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 (47) hide show
  1. package/dist/conditions/condition.evaluator.js +13 -1
  2. package/dist/conditions/condition.evaluator.js.map +1 -1
  3. package/dist/conditions/types.d.ts +2 -2
  4. package/dist/operations/boolean/index.d.ts +1 -0
  5. package/dist/operations/boolean/index.js +1 -0
  6. package/dist/operations/boolean/index.js.map +1 -1
  7. package/dist/operations/boolean/sanitizers.d.ts +4 -0
  8. package/dist/operations/boolean/sanitizers.js +17 -0
  9. package/dist/operations/boolean/sanitizers.js.map +1 -0
  10. package/dist/operations/components/sanitizers.resolver.d.ts +2 -0
  11. package/dist/operations/components/sanitizers.resolver.js +18 -0
  12. package/dist/operations/components/sanitizers.resolver.js.map +1 -0
  13. package/dist/operations/date/sanitizers.d.ts +5 -0
  14. package/dist/operations/date/sanitizers.js +27 -0
  15. package/dist/operations/date/sanitizers.js.map +1 -0
  16. package/dist/operations/numeric/index.d.ts +1 -0
  17. package/dist/operations/numeric/index.js +1 -0
  18. package/dist/operations/numeric/index.js.map +1 -1
  19. package/dist/operations/numeric/sanitizers.d.ts +5 -0
  20. package/dist/operations/numeric/sanitizers.js +32 -0
  21. package/dist/operations/numeric/sanitizers.js.map +1 -0
  22. package/dist/operations/string/sanitizers.d.ts +5 -0
  23. package/dist/operations/string/sanitizers.js +31 -0
  24. package/dist/operations/string/sanitizers.js.map +1 -0
  25. package/dist/operations/types/index.d.ts +9 -0
  26. package/dist/operations/types/index.js.map +1 -1
  27. package/docs/CHANGELOG.md +7 -0
  28. package/package.json +1 -1
  29. package/src/conditions/condition.evaluator.ts +16 -1
  30. package/src/conditions/types.ts +2 -2
  31. package/src/operations/boolean/index.ts +1 -0
  32. package/src/operations/boolean/sanitizers.ts +18 -0
  33. package/src/operations/boolean/{operations.spec.ts → tests/operations.spec.ts} +1 -1
  34. package/src/operations/boolean/tests/sanitizers.spec.ts +22 -0
  35. package/src/operations/components/sanitizers.resolver.ts +16 -0
  36. package/src/operations/components/tests/sanitizers.resolver.spec.ts +14 -0
  37. package/src/operations/date/sanitizers.ts +27 -0
  38. package/src/operations/date/{operations.spec.ts → tests/operations.spec.ts} +1 -1
  39. package/src/operations/date/tests/sanitizers.spec.ts +43 -0
  40. package/src/operations/numeric/index.ts +1 -0
  41. package/src/operations/numeric/sanitizers.ts +34 -0
  42. package/src/operations/numeric/tests/sanitizers.spec.ts +44 -0
  43. package/src/operations/string/sanitizers.ts +33 -0
  44. package/src/operations/string/tests/sanitizers.spec.ts +45 -0
  45. package/src/operations/types/index.ts +8 -0
  46. package/src/operations/numeric/operations.spec.ts +0 -63
  47. package/src/operations/string/operations.spec.ts +0 -38
@@ -2,8 +2,20 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createConditionEvaluator = void 0;
4
4
  const operation_resolver_1 = require("../operations/components/operation.resolver");
5
+ const sanitizers_resolver_1 = require("../operations/components/sanitizers.resolver");
6
+ function failingConditionEvaluator() {
7
+ return () => false;
8
+ }
5
9
  function createConditionEvaluator(payload) {
6
- const operation = (0, operation_resolver_1.useOperation)(payload.condition.op, payload.condition.value);
10
+ const sanitizer = (0, sanitizers_resolver_1.useSanitizer)(payload.condition.op);
11
+ if (!sanitizer) {
12
+ return failingConditionEvaluator();
13
+ }
14
+ const { isSanitized, sanitizedValue } = sanitizer(payload.condition.value);
15
+ if (!isSanitized || sanitizedValue === undefined) {
16
+ return failingConditionEvaluator();
17
+ }
18
+ const operation = (0, operation_resolver_1.useOperation)(payload.condition.op, sanitizedValue);
7
19
  return (attributes) => {
8
20
  const attributeKey = payload.condition.attribute;
9
21
  const value = attributes[attributeKey];
@@ -1 +1 @@
1
- {"version":3,"file":"condition.evaluator.js","sourceRoot":"","sources":["../../src/conditions/condition.evaluator.ts"],"names":[],"mappings":";;;AACA,oFAA2E;AAQ3E,SAAgB,wBAAwB,CAAC,OAAwC;IAC/E,MAAM,SAAS,GAAG,IAAA,iCAAY,EAAC,OAAO,CAAC,SAAS,CAAC,EAAE,EAAE,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAE9E,OAAO,CAAC,UAAmC,EAAE,EAAE;QAC7C,MAAM,YAAY,GAAG,OAAO,CAAC,SAAS,CAAC,SAAS,CAAC;QACjD,MAAM,KAAK,GAAG,UAAU,CAAC,YAAY,CAAC,CAAC;QACvC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,KAAK,KAAK,SAAS,IAAI,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QAErG,OAAO,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;IACrD,CAAC,CAAC;AACJ,CAAC;AAVD,4DAUC"}
1
+ {"version":3,"file":"condition.evaluator.js","sourceRoot":"","sources":["../../src/conditions/condition.evaluator.ts"],"names":[],"mappings":";;;AACA,oFAA2E;AAC3E,sFAA4E;AAQ5E,SAAS,yBAAyB;IAChC,OAAO,GAAG,EAAE,CAAC,KAAK,CAAC;AACrB,CAAC;AAED,SAAgB,wBAAwB,CAAC,OAAwC;IAC/E,MAAM,SAAS,GAAG,IAAA,kCAAY,EAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IACrD,IAAI,CAAC,SAAS,EAAE;QACd,OAAO,yBAAyB,EAAE,CAAC;KACpC;IAED,MAAM,EAAE,WAAW,EAAE,cAAc,EAAE,GAAG,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC3E,IAAI,CAAC,WAAW,IAAI,cAAc,KAAK,SAAS,EAAE;QAChD,OAAO,yBAAyB,EAAE,CAAC;KACpC;IAED,MAAM,SAAS,GAAG,IAAA,iCAAY,EAAC,OAAO,CAAC,SAAS,CAAC,EAAE,EAAE,cAAc,CAAC,CAAC;IAErE,OAAO,CAAC,UAAmC,EAAE,EAAE;QAC7C,MAAM,YAAY,GAAG,OAAO,CAAC,SAAS,CAAC,SAAS,CAAC;QACjD,MAAM,KAAK,GAAG,UAAU,CAAC,YAAY,CAAC,CAAC;QACvC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,KAAK,KAAK,SAAS,IAAI,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QAErG,OAAO,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;IACrD,CAAC,CAAC;AACJ,CAAC;AApBD,4DAoBC"}
@@ -1,7 +1,7 @@
1
- import { ConditionValue, OperationEnum } from '../operations/types';
1
+ import { OperationEnum, RawConditionValue } from '../operations/types';
2
2
  export interface Condition {
3
3
  attribute: string;
4
4
  negate: boolean;
5
5
  op: OperationEnum;
6
- value: ConditionValue;
6
+ value: RawConditionValue;
7
7
  }
@@ -1,3 +1,4 @@
1
1
  import { OperationsMapper } from '../types';
2
2
  export * from './operations';
3
+ export * from './sanitizers';
3
4
  export declare const BooleanOperationsMapper: OperationsMapper;
@@ -18,6 +18,7 @@ exports.BooleanOperationsMapper = void 0;
18
18
  const types_1 = require("../types");
19
19
  const operations_1 = require("./operations");
20
20
  __exportStar(require("./operations"), exports);
21
+ __exportStar(require("./sanitizers"), exports);
21
22
  exports.BooleanOperationsMapper = {
22
23
  [types_1.OperationEnum.Is]: (value) => (0, operations_1.useIsOperation)(value),
23
24
  };
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/operations/boolean/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,oCAA2D;AAC3D,6CAA8C;AAG9C,+CAA6B;AAEhB,QAAA,uBAAuB,GAAqB;IACvD,CAAC,qBAAa,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,IAAA,2BAAc,EAAC,KAAgC,CAAC;CAChF,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/operations/boolean/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,oCAA2D;AAC3D,6CAA8C;AAG9C,+CAA6B;AAC7B,+CAA6B;AAEhB,QAAA,uBAAuB,GAAqB;IACvD,CAAC,qBAAa,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,IAAA,2BAAc,EAAC,KAAgC,CAAC;CAChF,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { Sanitizer, SanitizersMapper } from '../types';
2
+ import { BooleanOperationPayload } from './types';
3
+ export declare const singleBooleanSanitizer: Sanitizer<BooleanOperationPayload>;
4
+ export declare const BooleanSanitizersMapper: SanitizersMapper<BooleanOperationPayload>;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BooleanSanitizersMapper = exports.singleBooleanSanitizer = void 0;
4
+ const types_1 = require("../types");
5
+ const isBoolean = (value) => typeof value === 'boolean';
6
+ const singleBooleanSanitizer = (value) => {
7
+ const sanitizedValue = value.boolean !== undefined && isBoolean(value.boolean) ? { boolean: value.boolean } : undefined;
8
+ return {
9
+ isSanitized: !!sanitizedValue,
10
+ sanitizedValue,
11
+ };
12
+ };
13
+ exports.singleBooleanSanitizer = singleBooleanSanitizer;
14
+ exports.BooleanSanitizersMapper = {
15
+ [types_1.OperationEnum.Is]: exports.singleBooleanSanitizer,
16
+ };
17
+ //# sourceMappingURL=sanitizers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitizers.js","sourceRoot":"","sources":["../../../src/operations/boolean/sanitizers.ts"],"names":[],"mappings":";;;AAAA,oCAAyF;AAGzF,MAAM,SAAS,GAAG,CAAC,KAAc,EAAoB,EAAE,CAAC,OAAO,KAAK,KAAK,SAAS,CAAC;AAE5E,MAAM,sBAAsB,GAAuC,CAAC,KAAwB,EAAE,EAAE;IACrG,MAAM,cAAc,GAClB,KAAK,CAAC,OAAO,KAAK,SAAS,IAAI,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IAEnG,OAAO;QACL,WAAW,EAAE,CAAC,CAAC,cAAc;QAC7B,cAAc;KACf,CAAC;AACJ,CAAC,CAAC;AARW,QAAA,sBAAsB,0BAQjC;AAEW,QAAA,uBAAuB,GAA8C;IAChF,CAAC,qBAAa,CAAC,EAAE,CAAC,EAAE,8BAAsB;CAC3C,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { ConditionValue, OperationEnum, Sanitizer } from '../types';
2
+ export declare function useSanitizer(operation: OperationEnum): Sanitizer<ConditionValue> | undefined;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useSanitizer = void 0;
4
+ const boolean_1 = require("../boolean");
5
+ const sanitizers_1 = require("../string/sanitizers");
6
+ const sanitizers_2 = require("../date/sanitizers");
7
+ const numeric_1 = require("../numeric");
8
+ const SanitizersMapper = {
9
+ ...sanitizers_1.StringSanitizersMapper,
10
+ ...numeric_1.NumericSanitizersMapper,
11
+ ...sanitizers_2.DateSanitizersMapper,
12
+ ...boolean_1.BooleanSanitizersMapper,
13
+ };
14
+ function useSanitizer(operation) {
15
+ return SanitizersMapper[operation];
16
+ }
17
+ exports.useSanitizer = useSanitizer;
18
+ //# sourceMappingURL=sanitizers.resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitizers.resolver.js","sourceRoot":"","sources":["../../../src/operations/components/sanitizers.resolver.ts"],"names":[],"mappings":";;;AACA,wCAAqD;AACrD,qDAA8D;AAC9D,mDAA0D;AAC1D,wCAAqD;AAErD,MAAM,gBAAgB,GAAqC;IACzD,GAAG,mCAAsB;IACzB,GAAG,iCAAuB;IAC1B,GAAG,iCAAoB;IACvB,GAAG,iCAAuB;CAC3B,CAAC;AAEF,SAAgB,YAAY,CAAC,SAAwB;IACnD,OAAO,gBAAgB,CAAC,SAAS,CAAC,CAAC;AACrC,CAAC;AAFD,oCAEC"}
@@ -0,0 +1,5 @@
1
+ import { Sanitizer, SanitizersMapper } from '../types';
2
+ import { BetweenDateOperationPayload, DateOperationPayload, SingleDateOperationPayload } from './types';
3
+ export declare const sanitizeSingleDate: Sanitizer<SingleDateOperationPayload>;
4
+ export declare const sanitizeDateRange: Sanitizer<BetweenDateOperationPayload>;
5
+ export declare const DateSanitizersMapper: SanitizersMapper<DateOperationPayload>;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DateSanitizersMapper = exports.sanitizeDateRange = exports.sanitizeSingleDate = void 0;
4
+ const types_1 = require("../types");
5
+ const sanitizeSingleDate = (value) => {
6
+ const sanitizedValue = value.date ? { date: value.date } : undefined;
7
+ return {
8
+ isSanitized: !!sanitizedValue,
9
+ sanitizedValue,
10
+ };
11
+ };
12
+ exports.sanitizeSingleDate = sanitizeSingleDate;
13
+ const sanitizeDateRange = (value) => {
14
+ const sanitizedValue = value.start && value.end ? { start: value.start, end: value.end } : undefined;
15
+ return {
16
+ isSanitized: !!sanitizedValue,
17
+ sanitizedValue,
18
+ };
19
+ };
20
+ exports.sanitizeDateRange = sanitizeDateRange;
21
+ exports.DateSanitizersMapper = {
22
+ [types_1.OperationEnum.On]: exports.sanitizeSingleDate,
23
+ [types_1.OperationEnum.OnOrAfter]: exports.sanitizeDateRange,
24
+ [types_1.OperationEnum.OnOrBefore]: exports.sanitizeSingleDate,
25
+ [types_1.OperationEnum.BetweenDate]: exports.sanitizeSingleDate,
26
+ };
27
+ //# sourceMappingURL=sanitizers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitizers.js","sourceRoot":"","sources":["../../../src/operations/date/sanitizers.ts"],"names":[],"mappings":";;;AAAA,oCAAsE;AAG/D,MAAM,kBAAkB,GAA0C,CAAC,KAAK,EAAE,EAAE;IACjF,MAAM,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAY,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IAE7E,OAAO;QACL,WAAW,EAAE,CAAC,CAAC,cAAc;QAC7B,cAAc;KACf,CAAC;AACJ,CAAC,CAAC;AAPW,QAAA,kBAAkB,sBAO7B;AAEK,MAAM,iBAAiB,GAA2C,CAAC,KAAK,EAAE,EAAE;IACjF,MAAM,cAAc,GAAG,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAa,EAAE,GAAG,EAAE,KAAK,CAAC,GAAW,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IAErH,OAAO;QACL,WAAW,EAAE,CAAC,CAAC,cAAc;QAC7B,cAAc;KACf,CAAC;AACJ,CAAC,CAAC;AAPW,QAAA,iBAAiB,qBAO5B;AAEW,QAAA,oBAAoB,GAA2C;IAC1E,CAAC,qBAAa,CAAC,EAAE,CAAC,EAAE,0BAAkB;IACtC,CAAC,qBAAa,CAAC,SAAS,CAAC,EAAE,yBAAiB;IAC5C,CAAC,qBAAa,CAAC,UAAU,CAAC,EAAE,0BAAkB;IAC9C,CAAC,qBAAa,CAAC,WAAW,CAAC,EAAE,0BAAkB;CAChD,CAAC"}
@@ -1,4 +1,5 @@
1
1
  import { OperationsMapper } from '../types';
2
2
  export * from './operations';
3
+ export * from './sanitizers';
3
4
  export * from './types';
4
5
  export declare const NumericOperationsMapper: OperationsMapper;
@@ -18,6 +18,7 @@ exports.NumericOperationsMapper = void 0;
18
18
  const types_1 = require("../types");
19
19
  const operations_1 = require("./operations");
20
20
  __exportStar(require("./operations"), exports);
21
+ __exportStar(require("./sanitizers"), exports);
21
22
  __exportStar(require("./types"), exports);
22
23
  exports.NumericOperationsMapper = {
23
24
  [types_1.OperationEnum.Equal]: (value) => (0, operations_1.useEqualsOperation)(value),
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/operations/numeric/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,oCAA2D;AAC3D,6CAOsB;AAGtB,+CAA6B;AAC7B,0CAAwB;AAEX,QAAA,uBAAuB,GAAqB;IACvD,CAAC,qBAAa,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,IAAA,+BAAkB,EAAC,KAAsC,CAAC;IAC5F,CAAC,qBAAa,CAAC,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,IAAA,oCAAuB,EAAC,KAAsC,CAAC;IACvG,CAAC,qBAAa,CAAC,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,IAAA,yCAA4B,EAAC,KAAsC,CAAC;IACjH,CAAC,qBAAa,CAAC,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,IAAA,mCAAsB,EAAC,KAAsC,CAAC;IACrG,CAAC,qBAAa,CAAC,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,IAAA,wCAA2B,EAAC,KAAsC,CAAC;IAC/G,CAAC,qBAAa,CAAC,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,IAAA,uCAA0B,EAAC,KAAuC,CAAC;CAC/G,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/operations/numeric/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,oCAA2D;AAC3D,6CAOsB;AAGtB,+CAA6B;AAC7B,+CAA6B;AAC7B,0CAAwB;AAEX,QAAA,uBAAuB,GAAqB;IACvD,CAAC,qBAAa,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,IAAA,+BAAkB,EAAC,KAAsC,CAAC;IAC5F,CAAC,qBAAa,CAAC,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,IAAA,oCAAuB,EAAC,KAAsC,CAAC;IACvG,CAAC,qBAAa,CAAC,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,IAAA,yCAA4B,EAAC,KAAsC,CAAC;IACjH,CAAC,qBAAa,CAAC,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,IAAA,mCAAsB,EAAC,KAAsC,CAAC;IACrG,CAAC,qBAAa,CAAC,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,IAAA,wCAA2B,EAAC,KAAsC,CAAC;IAC/G,CAAC,qBAAa,CAAC,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,IAAA,uCAA0B,EAAC,KAAuC,CAAC;CAC/G,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { Sanitizer, SanitizersMapper } from '../types';
2
+ import { BetweenNumericOperationPayload, NumericOperationPayload, SingleNumericOperationPayload } from './types';
3
+ export declare const sanitizeSingleNumber: Sanitizer<SingleNumericOperationPayload>;
4
+ export declare const sanitizeNumericRange: Sanitizer<BetweenNumericOperationPayload>;
5
+ export declare const NumericSanitizersMapper: SanitizersMapper<NumericOperationPayload>;
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NumericSanitizersMapper = exports.sanitizeNumericRange = exports.sanitizeSingleNumber = void 0;
4
+ const types_1 = require("../types");
5
+ const isNumber = (value) => typeof value === 'number';
6
+ const sanitizeSingleNumber = (value) => {
7
+ const sanitizedValue = value.number !== undefined && isNumber(value.number) ? { number: value.number } : undefined;
8
+ return {
9
+ isSanitized: !!sanitizedValue,
10
+ sanitizedValue,
11
+ };
12
+ };
13
+ exports.sanitizeSingleNumber = sanitizeSingleNumber;
14
+ const sanitizeNumericRange = (value) => {
15
+ const sanitizedValue = value.start !== undefined && value.end !== undefined && isNumber(value.start) && isNumber(value.end)
16
+ ? { start: value.start, end: value.end }
17
+ : undefined;
18
+ return {
19
+ isSanitized: !!sanitizedValue,
20
+ sanitizedValue,
21
+ };
22
+ };
23
+ exports.sanitizeNumericRange = sanitizeNumericRange;
24
+ exports.NumericSanitizersMapper = {
25
+ [types_1.OperationEnum.Equal]: exports.sanitizeSingleNumber,
26
+ [types_1.OperationEnum.GreaterThan]: exports.sanitizeNumericRange,
27
+ [types_1.OperationEnum.GreaterThanEqual]: exports.sanitizeSingleNumber,
28
+ [types_1.OperationEnum.LesserThan]: exports.sanitizeSingleNumber,
29
+ [types_1.OperationEnum.LesserThanEqual]: exports.sanitizeNumericRange,
30
+ [types_1.OperationEnum.BetweenNumeric]: exports.sanitizeNumericRange,
31
+ };
32
+ //# sourceMappingURL=sanitizers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitizers.js","sourceRoot":"","sources":["../../../src/operations/numeric/sanitizers.ts"],"names":[],"mappings":";;;AAAA,oCAAsE;AAGtE,MAAM,QAAQ,GAAG,CAAC,KAAc,EAAmB,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC;AAEzE,MAAM,oBAAoB,GAA6C,CAAC,KAAK,EAAE,EAAE;IACtF,MAAM,cAAc,GAAG,KAAK,CAAC,MAAM,KAAK,SAAS,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IAEnH,OAAO;QACL,WAAW,EAAE,CAAC,CAAC,cAAc;QAC7B,cAAc;KACf,CAAC;AACJ,CAAC,CAAC;AAPW,QAAA,oBAAoB,wBAO/B;AAEK,MAAM,oBAAoB,GAA8C,CAAC,KAAK,EAAE,EAAE;IACvF,MAAM,cAAc,GAClB,KAAK,CAAC,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,GAAG,KAAK,SAAS,IAAI,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC;QAClG,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE;QACxC,CAAC,CAAC,SAAS,CAAC;IAEhB,OAAO;QACL,WAAW,EAAE,CAAC,CAAC,cAAc;QAC7B,cAAc;KACf,CAAC;AACJ,CAAC,CAAC;AAVW,QAAA,oBAAoB,wBAU/B;AAEW,QAAA,uBAAuB,GAA8C;IAChF,CAAC,qBAAa,CAAC,KAAK,CAAC,EAAE,4BAAoB;IAC3C,CAAC,qBAAa,CAAC,WAAW,CAAC,EAAE,4BAAoB;IACjD,CAAC,qBAAa,CAAC,gBAAgB,CAAC,EAAE,4BAAoB;IACtD,CAAC,qBAAa,CAAC,UAAU,CAAC,EAAE,4BAAoB;IAChD,CAAC,qBAAa,CAAC,eAAe,CAAC,EAAE,4BAAoB;IACrD,CAAC,qBAAa,CAAC,cAAc,CAAC,EAAE,4BAAoB;CACrD,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { Sanitizer, SanitizersMapper } from '../types';
2
+ import { ListStringOperationPayload, SingleStringOperationPayload, StringOperationPayload } from './types';
3
+ export declare const sanitizeSingleString: Sanitizer<SingleStringOperationPayload>;
4
+ export declare const sanitizeListString: Sanitizer<ListStringOperationPayload>;
5
+ export declare const StringSanitizersMapper: SanitizersMapper<StringOperationPayload>;
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.StringSanitizersMapper = exports.sanitizeListString = exports.sanitizeSingleString = void 0;
4
+ const types_1 = require("../types");
5
+ const isString = (value) => typeof value === 'string';
6
+ const sanitizeSingleString = (value) => {
7
+ const sanitizedValue = value.string !== undefined && isString(value.string) ? { string: value.string } : undefined;
8
+ return {
9
+ isSanitized: !!sanitizedValue,
10
+ sanitizedValue,
11
+ };
12
+ };
13
+ exports.sanitizeSingleString = sanitizeSingleString;
14
+ const sanitizeListString = (value) => {
15
+ const sanitizedValue = value.list !== undefined && value.list.every((str) => isString(str))
16
+ ? { list: value.list }
17
+ : undefined;
18
+ return {
19
+ isSanitized: !!sanitizedValue,
20
+ sanitizedValue,
21
+ };
22
+ };
23
+ exports.sanitizeListString = sanitizeListString;
24
+ exports.StringSanitizersMapper = {
25
+ [types_1.OperationEnum.Matches]: exports.sanitizeSingleString,
26
+ [types_1.OperationEnum.Contains]: exports.sanitizeListString,
27
+ [types_1.OperationEnum.StartsWith]: exports.sanitizeSingleString,
28
+ [types_1.OperationEnum.EndsWith]: exports.sanitizeSingleString,
29
+ [types_1.OperationEnum.InList]: exports.sanitizeListString,
30
+ };
31
+ //# sourceMappingURL=sanitizers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitizers.js","sourceRoot":"","sources":["../../../src/operations/string/sanitizers.ts"],"names":[],"mappings":";;;AAAA,oCAAsE;AAGtE,MAAM,QAAQ,GAAG,CAAC,KAAc,EAAmB,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC;AAEzE,MAAM,oBAAoB,GAA4C,CAAC,KAAK,EAAE,EAAE;IACrF,MAAM,cAAc,GAAG,KAAK,CAAC,MAAM,KAAK,SAAS,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IAEnH,OAAO;QACL,WAAW,EAAE,CAAC,CAAC,cAAc;QAC7B,cAAc;KACf,CAAC;AACJ,CAAC,CAAC;AAPW,QAAA,oBAAoB,wBAO/B;AAEK,MAAM,kBAAkB,GAA0C,CAAC,KAAK,EAAE,EAAE;IACjF,MAAM,cAAc,GAClB,KAAK,CAAC,IAAI,KAAK,SAAS,IAAgB,KAAK,CAAC,IAAK,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC/E,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAgB,EAAE;QAClC,CAAC,CAAC,SAAS,CAAC;IAEhB,OAAO;QACL,WAAW,EAAE,CAAC,CAAC,cAAc;QAC7B,cAAc;KACf,CAAC;AACJ,CAAC,CAAC;AAVW,QAAA,kBAAkB,sBAU7B;AAEW,QAAA,sBAAsB,GAA6C;IAC9E,CAAC,qBAAa,CAAC,OAAO,CAAC,EAAE,4BAAoB;IAC7C,CAAC,qBAAa,CAAC,QAAQ,CAAC,EAAE,0BAAkB;IAC5C,CAAC,qBAAa,CAAC,UAAU,CAAC,EAAE,4BAAoB;IAChD,CAAC,qBAAa,CAAC,QAAQ,CAAC,EAAE,4BAAoB;IAC9C,CAAC,qBAAa,CAAC,MAAM,CAAC,EAAE,0BAAkB;CAC3C,CAAC"}
@@ -6,10 +6,19 @@ import { BooleanOperationPayload } from '../boolean/types';
6
6
  export interface OperationResult {
7
7
  isValid: boolean;
8
8
  }
9
+ export type RawConditionValue = Record<string, unknown>;
9
10
  export type ConditionValue = StringOperationPayload | NumericOperationPayload | DateOperationPayload | BooleanOperationPayload;
10
11
  export type OperationHandler = (attribute: any) => OperationResult;
11
12
  export type OperationContextEnricher = (value: ConditionValue) => OperationHandler;
12
13
  export type OperationsMapper = {
13
14
  [key in OperationEnum]?: OperationContextEnricher;
14
15
  };
16
+ export interface SanitizationResult<T extends ConditionValue> {
17
+ isSanitized: boolean;
18
+ sanitizedValue: T | undefined;
19
+ }
20
+ export type Sanitizer<T extends ConditionValue> = (value: RawConditionValue) => SanitizationResult<T>;
21
+ export type SanitizersMapper<T extends ConditionValue> = {
22
+ [key in OperationEnum]?: Sanitizer<T>;
23
+ };
15
24
  export * from './operation.enum';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/operations/types/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAqBA,mDAAiC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/operations/types/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AA6BA,mDAAiC"}
package/docs/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ # [1.0.0-alpha.5](https://github.com/frontegg/entitlements-javascript-commons/compare/v-1.0.0-alpha.4...v-1.0.0-alpha.5) (2023-10-10)
2
+
3
+
4
+ ### Features
5
+
6
+ * **sanitizers:** add value sanitizers ([#12](https://github.com/frontegg/entitlements-javascript-commons/issues/12)) ([1decf2c](https://github.com/frontegg/entitlements-javascript-commons/commit/1decf2c01e0a86055bc856db5ff115a2318f1c59))
7
+
1
8
  # [1.0.0-alpha.4](https://github.com/frontegg/entitlements-javascript-commons/compare/v-1.0.0-alpha.3...v-1.0.0-alpha.4) (2023-10-10)
2
9
 
3
10
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frontegg/entitlements-javascript-commons",
3
- "version": "1.0.0-alpha.4",
3
+ "version": "1.0.0-alpha.5",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -1,5 +1,6 @@
1
1
  import { Condition } from './types';
2
2
  import { useOperation } from '../operations/components/operation.resolver';
3
+ import { useSanitizer } from '../operations/components/sanitizers.resolver';
3
4
 
4
5
  export interface CreateConditionEvaluatorPayload {
5
6
  condition: Condition;
@@ -7,8 +8,22 @@ export interface CreateConditionEvaluatorPayload {
7
8
 
8
9
  export type ConditionEvaluator = (attributes: Record<string, unknown>) => boolean;
9
10
 
11
+ function failingConditionEvaluator(): ConditionEvaluator {
12
+ return () => false;
13
+ }
14
+
10
15
  export function createConditionEvaluator(payload: CreateConditionEvaluatorPayload): ConditionEvaluator {
11
- const operation = useOperation(payload.condition.op, payload.condition.value);
16
+ const sanitizer = useSanitizer(payload.condition.op);
17
+ if (!sanitizer) {
18
+ return failingConditionEvaluator();
19
+ }
20
+
21
+ const { isSanitized, sanitizedValue } = sanitizer(payload.condition.value);
22
+ if (!isSanitized || sanitizedValue === undefined) {
23
+ return failingConditionEvaluator();
24
+ }
25
+
26
+ const operation = useOperation(payload.condition.op, sanitizedValue);
12
27
 
13
28
  return (attributes: Record<string, unknown>) => {
14
29
  const attributeKey = payload.condition.attribute;
@@ -1,8 +1,8 @@
1
- import { ConditionValue, OperationEnum } from '../operations/types';
1
+ import { OperationEnum, RawConditionValue } from '../operations/types';
2
2
 
3
3
  export interface Condition {
4
4
  attribute: string;
5
5
  negate: boolean;
6
6
  op: OperationEnum;
7
- value: ConditionValue;
7
+ value: RawConditionValue;
8
8
  }
@@ -3,6 +3,7 @@ import { useIsOperation } from './operations';
3
3
  import { BooleanOperationPayload } from './types';
4
4
 
5
5
  export * from './operations';
6
+ export * from './sanitizers';
6
7
 
7
8
  export const BooleanOperationsMapper: OperationsMapper = {
8
9
  [OperationEnum.Is]: (value) => useIsOperation(value as BooleanOperationPayload),
@@ -0,0 +1,18 @@
1
+ import { OperationEnum, RawConditionValue, Sanitizer, SanitizersMapper } from '../types';
2
+ import { BooleanOperationPayload } from './types';
3
+
4
+ const isBoolean = (value: unknown): value is boolean => typeof value === 'boolean';
5
+
6
+ export const singleBooleanSanitizer: Sanitizer<BooleanOperationPayload> = (value: RawConditionValue) => {
7
+ const sanitizedValue =
8
+ value.boolean !== undefined && isBoolean(value.boolean) ? { boolean: value.boolean } : undefined;
9
+
10
+ return {
11
+ isSanitized: !!sanitizedValue,
12
+ sanitizedValue,
13
+ };
14
+ };
15
+
16
+ export const BooleanSanitizersMapper: SanitizersMapper<BooleanOperationPayload> = {
17
+ [OperationEnum.Is]: singleBooleanSanitizer,
18
+ };
@@ -1,5 +1,5 @@
1
1
  import { fc, test } from '@fast-check/jest';
2
- import { useIsOperation } from './operations';
2
+ import { useIsOperation } from '../operations';
3
3
 
4
4
  describe('Boolean operations', () => {
5
5
  test.prop([fc.boolean(), fc.boolean()], { verbose: true })(
@@ -0,0 +1,22 @@
1
+ import { fc, test } from '@fast-check/jest';
2
+ import { singleBooleanSanitizer } from '../sanitizers';
3
+
4
+ describe('Boolean sanitizers', () => {
5
+ test.prop([fc.record({ boolean: fc.boolean() })], { verbose: true })(
6
+ 'should return sanitized when boolean value exists',
7
+ (value) => {
8
+ const sanitizationResult = singleBooleanSanitizer(value);
9
+
10
+ expect(sanitizationResult.isSanitized).toBe(true);
11
+ expect(typeof sanitizationResult.sanitizedValue?.boolean).toBe('boolean');
12
+ expect(sanitizationResult.sanitizedValue?.boolean).toBe(value.boolean);
13
+ },
14
+ );
15
+
16
+ test.prop([fc.object()], { verbose: true })('should return undefined when no boolean value exists', (value) => {
17
+ const sanitizationResult = singleBooleanSanitizer(value);
18
+
19
+ expect(sanitizationResult.isSanitized).toBe(false);
20
+ expect(sanitizationResult.sanitizedValue).toBeUndefined();
21
+ });
22
+ });
@@ -0,0 +1,16 @@
1
+ import { ConditionValue, OperationEnum, Sanitizer, SanitizersMapper } from '../types';
2
+ import { BooleanSanitizersMapper } from '../boolean';
3
+ import { StringSanitizersMapper } from '../string/sanitizers';
4
+ import { DateSanitizersMapper } from '../date/sanitizers';
5
+ import { NumericSanitizersMapper } from '../numeric';
6
+
7
+ const SanitizersMapper: SanitizersMapper<ConditionValue> = {
8
+ ...StringSanitizersMapper,
9
+ ...NumericSanitizersMapper,
10
+ ...DateSanitizersMapper,
11
+ ...BooleanSanitizersMapper,
12
+ };
13
+
14
+ export function useSanitizer(operation: OperationEnum): Sanitizer<ConditionValue> | undefined {
15
+ return SanitizersMapper[operation];
16
+ }
@@ -0,0 +1,14 @@
1
+ import { useSanitizer } from '../sanitizers.resolver';
2
+ import { OperationEnum } from '../../types';
3
+
4
+ describe('SanitizerResolver', () => {
5
+ it('should return undefined when operation is not supported', () => {
6
+ const sanitizer = useSanitizer('not supported' as any);
7
+ expect(sanitizer).toEqual(undefined);
8
+ });
9
+
10
+ it('should return sanitizer when operation is supported', () => {
11
+ const sanitizer = useSanitizer(OperationEnum.On);
12
+ expect(sanitizer).toEqual(expect.any(Function));
13
+ });
14
+ });
@@ -0,0 +1,27 @@
1
+ import { OperationEnum, Sanitizer, SanitizersMapper } from '../types';
2
+ import { BetweenDateOperationPayload, DateOperationPayload, SingleDateOperationPayload } from './types';
3
+
4
+ export const sanitizeSingleDate: Sanitizer<SingleDateOperationPayload> = (value) => {
5
+ const sanitizedValue = value.date ? { date: value.date as Date } : undefined;
6
+
7
+ return {
8
+ isSanitized: !!sanitizedValue,
9
+ sanitizedValue,
10
+ };
11
+ };
12
+
13
+ export const sanitizeDateRange: Sanitizer<BetweenDateOperationPayload> = (value) => {
14
+ const sanitizedValue = value.start && value.end ? { start: value.start as Date, end: value.end as Date } : undefined;
15
+
16
+ return {
17
+ isSanitized: !!sanitizedValue,
18
+ sanitizedValue,
19
+ };
20
+ };
21
+
22
+ export const DateSanitizersMapper: SanitizersMapper<DateOperationPayload> = {
23
+ [OperationEnum.On]: sanitizeSingleDate,
24
+ [OperationEnum.OnOrAfter]: sanitizeDateRange,
25
+ [OperationEnum.OnOrBefore]: sanitizeSingleDate,
26
+ [OperationEnum.BetweenDate]: sanitizeSingleDate,
27
+ };
@@ -3,7 +3,7 @@ import {
3
3
  useDateOnOperation,
4
4
  useDateOnOrAfterOperation,
5
5
  useDateOnOrBeforeOperation,
6
- } from './index';
6
+ } from '../index';
7
7
  import { fc, test } from '@fast-check/jest';
8
8
 
9
9
  describe('Date operations', () => {
@@ -0,0 +1,43 @@
1
+ import { fc, test } from '@fast-check/jest';
2
+ import { sanitizeDateRange, sanitizeSingleDate } from '../sanitizers';
3
+
4
+ describe('Date sanitizers', () => {
5
+ test.prop([fc.record({ date: fc.date() })], { verbose: true })(
6
+ 'should return sanitized when date value exists',
7
+ (value) => {
8
+ const sanitizationResult = sanitizeSingleDate(value);
9
+
10
+ expect(sanitizationResult.isSanitized).toBe(true);
11
+ expect(typeof sanitizationResult.sanitizedValue).toBe('object');
12
+ expect(sanitizationResult.sanitizedValue).toEqual({ date: value.date });
13
+ },
14
+ );
15
+
16
+ test.prop([fc.object()], { verbose: true })('should fail sanitization when date value does not exist', (value) => {
17
+ const sanitizationResult = sanitizeSingleDate(value);
18
+
19
+ expect(sanitizationResult.isSanitized).toBe(false);
20
+ expect(sanitizationResult.sanitizedValue).toBeUndefined();
21
+ });
22
+
23
+ test.prop([fc.record({ start: fc.date(), end: fc.date() })], { verbose: true })(
24
+ 'should return sanitized when start and end values exist',
25
+ (value) => {
26
+ const sanitizationResult = sanitizeDateRange(value);
27
+
28
+ expect(sanitizationResult.isSanitized).toBe(true);
29
+ expect(typeof sanitizationResult.sanitizedValue).toBe('object');
30
+ expect(sanitizationResult.sanitizedValue).toEqual({ start: value.start, end: value.end });
31
+ },
32
+ );
33
+
34
+ test.prop([fc.object()], { verbose: true })(
35
+ 'should fail sanitization when start and end values do not exist',
36
+ (value) => {
37
+ const sanitizationResult = sanitizeDateRange(value);
38
+
39
+ expect(sanitizationResult.isSanitized).toBe(false);
40
+ expect(sanitizationResult.sanitizedValue).toBeUndefined();
41
+ },
42
+ );
43
+ });
@@ -10,6 +10,7 @@ import {
10
10
  import { BetweenNumericOperationPayload, SingleNumericOperationPayload } from './types';
11
11
 
12
12
  export * from './operations';
13
+ export * from './sanitizers';
13
14
  export * from './types';
14
15
 
15
16
  export const NumericOperationsMapper: OperationsMapper = {
@@ -0,0 +1,34 @@
1
+ import { OperationEnum, Sanitizer, SanitizersMapper } from '../types';
2
+ import { BetweenNumericOperationPayload, NumericOperationPayload, SingleNumericOperationPayload } from './types';
3
+
4
+ const isNumber = (value: unknown): value is number => typeof value === 'number';
5
+
6
+ export const sanitizeSingleNumber: Sanitizer<SingleNumericOperationPayload> = (value) => {
7
+ const sanitizedValue = value.number !== undefined && isNumber(value.number) ? { number: value.number } : undefined;
8
+
9
+ return {
10
+ isSanitized: !!sanitizedValue,
11
+ sanitizedValue,
12
+ };
13
+ };
14
+
15
+ export const sanitizeNumericRange: Sanitizer<BetweenNumericOperationPayload> = (value) => {
16
+ const sanitizedValue =
17
+ value.start !== undefined && value.end !== undefined && isNumber(value.start) && isNumber(value.end)
18
+ ? { start: value.start, end: value.end }
19
+ : undefined;
20
+
21
+ return {
22
+ isSanitized: !!sanitizedValue,
23
+ sanitizedValue,
24
+ };
25
+ };
26
+
27
+ export const NumericSanitizersMapper: SanitizersMapper<NumericOperationPayload> = {
28
+ [OperationEnum.Equal]: sanitizeSingleNumber,
29
+ [OperationEnum.GreaterThan]: sanitizeNumericRange,
30
+ [OperationEnum.GreaterThanEqual]: sanitizeSingleNumber,
31
+ [OperationEnum.LesserThan]: sanitizeSingleNumber,
32
+ [OperationEnum.LesserThanEqual]: sanitizeNumericRange,
33
+ [OperationEnum.BetweenNumeric]: sanitizeNumericRange,
34
+ };
@@ -0,0 +1,44 @@
1
+ import { fc, test } from '@fast-check/jest';
2
+ import { sanitizeNumericRange, sanitizeSingleNumber } from '../sanitizers';
3
+
4
+ describe('Numeric sanitizers', () => {
5
+ test.prop([fc.record({ number: fc.integer() })], { verbose: true })('should return sanitized number', (value) => {
6
+ const sanitizationResult = sanitizeSingleNumber(value);
7
+
8
+ expect(sanitizationResult.isSanitized).toBe(true);
9
+ expect(typeof sanitizationResult.sanitizedValue?.number).toBe('number');
10
+ expect(sanitizationResult.sanitizedValue).toEqual({ number: value.number });
11
+ });
12
+
13
+ test.prop([fc.object()], { verbose: true })(
14
+ 'should not return sanitization values when number does not exist in value',
15
+ (value) => {
16
+ const sanitizationResult = sanitizeSingleNumber(value);
17
+
18
+ expect(sanitizationResult.isSanitized).toBe(false);
19
+ expect(sanitizationResult.sanitizedValue).toBeUndefined();
20
+ },
21
+ );
22
+
23
+ test.prop([fc.record({ start: fc.integer(), end: fc.integer() })], { verbose: true })(
24
+ 'should return sanitized range',
25
+ (value) => {
26
+ const sanitizationResult = sanitizeNumericRange(value);
27
+
28
+ expect(sanitizationResult.isSanitized).toBe(true);
29
+ expect(typeof sanitizationResult.sanitizedValue?.start).toBe('number');
30
+ expect(typeof sanitizationResult.sanitizedValue?.end).toBe('number');
31
+ expect(sanitizationResult.sanitizedValue).toEqual({ start: value.start, end: value.end });
32
+ },
33
+ );
34
+
35
+ test.prop([fc.object()], { verbose: true })(
36
+ 'should not return sanitization values when start or end does not exist in value',
37
+ (value) => {
38
+ const sanitizationResult = sanitizeNumericRange(value);
39
+
40
+ expect(sanitizationResult.isSanitized).toBe(false);
41
+ expect(sanitizationResult.sanitizedValue).toBeUndefined();
42
+ },
43
+ );
44
+ });
@@ -0,0 +1,33 @@
1
+ import { OperationEnum, Sanitizer, SanitizersMapper } from '../types';
2
+ import { ListStringOperationPayload, SingleStringOperationPayload, StringOperationPayload } from './types';
3
+
4
+ const isString = (value: unknown): value is string => typeof value === 'string';
5
+
6
+ export const sanitizeSingleString: Sanitizer<SingleStringOperationPayload> = (value) => {
7
+ const sanitizedValue = value.string !== undefined && isString(value.string) ? { string: value.string } : undefined;
8
+
9
+ return {
10
+ isSanitized: !!sanitizedValue,
11
+ sanitizedValue,
12
+ };
13
+ };
14
+
15
+ export const sanitizeListString: Sanitizer<ListStringOperationPayload> = (value) => {
16
+ const sanitizedValue =
17
+ value.list !== undefined && (<unknown[]>value.list).every((str) => isString(str))
18
+ ? { list: value.list as string[] }
19
+ : undefined;
20
+
21
+ return {
22
+ isSanitized: !!sanitizedValue,
23
+ sanitizedValue,
24
+ };
25
+ };
26
+
27
+ export const StringSanitizersMapper: SanitizersMapper<StringOperationPayload> = {
28
+ [OperationEnum.Matches]: sanitizeSingleString,
29
+ [OperationEnum.Contains]: sanitizeListString,
30
+ [OperationEnum.StartsWith]: sanitizeSingleString,
31
+ [OperationEnum.EndsWith]: sanitizeSingleString,
32
+ [OperationEnum.InList]: sanitizeListString,
33
+ };
@@ -0,0 +1,45 @@
1
+ import { fc, test } from '@fast-check/jest';
2
+ import { sanitizeListString, sanitizeSingleString } from '../sanitizers';
3
+
4
+ describe('String sanitizers', () => {
5
+ test.prop([fc.record({ list: fc.array(fc.string()) })], { verbose: true })(
6
+ 'should return sanitized strings list',
7
+ (value) => {
8
+ const sanitizationResult = sanitizeListString(value);
9
+
10
+ expect(sanitizationResult.isSanitized).toBe(true);
11
+ expect(sanitizationResult.sanitizedValue?.list).toEqual(value.list);
12
+ },
13
+ );
14
+
15
+ test.prop([fc.object()], { verbose: true })(
16
+ 'should not return sanitized strings list when list property does not exist',
17
+ (value) => {
18
+ const sanitizationResult = sanitizeListString(value);
19
+
20
+ expect(sanitizationResult.isSanitized).toBe(false);
21
+ expect(sanitizationResult.sanitizedValue).toBeUndefined();
22
+ },
23
+ );
24
+
25
+ test.prop([fc.record({ string: fc.string() })], { verbose: true })(
26
+ 'should sanitized string string property exists',
27
+ (value) => {
28
+ const sanitizationResult = sanitizeSingleString(value);
29
+
30
+ expect(sanitizationResult.isSanitized).toBe(true);
31
+ expect(typeof sanitizationResult.sanitizedValue?.string).toEqual('string');
32
+ expect(sanitizationResult.sanitizedValue?.string).toEqual(value.string);
33
+ },
34
+ );
35
+
36
+ test.prop([fc.object()], { verbose: true })(
37
+ 'should not return sanitized string when string property does not exist',
38
+ (value) => {
39
+ const sanitizationResult = sanitizeSingleString(value);
40
+
41
+ expect(sanitizationResult.isSanitized).toBe(false);
42
+ expect(sanitizationResult.sanitizedValue).toBeUndefined();
43
+ },
44
+ );
45
+ });
@@ -8,6 +8,7 @@ export interface OperationResult {
8
8
  isValid: boolean;
9
9
  }
10
10
 
11
+ export type RawConditionValue = Record<string, unknown>;
11
12
  export type ConditionValue =
12
13
  | StringOperationPayload
13
14
  | NumericOperationPayload
@@ -19,4 +20,11 @@ export type OperationHandler = (attribute: any) => OperationResult;
19
20
  export type OperationContextEnricher = (value: ConditionValue) => OperationHandler;
20
21
  export type OperationsMapper = { [key in OperationEnum]?: OperationContextEnricher };
21
22
 
23
+ export interface SanitizationResult<T extends ConditionValue> {
24
+ isSanitized: boolean;
25
+ sanitizedValue: T | undefined;
26
+ }
27
+ export type Sanitizer<T extends ConditionValue> = (value: RawConditionValue) => SanitizationResult<T>;
28
+ export type SanitizersMapper<T extends ConditionValue> = { [key in OperationEnum]?: Sanitizer<T> };
29
+
22
30
  export * from './operation.enum';
@@ -1,63 +0,0 @@
1
- import {
2
- useBetweenNumericOperation,
3
- useEqualsOperation,
4
- useGreaterThanEqualOperation,
5
- useGreaterThanOperation, useLesserThanEqualOperation,
6
- useLesserThanOperation,
7
- } from './index';
8
- import { fc, test } from '@fast-check/jest';
9
-
10
- describe('Numeric operations', () => {
11
- test.prop([fc.integer(), fc.integer()], { verbose: true })(
12
- 'should return true if the numbers equal',
13
- (number, attribute) => {
14
- const result = useEqualsOperation({ number })(attribute);
15
- return (number === attribute) === result.isValid;
16
- },
17
- );
18
-
19
- test.prop([fc.integer(), fc.integer()], { verbose: true })(
20
- 'should return correct validity value when attribute is greater than the given number',
21
- (number, attribute) => {
22
- const result = useGreaterThanOperation({ number })(attribute);
23
-
24
- return attribute > number === result.isValid;
25
- },
26
- );
27
-
28
- test.prop([fc.integer(), fc.integer()], { verbose: true })(
29
- 'should return correct validity value when attribute is greater or equals to given number',
30
- (number, attribute) => {
31
- const result = useGreaterThanEqualOperation({ number })(attribute);
32
-
33
- return attribute >= number === result.isValid;
34
- },
35
- );
36
-
37
- test.prop([fc.integer(), fc.integer()], { verbose: true })(
38
- 'should return correct validity value when attribute is lesser than then given number',
39
- (number, attribute) => {
40
- const result = useLesserThanOperation({ number })(attribute);
41
-
42
- return attribute < number === result.isValid;
43
- },
44
- );
45
-
46
- test.prop([fc.integer(), fc.integer()], { verbose: true })(
47
- 'should return correct validity value when attribute is lesser or equals to given number',
48
- (number, attribute) => {
49
- const result = useLesserThanEqualOperation({ number })(attribute);
50
-
51
- return attribute <= number === result.isValid;
52
- },
53
- );
54
-
55
- test.prop([fc.integer(), fc.integer(), fc.integer()], { verbose: true })(
56
- 'should return correct validity value when attribute is between the given numbers',
57
- (start, end, attribute) => {
58
- const result = useBetweenNumericOperation({ start, end })(attribute);
59
-
60
- return (attribute >= start && attribute <= end) === result.isValid;
61
- },
62
- );
63
- });
@@ -1,38 +0,0 @@
1
- import { useContainsOperation, useEndsWithOperation, useInListOperation, useStartsWithOperation } from './index';
2
- import { fc, test } from '@fast-check/jest';
3
-
4
- describe('String operations', () => {
5
- test.prop([fc.array(fc.string()), fc.string()], { verbose: true })(
6
- 'should return correct validity if one of the strings starts with the given prefix',
7
- (list, prefix) => {
8
- const result = useStartsWithOperation({ list })(prefix);
9
- return list.some((value) => prefix.startsWith(value)) === result.isValid;
10
- },
11
- );
12
-
13
- test.prop([fc.array(fc.string()), fc.string()], { verbose: true })(
14
- 'should return correct validity if one of the strings ends with the given suffix',
15
- (list, suffix) => {
16
- const result = useEndsWithOperation({ list })(suffix);
17
- return list.some((value) => suffix.endsWith(value)) === result.isValid;
18
- },
19
- );
20
-
21
- test.prop([fc.array(fc.string()), fc.string()], { verbose: true })(
22
- 'should return correct validity if one of the strings contains with given attribute',
23
- (list, included) => {
24
- const result = useContainsOperation({ list })(included);
25
-
26
- return list.some((value) => included.includes(value)) === result.isValid;
27
- },
28
- );
29
-
30
- test.prop([fc.array(fc.string()), fc.string()], { verbose: true })(
31
- 'should return correct validity if one of the strings is in the given list',
32
- (list, string) => {
33
- const result = useInListOperation({ list })(string);
34
-
35
- return list.includes(string) === result.isValid;
36
- },
37
- );
38
- });