@proteinjs/db 1.0.15 → 1.0.17

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/.eslintrc.js +20 -0
  2. package/.prettierignore +4 -0
  3. package/.prettierrc +8 -0
  4. package/CHANGELOG.md +16 -26
  5. package/dist/generated/index.js +1 -1
  6. package/dist/generated/index.js.map +1 -1
  7. package/dist/src/Columns.d.ts.map +1 -1
  8. package/dist/src/Columns.js +34 -17
  9. package/dist/src/Columns.js.map +1 -1
  10. package/dist/src/Db.d.ts.map +1 -1
  11. package/dist/src/Db.js +45 -18
  12. package/dist/src/Db.js.map +1 -1
  13. package/dist/src/MigrationRunner.d.ts.map +1 -1
  14. package/dist/src/MigrationRunner.js +15 -7
  15. package/dist/src/MigrationRunner.js.map +1 -1
  16. package/dist/src/QueryBuilderFactory.d.ts.map +1 -1
  17. package/dist/src/QueryBuilderFactory.js +5 -7
  18. package/dist/src/QueryBuilderFactory.js.map +1 -1
  19. package/dist/src/Record.d.ts.map +1 -1
  20. package/dist/src/Record.js +4 -2
  21. package/dist/src/Record.js.map +1 -1
  22. package/dist/src/StatementConfigFactory.d.ts.map +1 -1
  23. package/dist/src/StatementConfigFactory.js +3 -2
  24. package/dist/src/StatementConfigFactory.js.map +1 -1
  25. package/dist/src/Table.d.ts.map +1 -1
  26. package/dist/src/Table.js +6 -3
  27. package/dist/src/Table.js.map +1 -1
  28. package/dist/src/auth/TableAuth.d.ts.map +1 -1
  29. package/dist/src/auth/TableAuth.js +16 -11
  30. package/dist/src/auth/TableAuth.js.map +1 -1
  31. package/dist/src/auth/TableServiceAuth.d.ts.map +1 -1
  32. package/dist/src/auth/TableServiceAuth.js +12 -6
  33. package/dist/src/auth/TableServiceAuth.js.map +1 -1
  34. package/dist/src/reference/Reference.d.ts.map +1 -1
  35. package/dist/src/reference/Reference.js.map +1 -1
  36. package/dist/src/reference/ReferenceArray.d.ts.map +1 -1
  37. package/dist/src/reference/ReferenceArray.js.map +1 -1
  38. package/dist/src/schema/SchemaMetadata.d.ts.map +1 -1
  39. package/dist/src/schema/SchemaMetadata.js +18 -15
  40. package/dist/src/schema/SchemaMetadata.js.map +1 -1
  41. package/dist/src/schema/SchemaOperations.d.ts.map +1 -1
  42. package/dist/src/schema/TableManager.d.ts.map +1 -1
  43. package/dist/src/schema/TableManager.js +24 -9
  44. package/dist/src/schema/TableManager.js.map +1 -1
  45. package/dist/src/serializers/GraphSerializer.d.ts.map +1 -1
  46. package/dist/src/serializers/QueryBuilderSerializer.d.ts.map +1 -1
  47. package/dist/src/serializers/ReferenceArraySerializer.d.ts.map +1 -1
  48. package/dist/src/serializers/ReferenceArraySerializer.js.map +1 -1
  49. package/dist/src/serializers/ReferenceSerializer.d.ts.map +1 -1
  50. package/dist/src/serializers/TableSerializer.d.ts.map +1 -1
  51. package/dist/src/services/DbService.d.ts.map +1 -1
  52. package/dist/src/source/SourceRecord.d.ts.map +1 -1
  53. package/dist/src/source/SourceRecord.js +7 -3
  54. package/dist/src/source/SourceRecord.js.map +1 -1
  55. package/dist/src/source/SourceRecordLoader.d.ts.map +1 -1
  56. package/dist/src/source/SourceRecordLoader.js +11 -4
  57. package/dist/src/source/SourceRecordLoader.js.map +1 -1
  58. package/dist/src/source/SourceRecordRepo.d.ts.map +1 -1
  59. package/dist/src/source/SourceRecordRepo.js.map +1 -1
  60. package/dist/src/tables/MigrationTable.d.ts.map +1 -1
  61. package/dist/src/tables/MigrationTable.js.map +1 -1
  62. package/dist/src/tables/tables.d.ts.map +1 -1
  63. package/dist/src/tables/tables.js.map +1 -1
  64. package/dist/test/CrudTests.d.ts.map +1 -1
  65. package/dist/test/CrudTests.js +13 -4
  66. package/dist/test/CrudTests.js.map +1 -1
  67. package/dist/test/TableManagerTests.d.ts.map +1 -1
  68. package/dist/test/TableManagerTests.js +17 -9
  69. package/dist/test/TableManagerTests.js.map +1 -1
  70. package/generated/index.ts +15 -18
  71. package/index.ts +1 -1
  72. package/jest.config.js +8 -17
  73. package/package.json +48 -43
  74. package/src/Columns.ts +284 -241
  75. package/src/Db.ts +188 -147
  76. package/src/MigrationRunner.ts +24 -10
  77. package/src/QueryBuilderFactory.ts +6 -9
  78. package/src/Record.ts +35 -29
  79. package/src/StatementConfigFactory.ts +14 -16
  80. package/src/Table.ts +91 -88
  81. package/src/auth/TableAuth.ts +37 -27
  82. package/src/auth/TableServiceAuth.ts +11 -9
  83. package/src/opt/moment.ts +1 -1
  84. package/src/reference/Reference.ts +7 -7
  85. package/src/reference/ReferenceArray.ts +8 -8
  86. package/src/schema/SchemaMetadata.ts +84 -64
  87. package/src/schema/SchemaOperations.ts +2 -2
  88. package/src/schema/TableManager.ts +178 -168
  89. package/src/serializers/GraphSerializer.ts +4 -4
  90. package/src/serializers/QueryBuilderSerializer.ts +11 -11
  91. package/src/serializers/ReferenceArraySerializer.ts +12 -8
  92. package/src/serializers/ReferenceSerializer.ts +7 -7
  93. package/src/serializers/TableSerializer.ts +5 -5
  94. package/src/services/DbService.ts +3 -3
  95. package/src/services/MigrationRunnerService.ts +1 -1
  96. package/src/source/SourceRecord.ts +43 -24
  97. package/src/source/SourceRecordLoader.ts +29 -18
  98. package/src/source/SourceRecordRepo.ts +3 -3
  99. package/src/tables/MigrationTable.ts +5 -5
  100. package/src/tables/tables.ts +1 -1
  101. package/test/CrudTests.ts +43 -30
  102. package/test/TableManagerTests.ts +329 -154
  103. package/tsconfig.json +18 -22
package/src/Table.ts CHANGED
@@ -10,117 +10,120 @@ export const isTable = (obj: any) => obj.__serializerId === TableSerializerId;
10
10
  export const getTables = <T extends Record = any>() => SourceRepository.get().objects<Table<T>>('@proteinjs/db/Table');
11
11
 
12
12
  export const tableByName = (name: string) => {
13
- const tables = getTables();
14
- for (let table of tables) {
15
- if (table.name == name)
16
- return table;
17
- }
13
+ const tables = getTables();
14
+ for (const table of tables) {
15
+ if (table.name == name) {
16
+ return table;
17
+ }
18
+ }
18
19
 
19
- throw new Error(`Unable to find table: ${name}`);
20
- }
20
+ throw new Error(`Unable to find table: ${name}`);
21
+ };
21
22
 
22
23
  export const getColumnPropertyName = (table: Table<any>, columnName: string) => {
23
- for (let columnPropertyName in table.columns) {
24
- const column = table.columns[columnPropertyName];
25
- if (column.name == columnName)
26
- return columnPropertyName;
27
- }
24
+ for (const columnPropertyName in table.columns) {
25
+ const column = table.columns[columnPropertyName];
26
+ if (column.name == columnName) {
27
+ return columnPropertyName;
28
+ }
29
+ }
28
30
 
29
- return null;
30
- }
31
+ return null;
32
+ };
31
33
 
32
34
  export const getColumnByName = (table: Table<any>, columnName: string) => {
33
- for (let columnPropertyName in table.columns) {
34
- const column = table.columns[columnPropertyName];
35
- if (column.name == columnName)
36
- return column;
37
- }
35
+ for (const columnPropertyName in table.columns) {
36
+ const column = table.columns[columnPropertyName];
37
+ if (column.name == columnName) {
38
+ return column;
39
+ }
40
+ }
38
41
 
39
- return null;
40
- }
42
+ return null;
43
+ };
41
44
 
42
45
  /**
43
46
  * primary key is `id`
44
47
  */
45
48
  export abstract class Table<T extends Record> implements Loadable, CustomSerializableObject {
46
- public __serializerId = TableSerializerId;
47
- abstract name: string;
48
- abstract columns: Columns<T>;
49
- public indexes: { columns: (keyof T)[], name?: string }[] = [];
50
- /** When records are deleted, delete records having references pointing to deleted records */
51
- public cascadeDeleteReferences: () => { table: string, referenceColumn: string }[] = () => [];
52
- /**
53
- * Options for configuring SourceRecords
54
- * @param doNotDeleteSourceRecordsFromDb if true, the SourceRecordLoader will not delete source records from the db if they no longer exist on the file system
55
- */
56
- public sourceRecordOptions: SourceRecordOptions = {
57
- doNotDeleteSourceRecordsFromDb: false,
58
- };
59
- public auth?: {
60
- db?: TableOperationsAuth,
61
- service?: TableOperationsAuth,
62
- ui?: {
63
- recordTable?: Identity,
64
- recordForm?: Identity,
65
- },
66
- };
49
+ public __serializerId = TableSerializerId;
50
+ abstract name: string;
51
+ abstract columns: Columns<T>;
52
+ public indexes: { columns: (keyof T)[]; name?: string }[] = [];
53
+ /** When records are deleted, delete records having references pointing to deleted records */
54
+ public cascadeDeleteReferences: () => { table: string; referenceColumn: string }[] = () => [];
55
+ /**
56
+ * Options for configuring SourceRecords
57
+ * @param doNotDeleteSourceRecordsFromDb if true, the SourceRecordLoader will not delete source records from the db if they no longer exist on the file system
58
+ */
59
+ public sourceRecordOptions: SourceRecordOptions = {
60
+ doNotDeleteSourceRecordsFromDb: false,
61
+ };
62
+ public auth?: {
63
+ db?: TableOperationsAuth;
64
+ service?: TableOperationsAuth;
65
+ ui?: {
66
+ recordTable?: Identity;
67
+ recordForm?: Identity;
68
+ };
69
+ };
67
70
  }
68
71
 
69
72
  type ExcludeFunctions<T> = {
70
- [P in keyof T as T[P] extends Function ? never : P]: T[P]
71
- }
73
+ [P in keyof T as T[P] extends Function ? never : P]: T[P];
74
+ };
72
75
 
73
76
  type RequiredProps<T> = {
74
- [P in keyof ExcludeFunctions<T>]: ExcludeFunctions<T>[P] extends undefined ? never : P
75
- }[keyof ExcludeFunctions<T>]
77
+ [P in keyof ExcludeFunctions<T>]: ExcludeFunctions<T>[P] extends undefined ? never : P;
78
+ }[keyof ExcludeFunctions<T>];
76
79
 
77
80
  type OptionalProps<T> = {
78
- [P in keyof ExcludeFunctions<T>]: ExcludeFunctions<T>[P] extends undefined ? P : never
79
- }[keyof ExcludeFunctions<T>]
81
+ [P in keyof ExcludeFunctions<T>]: ExcludeFunctions<T>[P] extends undefined ? P : never;
82
+ }[keyof ExcludeFunctions<T>];
80
83
 
81
84
  export type Columns<T> = {
82
- [P in RequiredProps<T>]: Column<T[P], any>
85
+ [P in RequiredProps<T>]: Column<T[P], any>;
83
86
  } & {
84
- [P in OptionalProps<T>]?: Column<T[P] | undefined, any>
85
- }
87
+ [P in OptionalProps<T>]?: Column<T[P] | undefined, any>;
88
+ };
86
89
 
87
90
  export type Column<T, Serialized> = {
88
- name: string,
89
- /**
90
- * Use to rename column, will find column with `oldName` and change it to `name`.
91
- *
92
- * Note: after name change has happened in prod, oldName can be removed.
93
- */
94
- oldName?: string,
95
- options?: ColumnOptions,
96
- serialize?: (fieldValue: T|undefined) => Promise<Serialized|undefined>,
97
- deserialize?: (serializedFieldValue: Serialized) => Promise<T|void>,
98
- beforeDelete?: (table: Table<any>, columnPropertyName: string, records: any[]) => Promise<void>,
99
- }
91
+ name: string;
92
+ /**
93
+ * Use to rename column, will find column with `oldName` and change it to `name`.
94
+ *
95
+ * Note: after name change has happened in prod, oldName can be removed.
96
+ */
97
+ oldName?: string;
98
+ options?: ColumnOptions;
99
+ serialize?: (fieldValue: T | undefined) => Promise<Serialized | undefined>;
100
+ deserialize?: (serializedFieldValue: Serialized) => Promise<T | void>;
101
+ beforeDelete?: (table: Table<any>, columnPropertyName: string, records: any[]) => Promise<void>;
102
+ };
100
103
 
101
104
  export type ColumnOptions = {
102
- unique?: { unique: boolean, indexName?: string },
103
- /**
104
- * The column in the reference table `table` is the primary key of the table (`id` unless otherwise specified in the Table definition)
105
- *
106
- * Note: use a migration to drop or change an existing foreign key
107
- */
108
- references?: { table: string },
109
- nullable?: boolean,
110
- /** Value stored on insert */
111
- defaultValue?: (insertObj: any) => Promise<any>,
112
- /** Value stored on update */
113
- updateValue?: (updateObj: any) => Promise<any>,
114
- /** Add conditions to query; called on every query of this table */
115
- addToQuery?: (qb: QueryBuilder) => Promise<void>,
116
- ui?: {
117
- hidden?: boolean,
118
- },
119
- }
120
-
121
- export type SourceRecordOptions = {
122
- doNotDeleteSourceRecordsFromDb?: boolean,
123
- ui?: {
124
- hideColumns?: boolean,
125
- },
126
- }
105
+ unique?: { unique: boolean; indexName?: string };
106
+ /**
107
+ * The column in the reference table `table` is the primary key of the table (`id` unless otherwise specified in the Table definition)
108
+ *
109
+ * Note: use a migration to drop or change an existing foreign key
110
+ */
111
+ references?: { table: string };
112
+ nullable?: boolean;
113
+ /** Value stored on insert */
114
+ defaultValue?: (insertObj: any) => Promise<any>;
115
+ /** Value stored on update */
116
+ updateValue?: (updateObj: any) => Promise<any>;
117
+ /** Add conditions to query; called on every query of this table */
118
+ addToQuery?: (qb: QueryBuilder) => Promise<void>;
119
+ ui?: {
120
+ hidden?: boolean;
121
+ };
122
+ };
123
+
124
+ export type SourceRecordOptions = {
125
+ doNotDeleteSourceRecordsFromDb?: boolean;
126
+ ui?: {
127
+ hideColumns?: boolean;
128
+ };
129
+ };
@@ -1,60 +1,70 @@
1
- import { UserAuth } from '@proteinjs/user-auth'
2
- import { Table } from '../Table'
1
+ import { UserAuth } from '@proteinjs/user-auth';
2
+ import { Table } from '../Table';
3
3
 
4
4
  /**
5
5
  * @public all users, including guests (do not need to be logged in), do not need any roles
6
6
  * @authenticated - users need to be logged in, do not need any roles
7
7
  * @roles string[] - authenticated users, having at least one of these roles
8
8
  */
9
- export type Identity = 'public'|'authenticated'|string[]
9
+ export type Identity = 'public' | 'authenticated' | string[];
10
10
 
11
11
  /**
12
12
  * These Identities can perform these operations on this table.
13
13
  * If omitted, defaults to requiring the 'admin' role (default deny)
14
14
  */
15
15
  export type TableOperationsAuth = {
16
- all?: Identity,
17
- query?: Identity,
18
- insert?: Identity,
19
- update?: Identity,
20
- delete?: Identity,
21
- }
16
+ all?: Identity;
17
+ query?: Identity;
18
+ insert?: Identity;
19
+ update?: Identity;
20
+ delete?: Identity;
21
+ };
22
22
 
23
23
  /**
24
24
  * Util to check which table operations a user can perform
25
25
  */
26
26
  export class TableAuth {
27
- private canAccess(table: Table<any>, api: 'db'|'service', operation: 'query'|'insert'|'update'|'delete'): boolean {
27
+ private canAccess(
28
+ table: Table<any>,
29
+ api: 'db' | 'service',
30
+ operation: 'query' | 'insert' | 'update' | 'delete'
31
+ ): boolean {
28
32
  const tableAuth = table.auth ? table.auth[api] : undefined;
29
- if (!tableAuth || Object.keys(tableAuth).length == 0)
33
+ if (!tableAuth || Object.keys(tableAuth).length == 0) {
30
34
  return UserAuth.hasRole('admin');
35
+ }
31
36
 
32
- return tableAuth.all === 'public'
33
- || tableAuth[operation] === 'public'
34
- || (tableAuth.all === 'authenticated' && UserAuth.isLoggedIn())
35
- || (tableAuth[operation] === 'authenticated' && UserAuth.isLoggedIn())
36
- || (Array.isArray(tableAuth.all) && UserAuth.hasRoles(tableAuth.all, 'at least one'))
37
- || (Array.isArray(tableAuth[operation]) && UserAuth.hasRoles(tableAuth[operation] as string[], 'at least one'))
38
- ;
37
+ return (
38
+ tableAuth.all === 'public' ||
39
+ tableAuth[operation] === 'public' ||
40
+ (tableAuth.all === 'authenticated' && UserAuth.isLoggedIn()) ||
41
+ (tableAuth[operation] === 'authenticated' && UserAuth.isLoggedIn()) ||
42
+ (Array.isArray(tableAuth.all) && UserAuth.hasRoles(tableAuth.all, 'at least one')) ||
43
+ (Array.isArray(tableAuth[operation]) && UserAuth.hasRoles(tableAuth[operation] as string[], 'at least one'))
44
+ );
39
45
  }
40
46
 
41
- canQuery(table: Table<any>, api: 'db'|'service' = 'db'): void {
42
- if (!this.canAccess(table, api, 'query'))
47
+ canQuery(table: Table<any>, api: 'db' | 'service' = 'db'): void {
48
+ if (!this.canAccess(table, api, 'query')) {
43
49
  throw new Error(`User is not authorized to query table: ${table.name}`);
50
+ }
44
51
  }
45
52
 
46
- canInsert(table: Table<any>, api: 'db'|'service' = 'db'): void {
47
- if (!this.canAccess(table, api, 'insert'))
53
+ canInsert(table: Table<any>, api: 'db' | 'service' = 'db'): void {
54
+ if (!this.canAccess(table, api, 'insert')) {
48
55
  throw new Error(`User is not authorized to insert records into table: ${table.name}`);
56
+ }
49
57
  }
50
58
 
51
- canUpdate(table: Table<any>, api: 'db'|'service' = 'db'): void {
52
- if (!this.canAccess(table, api, 'update'))
59
+ canUpdate(table: Table<any>, api: 'db' | 'service' = 'db'): void {
60
+ if (!this.canAccess(table, api, 'update')) {
53
61
  throw new Error(`User is not authorized to update records in table: ${table.name}`);
62
+ }
54
63
  }
55
64
 
56
- canDelete(table: Table<any>, api: 'db'|'service' = 'db'): void {
57
- if (!this.canAccess(table, api, 'query'))
65
+ canDelete(table: Table<any>, api: 'db' | 'service' = 'db'): void {
66
+ if (!this.canAccess(table, api, 'query')) {
58
67
  throw new Error(`User is not authorized to delete records from table: ${table.name}`);
68
+ }
59
69
  }
60
- }
70
+ }
@@ -7,21 +7,23 @@ export class TableServiceAuth {
7
7
 
8
8
  canAccess(methodName: string, args: any[]): boolean {
9
9
  try {
10
- const table: Table<any>|undefined = args[0];
11
- if (!isTable(table))
10
+ const table: Table<any> | undefined = args[0];
11
+ if (!isTable(table)) {
12
12
  throw new Error(`[DbServiceAuth] Expected first arg to be a table`);
13
-
13
+ }
14
+
14
15
  const tableAuth = new TableAuth();
15
- if (methodName === 'get' || methodName == 'query' || methodName == 'getRowCount')
16
+ if (methodName === 'get' || methodName == 'query' || methodName == 'getRowCount') {
16
17
  tableAuth.canQuery(table as Table<any>, 'service');
17
- else if (methodName === 'insert')
18
+ } else if (methodName === 'insert') {
18
19
  tableAuth.canInsert(table as Table<any>, 'service');
19
- else if (methodName === 'update')
20
+ } else if (methodName === 'update') {
20
21
  tableAuth.canUpdate(table as Table<any>, 'service');
21
- else if (methodName === 'delete')
22
+ } else if (methodName === 'delete') {
22
23
  tableAuth.canDelete(table as Table<any>, 'service');
23
- else
24
+ } else {
24
25
  throw new Error(`User is not authorized to access unsupported Db service api: ${methodName}`);
26
+ }
25
27
  } catch (error: any) {
26
28
  this.logger.error(error.stack);
27
29
  return false;
@@ -29,4 +31,4 @@ export class TableServiceAuth {
29
31
 
30
32
  return true;
31
33
  }
32
- }
34
+ }
package/src/opt/moment.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  import moment from 'moment';
2
2
  import { Moment } from 'moment';
3
3
 
4
- export { Moment, moment };
4
+ export { Moment, moment };
@@ -6,12 +6,12 @@ import { ReferenceSerializerId } from '../serializers/ReferenceSerializer';
6
6
 
7
7
  /**
8
8
  * The object returned by Db functions for each field of type ReferenceColumn in a record.
9
- * The reason for this is to make loading of reference records on-demand. For theoretically
9
+ * The reason for this is to make loading of reference records on-demand. For theoretically
10
10
  * infinitely-nested references, this is necessary. For everything else, this is optimal.
11
- *
11
+ *
12
12
  * Note: updating the reference via set does not automatically persist those changes in the db.
13
13
  * You still need to call Db.update on the record as you would when changing any other field on the record.
14
- *
14
+ *
15
15
  * Note: all instance members are internal state, made public for ReferenceArraySerializer.
16
16
  * Only get() and set() should be used.
17
17
  */
@@ -21,14 +21,14 @@ export class Reference<T extends Record> implements CustomSerializableObject {
21
21
  constructor(
22
22
  public _table: string,
23
23
  public _id?: string,
24
- public _object?: T,
24
+ public _object?: T
25
25
  ) {}
26
26
 
27
- static fromObject<T extends Record>(table: string, object: T|(Partial<T> & { id: string })) {
27
+ static fromObject<T extends Record>(table: string, object: T | (Partial<T> & { id: string })) {
28
28
  return new Reference<T>(table, object.id, object as T);
29
29
  }
30
30
 
31
- async get(): Promise<T|undefined> {
31
+ async get(): Promise<T | undefined> {
32
32
  if (!this._object && this._id) {
33
33
  const table = tableByName(this._table);
34
34
  const db = getDb();
@@ -42,4 +42,4 @@ export class Reference<T extends Record> implements CustomSerializableObject {
42
42
  this._object = object;
43
43
  this._id = object.id;
44
44
  }
45
- }
45
+ }
@@ -7,15 +7,15 @@ import { QueryBuilderFactory } from '../QueryBuilderFactory';
7
7
 
8
8
  /**
9
9
  * The object returned by Db functions for each field of type ReferenceArrayColumn in a record.
10
- * The reason for this is to make loading of reference records on-demand. For theoretically
10
+ * The reason for this is to make loading of reference records on-demand. For theoretically
11
11
  * infinitely-nested references, this is necessary. For everything else, this is optimal.
12
- *
12
+ *
13
13
  * Note: generally only get() needs to be called. Array operations performed on the returned array will be
14
14
  * persisted in ReferenceArray.
15
- *
15
+ *
16
16
  * Note: updating items in the returned array does not automatically persist those changes in the db.
17
17
  * You still need to call Db.update on the record as you would when changing any other field on the record.
18
- *
18
+ *
19
19
  * Note: all instance members are internal state, made public for ReferenceArraySerializer.
20
20
  * Only get() and set() should be used.
21
21
  */
@@ -25,11 +25,11 @@ export class ReferenceArray<T extends Record> implements CustomSerializableObjec
25
25
  constructor(
26
26
  public _table: string,
27
27
  public _ids: string[],
28
- public _objects?: T[],
28
+ public _objects?: T[]
29
29
  ) {}
30
30
 
31
- static fromObjects<T extends Record>(table: string, objects: (T|(Partial<T> & { id: string }))[]) {
32
- const ids = objects.map(object => object.id);
31
+ static fromObjects<T extends Record>(table: string, objects: (T | (Partial<T> & { id: string }))[]) {
32
+ const ids = objects.map((object) => object.id);
33
33
  return new ReferenceArray<T>(table, ids, objects as T[]);
34
34
  }
35
35
 
@@ -53,4 +53,4 @@ export class ReferenceArray<T extends Record> implements CustomSerializableObjec
53
53
  set(objects: T[]) {
54
54
  this._objects = objects;
55
55
  }
56
- }
56
+ }
@@ -6,113 +6,133 @@ export class SchemaMetadata {
6
6
  constructor(
7
7
  public dbDriver: DbDriver,
8
8
  private multiDbSupported = true
9
- ){}
9
+ ) {}
10
10
 
11
11
  async tableExists(table: Table<any>): Promise<boolean> {
12
- const qb = new QueryBuilder('TABLES')
12
+ const qb = new QueryBuilder('TABLES')
13
13
  .condition({ field: 'TABLE_SCHEMA', operator: '=', value: this.dbDriver.getDbName() })
14
- .condition({ field: 'TABLE_NAME', operator: '=', value: table.name })
15
- ;
16
- const generateStatement = (config: ParameterizationConfig) => qb.toSql({ dbName: 'INFORMATION_SCHEMA', ...config });
17
- const results = await this.dbDriver.runQuery(generateStatement);
18
- return results.length > 0;
19
- }
14
+ .condition({ field: 'TABLE_NAME', operator: '=', value: table.name });
15
+ const generateStatement = (config: ParameterizationConfig) => qb.toSql({ dbName: 'INFORMATION_SCHEMA', ...config });
16
+ const results = await this.dbDriver.runQuery(generateStatement);
17
+ return results.length > 0;
18
+ }
20
19
 
21
20
  async columnExists(columnName: string, table: Table<any>): Promise<boolean> {
22
- const qb = QueryBuilder.fromObject({
23
- 'TABLE_SCHEMA': this.multiDbSupported ? this.dbDriver.getDbName() : undefined,
24
- 'TABLE_NAME': table.name,
25
- 'COLUMN_NAME': columnName,
26
- }, 'COLUMNS');
27
- const generateStatement = (config: ParameterizationConfig) => qb.toSql({ dbName: 'INFORMATION_SCHEMA', ...config });
28
- const results = await this.dbDriver.runQuery(generateStatement);
29
- return results.length > 0;
21
+ const qb = QueryBuilder.fromObject(
22
+ {
23
+ TABLE_SCHEMA: this.multiDbSupported ? this.dbDriver.getDbName() : undefined,
24
+ TABLE_NAME: table.name,
25
+ COLUMN_NAME: columnName,
26
+ },
27
+ 'COLUMNS'
28
+ );
29
+ const generateStatement = (config: ParameterizationConfig) => qb.toSql({ dbName: 'INFORMATION_SCHEMA', ...config });
30
+ const results = await this.dbDriver.runQuery(generateStatement);
31
+ return results.length > 0;
30
32
  }
31
-
32
- async getColumnMetadata(table: Table<any>): Promise<{[columnName: string]: { type: string, isNullable: boolean }}> {
33
- const qb = QueryBuilder.fromObject({
34
- 'TABLE_SCHEMA': this.multiDbSupported ? this.dbDriver.getDbName() : undefined,
35
- 'TABLE_NAME': table.name
36
- }, 'COLUMNS');
33
+
34
+ async getColumnMetadata(table: Table<any>): Promise<{ [columnName: string]: { type: string; isNullable: boolean } }> {
35
+ const qb = QueryBuilder.fromObject(
36
+ {
37
+ TABLE_SCHEMA: this.multiDbSupported ? this.dbDriver.getDbName() : undefined,
38
+ TABLE_NAME: table.name,
39
+ },
40
+ 'COLUMNS'
41
+ );
37
42
  const generateStatement = (config: ParameterizationConfig) => qb.toSql({ dbName: 'INFORMATION_SCHEMA', ...config });
38
- const results = await this.dbDriver.runQuery(generateStatement);
39
- const columnMetadata: {[columnName: string]: { type: string, isNullable: boolean }} = {};
40
- for (const row of results)
43
+ const results = await this.dbDriver.runQuery(generateStatement);
44
+ const columnMetadata: { [columnName: string]: { type: string; isNullable: boolean } } = {};
45
+ for (const row of results) {
41
46
  columnMetadata[row['COLUMN_NAME']] = { type: row['DATA_TYPE'], isNullable: row['IS_NULLABLE'] === 'YES' };
42
-
47
+ }
48
+
43
49
  return columnMetadata;
44
50
  }
45
-
51
+
46
52
  async getPrimaryKey(table: Table<any>): Promise<string[]> {
47
- const qb = QueryBuilder.fromObject({
48
- 'TABLE_SCHEMA': this.multiDbSupported ? this.dbDriver.getDbName() : undefined,
49
- 'TABLE_NAME': table.name,
50
- 'CONSTRAINT_NAME': 'PRIMARY',
51
- }, 'KEY_COLUMN_USAGE');
53
+ const qb = QueryBuilder.fromObject(
54
+ {
55
+ TABLE_SCHEMA: this.multiDbSupported ? this.dbDriver.getDbName() : undefined,
56
+ TABLE_NAME: table.name,
57
+ CONSTRAINT_NAME: 'PRIMARY',
58
+ },
59
+ 'KEY_COLUMN_USAGE'
60
+ );
52
61
  const generateStatement = (config: ParameterizationConfig) => qb.toSql({ dbName: 'INFORMATION_SCHEMA' });
53
- const results = await this.dbDriver.runQuery(generateStatement);
62
+ const results = await this.dbDriver.runQuery(generateStatement);
54
63
  const primaryKey: string[] = [];
55
- for (const row of results)
64
+ for (const row of results) {
56
65
  primaryKey.push(row['COLUMN_NAME']);
57
-
66
+ }
67
+
58
68
  return primaryKey;
59
69
  }
60
-
61
- async getForeignKeys(table: Table<any>): Promise<{[columnName: string]: { referencedTableName: string, referencedColumnName: string }}> {
62
- const qb = QueryBuilder.fromObject({
63
- 'TABLE_SCHEMA': this.multiDbSupported ? this.dbDriver.getDbName() : undefined,
64
- 'TABLE_NAME': table.name
65
- }, 'KEY_COLUMN_USAGE');
70
+
71
+ async getForeignKeys(
72
+ table: Table<any>
73
+ ): Promise<{ [columnName: string]: { referencedTableName: string; referencedColumnName: string } }> {
74
+ const qb = QueryBuilder.fromObject(
75
+ {
76
+ TABLE_SCHEMA: this.multiDbSupported ? this.dbDriver.getDbName() : undefined,
77
+ TABLE_NAME: table.name,
78
+ },
79
+ 'KEY_COLUMN_USAGE'
80
+ );
66
81
  const generateStatement = (config: ParameterizationConfig) => qb.toSql({ dbName: 'INFORMATION_SCHEMA', ...config });
67
- const results = await this.dbDriver.runQuery(generateStatement);
68
- const foreignKeys: {[columnName: string]: { referencedTableName: string, referencedColumnName: string }} = {};
82
+ const results = await this.dbDriver.runQuery(generateStatement);
83
+ const foreignKeys: { [columnName: string]: { referencedTableName: string; referencedColumnName: string } } = {};
69
84
  for (const row of results) {
70
- if (!row['REFERENCED_TABLE_NAME'])
85
+ if (!row['REFERENCED_TABLE_NAME']) {
71
86
  continue;
72
-
87
+ }
88
+
73
89
  foreignKeys[row['COLUMN_NAME']] = {
74
90
  referencedTableName: row['REFERENCED_TABLE_NAME'],
75
91
  referencedColumnName: row['REFERENCED_COLUMN_NAME'],
76
92
  };
77
93
  }
78
-
94
+
79
95
  return foreignKeys;
80
96
  }
81
-
97
+
82
98
  async getUniqueColumns(table: Table<any>): Promise<string[]> {
83
- const qb = QueryBuilder.fromObject({
84
- 'TABLE_SCHEMA': this.multiDbSupported ? this.dbDriver.getDbName() : undefined,
85
- 'TABLE_NAME': table.name
86
- }, 'KEY_COLUMN_USAGE');
99
+ const qb = QueryBuilder.fromObject(
100
+ {
101
+ TABLE_SCHEMA: this.multiDbSupported ? this.dbDriver.getDbName() : undefined,
102
+ TABLE_NAME: table.name,
103
+ },
104
+ 'KEY_COLUMN_USAGE'
105
+ );
87
106
  const generateStatement = (config: ParameterizationConfig) => qb.toSql({ dbName: 'INFORMATION_SCHEMA', ...config });
88
- const results = await this.dbDriver.runQuery(generateStatement);
107
+ const results = await this.dbDriver.runQuery(generateStatement);
89
108
  const uniqueColumns: string[] = [];
90
109
  for (const row of results) {
91
- if (!(row['CONSTRAINT_NAME'] as string).endsWith('_unique'))
110
+ if (!(row['CONSTRAINT_NAME'] as string).endsWith('_unique')) {
92
111
  continue;
93
-
112
+ }
113
+
94
114
  uniqueColumns.push(row['COLUMN_NAME']);
95
115
  }
96
-
116
+
97
117
  return uniqueColumns;
98
118
  }
99
-
100
- async getIndexes(table: Table<any>): Promise<{[keyName: string]: string[]}> {
119
+
120
+ async getIndexes(table: Table<any>): Promise<{ [keyName: string]: string[] }> {
101
121
  const qb = new QueryBuilder('STATISTICS')
102
122
  .condition({ field: 'TABLE_SCHEMA', operator: '=', value: this.dbDriver.getDbName() })
103
123
  .condition({ field: 'TABLE_NAME', operator: '=', value: table.name })
104
- .sort([{ field: 'SEQ_IN_INDEX', desc: false }])
105
- ;
124
+ .sort([{ field: 'SEQ_IN_INDEX', desc: false }]);
106
125
  const generateStatement = (config: ParameterizationConfig) => qb.toSql({ dbName: 'INFORMATION_SCHEMA', ...config });
107
- const results: any[] = await this.dbDriver.runQuery(generateStatement);
126
+ const results: any[] = await this.dbDriver.runQuery(generateStatement);
108
127
  const indexes: { [keyName: string]: string[] } = {};
109
128
  for (const row of results) {
110
- if (!indexes[row['INDEX_NAME']])
129
+ if (!indexes[row['INDEX_NAME']]) {
111
130
  indexes[row['INDEX_NAME']] = [];
112
-
131
+ }
132
+
113
133
  indexes[row['INDEX_NAME']].push(row['COLUMN_NAME']);
114
134
  }
115
-
135
+
116
136
  return indexes;
117
137
  }
118
- }
138
+ }
@@ -7,7 +7,7 @@ export interface SchemaOperations {
7
7
 
8
8
  interface Index {
9
9
  name?: string;
10
- columns: string|string[];
10
+ columns: string | string[];
11
11
  unique?: boolean;
12
12
  }
13
13
 
@@ -41,4 +41,4 @@ export interface TableChanges {
41
41
  columnsWithUniqueConstraintsToDrop: string[];
42
42
  indexesToCreate: Index[];
43
43
  indexesToDrop: Index[];
44
- }
44
+ }