@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.
Files changed (62) hide show
  1. package/.github/workflows/node.yml +7 -2
  2. package/.vscode/settings.json +1 -0
  3. package/README.md +57 -27
  4. package/package.json +2 -2
  5. package/src/common/EntityAccessError.ts +10 -0
  6. package/src/common/IDisposable.ts +25 -0
  7. package/src/common/ImmutableObject.ts +53 -0
  8. package/src/common/Logger.ts +59 -0
  9. package/src/common/TypeInfo.ts +3 -0
  10. package/src/common/usingAsync.ts +42 -12
  11. package/src/compiler/QueryCompiler.ts +28 -30
  12. package/src/compiler/postgres/PostgreSqlMethodTransformer.ts +23 -0
  13. package/src/compiler/sql-server/SqlServerSqlMethodTransformer.ts +23 -0
  14. package/src/decorators/ForeignKey.ts +1 -1
  15. package/src/decorators/IClassOf.ts +2 -1
  16. package/src/decorators/parser/NameParser.ts +15 -0
  17. package/src/di/di.ts +224 -0
  18. package/src/drivers/base/BaseDriver.ts +28 -3
  19. package/src/drivers/sql-server/ExpressionToSqlServer.ts +48 -9
  20. package/src/drivers/sql-server/SqlServerDriver.ts +7 -16
  21. package/src/entity-query/EntityType.ts +1 -1
  22. package/src/model/EntityContext.ts +167 -22
  23. package/src/model/EntityQuery.ts +76 -60
  24. package/src/model/EntitySource.ts +39 -33
  25. package/src/model/IFilterWithParameter.ts +3 -0
  26. package/src/model/SourceExpression.ts +21 -25
  27. package/src/model/{ChangeEntry.ts → changes/ChangeEntry.ts} +33 -3
  28. package/src/model/{ChangeSet.ts → changes/ChangeSet.ts} +12 -11
  29. package/src/model/events/ContextEvents.ts +26 -0
  30. package/src/model/events/EntityEvents.ts +92 -0
  31. package/src/model/{IdentityService.ts → identity/IdentityService.ts} +1 -1
  32. package/src/model/symbols.ts +1 -0
  33. package/src/model/verification/VerificationSession.ts +173 -0
  34. package/src/query/ast/DebugStringVisitor.ts +128 -0
  35. package/src/query/ast/ExpressionToSql.ts +289 -119
  36. package/src/query/ast/Expressions.ts +111 -12
  37. package/src/query/ast/IStringTransformer.ts +16 -4
  38. package/src/query/ast/ReplaceParameter.ts +40 -0
  39. package/src/query/ast/Visitor.ts +20 -5
  40. package/src/query/parser/ArrowToExpression.ts +116 -16
  41. package/src/query/parser/BabelVisitor.ts +27 -44
  42. package/src/query/parser/NotSupportedError.ts +5 -0
  43. package/src/query/parser/Restructure.ts +66 -0
  44. package/src/query/parser/TransformVisitor.ts +83 -0
  45. package/src/sql/ISql.ts +10 -0
  46. package/src/tests/db-tests/tests/select-items.ts +12 -0
  47. package/src/tests/expressions/left-joins/child-joins.ts +19 -26
  48. package/src/tests/expressions/sanitize/sanitize-test.ts +17 -0
  49. package/src/tests/expressions/select/select.ts +24 -0
  50. package/src/tests/expressions/simple/parse-arrow.ts +10 -0
  51. package/src/tests/model/ShoppingContext.ts +7 -3
  52. package/src/tests/model/createContext.ts +45 -13
  53. package/src/tests/security/ShoppingContextEvents.ts +20 -0
  54. package/src/tests/security/events/OrderEvents.ts +66 -0
  55. package/src/tests/security/events/ProductEvents.ts +92 -0
  56. package/src/tests/security/events/UserEvents.ts +18 -0
  57. package/src/tests/security/events/UserInfo.ts +7 -0
  58. package/src/tests/security/tests/place-order.ts +71 -0
  59. package/test.js +11 -4
  60. package/tsconfig.json +2 -0
  61. package/src/decorators/parser/MemberParser.ts +0 -8
  62. 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 { ITextOrFunctionArray } from "./IStringTransformer.js";
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 PlaceholderExpression extends Expression {
72
- readonly type = "PlaceholderExpression";
73
- expression: () => ITextOrFunctionArray;
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: Expression[];
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: QuotedLiteral;
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
- PlaceholderExpression|
293
- ArrowFunctionExpression
388
+ ArrowFunctionExpression |
389
+ ConditionalExpression |
390
+ NewObjectExpression |
391
+ ParameterExpression |
392
+ TemplateElement
294
393
  ;
@@ -1,10 +1,22 @@
1
- export type ITextOrFunction = string | ((p: any) => any);
2
- export type ITextOrFunctionArray = ITextOrFunction[];
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: (ITextOrFunction | ITextOrFunctionArray)[]): ITextOrFunctionArray => {
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: (ITextOrFunction | ITextOrFunctionArray)[], sep: string = ","): ITextOrFunctionArray => {
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
+ }
@@ -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, PlaceholderExpression, QuotedLiteral, ReturnUpdated, SelectStatement, StringLiteral, TableLiteral, TemplateLiteral, UpdateStatement, ValuesStatement } from "./Expressions.js";
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
- visitArrowFunctionExpression(e: ArrowFunctionExpression): T {
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
- visitPlaceholderExpression(e: PlaceholderExpression): T {
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
- const node = parseExpression(fx.toString());
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 firstParam = node.params[0];
20
- if (firstParam.type !== "Identifier") {
21
- throw new Error("Expecting an identifier");
22
- }
24
+ const params = [] as ParameterExpression[];
23
25
 
24
- const paramName = firstParam.name;
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
- const target = firstTarget.name;
43
+ target ??= ParameterExpression.create({ name: firstTarget.name});
37
44
 
38
45
  body = body.body;
39
46
 
40
- const visitor = new this(paramName, target);
47
+ const visitor = new this(params, target, firstTarget.name);
41
48
  return {
42
- param: paramName,
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 param: string,
52
- public target: string
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 Error(`Operator ${operator} not supported`);
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 = node.params.map((x) => this.visit(x));
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(nodeAny: bpe.Expression | bpe.Node): T {
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
- visitMemberExpression(node: bpe.MemberExpression): T {
42
- return;
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
  }
@@ -0,0 +1,5 @@
1
+ export class NotSupportedError extends Error {
2
+ constructor(message?: string) {
3
+ super(message ? `${message} Not Supported`: "Not Supported");
4
+ }
5
+ }