@e22m4u/js-repository 0.0.31
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/.c8rc +9 -0
- package/.commitlintrc +5 -0
- package/.editorconfig +13 -0
- package/.eslintignore +1 -0
- package/.eslintrc.cjs +27 -0
- package/.husky/commit-msg +4 -0
- package/.husky/pre-commit +9 -0
- package/.mocharc.cjs +7 -0
- package/.prettierrc +7 -0
- package/LICENSE +21 -0
- package/README.md +523 -0
- package/mocha.setup.js +10 -0
- package/package.json +57 -0
- package/src/adapter/adapter-loader.d.ts +16 -0
- package/src/adapter/adapter-loader.js +63 -0
- package/src/adapter/adapter-loader.spec.js +31 -0
- package/src/adapter/adapter-registry.d.ts +14 -0
- package/src/adapter/adapter-registry.js +36 -0
- package/src/adapter/adapter-registry.spec.js +36 -0
- package/src/adapter/adapter.d.ts +118 -0
- package/src/adapter/adapter.js +181 -0
- package/src/adapter/adapter.spec.js +144 -0
- package/src/adapter/builtin/memory-adapter.d.ts +118 -0
- package/src/adapter/builtin/memory-adapter.js +342 -0
- package/src/adapter/builtin/memory-adapter.spec.js +2925 -0
- package/src/adapter/decorator/data-sanitizing-decorator.d.ts +13 -0
- package/src/adapter/decorator/data-sanitizing-decorator.js +44 -0
- package/src/adapter/decorator/data-sanitizing-decorator.spec.js +59 -0
- package/src/adapter/decorator/data-validation-decorator.d.ts +13 -0
- package/src/adapter/decorator/data-validation-decorator.js +41 -0
- package/src/adapter/decorator/data-validation-decorator.spec.js +59 -0
- package/src/adapter/decorator/default-values-decorator.d.ts +13 -0
- package/src/adapter/decorator/default-values-decorator.js +57 -0
- package/src/adapter/decorator/default-values-decorator.spec.js +141 -0
- package/src/adapter/decorator/fields-filtering-decorator.d.ts +13 -0
- package/src/adapter/decorator/fields-filtering-decorator.js +72 -0
- package/src/adapter/decorator/fields-filtering-decorator.spec.js +119 -0
- package/src/adapter/decorator/inclusion-decorator.d.ts +13 -0
- package/src/adapter/decorator/inclusion-decorator.js +78 -0
- package/src/adapter/decorator/inclusion-decorator.spec.js +117 -0
- package/src/adapter/decorator/index.d.ts +5 -0
- package/src/adapter/decorator/index.js +5 -0
- package/src/adapter/index.d.ts +3 -0
- package/src/adapter/index.js +3 -0
- package/src/definition/datasource/datasource-definition-validator.d.ts +14 -0
- package/src/definition/datasource/datasource-definition-validator.js +33 -0
- package/src/definition/datasource/datasource-definition-validator.spec.js +63 -0
- package/src/definition/datasource/datasource-definition.d.ts +7 -0
- package/src/definition/datasource/index.d.ts +2 -0
- package/src/definition/datasource/index.js +1 -0
- package/src/definition/definition-registry.d.ts +50 -0
- package/src/definition/definition-registry.js +98 -0
- package/src/definition/definition-registry.spec.js +78 -0
- package/src/definition/index.d.ts +3 -0
- package/src/definition/index.js +3 -0
- package/src/definition/model/index.d.ts +7 -0
- package/src/definition/model/index.js +6 -0
- package/src/definition/model/model-data-sanitizer.d.ts +15 -0
- package/src/definition/model/model-data-sanitizer.js +33 -0
- package/src/definition/model/model-data-validator.d.ts +32 -0
- package/src/definition/model/model-data-validator.js +144 -0
- package/src/definition/model/model-data-validator.spec.js +1889 -0
- package/src/definition/model/model-definition-utils.d.ts +161 -0
- package/src/definition/model/model-definition-utils.js +371 -0
- package/src/definition/model/model-definition-utils.spec.js +1474 -0
- package/src/definition/model/model-definition-validator.d.ts +14 -0
- package/src/definition/model/model-definition-validator.js +83 -0
- package/src/definition/model/model-definition-validator.spec.js +143 -0
- package/src/definition/model/model-definition.d.ts +28 -0
- package/src/definition/model/properties/data-type.d.ts +11 -0
- package/src/definition/model/properties/data-type.js +11 -0
- package/src/definition/model/properties/default-values-definition-validator.d.ts +15 -0
- package/src/definition/model/properties/default-values-definition-validator.js +53 -0
- package/src/definition/model/properties/default-values-definition-validator.spec.js +136 -0
- package/src/definition/model/properties/index.d.ts +5 -0
- package/src/definition/model/properties/index.js +4 -0
- package/src/definition/model/properties/primary-keys-definition-validator.d.ts +15 -0
- package/src/definition/model/properties/primary-keys-definition-validator.js +55 -0
- package/src/definition/model/properties/primary-keys-definition-validator.spec.js +145 -0
- package/src/definition/model/properties/properties-definition-validator.d.ts +15 -0
- package/src/definition/model/properties/properties-definition-validator.js +194 -0
- package/src/definition/model/properties/properties-definition-validator.spec.js +373 -0
- package/src/definition/model/properties/property-definition.d.ts +20 -0
- package/src/definition/model/relations/index.d.ts +3 -0
- package/src/definition/model/relations/index.js +2 -0
- package/src/definition/model/relations/relation-definition.d.ts +254 -0
- package/src/definition/model/relations/relation-type.d.ts +9 -0
- package/src/definition/model/relations/relation-type.js +9 -0
- package/src/definition/model/relations/relations-definition-validator.d.ts +15 -0
- package/src/definition/model/relations/relations-definition-validator.js +449 -0
- package/src/definition/model/relations/relations-definition-validator.spec.js +772 -0
- package/src/errors/index.d.ts +3 -0
- package/src/errors/index.js +3 -0
- package/src/errors/invalid-argument-error.d.ts +6 -0
- package/src/errors/invalid-argument-error.js +6 -0
- package/src/errors/invalid-argument-error.spec.js +33 -0
- package/src/errors/invalid-operator-value-error.d.ts +13 -0
- package/src/errors/invalid-operator-value-error.js +24 -0
- package/src/errors/invalid-operator-value-error.spec.js +11 -0
- package/src/errors/not-implemented-error.d.ts +6 -0
- package/src/errors/not-implemented-error.js +6 -0
- package/src/errors/not-implemented-error.spec.js +33 -0
- package/src/filter/fields-clause-tool.d.ts +38 -0
- package/src/filter/fields-clause-tool.js +88 -0
- package/src/filter/fields-clause-tool.spec.js +133 -0
- package/src/filter/filter.d.ts +335 -0
- package/src/filter/include-clause-tool.d.ts +53 -0
- package/src/filter/include-clause-tool.js +364 -0
- package/src/filter/include-clause-tool.spec.js +653 -0
- package/src/filter/index.d.ts +7 -0
- package/src/filter/index.js +6 -0
- package/src/filter/operator-clause-tool.d.ts +223 -0
- package/src/filter/operator-clause-tool.js +515 -0
- package/src/filter/operator-clause-tool.spec.js +1064 -0
- package/src/filter/order-clause-tool.d.ts +32 -0
- package/src/filter/order-clause-tool.js +97 -0
- package/src/filter/order-clause-tool.spec.js +438 -0
- package/src/filter/slice-clause-tool.d.ts +30 -0
- package/src/filter/slice-clause-tool.js +65 -0
- package/src/filter/slice-clause-tool.spec.js +117 -0
- package/src/filter/where-clause-tool.d.ts +23 -0
- package/src/filter/where-clause-tool.js +165 -0
- package/src/filter/where-clause-tool.spec.js +280 -0
- package/src/index.d.ts +9 -0
- package/src/index.js +8 -0
- package/src/relations/belongs-to-resolver.d.ts +46 -0
- package/src/relations/belongs-to-resolver.js +242 -0
- package/src/relations/belongs-to-resolver.spec.js +1047 -0
- package/src/relations/has-many-resolver.d.ts +67 -0
- package/src/relations/has-many-resolver.js +317 -0
- package/src/relations/has-many-resolver.spec.js +2911 -0
- package/src/relations/has-one-resolver.d.ts +67 -0
- package/src/relations/has-one-resolver.js +311 -0
- package/src/relations/has-one-resolver.spec.js +2274 -0
- package/src/relations/index.d.ts +4 -0
- package/src/relations/index.js +4 -0
- package/src/relations/references-many-resolver.d.ts +27 -0
- package/src/relations/references-many-resolver.js +113 -0
- package/src/relations/references-many-resolver.spec.js +631 -0
- package/src/repository/index.d.ts +2 -0
- package/src/repository/index.js +2 -0
- package/src/repository/repository-registry.d.ts +29 -0
- package/src/repository/repository-registry.js +57 -0
- package/src/repository/repository-registry.spec.js +38 -0
- package/src/repository/repository.d.ts +164 -0
- package/src/repository/repository.js +207 -0
- package/src/repository/repository.spec.js +202 -0
- package/src/schema.d.ts +37 -0
- package/src/schema.js +41 -0
- package/src/types.d.ts +30 -0
- package/src/utils/capitalize.d.ts +6 -0
- package/src/utils/capitalize.js +10 -0
- package/src/utils/capitalize.spec.js +14 -0
- package/src/utils/clone-deep.d.ts +6 -0
- package/src/utils/clone-deep.js +61 -0
- package/src/utils/clone-deep.spec.js +28 -0
- package/src/utils/exclude-object-keys.d.ts +10 -0
- package/src/utils/exclude-object-keys.js +20 -0
- package/src/utils/exclude-object-keys.spec.js +49 -0
- package/src/utils/get-ctor-name.d.ts +6 -0
- package/src/utils/get-ctor-name.js +11 -0
- package/src/utils/get-ctor-name.spec.js +17 -0
- package/src/utils/get-value-by-path.d.ts +12 -0
- package/src/utils/get-value-by-path.js +23 -0
- package/src/utils/get-value-by-path.spec.js +36 -0
- package/src/utils/index.d.ts +10 -0
- package/src/utils/index.js +10 -0
- package/src/utils/is-ctor.d.ts +7 -0
- package/src/utils/is-ctor.js +10 -0
- package/src/utils/is-ctor.spec.js +26 -0
- package/src/utils/is-pure-object.d.ts +6 -0
- package/src/utils/is-pure-object.js +15 -0
- package/src/utils/is-pure-object.spec.js +25 -0
- package/src/utils/select-object-keys.d.ts +10 -0
- package/src/utils/select-object-keys.js +37 -0
- package/src/utils/select-object-keys.spec.js +40 -0
- package/src/utils/singularize.d.ts +6 -0
- package/src/utils/singularize.js +22 -0
- package/src/utils/singularize.spec.js +23 -0
- package/src/utils/string-to-regexp.d.ts +10 -0
- package/src/utils/string-to-regexp.js +22 -0
- package/src/utils/string-to-regexp.spec.js +35 -0
- package/tsconfig.json +9 -0
|
@@ -0,0 +1,1047 @@
|
|
|
1
|
+
import {expect} from 'chai';
|
|
2
|
+
import {Schema} from '../schema.js';
|
|
3
|
+
import {format} from '@e22m4u/js-format';
|
|
4
|
+
import {DataType} from '../definition/index.js';
|
|
5
|
+
import {RelationType} from '../definition/index.js';
|
|
6
|
+
import {BelongsToResolver} from './belongs-to-resolver.js';
|
|
7
|
+
import {DEFAULT_PRIMARY_KEY_PROPERTY_NAME as DEF_PK} from '../definition/index.js';
|
|
8
|
+
|
|
9
|
+
describe('BelongsToResolver', function () {
|
|
10
|
+
describe('includeTo', function () {
|
|
11
|
+
it('requires the "entities" parameter to be an array', async function () {
|
|
12
|
+
const S = new Schema();
|
|
13
|
+
const R = S.getService(BelongsToResolver);
|
|
14
|
+
const error = v =>
|
|
15
|
+
format(
|
|
16
|
+
'The parameter "entities" of BelongsToResolver.includeTo requires ' +
|
|
17
|
+
'an Array of Object, but %s given.',
|
|
18
|
+
v,
|
|
19
|
+
);
|
|
20
|
+
const throwable = v =>
|
|
21
|
+
R.includeTo(v, 'sourceName', 'targetName', 'relationName');
|
|
22
|
+
await expect(throwable('')).to.be.rejectedWith(error('""'));
|
|
23
|
+
await expect(throwable('str')).to.be.rejectedWith(error('"str"'));
|
|
24
|
+
await expect(throwable(10)).to.be.rejectedWith(error('10'));
|
|
25
|
+
await expect(throwable(true)).to.be.rejectedWith(error('true'));
|
|
26
|
+
await expect(throwable(false)).to.be.rejectedWith(error('false'));
|
|
27
|
+
await expect(throwable({})).to.be.rejectedWith(error('Object'));
|
|
28
|
+
await expect(throwable(undefined)).to.be.rejectedWith(error('undefined'));
|
|
29
|
+
await expect(throwable(null)).to.be.rejectedWith(error('null'));
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('requires elements of the "entities" parameter to be an Object', async function () {
|
|
33
|
+
const S = new Schema();
|
|
34
|
+
const R = S.getService(BelongsToResolver);
|
|
35
|
+
const error = v =>
|
|
36
|
+
format(
|
|
37
|
+
'The parameter "entities" of BelongsToResolver.includeTo requires ' +
|
|
38
|
+
'an Array of Object, but %s given.',
|
|
39
|
+
v,
|
|
40
|
+
);
|
|
41
|
+
const throwable = v =>
|
|
42
|
+
R.includeTo([v], 'sourceName', 'targetName', 'relationName');
|
|
43
|
+
await expect(throwable('')).to.be.rejectedWith(error('""'));
|
|
44
|
+
await expect(throwable('str')).to.be.rejectedWith(error('"str"'));
|
|
45
|
+
await expect(throwable(10)).to.be.rejectedWith(error('10'));
|
|
46
|
+
await expect(throwable(true)).to.be.rejectedWith(error('true'));
|
|
47
|
+
await expect(throwable(false)).to.be.rejectedWith(error('false'));
|
|
48
|
+
await expect(throwable([])).to.be.rejectedWith(error('Array'));
|
|
49
|
+
await expect(throwable(undefined)).to.be.rejectedWith(error('undefined'));
|
|
50
|
+
await expect(throwable(null)).to.be.rejectedWith(error('null'));
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('requires the "sourceName" parameter to be a non-empty string', async function () {
|
|
54
|
+
const S = new Schema();
|
|
55
|
+
const R = S.getService(BelongsToResolver);
|
|
56
|
+
const error = v =>
|
|
57
|
+
format(
|
|
58
|
+
'The parameter "sourceName" of BelongsToResolver.includeTo requires ' +
|
|
59
|
+
'a non-empty String, but %s given.',
|
|
60
|
+
v,
|
|
61
|
+
);
|
|
62
|
+
const throwable = v => R.includeTo([], v, 'targetName', 'relationName');
|
|
63
|
+
await expect(throwable('')).to.be.rejectedWith(error('""'));
|
|
64
|
+
await expect(throwable(10)).to.be.rejectedWith(error('10'));
|
|
65
|
+
await expect(throwable(true)).to.be.rejectedWith(error('true'));
|
|
66
|
+
await expect(throwable(false)).to.be.rejectedWith(error('false'));
|
|
67
|
+
await expect(throwable([])).to.be.rejectedWith(error('Array'));
|
|
68
|
+
await expect(throwable({})).to.be.rejectedWith(error('Object'));
|
|
69
|
+
await expect(throwable(undefined)).to.be.rejectedWith(error('undefined'));
|
|
70
|
+
await expect(throwable(null)).to.be.rejectedWith(error('null'));
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('requires the "targetName" parameter to be a non-empty string', async function () {
|
|
74
|
+
const S = new Schema();
|
|
75
|
+
const R = S.getService(BelongsToResolver);
|
|
76
|
+
const error = v =>
|
|
77
|
+
format(
|
|
78
|
+
'The parameter "targetName" of BelongsToResolver.includeTo requires ' +
|
|
79
|
+
'a non-empty String, but %s given.',
|
|
80
|
+
v,
|
|
81
|
+
);
|
|
82
|
+
const throwable = v => R.includeTo([], 'sourceName', v, 'relationName');
|
|
83
|
+
await expect(throwable('')).to.be.rejectedWith(error('""'));
|
|
84
|
+
await expect(throwable(10)).to.be.rejectedWith(error('10'));
|
|
85
|
+
await expect(throwable(true)).to.be.rejectedWith(error('true'));
|
|
86
|
+
await expect(throwable(false)).to.be.rejectedWith(error('false'));
|
|
87
|
+
await expect(throwable([])).to.be.rejectedWith(error('Array'));
|
|
88
|
+
await expect(throwable({})).to.be.rejectedWith(error('Object'));
|
|
89
|
+
await expect(throwable(undefined)).to.be.rejectedWith(error('undefined'));
|
|
90
|
+
await expect(throwable(null)).to.be.rejectedWith(error('null'));
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it('requires the "relationName" parameter to be a non-empty string', async function () {
|
|
94
|
+
const S = new Schema();
|
|
95
|
+
const R = S.getService(BelongsToResolver);
|
|
96
|
+
const error = v =>
|
|
97
|
+
format(
|
|
98
|
+
'The parameter "relationName" of BelongsToResolver.includeTo requires ' +
|
|
99
|
+
'a non-empty String, but %s given.',
|
|
100
|
+
v,
|
|
101
|
+
);
|
|
102
|
+
const throwable = v => R.includeTo([], 'sourceName', 'targetName', v);
|
|
103
|
+
await expect(throwable('')).to.be.rejectedWith(error('""'));
|
|
104
|
+
await expect(throwable(10)).to.be.rejectedWith(error('10'));
|
|
105
|
+
await expect(throwable(true)).to.be.rejectedWith(error('true'));
|
|
106
|
+
await expect(throwable(false)).to.be.rejectedWith(error('false'));
|
|
107
|
+
await expect(throwable([])).to.be.rejectedWith(error('Array'));
|
|
108
|
+
await expect(throwable({})).to.be.rejectedWith(error('Object'));
|
|
109
|
+
await expect(throwable(undefined)).to.be.rejectedWith(error('undefined'));
|
|
110
|
+
await expect(throwable(null)).to.be.rejectedWith(error('null'));
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it('requires the provided parameter "foreignKey" to be a string', async function () {
|
|
114
|
+
const S = new Schema();
|
|
115
|
+
const R = S.getService(BelongsToResolver);
|
|
116
|
+
const error = v =>
|
|
117
|
+
format(
|
|
118
|
+
'The provided parameter "foreignKey" of BelongsToResolver.includeTo ' +
|
|
119
|
+
'should be a String, but %s given.',
|
|
120
|
+
v,
|
|
121
|
+
);
|
|
122
|
+
const throwable = v =>
|
|
123
|
+
R.includeTo([], 'sourceName', 'targetName', 'relationName', v);
|
|
124
|
+
await expect(throwable(10)).to.be.rejectedWith(error('10'));
|
|
125
|
+
await expect(throwable(true)).to.be.rejectedWith(error('true'));
|
|
126
|
+
await expect(throwable([])).to.be.rejectedWith(error('Array'));
|
|
127
|
+
await expect(throwable({})).to.be.rejectedWith(error('Object'));
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it('requires the provided parameter "scope" to be an object', async function () {
|
|
131
|
+
const S = new Schema();
|
|
132
|
+
const R = S.getService(BelongsToResolver);
|
|
133
|
+
const error = v =>
|
|
134
|
+
format(
|
|
135
|
+
'The provided parameter "scope" of BelongsToResolver.includeTo ' +
|
|
136
|
+
'should be an Object, but %s given.',
|
|
137
|
+
v,
|
|
138
|
+
);
|
|
139
|
+
const throwable = v =>
|
|
140
|
+
R.includeTo(
|
|
141
|
+
[],
|
|
142
|
+
'sourceName',
|
|
143
|
+
'targetName',
|
|
144
|
+
'relationName',
|
|
145
|
+
undefined,
|
|
146
|
+
v,
|
|
147
|
+
);
|
|
148
|
+
await expect(throwable('str')).to.be.rejectedWith(error('"str"'));
|
|
149
|
+
await expect(throwable(10)).to.be.rejectedWith(error('10'));
|
|
150
|
+
await expect(throwable(true)).to.be.rejectedWith(error('true'));
|
|
151
|
+
await expect(throwable([])).to.be.rejectedWith(error('Array'));
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it('throws an error if the given target model is not found', async function () {
|
|
155
|
+
const S = new Schema();
|
|
156
|
+
S.defineModel({name: 'source'});
|
|
157
|
+
const R = S.getService(BelongsToResolver);
|
|
158
|
+
const promise = R.includeTo([], 'source', 'target', 'relation');
|
|
159
|
+
await expect(promise).to.be.rejectedWith(
|
|
160
|
+
'The model "target" is not defined',
|
|
161
|
+
);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it('throws an error if the given target model does not have a datasource', async function () {
|
|
165
|
+
const S = new Schema();
|
|
166
|
+
S.defineModel({name: 'target'});
|
|
167
|
+
const R = S.getService(BelongsToResolver);
|
|
168
|
+
const promise = R.includeTo([], 'source', 'target', 'relation');
|
|
169
|
+
await expect(promise).to.be.rejectedWith(
|
|
170
|
+
'The model "target" does not have a specified datasource.',
|
|
171
|
+
);
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it('does not throw an error if a relation target is not found', async function () {
|
|
175
|
+
const S = new Schema();
|
|
176
|
+
S.defineDatasource({name: 'datasource', adapter: 'memory'});
|
|
177
|
+
S.defineModel({name: 'source', datasource: 'datasource'});
|
|
178
|
+
S.defineModel({name: 'target', datasource: 'datasource'});
|
|
179
|
+
const sourceRel = S.getRepository('source');
|
|
180
|
+
const source = await sourceRel.create({parentId: 10});
|
|
181
|
+
const R = S.getService(BelongsToResolver);
|
|
182
|
+
await R.includeTo([source], 'source', 'target', 'parent');
|
|
183
|
+
expect(source).to.be.eql({
|
|
184
|
+
[DEF_PK]: source[DEF_PK],
|
|
185
|
+
parentId: 10,
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
it('includes if a primary key is not defined in the target model', async function () {
|
|
190
|
+
const S = new Schema();
|
|
191
|
+
S.defineDatasource({name: 'datasource', adapter: 'memory'});
|
|
192
|
+
S.defineModel({name: 'source', datasource: 'datasource'});
|
|
193
|
+
S.defineModel({name: 'target', datasource: 'datasource'});
|
|
194
|
+
const sourceRep = S.getRepository('source');
|
|
195
|
+
const targetRep = S.getRepository('target');
|
|
196
|
+
const target = await targetRep.create({});
|
|
197
|
+
expect(target).to.be.eql({[DEF_PK]: target[DEF_PK]});
|
|
198
|
+
const source = await sourceRep.create({parentId: target[DEF_PK]});
|
|
199
|
+
expect(source).to.be.eql({
|
|
200
|
+
[DEF_PK]: source[DEF_PK],
|
|
201
|
+
parentId: target[DEF_PK],
|
|
202
|
+
});
|
|
203
|
+
const R = S.getService(BelongsToResolver);
|
|
204
|
+
await R.includeTo([source], 'source', 'target', 'parent');
|
|
205
|
+
expect(source).to.be.eql({
|
|
206
|
+
[DEF_PK]: source[DEF_PK],
|
|
207
|
+
parentId: target[DEF_PK],
|
|
208
|
+
parent: target,
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
it('includes if the target model has a custom primary key', async function () {
|
|
213
|
+
const S = new Schema();
|
|
214
|
+
S.defineDatasource({name: 'datasource', adapter: 'memory'});
|
|
215
|
+
S.defineModel({name: 'source', datasource: 'datasource'});
|
|
216
|
+
S.defineModel({
|
|
217
|
+
name: 'target',
|
|
218
|
+
datasource: 'datasource',
|
|
219
|
+
properties: {
|
|
220
|
+
myId: {
|
|
221
|
+
type: DataType.NUMBER,
|
|
222
|
+
primaryKey: true,
|
|
223
|
+
},
|
|
224
|
+
},
|
|
225
|
+
});
|
|
226
|
+
const sourceRep = S.getRepository('source');
|
|
227
|
+
const targetRep = S.getRepository('target');
|
|
228
|
+
const target = await targetRep.create({});
|
|
229
|
+
expect(target).to.be.eql({myId: target.myId});
|
|
230
|
+
const source = await sourceRep.create({parentId: target.myId});
|
|
231
|
+
expect(source).to.be.eql({
|
|
232
|
+
[DEF_PK]: source[DEF_PK],
|
|
233
|
+
parentId: target.myId,
|
|
234
|
+
});
|
|
235
|
+
const R = S.getService(BelongsToResolver);
|
|
236
|
+
await R.includeTo([source], 'source', 'target', 'parent');
|
|
237
|
+
expect(source).to.be.eql({
|
|
238
|
+
[DEF_PK]: source[DEF_PK],
|
|
239
|
+
parentId: target.myId,
|
|
240
|
+
parent: target,
|
|
241
|
+
});
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
it('includes if the source model has a custom primary key', async function () {
|
|
245
|
+
const S = new Schema();
|
|
246
|
+
S.defineDatasource({name: 'datasource', adapter: 'memory'});
|
|
247
|
+
S.defineModel({
|
|
248
|
+
name: 'source',
|
|
249
|
+
datasource: 'datasource',
|
|
250
|
+
properties: {
|
|
251
|
+
myId: {
|
|
252
|
+
type: DataType.NUMBER,
|
|
253
|
+
primaryKey: true,
|
|
254
|
+
},
|
|
255
|
+
},
|
|
256
|
+
});
|
|
257
|
+
S.defineModel({name: 'target', datasource: 'datasource'});
|
|
258
|
+
const sourceRep = S.getRepository('source');
|
|
259
|
+
const targetRep = S.getRepository('target');
|
|
260
|
+
const target = await targetRep.create({});
|
|
261
|
+
expect(target).to.be.eql({[DEF_PK]: target[DEF_PK]});
|
|
262
|
+
const source = await sourceRep.create({parentId: target[DEF_PK]});
|
|
263
|
+
expect(source).to.be.eql({
|
|
264
|
+
myId: source.myId,
|
|
265
|
+
parentId: target[DEF_PK],
|
|
266
|
+
});
|
|
267
|
+
const R = S.getService(BelongsToResolver);
|
|
268
|
+
await R.includeTo([source], 'source', 'target', 'parent');
|
|
269
|
+
expect(source).to.be.eql({
|
|
270
|
+
myId: source.myId,
|
|
271
|
+
parentId: target[DEF_PK],
|
|
272
|
+
parent: target,
|
|
273
|
+
});
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
it('includes if the property "foreignKey" is specified', async function () {
|
|
277
|
+
const S = new Schema();
|
|
278
|
+
S.defineDatasource({name: 'datasource', adapter: 'memory'});
|
|
279
|
+
S.defineModel({name: 'source', datasource: 'datasource'});
|
|
280
|
+
S.defineModel({name: 'target', datasource: 'datasource'});
|
|
281
|
+
const sourceRep = S.getRepository('source');
|
|
282
|
+
const targetRep = S.getRepository('target');
|
|
283
|
+
const target = await targetRep.create({});
|
|
284
|
+
expect(target).to.be.eql({[DEF_PK]: target[DEF_PK]});
|
|
285
|
+
const source = await sourceRep.create({parentId: target[DEF_PK]});
|
|
286
|
+
expect(source).to.be.eql({
|
|
287
|
+
[DEF_PK]: source[DEF_PK],
|
|
288
|
+
parentId: target[DEF_PK],
|
|
289
|
+
});
|
|
290
|
+
const R = S.getService(BelongsToResolver);
|
|
291
|
+
await R.includeTo([source], 'source', 'target', 'relation', 'parentId');
|
|
292
|
+
expect(source).to.be.eql({
|
|
293
|
+
[DEF_PK]: source[DEF_PK],
|
|
294
|
+
parentId: target[DEF_PK],
|
|
295
|
+
relation: target,
|
|
296
|
+
});
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
it('uses a where clause of the given scope to filter the relation target', async function () {
|
|
300
|
+
const S = new Schema();
|
|
301
|
+
S.defineDatasource({name: 'datasource', adapter: 'memory'});
|
|
302
|
+
S.defineModel({name: 'source', datasource: 'datasource'});
|
|
303
|
+
S.defineModel({name: 'target', datasource: 'datasource'});
|
|
304
|
+
const sourceRep = S.getRepository('source');
|
|
305
|
+
const targetRep = S.getRepository('target');
|
|
306
|
+
const target = await targetRep.create({
|
|
307
|
+
foo: 'fooVal',
|
|
308
|
+
bar: 'barVal',
|
|
309
|
+
});
|
|
310
|
+
expect(target).to.be.eql({
|
|
311
|
+
[DEF_PK]: target[DEF_PK],
|
|
312
|
+
foo: 'fooVal',
|
|
313
|
+
bar: 'barVal',
|
|
314
|
+
});
|
|
315
|
+
const source = await sourceRep.create({
|
|
316
|
+
parentId: target[DEF_PK],
|
|
317
|
+
});
|
|
318
|
+
expect(source).to.be.eql({
|
|
319
|
+
[DEF_PK]: source[DEF_PK],
|
|
320
|
+
parentId: target[DEF_PK],
|
|
321
|
+
});
|
|
322
|
+
const R = S.getService(BelongsToResolver);
|
|
323
|
+
await R.includeTo([source], 'source', 'target', 'parent', undefined, {
|
|
324
|
+
where: {foo: 'barVal'},
|
|
325
|
+
});
|
|
326
|
+
expect(source).to.be.eql({
|
|
327
|
+
[DEF_PK]: source[DEF_PK],
|
|
328
|
+
parentId: target[DEF_PK],
|
|
329
|
+
});
|
|
330
|
+
await R.includeTo([source], 'source', 'target', 'parent', undefined, {
|
|
331
|
+
where: {foo: 'fooVal'},
|
|
332
|
+
});
|
|
333
|
+
expect(source).to.be.eql({
|
|
334
|
+
[DEF_PK]: source[DEF_PK],
|
|
335
|
+
parentId: target[DEF_PK],
|
|
336
|
+
parent: target,
|
|
337
|
+
});
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
it('uses a fields clause of the given scope to filter the relation target', async function () {
|
|
341
|
+
const S = new Schema();
|
|
342
|
+
S.defineDatasource({name: 'datasource', adapter: 'memory'});
|
|
343
|
+
S.defineModel({name: 'source', datasource: 'datasource'});
|
|
344
|
+
S.defineModel({name: 'target', datasource: 'datasource'});
|
|
345
|
+
const sourceRep = S.getRepository('source');
|
|
346
|
+
const targetRep = S.getRepository('target');
|
|
347
|
+
const target = await targetRep.create({
|
|
348
|
+
foo: 'fooVal',
|
|
349
|
+
bar: 'barVal',
|
|
350
|
+
});
|
|
351
|
+
expect(target).to.be.eql({
|
|
352
|
+
[DEF_PK]: target[DEF_PK],
|
|
353
|
+
foo: 'fooVal',
|
|
354
|
+
bar: 'barVal',
|
|
355
|
+
});
|
|
356
|
+
const source = await sourceRep.create({
|
|
357
|
+
parentId: target[DEF_PK],
|
|
358
|
+
});
|
|
359
|
+
expect(source).to.be.eql({
|
|
360
|
+
[DEF_PK]: source[DEF_PK],
|
|
361
|
+
parentId: target[DEF_PK],
|
|
362
|
+
});
|
|
363
|
+
const R = S.getService(BelongsToResolver);
|
|
364
|
+
await R.includeTo([source], 'source', 'target', 'parent', undefined, {
|
|
365
|
+
fields: [DEF_PK, 'bar'],
|
|
366
|
+
});
|
|
367
|
+
expect(source).to.be.eql({
|
|
368
|
+
[DEF_PK]: source[DEF_PK],
|
|
369
|
+
parentId: target[DEF_PK],
|
|
370
|
+
parent: {
|
|
371
|
+
[DEF_PK]: target[DEF_PK],
|
|
372
|
+
bar: target.bar,
|
|
373
|
+
},
|
|
374
|
+
});
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
it('uses an include clause of the given scope to resolve target relations', async function () {
|
|
378
|
+
const S = new Schema();
|
|
379
|
+
S.defineDatasource({
|
|
380
|
+
name: 'datasource',
|
|
381
|
+
adapter: 'memory',
|
|
382
|
+
});
|
|
383
|
+
S.defineModel({
|
|
384
|
+
name: 'modelA',
|
|
385
|
+
datasource: 'datasource',
|
|
386
|
+
properties: {
|
|
387
|
+
id: {
|
|
388
|
+
type: DataType.NUMBER,
|
|
389
|
+
primaryKey: true,
|
|
390
|
+
},
|
|
391
|
+
source: {
|
|
392
|
+
type: DataType.STRING,
|
|
393
|
+
default: 'modelA',
|
|
394
|
+
},
|
|
395
|
+
},
|
|
396
|
+
});
|
|
397
|
+
S.defineModel({
|
|
398
|
+
name: 'modelB',
|
|
399
|
+
datasource: 'datasource',
|
|
400
|
+
properties: {
|
|
401
|
+
id: {
|
|
402
|
+
type: DataType.NUMBER,
|
|
403
|
+
primaryKey: true,
|
|
404
|
+
},
|
|
405
|
+
source: {
|
|
406
|
+
type: DataType.STRING,
|
|
407
|
+
default: 'modelB',
|
|
408
|
+
},
|
|
409
|
+
},
|
|
410
|
+
relations: {
|
|
411
|
+
parent: {
|
|
412
|
+
type: RelationType.BELONGS_TO,
|
|
413
|
+
model: 'modelA',
|
|
414
|
+
},
|
|
415
|
+
},
|
|
416
|
+
});
|
|
417
|
+
S.defineModel({
|
|
418
|
+
name: 'modelC',
|
|
419
|
+
datasource: 'datasource',
|
|
420
|
+
properties: {
|
|
421
|
+
id: {
|
|
422
|
+
type: DataType.NUMBER,
|
|
423
|
+
primaryKey: true,
|
|
424
|
+
},
|
|
425
|
+
source: {
|
|
426
|
+
type: DataType.STRING,
|
|
427
|
+
default: 'modelC',
|
|
428
|
+
},
|
|
429
|
+
},
|
|
430
|
+
relations: {
|
|
431
|
+
parent: {
|
|
432
|
+
type: RelationType.BELONGS_TO,
|
|
433
|
+
model: 'modelB',
|
|
434
|
+
},
|
|
435
|
+
},
|
|
436
|
+
});
|
|
437
|
+
const aRep = S.getRepository('modelA');
|
|
438
|
+
const bRep = S.getRepository('modelB');
|
|
439
|
+
const cRep = S.getRepository('modelC');
|
|
440
|
+
const a = await aRep.create({});
|
|
441
|
+
const b = await bRep.create({parentId: a.id});
|
|
442
|
+
const c = await cRep.create({parentId: b.id});
|
|
443
|
+
expect(a).to.be.eql({
|
|
444
|
+
id: a.id,
|
|
445
|
+
source: 'modelA',
|
|
446
|
+
});
|
|
447
|
+
expect(b).to.be.eql({
|
|
448
|
+
id: b.id,
|
|
449
|
+
source: 'modelB',
|
|
450
|
+
parentId: a.id,
|
|
451
|
+
});
|
|
452
|
+
expect(c).to.be.eql({
|
|
453
|
+
id: c.id,
|
|
454
|
+
source: 'modelC',
|
|
455
|
+
parentId: b.id,
|
|
456
|
+
});
|
|
457
|
+
const R = S.getService(BelongsToResolver);
|
|
458
|
+
await R.includeTo([c], 'modelC', 'modelB', 'parent', undefined, {
|
|
459
|
+
include: 'parent',
|
|
460
|
+
});
|
|
461
|
+
expect(c).to.be.eql({
|
|
462
|
+
id: c.id,
|
|
463
|
+
source: 'modelC',
|
|
464
|
+
parentId: b.id,
|
|
465
|
+
parent: {
|
|
466
|
+
id: b.id,
|
|
467
|
+
source: 'modelB',
|
|
468
|
+
parentId: a.id,
|
|
469
|
+
parent: {
|
|
470
|
+
id: a.id,
|
|
471
|
+
source: 'modelA',
|
|
472
|
+
},
|
|
473
|
+
},
|
|
474
|
+
});
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
it('does not break the "and" operator of the given "where" clause', async function () {
|
|
478
|
+
const S = new Schema();
|
|
479
|
+
S.defineDatasource({name: 'datasource', adapter: 'memory'});
|
|
480
|
+
S.defineModel({name: 'source', datasource: 'datasource'});
|
|
481
|
+
S.defineModel({name: 'target', datasource: 'datasource'});
|
|
482
|
+
const sourceRep = S.getRepository('source');
|
|
483
|
+
const targetRep = S.getRepository('target');
|
|
484
|
+
const target = await targetRep.create({
|
|
485
|
+
foo: 'fooVal',
|
|
486
|
+
bar: 'barVal',
|
|
487
|
+
});
|
|
488
|
+
expect(target).to.be.eql({
|
|
489
|
+
[DEF_PK]: target[DEF_PK],
|
|
490
|
+
foo: 'fooVal',
|
|
491
|
+
bar: 'barVal',
|
|
492
|
+
});
|
|
493
|
+
const source = await sourceRep.create({
|
|
494
|
+
parentId: target[DEF_PK],
|
|
495
|
+
});
|
|
496
|
+
expect(source).to.be.eql({
|
|
497
|
+
[DEF_PK]: source[DEF_PK],
|
|
498
|
+
parentId: target[DEF_PK],
|
|
499
|
+
});
|
|
500
|
+
const R = S.getService(BelongsToResolver);
|
|
501
|
+
await R.includeTo([source], 'source', 'target', 'parent', undefined, {
|
|
502
|
+
where: {and: [{foo: 'barVal'}]},
|
|
503
|
+
fields: [DEF_PK, 'bar'],
|
|
504
|
+
});
|
|
505
|
+
expect(source).to.be.eql({
|
|
506
|
+
[DEF_PK]: source[DEF_PK],
|
|
507
|
+
parentId: target[DEF_PK],
|
|
508
|
+
});
|
|
509
|
+
await R.includeTo([source], 'source', 'target', 'parent', undefined, {
|
|
510
|
+
where: {and: [{foo: 'fooVal'}]},
|
|
511
|
+
fields: [DEF_PK, 'bar'],
|
|
512
|
+
});
|
|
513
|
+
expect(source).to.be.eql({
|
|
514
|
+
[DEF_PK]: source[DEF_PK],
|
|
515
|
+
parentId: target[DEF_PK],
|
|
516
|
+
parent: {
|
|
517
|
+
[DEF_PK]: target[DEF_PK],
|
|
518
|
+
bar: target.bar,
|
|
519
|
+
},
|
|
520
|
+
});
|
|
521
|
+
});
|
|
522
|
+
});
|
|
523
|
+
|
|
524
|
+
describe('includePolymorphicTo', function () {
|
|
525
|
+
it('requires the "entities" parameter to be an array', async function () {
|
|
526
|
+
const S = new Schema();
|
|
527
|
+
const R = S.getService(BelongsToResolver);
|
|
528
|
+
const error = v =>
|
|
529
|
+
format(
|
|
530
|
+
'The parameter "entities" of BelongsToResolver.includePolymorphicTo requires ' +
|
|
531
|
+
'an Array of Object, but %s given.',
|
|
532
|
+
v,
|
|
533
|
+
);
|
|
534
|
+
const throwable = v =>
|
|
535
|
+
R.includePolymorphicTo(v, 'sourceName', 'relationName');
|
|
536
|
+
await expect(throwable('')).to.be.rejectedWith(error('""'));
|
|
537
|
+
await expect(throwable('str')).to.be.rejectedWith(error('"str"'));
|
|
538
|
+
await expect(throwable(10)).to.be.rejectedWith(error('10'));
|
|
539
|
+
await expect(throwable(true)).to.be.rejectedWith(error('true'));
|
|
540
|
+
await expect(throwable(false)).to.be.rejectedWith(error('false'));
|
|
541
|
+
await expect(throwable({})).to.be.rejectedWith(error('Object'));
|
|
542
|
+
await expect(throwable(undefined)).to.be.rejectedWith(error('undefined'));
|
|
543
|
+
await expect(throwable(null)).to.be.rejectedWith(error('null'));
|
|
544
|
+
});
|
|
545
|
+
|
|
546
|
+
it('requires elements of the "entities" parameter to be an Object', async function () {
|
|
547
|
+
const S = new Schema();
|
|
548
|
+
const R = S.getService(BelongsToResolver);
|
|
549
|
+
const error = v =>
|
|
550
|
+
format(
|
|
551
|
+
'The parameter "entities" of BelongsToResolver.includePolymorphicTo requires ' +
|
|
552
|
+
'an Array of Object, but %s given.',
|
|
553
|
+
v,
|
|
554
|
+
);
|
|
555
|
+
const throwable = v =>
|
|
556
|
+
R.includePolymorphicTo([v], 'sourceName', 'relationName');
|
|
557
|
+
await expect(throwable('')).to.be.rejectedWith(error('""'));
|
|
558
|
+
await expect(throwable('str')).to.be.rejectedWith(error('"str"'));
|
|
559
|
+
await expect(throwable(10)).to.be.rejectedWith(error('10'));
|
|
560
|
+
await expect(throwable(true)).to.be.rejectedWith(error('true'));
|
|
561
|
+
await expect(throwable(false)).to.be.rejectedWith(error('false'));
|
|
562
|
+
await expect(throwable([])).to.be.rejectedWith(error('Array'));
|
|
563
|
+
await expect(throwable(undefined)).to.be.rejectedWith(error('undefined'));
|
|
564
|
+
await expect(throwable(null)).to.be.rejectedWith(error('null'));
|
|
565
|
+
});
|
|
566
|
+
|
|
567
|
+
it('requires the "sourceName" parameter to be a non-empty string', async function () {
|
|
568
|
+
const S = new Schema();
|
|
569
|
+
const R = S.getService(BelongsToResolver);
|
|
570
|
+
const error = v =>
|
|
571
|
+
format(
|
|
572
|
+
'The parameter "sourceName" of BelongsToResolver.includePolymorphicTo requires ' +
|
|
573
|
+
'a non-empty String, but %s given.',
|
|
574
|
+
v,
|
|
575
|
+
);
|
|
576
|
+
const throwable = v =>
|
|
577
|
+
R.includePolymorphicTo([], v, 'sourceName', 'relationName');
|
|
578
|
+
await expect(throwable('')).to.be.rejectedWith(error('""'));
|
|
579
|
+
await expect(throwable(10)).to.be.rejectedWith(error('10'));
|
|
580
|
+
await expect(throwable(true)).to.be.rejectedWith(error('true'));
|
|
581
|
+
await expect(throwable(false)).to.be.rejectedWith(error('false'));
|
|
582
|
+
await expect(throwable([])).to.be.rejectedWith(error('Array'));
|
|
583
|
+
await expect(throwable({})).to.be.rejectedWith(error('Object'));
|
|
584
|
+
await expect(throwable(undefined)).to.be.rejectedWith(error('undefined'));
|
|
585
|
+
await expect(throwable(null)).to.be.rejectedWith(error('null'));
|
|
586
|
+
});
|
|
587
|
+
|
|
588
|
+
it('requires the "relationName" parameter to be a non-empty string', async function () {
|
|
589
|
+
const S = new Schema();
|
|
590
|
+
const R = S.getService(BelongsToResolver);
|
|
591
|
+
const error = v =>
|
|
592
|
+
format(
|
|
593
|
+
'The parameter "relationName" of BelongsToResolver.includePolymorphicTo requires ' +
|
|
594
|
+
'a non-empty String, but %s given.',
|
|
595
|
+
v,
|
|
596
|
+
);
|
|
597
|
+
const throwable = v => R.includePolymorphicTo([], 'sourceName', v);
|
|
598
|
+
await expect(throwable('')).to.be.rejectedWith(error('""'));
|
|
599
|
+
await expect(throwable(10)).to.be.rejectedWith(error('10'));
|
|
600
|
+
await expect(throwable(true)).to.be.rejectedWith(error('true'));
|
|
601
|
+
await expect(throwable(false)).to.be.rejectedWith(error('false'));
|
|
602
|
+
await expect(throwable([])).to.be.rejectedWith(error('Array'));
|
|
603
|
+
await expect(throwable({})).to.be.rejectedWith(error('Object'));
|
|
604
|
+
await expect(throwable(undefined)).to.be.rejectedWith(error('undefined'));
|
|
605
|
+
await expect(throwable(null)).to.be.rejectedWith(error('null'));
|
|
606
|
+
});
|
|
607
|
+
|
|
608
|
+
it('requires the provided parameter "foreignKey" to be a string', async function () {
|
|
609
|
+
const S = new Schema();
|
|
610
|
+
const R = S.getService(BelongsToResolver);
|
|
611
|
+
const error = v =>
|
|
612
|
+
format(
|
|
613
|
+
'The provided parameter "foreignKey" of BelongsToResolver.includePolymorphicTo ' +
|
|
614
|
+
'should be a String, but %s given.',
|
|
615
|
+
v,
|
|
616
|
+
);
|
|
617
|
+
const throwable = v =>
|
|
618
|
+
R.includePolymorphicTo([], 'sourceName', 'relationName', v);
|
|
619
|
+
await expect(throwable(10)).to.be.rejectedWith(error('10'));
|
|
620
|
+
await expect(throwable(true)).to.be.rejectedWith(error('true'));
|
|
621
|
+
await expect(throwable([])).to.be.rejectedWith(error('Array'));
|
|
622
|
+
await expect(throwable({})).to.be.rejectedWith(error('Object'));
|
|
623
|
+
});
|
|
624
|
+
|
|
625
|
+
it('requires the provided parameter "discriminator" to be a string', async function () {
|
|
626
|
+
const S = new Schema();
|
|
627
|
+
const R = S.getService(BelongsToResolver);
|
|
628
|
+
const error = v =>
|
|
629
|
+
format(
|
|
630
|
+
'The provided parameter "discriminator" of BelongsToResolver.includePolymorphicTo ' +
|
|
631
|
+
'should be a String, but %s given.',
|
|
632
|
+
v,
|
|
633
|
+
);
|
|
634
|
+
const throwable = v =>
|
|
635
|
+
R.includePolymorphicTo([], 'sourceName', 'relationName', undefined, v);
|
|
636
|
+
await expect(throwable(10)).to.be.rejectedWith(error('10'));
|
|
637
|
+
await expect(throwable(true)).to.be.rejectedWith(error('true'));
|
|
638
|
+
await expect(throwable([])).to.be.rejectedWith(error('Array'));
|
|
639
|
+
await expect(throwable({})).to.be.rejectedWith(error('Object'));
|
|
640
|
+
});
|
|
641
|
+
|
|
642
|
+
it('requires the provided parameter "scope" to be an object', async function () {
|
|
643
|
+
const S = new Schema();
|
|
644
|
+
const R = S.getService(BelongsToResolver);
|
|
645
|
+
const error = v =>
|
|
646
|
+
format(
|
|
647
|
+
'The provided parameter "scope" of BelongsToResolver.includePolymorphicTo ' +
|
|
648
|
+
'should be an Object, but %s given.',
|
|
649
|
+
v,
|
|
650
|
+
);
|
|
651
|
+
const throwable = v =>
|
|
652
|
+
R.includePolymorphicTo(
|
|
653
|
+
[],
|
|
654
|
+
'sourceName',
|
|
655
|
+
'relationName',
|
|
656
|
+
undefined,
|
|
657
|
+
undefined,
|
|
658
|
+
v,
|
|
659
|
+
);
|
|
660
|
+
await expect(throwable('str')).to.be.rejectedWith(error('"str"'));
|
|
661
|
+
await expect(throwable(10)).to.be.rejectedWith(error('10'));
|
|
662
|
+
await expect(throwable(true)).to.be.rejectedWith(error('true'));
|
|
663
|
+
await expect(throwable([])).to.be.rejectedWith(error('Array'));
|
|
664
|
+
});
|
|
665
|
+
|
|
666
|
+
it('does not throw an error if a target model is not found', async function () {
|
|
667
|
+
const S = new Schema();
|
|
668
|
+
S.defineModel({name: 'source'});
|
|
669
|
+
const R = S.getService(BelongsToResolver);
|
|
670
|
+
const entity = {[DEF_PK]: 1, parentId: 1, parentType: 'target'};
|
|
671
|
+
await R.includePolymorphicTo([entity], 'source', 'parent');
|
|
672
|
+
expect(entity).to.be.eql(entity);
|
|
673
|
+
});
|
|
674
|
+
|
|
675
|
+
it('does not throws an error if a target model does not have datasource', async function () {
|
|
676
|
+
const S = new Schema();
|
|
677
|
+
S.defineModel({name: 'source'});
|
|
678
|
+
S.defineModel({name: 'target'});
|
|
679
|
+
const R = S.getService(BelongsToResolver);
|
|
680
|
+
const entity = {[DEF_PK]: 1, parentId: 1, parentType: 'target'};
|
|
681
|
+
await R.includePolymorphicTo([entity], 'source', 'parent');
|
|
682
|
+
expect(entity).to.be.eql(entity);
|
|
683
|
+
});
|
|
684
|
+
|
|
685
|
+
it('does not throw an error if a relation target is not found', async function () {
|
|
686
|
+
const S = new Schema();
|
|
687
|
+
S.defineDatasource({name: 'datasource', adapter: 'memory'});
|
|
688
|
+
S.defineModel({name: 'source', datasource: 'datasource'});
|
|
689
|
+
S.defineModel({name: 'target', datasource: 'datasource'});
|
|
690
|
+
const sourceRel = S.getRepository('source');
|
|
691
|
+
const source = await sourceRel.create({
|
|
692
|
+
parentId: 10,
|
|
693
|
+
parentType: 'target',
|
|
694
|
+
});
|
|
695
|
+
const R = S.getService(BelongsToResolver);
|
|
696
|
+
await R.includePolymorphicTo([source], 'source', 'parent');
|
|
697
|
+
expect(source).to.be.eql({
|
|
698
|
+
[DEF_PK]: source[DEF_PK],
|
|
699
|
+
parentId: 10,
|
|
700
|
+
parentType: 'target',
|
|
701
|
+
});
|
|
702
|
+
});
|
|
703
|
+
|
|
704
|
+
it('does not throw an error if no discriminator value', async function () {
|
|
705
|
+
const S = new Schema();
|
|
706
|
+
S.defineModel({name: 'source'});
|
|
707
|
+
const R = S.getService(BelongsToResolver);
|
|
708
|
+
const entity = {[DEF_PK]: 1, parentId: 1};
|
|
709
|
+
await R.includePolymorphicTo([entity], 'source', 'parent');
|
|
710
|
+
expect(entity).to.be.eql(entity);
|
|
711
|
+
});
|
|
712
|
+
|
|
713
|
+
it('includes if a primary key is not defined in the target model', async function () {
|
|
714
|
+
const S = new Schema();
|
|
715
|
+
S.defineDatasource({name: 'datasource', adapter: 'memory'});
|
|
716
|
+
S.defineModel({name: 'source', datasource: 'datasource'});
|
|
717
|
+
S.defineModel({name: 'target', datasource: 'datasource'});
|
|
718
|
+
const sourceRep = S.getRepository('source');
|
|
719
|
+
const targetRep = S.getRepository('target');
|
|
720
|
+
const target = await targetRep.create({});
|
|
721
|
+
expect(target).to.be.eql({[DEF_PK]: target[DEF_PK]});
|
|
722
|
+
const source = await sourceRep.create({
|
|
723
|
+
parentId: target[DEF_PK],
|
|
724
|
+
parentType: 'target',
|
|
725
|
+
});
|
|
726
|
+
expect(source).to.be.eql({
|
|
727
|
+
[DEF_PK]: source[DEF_PK],
|
|
728
|
+
parentId: target[DEF_PK],
|
|
729
|
+
parentType: 'target',
|
|
730
|
+
});
|
|
731
|
+
const R = S.getService(BelongsToResolver);
|
|
732
|
+
await R.includePolymorphicTo([source], 'source', 'parent');
|
|
733
|
+
expect(source).to.be.eql({
|
|
734
|
+
[DEF_PK]: source[DEF_PK],
|
|
735
|
+
parentId: target[DEF_PK],
|
|
736
|
+
parentType: 'target',
|
|
737
|
+
parent: target,
|
|
738
|
+
});
|
|
739
|
+
});
|
|
740
|
+
|
|
741
|
+
it('includes if the source model has a custom primary key', async function () {
|
|
742
|
+
const S = new Schema();
|
|
743
|
+
S.defineDatasource({name: 'datasource', adapter: 'memory'});
|
|
744
|
+
S.defineModel({
|
|
745
|
+
name: 'source',
|
|
746
|
+
datasource: 'datasource',
|
|
747
|
+
properties: {
|
|
748
|
+
myId: {
|
|
749
|
+
type: DataType.NUMBER,
|
|
750
|
+
primaryKey: true,
|
|
751
|
+
},
|
|
752
|
+
},
|
|
753
|
+
});
|
|
754
|
+
S.defineModel({name: 'target', datasource: 'datasource'});
|
|
755
|
+
const sourceRep = S.getRepository('source');
|
|
756
|
+
const targetRep = S.getRepository('target');
|
|
757
|
+
const target = await targetRep.create({});
|
|
758
|
+
expect(target).to.be.eql({[DEF_PK]: target[DEF_PK]});
|
|
759
|
+
const source = await sourceRep.create({
|
|
760
|
+
parentId: target[DEF_PK],
|
|
761
|
+
parentType: 'target',
|
|
762
|
+
});
|
|
763
|
+
expect(source).to.be.eql({
|
|
764
|
+
myId: source.myId,
|
|
765
|
+
parentId: target[DEF_PK],
|
|
766
|
+
parentType: 'target',
|
|
767
|
+
});
|
|
768
|
+
const R = S.getService(BelongsToResolver);
|
|
769
|
+
await R.includePolymorphicTo([source], 'source', 'parent');
|
|
770
|
+
expect(source).to.be.eql({
|
|
771
|
+
myId: source.myId,
|
|
772
|
+
parentId: target[DEF_PK],
|
|
773
|
+
parentType: 'target',
|
|
774
|
+
parent: target,
|
|
775
|
+
});
|
|
776
|
+
});
|
|
777
|
+
|
|
778
|
+
it('includes if the property "foreignKey" is specified', async function () {
|
|
779
|
+
const S = new Schema();
|
|
780
|
+
S.defineDatasource({name: 'datasource', adapter: 'memory'});
|
|
781
|
+
S.defineModel({name: 'source', datasource: 'datasource'});
|
|
782
|
+
S.defineModel({name: 'target', datasource: 'datasource'});
|
|
783
|
+
const sourceRep = S.getRepository('source');
|
|
784
|
+
const targetRep = S.getRepository('target');
|
|
785
|
+
const target = await targetRep.create({});
|
|
786
|
+
expect(target).to.be.eql({[DEF_PK]: target[DEF_PK]});
|
|
787
|
+
const source = await sourceRep.create({
|
|
788
|
+
parentId: target[DEF_PK],
|
|
789
|
+
relationType: 'target',
|
|
790
|
+
});
|
|
791
|
+
expect(source).to.be.eql({
|
|
792
|
+
[DEF_PK]: source[DEF_PK],
|
|
793
|
+
parentId: target[DEF_PK],
|
|
794
|
+
relationType: 'target',
|
|
795
|
+
});
|
|
796
|
+
const R = S.getService(BelongsToResolver);
|
|
797
|
+
await R.includePolymorphicTo([source], 'source', 'relation', 'parentId');
|
|
798
|
+
expect(source).to.be.eql({
|
|
799
|
+
[DEF_PK]: source[DEF_PK],
|
|
800
|
+
parentId: target[DEF_PK],
|
|
801
|
+
relationType: 'target',
|
|
802
|
+
relation: target,
|
|
803
|
+
});
|
|
804
|
+
});
|
|
805
|
+
|
|
806
|
+
it('includes if the property "discriminator" is specified', async function () {
|
|
807
|
+
const S = new Schema();
|
|
808
|
+
S.defineDatasource({name: 'datasource', adapter: 'memory'});
|
|
809
|
+
S.defineModel({name: 'source', datasource: 'datasource'});
|
|
810
|
+
S.defineModel({name: 'target', datasource: 'datasource'});
|
|
811
|
+
const sourceRep = S.getRepository('source');
|
|
812
|
+
const targetRep = S.getRepository('target');
|
|
813
|
+
const target = await targetRep.create({});
|
|
814
|
+
expect(target).to.be.eql({[DEF_PK]: target[DEF_PK]});
|
|
815
|
+
const source = await sourceRep.create({
|
|
816
|
+
relationId: target[DEF_PK],
|
|
817
|
+
parentType: 'target',
|
|
818
|
+
});
|
|
819
|
+
expect(source).to.be.eql({
|
|
820
|
+
[DEF_PK]: source[DEF_PK],
|
|
821
|
+
relationId: target[DEF_PK],
|
|
822
|
+
parentType: 'target',
|
|
823
|
+
});
|
|
824
|
+
const R = S.getService(BelongsToResolver);
|
|
825
|
+
await R.includePolymorphicTo(
|
|
826
|
+
[source],
|
|
827
|
+
'source',
|
|
828
|
+
'relation',
|
|
829
|
+
undefined,
|
|
830
|
+
'parentType',
|
|
831
|
+
);
|
|
832
|
+
expect(source).to.be.eql({
|
|
833
|
+
[DEF_PK]: source[DEF_PK],
|
|
834
|
+
relationId: target[DEF_PK],
|
|
835
|
+
parentType: 'target',
|
|
836
|
+
relation: target,
|
|
837
|
+
});
|
|
838
|
+
});
|
|
839
|
+
|
|
840
|
+
it('uses a where clause of the given scope to filter the relation target', async function () {
|
|
841
|
+
const S = new Schema();
|
|
842
|
+
S.defineDatasource({name: 'datasource', adapter: 'memory'});
|
|
843
|
+
S.defineModel({name: 'source', datasource: 'datasource'});
|
|
844
|
+
S.defineModel({name: 'target', datasource: 'datasource'});
|
|
845
|
+
const sourceRep = S.getRepository('source');
|
|
846
|
+
const targetRep = S.getRepository('target');
|
|
847
|
+
const target = await targetRep.create({
|
|
848
|
+
foo: 'fooVal',
|
|
849
|
+
bar: 'barVal',
|
|
850
|
+
});
|
|
851
|
+
expect(target).to.be.eql({
|
|
852
|
+
[DEF_PK]: target[DEF_PK],
|
|
853
|
+
foo: 'fooVal',
|
|
854
|
+
bar: 'barVal',
|
|
855
|
+
});
|
|
856
|
+
const source = await sourceRep.create({
|
|
857
|
+
parentId: target[DEF_PK],
|
|
858
|
+
parentType: 'target',
|
|
859
|
+
});
|
|
860
|
+
expect(source).to.be.eql({
|
|
861
|
+
[DEF_PK]: source[DEF_PK],
|
|
862
|
+
parentId: target[DEF_PK],
|
|
863
|
+
parentType: 'target',
|
|
864
|
+
});
|
|
865
|
+
const R = S.getService(BelongsToResolver);
|
|
866
|
+
await R.includePolymorphicTo(
|
|
867
|
+
[source],
|
|
868
|
+
'source',
|
|
869
|
+
'parent',
|
|
870
|
+
undefined,
|
|
871
|
+
undefined,
|
|
872
|
+
{where: {foo: 'barVal'}},
|
|
873
|
+
);
|
|
874
|
+
expect(source).to.be.eql({
|
|
875
|
+
[DEF_PK]: source[DEF_PK],
|
|
876
|
+
parentId: target[DEF_PK],
|
|
877
|
+
parentType: 'target',
|
|
878
|
+
});
|
|
879
|
+
await R.includePolymorphicTo(
|
|
880
|
+
[source],
|
|
881
|
+
'source',
|
|
882
|
+
'parent',
|
|
883
|
+
undefined,
|
|
884
|
+
undefined,
|
|
885
|
+
{where: {foo: 'fooVal'}},
|
|
886
|
+
);
|
|
887
|
+
expect(source).to.be.eql({
|
|
888
|
+
[DEF_PK]: source[DEF_PK],
|
|
889
|
+
parentId: target[DEF_PK],
|
|
890
|
+
parentType: 'target',
|
|
891
|
+
parent: target,
|
|
892
|
+
});
|
|
893
|
+
});
|
|
894
|
+
|
|
895
|
+
it('uses a fields clause of the given scope to filter the relation target', async function () {
|
|
896
|
+
const S = new Schema();
|
|
897
|
+
S.defineDatasource({name: 'datasource', adapter: 'memory'});
|
|
898
|
+
S.defineModel({name: 'source', datasource: 'datasource'});
|
|
899
|
+
S.defineModel({name: 'target', datasource: 'datasource'});
|
|
900
|
+
const sourceRep = S.getRepository('source');
|
|
901
|
+
const targetRep = S.getRepository('target');
|
|
902
|
+
const target = await targetRep.create({
|
|
903
|
+
foo: 'fooVal',
|
|
904
|
+
bar: 'barVal',
|
|
905
|
+
});
|
|
906
|
+
expect(target).to.be.eql({
|
|
907
|
+
[DEF_PK]: target[DEF_PK],
|
|
908
|
+
foo: 'fooVal',
|
|
909
|
+
bar: 'barVal',
|
|
910
|
+
});
|
|
911
|
+
const source = await sourceRep.create({
|
|
912
|
+
parentId: target[DEF_PK],
|
|
913
|
+
parentType: 'target',
|
|
914
|
+
});
|
|
915
|
+
expect(source).to.be.eql({
|
|
916
|
+
[DEF_PK]: source[DEF_PK],
|
|
917
|
+
parentId: target[DEF_PK],
|
|
918
|
+
parentType: 'target',
|
|
919
|
+
});
|
|
920
|
+
const R = S.getService(BelongsToResolver);
|
|
921
|
+
await R.includePolymorphicTo(
|
|
922
|
+
[source],
|
|
923
|
+
'source',
|
|
924
|
+
'parent',
|
|
925
|
+
undefined,
|
|
926
|
+
undefined,
|
|
927
|
+
{fields: [DEF_PK, 'bar']},
|
|
928
|
+
);
|
|
929
|
+
expect(source).to.be.eql({
|
|
930
|
+
[DEF_PK]: source[DEF_PK],
|
|
931
|
+
parentId: target[DEF_PK],
|
|
932
|
+
parentType: 'target',
|
|
933
|
+
parent: {
|
|
934
|
+
[DEF_PK]: target[DEF_PK],
|
|
935
|
+
bar: target.bar,
|
|
936
|
+
},
|
|
937
|
+
});
|
|
938
|
+
});
|
|
939
|
+
|
|
940
|
+
it('uses an include clause of the given scope to resolve target relations', async function () {
|
|
941
|
+
const S = new Schema();
|
|
942
|
+
S.defineDatasource({
|
|
943
|
+
name: 'datasource',
|
|
944
|
+
adapter: 'memory',
|
|
945
|
+
});
|
|
946
|
+
S.defineModel({
|
|
947
|
+
name: 'modelA',
|
|
948
|
+
datasource: 'datasource',
|
|
949
|
+
properties: {
|
|
950
|
+
id: {
|
|
951
|
+
type: DataType.NUMBER,
|
|
952
|
+
primaryKey: true,
|
|
953
|
+
},
|
|
954
|
+
source: {
|
|
955
|
+
type: DataType.STRING,
|
|
956
|
+
default: 'modelA',
|
|
957
|
+
},
|
|
958
|
+
},
|
|
959
|
+
});
|
|
960
|
+
S.defineModel({
|
|
961
|
+
name: 'modelB',
|
|
962
|
+
datasource: 'datasource',
|
|
963
|
+
properties: {
|
|
964
|
+
id: {
|
|
965
|
+
type: DataType.NUMBER,
|
|
966
|
+
primaryKey: true,
|
|
967
|
+
},
|
|
968
|
+
source: {
|
|
969
|
+
type: DataType.STRING,
|
|
970
|
+
default: 'modelB',
|
|
971
|
+
},
|
|
972
|
+
},
|
|
973
|
+
relations: {
|
|
974
|
+
parent: {
|
|
975
|
+
type: RelationType.BELONGS_TO,
|
|
976
|
+
model: 'modelA',
|
|
977
|
+
},
|
|
978
|
+
},
|
|
979
|
+
});
|
|
980
|
+
S.defineModel({
|
|
981
|
+
name: 'modelC',
|
|
982
|
+
datasource: 'datasource',
|
|
983
|
+
properties: {
|
|
984
|
+
id: {
|
|
985
|
+
type: DataType.NUMBER,
|
|
986
|
+
primaryKey: true,
|
|
987
|
+
},
|
|
988
|
+
source: {
|
|
989
|
+
type: DataType.STRING,
|
|
990
|
+
default: 'modelC',
|
|
991
|
+
},
|
|
992
|
+
},
|
|
993
|
+
relations: {
|
|
994
|
+
parent: {
|
|
995
|
+
type: RelationType.BELONGS_TO,
|
|
996
|
+
polymorphic: true,
|
|
997
|
+
},
|
|
998
|
+
},
|
|
999
|
+
});
|
|
1000
|
+
const aRep = S.getRepository('modelA');
|
|
1001
|
+
const bRep = S.getRepository('modelB');
|
|
1002
|
+
const cRep = S.getRepository('modelC');
|
|
1003
|
+
const a = await aRep.create({});
|
|
1004
|
+
const b = await bRep.create({parentId: a.id});
|
|
1005
|
+
const c = await cRep.create({parentId: b.id, parentType: 'modelB'});
|
|
1006
|
+
expect(a).to.be.eql({
|
|
1007
|
+
id: a.id,
|
|
1008
|
+
source: 'modelA',
|
|
1009
|
+
});
|
|
1010
|
+
expect(b).to.be.eql({
|
|
1011
|
+
id: b.id,
|
|
1012
|
+
source: 'modelB',
|
|
1013
|
+
parentId: a.id,
|
|
1014
|
+
});
|
|
1015
|
+
expect(c).to.be.eql({
|
|
1016
|
+
id: c.id,
|
|
1017
|
+
source: 'modelC',
|
|
1018
|
+
parentId: b.id,
|
|
1019
|
+
parentType: 'modelB',
|
|
1020
|
+
});
|
|
1021
|
+
const R = S.getService(BelongsToResolver);
|
|
1022
|
+
await R.includePolymorphicTo(
|
|
1023
|
+
[c],
|
|
1024
|
+
'modelC',
|
|
1025
|
+
'parent',
|
|
1026
|
+
undefined,
|
|
1027
|
+
undefined,
|
|
1028
|
+
{include: 'parent'},
|
|
1029
|
+
);
|
|
1030
|
+
expect(c).to.be.eql({
|
|
1031
|
+
id: c.id,
|
|
1032
|
+
source: 'modelC',
|
|
1033
|
+
parentId: b.id,
|
|
1034
|
+
parentType: 'modelB',
|
|
1035
|
+
parent: {
|
|
1036
|
+
id: b.id,
|
|
1037
|
+
source: 'modelB',
|
|
1038
|
+
parentId: a.id,
|
|
1039
|
+
parent: {
|
|
1040
|
+
id: a.id,
|
|
1041
|
+
source: 'modelA',
|
|
1042
|
+
},
|
|
1043
|
+
},
|
|
1044
|
+
});
|
|
1045
|
+
});
|
|
1046
|
+
});
|
|
1047
|
+
});
|