@entity-access/entity-access 1.0.1

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 (70) hide show
  1. package/.eslintrc.cjs +234 -0
  2. package/.github/workflows/node.yml +44 -0
  3. package/.github/workflows/npm-publish.yml +33 -0
  4. package/.vscode/launch.json +20 -0
  5. package/.vscode/settings.json +39 -0
  6. package/LICENSE +201 -0
  7. package/README.md +247 -0
  8. package/package.json +39 -0
  9. package/src/TestRunner.ts +2 -0
  10. package/src/common/cache/InstanceCache.ts +14 -0
  11. package/src/common/cache/TimedCache.ts +74 -0
  12. package/src/common/symbols/symbols.ts +2 -0
  13. package/src/common/usingAsync.ts +24 -0
  14. package/src/compiler/ISqlHelpers.ts +30 -0
  15. package/src/compiler/QueryCompiler.ts +88 -0
  16. package/src/compiler/postgres/PostgreSqlMethodTransformer.ts +83 -0
  17. package/src/compiler/sql-server/SqlServerSqlMethodTransformer.ts +83 -0
  18. package/src/decorators/Column.ts +46 -0
  19. package/src/decorators/ForeignKey.ts +42 -0
  20. package/src/decorators/IClassOf.ts +1 -0
  21. package/src/decorators/IColumn.ts +70 -0
  22. package/src/decorators/ISqlType.ts +70 -0
  23. package/src/decorators/SchemaRegistry.ts +19 -0
  24. package/src/decorators/Table.ts +18 -0
  25. package/src/decorators/parser/MemberParser.ts +8 -0
  26. package/src/drivers/base/BaseDriver.ts +134 -0
  27. package/src/drivers/postgres/PostgreSqlDriver.ts +178 -0
  28. package/src/drivers/sql-server/ExpressionToSqlServer.ts +78 -0
  29. package/src/drivers/sql-server/SqlServerDriver.ts +215 -0
  30. package/src/drivers/sql-server/SqlServerLiteral.ts +12 -0
  31. package/src/drivers/sql-server/SqlServerQueryCompiler.ts +25 -0
  32. package/src/entity-query/EntityType.ts +116 -0
  33. package/src/migrations/Migrations.ts +17 -0
  34. package/src/migrations/postgres/PostgresAutomaticMigrations.ts +97 -0
  35. package/src/migrations/postgres/PostgresMigrations.ts +56 -0
  36. package/src/migrations/sql-server/SqlServerAutomaticMigrations.ts +102 -0
  37. package/src/migrations/sql-server/SqlServerMigrations.ts +60 -0
  38. package/src/model/ChangeEntry.ts +154 -0
  39. package/src/model/ChangeSet.ts +88 -0
  40. package/src/model/EntityContext.ts +48 -0
  41. package/src/model/EntityModel.ts +27 -0
  42. package/src/model/EntityQuery.ts +152 -0
  43. package/src/model/EntitySchema.ts +21 -0
  44. package/src/model/EntitySource.ts +98 -0
  45. package/src/model/IFilterWithParameter.ts +38 -0
  46. package/src/model/IdentityService.ts +23 -0
  47. package/src/model/SourceExpression.ts +137 -0
  48. package/src/query/Query.ts +158 -0
  49. package/src/query/ast/ExpressionToSql.ts +348 -0
  50. package/src/query/ast/Expressions.ts +294 -0
  51. package/src/query/ast/IStringTransformer.ts +74 -0
  52. package/src/query/ast/SqlLiteral.ts +25 -0
  53. package/src/query/ast/Visitor.ts +159 -0
  54. package/src/query/parser/ArrowToExpression.ts +160 -0
  55. package/src/query/parser/BabelVisitor.ts +86 -0
  56. package/src/sql/ISql.ts +31 -0
  57. package/src/sql/Sql.ts +4 -0
  58. package/src/tests/TestConfig.ts +6 -0
  59. package/src/tests/db-tests/tests/select-items.ts +37 -0
  60. package/src/tests/db-tests/tests/update-items.ts +17 -0
  61. package/src/tests/drivers/postgres/connection-test.ts +29 -0
  62. package/src/tests/drivers/sql-server/sql-server-test.ts +9 -0
  63. package/src/tests/expressions/left-joins/child-joins.ts +71 -0
  64. package/src/tests/expressions/simple/parse-arrow.ts +46 -0
  65. package/src/tests/expressions/trimInternal.ts +23 -0
  66. package/src/tests/model/ShoppingContext.ts +203 -0
  67. package/src/tests/model/createContext.ts +294 -0
  68. package/src/tests/query/combine.ts +28 -0
  69. package/test.js +107 -0
  70. package/tsconfig.json +22 -0
@@ -0,0 +1,294 @@
1
+ import { IColumn } from "../../decorators/IColumn.js";
2
+ import { IClassOf } from "../../decorators/IClassOf.js";
3
+ import { ITextOrFunctionArray } from "./IStringTransformer.js";
4
+ import type EntityType from "../../entity-query/EntityType.js";
5
+
6
+ const flattenedSelf = Symbol("flattenedSelf");
7
+
8
+ /**
9
+ * The reason we are using our own Expression type is to keep
10
+ * our expressions small and independent of JavaScript ESTree style.
11
+ *
12
+ * Reason is simple, our visitor pattern can be small and can stay
13
+ * independent of any other extra expression types.
14
+ *
15
+ * We will cache our expressions, to avoid parsing them multiple times.
16
+ * Our expressions do not need to store exact line numbers, comments,
17
+ * extra annotations. We can add some shortcut optimizations which might
18
+ * not be possible with outer libraries unless they support it.
19
+ *
20
+ * In future, we might make our own expression parser as we only need
21
+ * handful of features to keep it small and faster. Or we can swap some
22
+ * other JavaScript parser without affecting our code generation process.
23
+ */
24
+
25
+ export abstract class Expression {
26
+
27
+ static create<T extends Expression>(this: IClassOf<T>, p: Partial<Omit<T, "type">>) {
28
+ (p as any).type = (this as any).name;
29
+ Object.setPrototypeOf(p, this.prototype);
30
+ return p as T;
31
+ }
32
+
33
+ static clone<T extends Expression>(expression: T): T {
34
+ const r = {} as any;
35
+ Object.setPrototypeOf(r, Object.getPrototypeOf(expression));
36
+ for (const key in expression) {
37
+ if (Object.prototype.hasOwnProperty.call(expression, key)) {
38
+ const element = expression[key];
39
+ if(Array.isArray(element)) {
40
+ r[key] = element.map((x) => this.clone(x));
41
+ } else {
42
+ r[key] = element;
43
+ }
44
+ }
45
+ }
46
+ return r as T;
47
+ }
48
+
49
+ private static shallowCopy(expression, constants: Expression[]) {
50
+ const copy = {} as any;
51
+ for (const key in expression) {
52
+ if (Object.prototype.hasOwnProperty.call(expression, key)) {
53
+ const element = expression[key];
54
+ if (key === "type" || key === "is") {
55
+ continue;
56
+ }
57
+ if (element instanceof Constant) {
58
+ constants.push(element);
59
+ }
60
+ copy[key] = element;
61
+ }
62
+ }
63
+ Object.setPrototypeOf(copy, Object.getPrototypeOf(expression));
64
+ return copy;
65
+ }
66
+
67
+ readonly type: never | string;
68
+
69
+ }
70
+
71
+ export class PlaceholderExpression extends Expression {
72
+ readonly type = "PlaceholderExpression";
73
+ expression: () => ITextOrFunctionArray;
74
+ }
75
+
76
+ export class BinaryExpression extends Expression {
77
+
78
+ readonly type = "BinaryExpression";
79
+
80
+ left: Expression;
81
+ right: Expression;
82
+ operator: string;
83
+ }
84
+
85
+ export class CoalesceExpression extends Expression {
86
+ readonly type = "CoalesceExpression";
87
+ left: Expression;
88
+ right: Expression;
89
+ }
90
+
91
+ export class ValuesStatement extends Expression {
92
+ readonly type = "ValuesStatement";
93
+ as: QuotedLiteral;
94
+ fields: QuotedLiteral[];
95
+ values: Expression[][];
96
+ }
97
+
98
+ export class OrderByExpression extends Expression {
99
+ readonly type = "OrderByExpression";
100
+ target: Expression;
101
+ descending: boolean;
102
+ }
103
+
104
+ export class ExistsExpression extends Expression {
105
+ readonly type = "ExistsExpression";
106
+ target: Expression;
107
+ }
108
+
109
+ export class CallExpression extends Expression {
110
+ readonly type = "CallExpression";
111
+ callee: Expression;
112
+ arguments: Expression[];
113
+ }
114
+
115
+ export class MemberExpression extends Expression {
116
+ readonly type = "MemberExpression";
117
+ target: Expression;
118
+ property: Expression;
119
+ computed: boolean;
120
+ }
121
+
122
+ export class ArrowFunctionExpression extends Expression {
123
+ readonly type = "ArrowFunctionExpression";
124
+ params: Expression[];
125
+ body: Expression;
126
+ }
127
+
128
+ export type TableSource = SelectStatement | QuotedLiteral | ExpressionAs | TableLiteral;
129
+
130
+ export class SelectStatement extends Expression {
131
+
132
+ readonly type = "SelectStatement";
133
+
134
+ source: TableSource;
135
+
136
+ as: QuotedLiteral;
137
+
138
+ fields: (Expression | QuotedLiteral | ExpressionAs)[];
139
+
140
+ where: Expression;
141
+
142
+ orderBy: OrderByExpression[];
143
+
144
+ joins: JoinExpression[];
145
+
146
+ limit: number;
147
+
148
+ offset: number;
149
+
150
+ }
151
+
152
+ export class JoinExpression extends Expression {
153
+ readonly type = "JoinExpression";
154
+ joinType: "LEFT" | "INNER";
155
+ source: SelectStatement | QuotedLiteral | ExpressionAs;
156
+ as: QuotedLiteral;
157
+ where: Expression;
158
+ model: EntityType;
159
+ }
160
+
161
+ export class ReturnUpdated extends Expression {
162
+ readonly type = "ReturnUpdated";
163
+
164
+ fields: QuotedLiteral[];
165
+
166
+ changes: "INSERTED" | "DELETED" | "UPDATED";
167
+ }
168
+
169
+ export class Constant extends Expression {
170
+ readonly type = "Constant";
171
+ public value: any;
172
+ }
173
+
174
+ export class Identifier extends Expression {
175
+ readonly type = "Identifier";
176
+ public value: string;
177
+ }
178
+
179
+ export class NullExpression extends Expression {
180
+ readonly type = "NullExpression";
181
+ }
182
+
183
+ export class StringLiteral extends Expression {
184
+ readonly type = "StringLiteral";
185
+ public value: string;
186
+ }
187
+
188
+ export class BooleanLiteral extends Expression {
189
+ readonly type = "BooleanLiteral";
190
+ public value: boolean;
191
+ }
192
+
193
+ export class NumberLiteral extends Expression {
194
+ readonly type = "NumberLiteral";
195
+ public value: number;
196
+ }
197
+
198
+ export class BigIntLiteral extends Expression {
199
+ readonly type = "BigIntLiteral";
200
+ public value: bigint;
201
+ }
202
+
203
+ export class TemplateLiteral extends Expression {
204
+ readonly type = "TemplateLiteral";
205
+ public value: Expression[];
206
+ }
207
+
208
+ export class QuotedLiteral extends Expression {
209
+
210
+ static propertyChain(... properties: string[]): Expression {
211
+ const literal = properties.pop();
212
+ const property = QuotedLiteral.create({ literal });
213
+ if (properties.length === 0) {
214
+ return property;
215
+ }
216
+ return MemberExpression.create({
217
+ target: QuotedLiteral.propertyChain(... properties),
218
+ property
219
+ });
220
+ }
221
+
222
+ readonly type = "QuotedLiteral";
223
+ public literal: string;
224
+ }
225
+
226
+ export class ExpressionAs extends Expression {
227
+ readonly type = "ExpressionAs";
228
+ expression: Expression;
229
+ alias: QuotedLiteral;
230
+ }
231
+
232
+ export class TableLiteral extends Expression {
233
+ readonly type = "TableLiteral";
234
+ schema: QuotedLiteral;
235
+ name: QuotedLiteral;
236
+
237
+ }
238
+
239
+ export class InsertStatement extends Expression {
240
+ readonly type = "InsertStatement";
241
+ table: TableLiteral;
242
+
243
+ values: ValuesStatement | SelectStatement;
244
+
245
+ returnValues: ReturnUpdated;
246
+
247
+ }
248
+
249
+ export class UpdateStatement extends Expression {
250
+
251
+ readonly type = "UpdateStatement";
252
+
253
+ table: TableLiteral | QuotedLiteral;
254
+
255
+ set: BinaryExpression[];
256
+
257
+ where: Expression;
258
+
259
+ }
260
+
261
+ export class DeleteStatement extends Expression {
262
+ readonly type = "DeleteStatement";
263
+ table: TableLiteral;
264
+ where: Expression;
265
+ }
266
+
267
+ export type ExpressionType =
268
+ BinaryExpression |
269
+ ValuesStatement |
270
+ SelectStatement |
271
+ Constant|
272
+ QuotedLiteral|
273
+ ExpressionAs|
274
+ TableLiteral|
275
+ InsertStatement|
276
+ UpdateStatement|
277
+ DeleteStatement|
278
+ ReturnUpdated|
279
+ OrderByExpression|
280
+ JoinExpression|
281
+ NullExpression|
282
+ StringLiteral|
283
+ NumberLiteral|
284
+ BigIntLiteral|
285
+ BooleanLiteral|
286
+ TemplateLiteral|
287
+ MemberExpression|
288
+ CallExpression|
289
+ CoalesceExpression|
290
+ ExistsExpression|
291
+ Identifier |
292
+ PlaceholderExpression|
293
+ ArrowFunctionExpression
294
+ ;
@@ -0,0 +1,74 @@
1
+ export type ITextOrFunction = string | ((p: any) => any);
2
+ export type ITextOrFunctionArray = ITextOrFunction[];
3
+
4
+ export type IStringTransformer = (s: string) => string;
5
+
6
+ export type ISqlMethodTransformer = (callee: string, args: string[]) => string;
7
+
8
+
9
+ export const prepareAny = (a: TemplateStringsArray, ... p: any[]): any => {
10
+ const r = [];
11
+ for (let index = 0; index < a.length; index++) {
12
+ const element = a[index];
13
+ r.push(element);
14
+ if (index < p.length) {
15
+ const pi = p[index];
16
+ if (Array.isArray(pi)) {
17
+ r.push(... pi);
18
+ continue;
19
+ }
20
+ r.push(pi);
21
+ }
22
+ }
23
+ return r.flat(2);
24
+ };
25
+
26
+ const addNonEmptyFlat = (array: any[], item: any) => {
27
+ if (typeof item === "string") {
28
+ if(item) {
29
+ array.push(item);
30
+ return;
31
+ }
32
+ }
33
+ if (Array.isArray(item)) {
34
+ for (const iterator of item) {
35
+ if (typeof iterator === "string") {
36
+ if (iterator) {
37
+ array.push(iterator);
38
+ continue;
39
+ }
40
+ continue;
41
+ }
42
+ array.push(iterator);
43
+ }
44
+ return;
45
+ }
46
+ array.push(item);
47
+ };
48
+
49
+ export const prepare = (a: TemplateStringsArray, ... p: (ITextOrFunction | ITextOrFunctionArray)[]): ITextOrFunctionArray => {
50
+
51
+ const r = [];
52
+ for (let index = 0; index < a.length; index++) {
53
+ const element = a[index];
54
+ addNonEmptyFlat(r, element);
55
+ if (index < p.length) {
56
+ const pi = p[index];
57
+ addNonEmptyFlat(r, pi);
58
+ }
59
+ }
60
+ return r.flat(2);
61
+ };
62
+
63
+ export const prepareJoin = (a: (ITextOrFunction | ITextOrFunctionArray)[], sep: string = ","): ITextOrFunctionArray => {
64
+ const r = [];
65
+ let first = true;
66
+ for (const iterator of a) {
67
+ if (!first) {
68
+ r.push(",");
69
+ }
70
+ first = false;
71
+ addNonEmptyFlat(r, iterator);
72
+ }
73
+ return r.flat(2);
74
+ };
@@ -0,0 +1,25 @@
1
+ export default class SqlLiteral {
2
+ static escapeLiteral(str: string) {
3
+ let hasBackslash = false;
4
+ let escaped = "'";
5
+
6
+ for (const c of str) {
7
+ if (c === "'") {
8
+ escaped += c + c;
9
+ } else if (c === '\\') {
10
+ escaped += c + c;
11
+ hasBackslash = true;
12
+ } else {
13
+ escaped += c;
14
+ }
15
+ }
16
+
17
+ escaped += "'";
18
+
19
+ if (hasBackslash === true) {
20
+ escaped = ' E' + escaped;
21
+ }
22
+
23
+ return escaped;
24
+ }
25
+ }
@@ -0,0 +1,159 @@
1
+ import { ArrowFunctionExpression, BigIntLiteral, BinaryExpression, BooleanLiteral, CallExpression, CoalesceExpression, Constant, DeleteStatement, ExistsExpression, Expression, ExpressionAs, ExpressionType, Identifier, InsertStatement, JoinExpression, MemberExpression, NullExpression, NumberLiteral, OrderByExpression, PlaceholderExpression, QuotedLiteral, ReturnUpdated, SelectStatement, StringLiteral, TableLiteral, TemplateLiteral, UpdateStatement, ValuesStatement } from "./Expressions.js";
2
+
3
+
4
+ export default abstract class Visitor<T = any> {
5
+
6
+ visit(e1: Expression): T {
7
+
8
+ const e = e1 as ExpressionType;
9
+
10
+ switch (e.type) {
11
+ case "InsertStatement":
12
+ return this.visitInsertStatement(e);
13
+ case "Constant":
14
+ return this.visitConstant(e);
15
+ case "ExpressionAs":
16
+ return this.visitExpressionAs(e);
17
+ case "QuotedLiteral":
18
+ return this.visitQuotedLiteral(e);
19
+ case "SelectStatement":
20
+ return this.visitSelectStatement(e);
21
+ case "TableLiteral":
22
+ return this.visitTableLiteral(e);
23
+ case "ValuesStatement":
24
+ return this.visitValuesStatement(e);
25
+ case "BinaryExpression":
26
+ return this.visitBinaryExpression(e);
27
+ case "UpdateStatement":
28
+ return this.visitUpdateStatement(e);
29
+ case "DeleteStatement":
30
+ return this.visitDeleteStatement(e);
31
+ case "ReturnUpdated":
32
+ return this.visitReturnUpdated(e);
33
+ case "OrderByExpression":
34
+ return this.visitOrderByExpression(e);
35
+ case "JoinExpression":
36
+ return this.visitJoinExpression(e);
37
+ case "NullExpression":
38
+ return this.visitNullExpression(e);
39
+ case "BigIntLiteral":
40
+ return this.visitBigIntLiteral(e);
41
+ case "BooleanLiteral":
42
+ return this.visitBooleanLiteral(e);
43
+ case "NumberLiteral":
44
+ return this.visitNumberLiteral(e);
45
+ case "StringLiteral":
46
+ return this.visitStringLiteral(e);
47
+ case "TemplateLiteral":
48
+ return this.visitTemplateLiteral(e);
49
+ case "MemberExpression":
50
+ return this.visitMemberExpression(e);
51
+ case "CallExpression":
52
+ return this.visitCallExpression(e);
53
+ case "Identifier":
54
+ return this.visitIdentifier(e);
55
+ case "CoalesceExpression":
56
+ return this.visitCoalesceExpression(e);
57
+ case "ExistsExpression":
58
+ return this.visitExistsExpression(e);
59
+ case "PlaceholderExpression":
60
+ return this.visitPlaceholderExpression(e);
61
+ case "ArrowFunctionExpression":
62
+ return this.visitArrowFunctionExpression(e);
63
+ }
64
+ const c: never = e;
65
+ throw new Error(`${e1.type} Not implemented`);
66
+ }
67
+ visitArrowFunctionExpression(e: ArrowFunctionExpression): T {
68
+ return;
69
+ }
70
+ visitPlaceholderExpression(e: PlaceholderExpression): T {
71
+ return;
72
+ }
73
+ visitExistsExpression(e: ExistsExpression): T {
74
+ return;
75
+ }
76
+ visitCoalesceExpression(e: CoalesceExpression): T {
77
+ return;
78
+ }
79
+ visitIdentifier(e: Identifier): T {
80
+ return;
81
+ }
82
+ visitCallExpression(e: CallExpression): T {
83
+ return;
84
+ }
85
+ visitMemberExpression(e: MemberExpression): T {
86
+ return;
87
+ }
88
+ visitTemplateLiteral(e: TemplateLiteral): T {
89
+ return;
90
+ }
91
+ visitStringLiteral(e: StringLiteral): T {
92
+ return;
93
+ }
94
+ visitNumberLiteral(e: NumberLiteral): T {
95
+ return;
96
+ }
97
+ visitBooleanLiteral(e: BooleanLiteral): T {
98
+ return;
99
+ }
100
+ visitBigIntLiteral(e: BigIntLiteral): T {
101
+ return;
102
+ }
103
+ visitNullExpression(e: NullExpression): T {
104
+ return;
105
+ }
106
+
107
+ visitJoinExpression(e: JoinExpression): T {
108
+ return;
109
+ }
110
+
111
+ visitOrderByExpression(e: OrderByExpression): T {
112
+ return;
113
+ }
114
+
115
+ visitReturnUpdated(e: ReturnUpdated): T {
116
+ return;
117
+ }
118
+
119
+ visitDeleteStatement(e: DeleteStatement): T {
120
+ return;
121
+ }
122
+
123
+ visitUpdateStatement(e: UpdateStatement): T {
124
+ return;
125
+ }
126
+
127
+ visitBinaryExpression(e: BinaryExpression): T {
128
+ return;
129
+ }
130
+
131
+ visitValuesStatement(e: ValuesStatement): T {
132
+ return;
133
+ }
134
+
135
+ visitTableLiteral(e: TableLiteral): T {
136
+ return;
137
+ }
138
+
139
+ visitSelectStatement(e: SelectStatement): T {
140
+ return;
141
+ }
142
+
143
+ visitQuotedLiteral(e: QuotedLiteral): T {
144
+ return;
145
+ }
146
+
147
+ visitExpressionAs(e: ExpressionAs): T {
148
+ return;
149
+ }
150
+
151
+ visitConstant(e: Constant): T {
152
+ return;
153
+ }
154
+
155
+ visitInsertStatement(e: InsertStatement): T {
156
+ return;
157
+ }
158
+
159
+ }
@@ -0,0 +1,160 @@
1
+ import { parseExpression } from "@babel/parser";
2
+ import { ArrowFunctionExpression, BinaryExpression, CallExpression, CoalesceExpression, Constant, Expression, Identifier, MemberExpression, NullExpression, NumberLiteral, StringLiteral, TemplateLiteral } from "../ast/Expressions.js";
3
+ import { BabelVisitor } from "./BabelVisitor.js";
4
+ import * as bpe from "@babel/types";
5
+ import EntityType from "../../entity-query/EntityType.js";
6
+ import { EntitySource } from "../../model/EntitySource.js";
7
+
8
+ type IQueryFragment = string | { name?: string, value?: any };
9
+ type IQueryFragments = IQueryFragment[];
10
+
11
+ export default class ArrowToExpression extends BabelVisitor<Expression> {
12
+
13
+ public static transform(fx: (p: any) => (x: any) => any) {
14
+ const node = parseExpression(fx.toString());
15
+ if (node.type !== "ArrowFunctionExpression") {
16
+ throw new Error("Expecting an arrow function");
17
+ }
18
+
19
+ const firstParam = node.params[0];
20
+ if (firstParam.type !== "Identifier") {
21
+ throw new Error("Expecting an identifier");
22
+ }
23
+
24
+ const paramName = firstParam.name;
25
+
26
+ let body = node.body;
27
+ if (body.type !== "ArrowFunctionExpression") {
28
+ throw new Error("Expecting an arrow function");
29
+ }
30
+
31
+ const firstTarget = body.params[0];
32
+ if (firstTarget.type !== "Identifier") {
33
+ throw new Error("Expecting an identifier");
34
+ }
35
+
36
+ const target = firstTarget.name;
37
+
38
+ body = body.body;
39
+
40
+ const visitor = new this(paramName, target);
41
+ return {
42
+ param: paramName,
43
+ target,
44
+ body: visitor.visit(body)
45
+ };
46
+ }
47
+
48
+ public readonly leftJoins: string[] = [];
49
+
50
+ protected constructor(
51
+ public param: string,
52
+ public target: string
53
+ ) {
54
+ super();
55
+ }
56
+
57
+ visitBigIntLiteral({ value }: bpe.BigIntLiteral) {
58
+ return Constant.create({ value });
59
+ }
60
+
61
+ visitBooleanLiteral({ value }: bpe.BooleanLiteral) {
62
+ return Constant.create({ value });
63
+ }
64
+
65
+ visitDecimalLiteral( { value }: bpe.DecimalLiteral) {
66
+ return Constant.create({ value });
67
+ }
68
+
69
+ visitNullLiteral(node: bpe.NullLiteral) {
70
+ return NullExpression.create({});
71
+ }
72
+
73
+ visitStringLiteral({ value }: bpe.StringLiteral) {
74
+ return StringLiteral.create({ value });
75
+ }
76
+
77
+ visitNumericLiteral({ value }: bpe.NumericLiteral) {
78
+ return NumberLiteral.create({ value });
79
+ }
80
+
81
+ visitTemplateLiteral(node: bpe.TemplateLiteral) {
82
+ const value = node.expressions.map((x) => this.visit(x));
83
+ return TemplateLiteral.create({ value });
84
+ }
85
+
86
+ visitLogicalExpression(node: bpe.LogicalExpression): Expression {
87
+ const left = this.visit(node.left);
88
+ const right = this.visit(node.right);
89
+ let operator = node.operator as string;
90
+ switch(node.operator) {
91
+ case "&&":
92
+ operator = "AND";
93
+ break;
94
+ case "||":
95
+ operator = "OR";
96
+ break;
97
+ case "??":
98
+ return CoalesceExpression.create({ left, right });
99
+ }
100
+ return BinaryExpression.create({ left, operator, right });
101
+ }
102
+
103
+ visitBinaryExpression(node: bpe.BinaryExpression) {
104
+ let operator = node.operator as string;
105
+ switch(node.operator) {
106
+ case "!=":
107
+ case "!==":
108
+ operator = "<>";
109
+ break;
110
+ case "<":
111
+ case ">":
112
+ case "*":
113
+ case "%":
114
+ case "/":
115
+ case "+":
116
+ case "-":
117
+ case ">=":
118
+ case "<=":
119
+ break;
120
+ case "==":
121
+ case "===":
122
+ operator = "=";
123
+ break;
124
+ default:
125
+ throw new Error(`Operator ${operator} not supported`);
126
+ }
127
+ const left = this.visit(node.left);
128
+ const right = this.visit(node.right);
129
+ return BinaryExpression.create({ left , operator , right });
130
+ }
131
+
132
+ visitCallExpression({ callee, arguments: args }: bpe.CallExpression) {
133
+ return CallExpression.create({
134
+ callee: callee ? this.visit(callee) : void 0,
135
+ arguments: args ? args.map((x) => this.visit(x)) : []
136
+ });
137
+ }
138
+
139
+ visitIdentifier({ name: value }: bpe.Identifier): Expression {
140
+ return Identifier.create({ value });
141
+ }
142
+
143
+ visitMemberExpression({ object , property: key, computed }: bpe.MemberExpression) {
144
+ const property = this.visit(key);
145
+ return MemberExpression.create({
146
+ target: this.visit(object),
147
+ property,
148
+ computed
149
+ });
150
+ }
151
+
152
+ visitArrowFunctionExpression(node: bpe.ArrowFunctionExpression): Expression {
153
+ const params = node.params.map((x) => this.visit(x));
154
+ const body = this.visit(node.body);
155
+ return ArrowFunctionExpression.create({
156
+ params,
157
+ body
158
+ });
159
+ }
160
+ }