@entity-access/entity-access 1.0.488 → 1.0.490

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 (41) hide show
  1. package/dist/common/IColumnSchema.d.ts +2 -0
  2. package/dist/common/IColumnSchema.d.ts.map +1 -1
  3. package/dist/drivers/base/BaseDriver.d.ts +3 -2
  4. package/dist/drivers/base/BaseDriver.d.ts.map +1 -1
  5. package/dist/drivers/base/BaseDriver.js.map +1 -1
  6. package/dist/drivers/postgres/PostgreSqlDriver.d.ts.map +1 -1
  7. package/dist/drivers/postgres/PostgreSqlDriver.js +8 -7
  8. package/dist/drivers/postgres/PostgreSqlDriver.js.map +1 -1
  9. package/dist/drivers/sql-server/SqlServerDriver.d.ts +3 -2
  10. package/dist/drivers/sql-server/SqlServerDriver.d.ts.map +1 -1
  11. package/dist/drivers/sql-server/SqlServerDriver.js +7 -6
  12. package/dist/drivers/sql-server/SqlServerDriver.js.map +1 -1
  13. package/dist/migrations/ExistingSchema.d.ts +9 -0
  14. package/dist/migrations/ExistingSchema.d.ts.map +1 -0
  15. package/dist/migrations/ExistingSchema.js +31 -0
  16. package/dist/migrations/ExistingSchema.js.map +1 -0
  17. package/dist/migrations/Migrations.d.ts +9 -2
  18. package/dist/migrations/Migrations.d.ts.map +1 -1
  19. package/dist/migrations/Migrations.js +16 -2
  20. package/dist/migrations/Migrations.js.map +1 -1
  21. package/dist/migrations/postgres/PostgresAutomaticMigrations.d.ts +1 -1
  22. package/dist/migrations/postgres/PostgresAutomaticMigrations.d.ts.map +1 -1
  23. package/dist/migrations/postgres/PostgresAutomaticMigrations.js +13 -8
  24. package/dist/migrations/postgres/PostgresAutomaticMigrations.js.map +1 -1
  25. package/dist/migrations/sql-server/SqlServerAutomaticMigrations.d.ts +1 -1
  26. package/dist/migrations/sql-server/SqlServerAutomaticMigrations.d.ts.map +1 -1
  27. package/dist/migrations/sql-server/SqlServerAutomaticMigrations.js +13 -8
  28. package/dist/migrations/sql-server/SqlServerAutomaticMigrations.js.map +1 -1
  29. package/dist/tsconfig.tsbuildinfo +1 -1
  30. package/dist/workflows/WorkflowStorage.js +1 -1
  31. package/dist/workflows/WorkflowStorage.js.map +1 -1
  32. package/package.json +1 -1
  33. package/src/common/IColumnSchema.ts +2 -0
  34. package/src/drivers/base/BaseDriver.ts +3 -2
  35. package/src/drivers/postgres/PostgreSqlDriver.ts +9 -7
  36. package/src/drivers/sql-server/SqlServerDriver.ts +8 -6
  37. package/src/migrations/ExistingSchema.ts +39 -0
  38. package/src/migrations/Migrations.ts +25 -4
  39. package/src/migrations/postgres/PostgresAutomaticMigrations.ts +16 -10
  40. package/src/migrations/sql-server/SqlServerAutomaticMigrations.ts +17 -11
  41. package/src/workflows/WorkflowStorage.ts +1 -1
@@ -6,6 +6,7 @@ import QueryCompiler from "../../compiler/QueryCompiler.js";
6
6
  import EntityType from "../../entity-query/EntityType.js";
7
7
  import Migrations from "../../migrations/Migrations.js";
8
8
  import PostgresAutomaticMigrations from "../../migrations/postgres/PostgresAutomaticMigrations.js";
9
+ import EntityContext from "../../model/EntityContext.js";
9
10
  import DateTime from "../../types/DateTime.js";
10
11
  import { BaseConnection, BaseDriver, EntityTransaction, IDbConnectionString, IDbReader, IQuery, toQuery } from "../base/BaseDriver.js";
11
12
  import pg from "pg";
@@ -215,11 +216,11 @@ class PostgreSqlConnection extends BaseConnection {
215
216
  }
216
217
 
217
218
 
218
- public automaticMigrations(): Migrations {
219
- return new PostgresAutomaticMigrations(this.compiler);
219
+ public automaticMigrations(context: EntityContext): Migrations {
220
+ return new PostgresAutomaticMigrations(context);
220
221
  }
221
222
 
222
- async getColumnSchema(schema: string, table: string): Promise<IColumnSchema[]> {
223
+ async getColumnSchema(schema: string): Promise<IColumnSchema[]> {
223
224
  const text = `
224
225
  select
225
226
  column_name as "columnName",
@@ -242,11 +243,12 @@ class PostgreSqlConnection extends BaseConnection {
242
243
  else null end as "identity",
243
244
  case
244
245
  when is_generated = 'YES' then '() => 1'
245
- else null end as "computed"
246
+ else null end as "computed",
247
+ table_name as "ownerName",
248
+ 'table' as "ownerType"
246
249
  from information_schema.columns
247
- where table_schema = $1
248
- and table_name = $2`;
249
- const r = await this.executeQuery({ text, values: [ schema, table ]});
250
+ where table_schema = $1`;
251
+ const r = await this.executeQuery({ text, values: [ schema ]});
250
252
  return r.rows;
251
253
  }
252
254
 
@@ -10,6 +10,7 @@ import TimedCache from "../../common/cache/TimedCache.js";
10
10
  import EntityType from "../../entity-query/EntityType.js";
11
11
  import DateTime from "../../types/DateTime.js";
12
12
  import IColumnSchema from "../../common/IColumnSchema.js";
13
+ import type EntityContext from "../../model/EntityContext.js";
13
14
 
14
15
  export type ISqlServerConnectionString = IDbConnectionString & sql.config;
15
16
 
@@ -128,7 +129,7 @@ export class SqlServerConnection extends BaseConnection {
128
129
  super(driver);
129
130
  }
130
131
 
131
- async getColumnSchema(schema: string, table: string): Promise<IColumnSchema[]> {
132
+ async getColumnSchema(schema: string): Promise<IColumnSchema[]> {
132
133
  const text = `
133
134
  SELECT
134
135
  COLUMN_NAME as [name],
@@ -160,12 +161,13 @@ export class SqlServerConnection extends BaseConnection {
160
161
  WHEN COLUMN_DEFAULT is NULL THEN ''
161
162
  ELSE '() => ' + COLUMN_DEFAULT
162
163
  END as [default],
163
- ColumnProperty(OBJECT_ID(TABLE_SCHEMA+'.'+TABLE_NAME),COLUMN_NAME,'IsComputed') as [computed]
164
+ ColumnProperty(OBJECT_ID(TABLE_SCHEMA+'.'+TABLE_NAME),COLUMN_NAME,'IsComputed') as [computed],
165
+ TABLE_NAME as [ownerName],
166
+ 'table' as [ownerType]
164
167
  FROM INFORMATION_SCHEMA.COLUMNS
165
168
  WHERE TABLE_SCHEMA = $1
166
- AND TABLE_NAME = $2
167
169
  `;
168
- const r = await this.executeQuery({ text, values: [schema, table] });
170
+ const r = await this.executeQuery({ text, values: [schema] });
169
171
  return r.rows;
170
172
  }
171
173
 
@@ -237,8 +239,8 @@ export class SqlServerConnection extends BaseConnection {
237
239
  return value;
238
240
  }
239
241
 
240
- public automaticMigrations(): Migrations {
241
- return new SqlServerAutomaticMigrations(this.sqlQueryCompiler);
242
+ public automaticMigrations(context: EntityContext): Migrations {
243
+ return new SqlServerAutomaticMigrations(context);
242
244
  }
243
245
 
244
246
  protected async createDbTransaction(): Promise<EntityTransaction> {
@@ -0,0 +1,39 @@
1
+ import IColumnSchema from "../common/IColumnSchema.js";
2
+ import type { BaseConnection } from "../drivers/base/BaseDriver.js";
3
+
4
+ export default class ExistingSchema {
5
+
6
+
7
+ public static async getSchema(connection: BaseConnection, schema: string, table: string, caseInsensitive = false) {
8
+ let s = this.cache.get(schema);
9
+ if (!s) {
10
+ const columns = await connection.getColumnSchema(schema);
11
+ s = new ExistingSchema(columns, caseInsensitive);
12
+ this.cache.set(schema, s);
13
+ }
14
+ if (caseInsensitive) {
15
+ table = table.toLowerCase();
16
+ }
17
+ return s.tables.get(table) ?? [];
18
+ }
19
+
20
+ private static cache = new Map<string, ExistingSchema>();
21
+
22
+ public tables = new Map<string,IColumnSchema[]>();
23
+
24
+ constructor(columns: IColumnSchema[], caseInsensitive = false) {
25
+ for (const c of columns) {
26
+ let tableName = c.ownerName;
27
+ if (caseInsensitive) {
28
+ tableName = tableName.toLowerCase();
29
+ }
30
+ let table = this.tables.get(tableName);
31
+ if (!table) {
32
+ table = [];
33
+ this.tables.set(tableName, table);
34
+ }
35
+ table.push(c);
36
+ }
37
+ }
38
+
39
+ }
@@ -1,37 +1,52 @@
1
+ import Logger, { ConsoleLogger } from "../common/Logger.js";
1
2
  import { modelSymbol } from "../common/symbols/symbols.js";
2
3
  import type QueryCompiler from "../compiler/QueryCompiler.js";
3
4
  import ICheckConstraint from "../decorators/ICheckConstraint.js";
4
5
  import { IColumn } from "../decorators/IColumn.js";
5
6
  import type { IForeignKeyConstraint } from "../decorators/IForeignKeyConstraint.js";
6
7
  import type { IIndex } from "../decorators/IIndex.js";
8
+ import type { BaseConnection, IQuery, IQueryResult } from "../drivers/base/BaseDriver.js";
7
9
  import type EntityType from "../entity-query/EntityType.js";
8
10
  import type EntityContext from "../model/EntityContext.js";
9
11
  import type EntityQuery from "../model/EntityQuery.js";
12
+ import ExistingSchema from "./ExistingSchema.js";
10
13
 
11
14
  export default abstract class Migrations {
12
15
 
13
- constructor(protected compiler: QueryCompiler) {}
16
+ logger: Logger;
14
17
 
15
- public async migrate(context: EntityContext , {
18
+ constructor(
19
+ private context: EntityContext,
20
+ private connection: BaseConnection = context.connection,
21
+ protected compiler: QueryCompiler = context.driver.compiler
22
+ ) {
23
+
24
+ }
25
+
26
+ public async migrate({
16
27
  version,
17
28
  name = "default",
18
29
  historyTableName = "migrations",
30
+ log = new ConsoleLogger(false),
19
31
  seed,
20
32
  createIndexForForeignKeys = true
21
33
  }: {
22
34
  version?: string,
23
35
  name?: string,
24
- historyTableName?:
25
- string,
36
+ historyTableName?: string,
37
+ log?: Logger,
26
38
  seed?: (c: EntityContext) => Promise<any>,
27
39
  createIndexForForeignKeys?: boolean
28
40
  } = {} ) {
41
+ const { context } = this;
29
42
  const { model } = context;
43
+ this.logger = log ?? context.logger;
30
44
  const postMigration = [] as (() => Promise<void>)[];
31
45
 
32
46
  if (version) {
33
47
  // check if we have already stored this version...
34
48
  if(await this.hasVersion(context, name, version, historyTableName)) {
49
+ // eslint-disable-next-line no-console
35
50
  console.warn(`Skipping migration, migration already exists for ${version}`);
36
51
  return false;
37
52
  }
@@ -185,4 +200,10 @@ export default abstract class Migrations {
185
200
 
186
201
  abstract migrateCheckConstraint(context: EntityContext, checkConstraint: ICheckConstraint, type: EntityType);
187
202
 
203
+ protected executeQuery(command: IQuery, signal?: AbortSignal): Promise<IQueryResult> {
204
+ const text = typeof command === "string" ? command : command.text;
205
+ this.logger?.log(text);
206
+ return this.connection.executeQuery(command, signal);
207
+ }
208
+
188
209
  }
@@ -5,8 +5,8 @@ import { IForeignKeyConstraint } from "../../decorators/IForeignKeyConstraint.js
5
5
  import { IIndex } from "../../decorators/IIndex.js";
6
6
  import { BaseConnection, BaseDriver } from "../../drivers/base/BaseDriver.js";
7
7
  import EntityType from "../../entity-query/EntityType.js";
8
- import EntityContext from "../../model/EntityContext.js";
9
- import Migrations from "../Migrations.js";
8
+ import type EntityContext from "../../model/EntityContext.js";
9
+ import ExistingSchema from "../ExistingSchema.js";
10
10
  import PostgresMigrations from "./PostgresMigrations.js";
11
11
 
12
12
  export default class PostgresAutomaticMigrations extends PostgresMigrations {
@@ -59,7 +59,7 @@ export default class PostgresAutomaticMigrations extends PostgresMigrations {
59
59
  nonKeyColumns.sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
60
60
  }
61
61
 
62
- const columns = await driver.getColumnSchema(type.schema || "public", type.name);
62
+ const columns = await ExistingSchema.getSchema(driver, type.schema || "public", type.name, true);
63
63
 
64
64
  const columnSet = new Set(columns.map((x) => x.name));
65
65
 
@@ -83,13 +83,19 @@ export default class PostgresAutomaticMigrations extends PostgresMigrations {
83
83
  def += " DEFAULT " + iterator.default;
84
84
  }
85
85
 
86
- await driver.executeQuery(def + ";");
86
+ await this.executeQuery(def + ";");
87
87
  }
88
88
 
89
89
  }
90
90
 
91
91
  async createTable(driver: BaseConnection, type: EntityType, keys: IColumn[]) {
92
92
 
93
+ const columns = await ExistingSchema.getSchema(driver, type.schema || "public", type.name, true);
94
+
95
+ if (columns.length) {
96
+ return;
97
+ }
98
+
93
99
  const name = type.schema
94
100
  ? type.schema + "." + type.name
95
101
  : type.name;
@@ -119,7 +125,7 @@ export default class PostgresAutomaticMigrations extends PostgresMigrations {
119
125
  fields.push(def);
120
126
  }
121
127
 
122
- await driver.executeQuery(`CREATE TABLE IF NOT EXISTS ${name} (${fields.join(",")}
128
+ await this.executeQuery(`CREATE TABLE IF NOT EXISTS ${name} (${fields.join(",")}
123
129
  ,CONSTRAINT PK_${name} PRIMARY KEY (${keys.map((x) => x.columnName).join(",")})
124
130
  )`);
125
131
 
@@ -142,7 +148,7 @@ export default class PostgresAutomaticMigrations extends PostgresMigrations {
142
148
  if (index.filter) {
143
149
  query += ` WHERE (${index.filter})`;
144
150
  }
145
- await driver.executeQuery(query);
151
+ await this.executeQuery(query);
146
152
  }
147
153
 
148
154
  async constraintExists(context: EntityContext, name: string, schema: string, table = "referential_constraints") {
@@ -159,7 +165,7 @@ export default class PostgresAutomaticMigrations extends PostgresMigrations {
159
165
 
160
166
  const driver = context.connection;
161
167
 
162
- const r = await driver.executeQuery({ text, values });
168
+ const r = await this.executeQuery({ text, values });
163
169
  if (r.rows?.length) {
164
170
  return true;
165
171
  }
@@ -218,9 +224,9 @@ export default class PostgresAutomaticMigrations extends PostgresMigrations {
218
224
 
219
225
  await using tx = await driver.createTransaction();
220
226
  if (constraint.clearExisting && prepare) {
221
- await driver.executeQuery(prepare);
227
+ await this.executeQuery(prepare);
222
228
  }
223
- await driver.executeQuery(text);
229
+ await this.executeQuery(text);
224
230
  await tx.commit();
225
231
  } catch (error) {
226
232
  // we will simply ignore this
@@ -245,7 +251,7 @@ export default class PostgresAutomaticMigrations extends PostgresMigrations {
245
251
  const text = `ALTER TABLE ${name} ADD CONSTRAINT ${constraint.name} CHECK (${constraint.filter})`;
246
252
 
247
253
  try {
248
- await driver.executeQuery(text);
254
+ await this.executeQuery(text);
249
255
  } catch (error) {
250
256
  // we will simply ignore this
251
257
  console.warn(`Failed adding constraint ${constraint.name}`);
@@ -3,11 +3,11 @@ import ICheckConstraint from "../../decorators/ICheckConstraint.js";
3
3
  import { IColumn } from "../../decorators/IColumn.js";
4
4
  import { IForeignKeyConstraint } from "../../decorators/IForeignKeyConstraint.js";
5
5
  import { IIndex } from "../../decorators/IIndex.js";
6
- import { BaseConnection, BaseDriver } from "../../drivers/base/BaseDriver.js";
6
+ import { BaseConnection } from "../../drivers/base/BaseDriver.js";
7
7
  import { SqlServerLiteral } from "../../drivers/sql-server/SqlServerLiteral.js";
8
8
  import EntityType from "../../entity-query/EntityType.js";
9
- import EntityContext from "../../model/EntityContext.js";
10
- import Migrations from "../Migrations.js";
9
+ import type EntityContext from "../../model/EntityContext.js";
10
+ import ExistingSchema from "../ExistingSchema.js";
11
11
  import SqlServerMigrations from "./SqlServerMigrations.js";
12
12
 
13
13
  export default class SqlServerAutomaticMigrations extends SqlServerMigrations {
@@ -62,7 +62,7 @@ export default class SqlServerAutomaticMigrations extends SqlServerMigrations {
62
62
  nonKeyColumns.sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
63
63
  }
64
64
 
65
- const columns = await driver.getColumnSchema(type.schema || "dbo", type.name);
65
+ const columns = await ExistingSchema.getSchema(driver, type.schema || "dbo", type.name);
66
66
 
67
67
  const columnSet = new Set(columns.map((x) => x.name.toLowerCase()));
68
68
 
@@ -75,7 +75,7 @@ export default class SqlServerAutomaticMigrations extends SqlServerMigrations {
75
75
 
76
76
  if (iterator.computed) {
77
77
  def += ` AS ${iterator.computed} ${iterator.stored ? "PERSISTED" : ""}`;
78
- await driver.executeQuery(def + ";");
78
+ await this.executeQuery(def + ";");
79
79
  continue;
80
80
  }
81
81
 
@@ -91,13 +91,19 @@ export default class SqlServerAutomaticMigrations extends SqlServerMigrations {
91
91
  if (typeof iterator.default === "string") {
92
92
  def += " DEFAULT " + iterator.default;
93
93
  }
94
- await driver.executeQuery(def + ";");
94
+ await this.executeQuery(def + ";");
95
95
  }
96
96
 
97
97
  }
98
98
 
99
99
  async createTable(driver: BaseConnection, type: EntityType, keys: IColumn[]) {
100
100
 
101
+ const columns = await ExistingSchema.getSchema(driver, type.schema || "public", type.name);
102
+
103
+ if (columns.length) {
104
+ return;
105
+ }
106
+
101
107
  const name = type.schema
102
108
  ? type.schema + "." + type.name
103
109
  : type.name;
@@ -123,7 +129,7 @@ export default class SqlServerAutomaticMigrations extends SqlServerMigrations {
123
129
  fields.push(def);
124
130
  }
125
131
 
126
- await driver.executeQuery(`IF OBJECT_ID(${ SqlServerLiteral.escapeLiteral(name)}) IS NULL BEGIN
132
+ await this.executeQuery(`IF OBJECT_ID(${ SqlServerLiteral.escapeLiteral(name)}) IS NULL BEGIN
127
133
  CREATE TABLE ${name} (${fields.join(",")}
128
134
  , CONSTRAINT PK_${name} PRIMARY KEY(${keys.map((x) => x.quotedColumnName)})
129
135
  );
@@ -149,7 +155,7 @@ export default class SqlServerAutomaticMigrations extends SqlServerMigrations {
149
155
  query += ` WHERE (${index.filter})`;
150
156
  }
151
157
  query += `\nEND`;
152
- await driver.executeQuery(query);
158
+ await this.executeQuery(query);
153
159
  }
154
160
 
155
161
  async constraintExists(context: EntityContext, name: string, schema: string, type: EntityType) {
@@ -164,7 +170,7 @@ export default class SqlServerAutomaticMigrations extends SqlServerMigrations {
164
170
 
165
171
  const driver = context.connection;
166
172
 
167
- const r = await driver.executeQuery(text);
173
+ const r = await this.executeQuery(text);
168
174
  if (r.rows?.length === 0) {
169
175
  if (r.rows["c1"] > 0) {
170
176
  return true;
@@ -215,7 +221,7 @@ export default class SqlServerAutomaticMigrations extends SqlServerMigrations {
215
221
  }
216
222
 
217
223
  try {
218
- await driver.executeQuery(text);
224
+ await this.executeQuery(text);
219
225
  } catch (error) {
220
226
  // we will simply ignore this
221
227
  console.warn(`Failed adding constraint ${constraint.name}`);
@@ -238,7 +244,7 @@ export default class SqlServerAutomaticMigrations extends SqlServerMigrations {
238
244
  const text = `ALTER TABLE ${name} ADD CONSTRAINT ${constraint.name} CHECK (${constraint.filter})`;
239
245
 
240
246
  try {
241
- await driver.executeQuery(text);
247
+ await this.executeQuery(text);
242
248
  } catch (error) {
243
249
  // we will simply ignore this
244
250
  console.warn(`Failed adding constraint ${constraint.name}`);
@@ -234,7 +234,7 @@ export default class WorkflowStorage {
234
234
  async seed(version?) {
235
235
  const db = new WorkflowDbContext(this.driver);
236
236
  await db.connection.ensureDatabase();
237
- await db.connection.automaticMigrations().migrate(db, { version, name: "workflows" });
237
+ await db.connection.automaticMigrations(db).migrate({ log: null, version, name: "workflows" });
238
238
  }
239
239
 
240
240
  }