@entity-access/entity-access 1.0.2 → 1.0.5
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.
- package/.github/workflows/node.yml +7 -2
- package/.vscode/settings.json +1 -0
- package/README.md +57 -27
- package/package.json +2 -2
- package/src/common/EntityAccessError.ts +10 -0
- package/src/common/IDisposable.ts +25 -0
- package/src/common/ImmutableObject.ts +53 -0
- package/src/common/Logger.ts +59 -0
- package/src/common/TypeInfo.ts +3 -0
- package/src/common/usingAsync.ts +42 -12
- package/src/compiler/QueryCompiler.ts +28 -30
- package/src/compiler/postgres/PostgreSqlMethodTransformer.ts +23 -0
- package/src/compiler/sql-server/SqlServerSqlMethodTransformer.ts +23 -0
- package/src/decorators/ForeignKey.ts +1 -1
- package/src/decorators/IClassOf.ts +2 -1
- package/src/decorators/parser/NameParser.ts +15 -0
- package/src/di/di.ts +224 -0
- package/src/drivers/base/BaseDriver.ts +28 -3
- package/src/drivers/sql-server/ExpressionToSqlServer.ts +48 -9
- package/src/drivers/sql-server/SqlServerDriver.ts +7 -16
- package/src/entity-query/EntityType.ts +1 -1
- package/src/model/EntityContext.ts +167 -22
- package/src/model/EntityQuery.ts +76 -60
- package/src/model/EntitySource.ts +39 -33
- package/src/model/IFilterWithParameter.ts +3 -0
- package/src/model/SourceExpression.ts +21 -25
- package/src/model/{ChangeEntry.ts → changes/ChangeEntry.ts} +33 -3
- package/src/model/{ChangeSet.ts → changes/ChangeSet.ts} +12 -11
- package/src/model/events/ContextEvents.ts +26 -0
- package/src/model/events/EntityEvents.ts +92 -0
- package/src/model/{IdentityService.ts → identity/IdentityService.ts} +1 -1
- package/src/model/symbols.ts +1 -0
- package/src/model/verification/VerificationSession.ts +173 -0
- package/src/query/ast/DebugStringVisitor.ts +128 -0
- package/src/query/ast/ExpressionToSql.ts +289 -119
- package/src/query/ast/Expressions.ts +111 -12
- package/src/query/ast/IStringTransformer.ts +16 -4
- package/src/query/ast/ReplaceParameter.ts +40 -0
- package/src/query/ast/Visitor.ts +20 -5
- package/src/query/parser/ArrowToExpression.ts +116 -16
- package/src/query/parser/BabelVisitor.ts +27 -44
- package/src/query/parser/NotSupportedError.ts +5 -0
- package/src/query/parser/Restructure.ts +66 -0
- package/src/query/parser/TransformVisitor.ts +83 -0
- package/src/sql/ISql.ts +10 -0
- package/src/tests/db-tests/tests/select-items.ts +12 -0
- package/src/tests/expressions/left-joins/child-joins.ts +19 -26
- package/src/tests/expressions/sanitize/sanitize-test.ts +17 -0
- package/src/tests/expressions/select/select.ts +24 -0
- package/src/tests/expressions/simple/parse-arrow.ts +10 -0
- package/src/tests/model/ShoppingContext.ts +7 -3
- package/src/tests/model/createContext.ts +45 -13
- package/src/tests/security/ShoppingContextEvents.ts +20 -0
- package/src/tests/security/events/OrderEvents.ts +66 -0
- package/src/tests/security/events/ProductEvents.ts +92 -0
- package/src/tests/security/events/UserEvents.ts +18 -0
- package/src/tests/security/events/UserInfo.ts +7 -0
- package/src/tests/security/tests/place-order.ts +71 -0
- package/test.js +11 -4
- package/tsconfig.json +2 -0
- package/src/decorators/parser/MemberParser.ts +0 -8
- package/src/model/EntitySchema.ts +0 -21
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { IColumn } from "../../decorators/IColumn.js";
|
|
2
1
|
import { IClassOf } from "../../decorators/IClassOf.js";
|
|
3
|
-
import {
|
|
2
|
+
import { ITextQuery } from "./IStringTransformer.js";
|
|
4
3
|
import type EntityType from "../../entity-query/EntityType.js";
|
|
4
|
+
import DebugStringVisitor from "./DebugStringVisitor.js";
|
|
5
5
|
|
|
6
6
|
const flattenedSelf = Symbol("flattenedSelf");
|
|
7
7
|
|
|
@@ -24,9 +24,64 @@ const flattenedSelf = Symbol("flattenedSelf");
|
|
|
24
24
|
|
|
25
25
|
export abstract class Expression {
|
|
26
26
|
|
|
27
|
+
static as(expression: Expression, alias: QuotedLiteral | string) {
|
|
28
|
+
if (typeof alias === "string") {
|
|
29
|
+
alias = Expression.quotedLiteral(alias);
|
|
30
|
+
}
|
|
31
|
+
return ExpressionAs.create({
|
|
32
|
+
expression,
|
|
33
|
+
alias
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
static templateLiteral(value: Expression[]) {
|
|
38
|
+
return TemplateLiteral.create({ value });
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
static constant(value: string) {
|
|
43
|
+
return Constant.create({ value });
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
static quotedLiteral(name: string) {
|
|
47
|
+
return QuotedLiteral.create({ literal: name });
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
static parameter(name: string) {
|
|
51
|
+
return ParameterExpression.create({ name });
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
static identifier(name: string) {
|
|
55
|
+
return Identifier.create({ value: name });
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
static logicalAnd(left: Expression, right: Expression): BinaryExpression {
|
|
59
|
+
return BinaryExpression.create({ left, operator: "AND", right});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
static member(target: Expression, identifier: string |Expression): MemberExpression {
|
|
63
|
+
return MemberExpression.create({
|
|
64
|
+
target,
|
|
65
|
+
property: typeof identifier === "string"
|
|
66
|
+
? this.identifier(identifier)
|
|
67
|
+
: identifier
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
static equal(left: Expression, right: Expression) {
|
|
72
|
+
return BinaryExpression.create({ left, right, operator: "="});
|
|
73
|
+
}
|
|
74
|
+
|
|
27
75
|
static create<T extends Expression>(this: IClassOf<T>, p: Partial<Omit<T, "type">>) {
|
|
28
76
|
(p as any).type = (this as any).name;
|
|
29
77
|
Object.setPrototypeOf(p, this.prototype);
|
|
78
|
+
Object.defineProperty(p, "debugView", {
|
|
79
|
+
get() {
|
|
80
|
+
return DebugStringVisitor.expressionToString(this);
|
|
81
|
+
},
|
|
82
|
+
enumerable: true,
|
|
83
|
+
configurable: true
|
|
84
|
+
});
|
|
30
85
|
return p as T;
|
|
31
86
|
}
|
|
32
87
|
|
|
@@ -68,9 +123,9 @@ export abstract class Expression {
|
|
|
68
123
|
|
|
69
124
|
}
|
|
70
125
|
|
|
71
|
-
export class
|
|
72
|
-
readonly type = "
|
|
73
|
-
|
|
126
|
+
export class PartialExpression extends Expression {
|
|
127
|
+
readonly type = "PartialExpression";
|
|
128
|
+
query: ITextQuery;
|
|
74
129
|
}
|
|
75
130
|
|
|
76
131
|
export class BinaryExpression extends Expression {
|
|
@@ -112,6 +167,21 @@ export class CallExpression extends Expression {
|
|
|
112
167
|
arguments: Expression[];
|
|
113
168
|
}
|
|
114
169
|
|
|
170
|
+
export class ParameterExpression extends Expression {
|
|
171
|
+
readonly type = "ParameterExpression";
|
|
172
|
+
name: string;
|
|
173
|
+
/**
|
|
174
|
+
* Default value if any...
|
|
175
|
+
*/
|
|
176
|
+
value: any;
|
|
177
|
+
|
|
178
|
+
quotedLiteral: (x: string) => string;
|
|
179
|
+
|
|
180
|
+
toString() {
|
|
181
|
+
return this.quotedLiteral?.(this.name) ?? this.name;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
115
185
|
export class MemberExpression extends Expression {
|
|
116
186
|
readonly type = "MemberExpression";
|
|
117
187
|
target: Expression;
|
|
@@ -121,7 +191,7 @@ export class MemberExpression extends Expression {
|
|
|
121
191
|
|
|
122
192
|
export class ArrowFunctionExpression extends Expression {
|
|
123
193
|
readonly type = "ArrowFunctionExpression";
|
|
124
|
-
params:
|
|
194
|
+
params: ParameterExpression[];
|
|
125
195
|
body: Expression;
|
|
126
196
|
}
|
|
127
197
|
|
|
@@ -131,9 +201,9 @@ export class SelectStatement extends Expression {
|
|
|
131
201
|
|
|
132
202
|
readonly type = "SelectStatement";
|
|
133
203
|
|
|
134
|
-
source: TableSource;
|
|
204
|
+
source: TableSource | ValuesStatement;
|
|
135
205
|
|
|
136
|
-
as:
|
|
206
|
+
as: ParameterExpression;
|
|
137
207
|
|
|
138
208
|
fields: (Expression | QuotedLiteral | ExpressionAs)[];
|
|
139
209
|
|
|
@@ -147,13 +217,30 @@ export class SelectStatement extends Expression {
|
|
|
147
217
|
|
|
148
218
|
offset: number;
|
|
149
219
|
|
|
220
|
+
// name holds string
|
|
221
|
+
names: string;
|
|
222
|
+
|
|
223
|
+
model: EntityType;
|
|
224
|
+
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export class NewObjectExpression extends Expression {
|
|
228
|
+
readonly type = "NewObjectExpression";
|
|
229
|
+
properties: ExpressionAs[];
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
export class ConditionalExpression extends Expression {
|
|
233
|
+
readonly type = "ConditionalExpression";
|
|
234
|
+
test: Expression;
|
|
235
|
+
consequent: Expression;
|
|
236
|
+
alternate: Expression;
|
|
150
237
|
}
|
|
151
238
|
|
|
152
239
|
export class JoinExpression extends Expression {
|
|
153
240
|
readonly type = "JoinExpression";
|
|
154
241
|
joinType: "LEFT" | "INNER";
|
|
155
242
|
source: SelectStatement | QuotedLiteral | ExpressionAs;
|
|
156
|
-
as: QuotedLiteral;
|
|
243
|
+
as: QuotedLiteral | ParameterExpression;
|
|
157
244
|
where: Expression;
|
|
158
245
|
model: EntityType;
|
|
159
246
|
}
|
|
@@ -200,8 +287,17 @@ export class BigIntLiteral extends Expression {
|
|
|
200
287
|
public value: bigint;
|
|
201
288
|
}
|
|
202
289
|
|
|
290
|
+
export class TemplateElement extends Expression {
|
|
291
|
+
readonly type = "TemplateElement";
|
|
292
|
+
public value: {
|
|
293
|
+
raw: string;
|
|
294
|
+
cooked: string;
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
|
|
203
298
|
export class TemplateLiteral extends Expression {
|
|
204
299
|
readonly type = "TemplateLiteral";
|
|
300
|
+
public quasis: TemplateElement[];
|
|
205
301
|
public value: Expression[];
|
|
206
302
|
}
|
|
207
303
|
|
|
@@ -260,7 +356,7 @@ export class UpdateStatement extends Expression {
|
|
|
260
356
|
|
|
261
357
|
export class DeleteStatement extends Expression {
|
|
262
358
|
readonly type = "DeleteStatement";
|
|
263
|
-
table: TableLiteral;
|
|
359
|
+
table: TableLiteral | QuotedLiteral;
|
|
264
360
|
where: Expression;
|
|
265
361
|
}
|
|
266
362
|
|
|
@@ -289,6 +385,9 @@ export type ExpressionType =
|
|
|
289
385
|
CoalesceExpression|
|
|
290
386
|
ExistsExpression|
|
|
291
387
|
Identifier |
|
|
292
|
-
|
|
293
|
-
|
|
388
|
+
ArrowFunctionExpression |
|
|
389
|
+
ConditionalExpression |
|
|
390
|
+
NewObjectExpression |
|
|
391
|
+
ParameterExpression |
|
|
392
|
+
TemplateElement
|
|
294
393
|
;
|
|
@@ -1,10 +1,22 @@
|
|
|
1
|
-
export type
|
|
2
|
-
export type
|
|
1
|
+
export type ITextQueryFragment = string | ((p: any) => any) | { toString(): string };
|
|
2
|
+
export type ITextQuery = ITextQueryFragment[];
|
|
3
3
|
|
|
4
4
|
export type IStringTransformer = (s: string) => string;
|
|
5
5
|
|
|
6
6
|
export type ISqlMethodTransformer = (callee: string, args: string[]) => string;
|
|
7
7
|
|
|
8
|
+
export class QueryParameter {
|
|
9
|
+
|
|
10
|
+
static create(name: () => string, quotedLiteral: (n: string) => string ) {
|
|
11
|
+
return new QueryParameter(name, quotedLiteral);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
constructor(public name: () => string, public quotedLiteral: (n: string) => string) {}
|
|
15
|
+
|
|
16
|
+
toString() {
|
|
17
|
+
return this.quotedLiteral(this.name());
|
|
18
|
+
}
|
|
19
|
+
}
|
|
8
20
|
|
|
9
21
|
export const prepareAny = (a: TemplateStringsArray, ... p: any[]): any => {
|
|
10
22
|
const r = [];
|
|
@@ -46,7 +58,7 @@ const addNonEmptyFlat = (array: any[], item: any) => {
|
|
|
46
58
|
array.push(item);
|
|
47
59
|
};
|
|
48
60
|
|
|
49
|
-
export const prepare = (a: TemplateStringsArray, ... p: (
|
|
61
|
+
export const prepare = (a: TemplateStringsArray, ... p: (ITextQueryFragment | ITextQuery)[]): ITextQuery => {
|
|
50
62
|
|
|
51
63
|
const r = [];
|
|
52
64
|
for (let index = 0; index < a.length; index++) {
|
|
@@ -60,7 +72,7 @@ export const prepare = (a: TemplateStringsArray, ... p: (ITextOrFunction | IText
|
|
|
60
72
|
return r.flat(2);
|
|
61
73
|
};
|
|
62
74
|
|
|
63
|
-
export const prepareJoin = (a: (
|
|
75
|
+
export const prepareJoin = (a: (ITextQueryFragment | ITextQuery)[], sep: string = ","): ITextQuery => {
|
|
64
76
|
const r = [];
|
|
65
77
|
let first = true;
|
|
66
78
|
for (const iterator of a) {
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Expression } from "@babel/types";
|
|
2
|
+
|
|
3
|
+
export default class ReplaceParameter {
|
|
4
|
+
|
|
5
|
+
public static replace(tree: Expression | Expression[], from: Expression, to: Expression) {
|
|
6
|
+
if (!tree) {
|
|
7
|
+
return tree;
|
|
8
|
+
}
|
|
9
|
+
if (tree === from) {
|
|
10
|
+
return to;
|
|
11
|
+
}
|
|
12
|
+
if (Array.isArray(tree)) {
|
|
13
|
+
const copy = [];
|
|
14
|
+
let index = 0;
|
|
15
|
+
for (const iterator of tree) {
|
|
16
|
+
Object.defineProperty(copy, index++, {
|
|
17
|
+
value: this.replace(iterator, from, to),
|
|
18
|
+
writable: false,
|
|
19
|
+
enumerable: true
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
return tree;
|
|
23
|
+
}
|
|
24
|
+
if (!(tree as any).type) {
|
|
25
|
+
return tree;
|
|
26
|
+
}
|
|
27
|
+
const treeCopy = {};
|
|
28
|
+
for (const key in tree) {
|
|
29
|
+
if (Object.prototype.hasOwnProperty.call(tree, key)) {
|
|
30
|
+
const element = tree[key];
|
|
31
|
+
Object.defineProperty(treeCopy, key, {
|
|
32
|
+
value: this.replace(element, from, to)
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
Object.setPrototypeOf(treeCopy, Object.getPrototypeOf(tree));
|
|
37
|
+
return treeCopy;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
}
|
package/src/query/ast/Visitor.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ArrowFunctionExpression, BigIntLiteral, BinaryExpression, BooleanLiteral, CallExpression, CoalesceExpression, Constant, DeleteStatement, ExistsExpression, Expression, ExpressionAs, ExpressionType, Identifier, InsertStatement, JoinExpression, MemberExpression, NullExpression, NumberLiteral, OrderByExpression,
|
|
1
|
+
import { ArrowFunctionExpression, BigIntLiteral, BinaryExpression, BooleanLiteral, CallExpression, CoalesceExpression, ConditionalExpression, Constant, DeleteStatement, ExistsExpression, Expression, ExpressionAs, ExpressionType, Identifier, InsertStatement, JoinExpression, MemberExpression, NewObjectExpression, NullExpression, NumberLiteral, OrderByExpression, ParameterExpression, QuotedLiteral, ReturnUpdated, SelectStatement, StringLiteral, TableLiteral, TemplateElement, TemplateLiteral, UpdateStatement, ValuesStatement } from "./Expressions.js";
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
export default abstract class Visitor<T = any> {
|
|
@@ -56,18 +56,33 @@ export default abstract class Visitor<T = any> {
|
|
|
56
56
|
return this.visitCoalesceExpression(e);
|
|
57
57
|
case "ExistsExpression":
|
|
58
58
|
return this.visitExistsExpression(e);
|
|
59
|
-
case "PlaceholderExpression":
|
|
60
|
-
return this.visitPlaceholderExpression(e);
|
|
61
59
|
case "ArrowFunctionExpression":
|
|
62
60
|
return this.visitArrowFunctionExpression(e);
|
|
61
|
+
case "ConditionalExpression":
|
|
62
|
+
return this.visitConditionalExpression(e);
|
|
63
|
+
case "NewObjectExpression":
|
|
64
|
+
return this.visitNewObjectExpression(e);
|
|
65
|
+
case "TemplateElement":
|
|
66
|
+
return this.visitTemplateElement(e);
|
|
67
|
+
case "ParameterExpression":
|
|
68
|
+
return this.visitParameterExpression(e);
|
|
63
69
|
}
|
|
64
70
|
const c: never = e;
|
|
65
71
|
throw new Error(`${e1.type} Not implemented`);
|
|
66
72
|
}
|
|
67
|
-
|
|
73
|
+
visitParameterExpression(e: ParameterExpression): T {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
visitTemplateElement(e: TemplateElement): T {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
visitNewObjectExpression(e: NewObjectExpression): T {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
visitConditionalExpression(e: ConditionalExpression): T {
|
|
68
83
|
return;
|
|
69
84
|
}
|
|
70
|
-
|
|
85
|
+
visitArrowFunctionExpression(e: ArrowFunctionExpression): T {
|
|
71
86
|
return;
|
|
72
87
|
}
|
|
73
88
|
visitExistsExpression(e: ExistsExpression): T {
|
|
@@ -1,27 +1,34 @@
|
|
|
1
1
|
import { parseExpression } from "@babel/parser";
|
|
2
|
-
import { ArrowFunctionExpression, BinaryExpression, CallExpression, CoalesceExpression, Constant, Expression, Identifier, MemberExpression, NullExpression, NumberLiteral, StringLiteral, TemplateLiteral } from "../ast/Expressions.js";
|
|
2
|
+
import { ArrowFunctionExpression, BinaryExpression, CallExpression, CoalesceExpression, ConditionalExpression, Constant, Expression, ExpressionAs, Identifier, MemberExpression, NewObjectExpression, NullExpression, NumberLiteral, ParameterExpression, QuotedLiteral, StringLiteral, TemplateLiteral } from "../ast/Expressions.js";
|
|
3
3
|
import { BabelVisitor } from "./BabelVisitor.js";
|
|
4
4
|
import * as bpe from "@babel/types";
|
|
5
5
|
import EntityType from "../../entity-query/EntityType.js";
|
|
6
6
|
import { EntitySource } from "../../model/EntitySource.js";
|
|
7
|
+
import Restructure from "./Restructure.js";
|
|
8
|
+
import { NotSupportedError } from "./NotSupportedError.js";
|
|
7
9
|
|
|
8
10
|
type IQueryFragment = string | { name?: string, value?: any };
|
|
9
11
|
type IQueryFragments = IQueryFragment[];
|
|
10
12
|
|
|
11
13
|
export default class ArrowToExpression extends BabelVisitor<Expression> {
|
|
12
14
|
|
|
13
|
-
public static transform(fx: (p: any) => (x: any) => any) {
|
|
14
|
-
|
|
15
|
+
public static transform(fx: (p: any) => (x: any) => any, target?: ParameterExpression) {
|
|
16
|
+
|
|
17
|
+
const rs = new Restructure();
|
|
18
|
+
|
|
19
|
+
const node = rs.visit(parseExpression(fx.toString()));
|
|
15
20
|
if (node.type !== "ArrowFunctionExpression") {
|
|
16
21
|
throw new Error("Expecting an arrow function");
|
|
17
22
|
}
|
|
18
23
|
|
|
19
|
-
const
|
|
20
|
-
if (firstParam.type !== "Identifier") {
|
|
21
|
-
throw new Error("Expecting an identifier");
|
|
22
|
-
}
|
|
24
|
+
const params = [] as ParameterExpression[];
|
|
23
25
|
|
|
24
|
-
const
|
|
26
|
+
for (const iterator of node.params) {
|
|
27
|
+
if (iterator.type !== "Identifier") {
|
|
28
|
+
throw new Error("Expecting an identifier");
|
|
29
|
+
}
|
|
30
|
+
params.push(ParameterExpression.create({ name: iterator.name }));
|
|
31
|
+
}
|
|
25
32
|
|
|
26
33
|
let body = node.body;
|
|
27
34
|
if (body.type !== "ArrowFunctionExpression") {
|
|
@@ -33,13 +40,13 @@ export default class ArrowToExpression extends BabelVisitor<Expression> {
|
|
|
33
40
|
throw new Error("Expecting an identifier");
|
|
34
41
|
}
|
|
35
42
|
|
|
36
|
-
|
|
43
|
+
target ??= ParameterExpression.create({ name: firstTarget.name});
|
|
37
44
|
|
|
38
45
|
body = body.body;
|
|
39
46
|
|
|
40
|
-
const visitor = new this(
|
|
47
|
+
const visitor = new this(params, target, firstTarget.name);
|
|
41
48
|
return {
|
|
42
|
-
|
|
49
|
+
params,
|
|
43
50
|
target,
|
|
44
51
|
body: visitor.visit(body)
|
|
45
52
|
};
|
|
@@ -47,11 +54,19 @@ export default class ArrowToExpression extends BabelVisitor<Expression> {
|
|
|
47
54
|
|
|
48
55
|
public readonly leftJoins: string[] = [];
|
|
49
56
|
|
|
57
|
+
private targetStack: Map<any,any> = new Map();
|
|
58
|
+
|
|
50
59
|
protected constructor(
|
|
51
|
-
public
|
|
52
|
-
public target:
|
|
60
|
+
public params: ParameterExpression[],
|
|
61
|
+
public target: ParameterExpression,
|
|
62
|
+
targetName: string
|
|
53
63
|
) {
|
|
54
64
|
super();
|
|
65
|
+
this.targetStack.set("Sql", "Sql");
|
|
66
|
+
for (const iterator of params) {
|
|
67
|
+
this.targetStack.set(iterator.name, iterator);
|
|
68
|
+
}
|
|
69
|
+
this.targetStack.set(targetName ?? target.name, target);
|
|
55
70
|
}
|
|
56
71
|
|
|
57
72
|
visitBigIntLiteral({ value }: bpe.BigIntLiteral) {
|
|
@@ -79,10 +94,24 @@ export default class ArrowToExpression extends BabelVisitor<Expression> {
|
|
|
79
94
|
}
|
|
80
95
|
|
|
81
96
|
visitTemplateLiteral(node: bpe.TemplateLiteral) {
|
|
82
|
-
const value = node.expressions.map((x) => this.visit(x));
|
|
97
|
+
// const value = node.expressions.map((x) => this.visit(x));
|
|
98
|
+
const value = [] as Expression[];
|
|
99
|
+
for (let index = 0; index < node.quasis.length; index++) {
|
|
100
|
+
const { value: { cooked }} = node.quasis[index];
|
|
101
|
+
if (cooked) {
|
|
102
|
+
value.push(StringLiteral.create({ value: cooked }));
|
|
103
|
+
}
|
|
104
|
+
if (index < node.expressions.length) {
|
|
105
|
+
value.push(this.visit(node.expressions[index]));
|
|
106
|
+
}
|
|
107
|
+
}
|
|
83
108
|
return TemplateLiteral.create({ value });
|
|
84
109
|
}
|
|
85
110
|
|
|
111
|
+
visitTemplateElement(node: bpe.TemplateElement): Expression {
|
|
112
|
+
throw new NotSupportedError();
|
|
113
|
+
}
|
|
114
|
+
|
|
86
115
|
visitLogicalExpression(node: bpe.LogicalExpression): Expression {
|
|
87
116
|
const left = this.visit(node.left);
|
|
88
117
|
const right = this.visit(node.right);
|
|
@@ -122,7 +151,7 @@ export default class ArrowToExpression extends BabelVisitor<Expression> {
|
|
|
122
151
|
operator = "=";
|
|
123
152
|
break;
|
|
124
153
|
default:
|
|
125
|
-
throw new
|
|
154
|
+
throw new NotSupportedError(`Operator ${operator}`);
|
|
126
155
|
}
|
|
127
156
|
const left = this.visit(node.left);
|
|
128
157
|
const right = this.visit(node.right);
|
|
@@ -130,6 +159,10 @@ export default class ArrowToExpression extends BabelVisitor<Expression> {
|
|
|
130
159
|
}
|
|
131
160
|
|
|
132
161
|
visitCallExpression({ callee, arguments: args }: bpe.CallExpression) {
|
|
162
|
+
|
|
163
|
+
// we need to sanitize callee
|
|
164
|
+
this.sanitize(callee);
|
|
165
|
+
|
|
133
166
|
return CallExpression.create({
|
|
134
167
|
callee: callee ? this.visit(callee) : void 0,
|
|
135
168
|
arguments: args ? args.map((x) => this.visit(x)) : []
|
|
@@ -137,6 +170,10 @@ export default class ArrowToExpression extends BabelVisitor<Expression> {
|
|
|
137
170
|
}
|
|
138
171
|
|
|
139
172
|
visitIdentifier({ name: value }: bpe.Identifier): Expression {
|
|
173
|
+
const scopedName = this.targetStack.get(value);
|
|
174
|
+
if (typeof scopedName === "object") {
|
|
175
|
+
return scopedName;
|
|
176
|
+
}
|
|
140
177
|
return Identifier.create({ value });
|
|
141
178
|
}
|
|
142
179
|
|
|
@@ -150,11 +187,74 @@ export default class ArrowToExpression extends BabelVisitor<Expression> {
|
|
|
150
187
|
}
|
|
151
188
|
|
|
152
189
|
visitArrowFunctionExpression(node: bpe.ArrowFunctionExpression): Expression {
|
|
153
|
-
const params =
|
|
190
|
+
const params = [] as ParameterExpression[];
|
|
191
|
+
const names = [];
|
|
192
|
+
for (const iterator of node.params) {
|
|
193
|
+
if (iterator.type !== "Identifier") {
|
|
194
|
+
throw new NotSupportedError();
|
|
195
|
+
}
|
|
196
|
+
names.push(iterator.name);
|
|
197
|
+
const p = ParameterExpression.create({ value: iterator.name });
|
|
198
|
+
this.targetStack.set(iterator.name, p);
|
|
199
|
+
params.push(p);
|
|
200
|
+
}
|
|
154
201
|
const body = this.visit(node.body);
|
|
202
|
+
for (const name of names) {
|
|
203
|
+
this.targetStack.delete(name);
|
|
204
|
+
}
|
|
155
205
|
return ArrowFunctionExpression.create({
|
|
156
206
|
params,
|
|
157
207
|
body
|
|
158
208
|
});
|
|
159
209
|
}
|
|
210
|
+
|
|
211
|
+
visitObjectExpression(node: bpe.ObjectExpression): Expression {
|
|
212
|
+
const properties = [] as ExpressionAs[];
|
|
213
|
+
for (const iterator of node.properties) {
|
|
214
|
+
switch(iterator.type) {
|
|
215
|
+
case "ObjectProperty":
|
|
216
|
+
switch(iterator.key.type) {
|
|
217
|
+
case "Identifier":
|
|
218
|
+
properties.push( ExpressionAs.create({
|
|
219
|
+
alias: QuotedLiteral.create({ literal: iterator.key.name}),
|
|
220
|
+
expression: this.visit(iterator.value)
|
|
221
|
+
}) );
|
|
222
|
+
break;
|
|
223
|
+
default:
|
|
224
|
+
throw new NotSupportedError();
|
|
225
|
+
}
|
|
226
|
+
continue;
|
|
227
|
+
default:
|
|
228
|
+
throw new NotSupportedError();
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return NewObjectExpression.create({
|
|
232
|
+
properties
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
visitConditionalExpression(node: bpe.ConditionalExpression): Expression {
|
|
237
|
+
return ConditionalExpression.create({
|
|
238
|
+
test: this.visit(node.test),
|
|
239
|
+
consequent: this.visit(node.consequent),
|
|
240
|
+
alternate: this.visit(node.alternate)
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
private sanitize(node: bpe.Expression | bpe.V8IntrinsicIdentifier) {
|
|
245
|
+
switch(node.type) {
|
|
246
|
+
case "Identifier":
|
|
247
|
+
const name = node.name;
|
|
248
|
+
const scopedName = this.targetStack.get(name);
|
|
249
|
+
if (scopedName === null || scopedName === void 0) {
|
|
250
|
+
throw new Error(`Unknown identifier ${name}`);
|
|
251
|
+
}
|
|
252
|
+
return;
|
|
253
|
+
case "MemberExpression":
|
|
254
|
+
case "OptionalMemberExpression":
|
|
255
|
+
return this.sanitize(node.object);
|
|
256
|
+
}
|
|
257
|
+
throw new Error(`Unexpected expression type ${node.type}`);
|
|
258
|
+
}
|
|
259
|
+
|
|
160
260
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as bp from "@babel/parser";
|
|
2
2
|
import * as bpe from "@babel/types";
|
|
3
3
|
|
|
4
|
-
export class BabelVisitor<T> {
|
|
5
|
-
visit(
|
|
6
|
-
const node = nodeAny as bpe.Expression;
|
|
4
|
+
export abstract class BabelVisitor<T> {
|
|
5
|
+
visit(node: bpe.Expression | bpe.Node): T {
|
|
6
|
+
// const node = nodeAny as bpe.Expression;
|
|
7
7
|
switch (node.type) {
|
|
8
8
|
case "BinaryExpression":
|
|
9
9
|
return this.visitBinaryExpression(node);
|
|
@@ -33,54 +33,37 @@ export class BabelVisitor<T> {
|
|
|
33
33
|
return this.visitIdentifier(node);
|
|
34
34
|
case "MemberExpression":
|
|
35
35
|
return this.visitMemberExpression(node);
|
|
36
|
+
case "ObjectExpression":
|
|
37
|
+
return this.visitObjectExpression(node);
|
|
38
|
+
case "ObjectProperty":
|
|
39
|
+
return this.visitObjectProperty(node);
|
|
40
|
+
case "TemplateElement":
|
|
41
|
+
return this.visitTemplateElement(node);
|
|
36
42
|
case "RegExpLiteral":
|
|
37
43
|
default:
|
|
38
44
|
throw new Error(`Translation from ${node.type} not supported`);
|
|
39
45
|
}
|
|
40
46
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
visitLogicalExpression(node: bpe.LogicalExpression): T {
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
visitIdentifier(node: bpe.Identifier): T {
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
visitTemplateLiteral(node: bpe.TemplateLiteral): T {
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
visitNumericLiteral(node: bpe.NumericLiteral): T {
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
visitDecimalLiteral(node: bpe.DecimalLiteral): T {
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
visitBooleanLiteral(node: bpe.BooleanLiteral): T {
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
visitBigIntLiteral(node: bpe.BigIntLiteral): T {
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
visitStringLiteral(node: bpe.StringLiteral): T {
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
visitNullLiteral(node: bpe.NullLiteral): T {
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
visitConditionalExpression(node: bpe.ConditionalExpression): T {
|
|
72
|
-
return;
|
|
47
|
+
abstract visitTemplateElement(node: bpe.TemplateElement): T;
|
|
48
|
+
visitObjectProperty(node: bpe.ObjectProperty): T {
|
|
49
|
+
throw new Error("Method not implemented.");
|
|
73
50
|
}
|
|
51
|
+
abstract visitObjectExpression(node: bpe.ObjectExpression): T;
|
|
52
|
+
abstract visitMemberExpression(node: bpe.MemberExpression): T;
|
|
53
|
+
abstract visitLogicalExpression(node: bpe.LogicalExpression): T;
|
|
54
|
+
abstract visitIdentifier(node: bpe.Identifier): T;
|
|
55
|
+
abstract visitTemplateLiteral(node: bpe.TemplateLiteral): T;
|
|
56
|
+
abstract visitNumericLiteral(node: bpe.NumericLiteral): T;
|
|
57
|
+
abstract visitDecimalLiteral(node: bpe.DecimalLiteral): T;
|
|
58
|
+
abstract visitBooleanLiteral(node: bpe.BooleanLiteral): T;
|
|
59
|
+
abstract visitBigIntLiteral(node: bpe.BigIntLiteral): T;
|
|
60
|
+
abstract visitStringLiteral(node: bpe.StringLiteral): T;
|
|
61
|
+
abstract visitNullLiteral(node: bpe.NullLiteral): T;
|
|
62
|
+
abstract visitConditionalExpression(node: bpe.ConditionalExpression): T;
|
|
74
63
|
|
|
75
|
-
visitArrowFunctionExpression(node: bpe.ArrowFunctionExpression): T
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
64
|
+
abstract visitArrowFunctionExpression(node: bpe.ArrowFunctionExpression): T;
|
|
78
65
|
|
|
79
|
-
visitCallExpression(node: bpe.CallExpression): T
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
66
|
+
abstract visitCallExpression(node: bpe.CallExpression): T;
|
|
82
67
|
|
|
83
|
-
visitBinaryExpression(node: bpe.BinaryExpression): T
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
68
|
+
abstract visitBinaryExpression(node: bpe.BinaryExpression): T;
|
|
86
69
|
}
|