invariants.js

  1. /**
  2. * Invariants
  3. * @namespace invariants
  4. * @since 1.0.0
  5. * @note invariants are 100% tested from PredicateCore.test.js
  6. */
  7. const { is } = require('ramda');
  8. module.exports = ({ errors, rules }) => ({
  9. /**
  10. * [CompoundPredicateMustHaveAtLeastOneSubPredicate description]
  11. * @param {?Array<Predicate>} predicates list of predicates to add to a CompoundPredicate at creation time
  12. * @return {Promise<undefined, errors.CompoundPredicateMustHaveAtLeastOneSubPredicate>} resolve the promise if the invariant pass or yield a `CompoundPredicateMustHaveAtLeastOneSubPredicate` error otherwise
  13. * @memberof invariants
  14. * @since 1.0.0
  15. */
  16. CompoundPredicateMustHaveAtLeastOneSubPredicate: predicates =>
  17. !Array.isArray(predicates) || predicates.length === 0
  18. ? Promise.reject(
  19. new errors.CompoundPredicateMustHaveAtLeastOneSubPredicate()
  20. )
  21. : Promise.resolve(),
  22. /**
  23. * @param {String} type Predicate type
  24. * @param {Object} acceptedTypes list of accepted types
  25. * @return {Promise<undefined, errors.InvalidPredicateType>} resolve the promise if the invariant pass or yield a `InvalidPredicateType` error otherwise
  26. * @memberof invariants
  27. * @since 1.0.0
  28. */
  29. PredicateTypeMustBeValid: (type, acceptedTypes) =>
  30. !Object.keys(acceptedTypes).includes(type)
  31. ? Promise.reject(new errors.InvalidPredicateType())
  32. : Promise.resolve(),
  33. /**
  34. * @param {dataclasses.CompoundPredicate} root root
  35. * @return {Promise<dataclasses.CompoundPredicate, errors.RootPredicateMustBeACompoundPredicate>} resolve the promise if the invariant pass or yield a `RootPredicateMustBeACompoundPredicate` error otherwise
  36. * @memberof invariants
  37. * @since 1.0.0
  38. */
  39. RootPredicateMustBeACompoundPredicate: (root, CompoundPredicate) =>
  40. !CompoundPredicate.is(root)
  41. ? Promise.reject(new errors.RootPredicateMustBeACompoundPredicate())
  42. : Promise.resolve(root),
  43. /**
  44. * @param {dataclasses.Predicate} predicate predicate
  45. * @param {dataclasses.ComparisonPredicate} ComparisonPredicate ComparisonPredicate constructor
  46. * @return {Promise<undefined, errors.PredicateMustBeAComparisonPredicate>} resolve the promise if the invariant pass or yield a `PredicateMustBeAComparisonPredicate` error otherwise
  47. * @memberof invariants
  48. * @since 1.0.0
  49. */
  50. PredicateMustBeAComparisonPredicate: (predicate, ComparisonPredicate) =>
  51. !ComparisonPredicate.is(predicate)
  52. ? Promise.reject(new errors.PredicateMustBeAComparisonPredicate())
  53. : Promise.resolve(),
  54. /**
  55. * @param {dataclasses.Predicate} predicate
  56. * @param {dataclasses.CompoundPredicate} CompoundPredicate CompoundPredicate constructor
  57. * @return {Promise<undefined, errors.PredicateMustBeACompoundPredicate>} resolve the promise if the invariant pass or yield a `PredicateMustBeACompoundPredicate` error otherwise
  58. * @memberof invariants
  59. * @since 1.0.0
  60. */
  61. PredicateMustBeACompoundPredicate: (predicate, CompoundPredicate) =>
  62. !CompoundPredicate.is(predicate)
  63. ? Promise.reject(new errors.PredicateMustBeACompoundPredicate())
  64. : Promise.resolve(),
  65. /**
  66. * @param {dataclasses.CompoundPredicate} root root
  67. * @return {Promise<undefined, errors.AddCurrentlyOnlySupportAfterInsertion>} resolve the promise if the invariant pass or yield a `AddCurrentlyOnlySupportAfterInsertion` error otherwise
  68. * @memberof invariants
  69. * @since 1.0.0
  70. */
  71. AddOnlySupportsAfter: how =>
  72. how !== 'after'
  73. ? Promise.reject(new errors.AddCurrentlyOnlySupportAfterInsertion())
  74. : Promise.resolve(),
  75. /**
  76. * @param {dataclasses.CompoundPredicate} root root
  77. * @return {Promise<dataclasses.Type, errors.TargetMustReferToADefinedType>} resolve the promise if the invariant pass or yield a `TargetMustReferToADefinedType` error otherwise
  78. * @memberof invariants
  79. * @since 1.0.0
  80. */
  81. TargetMustReferToADefinedType: (type, target) => {
  82. if (type.isNone()) {
  83. return Promise.reject(
  84. new errors.TargetMustReferToADefinedType(
  85. `target ${JSON.stringify(
  86. target.target_id
  87. )} does not refer to a defined type, target.type_id=${JSON.stringify(
  88. target.type_id
  89. )}`
  90. )
  91. );
  92. }
  93. return Promise.resolve(type.value());
  94. },
  95. /**
  96. * @param {Option<dataclasses.LogicalType>} logicalType logicalType
  97. * @return {Promise<dataclasses.LogicalType, errors.LogicalType_idMustReferToADefinedLogicalType>} resolve the promise if the invariant pass or yield a `LogicalType_idMustReferToADefinedLogicalType` error otherwise
  98. * @memberof invariants
  99. * @since 1.0.0
  100. */
  101. LogicalType_idMustReferToADefinedLogicalType: logicalType =>
  102. logicalType.isNone()
  103. ? Promise.reject(
  104. new errors.LogicalType_idMustReferToADefinedLogicalType()
  105. )
  106. : Promise.resolve(logicalType),
  107. /**
  108. * @param {Option<dataclasses.Target>} target target
  109. * @return {Promise<dataclasses.Target, errors.Target_idMustReferToADefinedTarget>} resolve the promise if the invariant pass or yield a `Target_idMustReferToADefinedTarget` error otherwise
  110. * @memberof invariants
  111. * @since 1.0.0
  112. */
  113. Target_idMustReferToADefinedTarget: target =>
  114. target.isNone()
  115. ? Promise.reject(new errors.Target_idMustReferToADefinedTarget())
  116. : Promise.resolve(target),
  117. /**
  118. * @param {Option<dataclasses.Operator>} operator
  119. * @return {Promise<dataclasses.Operator, errors.Operator_idMustReferToADefinedOperator>} resolve the promise if the invariant pass or yield a `Operator_idMustReferToADefinedOperator` error otherwise
  120. * @memberof invariants
  121. * @since 1.0.0
  122. */
  123. Operator_idMustReferToADefinedOperator: operator =>
  124. operator.isNone()
  125. ? Promise.reject(new errors.Operator_idMustReferToADefinedOperator())
  126. : Promise.resolve(operator),
  127. /**
  128. * @param {dataclasses.CompoundPredicate} root root
  129. * @param {dataclasses.Predicate} predicateToRemove predicateToRemove
  130. * @return {Promise<predicateToRemove, errors.ForbiddenCannotRemoveRootCompoundPredicate>} resolve the promise if the invariant pass or yield a `ForbiddenCannotRemoveRootCompoundPredicate` error otherwise
  131. * @memberof invariants
  132. * @since 1.0.0
  133. */
  134. RemovePredicateMustDifferFromRootPredicate: (root, predicateToRemove) =>
  135. rules.predicateToRemoveIsRootPredicate(root, predicateToRemove)
  136. ? Promise.reject(new errors.ForbiddenCannotRemoveRootCompoundPredicate())
  137. : Promise.resolve(predicateToRemove),
  138. /**
  139. * @param {dataclasses.CompoundPredicate} root root
  140. * @param {dataclasses.Predicate} predicateToRemove
  141. * @param {dataclasses.CompoundPredicate} CompoundPredicate
  142. * @param {dataclasses.ComparisonPredicate} ComparisonPredicate
  143. * @return {Promise<undefined, errors.ForbiddenCannotRemoveLastComparisonPredicate>} resolve the promise if the invariant pass or yield a `RootPredicateMustBeACompoundPredicate` error otherwise
  144. * @memberof invariants
  145. * @since 1.0.0
  146. */
  147. RemovePredicateCannotBeTheLastComparisonPredicate: (
  148. root,
  149. predicateToRemove,
  150. CompoundPredicate,
  151. ComparisonPredicate
  152. ) =>
  153. ComparisonPredicate.is(predicateToRemove) &&
  154. rules.predicateToRemoveIsTheLastComparisonPredicate(
  155. root,
  156. CompoundPredicate,
  157. ComparisonPredicate
  158. )
  159. ? Promise.reject(
  160. new errors.ForbiddenCannotRemoveLastComparisonPredicate()
  161. )
  162. : Promise.resolve(),
  163. });