@data7expressions/3xpr 5.0.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.
Files changed (213) hide show
  1. package/CHANGELOG.md +78 -0
  2. package/LICENSE +201 -0
  3. package/README.md +144 -0
  4. package/expression/application/expressions.d.ts +69 -0
  5. package/expression/application/expressions.d.ts.map +1 -0
  6. package/expression/application/expressions.js +157 -0
  7. package/expression/application/expressions.js.map +1 -0
  8. package/expression/application/index.d.ts +4 -0
  9. package/expression/application/index.d.ts.map +1 -0
  10. package/expression/application/index.js +20 -0
  11. package/expression/application/index.js.map +1 -0
  12. package/expression/application/useCases/convert.d.ts +8 -0
  13. package/expression/application/useCases/convert.d.ts.map +1 -0
  14. package/expression/application/useCases/convert.js +25 -0
  15. package/expression/application/useCases/convert.js.map +1 -0
  16. package/expression/application/useCases/executor.d.ts +11 -0
  17. package/expression/application/useCases/executor.d.ts.map +1 -0
  18. package/expression/application/useCases/executor.js +23 -0
  19. package/expression/application/useCases/executor.js.map +1 -0
  20. package/expression/application/useCases/executorObserveDecorator.d.ts +16 -0
  21. package/expression/application/useCases/executorObserveDecorator.d.ts.map +1 -0
  22. package/expression/application/useCases/executorObserveDecorator.js +98 -0
  23. package/expression/application/useCases/executorObserveDecorator.js.map +1 -0
  24. package/expression/domain/expressions.d.ts +29 -0
  25. package/expression/domain/expressions.d.ts.map +1 -0
  26. package/expression/domain/expressions.js +3 -0
  27. package/expression/domain/expressions.js.map +1 -0
  28. package/expression/domain/index.d.ts +2 -0
  29. package/expression/domain/index.d.ts.map +1 -0
  30. package/expression/domain/index.js +18 -0
  31. package/expression/domain/index.js.map +1 -0
  32. package/expression/infrastructure/convertFrom/convertFromFunction.d.ts +15 -0
  33. package/expression/infrastructure/convertFrom/convertFromFunction.d.ts.map +1 -0
  34. package/expression/infrastructure/convertFrom/convertFromFunction.js +45 -0
  35. package/expression/infrastructure/convertFrom/convertFromFunction.js.map +1 -0
  36. package/expression/infrastructure/convertFrom/convertFromGraphql.d.ts +5 -0
  37. package/expression/infrastructure/convertFrom/convertFromGraphql.d.ts.map +1 -0
  38. package/expression/infrastructure/convertFrom/convertFromGraphql.js +96 -0
  39. package/expression/infrastructure/convertFrom/convertFromGraphql.js.map +1 -0
  40. package/expression/infrastructure/expressionsBuilder.d.ts +8 -0
  41. package/expression/infrastructure/expressionsBuilder.d.ts.map +1 -0
  42. package/expression/infrastructure/expressionsBuilder.js +28 -0
  43. package/expression/infrastructure/expressionsBuilder.js.map +1 -0
  44. package/expression/infrastructure/helper.d.ts +7 -0
  45. package/expression/infrastructure/helper.d.ts.map +1 -0
  46. package/expression/infrastructure/helper.js +34 -0
  47. package/expression/infrastructure/helper.js.map +1 -0
  48. package/expression/infrastructure/index.d.ts +2 -0
  49. package/expression/infrastructure/index.d.ts.map +1 -0
  50. package/expression/infrastructure/index.js +18 -0
  51. package/expression/infrastructure/index.js.map +1 -0
  52. package/expression/infrastructure/library.d.ts +30 -0
  53. package/expression/infrastructure/library.d.ts.map +1 -0
  54. package/expression/infrastructure/library.js +1813 -0
  55. package/expression/infrastructure/library.js.map +1 -0
  56. package/index.d.ts +31 -0
  57. package/index.d.ts.map +1 -0
  58. package/index.js +64 -0
  59. package/index.js.map +1 -0
  60. package/jest-unit-config.json +15 -0
  61. package/model/application/index.d.ts +2 -0
  62. package/model/application/index.d.ts.map +1 -0
  63. package/model/application/index.js +18 -0
  64. package/model/application/index.js.map +1 -0
  65. package/model/application/modelService.d.ts +42 -0
  66. package/model/application/modelService.d.ts.map +1 -0
  67. package/model/application/modelService.js +329 -0
  68. package/model/application/modelService.js.map +1 -0
  69. package/model/domain/index.d.ts +3 -0
  70. package/model/domain/index.d.ts.map +1 -0
  71. package/model/domain/index.js +19 -0
  72. package/model/domain/index.js.map +1 -0
  73. package/model/domain/library.d.ts +5 -0
  74. package/model/domain/library.d.ts.map +1 -0
  75. package/model/domain/library.js +3 -0
  76. package/model/domain/library.js.map +1 -0
  77. package/model/domain/services.d.ts +32 -0
  78. package/model/domain/services.d.ts.map +1 -0
  79. package/model/domain/services.js +3 -0
  80. package/model/domain/services.js.map +1 -0
  81. package/operand/application/facade.d.ts +27 -0
  82. package/operand/application/facade.d.ts.map +1 -0
  83. package/operand/application/facade.js +42 -0
  84. package/operand/application/facade.js.map +1 -0
  85. package/operand/application/index.d.ts +15 -0
  86. package/operand/application/index.d.ts.map +1 -0
  87. package/operand/application/index.js +31 -0
  88. package/operand/application/index.js.map +1 -0
  89. package/operand/application/services/builder.d.ts +17 -0
  90. package/operand/application/services/builder.d.ts.map +1 -0
  91. package/operand/application/services/builder.js +30 -0
  92. package/operand/application/services/builder.js.map +1 -0
  93. package/operand/application/services/builderCacheDecorator.d.ts +14 -0
  94. package/operand/application/services/builderCacheDecorator.d.ts.map +1 -0
  95. package/operand/application/services/builderCacheDecorator.js +29 -0
  96. package/operand/application/services/builderCacheDecorator.js.map +1 -0
  97. package/operand/application/services/factory.d.ts +10 -0
  98. package/operand/application/services/factory.d.ts.map +1 -0
  99. package/operand/application/services/factory.js +24 -0
  100. package/operand/application/services/factory.js.map +1 -0
  101. package/operand/application/services/normalizer.d.ts +4 -0
  102. package/operand/application/services/normalizer.d.ts.map +1 -0
  103. package/operand/application/services/normalizer.js +51 -0
  104. package/operand/application/services/normalizer.js.map +1 -0
  105. package/operand/application/services/parameterService.d.ts +6 -0
  106. package/operand/application/services/parameterService.d.ts.map +1 -0
  107. package/operand/application/services/parameterService.js +23 -0
  108. package/operand/application/services/parameterService.js.map +1 -0
  109. package/operand/application/services/parser.d.ts +49 -0
  110. package/operand/application/services/parser.d.ts.map +1 -0
  111. package/operand/application/services/parser.js +751 -0
  112. package/operand/application/services/parser.js.map +1 -0
  113. package/operand/application/services/serializer.d.ts +10 -0
  114. package/operand/application/services/serializer.d.ts.map +1 -0
  115. package/operand/application/services/serializer.js +40 -0
  116. package/operand/application/services/serializer.js.map +1 -0
  117. package/operand/application/services/typeService.d.ts +37 -0
  118. package/operand/application/services/typeService.d.ts.map +1 -0
  119. package/operand/application/services/typeService.js +392 -0
  120. package/operand/application/services/typeService.js.map +1 -0
  121. package/operand/application/useCases/build.d.ts +10 -0
  122. package/operand/application/useCases/build.d.ts.map +1 -0
  123. package/operand/application/useCases/build.js +25 -0
  124. package/operand/application/useCases/build.js.map +1 -0
  125. package/operand/application/useCases/clone.d.ts +10 -0
  126. package/operand/application/useCases/clone.d.ts.map +1 -0
  127. package/operand/application/useCases/clone.js +34 -0
  128. package/operand/application/useCases/clone.js.map +1 -0
  129. package/operand/application/useCases/complete.d.ts +9 -0
  130. package/operand/application/useCases/complete.d.ts.map +1 -0
  131. package/operand/application/useCases/complete.js +26 -0
  132. package/operand/application/useCases/complete.js.map +1 -0
  133. package/operand/application/useCases/normalize.d.ts +9 -0
  134. package/operand/application/useCases/normalize.d.ts.map +1 -0
  135. package/operand/application/useCases/normalize.js +43 -0
  136. package/operand/application/useCases/normalize.js.map +1 -0
  137. package/operand/application/useCases/reduce.d.ts +11 -0
  138. package/operand/application/useCases/reduce.d.ts.map +1 -0
  139. package/operand/application/useCases/reduce.js +57 -0
  140. package/operand/application/useCases/reduce.js.map +1 -0
  141. package/operand/domain/constBuilder.d.ts +5 -0
  142. package/operand/domain/constBuilder.d.ts.map +1 -0
  143. package/operand/domain/constBuilder.js +3 -0
  144. package/operand/domain/constBuilder.js.map +1 -0
  145. package/operand/domain/entities.d.ts +60 -0
  146. package/operand/domain/entities.d.ts.map +1 -0
  147. package/operand/domain/entities.js +38 -0
  148. package/operand/domain/entities.js.map +1 -0
  149. package/operand/domain/index.d.ts +4 -0
  150. package/operand/domain/index.d.ts.map +1 -0
  151. package/operand/domain/index.js +20 -0
  152. package/operand/domain/index.js.map +1 -0
  153. package/operand/domain/services.d.ts +39 -0
  154. package/operand/domain/services.d.ts.map +1 -0
  155. package/operand/domain/services.js +3 -0
  156. package/operand/domain/services.js.map +1 -0
  157. package/operand/infrastructure/constBuilder.d.ts +6 -0
  158. package/operand/infrastructure/constBuilder.d.ts.map +1 -0
  159. package/operand/infrastructure/constBuilder.js +15 -0
  160. package/operand/infrastructure/constBuilder.js.map +1 -0
  161. package/operand/infrastructure/executors/expression.d.ts +34 -0
  162. package/operand/infrastructure/executors/expression.d.ts.map +1 -0
  163. package/operand/infrastructure/executors/expression.js +534 -0
  164. package/operand/infrastructure/executors/expression.js.map +1 -0
  165. package/operand/infrastructure/executors/task.d.ts +8 -0
  166. package/operand/infrastructure/executors/task.d.ts.map +1 -0
  167. package/operand/infrastructure/executors/task.js +492 -0
  168. package/operand/infrastructure/executors/task.js.map +1 -0
  169. package/operand/infrastructure/facadeBuilder.d.ts +10 -0
  170. package/operand/infrastructure/facadeBuilder.d.ts.map +1 -0
  171. package/operand/infrastructure/facadeBuilder.js +35 -0
  172. package/operand/infrastructure/facadeBuilder.js.map +1 -0
  173. package/operand/infrastructure/helper.d.ts +20 -0
  174. package/operand/infrastructure/helper.d.ts.map +1 -0
  175. package/operand/infrastructure/helper.js +272 -0
  176. package/operand/infrastructure/helper.js.map +1 -0
  177. package/operand/infrastructure/index.d.ts +4 -0
  178. package/operand/infrastructure/index.d.ts.map +1 -0
  179. package/operand/infrastructure/index.js +20 -0
  180. package/operand/infrastructure/index.js.map +1 -0
  181. package/package.json +39 -0
  182. package/shared/domain/base.d.ts +32 -0
  183. package/shared/domain/base.d.ts.map +1 -0
  184. package/shared/domain/base.js +12 -0
  185. package/shared/domain/base.js.map +1 -0
  186. package/shared/domain/context.d.ts +37 -0
  187. package/shared/domain/context.d.ts.map +1 -0
  188. package/shared/domain/context.js +93 -0
  189. package/shared/domain/context.js.map +1 -0
  190. package/shared/domain/index.d.ts +6 -0
  191. package/shared/domain/index.d.ts.map +1 -0
  192. package/shared/domain/index.js +22 -0
  193. package/shared/domain/index.js.map +1 -0
  194. package/shared/domain/observer.d.ts +15 -0
  195. package/shared/domain/observer.d.ts.map +1 -0
  196. package/shared/domain/observer.js +11 -0
  197. package/shared/domain/observer.js.map +1 -0
  198. package/shared/domain/operand.d.ts +55 -0
  199. package/shared/domain/operand.d.ts.map +1 -0
  200. package/shared/domain/operand.js +69 -0
  201. package/shared/domain/operand.js.map +1 -0
  202. package/shared/domain/signals.d.ts +8 -0
  203. package/shared/domain/signals.d.ts.map +1 -0
  204. package/shared/domain/signals.js +3 -0
  205. package/shared/domain/signals.js.map +1 -0
  206. package/shared/infrastructure/helper.d.ts +9 -0
  207. package/shared/infrastructure/helper.d.ts.map +1 -0
  208. package/shared/infrastructure/helper.js +16 -0
  209. package/shared/infrastructure/helper.js.map +1 -0
  210. package/shared/infrastructure/index.d.ts +2 -0
  211. package/shared/infrastructure/index.d.ts.map +1 -0
  212. package/shared/infrastructure/index.js +18 -0
  213. package/shared/infrastructure/index.js.map +1 -0
@@ -0,0 +1,1813 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CoreLibrary = void 0;
4
+ const crypto_1 = require("crypto");
5
+ const domain_1 = require("../../shared/domain");
6
+ const domain_2 = require("../../operand/domain");
7
+ class CoreLibrary {
8
+ // eslint-disable-next-line no-useless-constructor
9
+ constructor(builder, cloner, helper) {
10
+ this.builder = builder;
11
+ this.cloner = cloner;
12
+ this.helper = helper;
13
+ }
14
+ load(model) {
15
+ this.constants(model);
16
+ this.enums(model);
17
+ this.formats(model);
18
+ this.operators(model);
19
+ this.generalFunctions(model);
20
+ this.comparisonFunctions(model);
21
+ this.nullFunctions(model);
22
+ this.numberFunctions(model);
23
+ this.stringFunctions(model);
24
+ this.arrayFunctions(model);
25
+ this.groupFunctions(model);
26
+ this.dateTimeFunctions(model);
27
+ this.conversionFunctions(model);
28
+ this.setsFunctions(model);
29
+ this.extAggregationFunctions(model);
30
+ this.windowFunctions(model);
31
+ this.jsonFunctions(model);
32
+ this.statisticalFunctions(model);
33
+ this.systemFunctions(model);
34
+ }
35
+ constants(model) {
36
+ model.addConstant('true', true);
37
+ model.addConstant('false', false);
38
+ model.addConstant('null', null);
39
+ }
40
+ enums(model) {
41
+ model.addEnum('DayOfWeek', [['Sunday', 0], ['Monday', 1], ['Tuesday', 2], ['Wednesday', 3], ['Thursday', 4], ['Friday', 5], ['Saturday', 6]]);
42
+ }
43
+ formats(model) {
44
+ model.addFormat('email', '^\\w+([\\.-]?\\w+)*@\\w+([\\.-]?\\w+)*(\\.\\w{2,3})+$');
45
+ model.addFormat('integer', '^\\d+$');
46
+ model.addFormat('decimal', '^\\d+\\.\\d+$');
47
+ model.addFormat('string', '^[a-zA-Z0-9_.]+$');
48
+ // https://stackoverflow.com/questions/3143070/javascript-regex-iso-dateTime
49
+ model.addFormat('date', '^\\d{4}-\\d{2}-\\d{2}$');
50
+ model.addFormat('dateTime', '\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d:[0-5]\\d\\.\\d+([+-][0-2]\\d:[0-5]\\d|Z)');
51
+ model.addFormat('time', '\\[0-2]\\d:[0-5]\\d:[0-5]\\d');
52
+ }
53
+ operators(model) {
54
+ model.addOperator('+(a:T,b:T):T', (a, b) => a + b, { priority: 5, description: 'Addition' });
55
+ model.addOperator('-(a:number,b:number):number', (a, b) => a - b, { priority: 5, description: 'Subtraction' });
56
+ model.addOperator('-(a:number):number', (a) => a * (-1), { priority: 9, description: 'Negation' });
57
+ model.addOperator('*(a:number,b:number):number', (a, b) => a * b, { priority: 6, description: 'Multiplication' });
58
+ model.addOperator('/(a:number,b:number):number', (a, b) => a / b, { priority: 6, description: 'Division' });
59
+ model.addOperator('**(a:number,b:number):number', (a, b) => a ** b, { priority: 7, description: 'Exponentiation' });
60
+ model.addOperator('//(a:number,b:number):number', (a, b) => Math.pow(a, (1 / b)), { priority: 7, description: 'Root' });
61
+ model.addOperator('%(a:number,b:number):number', (a, b) => a % b, { priority: 8, description: 'Modulus' });
62
+ model.addOperator('&(a:number,b:number):number', (a, b) => a & b, { priority: 5, description: 'Bitwise AND' });
63
+ model.addOperator('|(a:number,b:number):number', (a, b) => a | b, { priority: 5, description: 'Bitwise OR' });
64
+ model.addOperator('^(a:number,b:number):number', (a, b) => a ^ b, { priority: 5, description: 'Bitwise XOR' });
65
+ model.addOperator('~(a:number):number', (a) => ~a, { priority: 9, description: 'Bitwise NOT' });
66
+ model.addOperator('<<(a:number,b:number):number', (a, b) => a << b, { priority: 5, description: 'Bitwise Left Shift' });
67
+ model.addOperator('>>(a:number,b:number):number', (a, b) => a >> b, { priority: 5, description: 'Bitwise Right Shift' });
68
+ model.addOperator('==(a:T,b:T):boolean', (a, b) => a === b, { priority: 4, description: 'Equality' });
69
+ model.addOperatorAlias('===', '==');
70
+ model.addOperator('!=(a:T,b:T):boolean', (a, b) => a !== b, { priority: 4, description: 'Inequality' });
71
+ model.addOperatorAlias('!==', '!=');
72
+ model.addOperatorAlias('<>', '!=');
73
+ model.addOperator('>(a:T,b:T):boolean', (a, b) => a > b, { priority: 4, description: 'Greater than' });
74
+ model.addOperator('<(a:T,b:T):boolean', (a, b) => a < b, { priority: 4, description: 'Less than' });
75
+ model.addOperator('>=(a:T,b:T):boolean', (a, b) => a >= b, { priority: 4, description: 'Greater than or equal' });
76
+ model.addOperator('<=(a:T,b:T):boolean', (a, b) => a <= b, { priority: 4, description: 'Less than or equal' });
77
+ model.addOperator('&&(a:boolean,b:boolean):boolean', new And(), { priority: 3, description: 'Logical AND' });
78
+ model.addOperator('||(a:boolean,b:boolean):boolean', new Or(), { priority: 3, description: 'Logical OR' });
79
+ model.addOperator('!(a:boolean):boolean', (a) => !a, { priority: 5, description: 'Logical NOT' });
80
+ // index is any, because it can also be string when used to access a property of an object
81
+ // example: orders[0]["number"]
82
+ model.addOperator('[](list:T[],index:any):T', (list, index) => list[index], { priority: 2, description: 'Index' });
83
+ model.addOperator('$(name:string):string', (name) => process.env[name], { priority: 9, description: 'Environment Variable' });
84
+ model.addOperator('=(a:T,b:T):T', new Assignment(), { priority: 1, description: 'Assignment' });
85
+ model.addOperator('+=(a:number,b:number):number', new AssignmentOp((a, b) => a + b), { priority: 1, description: 'Assignment Addition' });
86
+ model.addOperator('-=(a:number,b:number):number', new AssignmentOp((a, b) => a - b), { priority: 1, description: 'Assignment Subtraction' });
87
+ model.addOperator('*=(a:number,b:number):number', new AssignmentOp((a, b) => a * b), { priority: 1, description: 'Assignment Multiplication' });
88
+ model.addOperator('/=(a:number,b:number):number', new AssignmentOp((a, b) => a / b), { priority: 1, description: 'Assignment Division' });
89
+ model.addOperator('**=(a:number,b:number):number', new AssignmentOp((a, b) => a ** b), { priority: 1, description: 'Assignment Exponentiation' });
90
+ model.addOperator('//=(a:number,b:number):number', new AssignmentOp((a, b) => Math.floor(a / b)), { priority: 1, description: 'Assignment Floor Division' });
91
+ model.addOperator('%=(a:number,b:number):number', new AssignmentOp((a, b) => a % b), { priority: 1, description: 'Assignment Modulus' });
92
+ model.addOperator('&=(a:number,b:number):number', new AssignmentOp((a, b) => a & b), { priority: 1, description: 'Assignment Bitwise AND' });
93
+ model.addOperator('|=(a:number,b:number):number', new AssignmentOp((a, b) => a | b), { priority: 1, description: 'Assignment Bitwise OR' });
94
+ model.addOperator('^=(a:number,b:number):number', new AssignmentOp((a, b) => a ^ b), { priority: 1, description: 'Assignment Bitwise XOR' });
95
+ model.addOperator('<<=(a:number,b:number):number', new AssignmentOp((a, b) => a << b), { priority: 1, description: 'Assignment Bitwise Left Shift' });
96
+ model.addOperator('>>=(a:number,b:number):number', new AssignmentOp((a, b) => a >> b), { priority: 1, description: 'Assignment Bitwise Right Shift' });
97
+ }
98
+ generalFunctions(model) {
99
+ model.addFunction('sleep(ms?: number):void', async (ms = 0) => {
100
+ return new Promise(resolve => setTimeout(resolve, ms));
101
+ }, { async: true, description: 'Sleeps for the specified number of milliseconds' });
102
+ model.addFunction('console(value:any):void', (value) => {
103
+ console.log(typeof value === 'object' ? JSON.stringify(value) : value);
104
+ }, { description: 'Prints to console' });
105
+ }
106
+ nullFunctions(model) {
107
+ model.addFunction('nvl(value:T, default:T):T', (value, _default) => this.helper.utils.nvl(value, _default), { description: 'Null value' });
108
+ model.addFunction('nvl2(value:any, a:T,b:T):T', (value, a, b) => this.helper.utils.nvl2(value, a, b), { description: 'Null value' });
109
+ model.addFunctionAlias('ifNull', 'nvl');
110
+ }
111
+ comparisonFunctions(model) {
112
+ model.addFunction('between(value:T,from:T,to:T):boolean', (value, from, to) => this.helper.val.between(value, from, to), { description: 'Between' });
113
+ model.addFunction('includes(source:string|T[],value:string|T):boolean', (source, value) => source && value ? source.includes(value) : false, { description: 'Includes' });
114
+ model.addFunctionAlias('contains', 'includes');
115
+ model.addFunction('in(source:T,...values:T):boolean', (source, ...values) => {
116
+ if (source === undefined || values === undefined) {
117
+ return false;
118
+ }
119
+ if (values.length === 1 && Array.isArray(values[0])) {
120
+ return values[0].includes(source);
121
+ }
122
+ else {
123
+ return values.includes(source);
124
+ }
125
+ }, { description: 'In' });
126
+ model.addFunction('like(value:string,pattern:string):boolean', (value, pattern) => value && pattern ? value.includes(pattern) : false, { description: 'String contains pattern' });
127
+ model.addFunction('isNull(value:any):boolean', (value) => this.helper.val.isNull(value), { description: 'Check if value is null' });
128
+ model.addFunction('isNotNull(value:any):boolean', (value) => this.helper.val.isNotNull(value), { description: 'Check if value is not null' });
129
+ model.addFunction('isEmpty(value:string):boolean', (value) => this.helper.val.isEmpty(value), { description: 'Check if value is empty' });
130
+ model.addFunction('isNotEmpty(value:string):boolean', (value) => this.helper.val.isNotEmpty(value), { description: 'Check if value is not empty' });
131
+ model.addFunction('isBoolean(value:any):boolean', (value) => this.helper.val.isBoolean(value), { description: 'Check if value is boolean' });
132
+ model.addFunction('isNumber(value:any):boolean', (value) => this.helper.val.isNumber(value), { description: 'Check if value is number' });
133
+ model.addFunction('isInteger(value:any):boolean', (value) => this.helper.val.isInteger(value), { description: 'Check if value is integer' });
134
+ model.addFunction('isDecimal(value:any):boolean', (value) => this.helper.val.isDecimal(value), { description: 'Check if value is decimal' });
135
+ model.addFunction('isString(value:any):boolean', (value) => this.helper.val.isString(value), { description: 'Check if value is string' });
136
+ model.addFunction('isDate(value:any):boolean', (value) => this.helper.val.isDate(value), { description: 'Check if value is date' });
137
+ model.addFunction('isDateTime(value:any):boolean', (value) => this.helper.val.isDateTime(value), { description: 'Check if value is date time' });
138
+ model.addFunction('isTime(value:any):boolean', (value) => this.helper.val.isTime(value), { description: 'Check if value is time' });
139
+ model.addFunction('isObject(value:any):boolean', (value) => this.helper.val.isObject(value), { description: 'Check if value is object' });
140
+ model.addFunction('isArray(value:any):boolean', (value) => this.helper.val.isArray(value), { description: 'Check if value is array' });
141
+ model.addFunction('isBooleanFormat(value:string):boolean', (value) => this.helper.val.isBooleanFormat(value), { description: 'Check if value is boolean format' });
142
+ model.addFunction('isNumberFormat(value:string):boolean', (value) => this.helper.val.isNumberFormat(value), { description: 'Check if value is number format' });
143
+ model.addFunction('isIntegerFormat(value:string):boolean', (value) => this.helper.val.isIntegerFormat(value), { description: 'Check if value is integer format' });
144
+ model.addFunction('isDecimalFormat(value:string):boolean', (value) => this.helper.val.isDecimalFormat(value), { description: 'Check if value is decimal format' });
145
+ model.addFunction('isDateFormat(value:string):boolean', (value) => this.helper.val.isDateFormat(value), { description: 'Check if value is date format' });
146
+ model.addFunction('isDateTimeFormat(value:string):boolean', (value) => this.helper.val.isDateTimeFormat(value), { description: 'Check if value is date time format' });
147
+ model.addFunction('isTimeFormat(value:string):boolean', (value) => this.helper.val.isTimeFormat(value), { description: 'Check if value is time format' });
148
+ model.addFunction('coalesce(...values:T):T', (...values) => { var _a; return (_a = values.find(v => v !== null && v !== undefined)) !== null && _a !== void 0 ? _a : null; }, { description: 'First non-null value' });
149
+ model.addFunction('nullIf(a:T,b:T):T', (a, b) => a === b ? null : a, { description: 'Null if two values are equal' });
150
+ model.addFunction('greatest(...values:T):T', (...values) => values.filter(v => v !== null && v !== undefined).reduce((m, v) => v > m ? v : m), { description: 'Greatest of values' });
151
+ model.addFunction('least(...values:T):T', (...values) => values.filter(v => v !== null && v !== undefined).reduce((m, v) => v < m ? v : m), { description: 'Least of values' });
152
+ model.addFunction('iif(condition:boolean,trueValue:T,falseValue:T):T', (condition, trueValue, falseValue) => condition ? trueValue : falseValue, { description: 'Inline if' });
153
+ model.addFunction('choose(index:integer,...values:T):T', (index, ...values) => index >= 1 && index <= values.length ? values[index - 1] : null, { description: 'Choose value by 1-based index' });
154
+ }
155
+ numberFunctions(model) {
156
+ model.addFunction('abs(x:number):number', Math.abs, { description: 'Absolute value' });
157
+ model.addFunction('acos(x:number):number', Math.acos, { description: 'Arc cosine' });
158
+ model.addFunction('asin(x:number):number', Math.asin, { description: 'Arc sine' });
159
+ model.addFunction('atan(x:number):number', Math.atan, { description: 'Arc tangent' });
160
+ model.addFunction('atan2(y:number,x:number):number', Math.atan2, { description: 'Arc tangent of two variables' });
161
+ model.addFunction('ceil(x:number):number', Math.ceil, { description: 'Ceiling' });
162
+ model.addFunction('cos(x:number):number', Math.cos, { description: 'Cosine' });
163
+ model.addFunction('cosh(x:number):number', Math.cosh, { description: 'Hyperbolic cosine' });
164
+ model.addFunction('exp(x:number):number', Math.exp, { description: 'Exponential' });
165
+ model.addFunction('floor(x:number):number', Math.floor, { description: 'Floor' });
166
+ model.addFunction('ln(x:number):number', Math.log, { description: 'Natural logarithm' });
167
+ model.addFunction('log10(x:number):number', Math.log10, { description: 'Base 10 logarithm' });
168
+ model.addFunction('log(x:number):number', Math.log, { description: 'Natural logarithm' });
169
+ model.addFunction('remainder(n1:number,n2:number):number', (n1, n2) => n1 % n2, { description: 'Remainder' });
170
+ model.addFunction('round(num:number,decimals=0):number', (num, decimals = 0) => decimals > 0 ? Number(num.toFixed(decimals)) : Math.round(num), { description: 'Round' });
171
+ model.addFunction('sign(x:number):number', Math.sign, { description: 'Sign' });
172
+ model.addFunction('sin(x:number):number', Math.sin, { description: 'Sine' });
173
+ model.addFunction('sinh(x:number):number', Math.sinh, { description: 'Hyperbolic sine' });
174
+ model.addFunction('tan(x:number):number', Math.tan, { description: 'Tangent' });
175
+ model.addFunction('tanh(x:number):number', Math.tanh, { description: 'Hyperbolic tangent' });
176
+ model.addFunction('trunc(x:number):number', Math.trunc, { description: 'Truncate' });
177
+ model.addFunctionAlias('mod', 'remainder');
178
+ model.addFunction('power(x:number,y:number):number', Math.pow, { description: 'Power' });
179
+ model.addFunction('sqrt(x:number):number', Math.sqrt, { description: 'Square root' });
180
+ model.addFunction('rand():number', Math.random, { deterministic: false, description: 'Random number between 0 and 1' });
181
+ model.addFunction('cot(x:number):number', (x) => 1 / Math.tan(x), { description: 'Cotangent' });
182
+ model.addFunction('degrees(x:number):number', (x) => x * (180 / Math.PI), { description: 'Radians to degrees' });
183
+ model.addFunction('radians(x:number):number', (x) => x * (Math.PI / 180), { description: 'Degrees to radians' });
184
+ model.addFunction('pi():number', () => Math.PI, { description: 'Pi constant' });
185
+ }
186
+ conversionFunctions(model) {
187
+ model.addFunction('toString(value:any):string', (value) => this.helper.str.toString(value), { description: 'Convert to string' });
188
+ model.addFunction('toNumber(value:any):number', (value) => this.helper.utils.toNumber(value), { description: 'Convert to number' });
189
+ model.addFunction('dateToString(date:date):string', (date) => {
190
+ if (typeof date === 'string') {
191
+ return new Date(date).toISOString();
192
+ }
193
+ return date.toISOString();
194
+ }, { description: 'Convert date to string' });
195
+ model.addFunction('stringify(value:any):string', (value) => JSON.stringify(value), { description: 'Convert to JSON string' });
196
+ model.addFunction('parse(value:string):any', (value) => JSON.parse(value), { description: 'Parse JSON string' });
197
+ model.addFunction('keys(obj: any):string[]', (obj) => typeof obj === 'object' ? Object.keys(obj) : [], { description: 'Object keys' });
198
+ model.addFunction('values(obj: any):any[]', (obj) => typeof obj === 'object' ? Object.values(obj) : [], { description: 'Object values' });
199
+ model.addFunction('entries(obj: any):[string,any][]', (obj) => typeof obj === 'object' ? Object.entries(obj) : [], { description: 'Object entries' });
200
+ model.addFunction('fromEntries(entries: [string,any][]): any', (entries) => this.helper.obj.fromEntries(entries), { description: 'Object from entries' });
201
+ }
202
+ stringFunctions(model) {
203
+ model.addFunction('chr(ascii: number):string', (ascii) => String.fromCharCode(ascii), { description: 'Character' });
204
+ model.addFunction('capitalize(value:string):string', (value) => this.helper.str.capitalize(value), { description: 'Capitalize' });
205
+ model.addFunction('endsWith(value:string, sub:string, start:number):boolean', (value, sub, start) => value.endsWith(sub, start), { description: 'Ends with' });
206
+ model.addFunction('strCount(source: string, value: string):number', (source, value) => source.split(value).length - 1, { description: 'Count' });
207
+ model.addFunction('lower(value: string):string', (value) => value.toLowerCase(), { description: 'Lower case' });
208
+ model.addFunction('lpad(value: string, len: number, pad: string):string', (value, len, pad) => value.padStart(len, pad), { description: 'Left pad' });
209
+ model.addFunction('ltrim(value: string):string', (value) => value.trimStart(), { description: 'Left trim' });
210
+ model.addFunction('indexOf(value:string, sub:string, start:number):number', (value, sub, start) => value.indexOf(sub, start), { description: 'Index of' });
211
+ model.addFunction('join(values:string[],separator:string=","):string', (values, separator = ',') => values.join(separator), { description: 'Join' });
212
+ model.addFunction('replace(value: string, source: string, target: string):string', (value, source, target) => this.helper.str.replace(value, source, target), { description: 'Replace' });
213
+ model.addFunction('rpad(value: string, len: number, pad: string):string', (value, len, pad) => value.padEnd(len, pad), { description: 'Right pad' });
214
+ model.addFunction('rtrim(value: string):string', (value) => value.trimEnd(), { description: 'Right trim' });
215
+ model.addFunction('substring(value: string, from: number, end: number):string', (value, from, end) => value.substring(from, end), { description: 'Substring' });
216
+ model.addFunctionAlias('substr', 'substring');
217
+ model.addFunction('trim(value: string):string', (value) => value.trim(), { description: 'Trim' });
218
+ model.addFunction('upper(value: string):string', (value) => value.toUpperCase(), { description: 'Upper case' });
219
+ model.addFunction('concat(...values:any):string', (...values) => this.helper.str.concat(values), { description: 'Concatenate' });
220
+ model.addFunctionAlias('concatenate', 'concat');
221
+ model.addFunction('test(value: string, regexp: string):boolean', (value, regexp) => new RegExp(regexp).test(value), { description: 'Test' });
222
+ model.addFunction('title(value:string):string', (value) => this.helper.str.initCap(value), { description: 'Title case' });
223
+ model.addFunction('match(value: string, regexp: string):any', (value, regexp) => value ? value.match(regexp) : null, { description: 'Match' });
224
+ model.addFunction('mask(value: string):string', (value) => {
225
+ if (!value)
226
+ return value;
227
+ if (value.length > 8) {
228
+ return value.substring(0, 3) + '*****' + value.substring(value.length - 3, value.length);
229
+ }
230
+ else if (value.length > 5) {
231
+ return value.substring(0, 1) + '*****' + value.substring(value.length - 1, value.length);
232
+ }
233
+ else {
234
+ return '*';
235
+ }
236
+ }, { description: 'Mask sensitive data' });
237
+ model.addFunction('split(value:string,separator:string=","):string[]', (value, separator = ',') => value.split(separator), { description: 'Split string' });
238
+ model.addFunction('startWith(value:string, sub:string, start:number):boolean', (value, sub, start) => value.startsWith(sub, start), { description: 'Starts with' });
239
+ model.addFunctionAlias('startsWith', 'startWith');
240
+ model.addFunction('left(value:string,n:integer):string', (value, n) => n > 0 ? value.substring(0, n) : '', { description: 'Left N characters' });
241
+ model.addFunction('right(value:string,n:integer):string', (value, n) => n > 0 ? value.substring(value.length - n) : '', { description: 'Right N characters' });
242
+ model.addFunction('concatWs(separator:string,...values:any):string', (separator, ...values) => values.filter(v => v !== null && v !== undefined).join(separator), { description: 'Concatenate with separator' });
243
+ model.addFunction('inStr(value:string,sub:string,start?:number):number', (value, sub, start = 0) => value.indexOf(sub, start), { description: 'Position of substring' });
244
+ model.addFunctionAlias('locate', 'inStr');
245
+ model.addFunctionAlias('charIndex', 'inStr');
246
+ model.addFunctionAlias('position', 'inStr');
247
+ model.addFunctionAlias('initCap', 'title');
248
+ model.addFunctionAlias('char', 'chr');
249
+ model.addFunction('repeat(value:string,n:integer):string', (value, n) => value.repeat(Math.max(0, n)), { description: 'Repeat string N times' });
250
+ model.addFunction('space(n:integer):string', (n) => ' '.repeat(Math.max(0, n)), { description: 'N space characters' });
251
+ model.addFunction('splitPart(value:string,delimiter:string,n:integer):string', (value, delimiter, n) => {
252
+ const parts = value.split(delimiter);
253
+ return n >= 1 && n <= parts.length ? parts[n - 1] : '';
254
+ }, { description: 'Nth part of split string (1-based)' });
255
+ model.addFunction('translate(value:string,from:string,to:string):string', (value, from, to) => {
256
+ let result = value;
257
+ for (let i = 0; i < from.length; i++) {
258
+ result = result.split(from[i]).join(i < to.length ? to[i] : '');
259
+ }
260
+ return result;
261
+ }, { description: 'Replace individual characters' });
262
+ model.addFunction('ascii(value:string):integer', (value) => value ? value.charCodeAt(0) : 0, { description: 'ASCII code of first character' });
263
+ model.addFunction('soundex(value:string):string', (value) => {
264
+ const map = { B: '1', F: '1', P: '1', V: '1', C: '2', G: '2', J: '2', K: '2', Q: '2', S: '2', X: '2', Z: '2', D: '3', T: '3', L: '4', M: '5', N: '5', R: '6' };
265
+ const s = value.toUpperCase().replace(/[^A-Z]/g, '');
266
+ if (!s)
267
+ return '0000';
268
+ let code = s[0];
269
+ let prev = map[s[0]] || '0';
270
+ for (let i = 1; i < s.length && code.length < 4; i++) {
271
+ const curr = map[s[i]] || '0';
272
+ if (curr !== '0' && curr !== prev)
273
+ code += curr;
274
+ prev = curr;
275
+ }
276
+ return code.padEnd(4, '0');
277
+ }, { description: 'Soundex phonetic code' });
278
+ model.addFunction('md5(value:string):string', (value) => (0, crypto_1.createHash)('md5').update(value).digest('hex'), { description: 'MD5 hash' });
279
+ model.addFunction('sha1(value:string):string', (value) => (0, crypto_1.createHash)('sha1').update(value).digest('hex'), { description: 'SHA1 hash' });
280
+ model.addFunction('sha2(value:string,bits?:number):string', (value, bits = 256) => (0, crypto_1.createHash)(`sha${bits}`).update(value).digest('hex'), { description: 'SHA2 hash' });
281
+ model.addFunction('regexpReplace(value:string,pattern:string,replacement:string):string', (value, pattern, replacement) => value.replace(new RegExp(pattern, 'g'), replacement), { description: 'Replace all regex matches' });
282
+ model.addFunctionAlias('regexpLike', 'test');
283
+ model.addFunction('regexpSubstr(value:string,pattern:string,n?:integer):string', (value, pattern, n = 1) => {
284
+ const matches = [...value.matchAll(new RegExp(pattern, 'g'))];
285
+ return n >= 1 && n <= matches.length ? matches[n - 1][0] : '';
286
+ }, { description: 'Extract Nth regex match' });
287
+ model.addFunction('regexpInstr(value:string,pattern:string,n?:integer):integer', (value, pattern, n = 1) => {
288
+ var _a;
289
+ const matches = [...value.matchAll(new RegExp(pattern, 'g'))];
290
+ return n >= 1 && n <= matches.length ? ((_a = matches[n - 1].index) !== null && _a !== void 0 ? _a : -1) + 1 : 0;
291
+ }, { description: 'Position of Nth regex match (1-based, 0 if not found)' });
292
+ model.addFunction('regexpCount(value:string,pattern:string):integer', (value, pattern) => (value.match(new RegExp(pattern, 'g')) || []).length, { description: 'Count regex matches' });
293
+ model.addFunction('reverseStr(value:string):string', (value) => value.split('').reverse().join(''), { description: 'Reverse string characters' });
294
+ model.addFunctionAlias('groupConcat', 'join');
295
+ model.addFunctionAlias('stringAgg', 'join');
296
+ model.addFunctionAlias('listAgg', 'join');
297
+ }
298
+ dateTimeFunctions(model) {
299
+ model.addFunction('curTime():time', () => {
300
+ const d = new Date();
301
+ return `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}:${String(d.getSeconds()).padStart(2, '0')}`;
302
+ }, { description: 'Current time' });
303
+ model.addFunction('today():date', () => {
304
+ const d = new Date();
305
+ return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
306
+ }, { description: 'Current date' });
307
+ model.addFunction('now():dateTime', () => new Date().toISOString(), { description: 'Current date time' });
308
+ model.addFunction('time(value: string):time', (value) => {
309
+ const d = new Date(value);
310
+ return `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}:${String(d.getSeconds()).padStart(2, '0')}`;
311
+ }, { description: 'Get time' });
312
+ model.addFunction('date(value: string):date', (value) => {
313
+ const d = new Date(value);
314
+ return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
315
+ }, { description: 'Get date' });
316
+ model.addFunction('dateTime(value: string):dateTime', (value) => new Date(value).toISOString(), { description: 'Get date time' });
317
+ model.addFunction('year(value: dateTime):integer', (value) => {
318
+ return new Date(value).getFullYear();
319
+ }, { description: 'Get year' });
320
+ model.addFunction('month(value: dateTime):integer', (value) => {
321
+ return new Date(value).getMonth() + 1;
322
+ }, { description: 'Get month' });
323
+ model.addFunction('day(value: dateTime):integer', (value) => {
324
+ return new Date(value).getDate();
325
+ }, { description: 'Get day' });
326
+ model.addFunction('weekday(value: dateTime):integer', (value) => {
327
+ return new Date(value).getDay();
328
+ }, { description: 'Get day of week' });
329
+ model.addFunction('hour(value: dateTime):integer', (value) => {
330
+ return new Date(value).getHours();
331
+ }, { description: 'Get hours' });
332
+ model.addFunction('minute(value: dateTime):integer', (value) => {
333
+ return new Date(value).getMinutes();
334
+ }, { description: 'Get minutes' });
335
+ model.addFunction('second(value: dateTime):integer', (value) => {
336
+ return new Date(value).getSeconds();
337
+ }, { description: 'Get seconds' });
338
+ model.addFunction('millisecond(value: dateTime):integer', (value) => {
339
+ return new Date(value).getMilliseconds();
340
+ }, { description: 'Get milliseconds' });
341
+ model.addFunction('addYear(date: dateTime, value: number):dateTime', (date, value) => {
342
+ const _date = new Date(date);
343
+ _date.setFullYear(_date.getFullYear() + value);
344
+ return _date.toISOString();
345
+ }, { description: 'Add years' });
346
+ model.addFunction('addMonth(date: dateTime, value: number):dateTime', (date, value) => {
347
+ const _date = new Date(date);
348
+ _date.setMonth(_date.getMonth() + value);
349
+ return _date.toISOString();
350
+ }, { description: 'Add months' });
351
+ model.addFunction('addDay(date: dateTime, value: number):dateTime', (date, value) => {
352
+ const _date = new Date(date);
353
+ _date.setDate(_date.getDate() + value);
354
+ return _date.toISOString();
355
+ }, { description: 'Add days' });
356
+ model.addFunction('addHour(date: dateTime, value: number):dateTime', (date, value) => {
357
+ const _date = new Date(date);
358
+ _date.setHours(_date.getHours() + value);
359
+ return _date.toISOString();
360
+ }, { description: 'Add hours' });
361
+ model.addFunction('addMinute(date: dateTime, value: number):dateTime', (date, value) => {
362
+ const _date = new Date(date);
363
+ _date.setMinutes(_date.getMinutes() + value);
364
+ return _date.toISOString();
365
+ }, { description: 'Add minutes' });
366
+ model.addFunction('addSecond(date: dateTime, value: number):dateTime', (date, value) => {
367
+ const _date = new Date(date);
368
+ _date.setSeconds(_date.getSeconds() + value);
369
+ return _date.toISOString();
370
+ }, { description: 'Add seconds' });
371
+ model.addFunction('addMillisecond(date: dateTime, value: number):dateTime', (date, value) => {
372
+ const _date = new Date(date);
373
+ _date.setMilliseconds(_date.getMilliseconds() + value);
374
+ return _date.toISOString();
375
+ }, { description: 'Add milliseconds' });
376
+ model.addFunction('addTime(date: dateTime, time: time):dateTime', (date, time) => {
377
+ const _time = new Date('2000-01-01T' + time);
378
+ const _date = new Date(date);
379
+ _date.setHours(_date.getHours() + _time.getHours());
380
+ _date.setMinutes(_date.getMinutes() + _time.getMinutes());
381
+ _date.setSeconds(_date.getSeconds() + _time.getSeconds());
382
+ _date.setMilliseconds(_date.getMilliseconds() + _time.getMilliseconds());
383
+ return _date.toISOString();
384
+ }, { description: 'Add time' });
385
+ model.addFunction('subtractTime(date: dateTime, time: time):dateTime', (date, time) => {
386
+ const _time = new Date('2000-01-01T' + time);
387
+ const _date = new Date(date);
388
+ _date.setHours(_date.getHours() - _time.getHours());
389
+ _date.setMinutes(_date.getMinutes() - _time.getMinutes());
390
+ _date.setSeconds(_date.getSeconds() - _time.getSeconds());
391
+ _date.setMilliseconds(_date.getMilliseconds() - _time.getMilliseconds());
392
+ return _date.toISOString();
393
+ }, { description: 'Subtract time' });
394
+ model.addFunction('yearDiff(date1: dateTime, date2: dateTime):integer', (date1, date2) => {
395
+ return Math.abs(new Date(date2).getFullYear() - new Date(date1).getFullYear());
396
+ }, { description: 'Year difference' });
397
+ model.addFunction('dayDiff(date1: dateTime, date2: dateTime):integer', (date1, date2) => {
398
+ return Math.abs(Math.floor((new Date(date1).getTime() - new Date(date2).getTime()) / (24 * 3600 * 1000)));
399
+ }, { description: 'Day difference' });
400
+ model.addFunction('hourDiff(date1: dateTime, date2: dateTime):integer', (date1, date2) => {
401
+ return Math.abs(Math.floor((new Date(date1).getTime() - new Date(date2).getTime()) / (3600 * 1000)));
402
+ }, { description: 'Hour difference' });
403
+ model.addFunction('secondDiff(date1: dateTime, date2: dateTime):integer', (date1, date2) => {
404
+ return Math.abs(Math.floor((new Date(date1).getTime() - new Date(date2).getTime()) / 1000));
405
+ }, { description: 'Second difference' });
406
+ model.addFunction('millisecondDiff(date1: dateTime, date2: dateTime):integer', (date1, date2) => {
407
+ return Math.floor(new Date(date1).getTime() - new Date(date2).getTime());
408
+ }, { description: 'Millisecond difference' });
409
+ model.addFunction('dayToDate(value: number):dateTime', (value) => {
410
+ return new Date(value * 24 * 3600 * 1000).toISOString();
411
+ }, { description: 'Convert days to date time' });
412
+ model.addFunction('hourToDate(value: number):dateTime', (value) => {
413
+ return new Date(value * 3600 * 1000).toISOString();
414
+ }, { description: 'Convert hours to date time' });
415
+ model.addFunction('secondToDate(value: number):dateTime', (value) => {
416
+ return new Date(value * 1000).toISOString();
417
+ }, { description: 'Convert seconds to date time' });
418
+ model.addFunction('millisecondToDate(value: number):dateTime', (value) => {
419
+ return new Date(value).toISOString();
420
+ }, { description: 'Convert milliseconds to date time' });
421
+ model.addFunctionAlias('currentTimestamp', 'now');
422
+ model.addFunctionAlias('curDate', 'today');
423
+ model.addFunctionAlias('currentDate', 'today');
424
+ model.addFunctionAlias('currentTime', 'curTime');
425
+ model.addFunctionAlias('addMonths', 'addMonth');
426
+ model.addFunctionAlias('toDate', 'date');
427
+ model.addFunctionAlias('dateDiff', 'dayDiff');
428
+ model.addFunction('timeDiff(time1:time,time2:time):time', (time1, time2) => {
429
+ const t1 = new Date('2000-01-01T' + time1);
430
+ const t2 = new Date('2000-01-01T' + time2);
431
+ const totalSec = Math.abs(Math.floor((t1.getTime() - t2.getTime()) / 1000));
432
+ return `${String(Math.floor(totalSec / 3600)).padStart(2, '0')}:${String(Math.floor((totalSec % 3600) / 60)).padStart(2, '0')}:${String(totalSec % 60).padStart(2, '0')}`;
433
+ }, { description: 'Difference between two times' });
434
+ model.addFunction('monthsBetween(date1:dateTime,date2:dateTime):number', (date1, date2) => {
435
+ const d1 = new Date(date1);
436
+ const d2 = new Date(date2);
437
+ return Math.abs((d2.getFullYear() - d1.getFullYear()) * 12 + d2.getMonth() - d1.getMonth());
438
+ }, { description: 'Months between two dates' });
439
+ model.addFunction('extract(part:string,date:dateTime):integer', (part, date) => {
440
+ const d = new Date(date);
441
+ switch (part.toLowerCase()) {
442
+ case 'year': return d.getFullYear();
443
+ case 'month': return d.getMonth() + 1;
444
+ case 'day': return d.getDate();
445
+ case 'hour': return d.getHours();
446
+ case 'minute': return d.getMinutes();
447
+ case 'second': return d.getSeconds();
448
+ case 'millisecond': return d.getMilliseconds();
449
+ case 'weekday': return d.getDay();
450
+ case 'week': return Math.ceil(((d.getTime() - new Date(d.getFullYear(), 0, 1).getTime()) / 86400000 + new Date(d.getFullYear(), 0, 1).getDay() + 1) / 7);
451
+ case 'quarter': return Math.floor(d.getMonth() / 3) + 1;
452
+ default: return 0;
453
+ }
454
+ }, { description: 'Extract date part by name' });
455
+ model.addFunction('dateFormat(date:dateTime,format:string):string', (date, format) => {
456
+ const d = new Date(date);
457
+ return format
458
+ .replace('%Y', String(d.getFullYear()))
459
+ .replace('%y', String(d.getFullYear()).slice(2))
460
+ .replace('%m', String(d.getMonth() + 1).padStart(2, '0'))
461
+ .replace('%c', String(d.getMonth() + 1))
462
+ .replace('%d', String(d.getDate()).padStart(2, '0'))
463
+ .replace('%e', String(d.getDate()))
464
+ .replace('%H', String(d.getHours()).padStart(2, '0'))
465
+ .replace('%k', String(d.getHours()))
466
+ .replace('%i', String(d.getMinutes()).padStart(2, '0'))
467
+ .replace('%s', String(d.getSeconds()).padStart(2, '0'));
468
+ }, { description: 'Format date with pattern (%Y %m %d %H %i %s)' });
469
+ model.addFunctionAlias('toChar', 'dateFormat');
470
+ model.addFunction('lastDay(date:dateTime):date', (date) => {
471
+ const d = new Date(date);
472
+ d.setMonth(d.getMonth() + 1, 0);
473
+ return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
474
+ }, { description: 'Last day of month' });
475
+ model.addFunction('nextDay(date:dateTime,weekday:integer):date', (date, weekday) => {
476
+ const d = new Date(date);
477
+ const daysUntil = ((weekday - d.getDay() + 7) % 7) || 7;
478
+ d.setDate(d.getDate() + daysUntil);
479
+ return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
480
+ }, { description: 'Next occurrence of weekday (0=Sun,6=Sat)' });
481
+ model.addFunction('dayName(date:dateTime):string', (date) => ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'][new Date(date).getDay()], { description: 'Name of weekday' });
482
+ model.addFunction('monthName(date:dateTime):string', (date) => ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'][new Date(date).getMonth()], { description: 'Name of month' });
483
+ model.addFunction('week(date:dateTime):integer', (date) => {
484
+ const d = new Date(date);
485
+ const start = new Date(d.getFullYear(), 0, 1);
486
+ return Math.ceil(((d.getTime() - start.getTime()) / 86400000 + start.getDay() + 1) / 7);
487
+ }, { description: 'Week number of year' });
488
+ model.addFunction('quarter(date:dateTime):integer', (date) => Math.floor(new Date(date).getMonth() / 3) + 1, { description: 'Quarter of year (1-4)' });
489
+ model.addFunction('dateTrunc(date:dateTime,precision:string):dateTime', (date, precision) => {
490
+ const d = new Date(date);
491
+ switch (precision.toLowerCase()) {
492
+ case 'year': return new Date(Date.UTC(d.getUTCFullYear(), 0, 1)).toISOString();
493
+ case 'month': return new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), 1)).toISOString();
494
+ case 'day': return new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate())).toISOString();
495
+ case 'hour': return new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(), d.getUTCHours())).toISOString();
496
+ case 'minute': return new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(), d.getUTCHours(), d.getUTCMinutes())).toISOString();
497
+ default: return d.toISOString();
498
+ }
499
+ }, { description: 'Truncate date to precision (year/month/day/hour/minute), UTC-based' });
500
+ model.addFunction('makeDate(year:integer,dayOfYear:integer):date', (year, dayOfYear) => {
501
+ const d = new Date(year, 0, dayOfYear);
502
+ return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
503
+ }, { description: 'Create date from year and day-of-year' });
504
+ model.addFunction('unixTimestamp(date?:dateTime):integer', (date) => Math.floor((date ? new Date(date) : new Date()).getTime() / 1000), { description: 'Unix timestamp in seconds' });
505
+ model.addFunction('fromUnixTime(ts:integer):dateTime', (ts) => new Date(ts * 1000).toISOString(), { description: 'Date from Unix timestamp' });
506
+ model.addFunction('age(date1:dateTime,date2?:dateTime):string', (date1, date2) => {
507
+ const d1 = new Date(date1);
508
+ const d2 = date2 ? new Date(date2) : new Date();
509
+ let years = d2.getFullYear() - d1.getFullYear();
510
+ let months = d2.getMonth() - d1.getMonth();
511
+ let days = d2.getDate() - d1.getDate();
512
+ if (days < 0) {
513
+ months--;
514
+ days += 30;
515
+ }
516
+ if (months < 0) {
517
+ years--;
518
+ months += 12;
519
+ }
520
+ return `${years} years ${months} months ${days} days`;
521
+ }, { description: 'Age between two dates as text' });
522
+ }
523
+ arrayFunctions(model) {
524
+ model.addFunction('map(list: any[], predicate: T):T[]', new MapEval(this.builder, this.cloner, this.helper), { description: 'Map' });
525
+ model.addFunctionAlias('select', 'map');
526
+ model.addFunction('foreach(list: any[], predicate: any):void', new Foreach(), { description: 'Foreach' });
527
+ model.addFunctionAlias('each', 'foreach');
528
+ model.addFunction('filter(list: T[], predicate: boolean):T[]', new Filter(), { description: 'Filter' });
529
+ model.addFunctionAlias('where', 'filter');
530
+ model.addFunction('reverse(list: T[], predicate: any):T[]', new Reverse(), { description: 'Reverse' });
531
+ model.addFunction('sort(list: T[], predicate: any):T[]', new Sort(), { description: 'Sort' });
532
+ model.addFunctionAlias('order', 'sort');
533
+ model.addFunction('remove(list: T[], predicate: boolean):T[]', new Remove(), { description: 'Remove' });
534
+ model.addFunctionAlias('delete', 'remove');
535
+ model.addFunction('push(list: T[], value: T):T[]', (list, item) => {
536
+ list.push(item);
537
+ return list;
538
+ }, { description: 'Push' });
539
+ model.addFunctionAlias('insert', 'push');
540
+ model.addFunction('bulkInsert(list: T[], value: T[]):T[]', (list, items) => {
541
+ for (const item of items) {
542
+ list.push(item);
543
+ }
544
+ return list;
545
+ }, { description: 'Bulk Insert' });
546
+ model.addFunction('pop(list: T[]): T', (list) => list.pop(), { description: 'Pop' });
547
+ model.addFunction('length(source: any[]|string):number', (source) => source.length, { description: 'Length' });
548
+ model.addFunctionAlias('len', 'length');
549
+ model.addFunction('slice(list: T[], from:integer, to:integer):T[]', (list, from, to) => list.slice(from, to), { description: 'Slice' });
550
+ model.addFunction('page(list: T[], page:integer, records:integer):T[]', (list, page, records) => {
551
+ let from = (page - 1) * records;
552
+ if (from < 0) {
553
+ from = 0;
554
+ }
555
+ let to = from + records;
556
+ if (to > list.length) {
557
+ to = list.length;
558
+ }
559
+ return list.slice(from, to);
560
+ }, { description: 'Paging' });
561
+ }
562
+ groupFunctions(model) {
563
+ model.addFunction('distinct(list: any[], predicate: any): any[]', new Distinct(this.helper), { description: 'Distinct' });
564
+ model.addFunction('first(list: T[], predicate: boolean): T', new First(this.helper), { description: 'First' });
565
+ model.addFunction('last(list: T[], predicate: boolean): T', new Last(this.helper), { description: 'Last' });
566
+ model.addFunction('count(list: T[], predicate: boolean): integer', new Count(this.helper), { description: 'Count' });
567
+ model.addFunction('max(list: T[], predicate: boolean): T', new Max(this.helper), { description: 'Max' });
568
+ model.addFunction('min(list: T[], predicate: boolean): T', new Min(this.helper), { description: 'Min' });
569
+ model.addFunction('avg(list: T[], value: number): number', new Avg(this.helper), { description: 'Average' });
570
+ model.addFunction('sum(list: T[], value: number): number', new Sum(this.helper), { description: 'Sum' });
571
+ }
572
+ extAggregationFunctions(model) {
573
+ model.addFunction('countDistinct(list:T[],predicate?:any):integer', new CountDistinct(), { description: 'Count distinct values' });
574
+ model.addFunction('sumDistinct(list:T[],predicate?:number):number', new SumDistinct(), { description: 'Sum of distinct values' });
575
+ model.addFunction('avgDistinct(list:T[],predicate?:number):number', new AvgDistinct(), { description: 'Average of distinct values' });
576
+ model.addFunction('median(list:T[],predicate?:number):number', new Median(), { description: 'Median value' });
577
+ model.addFunction('percentileCont(list:number[],p:number):number', (list, p) => {
578
+ if (!list.length)
579
+ return 0;
580
+ const sorted = [...list].sort((a, b) => a - b);
581
+ const pos = p * (sorted.length - 1);
582
+ const lo = Math.floor(pos);
583
+ const hi = Math.ceil(pos);
584
+ return lo === hi ? sorted[lo] : sorted[lo] + (sorted[hi] - sorted[lo]) * (pos - lo);
585
+ }, { description: 'Continuous percentile interpolation' });
586
+ model.addFunction('percentileDisc(list:number[],p:number):number', (list, p) => {
587
+ if (!list.length)
588
+ return 0;
589
+ const sorted = [...list].sort((a, b) => a - b);
590
+ return sorted[Math.min(Math.floor(p * sorted.length), sorted.length - 1)];
591
+ }, { description: 'Discrete percentile' });
592
+ model.addFunction('stdDev(list:T[],predicate?:number):number', new StdDevEval(false), { description: 'Sample standard deviation' });
593
+ model.addFunctionAlias('stdDevSamp', 'stdDev');
594
+ model.addFunction('stdDevPop(list:T[],predicate?:number):number', new StdDevEval(true), { description: 'Population standard deviation' });
595
+ model.addFunction('variance(list:T[],predicate?:number):number', new VarianceEval(false), { description: 'Sample variance' });
596
+ model.addFunctionAlias('varSamp', 'variance');
597
+ model.addFunction('varPop(list:T[],predicate?:number):number', new VarianceEval(true), { description: 'Population variance' });
598
+ model.addFunction('boolAnd(list:T[],predicate?:boolean):boolean', new BoolAndEval(), { description: 'True if all values are truthy' });
599
+ model.addFunctionAlias('every', 'boolAnd');
600
+ model.addFunction('boolOr(list:T[],predicate?:boolean):boolean', new BoolOrEval(), { description: 'True if any value is truthy' });
601
+ model.addFunction('bitAnd(list:T[],predicate?:number):number', new BitAndAgg(), { description: 'Bitwise AND of all values' });
602
+ model.addFunction('bitOr(list:T[],predicate?:number):number', new BitOrAgg(), { description: 'Bitwise OR of all values' });
603
+ }
604
+ windowFunctions(model) {
605
+ model.addFunction('rowNumber(list:T[]):number[]', (list) => list.map((_, i) => i + 1), { description: 'Row numbers 1..n' });
606
+ model.addFunction('rank(list:T[],predicate?:any):number[]', new RankEval(false), { description: 'Rank with gaps for ties' });
607
+ model.addFunction('denseRank(list:T[],predicate?:any):number[]', new RankEval(true), { description: 'Dense rank without gaps' });
608
+ model.addFunction('lag(list:T[],n?:integer):T[]', (list, n = 1) => list.map((_, i) => i >= n ? list[i - n] : null), { description: 'Values shifted N positions back' });
609
+ model.addFunction('lead(list:T[],n?:integer):T[]', (list, n = 1) => list.map((_, i) => i + n < list.length ? list[i + n] : null), { description: 'Values shifted N positions forward' });
610
+ model.addFunction('firstValue(list:T[]):T', (list) => list.length > 0 ? list[0] : null, { description: 'First value in list' });
611
+ model.addFunction('lastValue(list:T[]):T', (list) => list.length > 0 ? list[list.length - 1] : null, { description: 'Last value in list' });
612
+ model.addFunction('nthValue(list:T[],n:integer):T', (list, n) => n >= 1 && n <= list.length ? list[n - 1] : null, { description: 'Nth value in list (1-based)' });
613
+ model.addFunction('ntile(list:T[],n:integer):number[]', (list, n) => list.map((_, i) => Math.floor(i * n / list.length) + 1), { description: 'NTile bucket numbers' });
614
+ model.addFunction('cumeDist(list:T[]):number[]', (list) => { const len = list.length; return list.map((_, i) => (i + 1) / len); }, { description: 'Cumulative distribution 0..1' });
615
+ model.addFunction('percentRank(list:T[]):number[]', (list) => {
616
+ const len = list.length;
617
+ if (len <= 1)
618
+ return list.map(() => 0);
619
+ return list.map((_, i) => i / (len - 1));
620
+ }, { description: 'Percent rank 0..1' });
621
+ model.addFunction('sumOver(list:number[]):number[]', (list) => { let r = 0; return list.map(v => { r += v; return r; }); }, { description: 'Running sum' });
622
+ model.addFunction('avgOver(list:number[]):number[]', (list) => { let r = 0; return list.map((v, i) => { r += v; return r / (i + 1); }); }, { description: 'Running average' });
623
+ model.addFunction('countOver(list:T[]):number[]', (list) => list.map((_, i) => i + 1), { description: 'Running count' });
624
+ model.addFunction('minOver(list:number[]):number[]', (list) => { let m = Infinity; return list.map(v => { if (v < m)
625
+ m = v; return m; }); }, { description: 'Running minimum' });
626
+ model.addFunction('maxOver(list:number[]):number[]', (list) => { let m = -Infinity; return list.map(v => { if (v > m)
627
+ m = v; return m; }); }, { description: 'Running maximum' });
628
+ }
629
+ jsonFunctions(model) {
630
+ model.addFunction('jsonExtract(obj:any,path:string):any', (obj, path) => {
631
+ if (obj === null || obj === undefined)
632
+ return null;
633
+ const parts = path.replace(/^\$\.?/, '').split('.').filter(p => p);
634
+ let cur = obj;
635
+ for (const p of parts) {
636
+ if (cur === null || cur === undefined)
637
+ return null;
638
+ cur = cur[p];
639
+ }
640
+ return cur;
641
+ }, { description: 'Extract value from object by dot path ($. prefix optional)' });
642
+ model.addFunctionAlias('jsonValue', 'jsonExtract');
643
+ model.addFunctionAlias('jsonQuery', 'jsonExtract');
644
+ model.addFunction('jsonUnquote(value:string):any', (value) => { try {
645
+ return JSON.parse(value);
646
+ }
647
+ catch (_a) {
648
+ return value;
649
+ } }, { description: 'Parse JSON string, return as-is if invalid' });
650
+ model.addFunction('jsonArray(...values:any):any[]', (...values) => values, { description: 'Create JSON array' });
651
+ model.addFunction('jsonObject(...entries:any):any', (...entries) => {
652
+ const obj = {};
653
+ for (let i = 0; i + 1 < entries.length; i += 2)
654
+ obj[entries[i]] = entries[i + 1];
655
+ return obj;
656
+ }, { description: 'Create JSON object from key-value pairs' });
657
+ model.addFunction('jsonContains(obj:any,value:any):boolean', (obj, value) => {
658
+ if (!obj)
659
+ return false;
660
+ return JSON.stringify(obj).includes(JSON.stringify(value));
661
+ }, { description: 'Check if JSON contains value' });
662
+ model.addFunction('jsonMerge(a:any,b:any):any', (a, b) => (Object.assign(Object.assign({}, a), b)), { description: 'Merge two JSON objects' });
663
+ model.addFunction('jsonRemove(obj:any,key:string):any', (obj, key) => { const r = Object.assign({}, obj); delete r[key]; return r; }, { description: 'Remove property from JSON object' });
664
+ model.addFunction('jsonValid(value:string):boolean', (value) => { try {
665
+ JSON.parse(value);
666
+ return true;
667
+ }
668
+ catch (_a) {
669
+ return false;
670
+ } }, { description: 'Check if string is valid JSON' });
671
+ model.addFunctionAlias('jsonKeys', 'keys');
672
+ model.addFunction('jsonAgg(list:T[]):T[]', (list) => list, { description: 'Return list as JSON array' });
673
+ model.addFunctionAlias('jsonArrayAgg', 'jsonAgg');
674
+ model.addFunction('jsonObjectAgg(list:any[],keyProp:string,valueProp:string):any', (list, keyProp, valueProp) => {
675
+ const r = {};
676
+ for (const item of list)
677
+ r[item[keyProp]] = item[valueProp];
678
+ return r;
679
+ }, { description: 'Aggregate list to JSON object using key/value property names' });
680
+ model.addFunction('jsonModify(obj:any,path:string,value:any):any', (obj, path, value) => {
681
+ const result = JSON.parse(JSON.stringify(obj));
682
+ const parts = path.replace(/^\$\.?/, '').split('.').filter(p => p);
683
+ let cur = result;
684
+ for (let i = 0; i < parts.length - 1; i++) {
685
+ cur = cur[parts[i]];
686
+ }
687
+ if (parts.length > 0)
688
+ cur[parts[parts.length - 1]] = value;
689
+ return result;
690
+ }, { description: 'Set a value at a JSON path' });
691
+ }
692
+ statisticalFunctions(model) {
693
+ model.addFunction('corr(x:number[],y:number[]):number', (x, y) => {
694
+ const n = Math.min(x.length, y.length);
695
+ if (n === 0)
696
+ return 0;
697
+ const mx = x.slice(0, n).reduce((s, v) => s + v, 0) / n;
698
+ const my = y.slice(0, n).reduce((s, v) => s + v, 0) / n;
699
+ let num = 0;
700
+ let dx = 0;
701
+ let dy = 0;
702
+ for (let i = 0; i < n; i++) {
703
+ num += (x[i] - mx) * (y[i] - my);
704
+ dx += (x[i] - mx) ** 2;
705
+ dy += (y[i] - my) ** 2;
706
+ }
707
+ return dx === 0 || dy === 0 ? 0 : num / Math.sqrt(dx * dy);
708
+ }, { description: 'Pearson correlation coefficient' });
709
+ model.addFunction('covarPop(x:number[],y:number[]):number', (x, y) => {
710
+ const n = Math.min(x.length, y.length);
711
+ if (n === 0)
712
+ return 0;
713
+ const mx = x.slice(0, n).reduce((s, v) => s + v, 0) / n;
714
+ const my = y.slice(0, n).reduce((s, v) => s + v, 0) / n;
715
+ return x.slice(0, n).reduce((s, v, i) => s + (v - mx) * (y[i] - my), 0) / n;
716
+ }, { description: 'Population covariance' });
717
+ model.addFunction('covarSamp(x:number[],y:number[]):number', (x, y) => {
718
+ const n = Math.min(x.length, y.length);
719
+ if (n <= 1)
720
+ return 0;
721
+ const mx = x.slice(0, n).reduce((s, v) => s + v, 0) / n;
722
+ const my = y.slice(0, n).reduce((s, v) => s + v, 0) / n;
723
+ return x.slice(0, n).reduce((s, v, i) => s + (v - mx) * (y[i] - my), 0) / (n - 1);
724
+ }, { description: 'Sample covariance' });
725
+ model.addFunction('regrSlope(y:number[],x:number[]):number', (y, x) => {
726
+ const n = Math.min(x.length, y.length);
727
+ if (n === 0)
728
+ return 0;
729
+ const mx = x.slice(0, n).reduce((s, v) => s + v, 0) / n;
730
+ const my = y.slice(0, n).reduce((s, v) => s + v, 0) / n;
731
+ const num = x.slice(0, n).reduce((s, v, i) => s + (v - mx) * (y[i] - my), 0);
732
+ const den = x.slice(0, n).reduce((s, v) => s + (v - mx) ** 2, 0);
733
+ return den === 0 ? 0 : num / den;
734
+ }, { description: 'Slope of linear regression line' });
735
+ model.addFunction('regrIntercept(y:number[],x:number[]):number', (y, x) => {
736
+ const n = Math.min(x.length, y.length);
737
+ if (n === 0)
738
+ return 0;
739
+ const mx = x.slice(0, n).reduce((s, v) => s + v, 0) / n;
740
+ const my = y.slice(0, n).reduce((s, v) => s + v, 0) / n;
741
+ const num = x.slice(0, n).reduce((s, v, i) => s + (v - mx) * (y[i] - my), 0);
742
+ const den = x.slice(0, n).reduce((s, v) => s + (v - mx) ** 2, 0);
743
+ return my - (den === 0 ? 0 : num / den) * mx;
744
+ }, { description: 'Intercept of linear regression line' });
745
+ }
746
+ systemFunctions(model) {
747
+ model.addFunction('uuid():string', () => {
748
+ if (typeof globalThis.crypto !== 'undefined' && typeof globalThis.crypto.randomUUID === 'function') {
749
+ return globalThis.crypto.randomUUID();
750
+ }
751
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
752
+ const r = Math.random() * 16 | 0;
753
+ return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
754
+ });
755
+ }, { deterministic: false, description: 'Generate UUID v4' });
756
+ }
757
+ setsFunctions(model) {
758
+ model.addFunction('union(a: T[], b: T[]): T[]', new Union(this.helper), { description: 'Union' });
759
+ model.addFunction('intersection(a: T[], b: T[]): T[]', new Intersection(this.helper), { description: 'Intersection' });
760
+ model.addFunction('difference(a: T[], b: T[]): T[]', new Difference(this.helper), { description: 'Difference' });
761
+ model.addFunction('symmetricDifference(a: T[], b: T[]): T[]', new SymmetricDifference(this.helper), { description: 'Symmetric Difference' });
762
+ }
763
+ }
764
+ exports.CoreLibrary = CoreLibrary;
765
+ class And extends domain_2.PrototypeEvaluator {
766
+ clone(operand) {
767
+ return new And(operand);
768
+ }
769
+ eval(context) {
770
+ if (!this.op.children[0].eval(context))
771
+ return false;
772
+ return this.op.children[1].eval(context);
773
+ }
774
+ async evalAsync(context) {
775
+ if (!(await this.op.children[0].solve(context)))
776
+ return false;
777
+ return await this.op.children[1].solve(context);
778
+ }
779
+ }
780
+ class Or extends domain_2.PrototypeEvaluator {
781
+ clone(operand) {
782
+ return new Or(operand);
783
+ }
784
+ eval(context) {
785
+ if (this.op.children[0].eval(context))
786
+ return true;
787
+ return this.op.children[1].eval(context);
788
+ }
789
+ async evalAsync(context) {
790
+ if (await this.op.children[0].solve(context))
791
+ return true;
792
+ return await this.op.children[1].solve(context);
793
+ }
794
+ }
795
+ class Assignment extends domain_2.PrototypeEvaluator {
796
+ clone(operand) {
797
+ return new Assignment(operand);
798
+ }
799
+ eval(context) {
800
+ const value = this.op.children[1].eval(context);
801
+ context.data.set(this.op.children[0].name, value);
802
+ return value;
803
+ }
804
+ async evalAsync(context) {
805
+ const value = await this.op.children[1].solve(context);
806
+ context.data.set(this.op.children[0].name, value);
807
+ return value;
808
+ }
809
+ }
810
+ class AssignmentOp extends domain_2.PrototypeEvaluator {
811
+ constructor(operate, operand) {
812
+ super(operand);
813
+ this.operate = operate;
814
+ }
815
+ clone(operand) {
816
+ return new AssignmentOp(this.operate, operand);
817
+ }
818
+ eval(context) {
819
+ const value = this.operate(this.op.children[0].eval(context), this.op.children[1].eval(context));
820
+ context.data.set(this.op.children[0].name, value);
821
+ return value;
822
+ }
823
+ async evalAsync(context) {
824
+ const a = await this.op.children[0].solve(context);
825
+ const b = await this.op.children[1].solve(context);
826
+ const value = this.operate(a, b);
827
+ context.data.set(this.op.children[0].name, value);
828
+ return value;
829
+ }
830
+ }
831
+ class MapEval extends domain_2.PrototypeEvaluator {
832
+ // eslint-disable-next-line no-useless-constructor
833
+ constructor(builder, cloner, helper, operand) {
834
+ super(operand);
835
+ this.builder = builder;
836
+ this.cloner = cloner;
837
+ this.helper = helper;
838
+ }
839
+ clone(operand) {
840
+ return new MapEval(this.builder, this.cloner, this.helper, operand);
841
+ }
842
+ eval(context) {
843
+ const rows = [];
844
+ const list = this.op.children[0].eval(context);
845
+ if (!list) {
846
+ throw new Error(`Array ${this.op.children[0].name} undefined`);
847
+ }
848
+ if (this.op.children[2].type === domain_1.OperandType.Obj) {
849
+ const groupers = [];
850
+ const aggregates = [];
851
+ for (const child of this.op.children[2].children) {
852
+ const keyValue = child;
853
+ if (keyValue) {
854
+ if (this.helper.operand.haveAggregates(keyValue.children[0])) {
855
+ aggregates.push(keyValue);
856
+ }
857
+ else {
858
+ groupers.push(keyValue);
859
+ }
860
+ }
861
+ }
862
+ if (aggregates.length > 0) {
863
+ const keys = this.helper.operand.getKeys(this.op.children[1], groupers, list, context);
864
+ const variable = this.op.children[1];
865
+ for (const key of keys) {
866
+ for (const keyValue of aggregates) {
867
+ const operandCloned = this.cloner.clone(keyValue.children[0], 'expression');
868
+ const operandResolved = this.helper.operand.solveAggregates(key.items, variable, operandCloned, context);
869
+ const value = operandResolved.eval(context);
870
+ key.summarizers.push({ name: keyValue.name, value });
871
+ }
872
+ }
873
+ for (const key of keys) {
874
+ const row = {};
875
+ for (const value of key.values) {
876
+ row[value.name] = value.value;
877
+ }
878
+ for (const summarizer of key.summarizers) {
879
+ row[summarizer.name] = summarizer.value;
880
+ }
881
+ rows.push(row);
882
+ }
883
+ return rows;
884
+ }
885
+ }
886
+ else if (this.op.children[2].type === domain_1.OperandType.Var && !Array.isArray(list)) {
887
+ // Example orders.0.number
888
+ return list;
889
+ }
890
+ const childContext = context.newContext();
891
+ for (const item of list) {
892
+ childContext.data.set(this.op.children[1].name, item);
893
+ const row = this.op.children[2].eval(childContext);
894
+ rows.push(row);
895
+ }
896
+ return rows;
897
+ }
898
+ async evalAsync(context) {
899
+ const rows = [];
900
+ const list = await this.op.children[0].solve(context);
901
+ if (!list) {
902
+ throw new Error(`Array ${this.op.children[0].name} undefined`);
903
+ }
904
+ if (this.op.children[2].type === domain_1.OperandType.Obj) {
905
+ const groupers = [];
906
+ const aggregates = [];
907
+ for (const child of this.op.children[2].children) {
908
+ const keyValue = child;
909
+ if (keyValue) {
910
+ if (this.helper.operand.haveAggregates(keyValue.children[0])) {
911
+ aggregates.push(keyValue);
912
+ }
913
+ else {
914
+ groupers.push(keyValue);
915
+ }
916
+ }
917
+ }
918
+ if (aggregates.length > 0) {
919
+ const keys = this.helper.operand.getKeys(this.op.children[1], groupers, list, context);
920
+ const variable = this.op.children[1];
921
+ for (const key of keys) {
922
+ for (const keyValue of aggregates) {
923
+ const operandCloned = this.cloner.clone(keyValue.children[0], 'expression');
924
+ const operandResolved = this.helper.operand.solveAggregates(key.items, variable, operandCloned, context);
925
+ const value = await operandResolved.solve(context);
926
+ key.summarizers.push({ name: keyValue.name, value });
927
+ }
928
+ }
929
+ for (const key of keys) {
930
+ const row = {};
931
+ for (const value of key.values) {
932
+ row[value.name] = value.value;
933
+ }
934
+ for (const summarizer of key.summarizers) {
935
+ row[summarizer.name] = summarizer.value;
936
+ }
937
+ rows.push(row);
938
+ }
939
+ return rows;
940
+ }
941
+ }
942
+ else if (this.op.children[2].type === domain_1.OperandType.Var && !Array.isArray(list)) {
943
+ // Example orders.0.number
944
+ return list;
945
+ }
946
+ const childContext = context.newContext();
947
+ for (const item of list) {
948
+ childContext.data.set(this.op.children[1].name, item);
949
+ const row = await this.op.children[2].solve(childContext);
950
+ rows.push(row);
951
+ }
952
+ return rows;
953
+ }
954
+ }
955
+ class Distinct extends domain_2.PrototypeEvaluator {
956
+ constructor(helper, operand) {
957
+ super(operand);
958
+ this.helper = helper;
959
+ }
960
+ clone(operand) {
961
+ return new Distinct(this.helper, operand);
962
+ }
963
+ eval(context) {
964
+ const rows = [];
965
+ const list = this.op.children[0].eval(context);
966
+ if (!list) {
967
+ throw new Error(`Array ${this.op.children[0].name} undefined`);
968
+ }
969
+ if (this.op.children.length === 1) {
970
+ for (const item of list) {
971
+ if (rows.find((p) => p === item) === undefined) {
972
+ rows.push(item);
973
+ }
974
+ }
975
+ return rows;
976
+ }
977
+ else if (this.op.children[2].type === domain_1.OperandType.Obj) {
978
+ const keys = this.helper.operand.getKeys(this.op.children[1], this.op.children[2].children, list, context.newContext());
979
+ for (const key of keys) {
980
+ const row = {};
981
+ for (const value of key.values) {
982
+ row[value.name] = value.value;
983
+ }
984
+ rows.push(row);
985
+ }
986
+ return rows;
987
+ }
988
+ else if (this.op.children[2].type === domain_1.OperandType.List) {
989
+ throw new Error('Distinct not support Array result');
990
+ }
991
+ const childContext = context.newContext();
992
+ for (const item of list) {
993
+ childContext.data.set(this.op.children[1].name, item);
994
+ const value = this.op.children[2].eval(childContext);
995
+ if (rows.find((p) => p === value) === undefined) {
996
+ rows.push(value);
997
+ }
998
+ }
999
+ return rows;
1000
+ }
1001
+ async evalAsync(context) {
1002
+ const rows = [];
1003
+ const list = await this.op.children[0].solve(context);
1004
+ if (!list) {
1005
+ throw new Error(`Array ${this.op.children[0].name} undefined`);
1006
+ }
1007
+ if (this.op.children.length === 1) {
1008
+ for (const item of list) {
1009
+ if (rows.find((p) => p === item) === undefined) {
1010
+ rows.push(item);
1011
+ }
1012
+ }
1013
+ return rows;
1014
+ }
1015
+ else if (this.op.children[2].type === domain_1.OperandType.Obj) {
1016
+ const keys = this.helper.operand.getKeys(this.op.children[1], this.op.children[2].children, list, context.newContext());
1017
+ for (const key of keys) {
1018
+ const row = {};
1019
+ for (const value of key.values) {
1020
+ row[value.name] = value.value;
1021
+ }
1022
+ rows.push(row);
1023
+ }
1024
+ return rows;
1025
+ }
1026
+ else if (this.op.children[2].type === domain_1.OperandType.List) {
1027
+ throw new Error('Distinct not support Array result');
1028
+ }
1029
+ const childContext = context.newContext();
1030
+ for (const item of list) {
1031
+ childContext.data.set(this.op.children[1].name, item);
1032
+ const value = await this.op.children[2].solve(childContext);
1033
+ if (rows.find((p) => p === value) === undefined) {
1034
+ rows.push(value);
1035
+ }
1036
+ }
1037
+ return rows;
1038
+ }
1039
+ }
1040
+ class Foreach extends domain_2.PrototypeEvaluator {
1041
+ clone(operand) {
1042
+ return new Foreach(operand);
1043
+ }
1044
+ eval(context) {
1045
+ const list = this.op.children[0].eval(context);
1046
+ if (!list) {
1047
+ throw new Error(`Array ${this.op.children[0].name} undefined`);
1048
+ }
1049
+ const childContext = context.newContext();
1050
+ for (const item of list) {
1051
+ childContext.data.set(this.op.children[1].name, item);
1052
+ this.op.children[2].eval(childContext);
1053
+ }
1054
+ return list;
1055
+ }
1056
+ async evalAsync(context) {
1057
+ const list = await this.op.children[0].solve(context);
1058
+ if (!list) {
1059
+ throw new Error(`Array ${this.op.children[0].name} undefined`);
1060
+ }
1061
+ const childContext = context.newContext();
1062
+ for (const item of list) {
1063
+ childContext.data.set(this.op.children[1].name, item);
1064
+ await this.op.children[2].solve(childContext);
1065
+ }
1066
+ return list;
1067
+ }
1068
+ }
1069
+ class Filter extends domain_2.PrototypeEvaluator {
1070
+ clone(operand) {
1071
+ return new Filter(operand);
1072
+ }
1073
+ eval(context) {
1074
+ const rows = [];
1075
+ const list = this.op.children[0].eval(context);
1076
+ if (!list) {
1077
+ throw new Error(`Array ${this.op.children[0].name} undefined`);
1078
+ }
1079
+ const childContext = context.newContext();
1080
+ for (const item of list) {
1081
+ childContext.data.set(this.op.children[1].name, item);
1082
+ if (this.op.children[2].eval(childContext)) {
1083
+ rows.push(item);
1084
+ }
1085
+ }
1086
+ return rows;
1087
+ }
1088
+ async evalAsync(context) {
1089
+ const rows = [];
1090
+ const list = await this.op.children[0].solve(context);
1091
+ if (!list) {
1092
+ throw new Error(`Array ${this.op.children[0].name} undefined`);
1093
+ }
1094
+ const childContext = context.newContext();
1095
+ for (const item of list) {
1096
+ childContext.data.set(this.op.children[1].name, item);
1097
+ if (await this.op.children[2].solve(childContext)) {
1098
+ rows.push(item);
1099
+ }
1100
+ }
1101
+ return rows;
1102
+ }
1103
+ }
1104
+ class Reverse extends domain_2.PrototypeEvaluator {
1105
+ clone(operand) {
1106
+ return new Reverse(operand);
1107
+ }
1108
+ eval(context) {
1109
+ const list = this.op.children[0].eval(context);
1110
+ if (!list) {
1111
+ throw new Error(`Array ${this.op.children[0].name} undefined`);
1112
+ }
1113
+ if (this.op.children.length === 1) {
1114
+ return list.reverse();
1115
+ }
1116
+ const values = [];
1117
+ const childContext = context.newContext();
1118
+ for (const item of list) {
1119
+ childContext.data.set(this.op.children[1].name, item);
1120
+ const value = this.op.children[2].eval(childContext);
1121
+ values.push({ value, p: item });
1122
+ }
1123
+ values.sort((a, b) => a.value > b.value ? 1 : a.value < b.value ? -1 : 0);
1124
+ values.reverse();
1125
+ return values.map(p => p.p);
1126
+ }
1127
+ async evalAsync(context) {
1128
+ const list = await this.op.children[0].solve(context);
1129
+ if (!list) {
1130
+ throw new Error(`Array ${this.op.children[0].name} undefined`);
1131
+ }
1132
+ if (this.op.children.length === 1) {
1133
+ return list.reverse();
1134
+ }
1135
+ const values = [];
1136
+ const childContext = context.newContext();
1137
+ for (const item of list) {
1138
+ childContext.data.set(this.op.children[1].name, item);
1139
+ const value = await this.op.children[2].solve(childContext);
1140
+ values.push({ value, p: item });
1141
+ }
1142
+ values.sort((a, b) => a.value > b.value ? 1 : a.value < b.value ? -1 : 0);
1143
+ values.reverse();
1144
+ return values.map(p => p.p);
1145
+ }
1146
+ }
1147
+ class Sort extends domain_2.PrototypeEvaluator {
1148
+ clone(operand) {
1149
+ return new Sort(operand);
1150
+ }
1151
+ eval(context) {
1152
+ const values = [];
1153
+ const list = this.op.children[0].eval(context);
1154
+ if (!list) {
1155
+ throw new Error(`Array ${this.op.children[0].name} undefined`);
1156
+ }
1157
+ if (this.op.children.length === 1) {
1158
+ return list.sort();
1159
+ }
1160
+ const childContext = context.newContext();
1161
+ for (const item of list) {
1162
+ childContext.data.set(this.op.children[1].name, item);
1163
+ const value = this.op.children[2].eval(childContext);
1164
+ values.push({ value, p: item });
1165
+ }
1166
+ values.sort((a, b) => a.value > b.value ? 1 : a.value < b.value ? -1 : 0);
1167
+ return values.map(p => p.p);
1168
+ }
1169
+ async evalAsync(context) {
1170
+ const values = [];
1171
+ const list = await this.op.children[0].solve(context);
1172
+ if (!list) {
1173
+ throw new Error(`Array ${this.op.children[0].name} undefined`);
1174
+ }
1175
+ if (this.op.children.length === 1) {
1176
+ return list.sort();
1177
+ }
1178
+ const childContext = context.newContext();
1179
+ for (const item of list) {
1180
+ childContext.data.set(this.op.children[1].name, item);
1181
+ const value = await this.op.children[2].solve(childContext);
1182
+ values.push({ value, p: item });
1183
+ }
1184
+ values.sort((a, b) => a.value > b.value ? 1 : a.value < b.value ? -1 : 0);
1185
+ return values.map(p => p.p);
1186
+ }
1187
+ }
1188
+ class Remove extends domain_2.PrototypeEvaluator {
1189
+ clone(operand) {
1190
+ return new Remove(operand);
1191
+ }
1192
+ eval(context) {
1193
+ const rows = [];
1194
+ const list = this.op.children[0].eval(context);
1195
+ if (!list) {
1196
+ throw new Error(`Array ${this.op.children[0].name} undefined`);
1197
+ }
1198
+ const childContext = context.newContext();
1199
+ for (const item of list) {
1200
+ childContext.data.set(this.op.children[1].name, item);
1201
+ if (!this.op.children[2].eval(childContext)) {
1202
+ rows.push(item);
1203
+ }
1204
+ }
1205
+ return rows;
1206
+ }
1207
+ async evalAsync(context) {
1208
+ const rows = [];
1209
+ const list = await this.op.children[0].solve(context);
1210
+ if (!list) {
1211
+ throw new Error(`Array ${this.op.children[0].name} undefined`);
1212
+ }
1213
+ const childContext = context.newContext();
1214
+ for (const item of list) {
1215
+ childContext.data.set(this.op.children[1].name, item);
1216
+ if (!(await this.op.children[2].solve(childContext))) {
1217
+ rows.push(item);
1218
+ }
1219
+ }
1220
+ return rows;
1221
+ }
1222
+ }
1223
+ class First extends domain_2.PrototypeEvaluator {
1224
+ constructor(helper, operand) {
1225
+ super(operand);
1226
+ this.helper = helper;
1227
+ }
1228
+ clone(operand) {
1229
+ return new First(this.helper, operand);
1230
+ }
1231
+ eval(context) {
1232
+ return this.first(this.op.children[0].eval(context), context);
1233
+ }
1234
+ async evalAsync(context) {
1235
+ return this.first(await this.op.children[0].solve(context), context);
1236
+ }
1237
+ first(list, context) {
1238
+ if (!list) {
1239
+ throw new Error(`Array ${this.op.children[0].name} undefined`);
1240
+ }
1241
+ if (this.op.children.length === 1) {
1242
+ return list && list.length > 0 ? list[0] : null;
1243
+ }
1244
+ return this.helper.operand.first(list, this.op.children[1], this.op.children[2], context.newContext());
1245
+ }
1246
+ }
1247
+ class Last extends domain_2.PrototypeEvaluator {
1248
+ constructor(helper, operand) {
1249
+ super(operand);
1250
+ this.helper = helper;
1251
+ }
1252
+ clone(operand) {
1253
+ return new Last(this.helper, operand);
1254
+ }
1255
+ eval(context) {
1256
+ return this.last(this.op.children[0].eval(context), context);
1257
+ }
1258
+ async evalAsync(context) {
1259
+ return this.last(await this.op.children[0].solve(context), context);
1260
+ }
1261
+ last(list, context) {
1262
+ if (!list) {
1263
+ throw new Error(`Array ${this.op.children[0].name} undefined`);
1264
+ }
1265
+ if (this.op.children.length === 1) {
1266
+ return list && list.length > 0 ? list[list.length - 1] : null;
1267
+ }
1268
+ return this.helper.operand.last(list, this.op.children[1], this.op.children[2], context.newContext());
1269
+ }
1270
+ }
1271
+ class Count extends domain_2.PrototypeEvaluator {
1272
+ constructor(helper, operand) {
1273
+ super(operand);
1274
+ this.helper = helper;
1275
+ }
1276
+ clone(operand) {
1277
+ return new Count(this.helper, operand);
1278
+ }
1279
+ eval(context) {
1280
+ return this.count(this.op.children[0].eval(context), context);
1281
+ }
1282
+ async evalAsync(context) {
1283
+ return this.count(await this.op.children[0].solve(context), context);
1284
+ }
1285
+ count(list, context) {
1286
+ if (!list) {
1287
+ throw new Error(`Array ${this.op.children[0].name} undefined`);
1288
+ }
1289
+ if (this.op.children.length === 1) {
1290
+ return list.length;
1291
+ }
1292
+ return this.helper.operand.count(list, this.op.children[1], this.op.children[2], context.newContext());
1293
+ }
1294
+ }
1295
+ class Max extends domain_2.PrototypeEvaluator {
1296
+ constructor(helper, operand) {
1297
+ super(operand);
1298
+ this.helper = helper;
1299
+ }
1300
+ clone(operand) {
1301
+ return new Max(this.helper, operand);
1302
+ }
1303
+ eval(context) {
1304
+ return this.max(this.op.children[0].eval(context), context);
1305
+ }
1306
+ async evalAsync(context) {
1307
+ return this.max(await this.op.children[0].solve(context), context);
1308
+ }
1309
+ max(list, context) {
1310
+ if (!list) {
1311
+ throw new Error(`Array ${this.op.children[0].name} undefined`);
1312
+ }
1313
+ if (this.op.children.length === 1) {
1314
+ let max;
1315
+ for (const item of list) {
1316
+ if (max === undefined || (item !== null && item > max)) {
1317
+ max = item;
1318
+ }
1319
+ }
1320
+ return max;
1321
+ }
1322
+ return this.helper.operand.max(list, this.op.children[1], this.op.children[2], context.newContext());
1323
+ }
1324
+ }
1325
+ class Min extends domain_2.PrototypeEvaluator {
1326
+ constructor(helper, operand) {
1327
+ super(operand);
1328
+ this.helper = helper;
1329
+ }
1330
+ clone(operand) {
1331
+ return new Min(this.helper, operand);
1332
+ }
1333
+ eval(context) {
1334
+ return this.min(this.op.children[0].eval(context), context);
1335
+ }
1336
+ async evalAsync(context) {
1337
+ return this.min(await this.op.children[0].solve(context), context);
1338
+ }
1339
+ min(list, context) {
1340
+ if (!list) {
1341
+ throw new Error(`Array ${this.op.children[0].name} undefined`);
1342
+ }
1343
+ if (this.op.children.length === 1) {
1344
+ let min;
1345
+ for (const item of list) {
1346
+ if (min === undefined || (item !== null && item < min)) {
1347
+ min = item;
1348
+ }
1349
+ }
1350
+ return min;
1351
+ }
1352
+ return this.helper.operand.min(list, this.op.children[1], this.op.children[2], context.newContext());
1353
+ }
1354
+ }
1355
+ class Avg extends domain_2.PrototypeEvaluator {
1356
+ constructor(helper, operand) {
1357
+ super(operand);
1358
+ this.helper = helper;
1359
+ }
1360
+ clone(operand) {
1361
+ return new Avg(this.helper, operand);
1362
+ }
1363
+ eval(context) {
1364
+ return this.avg(this.op.children[0].eval(context), context);
1365
+ }
1366
+ async evalAsync(context) {
1367
+ return this.avg(await this.op.children[0].solve(context), context);
1368
+ }
1369
+ avg(list, context) {
1370
+ if (this.op.children.length === 1) {
1371
+ let sum = 0;
1372
+ for (const item of list) {
1373
+ if (item !== null) {
1374
+ sum = sum + item;
1375
+ }
1376
+ }
1377
+ return list.length > 0 ? sum / list.length : 0;
1378
+ }
1379
+ return this.helper.operand.avg(list, this.op.children[1], this.op.children[2], context.newContext());
1380
+ }
1381
+ }
1382
+ class Sum extends domain_2.PrototypeEvaluator {
1383
+ constructor(helper, operand) {
1384
+ super(operand);
1385
+ this.helper = helper;
1386
+ }
1387
+ clone(operand) {
1388
+ return new Sum(this.helper, operand);
1389
+ }
1390
+ eval(context) {
1391
+ return this.sum(this.op.children[0].eval(context), context);
1392
+ }
1393
+ async evalAsync(context) {
1394
+ return this.sum(await this.op.children[0].solve(context), context);
1395
+ }
1396
+ sum(list, context) {
1397
+ if (!list) {
1398
+ throw new Error(`Array ${this.op.children[0].name} undefined`);
1399
+ }
1400
+ if (this.op.children.length === 1) {
1401
+ let sum = 0;
1402
+ for (const item of list) {
1403
+ if (item !== null) {
1404
+ sum = sum + item;
1405
+ }
1406
+ }
1407
+ return sum;
1408
+ }
1409
+ return this.helper.operand.sum(list, this.op.children[1], this.op.children[2], context.newContext());
1410
+ }
1411
+ }
1412
+ class Union extends domain_2.PrototypeEvaluator {
1413
+ constructor(helper, operand) {
1414
+ super(operand);
1415
+ this.helper = helper;
1416
+ }
1417
+ clone(operand) {
1418
+ return new Union(this.helper, operand);
1419
+ }
1420
+ eval(context) {
1421
+ const a = this.op.children[0].eval(context);
1422
+ const b = this.op.children[1].eval(context);
1423
+ return this.union(a, b);
1424
+ }
1425
+ async evalAsync(context) {
1426
+ const a = await this.op.children[0].solve(context);
1427
+ const b = await this.op.children[1].solve(context);
1428
+ return this.union(a, b);
1429
+ }
1430
+ union(a, b) {
1431
+ if (a.length === 0) {
1432
+ return b;
1433
+ }
1434
+ if (b.length === 0) {
1435
+ return a;
1436
+ }
1437
+ let result = [];
1438
+ if (Array.isArray(a[0]) || Array.isArray(b[0])) {
1439
+ throw new Error('Cannot union arrays of arrays');
1440
+ }
1441
+ else if (typeof a[0] === 'object') {
1442
+ for (const element of a) {
1443
+ const key = this.helper.operand.objectKey(element);
1444
+ result.push({ key, value: element });
1445
+ }
1446
+ for (const element of b) {
1447
+ const key = this.helper.operand.objectKey(element);
1448
+ if (!result.find((p) => p.key === key)) {
1449
+ result.push({ key, value: element });
1450
+ }
1451
+ }
1452
+ return result.map((p) => p.value);
1453
+ }
1454
+ result = result.concat(a);
1455
+ for (const element of b) {
1456
+ if (!result.includes(element)) {
1457
+ result.push(element);
1458
+ }
1459
+ }
1460
+ return result;
1461
+ }
1462
+ }
1463
+ class Intersection extends domain_2.PrototypeEvaluator {
1464
+ constructor(helper, operand) {
1465
+ super(operand);
1466
+ this.helper = helper;
1467
+ }
1468
+ clone(operand) {
1469
+ return new Intersection(this.helper, operand);
1470
+ }
1471
+ eval(context) {
1472
+ const a = this.op.children[0].eval(context);
1473
+ const b = this.op.children[1].eval(context);
1474
+ return this.intersection(a, b);
1475
+ }
1476
+ async evalAsync(context) {
1477
+ const a = await this.op.children[0].solve(context);
1478
+ const b = await this.op.children[1].solve(context);
1479
+ return this.intersection(a, b);
1480
+ }
1481
+ intersection(a, b) {
1482
+ if (!a) {
1483
+ throw new Error(`Array ${this.op.children[0].name} undefined`);
1484
+ }
1485
+ if (!b) {
1486
+ throw new Error(`Array ${this.op.children[1].name} undefined`);
1487
+ }
1488
+ if (a.length === 0 || b.length === 0) {
1489
+ return [];
1490
+ }
1491
+ const result = [];
1492
+ if (Array.isArray(a[0]) || Array.isArray(b[0])) {
1493
+ throw new Error('Cannot intersect arrays of arrays');
1494
+ }
1495
+ else if (typeof a[0] === 'object') {
1496
+ const keys = a.map((p) => this.helper.operand.objectKey(p));
1497
+ for (const element of b) {
1498
+ const key = this.helper.operand.objectKey(element);
1499
+ if (keys.includes(key)) {
1500
+ result.push(element);
1501
+ }
1502
+ }
1503
+ return result;
1504
+ }
1505
+ else {
1506
+ for (const element of b) {
1507
+ if (a.includes(element)) {
1508
+ result.push(element);
1509
+ }
1510
+ }
1511
+ return result;
1512
+ }
1513
+ }
1514
+ }
1515
+ class Difference extends domain_2.PrototypeEvaluator {
1516
+ constructor(helper, operand) {
1517
+ super(operand);
1518
+ this.helper = helper;
1519
+ }
1520
+ clone(operand) {
1521
+ return new Difference(this.helper, operand);
1522
+ }
1523
+ eval(context) {
1524
+ const a = this.op.children[0].eval(context);
1525
+ const b = this.op.children[1].eval(context);
1526
+ return this.difference(a, b);
1527
+ }
1528
+ async evalAsync(context) {
1529
+ const a = await this.op.children[0].solve(context);
1530
+ const b = await this.op.children[1].solve(context);
1531
+ return this.difference(a, b);
1532
+ }
1533
+ difference(a, b) {
1534
+ if (!a) {
1535
+ throw new Error(`Array ${this.op.children[0].name} undefined`);
1536
+ }
1537
+ if (!b) {
1538
+ throw new Error(`Array ${this.op.children[1].name} undefined`);
1539
+ }
1540
+ if (a.length === 0) {
1541
+ return [];
1542
+ }
1543
+ if (b.length === 0) {
1544
+ return a;
1545
+ }
1546
+ const result = [];
1547
+ if (Array.isArray(a[0]) || Array.isArray(b[0])) {
1548
+ throw new Error('Cannot difference arrays of arrays');
1549
+ }
1550
+ else if (typeof a[0] === 'object') {
1551
+ const keys = b.map((p) => this.helper.operand.objectKey(p));
1552
+ for (const element of a) {
1553
+ const key = this.helper.operand.objectKey(element);
1554
+ if (!keys.includes(key)) {
1555
+ result.push(element);
1556
+ }
1557
+ }
1558
+ return result;
1559
+ }
1560
+ else {
1561
+ for (const element of a) {
1562
+ if (!b.includes(element)) {
1563
+ result.push(element);
1564
+ }
1565
+ }
1566
+ return result;
1567
+ }
1568
+ }
1569
+ }
1570
+ class SymmetricDifference extends domain_2.PrototypeEvaluator {
1571
+ constructor(helper, operand) {
1572
+ super(operand);
1573
+ this.helper = helper;
1574
+ }
1575
+ clone(operand) {
1576
+ return new SymmetricDifference(this.helper, operand);
1577
+ }
1578
+ eval(context) {
1579
+ const a = this.op.children[0].eval(context);
1580
+ const b = this.op.children[1].eval(context);
1581
+ return this.symmetricDifference(a, b);
1582
+ }
1583
+ async evalAsync(context) {
1584
+ const a = await this.op.children[0].solve(context);
1585
+ const b = await this.op.children[1].solve(context);
1586
+ return this.symmetricDifference(a, b);
1587
+ }
1588
+ symmetricDifference(a, b) {
1589
+ if (!a) {
1590
+ throw new Error(`Array ${this.op.children[0].name} undefined`);
1591
+ }
1592
+ if (!b) {
1593
+ throw new Error(`Array ${this.op.children[1].name} undefined`);
1594
+ }
1595
+ if (a.length === 0) {
1596
+ return b;
1597
+ }
1598
+ if (b.length === 0) {
1599
+ return a;
1600
+ }
1601
+ const result = [];
1602
+ if (Array.isArray(a[0]) || Array.isArray(b[0])) {
1603
+ throw new Error('Cannot compute symmetric difference of arrays of arrays');
1604
+ }
1605
+ else if (typeof a[0] === 'object') {
1606
+ const aKeys = a.map((p) => this.helper.operand.objectKey(p));
1607
+ const bKeys = b.map((p) => this.helper.operand.objectKey(p));
1608
+ for (const element of a) {
1609
+ const key = this.helper.operand.objectKey(element);
1610
+ if (!bKeys.includes(key)) {
1611
+ result.push(element);
1612
+ }
1613
+ }
1614
+ for (const element of b) {
1615
+ const key = this.helper.operand.objectKey(element);
1616
+ if (!aKeys.includes(key)) {
1617
+ result.push(element);
1618
+ }
1619
+ }
1620
+ return result;
1621
+ }
1622
+ else {
1623
+ for (const element of a) {
1624
+ if (!b.includes(element)) {
1625
+ result.push(element);
1626
+ }
1627
+ }
1628
+ for (const element of b) {
1629
+ if (!a.includes(element)) {
1630
+ result.push(element);
1631
+ }
1632
+ }
1633
+ return result;
1634
+ }
1635
+ }
1636
+ }
1637
+ class AggregateEval extends domain_2.PrototypeEvaluator {
1638
+ getList(context) {
1639
+ const list = this.op.children[0].eval(context);
1640
+ if (!list)
1641
+ throw new Error(`Array ${this.op.children[0].name} undefined`);
1642
+ return list;
1643
+ }
1644
+ async getListAsync(context) {
1645
+ const list = await this.op.children[0].solve(context);
1646
+ if (!list)
1647
+ throw new Error(`Array ${this.op.children[0].name} undefined`);
1648
+ return list;
1649
+ }
1650
+ evalValues(list, context) {
1651
+ if (this.op.children.length === 1)
1652
+ return list.filter(v => v !== null && v !== undefined);
1653
+ const values = [];
1654
+ const ctx = context.newContext();
1655
+ for (const item of list) {
1656
+ ctx.data.set(this.op.children[1].name, item);
1657
+ const v = this.op.children[2].eval(ctx);
1658
+ if (v !== null && v !== undefined)
1659
+ values.push(v);
1660
+ }
1661
+ return values;
1662
+ }
1663
+ async evalValuesAsync(list, context) {
1664
+ if (this.op.children.length === 1)
1665
+ return list.filter(v => v !== null && v !== undefined);
1666
+ const values = [];
1667
+ const ctx = context.newContext();
1668
+ for (const item of list) {
1669
+ ctx.data.set(this.op.children[1].name, item);
1670
+ const v = await this.op.children[2].solve(ctx);
1671
+ if (v !== null && v !== undefined)
1672
+ values.push(v);
1673
+ }
1674
+ return values;
1675
+ }
1676
+ }
1677
+ class CountDistinct extends AggregateEval {
1678
+ clone(operand) { return new CountDistinct(operand); }
1679
+ eval(context) { return new Set(this.evalValues(this.getList(context), context)).size; }
1680
+ async evalAsync(context) {
1681
+ return new Set(await this.evalValuesAsync(await this.getListAsync(context), context)).size;
1682
+ }
1683
+ }
1684
+ class SumDistinct extends AggregateEval {
1685
+ clone(operand) { return new SumDistinct(operand); }
1686
+ eval(context) { return [...new Set(this.evalValues(this.getList(context), context))].reduce((s, v) => s + v, 0); }
1687
+ async evalAsync(context) {
1688
+ return [...new Set(await this.evalValuesAsync(await this.getListAsync(context), context))].reduce((s, v) => s + v, 0);
1689
+ }
1690
+ }
1691
+ class AvgDistinct extends AggregateEval {
1692
+ clone(operand) { return new AvgDistinct(operand); }
1693
+ eval(context) { return this.compute(this.evalValues(this.getList(context), context)); }
1694
+ async evalAsync(context) { return this.compute(await this.evalValuesAsync(await this.getListAsync(context), context)); }
1695
+ compute(values) {
1696
+ const distinct = [...new Set(values)];
1697
+ return distinct.length === 0 ? 0 : distinct.reduce((s, v) => s + v, 0) / distinct.length;
1698
+ }
1699
+ }
1700
+ class Median extends AggregateEval {
1701
+ clone(operand) { return new Median(operand); }
1702
+ eval(context) { return this.compute(this.evalValues(this.getList(context), context)); }
1703
+ async evalAsync(context) { return this.compute(await this.evalValuesAsync(await this.getListAsync(context), context)); }
1704
+ compute(values) {
1705
+ if (!values.length)
1706
+ return null;
1707
+ const sorted = [...values].sort((a, b) => a - b);
1708
+ const mid = Math.floor(sorted.length / 2);
1709
+ return sorted.length % 2 === 0 ? (sorted[mid - 1] + sorted[mid]) / 2 : sorted[mid];
1710
+ }
1711
+ }
1712
+ class StdDevEval extends AggregateEval {
1713
+ constructor(population, operand) {
1714
+ super(operand);
1715
+ this.population = population;
1716
+ }
1717
+ clone(operand) { return new StdDevEval(this.population, operand); }
1718
+ eval(context) { return this.compute(this.evalValues(this.getList(context), context)); }
1719
+ async evalAsync(context) { return this.compute(await this.evalValuesAsync(await this.getListAsync(context), context)); }
1720
+ compute(values) {
1721
+ const n = values.length;
1722
+ if (n === 0)
1723
+ return 0;
1724
+ const mean = values.reduce((s, v) => s + v, 0) / n;
1725
+ const divisor = this.population ? n : n - 1;
1726
+ if (divisor === 0)
1727
+ return 0;
1728
+ return Math.sqrt(values.reduce((s, v) => s + (v - mean) ** 2, 0) / divisor);
1729
+ }
1730
+ }
1731
+ class VarianceEval extends AggregateEval {
1732
+ constructor(population, operand) {
1733
+ super(operand);
1734
+ this.population = population;
1735
+ }
1736
+ clone(operand) { return new VarianceEval(this.population, operand); }
1737
+ eval(context) { return this.compute(this.evalValues(this.getList(context), context)); }
1738
+ async evalAsync(context) { return this.compute(await this.evalValuesAsync(await this.getListAsync(context), context)); }
1739
+ compute(values) {
1740
+ const n = values.length;
1741
+ if (n === 0)
1742
+ return 0;
1743
+ const mean = values.reduce((s, v) => s + v, 0) / n;
1744
+ const divisor = this.population ? n : n - 1;
1745
+ if (divisor === 0)
1746
+ return 0;
1747
+ return values.reduce((s, v) => s + (v - mean) ** 2, 0) / divisor;
1748
+ }
1749
+ }
1750
+ class BoolAndEval extends AggregateEval {
1751
+ clone(operand) { return new BoolAndEval(operand); }
1752
+ eval(context) { return this.evalValues(this.getList(context), context).every(v => !!v); }
1753
+ async evalAsync(context) { return (await this.evalValuesAsync(await this.getListAsync(context), context)).every(v => !!v); }
1754
+ }
1755
+ class BoolOrEval extends AggregateEval {
1756
+ clone(operand) { return new BoolOrEval(operand); }
1757
+ eval(context) { return this.evalValues(this.getList(context), context).some(v => !!v); }
1758
+ async evalAsync(context) { return (await this.evalValuesAsync(await this.getListAsync(context), context)).some(v => !!v); }
1759
+ }
1760
+ class BitAndAgg extends AggregateEval {
1761
+ clone(operand) { return new BitAndAgg(operand); }
1762
+ eval(context) { return this.evalValues(this.getList(context), context).reduce((acc, v) => acc & v, -1); }
1763
+ async evalAsync(context) { return (await this.evalValuesAsync(await this.getListAsync(context), context)).reduce((acc, v) => acc & v, -1); }
1764
+ }
1765
+ class BitOrAgg extends AggregateEval {
1766
+ clone(operand) { return new BitOrAgg(operand); }
1767
+ eval(context) { return this.evalValues(this.getList(context), context).reduce((acc, v) => acc | v, 0); }
1768
+ async evalAsync(context) { return (await this.evalValuesAsync(await this.getListAsync(context), context)).reduce((acc, v) => acc | v, 0); }
1769
+ }
1770
+ class RankEval extends domain_2.PrototypeEvaluator {
1771
+ constructor(dense, operand) {
1772
+ super(operand);
1773
+ this.dense = dense;
1774
+ }
1775
+ clone(operand) { return new RankEval(this.dense, operand); }
1776
+ eval(context) { return this.computeRank(this.extractValues(this.op.children[0].eval(context), context)); }
1777
+ async evalAsync(context) { return this.computeRank(await this.extractValuesAsync(await this.op.children[0].solve(context), context)); }
1778
+ extractValues(list, context) {
1779
+ if (this.op.children.length === 1)
1780
+ return list;
1781
+ const values = [];
1782
+ const ctx = context.newContext();
1783
+ for (const item of list) {
1784
+ ctx.data.set(this.op.children[1].name, item);
1785
+ values.push(this.op.children[2].eval(ctx));
1786
+ }
1787
+ return values;
1788
+ }
1789
+ async extractValuesAsync(list, context) {
1790
+ if (this.op.children.length === 1)
1791
+ return list;
1792
+ const values = [];
1793
+ const ctx = context.newContext();
1794
+ for (const item of list) {
1795
+ ctx.data.set(this.op.children[1].name, item);
1796
+ values.push(await this.op.children[2].solve(ctx));
1797
+ }
1798
+ return values;
1799
+ }
1800
+ computeRank(values) {
1801
+ const sorted = [...new Set(values)].sort((a, b) => a > b ? 1 : -1);
1802
+ if (this.dense)
1803
+ return values.map(v => sorted.indexOf(v) + 1);
1804
+ const rankMap = new Map();
1805
+ let rank = 1;
1806
+ for (const v of sorted) {
1807
+ rankMap.set(v, rank);
1808
+ rank += values.filter(x => x === v).length;
1809
+ }
1810
+ return values.map(v => rankMap.get(v));
1811
+ }
1812
+ }
1813
+ //# sourceMappingURL=library.js.map