flowquery 1.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 (128) hide show
  1. package/.github/workflows/npm-publish.yml +30 -0
  2. package/.github/workflows/release.yml +84 -0
  3. package/CODE_OF_CONDUCT.md +10 -0
  4. package/FlowQueryLogoIcon.png +0 -0
  5. package/LICENSE +21 -0
  6. package/README.md +113 -0
  7. package/SECURITY.md +14 -0
  8. package/SUPPORT.md +13 -0
  9. package/docs/flowquery.min.js +1 -0
  10. package/docs/index.html +105 -0
  11. package/flowquery-vscode/.vscode-test.mjs +5 -0
  12. package/flowquery-vscode/.vscodeignore +13 -0
  13. package/flowquery-vscode/LICENSE +21 -0
  14. package/flowquery-vscode/README.md +11 -0
  15. package/flowquery-vscode/demo/FlowQueryVSCodeDemo.gif +0 -0
  16. package/flowquery-vscode/eslint.config.mjs +25 -0
  17. package/flowquery-vscode/extension.js +508 -0
  18. package/flowquery-vscode/flowQueryEngine/flowquery.min.js +1 -0
  19. package/flowquery-vscode/flowquery-worker.js +66 -0
  20. package/flowquery-vscode/images/FlowQueryLogoIcon.png +0 -0
  21. package/flowquery-vscode/jsconfig.json +13 -0
  22. package/flowquery-vscode/libs/page.css +53 -0
  23. package/flowquery-vscode/libs/table.css +13 -0
  24. package/flowquery-vscode/libs/tabs.css +66 -0
  25. package/flowquery-vscode/package-lock.json +2917 -0
  26. package/flowquery-vscode/package.json +51 -0
  27. package/flowquery-vscode/test/extension.test.js +196 -0
  28. package/flowquery-vscode/test/worker.test.js +25 -0
  29. package/flowquery-vscode/vsc-extension-quickstart.md +42 -0
  30. package/jest.config.js +11 -0
  31. package/package.json +28 -0
  32. package/queries/analyze_catfacts.cql +75 -0
  33. package/queries/azure_openai_completions.cql +13 -0
  34. package/queries/azure_openai_models.cql +9 -0
  35. package/queries/mock_pipeline.cql +84 -0
  36. package/queries/openai_completions.cql +15 -0
  37. package/queries/openai_models.cql +13 -0
  38. package/queries/test.cql +6 -0
  39. package/queries/tool_inference.cql +24 -0
  40. package/queries/wisdom.cql +6 -0
  41. package/queries/wisdom_letter_histogram.cql +8 -0
  42. package/src/compute/runner.ts +65 -0
  43. package/src/index.browser.ts +11 -0
  44. package/src/index.ts +12 -0
  45. package/src/io/command_line.ts +74 -0
  46. package/src/parsing/alias.ts +23 -0
  47. package/src/parsing/alias_option.ts +5 -0
  48. package/src/parsing/ast_node.ts +153 -0
  49. package/src/parsing/base_parser.ts +92 -0
  50. package/src/parsing/components/csv.ts +9 -0
  51. package/src/parsing/components/from.ts +12 -0
  52. package/src/parsing/components/headers.ts +12 -0
  53. package/src/parsing/components/json.ts +9 -0
  54. package/src/parsing/components/null.ts +9 -0
  55. package/src/parsing/components/post.ts +9 -0
  56. package/src/parsing/components/text.ts +9 -0
  57. package/src/parsing/context.ts +48 -0
  58. package/src/parsing/data_structures/associative_array.ts +43 -0
  59. package/src/parsing/data_structures/json_array.ts +31 -0
  60. package/src/parsing/data_structures/key_value_pair.ts +37 -0
  61. package/src/parsing/data_structures/lookup.ts +40 -0
  62. package/src/parsing/data_structures/range_lookup.ts +36 -0
  63. package/src/parsing/expressions/expression.ts +142 -0
  64. package/src/parsing/expressions/f_string.ts +26 -0
  65. package/src/parsing/expressions/identifier.ts +22 -0
  66. package/src/parsing/expressions/number.ts +40 -0
  67. package/src/parsing/expressions/operator.ts +179 -0
  68. package/src/parsing/expressions/reference.ts +42 -0
  69. package/src/parsing/expressions/string.ts +34 -0
  70. package/src/parsing/functions/aggregate_function.ts +58 -0
  71. package/src/parsing/functions/avg.ts +37 -0
  72. package/src/parsing/functions/collect.ts +44 -0
  73. package/src/parsing/functions/function.ts +60 -0
  74. package/src/parsing/functions/function_factory.ts +66 -0
  75. package/src/parsing/functions/join.ts +26 -0
  76. package/src/parsing/functions/predicate_function.ts +44 -0
  77. package/src/parsing/functions/predicate_function_factory.ts +15 -0
  78. package/src/parsing/functions/predicate_sum.ts +29 -0
  79. package/src/parsing/functions/rand.ts +13 -0
  80. package/src/parsing/functions/range.ts +18 -0
  81. package/src/parsing/functions/reducer_element.ts +10 -0
  82. package/src/parsing/functions/replace.ts +19 -0
  83. package/src/parsing/functions/round.ts +17 -0
  84. package/src/parsing/functions/size.ts +17 -0
  85. package/src/parsing/functions/split.ts +26 -0
  86. package/src/parsing/functions/stringify.ts +26 -0
  87. package/src/parsing/functions/sum.ts +31 -0
  88. package/src/parsing/functions/to_json.ts +17 -0
  89. package/src/parsing/functions/value_holder.ts +13 -0
  90. package/src/parsing/logic/case.ts +26 -0
  91. package/src/parsing/logic/else.ts +12 -0
  92. package/src/parsing/logic/end.ts +9 -0
  93. package/src/parsing/logic/then.ts +12 -0
  94. package/src/parsing/logic/when.ts +12 -0
  95. package/src/parsing/operations/aggregated_return.ts +18 -0
  96. package/src/parsing/operations/aggregated_with.ts +18 -0
  97. package/src/parsing/operations/group_by.ts +124 -0
  98. package/src/parsing/operations/limit.ts +22 -0
  99. package/src/parsing/operations/load.ts +92 -0
  100. package/src/parsing/operations/operation.ts +65 -0
  101. package/src/parsing/operations/projection.ts +18 -0
  102. package/src/parsing/operations/return.ts +43 -0
  103. package/src/parsing/operations/unwind.ts +32 -0
  104. package/src/parsing/operations/where.ts +38 -0
  105. package/src/parsing/operations/with.ts +20 -0
  106. package/src/parsing/parser.ts +762 -0
  107. package/src/parsing/token_to_node.ts +91 -0
  108. package/src/tokenization/keyword.ts +43 -0
  109. package/src/tokenization/operator.ts +25 -0
  110. package/src/tokenization/string_walker.ts +194 -0
  111. package/src/tokenization/symbol.ts +15 -0
  112. package/src/tokenization/token.ts +633 -0
  113. package/src/tokenization/token_mapper.ts +53 -0
  114. package/src/tokenization/token_type.ts +15 -0
  115. package/src/tokenization/tokenizer.ts +229 -0
  116. package/src/tokenization/trie.ts +117 -0
  117. package/src/utils/object_utils.ts +17 -0
  118. package/src/utils/string_utils.ts +114 -0
  119. package/tests/compute/runner.test.ts +498 -0
  120. package/tests/parsing/context.test.ts +27 -0
  121. package/tests/parsing/expression.test.ts +40 -0
  122. package/tests/parsing/parser.test.ts +434 -0
  123. package/tests/tokenization/token_mapper.test.ts +47 -0
  124. package/tests/tokenization/tokenizer.test.ts +67 -0
  125. package/tests/tokenization/trie.test.ts +20 -0
  126. package/tsconfig.json +15 -0
  127. package/typedoc.json +16 -0
  128. package/webpack.config.js +26 -0
@@ -0,0 +1,60 @@
1
+ import ASTNode from "../ast_node";
2
+
3
+ /**
4
+ * Base class for all functions in FlowQuery.
5
+ *
6
+ * Functions can have parameters and may support the DISTINCT modifier.
7
+ * Subclasses implement specific function logic.
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * const func = FunctionFactory.create("sum");
12
+ * func.parameters = [expression1, expression2];
13
+ * ```
14
+ */
15
+ class Function extends ASTNode {
16
+ protected _name: string;
17
+ protected _expectedParameterCount: number | null = null;
18
+ protected _supports_distinct: boolean = false;
19
+
20
+ /**
21
+ * Creates a new Function with the given name.
22
+ *
23
+ * @param name - The function name
24
+ */
25
+ constructor(name: string) {
26
+ super();
27
+ this._name = name;
28
+ }
29
+
30
+ /**
31
+ * Sets the function parameters.
32
+ *
33
+ * @param nodes - Array of AST nodes representing the function arguments
34
+ * @throws {Error} If the number of parameters doesn't match expected count
35
+ */
36
+ public set parameters(nodes: ASTNode[]) {
37
+ if (this._expectedParameterCount !== null && this._expectedParameterCount !== nodes.length) {
38
+ throw new Error(`Function ${this._name} expected ${this._expectedParameterCount} parameters, but got ${nodes.length}`);
39
+ }
40
+ this.children = nodes;
41
+ }
42
+
43
+ public get name(): string {
44
+ return this._name;
45
+ }
46
+
47
+ public toString(): string {
48
+ return `Function (${this._name})`;
49
+ }
50
+
51
+ public set distinct(distinct: boolean) {
52
+ if (this._supports_distinct) {
53
+ this._supports_distinct = distinct;
54
+ } else {
55
+ throw new Error(`Function ${this._name} does not support distinct`);
56
+ }
57
+ }
58
+ }
59
+
60
+ export default Function;
@@ -0,0 +1,66 @@
1
+ import Sum from "./sum";
2
+ import Collect from "./collect";
3
+ import Avg from "./avg";
4
+ import Range from "./range";
5
+ import Rand from "./rand";
6
+ import Round from "./round";
7
+ import Split from "./split";
8
+ import Join from "./join";
9
+ import ToJson from "./to_json";
10
+ import Replace from "./replace";
11
+ import Stringify from "./stringify";
12
+ import Size from "./size";
13
+ import Function from "./function";
14
+
15
+ /**
16
+ * Factory for creating function instances by name.
17
+ *
18
+ * Maps function names (case-insensitive) to their corresponding implementation classes.
19
+ * Supports built-in functions like sum, avg, collect, range, split, join, etc.
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * const sumFunc = FunctionFactory.create("sum");
24
+ * const avgFunc = FunctionFactory.create("AVG");
25
+ * ```
26
+ */
27
+ class FunctionFactory {
28
+ /**
29
+ * Creates a function instance by name.
30
+ *
31
+ * @param name - The function name (case-insensitive)
32
+ * @returns A Function instance of the appropriate type
33
+ */
34
+ public static create(name: string): Function {
35
+ switch (name.toLowerCase()) {
36
+ case "sum":
37
+ return new Sum();
38
+ case "collect":
39
+ return new Collect();
40
+ case "avg":
41
+ return new Avg();
42
+ case "range":
43
+ return new Range();
44
+ case "rand":
45
+ return new Rand();
46
+ case "round":
47
+ return new Round();
48
+ case "split":
49
+ return new Split();
50
+ case "join":
51
+ return new Join();
52
+ case "tojson":
53
+ return new ToJson();
54
+ case "replace":
55
+ return new Replace();
56
+ case "stringify":
57
+ return new Stringify();
58
+ case "size":
59
+ return new Size();
60
+ default:
61
+ return new Function(name);
62
+ }
63
+ }
64
+ }
65
+
66
+ export default FunctionFactory;
@@ -0,0 +1,26 @@
1
+ import ASTNode from "../ast_node";
2
+ import Function from "./function";
3
+ import String from "../expressions/string";
4
+
5
+ class Join extends Function {
6
+ constructor() {
7
+ super("join");
8
+ this._expectedParameterCount = 2;
9
+ }
10
+ public set parameters(nodes: ASTNode[]) {
11
+ if(nodes.length === 1) {
12
+ nodes.push(new String(""));
13
+ }
14
+ super.parameters = nodes;
15
+ }
16
+ public value(): any {
17
+ const array = this.getChildren()[0].value();
18
+ const delimiter = this.getChildren()[1].value();
19
+ if (!Array.isArray(array) || typeof delimiter !== "string") {
20
+ throw new Error("Invalid arguments for join function");
21
+ }
22
+ return array.join(delimiter);
23
+ }
24
+ }
25
+
26
+ export default Join;
@@ -0,0 +1,44 @@
1
+ import ASTNode from "../ast_node";
2
+ import Expression from "../expressions/expression";
3
+ import Reference from "../expressions/reference";
4
+ import Where from "../operations/where";
5
+ import ValueHolder from "./value_holder";
6
+
7
+ class PredicateFunction extends ASTNode {
8
+ private _name: string;
9
+ protected _valueHolder: ValueHolder = new ValueHolder();
10
+
11
+ constructor(name: string) {
12
+ super();
13
+ this._name = name;
14
+ }
15
+
16
+ protected get reference(): Reference {
17
+ return this.firstChild() as Reference;
18
+ }
19
+
20
+ protected get array(): ASTNode {
21
+ return this.getChildren()[1].firstChild();
22
+ }
23
+
24
+ protected get _return(): Expression {
25
+ return this.getChildren()[2] as Expression;
26
+ }
27
+
28
+ protected get where(): Where | null {
29
+ if (this.getChildren().length === 4) {
30
+ return this.getChildren()[3] as Where;
31
+ }
32
+ return null;
33
+ }
34
+
35
+ public value(): any {
36
+ throw new Error("Method not implemented.");
37
+ }
38
+
39
+ public toString(): string {
40
+ return `PredicateFunction (${this._name})`;
41
+ }
42
+ }
43
+
44
+ export default PredicateFunction;
@@ -0,0 +1,15 @@
1
+ import PredicateFunction from "./predicate_function";
2
+ import PredicateSum from "./predicate_sum";
3
+
4
+ class PredicateFunctionFactory {
5
+ public static create(name: string): PredicateFunction {
6
+ switch (name.toLowerCase()) {
7
+ case "sum":
8
+ return new PredicateSum();
9
+ default:
10
+ return new PredicateFunction(name);
11
+ }
12
+ }
13
+ }
14
+
15
+ export default PredicateFunctionFactory;
@@ -0,0 +1,29 @@
1
+ import PredicateFunction from "./predicate_function";
2
+
3
+ class PredicateSum extends PredicateFunction {
4
+ constructor() {
5
+ super("sum");
6
+ }
7
+
8
+ public value(): any {
9
+ this.reference.referred = this._valueHolder;
10
+ const array = this.array.value();
11
+ if (array === null || !Array.isArray(array)) {
12
+ throw new Error("Invalid array for sum function");
13
+ }
14
+ let _sum: any | null = null;
15
+ for(let i = 0; i < array.length; i++) {
16
+ this._valueHolder.holder = array[i];
17
+ if (this.where === null || this.where.value()) {
18
+ if (_sum === null) {
19
+ _sum = this._return.value();
20
+ } else {
21
+ _sum += this._return.value();
22
+ }
23
+ }
24
+ }
25
+ return _sum;
26
+ }
27
+ }
28
+
29
+ export default PredicateSum;
@@ -0,0 +1,13 @@
1
+ import Function from "./function";
2
+
3
+ class Rand extends Function {
4
+ constructor() {
5
+ super("rand");
6
+ this._expectedParameterCount = 0;
7
+ }
8
+ public value(): any {
9
+ return Math.random();
10
+ }
11
+ }
12
+
13
+ export default Rand;
@@ -0,0 +1,18 @@
1
+ import Function from "./function";
2
+
3
+ class Range extends Function {
4
+ constructor() {
5
+ super("range");
6
+ this._expectedParameterCount = 2;
7
+ }
8
+ public value(): any {
9
+ const start = this.getChildren()[0].value();
10
+ const end = this.getChildren()[1].value();
11
+ if (typeof start !== "number" || typeof end !== "number") {
12
+ throw new Error("Invalid arguments for range function");
13
+ }
14
+ return Array.from({ length: end - start + 1 }, (_, i) => start + i);
15
+ }
16
+ }
17
+
18
+ export default Range;
@@ -0,0 +1,10 @@
1
+ class ReducerElement {
2
+ public get value(): any {
3
+ throw new Error("Method not implemented.");
4
+ }
5
+ public set value(value: any) {
6
+ throw new Error("Method not implemented.");
7
+ }
8
+ }
9
+
10
+ export default ReducerElement;
@@ -0,0 +1,19 @@
1
+ import Function from "./function";
2
+
3
+ class Replace extends Function {
4
+ constructor() {
5
+ super("replace");
6
+ this._expectedParameterCount = 3;
7
+ }
8
+ public value(): any {
9
+ const str = this.getChildren()[0].value();
10
+ const search = this.getChildren()[1].value();
11
+ const replacement = this.getChildren()[2].value();
12
+ if (typeof str !== "string" || typeof search !== "string" || typeof replacement !== "string") {
13
+ throw new Error("Invalid arguments for replace function");
14
+ }
15
+ return str.replace(new RegExp(search, "g"), replacement);
16
+ }
17
+ }
18
+
19
+ export default Replace;
@@ -0,0 +1,17 @@
1
+ import Function from "./function";
2
+
3
+ class Round extends Function {
4
+ constructor() {
5
+ super("round");
6
+ this._expectedParameterCount = 1;
7
+ }
8
+ public value(): any {
9
+ const value = this.getChildren()[0].value();
10
+ if (typeof value !== "number") {
11
+ throw new Error("Invalid argument for round function");
12
+ }
13
+ return Math.round(value);
14
+ }
15
+ }
16
+
17
+ export default Round;
@@ -0,0 +1,17 @@
1
+ import Function from "./function";
2
+
3
+ class Size extends Function {
4
+ constructor() {
5
+ super("size");
6
+ this._expectedParameterCount = 1;
7
+ }
8
+ public value(): any {
9
+ const arr = this.getChildren()[0].value();
10
+ if (!Array.isArray(arr)) {
11
+ throw new Error("Invalid argument for size function");
12
+ }
13
+ return arr.length;
14
+ }
15
+ }
16
+
17
+ export default Size;
@@ -0,0 +1,26 @@
1
+ import ASTNode from "../ast_node";
2
+ import Function from "./function";
3
+ import String from "../expressions/string";
4
+
5
+ class Split extends Function {
6
+ constructor() {
7
+ super("split");
8
+ this._expectedParameterCount = 2;
9
+ }
10
+ public set parameters(nodes: ASTNode[]) {
11
+ if(nodes.length === 1) {
12
+ nodes.push(new String(""));
13
+ }
14
+ super.parameters = nodes;
15
+ }
16
+ public value(): any {
17
+ const str = this.getChildren()[0].value();
18
+ const delimiter = this.getChildren()[1].value();
19
+ if (typeof str !== "string" || typeof delimiter !== "string") {
20
+ throw new Error("Invalid arguments for split function");
21
+ }
22
+ return str.split(delimiter);
23
+ }
24
+ }
25
+
26
+ export default Split;
@@ -0,0 +1,26 @@
1
+ import ASTNode from "../ast_node";
2
+ import Function from "./function";
3
+ import Number from "../expressions/number";
4
+
5
+ class Stringify extends Function {
6
+ constructor() {
7
+ super("stringify");
8
+ this._expectedParameterCount = 2;
9
+ }
10
+ public set parameters(nodes: ASTNode[]) {
11
+ if(nodes.length === 1) {
12
+ nodes.push(new Number("3")); // Default to 3 if only one parameter is provided
13
+ }
14
+ super.parameters = nodes;
15
+ }
16
+ public value(): any {
17
+ const value = this.getChildren()[0].value();
18
+ const indent = parseInt(this.getChildren()[1].value());
19
+ if (typeof value !== "object") {
20
+ throw new Error("Invalid argument for stringify function");
21
+ }
22
+ return JSON.stringify(value, null, indent);
23
+ }
24
+ }
25
+
26
+ export default Stringify;
@@ -0,0 +1,31 @@
1
+ import AggregateFunction from "./aggregate_function";
2
+ import ReducerElement from "./reducer_element";
3
+
4
+ class SumReducerElement extends ReducerElement {
5
+ private _value: any = null;
6
+ public get value(): any {
7
+ return this._value;
8
+ }
9
+ public set value(value: any) {
10
+ if(this._value !== null) {
11
+ this._value += value;
12
+ } else {
13
+ this._value = value;
14
+ }
15
+ }
16
+ }
17
+
18
+ class Sum extends AggregateFunction {
19
+ constructor() {
20
+ super("sum");
21
+ this._expectedParameterCount = 1;
22
+ }
23
+ public reduce(element: SumReducerElement): void {
24
+ element.value = this.firstChild().value();
25
+ }
26
+ public element(): SumReducerElement {
27
+ return new SumReducerElement();
28
+ }
29
+ }
30
+
31
+ export default Sum;
@@ -0,0 +1,17 @@
1
+ import Function from "./function";
2
+
3
+ class ToJson extends Function {
4
+ constructor() {
5
+ super("tojson");
6
+ this._expectedParameterCount = 1;
7
+ }
8
+ public value(): any {
9
+ const str = this.getChildren()[0].value();
10
+ if (typeof str !== "string") {
11
+ throw new Error("Invalid arguments for tojson function");
12
+ }
13
+ return JSON.parse(str);
14
+ }
15
+ }
16
+
17
+ export default ToJson;
@@ -0,0 +1,13 @@
1
+ import ASTNode from "../ast_node";
2
+
3
+ class ValueHolder extends ASTNode {
4
+ private _holder: any;
5
+ public set holder(value: any) {
6
+ this._holder = value;
7
+ }
8
+ public value(): any {
9
+ return this._holder;
10
+ }
11
+ }
12
+
13
+ export default ValueHolder;
@@ -0,0 +1,26 @@
1
+ import ASTNode from "../ast_node";
2
+ import Else from "./else";
3
+ import When from "./when";
4
+ import Then from "./then";
5
+
6
+ class Case extends ASTNode {
7
+ constructor() {
8
+ super();
9
+ }
10
+
11
+ public value(): any {
12
+ let i = 0;
13
+ let child = this.getChildren()[i];
14
+ while (child instanceof When) {
15
+ const then = (this.getChildren()[i+1] as Then);
16
+ if (child.value()) {
17
+ return then.value();
18
+ }
19
+ i += 2;
20
+ child = this.getChildren()[i];
21
+ }
22
+ return (child as Else).value();
23
+ }
24
+ }
25
+
26
+ export default Case;
@@ -0,0 +1,12 @@
1
+ import ASTNode from "../ast_node";
2
+
3
+ class Else extends ASTNode {
4
+ constructor() {
5
+ super();
6
+ }
7
+ public value(): any {
8
+ return this.getChildren()[0].value();
9
+ }
10
+ }
11
+
12
+ export default Else;
@@ -0,0 +1,9 @@
1
+ import ASTNode from "../ast_node";
2
+
3
+ class End extends ASTNode {
4
+ constructor() {
5
+ super();
6
+ }
7
+ }
8
+
9
+ export default End;
@@ -0,0 +1,12 @@
1
+ import ASTNode from "../ast_node";
2
+
3
+ class Then extends ASTNode {
4
+ constructor() {
5
+ super();
6
+ }
7
+ public value(): any {
8
+ return this.getChildren()[0].value();
9
+ }
10
+ }
11
+
12
+ export default Then;
@@ -0,0 +1,12 @@
1
+ import ASTNode from "../ast_node";
2
+
3
+ class When extends ASTNode {
4
+ constructor() {
5
+ super();
6
+ }
7
+ public value(): boolean {
8
+ return this.getChildren()[0].value();
9
+ }
10
+ }
11
+
12
+ export default When;
@@ -0,0 +1,18 @@
1
+ import Return from "./return";
2
+ import GroupBy from "./group_by";
3
+ import Expression from "../expressions/expression";
4
+
5
+ class AggregatedReturn extends Return {
6
+ private _group_by: GroupBy = new GroupBy(this.children as Expression[]);
7
+ public async run(): Promise<void> {
8
+ await this._group_by.run();
9
+ }
10
+ public get results(): Record<string, any>[] {
11
+ if(this._where !== null) {
12
+ this._group_by.where = this._where;
13
+ }
14
+ return Array.from(this._group_by.generate_results());
15
+ }
16
+ }
17
+
18
+ export default AggregatedReturn;
@@ -0,0 +1,18 @@
1
+ import With from "./return";
2
+ import GroupBy from "./group_by";
3
+ import Expression from "../expressions/expression";
4
+
5
+ class AggregatedWith extends With {
6
+ private _group_by: GroupBy = new GroupBy(this.children as Expression[]);
7
+ public async run(): Promise<void> {
8
+ await this._group_by.run();
9
+ }
10
+ public async finish(): Promise<void> {
11
+ for(const _ of this._group_by.generate_results()) {
12
+ await this.next?.run();
13
+ }
14
+ await super.finish();
15
+ }
16
+ }
17
+
18
+ export default AggregatedWith;