@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,242 @@
|
|
|
1
|
+
import {Service} from '@e22m4u/js-service';
|
|
2
|
+
import {cloneDeep} from '../utils/index.js';
|
|
3
|
+
import {singularize} from '../utils/index.js';
|
|
4
|
+
import {InvalidArgumentError} from '../errors/index.js';
|
|
5
|
+
import {RepositoryRegistry} from '../repository/index.js';
|
|
6
|
+
import {ModelDefinitionUtils} from '../definition/index.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Belongs to resolver.
|
|
10
|
+
*/
|
|
11
|
+
export class BelongsToResolver extends Service {
|
|
12
|
+
/**
|
|
13
|
+
* Include to.
|
|
14
|
+
*
|
|
15
|
+
* @param {object[]} entities
|
|
16
|
+
* @param {string} sourceName
|
|
17
|
+
* @param {string} targetName
|
|
18
|
+
* @param {string} relationName
|
|
19
|
+
* @param {string|undefined} foreignKey
|
|
20
|
+
* @param {object|undefined} scope
|
|
21
|
+
* @returns {Promise<void>}
|
|
22
|
+
*/
|
|
23
|
+
async includeTo(
|
|
24
|
+
entities,
|
|
25
|
+
sourceName,
|
|
26
|
+
targetName,
|
|
27
|
+
relationName,
|
|
28
|
+
foreignKey = undefined,
|
|
29
|
+
scope = undefined,
|
|
30
|
+
) {
|
|
31
|
+
if (!entities || !Array.isArray(entities))
|
|
32
|
+
throw new InvalidArgumentError(
|
|
33
|
+
'The parameter "entities" of BelongsToResolver.includeTo requires ' +
|
|
34
|
+
'an Array of Object, but %v given.',
|
|
35
|
+
entities,
|
|
36
|
+
);
|
|
37
|
+
if (!sourceName || typeof sourceName !== 'string')
|
|
38
|
+
throw new InvalidArgumentError(
|
|
39
|
+
'The parameter "sourceName" of BelongsToResolver.includeTo requires ' +
|
|
40
|
+
'a non-empty String, but %v given.',
|
|
41
|
+
sourceName,
|
|
42
|
+
);
|
|
43
|
+
if (!targetName || typeof targetName !== 'string')
|
|
44
|
+
throw new InvalidArgumentError(
|
|
45
|
+
'The parameter "targetName" of BelongsToResolver.includeTo requires ' +
|
|
46
|
+
'a non-empty String, but %v given.',
|
|
47
|
+
targetName,
|
|
48
|
+
);
|
|
49
|
+
if (!relationName || typeof relationName !== 'string')
|
|
50
|
+
throw new InvalidArgumentError(
|
|
51
|
+
'The parameter "relationName" of BelongsToResolver.includeTo requires ' +
|
|
52
|
+
'a non-empty String, but %v given.',
|
|
53
|
+
relationName,
|
|
54
|
+
);
|
|
55
|
+
if (foreignKey && typeof foreignKey !== 'string')
|
|
56
|
+
throw new InvalidArgumentError(
|
|
57
|
+
'The provided parameter "foreignKey" of BelongsToResolver.includeTo ' +
|
|
58
|
+
'should be a String, but %v given.',
|
|
59
|
+
foreignKey,
|
|
60
|
+
);
|
|
61
|
+
if (scope && (typeof scope !== 'object' || Array.isArray(scope)))
|
|
62
|
+
throw new InvalidArgumentError(
|
|
63
|
+
'The provided parameter "scope" of BelongsToResolver.includeTo ' +
|
|
64
|
+
'should be an Object, but %v given.',
|
|
65
|
+
scope,
|
|
66
|
+
);
|
|
67
|
+
if (foreignKey == null) foreignKey = `${relationName}Id`;
|
|
68
|
+
const targetIds = entities.reduce((acc, entity) => {
|
|
69
|
+
if (!entity || typeof entity !== 'object' || Array.isArray(entity))
|
|
70
|
+
throw new InvalidArgumentError(
|
|
71
|
+
'The parameter "entities" of BelongsToResolver.includeTo requires ' +
|
|
72
|
+
'an Array of Object, but %v given.',
|
|
73
|
+
entity,
|
|
74
|
+
);
|
|
75
|
+
const targetId = entity[foreignKey];
|
|
76
|
+
return targetId != null ? [...acc, targetId] : acc;
|
|
77
|
+
}, []);
|
|
78
|
+
const targetRepository =
|
|
79
|
+
this.getService(RepositoryRegistry).getRepository(targetName);
|
|
80
|
+
const targetPkPropName =
|
|
81
|
+
this.getService(ModelDefinitionUtils).getPrimaryKeyAsPropertyName(
|
|
82
|
+
targetName,
|
|
83
|
+
);
|
|
84
|
+
scope = scope ? cloneDeep(scope) : {};
|
|
85
|
+
const filter = cloneDeep(scope);
|
|
86
|
+
filter.where = {
|
|
87
|
+
and: [
|
|
88
|
+
{[targetPkPropName]: {inq: targetIds}},
|
|
89
|
+
...(scope.where ? [scope.where] : []),
|
|
90
|
+
],
|
|
91
|
+
};
|
|
92
|
+
const targets = await targetRepository.find(filter);
|
|
93
|
+
entities.forEach(entity => {
|
|
94
|
+
const target = targets.find(
|
|
95
|
+
e => e[targetPkPropName] === entity[foreignKey],
|
|
96
|
+
);
|
|
97
|
+
if (target) entity[relationName] = target;
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Include polymorphic to.
|
|
103
|
+
*
|
|
104
|
+
* @param {object[]} entities
|
|
105
|
+
* @param {string} sourceName
|
|
106
|
+
* @param {string} relationName
|
|
107
|
+
* @param {string|undefined} foreignKey
|
|
108
|
+
* @param {string|undefined} discriminator
|
|
109
|
+
* @param {object|undefined} scope
|
|
110
|
+
* @returns {Promise<void>}
|
|
111
|
+
*/
|
|
112
|
+
async includePolymorphicTo(
|
|
113
|
+
entities,
|
|
114
|
+
sourceName,
|
|
115
|
+
relationName,
|
|
116
|
+
foreignKey = undefined,
|
|
117
|
+
discriminator = undefined,
|
|
118
|
+
scope = undefined,
|
|
119
|
+
) {
|
|
120
|
+
if (!entities || !Array.isArray(entities))
|
|
121
|
+
throw new InvalidArgumentError(
|
|
122
|
+
'The parameter "entities" of BelongsToResolver.includePolymorphicTo ' +
|
|
123
|
+
'requires an Array of Object, but %v given.',
|
|
124
|
+
entities,
|
|
125
|
+
);
|
|
126
|
+
if (!sourceName || typeof sourceName !== 'string')
|
|
127
|
+
throw new InvalidArgumentError(
|
|
128
|
+
'The parameter "sourceName" of BelongsToResolver.includePolymorphicTo ' +
|
|
129
|
+
'requires a non-empty String, but %v given.',
|
|
130
|
+
sourceName,
|
|
131
|
+
);
|
|
132
|
+
if (!relationName || typeof relationName !== 'string')
|
|
133
|
+
throw new InvalidArgumentError(
|
|
134
|
+
'The parameter "relationName" of BelongsToResolver.includePolymorphicTo ' +
|
|
135
|
+
'requires a non-empty String, but %v given.',
|
|
136
|
+
relationName,
|
|
137
|
+
);
|
|
138
|
+
if (foreignKey && typeof foreignKey !== 'string')
|
|
139
|
+
throw new InvalidArgumentError(
|
|
140
|
+
'The provided parameter "foreignKey" of BelongsToResolver.includePolymorphicTo ' +
|
|
141
|
+
'should be a String, but %v given.',
|
|
142
|
+
foreignKey,
|
|
143
|
+
);
|
|
144
|
+
if (discriminator && typeof discriminator !== 'string')
|
|
145
|
+
throw new InvalidArgumentError(
|
|
146
|
+
'The provided parameter "discriminator" of BelongsToResolver.includePolymorphicTo ' +
|
|
147
|
+
'should be a String, but %v given.',
|
|
148
|
+
discriminator,
|
|
149
|
+
);
|
|
150
|
+
if (scope && (typeof scope !== 'object' || Array.isArray(scope)))
|
|
151
|
+
throw new InvalidArgumentError(
|
|
152
|
+
'The provided parameter "scope" of BelongsToResolver.includePolymorphicTo ' +
|
|
153
|
+
'should be an Object, but %v given.',
|
|
154
|
+
scope,
|
|
155
|
+
);
|
|
156
|
+
if (foreignKey == null) {
|
|
157
|
+
const singularRelationName = singularize(relationName);
|
|
158
|
+
foreignKey = `${singularRelationName}Id`;
|
|
159
|
+
}
|
|
160
|
+
if (discriminator == null) {
|
|
161
|
+
const singularRelationName = singularize(relationName);
|
|
162
|
+
discriminator = `${singularRelationName}Type`;
|
|
163
|
+
}
|
|
164
|
+
const targetIdsByTargetName = {};
|
|
165
|
+
entities.forEach(entity => {
|
|
166
|
+
if (!entity || typeof entity !== 'object' || Array.isArray(entity))
|
|
167
|
+
throw new InvalidArgumentError(
|
|
168
|
+
'The parameter "entities" of BelongsToResolver.includePolymorphicTo requires ' +
|
|
169
|
+
'an Array of Object, but %v given.',
|
|
170
|
+
entity,
|
|
171
|
+
);
|
|
172
|
+
const targetId = entity[foreignKey];
|
|
173
|
+
const targetName = entity[discriminator];
|
|
174
|
+
if (targetId == null || targetName == null) return;
|
|
175
|
+
if (targetIdsByTargetName[targetName] == null)
|
|
176
|
+
targetIdsByTargetName[targetName] = [];
|
|
177
|
+
if (!targetIdsByTargetName[targetName].includes(targetId))
|
|
178
|
+
targetIdsByTargetName[targetName].push(targetId);
|
|
179
|
+
});
|
|
180
|
+
const promises = [];
|
|
181
|
+
const targetNames = Object.keys(targetIdsByTargetName);
|
|
182
|
+
scope = scope ? cloneDeep(scope) : {};
|
|
183
|
+
const targetEntitiesByTargetNames = {};
|
|
184
|
+
targetNames.forEach(targetName => {
|
|
185
|
+
let targetRepository;
|
|
186
|
+
try {
|
|
187
|
+
targetRepository =
|
|
188
|
+
this.getService(RepositoryRegistry).getRepository(targetName);
|
|
189
|
+
} catch (error) {
|
|
190
|
+
if (error instanceof InvalidArgumentError) {
|
|
191
|
+
if (
|
|
192
|
+
error.message === `The model "${targetName}" is not defined.` ||
|
|
193
|
+
error.message ===
|
|
194
|
+
`The model "${targetName}" does not have a specified datasource.`
|
|
195
|
+
) {
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
} else {
|
|
199
|
+
throw error;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
const targetPkPropName =
|
|
203
|
+
this.getService(ModelDefinitionUtils).getPrimaryKeyAsPropertyName(
|
|
204
|
+
targetName,
|
|
205
|
+
);
|
|
206
|
+
const targetFilter = cloneDeep(scope);
|
|
207
|
+
const targetIds = targetIdsByTargetName[targetName];
|
|
208
|
+
targetFilter.where = {
|
|
209
|
+
and: [
|
|
210
|
+
{[targetPkPropName]: {inq: targetIds}},
|
|
211
|
+
...(scope.where ? [scope.where] : []),
|
|
212
|
+
],
|
|
213
|
+
};
|
|
214
|
+
const promise = targetRepository.find(targetFilter).then(result => {
|
|
215
|
+
targetEntitiesByTargetNames[targetName] = [
|
|
216
|
+
...(targetEntitiesByTargetNames[targetName] ?? []),
|
|
217
|
+
...result,
|
|
218
|
+
];
|
|
219
|
+
});
|
|
220
|
+
promises.push(promise);
|
|
221
|
+
});
|
|
222
|
+
await Promise.all(promises);
|
|
223
|
+
entities.forEach(entity => {
|
|
224
|
+
const targetId = entity[foreignKey];
|
|
225
|
+
const targetName = entity[discriminator];
|
|
226
|
+
if (
|
|
227
|
+
targetId == null ||
|
|
228
|
+
targetName == null ||
|
|
229
|
+
targetEntitiesByTargetNames[targetName] == null
|
|
230
|
+
) {
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
const targetEntities = targetEntitiesByTargetNames[targetName] ?? [];
|
|
234
|
+
const targetPkPropName =
|
|
235
|
+
this.getService(ModelDefinitionUtils).getPrimaryKeyAsPropertyName(
|
|
236
|
+
targetName,
|
|
237
|
+
);
|
|
238
|
+
const target = targetEntities.find(e => e[targetPkPropName] === targetId);
|
|
239
|
+
if (target) entity[relationName] = target;
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
}
|