@entity-access/entity-access 1.0.95 → 1.0.96

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 (103) hide show
  1. package/.vscode/launch.json +3 -0
  2. package/dist/compiler/QueryCompiler.d.ts +2 -0
  3. package/dist/compiler/QueryCompiler.d.ts.map +1 -1
  4. package/dist/compiler/QueryCompiler.js +6 -0
  5. package/dist/compiler/QueryCompiler.js.map +1 -1
  6. package/dist/compiler/RawQuery.d.ts +10 -0
  7. package/dist/compiler/RawQuery.d.ts.map +1 -0
  8. package/dist/compiler/RawQuery.js +26 -0
  9. package/dist/compiler/RawQuery.js.map +1 -0
  10. package/dist/compiler/postgres/PostgreSqlMethodTransformer.d.ts.map +1 -1
  11. package/dist/compiler/postgres/PostgreSqlMethodTransformer.js +3 -0
  12. package/dist/compiler/postgres/PostgreSqlMethodTransformer.js.map +1 -1
  13. package/dist/compiler/sql-server/SqlServerSqlMethodTransformer.d.ts.map +1 -1
  14. package/dist/compiler/sql-server/SqlServerSqlMethodTransformer.js +9 -6
  15. package/dist/compiler/sql-server/SqlServerSqlMethodTransformer.js.map +1 -1
  16. package/dist/drivers/base/BaseDriver.d.ts +15 -8
  17. package/dist/drivers/base/BaseDriver.d.ts.map +1 -1
  18. package/dist/drivers/base/BaseDriver.js +13 -3
  19. package/dist/drivers/base/BaseDriver.js.map +1 -1
  20. package/dist/drivers/postgres/PostgreSqlDriver.d.ts +2 -12
  21. package/dist/drivers/postgres/PostgreSqlDriver.d.ts.map +1 -1
  22. package/dist/drivers/postgres/PostgreSqlDriver.js +11 -2
  23. package/dist/drivers/postgres/PostgreSqlDriver.js.map +1 -1
  24. package/dist/drivers/sql-server/SqlServerDriver.d.ts +8 -2
  25. package/dist/drivers/sql-server/SqlServerDriver.d.ts.map +1 -1
  26. package/dist/drivers/sql-server/SqlServerDriver.js +18 -10
  27. package/dist/drivers/sql-server/SqlServerDriver.js.map +1 -1
  28. package/dist/eternity/ActivitySuspendedError.d.ts +3 -0
  29. package/dist/eternity/ActivitySuspendedError.d.ts.map +1 -1
  30. package/dist/eternity/ActivitySuspendedError.js +6 -0
  31. package/dist/eternity/ActivitySuspendedError.js.map +1 -1
  32. package/dist/eternity/EternityContext.d.ts +3 -1
  33. package/dist/eternity/EternityContext.d.ts.map +1 -1
  34. package/dist/eternity/EternityContext.js +54 -6
  35. package/dist/eternity/EternityContext.js.map +1 -1
  36. package/dist/eternity/EternityStorage.d.ts +6 -0
  37. package/dist/eternity/EternityStorage.d.ts.map +1 -1
  38. package/dist/eternity/EternityStorage.js +60 -19
  39. package/dist/eternity/EternityStorage.js.map +1 -1
  40. package/dist/eternity/Workflow.d.ts +15 -4
  41. package/dist/eternity/Workflow.d.ts.map +1 -1
  42. package/dist/eternity/Workflow.js +35 -22
  43. package/dist/eternity/Workflow.js.map +1 -1
  44. package/dist/migrations/postgres/PostgresAutomaticMigrations.d.ts +3 -3
  45. package/dist/migrations/postgres/PostgresAutomaticMigrations.d.ts.map +1 -1
  46. package/dist/migrations/postgres/PostgresAutomaticMigrations.js +2 -2
  47. package/dist/migrations/postgres/PostgresAutomaticMigrations.js.map +1 -1
  48. package/dist/migrations/sql-server/SqlServerAutomaticMigrations.d.ts +3 -3
  49. package/dist/migrations/sql-server/SqlServerAutomaticMigrations.d.ts.map +1 -1
  50. package/dist/migrations/sql-server/SqlServerAutomaticMigrations.js +2 -2
  51. package/dist/migrations/sql-server/SqlServerAutomaticMigrations.js.map +1 -1
  52. package/dist/model/EntityContext.d.ts +3 -1
  53. package/dist/model/EntityContext.d.ts.map +1 -1
  54. package/dist/model/EntityContext.js +6 -2
  55. package/dist/model/EntityContext.js.map +1 -1
  56. package/dist/model/EntityQuery.js +3 -3
  57. package/dist/model/EntityQuery.js.map +1 -1
  58. package/dist/model/verification/VerificationSession.js +1 -1
  59. package/dist/model/verification/VerificationSession.js.map +1 -1
  60. package/dist/query/ast/ExpressionToSql.d.ts.map +1 -1
  61. package/dist/query/ast/ExpressionToSql.js +21 -19
  62. package/dist/query/ast/ExpressionToSql.js.map +1 -1
  63. package/dist/query/ast/Expressions.d.ts +1 -0
  64. package/dist/query/ast/Expressions.d.ts.map +1 -1
  65. package/dist/query/ast/Expressions.js +3 -0
  66. package/dist/query/ast/Expressions.js.map +1 -1
  67. package/dist/sql/ISql.d.ts +2 -0
  68. package/dist/sql/ISql.d.ts.map +1 -1
  69. package/dist/tests/drivers/postgres/connection-test.js +1 -1
  70. package/dist/tests/drivers/postgres/connection-test.js.map +1 -1
  71. package/dist/tests/eternity/child-tests.d.ts +3 -0
  72. package/dist/tests/eternity/child-tests.d.ts.map +1 -0
  73. package/dist/tests/eternity/child-tests.js +103 -0
  74. package/dist/tests/eternity/child-tests.js.map +1 -0
  75. package/dist/tests/eternity/eternity-tests.d.ts.map +1 -1
  76. package/dist/tests/eternity/eternity-tests.js.map +1 -1
  77. package/dist/tests/model/createContext.js +2 -2
  78. package/dist/tests/model/createContext.js.map +1 -1
  79. package/dist/tsconfig.tsbuildinfo +1 -1
  80. package/package.json +1 -1
  81. package/src/compiler/QueryCompiler.ts +7 -0
  82. package/src/compiler/RawQuery.ts +29 -0
  83. package/src/compiler/postgres/PostgreSqlMethodTransformer.ts +3 -0
  84. package/src/compiler/sql-server/SqlServerSqlMethodTransformer.ts +9 -6
  85. package/src/drivers/base/BaseDriver.ts +28 -10
  86. package/src/drivers/postgres/PostgreSqlDriver.ts +15 -2
  87. package/src/drivers/sql-server/SqlServerDriver.ts +21 -11
  88. package/src/eternity/ActivitySuspendedError.ts +8 -1
  89. package/src/eternity/EternityContext.ts +69 -6
  90. package/src/eternity/EternityStorage.ts +79 -19
  91. package/src/eternity/Workflow.ts +51 -11
  92. package/src/migrations/postgres/PostgresAutomaticMigrations.ts +5 -5
  93. package/src/migrations/sql-server/SqlServerAutomaticMigrations.ts +5 -5
  94. package/src/model/EntityContext.ts +9 -3
  95. package/src/model/EntityQuery.ts +3 -3
  96. package/src/model/verification/VerificationSession.ts +1 -1
  97. package/src/query/ast/ExpressionToSql.ts +22 -20
  98. package/src/query/ast/Expressions.ts +4 -0
  99. package/src/sql/ISql.ts +3 -0
  100. package/src/tests/drivers/postgres/connection-test.ts +1 -1
  101. package/src/tests/eternity/child-tests.ts +119 -0
  102. package/src/tests/eternity/eternity-tests.ts +1 -0
  103. package/src/tests/model/createContext.ts +2 -2
@@ -1,6 +1,6 @@
1
1
  import { IColumn } from "../../decorators/IColumn.js";
2
2
  import { IIndex } from "../../decorators/IIndex.js";
3
- import { BaseDriver } from "../../drivers/base/BaseDriver.js";
3
+ import { BaseConnection, BaseDriver } from "../../drivers/base/BaseDriver.js";
4
4
  import { SqlServerLiteral } from "../../drivers/sql-server/SqlServerLiteral.js";
5
5
  import EntityType from "../../entity-query/EntityType.js";
6
6
  import EntityContext from "../../model/EntityContext.js";
@@ -16,7 +16,7 @@ export default class SqlServerAutomaticMigrations extends SqlServerMigrations {
16
16
  const nonKeyColumns = type.nonKeys;
17
17
  const keys = type.keys;
18
18
 
19
- const driver = context.driver;
19
+ const driver = context.connection;
20
20
 
21
21
  await this.createTable(driver, type, keys);
22
22
 
@@ -43,7 +43,7 @@ export default class SqlServerAutomaticMigrations extends SqlServerMigrations {
43
43
  }
44
44
  }
45
45
 
46
- async createColumns(driver: BaseDriver, type: EntityType, nonKeyColumns: IColumn[]) {
46
+ async createColumns(driver: BaseConnection, type: EntityType, nonKeyColumns: IColumn[]) {
47
47
 
48
48
  const name = type.schema
49
49
  ? type.schema + "." + type.name
@@ -70,7 +70,7 @@ export default class SqlServerAutomaticMigrations extends SqlServerMigrations {
70
70
 
71
71
  }
72
72
 
73
- async createTable(driver: BaseDriver, type: EntityType, keys: IColumn[]) {
73
+ async createTable(driver: BaseConnection, type: EntityType, keys: IColumn[]) {
74
74
 
75
75
  const name = type.schema
76
76
  ? type.schema + "." + type.name
@@ -102,7 +102,7 @@ export default class SqlServerAutomaticMigrations extends SqlServerMigrations {
102
102
  }
103
103
 
104
104
  async migrateIndex(context: EntityContext, index: IIndex, type: EntityType) {
105
- const driver = context.driver;
105
+ const driver = context.connection;
106
106
  const name = type.schema
107
107
  ? type.schema + "." + type.name
108
108
  : type.name;
@@ -1,4 +1,4 @@
1
- import { BaseDriver } from "../drivers/base/BaseDriver.js";
1
+ import { BaseConnection, BaseDriver } from "../drivers/base/BaseDriver.js";
2
2
  import ChangeSet from "./changes/ChangeSet.js";
3
3
  import EntityModel from "./EntityModel.js";
4
4
  import { Expression } from "../query/ast/Expressions.js";
@@ -28,8 +28,14 @@ export default class EntityContext {
28
28
  return this[isChanging];
29
29
  }
30
30
 
31
+ public get connection() {
32
+ return this._connection ??= this.driver.newConnection();
33
+ }
34
+
31
35
  private postSaveChangesQueue: { task: () => any, order: number }[];
32
36
 
37
+ private _connection: BaseConnection;
38
+
33
39
  constructor(
34
40
  @Inject
35
41
  public driver: BaseDriver,
@@ -180,7 +186,7 @@ export default class EntityContext {
180
186
  }
181
187
 
182
188
  protected async saveChangesWithoutEvents(signal: AbortSignal) {
183
- return this.driver.runInTransaction(async () => {
189
+ return this.connection.runInTransaction(async () => {
184
190
  const copy = Array.from(this.changeSet.getChanges()) as ChangeEntry[];
185
191
  for (const iterator of copy) {
186
192
  switch (iterator.status) {
@@ -212,7 +218,7 @@ export default class EntityContext {
212
218
 
213
219
  private async executeExpression(expression: Expression, signal: AbortSignal) {
214
220
  const { text, values } = this.driver.compiler.compileExpression(null, expression);
215
- const r = await this.driver.executeQuery({ text, values }, signal);
221
+ const r = await this.connection.executeQuery({ text, values }, signal);
216
222
  return r.rows?.[0];
217
223
  }
218
224
 
@@ -93,7 +93,7 @@ export default class EntityQuery<T = any>
93
93
  signal?.throwIfAborted();
94
94
 
95
95
  query = this.context.driver.compiler.compileExpression(this, this.selectStatement);
96
- const reader = await this.context.driver.executeReader(query, signal);
96
+ const reader = await this.context.connection.executeReader(query, signal);
97
97
  scope.register(reader);
98
98
  for await (const iterator of reader.next(10, signal)) {
99
99
  if (type) {
@@ -120,7 +120,7 @@ export default class EntityQuery<T = any>
120
120
  let reader: IDbReader;
121
121
  try {
122
122
  query = this.context.driver.compiler.compileExpression(this, select);
123
- reader = await this.context.driver.executeReader(query, signal);
123
+ reader = await this.context.connection.executeReader(query, signal);
124
124
  for await (const iterator of reader.next(10, signal)) {
125
125
  const item = select.model?.map(iterator) ?? iterator;
126
126
  const entry = this.context.changeSet.getEntry(item, item);
@@ -200,7 +200,7 @@ export default class EntityQuery<T = any>
200
200
  let query;
201
201
  try {
202
202
  query = this.context.driver.compiler.compileExpression(nq, select);
203
- const reader = await this.context.driver.executeReader(query);
203
+ const reader = await this.context.connection.executeReader(query);
204
204
  scope.register(reader);
205
205
  for await (const iterator of reader.next()) {
206
206
  return iterator.c1 as number;
@@ -152,7 +152,7 @@ export default class VerificationSession {
152
152
  const logger = ServiceProvider.resolve(this.context, Logger);
153
153
  const session = logger.newSession();
154
154
  try {
155
- const { rows: [ { error }]} = await this.context.driver.executeQuery(query);
155
+ const { rows: [ { error }]} = await this.context.connection.executeQuery(query);
156
156
  if (error) {
157
157
  session.error(`Failed executing ${query.text}\n[${query.values.join(",")}]\n${error?.stack ?? error}`);
158
158
  EntityAccessError.throw(error);
@@ -239,7 +239,7 @@ export default class ExpressionToSql extends Visitor<ITextQuery> {
239
239
  }
240
240
 
241
241
  if (identifier?.value === "Sql") {
242
- const argList = e.arguments.map((x) => this.visit(x));
242
+ const argList = e.arguments?.map((x) => this.visit(x)) ?? [];
243
243
  const transformedCallee = this.compiler.sqlMethodTransformer(this.compiler, chain, argList as any[]);
244
244
  if (transformedCallee) {
245
245
  return prepare `${transformedCallee}`;
@@ -269,27 +269,29 @@ export default class ExpressionToSql extends Visitor<ITextQuery> {
269
269
  const propertyChain = this.getPropertyChain(me);
270
270
  if (propertyChain) {
271
271
  const { parameter, identifier, chain } = propertyChain;
272
- if (parameter === this.root) {
273
- // we have a parameter...
274
- return [(p) => p[chain[0]]];
275
- }
276
- if (parameter.value) {
277
- const value = parameter.value;
278
- return [() => value[chain[0]]];
279
- }
280
- const scope = this.scope.get(parameter);
281
- if (scope.isRuntimeParam) {
282
- return [(p) => p[chain[0]]];
283
- }
284
- const name = this.scope.nameOf(parameter);
272
+ if (parameter) {
273
+ if (parameter === this.root) {
274
+ // we have a parameter...
275
+ return [(p) => p[chain[0]]];
276
+ }
277
+ if (parameter.value) {
278
+ const value = parameter.value;
279
+ return [() => value[chain[0]]];
280
+ }
281
+ const scope = this.scope.get(parameter);
282
+ if (scope.isRuntimeParam) {
283
+ return [(p) => p[chain[0]]];
284
+ }
285
+ const name = this.scope.nameOf(parameter);
285
286
 
286
- // need to change name as per naming convention here...
287
- const namingConvention = this.compiler.namingConvention;
288
- if (scope.model && namingConvention) {
289
- chain[0] = namingConvention(chain[0]);
290
- }
287
+ // need to change name as per naming convention here...
288
+ const namingConvention = this.compiler.namingConvention;
289
+ if (scope.model && namingConvention) {
290
+ chain[0] = namingConvention(chain[0]);
291
+ }
291
292
 
292
- return [ QueryParameter.create(() => name) , "." , chain.join(".")];
293
+ return [ QueryParameter.create(() => name) , "." , chain.join(".")];
294
+ }
293
295
  }
294
296
 
295
297
  const { target, computed, property } = me;
@@ -73,6 +73,10 @@ export abstract class Expression {
73
73
  return BinaryExpression.create({ left, right, operator: "="});
74
74
  }
75
75
 
76
+ static assign(left: Expression, right: Expression) {
77
+ return BinaryExpression.create({ left, right, operator: "="});
78
+ }
79
+
76
80
  static create<T extends Expression>(this: IClassOf<T>, p: Partial<Omit<T, "type">>) {
77
81
  (p as any).type = (this as any).name;
78
82
  Object.setPrototypeOf(p, this.prototype);
package/src/sql/ISql.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import DateTime from "../types/DateTime.js";
2
+
1
3
  export interface ISql {
2
4
 
3
5
  in<T>(a: T, array: T[]): boolean;
@@ -55,6 +57,7 @@ export interface ISql {
55
57
  },
56
58
 
57
59
  date: {
60
+ now(): DateTime,
58
61
  yearOf(d: Date): number;
59
62
  monthOf(d: Date): number;
60
63
  dayOf(d: Date): number;
@@ -9,7 +9,7 @@ export default async function (this: TestConfig) {
9
9
  return;
10
10
  }
11
11
 
12
- const connection = this.driver;
12
+ const connection = this.driver.newConnection();
13
13
 
14
14
  await connection.ensureDatabase();
15
15
  // create table...
@@ -0,0 +1,119 @@
1
+ import assert from "assert";
2
+ import Inject, { Register, RegisterSingleton, ServiceProvider } from "../../di/di.js";
3
+ import EternityContext from "../../eternity/EternityContext.js";
4
+ import Workflow, { Activity, UniqueActivity } from "../../eternity/Workflow.js";
5
+ import WorkflowClock from "../../eternity/WorkflowClock.js";
6
+ import DateTime from "../../types/DateTime.js";
7
+ import { TestConfig } from "../TestConfig.js";
8
+ import { BaseDriver } from "../../drivers/base/BaseDriver.js";
9
+ import EternityStorage from "../../eternity/EternityStorage.js";
10
+ import TimeSpan from "../../types/TimeSpan.js";
11
+ import sleep from "../../common/sleep.js";
12
+
13
+ class MockClock extends WorkflowClock {
14
+
15
+ public get utcNow(): DateTime {
16
+ return this.time;
17
+ }
18
+
19
+ public set utcNow(v: DateTime) {
20
+ this.time = v;
21
+ }
22
+
23
+ private time: DateTime = DateTime.utcNow;
24
+
25
+ public add(ts: TimeSpan) {
26
+ this.time = this.time.add(ts);
27
+ return this;
28
+ }
29
+ }
30
+
31
+ @RegisterSingleton
32
+ class CallTracker {
33
+ track: number = 0;
34
+ }
35
+
36
+ class ChildWorkflow extends Workflow<[string, string], string> {
37
+
38
+ async run() {
39
+ await this.delay(TimeSpan.fromSeconds(30));
40
+ return await this.add("Name:", this.input);
41
+ }
42
+
43
+ @UniqueActivity
44
+ async add(a: string, b: string[], @Inject tracker?: CallTracker) {
45
+ tracker.track++;
46
+ return a + " " + b.join(" ");
47
+ }
48
+ }
49
+
50
+ class ParentWorkflow extends Workflow<string, string> {
51
+
52
+ public async run(): Promise<any> {
53
+ const all = await this.all([
54
+ this.runChild(ChildWorkflow, [this.input, "1"]),
55
+ this.runChild(ChildWorkflow, [this.input, "2"])
56
+ ]);
57
+
58
+ return all.join(",");
59
+ }
60
+
61
+ }
62
+
63
+ export default async function(this: TestConfig) {
64
+
65
+ const mockClock = new MockClock();
66
+
67
+ const tracker = new CallTracker();
68
+
69
+ const scope = new ServiceProvider();
70
+ scope.add(WorkflowClock, mockClock);
71
+ scope.add(BaseDriver, this.driver);
72
+ scope.add(CallTracker, tracker);
73
+ const storage = new EternityStorage(this.driver, mockClock);
74
+ scope.add(EternityStorage, storage);
75
+
76
+ const c = new EternityContext(storage);
77
+ scope.add(EternityContext, c);
78
+
79
+ // this is an important step
80
+ c.register(ChildWorkflow);
81
+ c.register(ParentWorkflow);
82
+
83
+ await storage.seed();
84
+
85
+ const id = await c.queue(ParentWorkflow, "a");
86
+
87
+ mockClock.add(TimeSpan.fromSeconds(15));
88
+
89
+ await c.processQueueOnce();
90
+
91
+ assert.equal(0, tracker.track);
92
+
93
+ mockClock.add(TimeSpan.fromSeconds(20));
94
+
95
+ await c.processQueueOnce();
96
+
97
+ mockClock.add(TimeSpan.fromSeconds(20));
98
+
99
+ await c.processQueueOnce();
100
+
101
+ mockClock.add(TimeSpan.fromSeconds(20));
102
+
103
+ await c.processQueueOnce();
104
+
105
+ assert.notEqual(0, tracker.track);
106
+
107
+ await c.processQueueOnce();
108
+
109
+ mockClock.add(TimeSpan.fromSeconds(5));
110
+
111
+ await c.processQueueOnce();
112
+ mockClock.add(TimeSpan.fromSeconds(5));
113
+ await c.processQueueOnce();
114
+ mockClock.add(TimeSpan.fromSeconds(5));
115
+ await c.processQueueOnce();
116
+
117
+ const r = await storage.get(id);
118
+ assert.equal("done", r.state);
119
+ }
@@ -106,4 +106,5 @@ export default async function (this: TestConfig) {
106
106
 
107
107
  // throw new Error("Preserve");
108
108
 
109
+
109
110
  }
@@ -11,9 +11,9 @@ export async function createContext(driver: BaseDriver) {
11
11
  Object.setPrototypeOf(copy, Object.getPrototypeOf(driver));
12
12
  const context = new ShoppingContext(copy);
13
13
 
14
- await context.driver.ensureDatabase();
14
+ await context.connection.ensureDatabase();
15
15
 
16
- await context.driver.automaticMigrations().migrate(context);
16
+ await context.connection.automaticMigrations().migrate(context);
17
17
 
18
18
  await seed(context);
19
19