@entity-access/entity-access 1.0.303 → 1.0.305

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 (73) hide show
  1. package/README.md +1 -1
  2. package/dist/compiler/ISqlHelpers.d.ts +2 -0
  3. package/dist/compiler/ISqlHelpers.d.ts.map +1 -1
  4. package/dist/compiler/ISqlHelpers.js +26 -0
  5. package/dist/compiler/ISqlHelpers.js.map +1 -1
  6. package/dist/compiler/QueryCompiler.js +1 -1
  7. package/dist/compiler/QueryCompiler.js.map +1 -1
  8. package/dist/compiler/postgres/PostgreSqlMethodTransformer.d.ts +1 -2
  9. package/dist/compiler/postgres/PostgreSqlMethodTransformer.d.ts.map +1 -1
  10. package/dist/compiler/postgres/PostgreSqlMethodTransformer.js +18 -16
  11. package/dist/compiler/postgres/PostgreSqlMethodTransformer.js.map +1 -1
  12. package/dist/compiler/sql-server/SqlServerSqlMethodTransformer.d.ts +1 -2
  13. package/dist/compiler/sql-server/SqlServerSqlMethodTransformer.d.ts.map +1 -1
  14. package/dist/compiler/sql-server/SqlServerSqlMethodTransformer.js +18 -16
  15. package/dist/compiler/sql-server/SqlServerSqlMethodTransformer.js.map +1 -1
  16. package/dist/drivers/sql-server/SqlServerQueryCompiler.js +1 -1
  17. package/dist/drivers/sql-server/SqlServerQueryCompiler.js.map +1 -1
  18. package/dist/query/ast/DebugStringVisitor.d.ts +2 -1
  19. package/dist/query/ast/DebugStringVisitor.d.ts.map +1 -1
  20. package/dist/query/ast/DebugStringVisitor.js +3 -0
  21. package/dist/query/ast/DebugStringVisitor.js.map +1 -1
  22. package/dist/query/ast/ExpressionToSql.d.ts +2 -1
  23. package/dist/query/ast/ExpressionToSql.d.ts.map +1 -1
  24. package/dist/query/ast/ExpressionToSql.js +20 -6
  25. package/dist/query/ast/ExpressionToSql.js.map +1 -1
  26. package/dist/query/ast/Expressions.d.ts +6 -1
  27. package/dist/query/ast/Expressions.d.ts.map +1 -1
  28. package/dist/query/ast/Expressions.js +6 -0
  29. package/dist/query/ast/Expressions.js.map +1 -1
  30. package/dist/query/ast/IStringTransformer.d.ts +1 -1
  31. package/dist/query/ast/IStringTransformer.d.ts.map +1 -1
  32. package/dist/query/ast/Visitor.d.ts +2 -1
  33. package/dist/query/ast/Visitor.d.ts.map +1 -1
  34. package/dist/query/ast/Visitor.js +5 -0
  35. package/dist/query/ast/Visitor.js.map +1 -1
  36. package/dist/query/parser/ArrowToExpression.d.ts +10 -2
  37. package/dist/query/parser/ArrowToExpression.d.ts.map +1 -1
  38. package/dist/query/parser/ArrowToExpression.js +68 -2
  39. package/dist/query/parser/ArrowToExpression.js.map +1 -1
  40. package/dist/tests/db-tests/tests/select-inverse-one-to-one.js +2 -2
  41. package/dist/tests/db-tests/tests/select-inverse-one-to-one.js.map +1 -1
  42. package/dist/tests/db-tests/tests/select-items-sum.d.ts.map +1 -1
  43. package/dist/tests/db-tests/tests/select-items-sum.js +5 -1
  44. package/dist/tests/db-tests/tests/select-items-sum.js.map +1 -1
  45. package/dist/tests/model/ShoppingContext.d.ts +1 -0
  46. package/dist/tests/model/ShoppingContext.d.ts.map +1 -1
  47. package/dist/tests/model/ShoppingContext.js +4 -0
  48. package/dist/tests/model/ShoppingContext.js.map +1 -1
  49. package/dist/tests/security/events/UserFileEvents.js +1 -1
  50. package/dist/tests/security/events/UserFileEvents.js.map +1 -1
  51. package/dist/tests/security/tests/test-events.js +1 -1
  52. package/dist/tests/security/tests/test-events.js.map +1 -1
  53. package/dist/tsconfig.tsbuildinfo +1 -1
  54. package/dist/workflows/WorkflowStorage.js +3 -3
  55. package/dist/workflows/WorkflowStorage.js.map +1 -1
  56. package/package.json +1 -1
  57. package/src/compiler/ISqlHelpers.ts +33 -0
  58. package/src/compiler/QueryCompiler.ts +1 -1
  59. package/src/compiler/postgres/PostgreSqlMethodTransformer.ts +19 -17
  60. package/src/compiler/sql-server/SqlServerSqlMethodTransformer.ts +19 -17
  61. package/src/drivers/sql-server/SqlServerQueryCompiler.ts +1 -1
  62. package/src/query/ast/DebugStringVisitor.ts +5 -1
  63. package/src/query/ast/ExpressionToSql.ts +38 -20
  64. package/src/query/ast/Expressions.ts +7 -0
  65. package/src/query/ast/IStringTransformer.ts +1 -1
  66. package/src/query/ast/Visitor.ts +6 -1
  67. package/src/query/parser/ArrowToExpression.ts +81 -2
  68. package/src/tests/db-tests/tests/select-inverse-one-to-one.ts +2 -2
  69. package/src/tests/db-tests/tests/select-items-sum.ts +6 -1
  70. package/src/tests/model/ShoppingContext.ts +3 -0
  71. package/src/tests/security/events/UserFileEvents.ts +1 -1
  72. package/src/tests/security/tests/test-events.ts +1 -1
  73. package/src/workflows/WorkflowStorage.ts +3 -3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@entity-access/entity-access",
3
- "version": "1.0.303",
3
+ "version": "1.0.305",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -1,4 +1,7 @@
1
+ import EntityAccessError from "../common/EntityAccessError.js";
2
+ import type { ISqlMethodTransformer } from "../query/ast/IStringTransformer.js";
1
3
  import { ISql } from "../sql/ISql.js";
4
+ import type QueryCompiler from "./QueryCompiler.js";
2
5
 
3
6
  type IFunction = ( ... a: any[]) => any;
4
7
 
@@ -28,3 +31,33 @@ export const flattenHelpers = (f, name, target = {}) => {
28
31
  }
29
32
  return target;
30
33
  };
34
+
35
+ export const flattenMethods = (m: any): ISqlMethodTransformer => {
36
+
37
+ const map = new Map<string, (...a) => any>();
38
+
39
+ const fillMap = (target, root = "Sql") => {
40
+ for (const key in target) {
41
+ if (Object.prototype.hasOwnProperty.call(target, key)) {
42
+ const element = target[key];
43
+ if (typeof element === "object") {
44
+ fillMap(element, root + "." + key);
45
+ continue;
46
+ }
47
+ if (typeof element === "function") {
48
+ map.set(root + "." + key, element);
49
+ }
50
+ }
51
+ }
52
+ };
53
+
54
+ fillMap(m);
55
+
56
+ return (compiler: QueryCompiler, method: string, args: string[]) => {
57
+ const fx = map.get(method);
58
+ if (!fx) {
59
+ throw new EntityAccessError(`Invalid method ${method}`);
60
+ }
61
+ return fx.apply(compiler, args);
62
+ };
63
+ };
@@ -3,7 +3,7 @@ import { ISqlMethodTransformer, IStringTransformer, ITextQuery } from "../query/
3
3
  import { Expression, ParameterExpression, SelectStatement } from "../query/ast/Expressions.js";
4
4
  import SqlLiteral from "../query/ast/SqlLiteral.js";
5
5
  import ArrowToExpression from "../query/parser/ArrowToExpression.js";
6
- import PostgreSqlMethodTransformer from "./postgres/PostgreSqlMethodTransformer.js";
6
+ import { PostgreSqlMethodTransformer } from "./postgres/PostgreSqlMethodTransformer.js";
7
7
  import EntityQuery from "../model/EntityQuery.js";
8
8
  import { NamingConventions } from "./NamingConventions.js";
9
9
  import RawQuery from "./RawQuery.js";
@@ -1,7 +1,7 @@
1
1
  import { joinAny, joinMap, prepareAny } from "../../query/ast/IStringTransformer.js";
2
2
  import { NotSupportedError } from "../../query/parser/NotSupportedError.js";
3
3
  import Sql from "../../sql/Sql.js";
4
- import { ISqlHelpers } from "../ISqlHelpers.js";
4
+ import { ISqlHelpers, flattenMethods } from "../ISqlHelpers.js";
5
5
  import type QueryCompiler from "../QueryCompiler.js";
6
6
 
7
7
  const onlyAlphaNumeric = (x: string) => x.replace(/\W/g, "");
@@ -13,13 +13,13 @@ export const PostgreSqlHelper: ISqlHelpers = {
13
13
  },
14
14
  coll: {
15
15
  sum(a) {
16
- return prepareAny `COALESCE(SUM((${a})), 0.0)`;
16
+ return prepareAny `SUM(${a})`;
17
17
  },
18
18
  count(a) {
19
19
  return prepareAny `COUNT(${a})`;
20
20
  },
21
21
  avg(a) {
22
- return prepareAny `COALESCE(AVG(${a}, 0.0)`;
22
+ return prepareAny `AVG(${a})`;
23
23
  },
24
24
  },
25
25
  math: {
@@ -204,18 +204,20 @@ export const PostgreSqlHelper: ISqlHelpers = {
204
204
  }
205
205
  };
206
206
 
207
- export default function PostgreSqlMethodTransformer(compiler: QueryCompiler, callee: string[], args: any[]): string {
207
+ export const PostgreSqlMethodTransformer = flattenMethods(PostgreSqlHelper);
208
208
 
209
- let start = PostgreSqlHelper;
210
- for (const iterator of callee) {
211
- start = start[iterator];
212
- if (!start) {
213
- return;
214
- }
215
- }
216
- if (!start) {
217
- return;
218
- }
219
- // eslint-disable-next-line @typescript-eslint/ban-types
220
- return (start as unknown as Function).apply(compiler, args);
221
- }
209
+ // export default function PostgreSqlMethodTransformer(compiler: QueryCompiler, method: string, args: any[]): string {
210
+
211
+ // let start = PostgreSqlHelper;
212
+ // for (const iterator of callee) {
213
+ // start = start[iterator];
214
+ // if (!start) {
215
+ // return;
216
+ // }
217
+ // }
218
+ // if (!start) {
219
+ // return;
220
+ // }
221
+ // // eslint-disable-next-line @typescript-eslint/ban-types
222
+ // return (start as unknown as Function).apply(compiler, args);
223
+ // }
@@ -1,7 +1,7 @@
1
1
 
2
2
  import { joinAny, joinMap, prepareAny } from "../../query/ast/IStringTransformer.js";
3
3
  import Sql from "../../sql/Sql.js";
4
- import { ISqlHelpers } from "../ISqlHelpers.js";
4
+ import { ISqlHelpers, flattenMethods } from "../ISqlHelpers.js";
5
5
  import type QueryCompiler from "../QueryCompiler.js";
6
6
 
7
7
  export const SqlServerSqlHelper: ISqlHelpers = {
@@ -11,13 +11,13 @@ export const SqlServerSqlHelper: ISqlHelpers = {
11
11
  },
12
12
  coll: {
13
13
  sum(a) {
14
- return prepareAny `COALESCE(SUM((${a})), 0.0)`;
14
+ return prepareAny `SUM(${a})`;
15
15
  },
16
16
  count(a) {
17
17
  return prepareAny `COUNT(${a})`;
18
18
  },
19
19
  avg(a) {
20
- return prepareAny `COALESCE(AVG((${a}), 0.0)`;
20
+ return prepareAny `AVG(${a})`;
21
21
  },
22
22
  },
23
23
  cast: {
@@ -207,18 +207,20 @@ export const SqlServerSqlHelper: ISqlHelpers = {
207
207
  }
208
208
  };
209
209
 
210
- export default function SqlServerSqlMethodTransformer(compiler: QueryCompiler, callee: string[], args: any[]): string {
210
+ export const SqlServerSqlMethodTransformer = flattenMethods(SqlServerSqlHelper);
211
211
 
212
- let start = SqlServerSqlHelper;
213
- for (const iterator of callee) {
214
- start = start[iterator];
215
- if (!start) {
216
- return;
217
- }
218
- }
219
- if (!start) {
220
- return;
221
- }
222
- // eslint-disable-next-line @typescript-eslint/ban-types
223
- return (start as unknown as Function).apply(compiler, args);
224
- }
212
+ // export default function SqlServerSqlMethodTransformer(compiler: QueryCompiler, method: string, args: any[]): string {
213
+
214
+ // let start = SqlServerSqlHelper;
215
+ // for (const iterator of callee) {
216
+ // start = start[iterator];
217
+ // if (!start) {
218
+ // return;
219
+ // }
220
+ // }
221
+ // if (!start) {
222
+ // return;
223
+ // }
224
+ // // eslint-disable-next-line @typescript-eslint/ban-types
225
+ // return (start as unknown as Function).apply(compiler, args);
226
+ // }
@@ -1,6 +1,6 @@
1
1
  import { NamingConventions } from "../../compiler/NamingConventions.js";
2
2
  import QueryCompiler from "../../compiler/QueryCompiler.js";
3
- import SqlServerSqlMethodTransformer from "../../compiler/sql-server/SqlServerSqlMethodTransformer.js";
3
+ import { SqlServerSqlMethodTransformer } from "../../compiler/sql-server/SqlServerSqlMethodTransformer.js";
4
4
  import ArrowToExpression from "../../query/parser/ArrowToExpression.js";
5
5
  import ExpressionToSqlServer from "./ExpressionToSqlServer.js";
6
6
  import { SqlServerLiteral } from "./SqlServerLiteral.js";
@@ -1,4 +1,4 @@
1
- import { ArrayExpression, ArrowFunctionExpression, BigIntLiteral, BinaryExpression, BooleanLiteral, CallExpression, CoalesceExpression, ConditionalExpression, Constant, DeleteStatement, ExistsExpression, Expression, ExpressionAs, Identifier, InsertStatement, JoinExpression, MemberExpression, NewObjectExpression, NotExits, NullExpression, NumberLiteral, OrderByExpression, ParameterExpression, ReturnUpdated, SelectStatement, StringLiteral, TableLiteral, TemplateElement, TemplateLiteral, UnionAllStatement, UpdateStatement, ValuesStatement } from "./Expressions.js";
1
+ import { ArrayExpression, ArrowFunctionExpression, BigIntLiteral, BinaryExpression, BooleanLiteral, BracketExpression, CallExpression, CoalesceExpression, ConditionalExpression, Constant, DeleteStatement, ExistsExpression, Expression, ExpressionAs, Identifier, InsertStatement, JoinExpression, MemberExpression, NewObjectExpression, NotExits, NullExpression, NumberLiteral, OrderByExpression, ParameterExpression, ReturnUpdated, SelectStatement, StringLiteral, TableLiteral, TemplateElement, TemplateLiteral, UnionAllStatement, UpdateStatement, ValuesStatement } from "./Expressions.js";
2
2
  import Visitor from "./Visitor.js";
3
3
 
4
4
  const isBinary = (type) => /^(BinaryExpression|CoalesceExpression)$/.test(type);
@@ -58,6 +58,10 @@ export default class DebugStringVisitor extends Visitor<string> {
58
58
  return `"Constant:${e.value}"`;
59
59
  }
60
60
 
61
+ visitBracketExpression(e: BracketExpression): string {
62
+ return `(${this.visit(e.target)})`;
63
+ }
64
+
61
65
  visitExpressionAs(e: ExpressionAs): string {
62
66
  return `${this.visit(e.expression)} as ${this.visit(e.alias)}`;
63
67
  }
@@ -4,7 +4,7 @@ import EntityType, { IEntityProperty } from "../../entity-query/EntityType.js";
4
4
  import EntityQuery from "../../model/EntityQuery.js";
5
5
  import { FilteredExpression, filteredSymbol } from "../../model/events/FilteredExpression.js";
6
6
  import { NotSupportedError } from "../parser/NotSupportedError.js";
7
- import { ArrowFunctionExpression, BigIntLiteral, BinaryExpression, BooleanLiteral, CallExpression, CoalesceExpression, ConditionalExpression, Constant, DeleteStatement, ExistsExpression, Expression, ExpressionAs, ExpressionType, Identifier, InsertStatement, JoinExpression, MemberExpression, UpsertStatement, NewObjectExpression, NotExits, NullExpression, NumberLiteral, OrderByExpression, ParameterExpression, ReturnUpdated, SelectStatement, StringLiteral, TableLiteral, TemplateLiteral, UnionAllStatement, UpdateStatement, ValuesStatement, NotExpression, ArrayExpression } from "./Expressions.js";
7
+ import { ArrowFunctionExpression, BigIntLiteral, BinaryExpression, BooleanLiteral, CallExpression, CoalesceExpression, ConditionalExpression, Constant, DeleteStatement, ExistsExpression, Expression, ExpressionAs, ExpressionType, Identifier, InsertStatement, JoinExpression, MemberExpression, UpsertStatement, NewObjectExpression, NotExits, NullExpression, NumberLiteral, OrderByExpression, ParameterExpression, ReturnUpdated, SelectStatement, StringLiteral, TableLiteral, TemplateLiteral, UnionAllStatement, UpdateStatement, ValuesStatement, NotExpression, ArrayExpression, BracketExpression } from "./Expressions.js";
8
8
  import { ITextQuery, QueryParameter, joinMap, prepare, prepareJoin } from "./IStringTransformer.js";
9
9
  import ParameterScope from "./ParameterScope.js";
10
10
  import Visitor from "./Visitor.js";
@@ -12,7 +12,7 @@ import Visitor from "./Visitor.js";
12
12
  interface IPropertyChain {
13
13
  identifier?: Identifier,
14
14
  parameter?: ParameterExpression,
15
- chain: { member: string, args?: Expression[] }[]
15
+ chain: { member: string, args?: Expression[], isCollectionMethod?: boolean }[]
16
16
  }
17
17
 
18
18
  interface IPropertyMethods {
@@ -163,6 +163,10 @@ export default class ExpressionToSql extends Visitor<ITextQuery> {
163
163
  return prepare `CONCAT(${args})`;
164
164
  }
165
165
 
166
+ visitBracketExpression(e: BracketExpression): ITextQuery {
167
+ return prepare `(${this.visit(e.target)})`;
168
+ }
169
+
166
170
  visitCallExpression(e: CallExpression): ITextQuery {
167
171
  // let us check if we are using any of array extension methods...
168
172
  // .some alias .any
@@ -209,33 +213,45 @@ export default class ExpressionToSql extends Visitor<ITextQuery> {
209
213
  if (/^(some|any)$/.test(lastMethod.member)) {
210
214
  return this.visit(exists);
211
215
  }
212
- if (/^(map|select)$/.test(lastMethod.member)) {
216
+ if (/^(map|select)$/.test(lastMethod.member) || lastMethod.isCollectionMethod ) {
213
217
  const select = this.expandCollection(relation, e, parameter, targetType);
214
218
  const p1 = body.params[0];
215
219
  this.scope.alias(select.sourceParameter, p1, select);
216
220
 
217
221
  let where = select.where;
218
222
 
219
- while(methods.length) {
220
- const last = methods.pop();
221
- if (last.member !== "filter") {
222
- throw new EntityAccessError(`Invalid method ${last.member}`);
223
- }
224
- const filterArrow = last.args[0] as ArrowFunctionExpression;
225
- this.scope.alias(select.sourceParameter, filterArrow.params[0], select);
226
- if (where) {
227
- where = Expression.logicalAnd(where, filterArrow.body);
228
- } else {
229
- where = filterArrow.body;
230
- }
223
+ while(methods.length) {
224
+ const last = methods.pop();
225
+ if (last.member !== "filter") {
226
+ throw new EntityAccessError(`Invalid method ${last.member}`);
231
227
  }
228
+ const filterArrow = last.args[0] as ArrowFunctionExpression;
229
+ this.scope.alias(select.sourceParameter, filterArrow.params[0], select);
230
+ if (where) {
231
+ where = Expression.logicalAnd(where, filterArrow.body);
232
+ } else {
233
+ where = filterArrow.body;
234
+ }
235
+ }
232
236
 
233
237
  if (body.body.type === "NewObjectExpression") {
234
238
  const noe = body.body as NewObjectExpression;
235
239
  const fields = noe.properties as ExpressionAs[];
236
240
  return this.visit({ ... select, where, fields } as SelectStatement);
237
241
  }
238
- return this.visit({ ... select, where, fields: [body.body] } as SelectStatement);
242
+
243
+ if (lastMethod.isCollectionMethod) {
244
+ return this.visit({ ... select, where, fields: [
245
+ CallExpression.create({
246
+ callee: Expression.identifier("Sql.coll." + lastMethod.member),
247
+ arguments: [body.body]
248
+ })
249
+ ] } as SelectStatement);
250
+ }
251
+
252
+ return this.visit({ ... select, where, fields: [
253
+ body.body
254
+ ] } as SelectStatement);
239
255
  }
240
256
  }
241
257
 
@@ -243,9 +259,11 @@ export default class ExpressionToSql extends Visitor<ITextQuery> {
243
259
  }
244
260
  }
245
261
 
246
- if (identifier?.value === "Sql") {
262
+ const identifierValue = identifier?.value;
263
+
264
+ if (identifierValue?.startsWith("Sql")) {
247
265
  const argList = e.arguments?.map((x) => this.visit(x)) ?? [];
248
- const transformedCallee = this.compiler.sqlMethodTransformer(this.compiler, chain.map((x) => x.member), argList.map((al) => al.flat(2)) as any[]);
266
+ const transformedCallee = this.compiler.sqlMethodTransformer(this.compiler, identifierValue, argList.map((al) => al.flat(2)) as any[]);
249
267
  if (transformedCallee) {
250
268
  return prepare `${transformedCallee}`;
251
269
  }
@@ -854,7 +872,7 @@ export default class ExpressionToSql extends Visitor<ITextQuery> {
854
872
  x = resolved;
855
873
  }
856
874
 
857
- const chain = [] as { member: string, args?: Expression[]}[];
875
+ const chain = [] as { member: string, args?: Expression[], isCollectionMethod?: boolean}[];
858
876
  while (x) {
859
877
  if (x.type === "ParameterExpression") {
860
878
  return { parameter: x as ParameterExpression, chain };
@@ -865,7 +883,7 @@ export default class ExpressionToSql extends Visitor<ITextQuery> {
865
883
  if (x.type === "MemberExpression") {
866
884
  const me = x as MemberExpression;
867
885
  x = me.target;
868
- chain.unshift({ member: (me.property as Identifier).value });
886
+ chain.unshift({ member: (me.property as Identifier).value , isCollectionMethod: me.isCollectionMethod });
869
887
  continue;
870
888
  }
871
889
  if (x.type === "CallExpression") {
@@ -214,6 +214,11 @@ export class CallExpression extends Expression {
214
214
  arguments: Expression[];
215
215
  }
216
216
 
217
+ export class BracketExpression extends Expression {
218
+ readonly type = "BracketExpression";
219
+ target: Expression;
220
+ }
221
+
217
222
  export class ParameterExpression extends Expression {
218
223
  readonly type = "ParameterExpression";
219
224
  name: string;
@@ -239,6 +244,7 @@ export class MemberExpression extends Expression {
239
244
  target: Expression;
240
245
  property: Expression;
241
246
  computed: boolean;
247
+ isCollectionMethod: boolean;
242
248
  }
243
249
 
244
250
  export class ArrowFunctionExpression extends Expression {
@@ -477,5 +483,6 @@ export type ExpressionType =
477
483
  NotExits |
478
484
  UnionAllStatement |
479
485
  NotExpression |
486
+ BracketExpression |
480
487
  TemplateElement
481
488
  ;
@@ -5,7 +5,7 @@ export type ITextQuery = ITextQueryFragment[];
5
5
 
6
6
  export type IStringTransformer = (s: string) => string;
7
7
 
8
- export type ISqlMethodTransformer = (compiler: QueryCompiler, callee: string[], args: string[]) => string;
8
+ export type ISqlMethodTransformer = (compiler: QueryCompiler, method: string, args: string[]) => string;
9
9
 
10
10
  export class QueryParameter {
11
11
 
@@ -1,5 +1,5 @@
1
1
  import { NotSupportedError } from "../parser/NotSupportedError.js";
2
- import { ArrayExpression, ArrowFunctionExpression, BigIntLiteral, BinaryExpression, BooleanLiteral, CallExpression, CoalesceExpression, ConditionalExpression, Constant, DeleteStatement, ExistsExpression, Expression, ExpressionAs, ExpressionType, Identifier, InsertStatement, JoinExpression, MemberExpression, UpsertStatement, NewObjectExpression, NotExits, NullExpression, NumberLiteral, OrderByExpression, ParameterExpression, ReturnUpdated, SelectStatement, StringLiteral, TableLiteral, TemplateElement, TemplateLiteral, UnionAllStatement, UpdateStatement, ValuesStatement, NotExpression } from "./Expressions.js";
2
+ import { ArrayExpression, ArrowFunctionExpression, BigIntLiteral, BinaryExpression, BooleanLiteral, CallExpression, CoalesceExpression, ConditionalExpression, Constant, DeleteStatement, ExistsExpression, Expression, ExpressionAs, ExpressionType, Identifier, InsertStatement, JoinExpression, MemberExpression, UpsertStatement, NewObjectExpression, NotExits, NullExpression, NumberLiteral, OrderByExpression, ParameterExpression, ReturnUpdated, SelectStatement, StringLiteral, TableLiteral, TemplateElement, TemplateLiteral, UnionAllStatement, UpdateStatement, ValuesStatement, NotExpression, BracketExpression } from "./Expressions.js";
3
3
 
4
4
 
5
5
  export default abstract class Visitor<T = any> {
@@ -75,10 +75,15 @@ export default abstract class Visitor<T = any> {
75
75
  return this.visitUpsertStatement(e);
76
76
  case "NotExpression":
77
77
  return this.visitNotExpression(e);
78
+ case "BracketExpression":
79
+ return this.visitBracketExpression(e);
78
80
  }
79
81
  const c: never = e;
80
82
  throw new Error(`${e1.type} Not implemented`);
81
83
  }
84
+ visitBracketExpression(e: BracketExpression): T {
85
+ throw new Error("Method not implemented.");
86
+ }
82
87
  visitNotExpression(e: NotExpression): T {
83
88
  throw new Error("Method not implemented.");
84
89
  }
@@ -1,5 +1,5 @@
1
1
  import { parseExpression } from "@babel/parser";
2
- import { ArrowFunctionExpression, BinaryExpression, BooleanLiteral, CallExpression, CoalesceExpression, ConditionalExpression, Constant, Expression, ExpressionAs, Identifier, MemberExpression, NewObjectExpression, NotExpression, NullExpression, NumberLiteral, ParameterExpression, StringLiteral, TemplateLiteral } from "../ast/Expressions.js";
2
+ import { ArrowFunctionExpression, BinaryExpression, BooleanLiteral, BracketExpression, CallExpression, CoalesceExpression, ConditionalExpression, Constant, Expression, ExpressionAs, Identifier, MemberExpression, NewObjectExpression, NotExpression, NullExpression, NumberLiteral, ParameterExpression, StringLiteral, TemplateLiteral } from "../ast/Expressions.js";
3
3
  import { BabelVisitor } from "./BabelVisitor.js";
4
4
  import * as bpe from "@babel/types";
5
5
  import Restructure from "./Restructure.js";
@@ -217,10 +217,89 @@ export default class ArrowToExpression extends BabelVisitor<Expression> {
217
217
 
218
218
  // change Sql.coll. with arrow functions to move it inside
219
219
 
220
- return CallExpression.create({
220
+ const ce = CallExpression.create({
221
221
  callee: callee ? this.visit(callee) : void 0,
222
222
  arguments: args ? args.map((x) => this.visit(x)) : []
223
223
  });
224
+
225
+ // for Sql.Coll. , change it to coalesce
226
+ // and move Sql.Coll. inside the first map..
227
+ return this.reAssignCollectionMethods(ce);
228
+ }
229
+
230
+ /**
231
+ * We need to change Sql.coll.sum(p.orders.map((o) => o.total)
232
+ * to
233
+ * p.orders.sum((o) => o.total) ?? 0
234
+ * @param ce
235
+ * @returns
236
+ */
237
+ reAssignCollectionMethods(ce: CallExpression) {
238
+
239
+ if (ce.callee.type !== "MemberExpression") {
240
+ return ce;
241
+ }
242
+
243
+ let callee = ce.callee as MemberExpression;
244
+ const name = [];
245
+ while(callee) {
246
+ name.splice(0, 0, (callee.property as Identifier)?.value);
247
+ const target = callee.target;
248
+ switch(target.type) {
249
+ case "MemberExpression":
250
+ callee = target as MemberExpression;
251
+ continue;
252
+ case "Identifier":
253
+ name.splice(0, 0, (target as Identifier).value);
254
+ callee = null;
255
+ break;
256
+ default:
257
+ return ce;
258
+ }
259
+ }
260
+
261
+ if (name[0] !== "Sql") {
262
+ return ce;
263
+ }
264
+
265
+ const method = name[2];
266
+
267
+ const reWrittenCe = CallExpression.create({
268
+ callee: Expression.identifier(name.join(".")),
269
+ arguments: ce.arguments
270
+ });
271
+
272
+
273
+ if (name[1] !== "coll") {
274
+ // rewrite...
275
+ return reWrittenCe;
276
+ }
277
+
278
+ const firstArg = ce.arguments[0] as CallExpression;
279
+ if (firstArg?.type !== "CallExpression") {
280
+ return reWrittenCe;
281
+ }
282
+
283
+ const mapCallee = firstArg.callee as MemberExpression;
284
+ if (mapCallee?.type !== "MemberExpression") {
285
+ return reWrittenCe;
286
+ }
287
+
288
+ const left = CallExpression.create({
289
+ callee: MemberExpression.create({
290
+ target: mapCallee.target,
291
+ property: Expression.identifier(method),
292
+ isCollectionMethod: true
293
+ }),
294
+ arguments: firstArg.arguments
295
+ });
296
+
297
+ // move it inside...
298
+ const rewritten = CoalesceExpression.create({
299
+ left: BracketExpression.create({ target: left }) ,
300
+ right: NumberLiteral.zero
301
+ });
302
+ return rewritten;
224
303
  }
225
304
 
226
305
  visitIdentifier({ name: value }: bpe.Identifier): Expression {
@@ -19,14 +19,14 @@ export default async function(this: TestConfig) {
19
19
 
20
20
  // include inverse...
21
21
  let all = await context.users.all()
22
- .where({} , (p) => (x) => x.profile.photos.some((a) => true) || x.profile.photos.some((a) => true))
22
+ .where({} , (p) => (x) => x.profile.photos.some((a) => a.photoID > 0) || x.profile.photos.some((a) => a.photoID > 0))
23
23
  .include((x) => x.profile.photos)
24
24
  .first();
25
25
 
26
26
  assert.equal(null, all);
27
27
 
28
28
  all = await context.users.all()
29
- .where({} , (p) => (x) => x.files.some((a) => true))
29
+ .where({} , (p) => (x) => x.files.some((a) => a.fileID > 0))
30
30
  .include((x) => x.files)
31
31
  .first();
32
32
 
@@ -31,12 +31,17 @@ export default async function(this: TestConfig) {
31
31
 
32
32
  // assert.notEqual(null, report);
33
33
 
34
+ await context.orders.asQuery()
35
+ .update(void 0, (p) => (x) => ({
36
+ total: Sql.coll.sum(x.orderItems.map((o) => o.amount ))
37
+ }));
38
+
34
39
  report = await context.users.all()
35
40
  .where({}, (p) => (x) => x.orders.some((oi) => oi.customerID > 0))
36
41
  .map({}, (p) => (x) => ({
37
42
  total: Sql.coll.sum(x.orders
38
43
  .filter((o) => o.status === "pending")
39
- .map((o) => Sql.coll.sum(o.orderItems.map((oi) => oi.amount))))
44
+ .map((o) => o.total))
40
45
  })
41
46
  )
42
47
  .trace(console.log)
@@ -345,6 +345,9 @@ export class Order {
345
345
  @Column({ dataType: "Char", length: 20, default: () => "pending"})
346
346
  public status: string;
347
347
 
348
+ @Column({ dataType: "Decimal", default: () => 0})
349
+ public total: number;
350
+
348
351
  public orderItems: OrderItem[];
349
352
 
350
353
  public customer: User;
@@ -5,7 +5,7 @@ import { UserFile } from "../../model/UseFile.js";
5
5
  export class UserFileEvents extends EntityEvents<UserFile> {
6
6
 
7
7
  filter(query: IEntityQuery<UserFile>): IEntityQuery<UserFile> {
8
- return query.where({}, (p) => (x) => x.photoUsers.some((p1) => p1.orders.some((o1) => true)));
8
+ return query.where({}, (p) => (x) => x.photoUsers.some((p1) => p1.orders.some((o1) => true === true)));
9
9
  }
10
10
 
11
11
  }
@@ -48,7 +48,7 @@ export default async function (this: TestConfig) {
48
48
  await context.saveChanges();
49
49
  assert.equal(true, p.afterInsertInvoked);
50
50
 
51
- await context.userFiles.filtered("read").where({}, (_) => (x) => x.photoUsers.some((p1) => true))
51
+ await context.userFiles.filtered("read").where({}, (_) => (x) => x.photoUsers.some((p1) => true === true))
52
52
  .include((x) => x.user.profile).toArray();
53
53
 
54
54
 
@@ -274,9 +274,9 @@ export default class WorkflowStorage {
274
274
  Expression.assign(
275
275
  Expression.identifier(lockTTLField),
276
276
  CallExpression.create({
277
- callee: Expression.member(Expression.member(Expression.identifier("Sql"), "date"), "addMinutes"),
277
+ callee: Expression.identifier("Sql.date.addMinutes"),
278
278
  arguments: [CallExpression.create({
279
- callee: Expression.member(Expression.member(Expression.identifier("Sql"), "date"), "now")
279
+ callee: Expression.identifier("Sql.date.now")
280
280
  }),
281
281
  NumberLiteral.create({ value: 15 })
282
282
  ]
@@ -294,7 +294,7 @@ export default class WorkflowStorage {
294
294
  Expression.lessOrEqual(
295
295
  Expression.identifier(lockTTLField),
296
296
  CallExpression.create({
297
- callee: Expression.member(Expression.member(Expression.identifier("Sql"), "date"), "now")
297
+ callee: Expression.identifier("Sql.date.now")
298
298
  })
299
299
  )
300
300
  ))