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
|
@@ -26,33 +26,33 @@ export interface ICoreIntegratedDriver extends ICore {
|
|
|
26
26
|
query: string,
|
|
27
27
|
values?: object,
|
|
28
28
|
errorHandler?: (err: Error) => never
|
|
29
|
-
) => T
|
|
29
|
+
) => Promise<T>;
|
|
30
30
|
|
|
31
31
|
// Execute a query returning either single model or undefined, or throws.
|
|
32
32
|
oneOrNone: <T extends IModel>(
|
|
33
33
|
query: string,
|
|
34
34
|
values?: object,
|
|
35
35
|
errorHandler?: (err: Error) => never
|
|
36
|
-
) => T | void
|
|
36
|
+
) => Promise<T | void>;
|
|
37
37
|
|
|
38
38
|
// Execute a query returning a Collection with at least one model, or throws.
|
|
39
39
|
many: <T extends ICollection<IModel>>(
|
|
40
40
|
query: string,
|
|
41
41
|
values?: object,
|
|
42
42
|
errorHandler?: (err: Error) => never
|
|
43
|
-
) => T
|
|
43
|
+
) => Promise<T>;
|
|
44
44
|
|
|
45
45
|
// Execute a query returning a Collection.
|
|
46
46
|
any: <T extends ICollection<IModel>>(
|
|
47
47
|
query: string,
|
|
48
48
|
values?: object,
|
|
49
49
|
errorHandler?: (err: Error) => never
|
|
50
|
-
) => T | void
|
|
50
|
+
) => Promise<T | void>;
|
|
51
51
|
|
|
52
52
|
// Execute a query returning null.
|
|
53
53
|
none: (
|
|
54
54
|
query: string,
|
|
55
55
|
values?: object,
|
|
56
56
|
errorHandler?: (err: Error) => never
|
|
57
|
-
) => void
|
|
57
|
+
) => Promise<void>;
|
|
58
58
|
}
|
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
/* eslint-disable max-len */
|
|
2
|
+
import { createForPGP } from './pgp';
|
|
3
|
+
import { createCore, IModel, ICollection } from '../core';
|
|
4
|
+
import { entities as orderEntities } from '../../test-utils/order/entities';
|
|
5
|
+
|
|
6
|
+
class SimpleModel implements IModel {
|
|
7
|
+
id: number;
|
|
8
|
+
constructor(props: any) {
|
|
9
|
+
this.id = props.id;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
class SimpleCollection implements ICollection<SimpleModel> {
|
|
13
|
+
models: Array<SimpleModel>;
|
|
14
|
+
constructor({ models }: any) {
|
|
15
|
+
this.models = models;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const simpleEntities = [
|
|
20
|
+
{
|
|
21
|
+
tableName: 'widget',
|
|
22
|
+
columns: ['id'] as any,
|
|
23
|
+
Model: SimpleModel,
|
|
24
|
+
Collection: SimpleCollection
|
|
25
|
+
}
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
const makeRow = (id: number) => ({
|
|
29
|
+
'widget#id': id
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
const makeOrderRow = (id: number, email: string) => ({
|
|
33
|
+
'order#id': id,
|
|
34
|
+
'order#email': email,
|
|
35
|
+
'order#browser_ip': null,
|
|
36
|
+
'order#browser_user_agent': null,
|
|
37
|
+
'order#kujo_imported_date': null,
|
|
38
|
+
'order#created_date': null,
|
|
39
|
+
'order#cancel_reason': null,
|
|
40
|
+
'order#cancelled_date': null,
|
|
41
|
+
'order#closed_date': null,
|
|
42
|
+
'order#processed_date': null,
|
|
43
|
+
'order#updated_date': null,
|
|
44
|
+
'order#note': null,
|
|
45
|
+
'order#subtotal_price': null,
|
|
46
|
+
'order#taxes_included': null,
|
|
47
|
+
'order#total_discounts': null,
|
|
48
|
+
'order#total_price': null,
|
|
49
|
+
'order#total_tax': null,
|
|
50
|
+
'order#total_weight': null,
|
|
51
|
+
'order#order_status_url': null,
|
|
52
|
+
'order#utm_source_id': null,
|
|
53
|
+
'order#utm_medium_id': null,
|
|
54
|
+
'order#utm_campaign': null,
|
|
55
|
+
'order#utm_content': null,
|
|
56
|
+
'order#utm_term': null
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
/* -------------------------------------------------------------------------*/
|
|
60
|
+
/* one ---------------------------------------------------------------------*/
|
|
61
|
+
/* -------------------------------------------------------------------------*/
|
|
62
|
+
|
|
63
|
+
describe('one', () => {
|
|
64
|
+
test('calls db.many and returns a single model', async () => {
|
|
65
|
+
const core = createCore({ entities: simpleEntities });
|
|
66
|
+
const db = { many: jest.fn().mockResolvedValue([makeRow(1)]) };
|
|
67
|
+
const pgp = createForPGP({ core, db });
|
|
68
|
+
|
|
69
|
+
const result = await pgp.one('SELECT ...', { id: 1 });
|
|
70
|
+
expect(db.many).toHaveBeenCalledWith('SELECT ...', { id: 1 });
|
|
71
|
+
expect(result.id).toEqual(1);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
test('throws when db.many returns empty array', async () => {
|
|
75
|
+
const core = createCore({ entities: simpleEntities });
|
|
76
|
+
const db = { many: jest.fn().mockResolvedValue([]) };
|
|
77
|
+
const pgp = createForPGP({ core, db });
|
|
78
|
+
|
|
79
|
+
await expect(pgp.one('SELECT ...')).rejects.toThrow();
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
test('throws when result nests into more than one model', async () => {
|
|
83
|
+
const core = createCore({ entities: simpleEntities });
|
|
84
|
+
const db = {
|
|
85
|
+
many: jest.fn().mockResolvedValue([makeRow(1), makeRow(2)])
|
|
86
|
+
};
|
|
87
|
+
const pgp = createForPGP({ core, db });
|
|
88
|
+
|
|
89
|
+
await expect(pgp.one('SELECT ...')).rejects.toThrow();
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
test('passes values to db.many', async () => {
|
|
93
|
+
const core = createCore({ entities: simpleEntities });
|
|
94
|
+
const db = { many: jest.fn().mockResolvedValue([makeRow(5)]) };
|
|
95
|
+
const pgp = createForPGP({ core, db });
|
|
96
|
+
|
|
97
|
+
await pgp.one('SELECT ... WHERE id = $1', [5]);
|
|
98
|
+
expect(db.many).toHaveBeenCalledWith('SELECT ... WHERE id = $1', [5]);
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
/* -------------------------------------------------------------------------*/
|
|
103
|
+
/* oneOrNone ---------------------------------------------------------------*/
|
|
104
|
+
/* -------------------------------------------------------------------------*/
|
|
105
|
+
|
|
106
|
+
describe('oneOrNone', () => {
|
|
107
|
+
test('returns a model when one result exists', async () => {
|
|
108
|
+
const core = createCore({ entities: simpleEntities });
|
|
109
|
+
const db = { any: jest.fn().mockResolvedValue([makeRow(1)]) };
|
|
110
|
+
const pgp = createForPGP({ core, db });
|
|
111
|
+
|
|
112
|
+
const result = await pgp.oneOrNone('SELECT ...', { id: 1 });
|
|
113
|
+
expect(db.any).toHaveBeenCalledWith('SELECT ...', { id: 1 });
|
|
114
|
+
expect(result!.id).toEqual(1);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
test('returns undefined when no results', async () => {
|
|
118
|
+
const core = createCore({ entities: simpleEntities });
|
|
119
|
+
const db = { any: jest.fn().mockResolvedValue([]) };
|
|
120
|
+
const pgp = createForPGP({ core, db });
|
|
121
|
+
|
|
122
|
+
const result = await pgp.oneOrNone('SELECT ...');
|
|
123
|
+
expect(result).toBeUndefined();
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
test('throws when more than one result', async () => {
|
|
127
|
+
const core = createCore({ entities: simpleEntities });
|
|
128
|
+
const db = {
|
|
129
|
+
any: jest.fn().mockResolvedValue([makeRow(1), makeRow(2)])
|
|
130
|
+
};
|
|
131
|
+
const pgp = createForPGP({ core, db });
|
|
132
|
+
|
|
133
|
+
await expect(pgp.oneOrNone('SELECT ...')).rejects.toThrow();
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
/* -------------------------------------------------------------------------*/
|
|
138
|
+
/* many --------------------------------------------------------------------*/
|
|
139
|
+
/* -------------------------------------------------------------------------*/
|
|
140
|
+
|
|
141
|
+
describe('many', () => {
|
|
142
|
+
test('returns a collection with at least one model', async () => {
|
|
143
|
+
const core = createCore({ entities: simpleEntities });
|
|
144
|
+
const db = {
|
|
145
|
+
any: jest.fn().mockResolvedValue([makeRow(1), makeRow(2)])
|
|
146
|
+
};
|
|
147
|
+
const pgp = createForPGP({ core, db });
|
|
148
|
+
|
|
149
|
+
const result: any = await pgp.many('SELECT ...');
|
|
150
|
+
expect(db.any).toHaveBeenCalledWith('SELECT ...', undefined);
|
|
151
|
+
expect(result.models.length).toEqual(2);
|
|
152
|
+
expect(result.models[0].id).toEqual(1);
|
|
153
|
+
expect(result.models[1].id).toEqual(2);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
test('works with a single result row', async () => {
|
|
157
|
+
const core = createCore({ entities: simpleEntities });
|
|
158
|
+
const db = { any: jest.fn().mockResolvedValue([makeRow(42)]) };
|
|
159
|
+
const pgp = createForPGP({ core, db });
|
|
160
|
+
|
|
161
|
+
const result: any = await pgp.many('SELECT ...');
|
|
162
|
+
expect(result.models.length).toEqual(1);
|
|
163
|
+
expect(result.models[0].id).toEqual(42);
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
test('throws when no results', async () => {
|
|
167
|
+
const core = createCore({ entities: simpleEntities });
|
|
168
|
+
const db = { any: jest.fn().mockResolvedValue([]) };
|
|
169
|
+
const pgp = createForPGP({ core, db });
|
|
170
|
+
|
|
171
|
+
await expect(pgp.many('SELECT ...')).rejects.toThrow();
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
test('passes values to db.any', async () => {
|
|
175
|
+
const core = createCore({ entities: simpleEntities });
|
|
176
|
+
const db = { any: jest.fn().mockResolvedValue([makeRow(1)]) };
|
|
177
|
+
const pgp = createForPGP({ core, db });
|
|
178
|
+
|
|
179
|
+
await pgp.many('SELECT ... WHERE x = $1', [10]);
|
|
180
|
+
expect(db.any).toHaveBeenCalledWith('SELECT ... WHERE x = $1', [10]);
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
/* -------------------------------------------------------------------------*/
|
|
185
|
+
/* any ---------------------------------------------------------------------*/
|
|
186
|
+
/* -------------------------------------------------------------------------*/
|
|
187
|
+
|
|
188
|
+
describe('any', () => {
|
|
189
|
+
test('returns a collection when results exist', async () => {
|
|
190
|
+
const core = createCore({ entities: simpleEntities });
|
|
191
|
+
const db = {
|
|
192
|
+
result: jest.fn().mockResolvedValue({
|
|
193
|
+
rows: [makeRow(1), makeRow(2)],
|
|
194
|
+
fields: [{ name: 'widget#id' }]
|
|
195
|
+
})
|
|
196
|
+
};
|
|
197
|
+
const pgp = createForPGP({ core, db });
|
|
198
|
+
|
|
199
|
+
const result: any = await pgp.any('SELECT ...');
|
|
200
|
+
expect(db.result).toHaveBeenCalledWith('SELECT ...', undefined);
|
|
201
|
+
expect(result.models.length).toEqual(2);
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
test('returns empty collection when no results', async () => {
|
|
205
|
+
const core = createCore({ entities: simpleEntities });
|
|
206
|
+
const db = {
|
|
207
|
+
result: jest.fn().mockResolvedValue({
|
|
208
|
+
rows: [],
|
|
209
|
+
fields: [{ name: 'widget#id' }]
|
|
210
|
+
})
|
|
211
|
+
};
|
|
212
|
+
const pgp = createForPGP({ core, db });
|
|
213
|
+
|
|
214
|
+
const result: any = await pgp.any('SELECT ...');
|
|
215
|
+
expect(result.models).toBeDefined();
|
|
216
|
+
expect(result.models.length).toEqual(0);
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
test('extracts table name from first field name', async () => {
|
|
220
|
+
const core = createCore({ entities: orderEntities });
|
|
221
|
+
const db = {
|
|
222
|
+
result: jest.fn().mockResolvedValue({
|
|
223
|
+
rows: [makeOrderRow(1, 'a@b.com')],
|
|
224
|
+
fields: [{ name: 'order#id' }]
|
|
225
|
+
})
|
|
226
|
+
};
|
|
227
|
+
const pgp = createForPGP({ core, db });
|
|
228
|
+
|
|
229
|
+
const result: any = await pgp.any('SELECT ...');
|
|
230
|
+
expect(result.models.length).toEqual(1);
|
|
231
|
+
expect(result.models[0].id).toEqual(1);
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
test('passes values to db.result', async () => {
|
|
235
|
+
const core = createCore({ entities: simpleEntities });
|
|
236
|
+
const db = {
|
|
237
|
+
result: jest.fn().mockResolvedValue({
|
|
238
|
+
rows: [],
|
|
239
|
+
fields: [{ name: 'widget#id' }]
|
|
240
|
+
})
|
|
241
|
+
};
|
|
242
|
+
const pgp = createForPGP({ core, db });
|
|
243
|
+
|
|
244
|
+
await pgp.any('SELECT ... WHERE x = $1', [5]);
|
|
245
|
+
expect(db.result).toHaveBeenCalledWith('SELECT ... WHERE x = $1', [5]);
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
/* -------------------------------------------------------------------------*/
|
|
250
|
+
/* none --------------------------------------------------------------------*/
|
|
251
|
+
/* -------------------------------------------------------------------------*/
|
|
252
|
+
|
|
253
|
+
describe('none', () => {
|
|
254
|
+
test('calls db.none and resolves to null', async () => {
|
|
255
|
+
const core = createCore({ entities: simpleEntities });
|
|
256
|
+
const db = { none: jest.fn().mockResolvedValue(undefined) };
|
|
257
|
+
const pgp = createForPGP({ core, db });
|
|
258
|
+
|
|
259
|
+
const result = await pgp.none('DELETE ...');
|
|
260
|
+
expect(db.none).toHaveBeenCalledWith('DELETE ...', undefined);
|
|
261
|
+
expect(result).toBeNull();
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
test('passes values to db.none', async () => {
|
|
265
|
+
const core = createCore({ entities: simpleEntities });
|
|
266
|
+
const db = { none: jest.fn().mockResolvedValue(undefined) };
|
|
267
|
+
const pgp = createForPGP({ core, db });
|
|
268
|
+
|
|
269
|
+
await pgp.none('DELETE ... WHERE id = $(id)', { id: 7 });
|
|
270
|
+
expect(db.none).toHaveBeenCalledWith('DELETE ... WHERE id = $(id)', {
|
|
271
|
+
id: 7
|
|
272
|
+
});
|
|
273
|
+
});
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
/* -------------------------------------------------------------------------*/
|
|
277
|
+
/* Error handling ----------------------------------------------------------*/
|
|
278
|
+
/* -------------------------------------------------------------------------*/
|
|
279
|
+
|
|
280
|
+
describe('error handling', () => {
|
|
281
|
+
test('defaultErrorHandler rethrows the error', async () => {
|
|
282
|
+
const core = createCore({ entities: simpleEntities });
|
|
283
|
+
const err = new Error('db error');
|
|
284
|
+
const db = { many: jest.fn().mockRejectedValue(err) };
|
|
285
|
+
const pgp = createForPGP({ core, db });
|
|
286
|
+
|
|
287
|
+
await expect(pgp.one('SELECT ...')).rejects.toThrow('db error');
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
test('defaultErrorHandler calls logError for non-QueryResultError', async () => {
|
|
291
|
+
const logError = jest.fn((err: Error) => {
|
|
292
|
+
throw err;
|
|
293
|
+
}) as any;
|
|
294
|
+
const core = createCore({ entities: simpleEntities });
|
|
295
|
+
const err = new Error('unexpected error');
|
|
296
|
+
const db = { many: jest.fn().mockRejectedValue(err) };
|
|
297
|
+
const pgp = createForPGP({ core, db, logError });
|
|
298
|
+
|
|
299
|
+
await expect(pgp.one('SELECT ...')).rejects.toThrow('unexpected error');
|
|
300
|
+
expect(logError).toHaveBeenCalledWith(err);
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
test('defaultErrorHandler does not call logError for QueryResultError', async () => {
|
|
304
|
+
const logError = jest.fn((err: Error) => {
|
|
305
|
+
throw err;
|
|
306
|
+
}) as any;
|
|
307
|
+
const core = createCore({ entities: simpleEntities });
|
|
308
|
+
const err = new Error('no data');
|
|
309
|
+
err.name = 'QueryResultError';
|
|
310
|
+
const db = { many: jest.fn().mockRejectedValue(err) };
|
|
311
|
+
const pgp = createForPGP({ core, db, logError });
|
|
312
|
+
|
|
313
|
+
await expect(pgp.one('SELECT ...')).rejects.toThrow('no data');
|
|
314
|
+
expect(logError).not.toHaveBeenCalled();
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
test('custom errorHandler overrides defaultErrorHandler', async () => {
|
|
318
|
+
const core = createCore({ entities: simpleEntities });
|
|
319
|
+
const err = new Error('db failure');
|
|
320
|
+
const db = { many: jest.fn().mockRejectedValue(err) };
|
|
321
|
+
const pgp = createForPGP({ core, db });
|
|
322
|
+
const customHandler = jest.fn((_err: Error) => {
|
|
323
|
+
throw new Error('custom handled');
|
|
324
|
+
}) as any;
|
|
325
|
+
|
|
326
|
+
await expect(
|
|
327
|
+
pgp.one('SELECT ...', undefined, customHandler)
|
|
328
|
+
).rejects.toThrow('custom handled');
|
|
329
|
+
expect(customHandler).toHaveBeenCalledWith(err);
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
test('custom errorHandler works for oneOrNone', async () => {
|
|
333
|
+
const core = createCore({ entities: simpleEntities });
|
|
334
|
+
const err = new Error('fail');
|
|
335
|
+
const db = { any: jest.fn().mockRejectedValue(err) };
|
|
336
|
+
const pgp = createForPGP({ core, db });
|
|
337
|
+
const customHandler = jest.fn((_err: Error) => {
|
|
338
|
+
throw new Error('caught');
|
|
339
|
+
}) as any;
|
|
340
|
+
|
|
341
|
+
await expect(
|
|
342
|
+
pgp.oneOrNone('SELECT ...', undefined, customHandler)
|
|
343
|
+
).rejects.toThrow('caught');
|
|
344
|
+
expect(customHandler).toHaveBeenCalledWith(err);
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
test('custom errorHandler works for many', async () => {
|
|
348
|
+
const core = createCore({ entities: simpleEntities });
|
|
349
|
+
const err = new Error('fail');
|
|
350
|
+
const db = { any: jest.fn().mockRejectedValue(err) };
|
|
351
|
+
const pgp = createForPGP({ core, db });
|
|
352
|
+
const customHandler = jest.fn((_err: Error) => {
|
|
353
|
+
throw new Error('caught');
|
|
354
|
+
}) as any;
|
|
355
|
+
|
|
356
|
+
await expect(
|
|
357
|
+
pgp.many('SELECT ...', undefined, customHandler)
|
|
358
|
+
).rejects.toThrow('caught');
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
test('custom errorHandler works for any', async () => {
|
|
362
|
+
const core = createCore({ entities: simpleEntities });
|
|
363
|
+
const err = new Error('fail');
|
|
364
|
+
const db = { result: jest.fn().mockRejectedValue(err) };
|
|
365
|
+
const pgp = createForPGP({ core, db });
|
|
366
|
+
const customHandler = jest.fn((_err: Error) => {
|
|
367
|
+
throw new Error('caught');
|
|
368
|
+
}) as any;
|
|
369
|
+
|
|
370
|
+
await expect(
|
|
371
|
+
pgp.any('SELECT ...', undefined, customHandler)
|
|
372
|
+
).rejects.toThrow('caught');
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
test('custom errorHandler works for none', async () => {
|
|
376
|
+
const core = createCore({ entities: simpleEntities });
|
|
377
|
+
const err = new Error('fail');
|
|
378
|
+
const db = { none: jest.fn().mockRejectedValue(err) };
|
|
379
|
+
const pgp = createForPGP({ core, db });
|
|
380
|
+
const customHandler = jest.fn((_err: Error) => {
|
|
381
|
+
throw new Error('caught');
|
|
382
|
+
}) as any;
|
|
383
|
+
|
|
384
|
+
await expect(
|
|
385
|
+
pgp.none('DELETE ...', undefined, customHandler)
|
|
386
|
+
).rejects.toThrow('caught');
|
|
387
|
+
});
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
/* -------------------------------------------------------------------------*/
|
|
391
|
+
/* Returned object structure -----------------------------------------------*/
|
|
392
|
+
/* -------------------------------------------------------------------------*/
|
|
393
|
+
|
|
394
|
+
describe('createForPGP return structure', () => {
|
|
395
|
+
test('includes all core methods', () => {
|
|
396
|
+
const core = createCore({ entities: simpleEntities });
|
|
397
|
+
const db = {
|
|
398
|
+
many: jest.fn(),
|
|
399
|
+
any: jest.fn(),
|
|
400
|
+
result: jest.fn(),
|
|
401
|
+
none: jest.fn()
|
|
402
|
+
};
|
|
403
|
+
const pgp = createForPGP({ core, db });
|
|
404
|
+
|
|
405
|
+
expect(typeof pgp.createFromDatabase).toBe('function');
|
|
406
|
+
expect(typeof pgp.createOneFromDatabase).toBe('function');
|
|
407
|
+
expect(typeof pgp.createOneOrNoneFromDatabase).toBe('function');
|
|
408
|
+
expect(typeof pgp.createManyFromDatabase).toBe('function');
|
|
409
|
+
expect(typeof pgp.createAnyFromDatabase).toBe('function');
|
|
410
|
+
expect(typeof pgp.getEntityByModel).toBe('function');
|
|
411
|
+
expect(typeof pgp.getEntityByTableName).toBe('function');
|
|
412
|
+
expect(pgp.tables).toBeDefined();
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
test('includes all query methods', () => {
|
|
416
|
+
const core = createCore({ entities: simpleEntities });
|
|
417
|
+
const db = {
|
|
418
|
+
many: jest.fn(),
|
|
419
|
+
any: jest.fn(),
|
|
420
|
+
result: jest.fn(),
|
|
421
|
+
none: jest.fn()
|
|
422
|
+
};
|
|
423
|
+
const pgp = createForPGP({ core, db });
|
|
424
|
+
|
|
425
|
+
expect(typeof pgp.one).toBe('function');
|
|
426
|
+
expect(typeof pgp.oneOrNone).toBe('function');
|
|
427
|
+
expect(typeof pgp.many).toBe('function');
|
|
428
|
+
expect(typeof pgp.any).toBe('function');
|
|
429
|
+
expect(typeof pgp.none).toBe('function');
|
|
430
|
+
});
|
|
431
|
+
|
|
432
|
+
test('exposes db reference', () => {
|
|
433
|
+
const core = createCore({ entities: simpleEntities });
|
|
434
|
+
const db = {
|
|
435
|
+
many: jest.fn(),
|
|
436
|
+
any: jest.fn(),
|
|
437
|
+
result: jest.fn(),
|
|
438
|
+
none: jest.fn()
|
|
439
|
+
};
|
|
440
|
+
const pgp = createForPGP({ core, db });
|
|
441
|
+
|
|
442
|
+
expect(pgp.db).toBe(db);
|
|
443
|
+
});
|
|
444
|
+
});
|
|
@@ -23,7 +23,7 @@ export const createForPGP = ({
|
|
|
23
23
|
query: string,
|
|
24
24
|
values?: object,
|
|
25
25
|
errorHandler = defaultErrorHandler
|
|
26
|
-
): T => {
|
|
26
|
+
): Promise<T> => {
|
|
27
27
|
return db
|
|
28
28
|
.many(query, values)
|
|
29
29
|
.then((rows: any) => core.createOneFromDatabase(rows))
|
|
@@ -34,7 +34,7 @@ export const createForPGP = ({
|
|
|
34
34
|
query: string,
|
|
35
35
|
values?: object,
|
|
36
36
|
errorHandler = defaultErrorHandler
|
|
37
|
-
): T | void => {
|
|
37
|
+
): Promise<T | void> => {
|
|
38
38
|
return db
|
|
39
39
|
.any(query, values)
|
|
40
40
|
.then((rows: any) => core.createOneOrNoneFromDatabase(rows))
|
|
@@ -45,7 +45,7 @@ export const createForPGP = ({
|
|
|
45
45
|
query: string,
|
|
46
46
|
values?: object,
|
|
47
47
|
errorHandler = defaultErrorHandler
|
|
48
|
-
): T => {
|
|
48
|
+
): Promise<T> => {
|
|
49
49
|
return db
|
|
50
50
|
.any(query, values)
|
|
51
51
|
.then((rows: any) => core.createManyFromDatabase(rows))
|
|
@@ -56,7 +56,7 @@ export const createForPGP = ({
|
|
|
56
56
|
query: string,
|
|
57
57
|
values?: object,
|
|
58
58
|
errorHandler = defaultErrorHandler
|
|
59
|
-
): T | void => {
|
|
59
|
+
): Promise<T | void> => {
|
|
60
60
|
return db
|
|
61
61
|
.result(query, values)
|
|
62
62
|
.then((result: any) =>
|
|
@@ -72,7 +72,7 @@ export const createForPGP = ({
|
|
|
72
72
|
query: string,
|
|
73
73
|
values?: object,
|
|
74
74
|
errorHandler = defaultErrorHandler
|
|
75
|
-
): void => {
|
|
75
|
+
): Promise<void> => {
|
|
76
76
|
return db
|
|
77
77
|
.none(query, values)
|
|
78
78
|
.then(() => null)
|