@entity-access/entity-access 1.0.26 → 1.0.28

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 (71) hide show
  1. package/dist/common/EntityAccessError.d.ts +3 -1
  2. package/dist/common/EntityAccessError.d.ts.map +1 -1
  3. package/dist/common/EntityAccessError.js +8 -1
  4. package/dist/common/EntityAccessError.js.map +1 -1
  5. package/dist/common/ErrorModel.d.ts +13 -0
  6. package/dist/common/ErrorModel.d.ts.map +1 -0
  7. package/dist/common/ErrorModel.js +17 -0
  8. package/dist/common/ErrorModel.js.map +1 -0
  9. package/dist/decorators/IColumn.d.ts +5 -0
  10. package/dist/decorators/IColumn.d.ts.map +1 -1
  11. package/dist/decorators/IIndex.d.ts +25 -0
  12. package/dist/decorators/IIndex.d.ts.map +1 -0
  13. package/dist/decorators/IIndex.js +2 -0
  14. package/dist/decorators/IIndex.js.map +1 -0
  15. package/dist/decorators/Index.d.ts +4 -0
  16. package/dist/decorators/Index.d.ts.map +1 -0
  17. package/dist/decorators/Index.js +27 -0
  18. package/dist/decorators/Index.js.map +1 -0
  19. package/dist/drivers/postgres/PostgreSqlDriver.js +1 -1
  20. package/dist/drivers/postgres/PostgreSqlDriver.js.map +1 -1
  21. package/dist/drivers/sql-server/SqlServerDriver.js +1 -1
  22. package/dist/drivers/sql-server/SqlServerDriver.js.map +1 -1
  23. package/dist/entity-query/EntityType.d.ts +2 -0
  24. package/dist/entity-query/EntityType.d.ts.map +1 -1
  25. package/dist/entity-query/EntityType.js +1 -0
  26. package/dist/entity-query/EntityType.js.map +1 -1
  27. package/dist/migrations/Migrations.d.ts +7 -1
  28. package/dist/migrations/Migrations.d.ts.map +1 -1
  29. package/dist/migrations/Migrations.js +11 -0
  30. package/dist/migrations/Migrations.js.map +1 -1
  31. package/dist/migrations/postgres/PostgresAutomaticMigrations.d.ts +3 -1
  32. package/dist/migrations/postgres/PostgresAutomaticMigrations.d.ts.map +1 -1
  33. package/dist/migrations/postgres/PostgresAutomaticMigrations.js +28 -12
  34. package/dist/migrations/postgres/PostgresAutomaticMigrations.js.map +1 -1
  35. package/dist/migrations/sql-server/SqlServerAutomaticMigrations.d.ts +3 -1
  36. package/dist/migrations/sql-server/SqlServerAutomaticMigrations.d.ts.map +1 -1
  37. package/dist/migrations/sql-server/SqlServerAutomaticMigrations.js +31 -15
  38. package/dist/migrations/sql-server/SqlServerAutomaticMigrations.js.map +1 -1
  39. package/dist/model/changes/ChangeEntry.d.ts.map +1 -1
  40. package/dist/model/changes/ChangeEntry.js +30 -4
  41. package/dist/model/changes/ChangeEntry.js.map +1 -1
  42. package/dist/model/changes/ChangeSet.d.ts.map +1 -1
  43. package/dist/model/changes/ChangeSet.js +6 -1
  44. package/dist/model/changes/ChangeSet.js.map +1 -1
  45. package/dist/tests/model/ShoppingContext.d.ts +1 -0
  46. package/dist/tests/model/ShoppingContext.d.ts.map +1 -1
  47. package/dist/tests/model/ShoppingContext.js +12 -1
  48. package/dist/tests/model/ShoppingContext.js.map +1 -1
  49. package/dist/tests/model/createContext.d.ts.map +1 -1
  50. package/dist/tests/model/createContext.js +10 -2
  51. package/dist/tests/model/createContext.js.map +1 -1
  52. package/dist/tests/security/tests/place-order.js +2 -2
  53. package/dist/tests/security/tests/place-order.js.map +1 -1
  54. package/dist/tsconfig.tsbuildinfo +1 -1
  55. package/package.json +1 -1
  56. package/src/common/EntityAccessError.ts +11 -2
  57. package/src/common/ErrorModel.ts +24 -0
  58. package/src/decorators/IColumn.ts +5 -0
  59. package/src/decorators/IIndex.ts +24 -0
  60. package/src/decorators/Index.ts +42 -0
  61. package/src/drivers/postgres/PostgreSqlDriver.ts +1 -1
  62. package/src/drivers/sql-server/SqlServerDriver.ts +1 -1
  63. package/src/entity-query/EntityType.ts +3 -0
  64. package/src/migrations/Migrations.ts +18 -1
  65. package/src/migrations/postgres/PostgresAutomaticMigrations.ts +30 -14
  66. package/src/migrations/sql-server/SqlServerAutomaticMigrations.ts +33 -17
  67. package/src/model/changes/ChangeEntry.ts +33 -4
  68. package/src/model/changes/ChangeSet.ts +6 -1
  69. package/src/tests/model/ShoppingContext.ts +9 -0
  70. package/src/tests/model/createContext.ts +10 -2
  71. package/src/tests/security/tests/place-order.ts +2 -2
@@ -1,4 +1,5 @@
1
1
  import { IColumn } from "../../decorators/IColumn.js";
2
+ import { IIndex } from "../../decorators/IIndex.js";
2
3
  import { BaseDriver } from "../../drivers/base/BaseDriver.js";
3
4
  import { SqlServerLiteral } from "../../drivers/sql-server/SqlServerLiteral.js";
4
5
  import EntityType from "../../entity-query/EntityType.js";
@@ -21,27 +22,21 @@ export default class SqlServerAutomaticMigrations extends SqlServerMigrations {
21
22
 
22
23
  await this.createColumns(driver, type, nonKeyColumns);
23
24
 
24
- await this.createIndexes(driver, type, nonKeyColumns.filter((x) => x.fkRelation && !x.fkRelation?.dotNotCreateIndex));
25
+ await this.createIndexes(context, type, nonKeyColumns.filter((x) => x.fkRelation && !x.fkRelation?.dotNotCreateIndex));
25
26
 
26
27
  }
27
28
 
28
- async createIndexes(driver: BaseDriver, type: EntityType, fkColumns: IColumn[]) {
29
-
30
- const name = type.schema
31
- ? SqlServerLiteral.quotedLiteral(type.schema) + "." + SqlServerLiteral.quotedLiteral(type.name)
32
- : SqlServerLiteral.quotedLiteral(type.name);
33
-
29
+ async createIndexes(context: EntityContext, type: EntityType, fkColumns: IColumn[]) {
34
30
  for (const iterator of fkColumns) {
35
- const indexName = SqlServerLiteral.quotedLiteral(`IX_${type.name}_${iterator.columnName}`);
36
- const columnName = SqlServerLiteral.quotedLiteral(iterator.columnName);
37
- let query = `IF NOT EXISTS(SELECT * FROM sys.indexes WHERE name = '${indexName}' AND object_id = OBJECT_ID('${name}'))
38
- BEGIN
39
- CREATE INDEX ${indexName} ON ${name} ( ${columnName})`;
40
- if (iterator.nullable !== true) {
41
- query += ` WHERE (${columnName} is not null)`;
42
- }
43
- query += `END`;
44
- await driver.executeQuery(query);
31
+ const filter = iterator.nullable
32
+ ? `${ SqlServerLiteral.quotedLiteral(iterator.columnName)} IS NOT NULL`
33
+ : "";
34
+ const indexDef: IIndex = {
35
+ name: `IX_${type.name}_${iterator.columnName}`,
36
+ columns: [{ name: iterator.columnName, descending: iterator.indexOrder !== "ascending"}],
37
+ filter
38
+ };
39
+ await this.migrateIndex(context, indexDef, type);
45
40
  }
46
41
  }
47
42
 
@@ -101,5 +96,26 @@ export default class SqlServerAutomaticMigrations extends SqlServerMigrations {
101
96
 
102
97
  }
103
98
 
99
+ async migrateIndex(context: EntityContext, index: IIndex, type: EntityType) {
100
+ const driver = context.driver;
101
+ const name = type.schema
102
+ ? SqlServerLiteral.quotedLiteral(type.schema) + "." + SqlServerLiteral.quotedLiteral(type.name)
103
+ : SqlServerLiteral.quotedLiteral(type.name);
104
+ const indexName = SqlServerLiteral.quotedLiteral(index.name);
105
+ const columns = [];
106
+ for (const column of index.columns) {
107
+ const columnName = SqlServerLiteral.quotedLiteral(column.name);
108
+ columns.push(`${columnName} ${column.descending ? "DESC" : "ASC"}`);
109
+ }
110
+ let query = `IF NOT EXISTS(SELECT * FROM sys.indexes WHERE name = '${indexName}' AND object_id = OBJECT_ID('${name}'))
111
+ BEGIN
112
+ CREATE ${index.unique ? "UNIQUE" : ""} INDEX ${indexName} ON ${name} ( ${columns.join(", ")})`;
113
+ if (index.filter) {
114
+ query += ` WHERE (${index.filter})`;
115
+ }
116
+ query += `\nEND`;
117
+ await driver.executeQuery(query);
118
+ }
119
+
104
120
 
105
121
  }
@@ -49,12 +49,36 @@ export default class ChangeEntry implements IChanges {
49
49
  return;
50
50
  }
51
51
 
52
- const { type: { columns }, entity, original } = this;
52
+ const { type: { columns, keys }, entity } = this;
53
+ let { original } = this;
53
54
 
54
55
  if (original === void 0) {
55
- this.status = "inserted";
56
- this.detectDependencies();
57
- return;
56
+
57
+ // check if all keys are set or not...
58
+
59
+ let keysSet = true;
60
+ let autoGenerate = false;
61
+ for (const iterator of keys) {
62
+ autoGenerate ||= iterator.autoGenerate;
63
+ if(entity[iterator.name] === void 0) {
64
+ keysSet = false;
65
+ }
66
+ }
67
+
68
+ if (keysSet) {
69
+ if (!autoGenerate) {
70
+ this.status = "inserted";
71
+ this.detectDependencies();
72
+ return;
73
+ }
74
+ } else if (autoGenerate) {
75
+ this.status = "inserted";
76
+ this.detectDependencies();
77
+ return;
78
+ }
79
+
80
+ this.original = { ... entity };
81
+ original = this.original;
58
82
  }
59
83
 
60
84
  this.detectDependencies();
@@ -133,6 +157,11 @@ export default class ChangeEntry implements IChanges {
133
157
  // if related has key defined.. set it...
134
158
  const rKey = iterator.relatedEntity.keys[0];
135
159
 
160
+ // lets set the prototype...
161
+ const prototype = iterator.relatedTypeClass.prototype;
162
+ if (Object.getPrototypeOf(related) !== prototype) {
163
+ Object.setPrototypeOf(related, prototype);
164
+ }
136
165
  const relatedChanges = this.changeSet.getEntry(related);
137
166
 
138
167
  const keyValue = related[rKey.name];
@@ -1,3 +1,4 @@
1
+ import EntityAccessError from "../../common/EntityAccessError.js";
1
2
  import SchemaRegistry from "../../decorators/SchemaRegistry.js";
2
3
  import EntityContext from "../EntityContext.js";
3
4
  import IdentityService, { identityMapSymbol } from "../identity/IdentityService.js";
@@ -47,7 +48,11 @@ export default class ChangeSet {
47
48
  if (entry) {
48
49
  return entry;
49
50
  }
50
- const type = SchemaRegistry.model(Object.getPrototypeOf(entity).constructor);
51
+ const c = Object.getPrototypeOf(entity).constructor;
52
+ if (c === Object) {
53
+ throw new EntityAccessError("Entity type not set");
54
+ }
55
+ const type = SchemaRegistry.model(c);
51
56
  const jsonKey = IdentityService.getIdentity(entity);
52
57
  if (jsonKey) {
53
58
  const existing = this.identityMap.get(jsonKey);
@@ -2,6 +2,7 @@ import EntityContext from "../../model/EntityContext.js";
2
2
  import Column from "../../decorators/Column.js";
3
3
  import { RelateTo } from "../../decorators/Relate.js";
4
4
  import Table from "../../decorators/Table.js";
5
+ import Index from "../../decorators/Index.js";
5
6
 
6
7
  export const statusPublished = "published";
7
8
 
@@ -24,6 +25,11 @@ export class ShoppingContext extends EntityContext {
24
25
  }
25
26
 
26
27
  @Table("Users")
28
+ @Index({
29
+ name: "IX_Unique_Users",
30
+ columns: [(x) => x.userName],
31
+ unique: true
32
+ })
27
33
  export class User {
28
34
 
29
35
  @Column({ key: true , autoGenerate: true, dataType: "BigInt" })
@@ -32,6 +38,9 @@ export class User {
32
38
  @Column({})
33
39
  public dateCreated: Date;
34
40
 
41
+ @Column({ dataType: "Char", length: 200 })
42
+ public userName: string;
43
+
35
44
  public ownedProducts: Product[];
36
45
 
37
46
  public orders: Order[];
@@ -17,6 +17,7 @@ export async function createContext(driver: BaseDriver) {
17
17
 
18
18
  await seed(context);
19
19
 
20
+ driver.connectionString.database = context.driver.connectionString.database;
20
21
  return context;
21
22
 
22
23
  }
@@ -29,9 +30,15 @@ async function seed(context: ShoppingContext) {
29
30
  const now = new Date();
30
31
 
31
32
  // add admin user...
32
- context.users.add({ dateCreated: new Date()});
33
+ context.users.add({
34
+ userName: "admin",
35
+ dateCreated: new Date()
36
+ });
33
37
  // add seller
34
- const seller = context.users.add({ dateCreated: new Date()});
38
+ const seller = context.users.add({
39
+ userName: "self",
40
+ dateCreated: new Date()
41
+ });
35
42
 
36
43
  addHeadPhones(context, now, seller);
37
44
 
@@ -45,6 +52,7 @@ async function seed(context: ShoppingContext) {
45
52
  const productPrice = product.prices[0];
46
53
 
47
54
  const user = context.users.add({
55
+ userName: "customer1",
48
56
  dateCreated: new Date(),
49
57
  orders: [
50
58
  context.orders.add({
@@ -94,11 +94,11 @@ async function addNewOrder(this: TestConfig, customer: User, userID?) {
94
94
 
95
95
  async function createUser(config: TestConfig) {
96
96
  const context = await createContext(config.driver);
97
- config.driver.connectionString.database = context.driver.connectionString.database;
98
97
  const user = context.users.add({
98
+ userName: "customer",
99
99
  dateCreated: new Date()
100
100
  });
101
101
  await context.saveChanges();
102
- return user;
102
+ return { ... user };
103
103
  }
104
104