pure-orm 4.0.2 → 4.1.4
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.
- package/.benchmarks/bench-core-baseline.json +303 -0
- package/.eslintrc.json +20 -10
- package/README.md +0 -7
- package/coverage/clover.xml +1493 -1232
- package/coverage/coverage-final.json +103 -103
- package/coverage/lcov-report/dist/src/core.js.html +590 -383
- package/coverage/lcov-report/dist/src/driver-integrations/index.html +20 -20
- package/coverage/lcov-report/dist/src/driver-integrations/pgp.js.html +52 -52
- package/coverage/lcov-report/dist/src/index.html +28 -28
- package/coverage/lcov-report/dist/src/index.js.html +2 -2
- package/coverage/lcov-report/dist/src/orm.js.html +392 -209
- package/coverage/lcov-report/dist/test-utils/blog/entities.js.html +1 -1
- package/coverage/lcov-report/dist/test-utils/blog/index.html +1 -1
- package/coverage/lcov-report/dist/test-utils/blog/models/article.js.html +15 -15
- package/coverage/lcov-report/dist/test-utils/blog/models/article_tag.js.html +2 -2
- package/coverage/lcov-report/dist/test-utils/blog/models/index.html +1 -1
- package/coverage/lcov-report/dist/test-utils/blog/models/person.js.html +13 -13
- package/coverage/lcov-report/dist/test-utils/blog/models/tag.js.html +1 -1
- package/coverage/lcov-report/dist/test-utils/five/entities.js.html +1 -1
- package/coverage/lcov-report/dist/test-utils/five/index.html +1 -1
- package/coverage/lcov-report/dist/test-utils/five/models/index.html +1 -1
- package/coverage/lcov-report/dist/test-utils/five/models/line-item.js.html +4 -4
- package/coverage/lcov-report/dist/test-utils/five/models/order.js.html +3 -3
- package/coverage/lcov-report/dist/test-utils/five/models/parcel-event.js.html +6 -6
- package/coverage/lcov-report/dist/test-utils/five/models/parcel-line-item.js.html +7 -7
- package/coverage/lcov-report/dist/test-utils/five/models/parcel.js.html +2 -2
- package/coverage/lcov-report/dist/test-utils/fourteen/entities.js.html +1 -1
- package/coverage/lcov-report/dist/test-utils/fourteen/index.html +1 -1
- package/coverage/lcov-report/dist/test-utils/fourteen/models/customer.js.html +1 -1
- package/coverage/lcov-report/dist/test-utils/fourteen/models/index.html +1 -1
- package/coverage/lcov-report/dist/test-utils/fourteen/models/person.js.html +1 -1
- package/coverage/lcov-report/dist/test-utils/nine/entities.js.html +1 -1
- package/coverage/lcov-report/dist/test-utils/nine/index.html +1 -1
- package/coverage/lcov-report/dist/test-utils/nine/models/feature-switch.js.html +6 -6
- package/coverage/lcov-report/dist/test-utils/nine/models/index.html +1 -1
- package/coverage/lcov-report/dist/test-utils/order/entities.js.html +9 -9
- package/coverage/lcov-report/dist/test-utils/order/index.html +1 -1
- package/coverage/lcov-report/dist/test-utils/order/models/index.html +14 -14
- package/coverage/lcov-report/dist/test-utils/order/models/line-item.js.html +11 -11
- package/coverage/lcov-report/dist/test-utils/order/models/order.js.html +41 -41
- package/coverage/lcov-report/dist/test-utils/order/models/product-variant.js.html +18 -18
- package/coverage/lcov-report/dist/test-utils/order/models/product.js.html +17 -17
- package/coverage/lcov-report/dist/test-utils/order/models/utm-source.js.html +12 -12
- package/coverage/lcov-report/dist/test-utils/order-more/entities.js.html +1 -1
- package/coverage/lcov-report/dist/test-utils/order-more/index.html +1 -1
- package/coverage/lcov-report/dist/test-utils/order-more/models/actual-product-variant.js.html +3 -3
- package/coverage/lcov-report/dist/test-utils/order-more/models/color.js.html +6 -6
- package/coverage/lcov-report/dist/test-utils/order-more/models/customer.js.html +3 -3
- package/coverage/lcov-report/dist/test-utils/order-more/models/gender.js.html +4 -4
- package/coverage/lcov-report/dist/test-utils/order-more/models/index.html +23 -23
- package/coverage/lcov-report/dist/test-utils/order-more/models/inventory-level.js.html +11 -11
- package/coverage/lcov-report/dist/test-utils/order-more/models/line-item.js.html +15 -15
- package/coverage/lcov-report/dist/test-utils/order-more/models/order.js.html +39 -39
- package/coverage/lcov-report/dist/test-utils/order-more/models/parcel-event.js.html +6 -6
- package/coverage/lcov-report/dist/test-utils/order-more/models/parcel-line-item.js.html +7 -7
- package/coverage/lcov-report/dist/test-utils/order-more/models/parcel.js.html +2 -2
- package/coverage/lcov-report/dist/test-utils/order-more/models/physical-address.js.html +12 -12
- package/coverage/lcov-report/dist/test-utils/order-more/models/product-variant-image.js.html +7 -7
- package/coverage/lcov-report/dist/test-utils/order-more/models/product-variant.js.html +22 -22
- package/coverage/lcov-report/dist/test-utils/order-more/models/product.js.html +11 -11
- package/coverage/lcov-report/dist/test-utils/order-more/models/refund.js.html +11 -11
- package/coverage/lcov-report/dist/test-utils/order-more/models/shipment-actual-product-variant.js.html +9 -9
- package/coverage/lcov-report/dist/test-utils/order-more/models/shipment.js.html +4 -4
- package/coverage/lcov-report/dist/test-utils/order-more/models/size.js.html +4 -4
- package/coverage/lcov-report/dist/test-utils/order-more/models/utm-medium.js.html +15 -15
- package/coverage/lcov-report/dist/test-utils/order-more/models/utm-source.js.html +17 -17
- package/coverage/lcov-report/dist/test-utils/six/entities.js.html +1 -1
- package/coverage/lcov-report/dist/test-utils/six/index.html +1 -1
- package/coverage/lcov-report/dist/test-utils/six/models/customer.js.html +3 -3
- package/coverage/lcov-report/dist/test-utils/six/models/index.html +21 -21
- package/coverage/lcov-report/dist/test-utils/six/models/line-item.js.html +10 -10
- package/coverage/lcov-report/dist/test-utils/six/models/order.js.html +13 -13
- package/coverage/lcov-report/dist/test-utils/six/models/parcel-line-item.js.html +2 -2
- package/coverage/lcov-report/dist/test-utils/six/models/parcel.js.html +2 -2
- package/coverage/lcov-report/dist/test-utils/thirteen/entities.js.html +1 -1
- package/coverage/lcov-report/dist/test-utils/thirteen/index.html +1 -1
- package/coverage/lcov-report/dist/test-utils/thirteen/models/audience.js.html +2 -2
- package/coverage/lcov-report/dist/test-utils/thirteen/models/brand.js.html +2 -2
- package/coverage/lcov-report/dist/test-utils/thirteen/models/category.js.html +1 -1
- package/coverage/lcov-report/dist/test-utils/thirteen/models/index.html +14 -14
- package/coverage/lcov-report/dist/test-utils/thirteen/models/member.js.html +2 -2
- package/coverage/lcov-report/dist/test-utils/thirteen/models/passion.js.html +2 -2
- package/coverage/lcov-report/dist/test-utils/thirteen/models/product.js.html +10 -10
- package/coverage/lcov-report/dist/test-utils/thirteen/models/recommendation-audience.js.html +2 -2
- package/coverage/lcov-report/dist/test-utils/thirteen/models/recommendation.js.html +2 -2
- package/coverage/lcov-report/dist/test-utils/three/index.html +1 -1
- package/coverage/lcov-report/dist/test-utils/three/results.js.html +1 -1
- package/coverage/lcov-report/dist/test-utils/twelve/entities.js.html +1 -1
- package/coverage/lcov-report/dist/test-utils/twelve/index.html +1 -1
- package/coverage/lcov-report/dist/test-utils/twelve/models/index.html +1 -1
- package/coverage/lcov-report/dist/test-utils/twelve/models/member.js.html +1 -1
- package/coverage/lcov-report/dist/test-utils/twelve/models/prompt.js.html +2 -2
- package/coverage/lcov-report/dist/test-utils/two/index.html +1 -1
- package/coverage/lcov-report/dist/test-utils/two/results.js.html +1 -1
- package/coverage/lcov-report/index.html +103 -103
- package/coverage/lcov-report/src/core.ts.html +841 -415
- package/coverage/lcov-report/src/driver-integrations/index.html +20 -20
- package/coverage/lcov-report/src/driver-integrations/pgp.ts.html +63 -63
- package/coverage/lcov-report/src/index.html +28 -28
- package/coverage/lcov-report/src/index.ts.html +1 -1
- package/coverage/lcov-report/src/orm.ts.html +388 -298
- package/coverage/lcov-report/test-utils/blog/entities.ts.html +1 -1
- package/coverage/lcov-report/test-utils/blog/index.html +1 -1
- package/coverage/lcov-report/test-utils/blog/models/article.ts.html +15 -15
- package/coverage/lcov-report/test-utils/blog/models/article_tag.ts.html +2 -2
- package/coverage/lcov-report/test-utils/blog/models/index.html +1 -1
- package/coverage/lcov-report/test-utils/blog/models/person.ts.html +13 -13
- package/coverage/lcov-report/test-utils/blog/models/tag.ts.html +1 -1
- package/coverage/lcov-report/test-utils/five/entities.ts.html +1 -1
- package/coverage/lcov-report/test-utils/five/index.html +1 -1
- package/coverage/lcov-report/test-utils/five/models/index.html +1 -1
- package/coverage/lcov-report/test-utils/five/models/line-item.ts.html +4 -4
- package/coverage/lcov-report/test-utils/five/models/order.ts.html +3 -3
- package/coverage/lcov-report/test-utils/five/models/parcel-event.ts.html +6 -6
- package/coverage/lcov-report/test-utils/five/models/parcel-line-item.ts.html +7 -7
- package/coverage/lcov-report/test-utils/five/models/parcel.ts.html +2 -2
- package/coverage/lcov-report/test-utils/fourteen/entities.ts.html +1 -1
- package/coverage/lcov-report/test-utils/fourteen/index.html +1 -1
- package/coverage/lcov-report/test-utils/fourteen/models/customer.ts.html +1 -1
- package/coverage/lcov-report/test-utils/fourteen/models/index.html +1 -1
- package/coverage/lcov-report/test-utils/fourteen/models/person.ts.html +1 -1
- package/coverage/lcov-report/test-utils/nine/entities.ts.html +1 -1
- package/coverage/lcov-report/test-utils/nine/index.html +1 -1
- package/coverage/lcov-report/test-utils/nine/models/feature-switch.ts.html +8 -8
- package/coverage/lcov-report/test-utils/nine/models/index.html +1 -1
- package/coverage/lcov-report/test-utils/order/entities.ts.html +2 -2
- package/coverage/lcov-report/test-utils/order/index.html +1 -1
- package/coverage/lcov-report/test-utils/order/models/index.html +14 -14
- package/coverage/lcov-report/test-utils/order/models/line-item.ts.html +5 -5
- package/coverage/lcov-report/test-utils/order/models/order.ts.html +36 -36
- package/coverage/lcov-report/test-utils/order/models/product-variant.ts.html +13 -13
- package/coverage/lcov-report/test-utils/order/models/product.ts.html +13 -13
- package/coverage/lcov-report/test-utils/order/models/utm-source.ts.html +8 -8
- package/coverage/lcov-report/test-utils/order-more/entities.ts.html +1 -1
- package/coverage/lcov-report/test-utils/order-more/index.html +1 -1
- package/coverage/lcov-report/test-utils/order-more/models/actual-product-variant.ts.html +3 -3
- package/coverage/lcov-report/test-utils/order-more/models/color.ts.html +6 -6
- package/coverage/lcov-report/test-utils/order-more/models/customer.ts.html +3 -3
- package/coverage/lcov-report/test-utils/order-more/models/gender.ts.html +4 -4
- package/coverage/lcov-report/test-utils/order-more/models/index.html +23 -23
- package/coverage/lcov-report/test-utils/order-more/models/inventory-level.ts.html +11 -11
- package/coverage/lcov-report/test-utils/order-more/models/line-item.ts.html +15 -15
- package/coverage/lcov-report/test-utils/order-more/models/order.ts.html +45 -45
- package/coverage/lcov-report/test-utils/order-more/models/parcel-event.ts.html +6 -6
- package/coverage/lcov-report/test-utils/order-more/models/parcel-line-item.ts.html +7 -7
- package/coverage/lcov-report/test-utils/order-more/models/parcel.ts.html +2 -2
- package/coverage/lcov-report/test-utils/order-more/models/physical-address.ts.html +12 -12
- package/coverage/lcov-report/test-utils/order-more/models/product-variant-image.ts.html +7 -7
- package/coverage/lcov-report/test-utils/order-more/models/product-variant.ts.html +22 -22
- package/coverage/lcov-report/test-utils/order-more/models/product.ts.html +11 -11
- package/coverage/lcov-report/test-utils/order-more/models/refund.ts.html +11 -11
- package/coverage/lcov-report/test-utils/order-more/models/shipment-actual-product-variant.ts.html +9 -9
- package/coverage/lcov-report/test-utils/order-more/models/shipment.ts.html +4 -4
- package/coverage/lcov-report/test-utils/order-more/models/size.ts.html +4 -4
- package/coverage/lcov-report/test-utils/order-more/models/utm-medium.ts.html +15 -15
- package/coverage/lcov-report/test-utils/order-more/models/utm-source.ts.html +17 -17
- package/coverage/lcov-report/test-utils/six/entities.ts.html +1 -1
- package/coverage/lcov-report/test-utils/six/index.html +1 -1
- package/coverage/lcov-report/test-utils/six/models/customer.ts.html +3 -3
- package/coverage/lcov-report/test-utils/six/models/index.html +21 -21
- package/coverage/lcov-report/test-utils/six/models/line-item.ts.html +10 -10
- package/coverage/lcov-report/test-utils/six/models/order.ts.html +13 -13
- package/coverage/lcov-report/test-utils/six/models/parcel-line-item.ts.html +2 -2
- package/coverage/lcov-report/test-utils/six/models/parcel.ts.html +2 -2
- package/coverage/lcov-report/test-utils/thirteen/entities.ts.html +1 -1
- package/coverage/lcov-report/test-utils/thirteen/index.html +1 -1
- package/coverage/lcov-report/test-utils/thirteen/models/audience.ts.html +2 -2
- package/coverage/lcov-report/test-utils/thirteen/models/brand.ts.html +2 -2
- package/coverage/lcov-report/test-utils/thirteen/models/category.ts.html +1 -1
- package/coverage/lcov-report/test-utils/thirteen/models/index.html +14 -14
- package/coverage/lcov-report/test-utils/thirteen/models/member.ts.html +2 -2
- package/coverage/lcov-report/test-utils/thirteen/models/passion.ts.html +2 -2
- package/coverage/lcov-report/test-utils/thirteen/models/product.ts.html +10 -10
- package/coverage/lcov-report/test-utils/thirteen/models/recommendation-audience.ts.html +2 -2
- package/coverage/lcov-report/test-utils/thirteen/models/recommendation.ts.html +2 -2
- package/coverage/lcov-report/test-utils/three/index.html +1 -1
- package/coverage/lcov-report/test-utils/three/results.js.html +1 -1
- package/coverage/lcov-report/test-utils/twelve/entities.ts.html +1 -1
- package/coverage/lcov-report/test-utils/twelve/index.html +1 -1
- package/coverage/lcov-report/test-utils/twelve/models/index.html +1 -1
- package/coverage/lcov-report/test-utils/twelve/models/member.ts.html +1 -1
- package/coverage/lcov-report/test-utils/twelve/models/prompt.ts.html +2 -2
- package/coverage/lcov-report/test-utils/two/index.html +1 -1
- package/coverage/lcov-report/test-utils/two/results.js.html +1 -1
- package/coverage/lcov.info +2136 -1991
- package/dist/example/data-access/person.d.ts +1 -1
- package/dist/src/core.d.ts +13 -7
- package/dist/src/core.js +258 -189
- package/dist/src/core.spec.js +413 -0
- package/dist/src/driver-integrations/index.d.ts +5 -5
- package/dist/src/driver-integrations/pgp.spec.d.ts +1 -0
- package/dist/src/driver-integrations/pgp.spec.js +376 -0
- package/dist/src/orm.d.ts +9 -9
- package/dist/src/orm.js +137 -76
- package/dist/src/orm.spec.js +535 -85
- package/dist/test-utils/nine/models/feature-switch.d.ts +2 -2
- package/dist/test-utils/nine/models/feature-switch.ts +2 -2
- package/example/data-access/person.ts +1 -1
- package/package.json +9 -6
- package/scripts/bench-core.js +636 -0
- package/scripts/check-bench-scenarios.js +47 -0
- package/src/core.spec.ts +485 -2
- package/src/core.ts +369 -227
- package/src/driver-integrations/index.ts +5 -5
- package/src/driver-integrations/pgp.spec.ts +444 -0
- package/src/driver-integrations/pgp.ts +5 -5
- package/src/orm.spec.ts +592 -88
- package/src/orm.ts +173 -143
- package/test-utils/nine/models/feature-switch.ts +2 -2
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { Person } from '../models/person';
|
|
2
|
-
export declare const getPerson: (id: number) => Person
|
|
2
|
+
export declare const getPerson: (id: number) => Promise<Person>;
|
package/dist/src/core.d.ts
CHANGED
|
@@ -4,20 +4,20 @@ export interface IColumnData {
|
|
|
4
4
|
references?: IModelClass;
|
|
5
5
|
primaryKey?: boolean;
|
|
6
6
|
}
|
|
7
|
-
export
|
|
8
|
-
export
|
|
7
|
+
export type IColumn = IColumnData | string;
|
|
8
|
+
export type IColumns = Array<IColumn> | (() => Array<IColumn>);
|
|
9
9
|
export interface IColumnInternalData {
|
|
10
10
|
column: string;
|
|
11
11
|
property: string;
|
|
12
12
|
references?: IModelClass;
|
|
13
13
|
primaryKey: boolean;
|
|
14
14
|
}
|
|
15
|
-
export
|
|
16
|
-
export
|
|
15
|
+
export type IColumnInternal = IColumnInternalData;
|
|
16
|
+
export type IColumnsInternal = Array<IColumnInternal>;
|
|
17
17
|
export interface IModel {
|
|
18
18
|
[key: string]: any;
|
|
19
19
|
}
|
|
20
|
-
export
|
|
20
|
+
export type IModelClass = new (props: any) => IModel;
|
|
21
21
|
export interface ICollection<T extends IModel> {
|
|
22
22
|
models: Array<T>;
|
|
23
23
|
}
|
|
@@ -29,7 +29,7 @@ export interface IEntity<T extends IModel> {
|
|
|
29
29
|
Model: new (props: any) => T;
|
|
30
30
|
Collection: new ({ models }: any) => ICollection<T>;
|
|
31
31
|
}
|
|
32
|
-
export
|
|
32
|
+
export type IEntities<T extends IModel> = Array<IEntity<T>>;
|
|
33
33
|
export interface IEntityInternal<T extends IModel> {
|
|
34
34
|
tableName: string;
|
|
35
35
|
displayName: string;
|
|
@@ -44,8 +44,14 @@ export interface IEntityInternal<T extends IModel> {
|
|
|
44
44
|
references: object;
|
|
45
45
|
selectColumnsClause: string;
|
|
46
46
|
getPkId: (model: IModel) => string;
|
|
47
|
+
columnToPropertyMap: Map<string, string>;
|
|
48
|
+
propertyToColumnMap: Map<string, string>;
|
|
49
|
+
referencesEntries: Array<{
|
|
50
|
+
property: string;
|
|
51
|
+
ModelClass: IModelClass;
|
|
52
|
+
}>;
|
|
47
53
|
}
|
|
48
|
-
export
|
|
54
|
+
export type IEntitiesInternal<T extends IModel> = Array<IEntityInternal<T>>;
|
|
49
55
|
export interface ICreateCoreOptions {
|
|
50
56
|
entities: IEntities<IModel>;
|
|
51
57
|
}
|
package/dist/src/core.js
CHANGED
|
@@ -28,17 +28,33 @@ const createCore = ({ entities: externalEntities }) => {
|
|
|
28
28
|
const pkColumnsData = columns.filter((x) => x.primaryKey);
|
|
29
29
|
const _primaryKeys = pkColumnsData.map((x) => x.column);
|
|
30
30
|
const primaryKeys = _primaryKeys.length > 0 ? _primaryKeys : ['id'];
|
|
31
|
-
// Returns unique identifier of model (the values of the primary keys)
|
|
32
31
|
const getPkId = (model) => {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
let id = '';
|
|
33
|
+
for (let i = 0; i < primaryKeys.length; i++) {
|
|
34
|
+
const part = model[primaryKeys[i]];
|
|
35
|
+
if (part !== void 0 && part !== null) {
|
|
36
|
+
id += String(part);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return id;
|
|
36
40
|
};
|
|
37
|
-
const references =
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
41
|
+
const references = {};
|
|
42
|
+
const referencesEntries = [];
|
|
43
|
+
for (const col of columns) {
|
|
44
|
+
if (col.references) {
|
|
45
|
+
references[col.property] = col.references;
|
|
46
|
+
referencesEntries.push({
|
|
47
|
+
property: col.property,
|
|
48
|
+
ModelClass: col.references
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
const columnToPropertyMap = new Map();
|
|
53
|
+
const propertyToColumnMap = new Map();
|
|
54
|
+
for (let i = 0; i < columnNames.length; i++) {
|
|
55
|
+
columnToPropertyMap.set(columnNames[i], propertyNames[i]);
|
|
56
|
+
propertyToColumnMap.set(propertyNames[i], columnNames[i]);
|
|
57
|
+
}
|
|
42
58
|
const selectColumnsClause = prefixedColumnNames
|
|
43
59
|
.map((prefixed, index) => `"${tableName}".${columnNames[index]} as "${prefixed}"`)
|
|
44
60
|
.join(', ');
|
|
@@ -55,7 +71,10 @@ const createCore = ({ entities: externalEntities }) => {
|
|
|
55
71
|
primaryKeys,
|
|
56
72
|
references,
|
|
57
73
|
selectColumnsClause,
|
|
58
|
-
getPkId
|
|
74
|
+
getPkId,
|
|
75
|
+
columnToPropertyMap,
|
|
76
|
+
propertyToColumnMap,
|
|
77
|
+
referencesEntries
|
|
59
78
|
};
|
|
60
79
|
});
|
|
61
80
|
const tableNameToEntityMap = entities.reduce((map, entity) => {
|
|
@@ -83,200 +102,250 @@ const createCore = ({ entities: externalEntities }) => {
|
|
|
83
102
|
const getEntityByModel = (model) => {
|
|
84
103
|
return getEntityByModelClass(model.constructor);
|
|
85
104
|
};
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
let
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
...nodes.slice(0, indexOfOldestParent + 1).reverse()
|
|
139
|
-
];
|
|
140
|
-
const nodeItPointsTo = parentHeirarchy.find((parent) => {
|
|
141
|
-
const indexes = Object.values(getEntityByModel(model).references)
|
|
142
|
-
.map((x, i) => x === parent.constructor ? i : null)
|
|
143
|
-
.filter((x, i) => x != null);
|
|
144
|
-
if (!indexes.length) {
|
|
145
|
-
return false;
|
|
146
|
-
}
|
|
147
|
-
for (const index of indexes) {
|
|
148
|
-
const property = Object.keys(getEntityByModel(model).references)[index];
|
|
149
|
-
if (model[property] === parent.id) {
|
|
150
|
-
return true;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
return false;
|
|
154
|
-
});
|
|
155
|
-
if (isNodeAlreadySeen) {
|
|
156
|
-
if (nodeItPointsTo && !nodePointingToIt) {
|
|
157
|
-
nodes = [model, ...nodes];
|
|
158
|
-
return;
|
|
159
|
-
}
|
|
160
|
-
// If the nodePointingToIt (eg, parcel_event) is part of an
|
|
161
|
-
// existing collection on this node (eg, parcel) which is a
|
|
162
|
-
// nodeAlreadySeen, early return so we don't create it (parcel) on
|
|
163
|
-
// the nodePointingToIt (parcel_event), since it (parcel) has been
|
|
164
|
-
// shown to be the parent (of parcel_events).
|
|
165
|
-
if (nodePointingToIt) {
|
|
166
|
-
const ec = model[getEntityByModel(nodePointingToIt)
|
|
167
|
-
.collectionDisplayName];
|
|
168
|
-
if (ec && ec.models.find((m) => m === nodePointingToIt)) {
|
|
169
|
-
nodes = [model, ...nodes];
|
|
170
|
-
return;
|
|
171
|
-
}
|
|
172
|
-
}
|
|
105
|
+
const entityReferencePlans = new Map();
|
|
106
|
+
for (let i = 0; i < entities.length; i++) {
|
|
107
|
+
const entity = entities[i];
|
|
108
|
+
const plans = new Array(entity.referencesEntries.length);
|
|
109
|
+
for (let j = 0; j < entity.referencesEntries.length; j++) {
|
|
110
|
+
const ref = entity.referencesEntries[j];
|
|
111
|
+
plans[j] = {
|
|
112
|
+
property: ref.property,
|
|
113
|
+
targetEntity: getEntityByModelClass(ref.ModelClass)
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
entityReferencePlans.set(entity, plans);
|
|
117
|
+
}
|
|
118
|
+
const getPkIdFromRow = (row, primaryKeyRowKeys) => {
|
|
119
|
+
let id = '';
|
|
120
|
+
for (let i = 0; i < primaryKeyRowKeys.length; i++) {
|
|
121
|
+
const part = row[primaryKeyRowKeys[i]];
|
|
122
|
+
if (part !== void 0 && part !== null) {
|
|
123
|
+
id += String(part);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return id;
|
|
127
|
+
};
|
|
128
|
+
const buildEntityRowPlans = (sampleRow) => {
|
|
129
|
+
const plansByTable = new Map();
|
|
130
|
+
const tableOrder = [];
|
|
131
|
+
for (const text in sampleRow) {
|
|
132
|
+
if (!Object.prototype.hasOwnProperty.call(sampleRow, text)) {
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
const hashIndex = text.indexOf('#');
|
|
136
|
+
if (hashIndex === -1) {
|
|
137
|
+
throw new Error('Column names must be namespaced to table');
|
|
138
|
+
}
|
|
139
|
+
const tableName = text.substring(0, hashIndex);
|
|
140
|
+
const column = text.substring(hashIndex + 1);
|
|
141
|
+
let plan = plansByTable.get(tableName);
|
|
142
|
+
if (!plan) {
|
|
143
|
+
const entity = getEntityByTableName(tableName);
|
|
144
|
+
const primaryKeyRowKeys = entity.primaryKeys.map((pk) => `${tableName}#${pk}`);
|
|
145
|
+
plan = {
|
|
146
|
+
entity,
|
|
147
|
+
columnPlans: [],
|
|
148
|
+
primaryKeyRowKeys
|
|
149
|
+
};
|
|
150
|
+
plansByTable.set(tableName, plan);
|
|
151
|
+
tableOrder.push(tableName);
|
|
152
|
+
}
|
|
153
|
+
let propertyName = plan.entity.columnToPropertyMap.get(column);
|
|
154
|
+
if (!propertyName) {
|
|
155
|
+
if (column.startsWith('meta_')) {
|
|
156
|
+
propertyName = (0, camelcase_1.default)(column);
|
|
173
157
|
}
|
|
174
|
-
|
|
175
|
-
|
|
158
|
+
else {
|
|
159
|
+
throw Error(`No property name for "${column}" in business object "${plan.entity.displayName}". Non-spec'd columns must begin with "meta_".`);
|
|
176
160
|
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
161
|
+
}
|
|
162
|
+
plan.columnPlans.push({
|
|
163
|
+
rowKey: text,
|
|
164
|
+
propertyName
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
const orderedPlans = new Array(tableOrder.length);
|
|
168
|
+
for (let i = 0; i < tableOrder.length; i++) {
|
|
169
|
+
orderedPlans[i] = plansByTable.get(tableOrder[i]);
|
|
170
|
+
}
|
|
171
|
+
return orderedPlans;
|
|
172
|
+
};
|
|
173
|
+
const materializeModelsFromRow = (row, entityRowPlans, rootScopedModelsByEntity, rowModels, rowModelPkIds, rowCreatedWithPkIndexes) => {
|
|
174
|
+
rowCreatedWithPkIndexes.length = 0;
|
|
175
|
+
for (let i = 0; i < entityRowPlans.length; i++) {
|
|
176
|
+
const plan = entityRowPlans[i];
|
|
177
|
+
const pkId = getPkIdFromRow(row, plan.primaryKeyRowKeys);
|
|
178
|
+
rowModelPkIds[i] = pkId;
|
|
179
|
+
if (pkId) {
|
|
180
|
+
let modelsForEntity = rootScopedModelsByEntity.get(plan.entity);
|
|
181
|
+
if (!modelsForEntity) {
|
|
182
|
+
modelsForEntity = new Map();
|
|
183
|
+
rootScopedModelsByEntity.set(plan.entity, modelsForEntity);
|
|
189
184
|
}
|
|
190
185
|
else {
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
186
|
+
const existing = modelsForEntity.get(pkId);
|
|
187
|
+
if (existing) {
|
|
188
|
+
rowModels[i] = existing;
|
|
189
|
+
continue;
|
|
194
190
|
}
|
|
195
|
-
throw Error(`Could not find how this BO fits: ${JSON.stringify(model)} ${getEntityByModel(model).tableName}`);
|
|
196
191
|
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
192
|
+
}
|
|
193
|
+
else if (i !== 0) {
|
|
194
|
+
// No primary key means this is typically an outer-joined null row.
|
|
195
|
+
// Skip model construction for non-root entities since it cannot link.
|
|
196
|
+
rowModels[i] = void 0;
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
const props = {};
|
|
200
|
+
for (let j = 0; j < plan.columnPlans.length; j++) {
|
|
201
|
+
const columnPlan = plan.columnPlans[j];
|
|
202
|
+
props[columnPlan.propertyName] = row[columnPlan.rowKey];
|
|
203
|
+
}
|
|
204
|
+
const model = new plan.entity.Model(props);
|
|
205
|
+
if (pkId) {
|
|
206
|
+
// modelsForEntity is guaranteed to be initialized above for pk rows.
|
|
207
|
+
rootScopedModelsByEntity.get(plan.entity).set(pkId, model);
|
|
208
|
+
rowCreatedWithPkIndexes.push(i);
|
|
209
|
+
}
|
|
210
|
+
rowModels[i] = model;
|
|
211
|
+
}
|
|
212
|
+
return rowModels[0];
|
|
213
|
+
};
|
|
214
|
+
const getRootScopeKey = (row, rootEntity, rootPrimaryKeys) => {
|
|
215
|
+
let rootScopeKey = '';
|
|
216
|
+
for (let i = 0; i < rootPrimaryKeys.length; i++) {
|
|
217
|
+
if (i > 0) {
|
|
218
|
+
rootScopeKey += '@';
|
|
219
|
+
}
|
|
220
|
+
const value = row[`${rootEntity.tableName}#${rootPrimaryKeys[i]}`];
|
|
221
|
+
rootScopeKey += value === void 0 || value === null ? '' : String(value);
|
|
222
|
+
}
|
|
223
|
+
return rootScopeKey;
|
|
224
|
+
};
|
|
225
|
+
const ensureRootScopeState = (rootScopeKey, rootScopeStateByKey) => {
|
|
226
|
+
let state = rootScopeStateByKey.get(rootScopeKey);
|
|
227
|
+
if (!state) {
|
|
228
|
+
state = {
|
|
229
|
+
modelsByEntity: new Map()
|
|
230
|
+
};
|
|
231
|
+
rootScopeStateByKey.set(rootScopeKey, state);
|
|
232
|
+
}
|
|
233
|
+
return state;
|
|
234
|
+
};
|
|
235
|
+
const ensureCollectionMembership = (rootScopeState) => {
|
|
236
|
+
if (!rootScopeState.collectionMembership) {
|
|
237
|
+
rootScopeState.collectionMembership = new WeakMap();
|
|
238
|
+
}
|
|
239
|
+
return rootScopeState.collectionMembership;
|
|
240
|
+
};
|
|
241
|
+
const linkSourceToTarget = ({ sourceEntity, sourceModel, sourceModelPkId, targetEntity, targetModel, collectionMembership }) => {
|
|
242
|
+
sourceModel[targetEntity.displayName] =
|
|
243
|
+
targetModel;
|
|
244
|
+
let collection = targetModel[sourceEntity.collectionDisplayName];
|
|
245
|
+
if (!collection) {
|
|
246
|
+
const Collection = sourceEntity.Collection;
|
|
247
|
+
collection = new Collection({ models: [] });
|
|
248
|
+
targetModel[sourceEntity.collectionDisplayName] = collection;
|
|
249
|
+
}
|
|
250
|
+
let byCollection = collectionMembership.get(targetModel);
|
|
251
|
+
if (!byCollection) {
|
|
252
|
+
byCollection = new Map();
|
|
253
|
+
collectionMembership.set(targetModel, byCollection);
|
|
254
|
+
}
|
|
255
|
+
let memberIds = byCollection.get(sourceEntity);
|
|
256
|
+
if (!memberIds) {
|
|
257
|
+
memberIds = new Set();
|
|
258
|
+
byCollection.set(sourceEntity, memberIds);
|
|
259
|
+
}
|
|
260
|
+
if (!memberIds.has(sourceModelPkId)) {
|
|
261
|
+
collection.models.push(sourceModel);
|
|
262
|
+
memberIds.add(sourceModelPkId);
|
|
263
|
+
}
|
|
201
264
|
};
|
|
202
265
|
/*
|
|
203
|
-
*
|
|
204
|
-
*
|
|
205
|
-
*
|
|
206
|
-
*
|
|
207
|
-
*
|
|
208
|
-
*
|
|
209
|
-
* ]
|
|
210
|
-
* Out:
|
|
211
|
-
* [
|
|
212
|
-
* [
|
|
213
|
-
* [Article {id: 32}, ArticleTag {id: 54}]
|
|
214
|
-
* [Article {id: 32}, ArticleTag {id: 55}]
|
|
215
|
-
* ]
|
|
216
|
-
* [
|
|
217
|
-
* [Article {id: 33}, ArticleTag {id: 56}]
|
|
218
|
-
* ]
|
|
219
|
-
* ]
|
|
266
|
+
* createFromDatabase architecture:
|
|
267
|
+
* 1) Compile row plans once (column -> property mapping per entity/table).
|
|
268
|
+
* 2) Materialize models per row with scoped de-duplication by root scope key.
|
|
269
|
+
* 3) Index models by root scope + entity + entity primary key.
|
|
270
|
+
* 4) Link refs incrementally as new models appear.
|
|
271
|
+
* 5) Return root models in first-seen root scope order.
|
|
220
272
|
*/
|
|
221
|
-
const
|
|
222
|
-
|
|
223
|
-
const
|
|
224
|
-
const
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
273
|
+
const createFromDatabase = (rows) => {
|
|
274
|
+
var _a;
|
|
275
|
+
const result = Array.isArray(rows) ? rows : [rows];
|
|
276
|
+
const len = result.length;
|
|
277
|
+
const entityRowPlans = buildEntityRowPlans(result[0]);
|
|
278
|
+
const selectedEntities = new Set();
|
|
279
|
+
for (let i = 0; i < entityRowPlans.length; i++) {
|
|
280
|
+
selectedEntities.add(entityRowPlans[i].entity);
|
|
281
|
+
}
|
|
282
|
+
const applicableRefPlans = new Map();
|
|
283
|
+
for (let i = 0; i < entityRowPlans.length; i++) {
|
|
284
|
+
const entity = entityRowPlans[i].entity;
|
|
285
|
+
const refs = entityReferencePlans.get(entity) || [];
|
|
286
|
+
const filteredRefs = refs.filter((ref) => selectedEntities.has(ref.targetEntity));
|
|
287
|
+
applicableRefPlans.set(entity, filteredRefs);
|
|
288
|
+
}
|
|
289
|
+
const rootEntity = entityRowPlans[0].entity;
|
|
290
|
+
const rootPrimaryKeys = rootEntity.primaryKeys;
|
|
291
|
+
const rootScopeOrder = [];
|
|
292
|
+
const rootModelsByScopeKey = new Map();
|
|
293
|
+
const rootScopeStateByKey = new Map();
|
|
294
|
+
let currentRootScopeKey = void 0;
|
|
295
|
+
let currentRootScopeState = void 0;
|
|
296
|
+
const rowModels = new Array(entityRowPlans.length);
|
|
297
|
+
const rowModelPkIds = new Array(entityRowPlans.length);
|
|
298
|
+
const rowCreatedWithPkIndexes = [];
|
|
299
|
+
// Phase 1: materialize and index model instances by root scope + entity.
|
|
300
|
+
for (let i = 0; i < len; i++) {
|
|
301
|
+
const row = result[i];
|
|
302
|
+
const rootScopeKey = getRootScopeKey(row, rootEntity, rootPrimaryKeys);
|
|
303
|
+
let rootScopeState = currentRootScopeState;
|
|
304
|
+
if (!rootScopeState || rootScopeKey !== currentRootScopeKey) {
|
|
305
|
+
rootScopeState = ensureRootScopeState(rootScopeKey, rootScopeStateByKey);
|
|
306
|
+
currentRootScopeKey = rootScopeKey;
|
|
307
|
+
currentRootScopeState = rootScopeState;
|
|
230
308
|
}
|
|
231
|
-
|
|
232
|
-
|
|
309
|
+
const rootModel = materializeModelsFromRow(row, entityRowPlans, rootScopeState.modelsByEntity, rowModels, rowModelPkIds, rowCreatedWithPkIndexes);
|
|
310
|
+
if (!rootModelsByScopeKey.has(rootScopeKey)) {
|
|
311
|
+
rootScopeOrder.push(rootScopeKey);
|
|
312
|
+
rootModelsByScopeKey.set(rootScopeKey, rootModel);
|
|
233
313
|
}
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
314
|
+
for (let c = 0; c < rowCreatedWithPkIndexes.length; c++) {
|
|
315
|
+
const j = rowCreatedWithPkIndexes[c];
|
|
316
|
+
const sourceModel = rowModels[j];
|
|
317
|
+
const sourceModelPkId = rowModelPkIds[j];
|
|
318
|
+
const sourceEntity = entityRowPlans[j].entity;
|
|
319
|
+
const refs = applicableRefPlans.get(sourceEntity);
|
|
320
|
+
if (!refs || refs.length === 0) {
|
|
321
|
+
continue;
|
|
322
|
+
}
|
|
323
|
+
for (let r = 0; r < refs.length; r++) {
|
|
324
|
+
const ref = refs[r];
|
|
325
|
+
const refId = sourceModel[ref.property];
|
|
326
|
+
if (refId == null) {
|
|
327
|
+
continue;
|
|
246
328
|
}
|
|
247
|
-
|
|
248
|
-
|
|
329
|
+
const targetPkId = String(refId);
|
|
330
|
+
const target = (_a = rootScopeState.modelsByEntity
|
|
331
|
+
.get(ref.targetEntity)) === null || _a === void 0 ? void 0 : _a.get(targetPkId);
|
|
332
|
+
if (target) {
|
|
333
|
+
linkSourceToTarget({
|
|
334
|
+
sourceEntity,
|
|
335
|
+
sourceModel,
|
|
336
|
+
sourceModelPkId,
|
|
337
|
+
targetEntity: ref.targetEntity,
|
|
338
|
+
targetModel: target,
|
|
339
|
+
collectionMembership: ensureCollectionMembership(rootScopeState)
|
|
340
|
+
});
|
|
249
341
|
}
|
|
250
342
|
}
|
|
251
|
-
obj[propertyName] = objectified[tableName][column];
|
|
252
|
-
return obj;
|
|
253
|
-
}, {});
|
|
254
|
-
return new entity.Model(propified);
|
|
255
|
-
});
|
|
256
|
-
};
|
|
257
|
-
/*
|
|
258
|
-
* Make objects (based on special table#column names) from flat database
|
|
259
|
-
* return value.
|
|
260
|
-
*/
|
|
261
|
-
const objectifyDatabaseResult = (result) => {
|
|
262
|
-
return Object.keys(result).reduce((obj, text) => {
|
|
263
|
-
const tableName = text.split('#')[0];
|
|
264
|
-
const column = text.split('#')[1];
|
|
265
|
-
if (!tableName || !column) {
|
|
266
|
-
throw new Error('Column names must be namespaced to table');
|
|
267
343
|
}
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
const createFromDatabase = (rows) => {
|
|
274
|
-
const result = Array.isArray(rows) ? rows : [rows];
|
|
275
|
-
const objectified = result.map(objectifyDatabaseResult);
|
|
276
|
-
const boified = objectified.map(mapToBos);
|
|
277
|
-
const clumps = clumpIntoGroups(boified);
|
|
278
|
-
const nested = clumps.map(nestClump);
|
|
279
|
-
const models = nested.map((n) => Object.values(n)[0]);
|
|
344
|
+
}
|
|
345
|
+
const models = new Array(rootScopeOrder.length);
|
|
346
|
+
for (let i = 0; i < rootScopeOrder.length; i++) {
|
|
347
|
+
models[i] = rootModelsByScopeKey.get(rootScopeOrder[i]);
|
|
348
|
+
}
|
|
280
349
|
const Collection = getEntityByModel(models[0]).Collection;
|
|
281
350
|
return new Collection({ models });
|
|
282
351
|
};
|