@e22m4u/js-repository 0.3.3 → 0.4.0
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/dist/cjs/index.cjs +36 -8
- package/package.json +7 -7
- package/src/definition/definition-registry.js +12 -6
- package/src/definition/definition-registry.spec.js +173 -46
- package/src/repository/repository-registry.js +4 -2
- package/src/repository/repository-registry.spec.js +39 -9
- package/src/utils/index.d.ts +1 -0
- package/src/utils/index.js +1 -0
- package/src/utils/model-name-to-model-key.d.ts +6 -0
- package/src/utils/model-name-to-model-key.js +17 -0
- package/src/utils/model-name-to-model-key.spec.js +92 -0
package/dist/cjs/index.cjs
CHANGED
|
@@ -396,6 +396,23 @@ var init_exclude_object_keys = __esm({
|
|
|
396
396
|
}
|
|
397
397
|
});
|
|
398
398
|
|
|
399
|
+
// src/utils/model-name-to-model-key.js
|
|
400
|
+
function modelNameToModelKey(modelName) {
|
|
401
|
+
if (!modelName || typeof modelName !== "string" || /\s/.test(modelName))
|
|
402
|
+
throw new InvalidArgumentError(
|
|
403
|
+
"The model name should be a non-empty String without spaces, but %v given.",
|
|
404
|
+
modelName
|
|
405
|
+
);
|
|
406
|
+
return modelName.toLowerCase().replace(/[-_]/g, "");
|
|
407
|
+
}
|
|
408
|
+
var init_model_name_to_model_key = __esm({
|
|
409
|
+
"src/utils/model-name-to-model-key.js"() {
|
|
410
|
+
"use strict";
|
|
411
|
+
init_errors();
|
|
412
|
+
__name(modelNameToModelKey, "modelNameToModelKey");
|
|
413
|
+
}
|
|
414
|
+
});
|
|
415
|
+
|
|
399
416
|
// src/utils/get-decorator-target-type.js
|
|
400
417
|
function getDecoratorTargetType(target, propertyKey, descriptorOrIndex) {
|
|
401
418
|
const isCtor2 = typeof target === "function";
|
|
@@ -452,6 +469,7 @@ var init_utils = __esm({
|
|
|
452
469
|
init_transform_promise();
|
|
453
470
|
init_select_object_keys();
|
|
454
471
|
init_exclude_object_keys();
|
|
472
|
+
init_model_name_to_model_key();
|
|
455
473
|
init_get_decorator_target_type();
|
|
456
474
|
}
|
|
457
475
|
});
|
|
@@ -2040,6 +2058,7 @@ var init_definition_registry = __esm({
|
|
|
2040
2058
|
"src/definition/definition-registry.js"() {
|
|
2041
2059
|
"use strict";
|
|
2042
2060
|
import_js_service8 = require("@e22m4u/js-service");
|
|
2061
|
+
init_utils();
|
|
2043
2062
|
init_errors();
|
|
2044
2063
|
init_model();
|
|
2045
2064
|
init_definition();
|
|
@@ -2099,10 +2118,13 @@ var init_definition_registry = __esm({
|
|
|
2099
2118
|
*/
|
|
2100
2119
|
addModel(modelDef) {
|
|
2101
2120
|
this.getService(ModelDefinitionValidator).validate(modelDef);
|
|
2102
|
-
const
|
|
2103
|
-
if (
|
|
2104
|
-
throw new InvalidArgumentError(
|
|
2105
|
-
|
|
2121
|
+
const modelKey = modelNameToModelKey(modelDef.name);
|
|
2122
|
+
if (modelKey in this._models)
|
|
2123
|
+
throw new InvalidArgumentError(
|
|
2124
|
+
"The model %v is already defined.",
|
|
2125
|
+
modelDef.name
|
|
2126
|
+
);
|
|
2127
|
+
this._models[modelKey] = modelDef;
|
|
2106
2128
|
}
|
|
2107
2129
|
/**
|
|
2108
2130
|
* Has model.
|
|
@@ -2111,7 +2133,8 @@ var init_definition_registry = __esm({
|
|
|
2111
2133
|
* @returns {boolean}
|
|
2112
2134
|
*/
|
|
2113
2135
|
hasModel(name) {
|
|
2114
|
-
|
|
2136
|
+
const modelKey = modelNameToModelKey(name);
|
|
2137
|
+
return Boolean(this._models[modelKey]);
|
|
2115
2138
|
}
|
|
2116
2139
|
/**
|
|
2117
2140
|
* Get model.
|
|
@@ -2120,7 +2143,8 @@ var init_definition_registry = __esm({
|
|
|
2120
2143
|
* @returns {object}
|
|
2121
2144
|
*/
|
|
2122
2145
|
getModel(name) {
|
|
2123
|
-
const
|
|
2146
|
+
const modelKey = modelNameToModelKey(name);
|
|
2147
|
+
const modelDef = this._models[modelKey];
|
|
2124
2148
|
if (!modelDef)
|
|
2125
2149
|
throw new InvalidArgumentError("The model %v is not defined.", name);
|
|
2126
2150
|
return modelDef;
|
|
@@ -5060,6 +5084,7 @@ var init_repository_registry = __esm({
|
|
|
5060
5084
|
"use strict";
|
|
5061
5085
|
import_js_service30 = require("@e22m4u/js-service");
|
|
5062
5086
|
init_repository();
|
|
5087
|
+
init_utils();
|
|
5063
5088
|
init_errors();
|
|
5064
5089
|
_RepositoryRegistry = class _RepositoryRegistry extends import_js_service30.Service {
|
|
5065
5090
|
/**
|
|
@@ -5096,10 +5121,11 @@ var init_repository_registry = __esm({
|
|
|
5096
5121
|
* @returns {Repository}
|
|
5097
5122
|
*/
|
|
5098
5123
|
getRepository(modelName) {
|
|
5099
|
-
|
|
5124
|
+
const modelKey = modelNameToModelKey(modelName);
|
|
5125
|
+
let repository = this._repositories[modelKey];
|
|
5100
5126
|
if (repository) return repository;
|
|
5101
5127
|
repository = new this._repositoryCtor(this.container, modelName);
|
|
5102
|
-
this._repositories[
|
|
5128
|
+
this._repositories[modelKey] = repository;
|
|
5103
5129
|
return repository;
|
|
5104
5130
|
}
|
|
5105
5131
|
};
|
|
@@ -6361,6 +6387,7 @@ __export(index_exports, {
|
|
|
6361
6387
|
isDeepEqual: () => isDeepEqual,
|
|
6362
6388
|
isPromise: () => isPromise,
|
|
6363
6389
|
isPureObject: () => isPureObject,
|
|
6390
|
+
modelNameToModelKey: () => modelNameToModelKey,
|
|
6364
6391
|
selectObjectKeys: () => selectObjectKeys,
|
|
6365
6392
|
singularize: () => singularize,
|
|
6366
6393
|
stringToRegexp: () => stringToRegexp,
|
|
@@ -6465,6 +6492,7 @@ init_repository2();
|
|
|
6465
6492
|
isDeepEqual,
|
|
6466
6493
|
isPromise,
|
|
6467
6494
|
isPureObject,
|
|
6495
|
+
modelNameToModelKey,
|
|
6468
6496
|
selectObjectKeys,
|
|
6469
6497
|
singularize,
|
|
6470
6498
|
stringToRegexp,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@e22m4u/js-repository",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Реализация репозитория для работы с базами данных в Node.js",
|
|
5
5
|
"author": "Mikhail Evstropov <e22m4u@yandex.ru>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"@e22m4u/js-empty-values": "~0.0.2",
|
|
43
43
|
"@e22m4u/js-format": "~0.1.8",
|
|
44
|
-
"@e22m4u/js-service": "~0.3.
|
|
44
|
+
"@e22m4u/js-service": "~0.3.6"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@commitlint/cli": "~19.8.1",
|
|
@@ -51,14 +51,14 @@
|
|
|
51
51
|
"@types/chai-spies": "~1.0.6",
|
|
52
52
|
"@types/mocha": "~10.0.10",
|
|
53
53
|
"c8": "~10.1.3",
|
|
54
|
-
"chai": "~
|
|
55
|
-
"chai-as-promised": "~8.0.
|
|
54
|
+
"chai": "~6.0.1",
|
|
55
|
+
"chai-as-promised": "~8.0.2",
|
|
56
56
|
"chai-spies": "~1.1.0",
|
|
57
57
|
"esbuild": "~0.25.9",
|
|
58
|
-
"eslint": "~9.
|
|
58
|
+
"eslint": "~9.34.0",
|
|
59
59
|
"eslint-config-prettier": "~10.1.8",
|
|
60
60
|
"eslint-plugin-chai-expect": "~3.1.0",
|
|
61
|
-
"eslint-plugin-jsdoc": "~54.1.
|
|
61
|
+
"eslint-plugin-jsdoc": "~54.1.1",
|
|
62
62
|
"eslint-plugin-mocha": "~11.1.0",
|
|
63
63
|
"husky": "~9.1.7",
|
|
64
64
|
"mocha": "~11.7.1",
|
|
@@ -66,6 +66,6 @@
|
|
|
66
66
|
"rimraf": "~6.0.1",
|
|
67
67
|
"ts-node": "~10.9.2",
|
|
68
68
|
"typescript": "~5.9.2",
|
|
69
|
-
"typescript-eslint": "~8.
|
|
69
|
+
"typescript-eslint": "~8.41.0"
|
|
70
70
|
}
|
|
71
71
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {Service} from '@e22m4u/js-service';
|
|
2
|
+
import {modelNameToModelKey} from '../utils/index.js';
|
|
2
3
|
import {InvalidArgumentError} from '../errors/index.js';
|
|
3
4
|
import {ModelDefinitionValidator} from './model/index.js';
|
|
4
5
|
import {DatasourceDefinitionValidator} from '../definition/index.js';
|
|
@@ -67,10 +68,13 @@ export class DefinitionRegistry extends Service {
|
|
|
67
68
|
*/
|
|
68
69
|
addModel(modelDef) {
|
|
69
70
|
this.getService(ModelDefinitionValidator).validate(modelDef);
|
|
70
|
-
const
|
|
71
|
-
if (
|
|
72
|
-
throw new InvalidArgumentError(
|
|
73
|
-
|
|
71
|
+
const modelKey = modelNameToModelKey(modelDef.name);
|
|
72
|
+
if (modelKey in this._models)
|
|
73
|
+
throw new InvalidArgumentError(
|
|
74
|
+
'The model %v is already defined.',
|
|
75
|
+
modelDef.name,
|
|
76
|
+
);
|
|
77
|
+
this._models[modelKey] = modelDef;
|
|
74
78
|
}
|
|
75
79
|
|
|
76
80
|
/**
|
|
@@ -80,7 +84,8 @@ export class DefinitionRegistry extends Service {
|
|
|
80
84
|
* @returns {boolean}
|
|
81
85
|
*/
|
|
82
86
|
hasModel(name) {
|
|
83
|
-
|
|
87
|
+
const modelKey = modelNameToModelKey(name);
|
|
88
|
+
return Boolean(this._models[modelKey]);
|
|
84
89
|
}
|
|
85
90
|
|
|
86
91
|
/**
|
|
@@ -90,7 +95,8 @@ export class DefinitionRegistry extends Service {
|
|
|
90
95
|
* @returns {object}
|
|
91
96
|
*/
|
|
92
97
|
getModel(name) {
|
|
93
|
-
const
|
|
98
|
+
const modelKey = modelNameToModelKey(name);
|
|
99
|
+
const modelDef = this._models[modelKey];
|
|
94
100
|
if (!modelDef)
|
|
95
101
|
throw new InvalidArgumentError('The model %v is not defined.', name);
|
|
96
102
|
return modelDef;
|
|
@@ -17,63 +17,190 @@ describe('DefinitionRegistry', function () {
|
|
|
17
17
|
sandbox.restore();
|
|
18
18
|
});
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
20
|
+
describe('addDatasource', function () {
|
|
21
|
+
it('adds the given datasource to the registry', function () {
|
|
22
|
+
const datasource = {name: 'datasource', adapter: 'adapter'};
|
|
23
|
+
S.addDatasource(datasource);
|
|
24
|
+
const result = S.getDatasource('datasource');
|
|
25
|
+
expect(result).to.be.eql(datasource);
|
|
26
|
+
});
|
|
26
27
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
);
|
|
35
|
-
});
|
|
28
|
+
it('uses DatasourceDefinitionValidator to validate a given datasource', function () {
|
|
29
|
+
const V = S.getService(DatasourceDefinitionValidator);
|
|
30
|
+
sandbox.on(V, 'validate');
|
|
31
|
+
const datasource = {name: 'datasource', adapter: 'adapter'};
|
|
32
|
+
S.addDatasource(datasource);
|
|
33
|
+
expect(V.validate).to.have.been.called.once;
|
|
34
|
+
expect(V.validate).to.have.been.called.with.exactly(datasource);
|
|
35
|
+
});
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
it('throws an error if a given datasource is already defined', function () {
|
|
38
|
+
const datasource1 = {name: 'datasource', adapter: 'adapter'};
|
|
39
|
+
const datasource2 = {name: 'datasource', adapter: 'adapter'};
|
|
40
|
+
S.addDatasource(datasource1);
|
|
41
|
+
const throwable = () => S.addDatasource(datasource2);
|
|
42
|
+
expect(throwable).to.throw(
|
|
43
|
+
'The datasource "datasource" is already defined.',
|
|
44
|
+
);
|
|
45
|
+
});
|
|
40
46
|
});
|
|
41
47
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
48
|
+
describe('hasDatasource', function () {
|
|
49
|
+
it('should check the datasource registration by its name', function () {
|
|
50
|
+
const datasource = {name: 'datasource', adapter: 'adapter'};
|
|
51
|
+
expect(S.hasDatasource(datasource.name)).to.be.false;
|
|
52
|
+
S.addDatasource(datasource);
|
|
53
|
+
expect(S.hasDatasource(datasource.name)).to.be.true;
|
|
54
|
+
});
|
|
49
55
|
});
|
|
50
56
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
57
|
+
describe('getDatasource', function () {
|
|
58
|
+
it('returns the datasource by its name', function () {
|
|
59
|
+
const datasource = {name: 'datasource', adapter: 'adapter'};
|
|
60
|
+
S.addDatasource(datasource);
|
|
61
|
+
const result = S.getDatasource('datasource');
|
|
62
|
+
expect(result).to.be.eql(datasource);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('throws an error if ths datasource is not defined', function () {
|
|
66
|
+
const throwable = () => S.getDatasource('undefined');
|
|
67
|
+
expect(throwable).to.throw('The datasource "undefined" is not defined.');
|
|
68
|
+
});
|
|
56
69
|
});
|
|
57
70
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
71
|
+
describe('addModel', function () {
|
|
72
|
+
it('adds the given model to the registry', function () {
|
|
73
|
+
const model = {name: 'model'};
|
|
74
|
+
S.addModel(model);
|
|
75
|
+
const result = S.getModel('model');
|
|
76
|
+
expect(result).to.be.eql(model);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('uses ModelDefinitionValidator to validate a given model', function () {
|
|
80
|
+
const V = S.getService(ModelDefinitionValidator);
|
|
81
|
+
sandbox.on(V, 'validate');
|
|
82
|
+
const model = {name: 'model'};
|
|
83
|
+
S.addModel(model);
|
|
84
|
+
expect(V.validate).to.have.been.called.once;
|
|
85
|
+
expect(V.validate).to.have.been.called.with.exactly(model);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('throws an error if a given model is already defined', function () {
|
|
89
|
+
const model1 = {name: 'TestModel'};
|
|
90
|
+
const model2 = {name: 'TestModel'};
|
|
91
|
+
S.addModel(model1);
|
|
92
|
+
const throwable = () => S.addModel(model2);
|
|
93
|
+
expect(throwable).to.throw('The model "TestModel" is already defined.');
|
|
94
|
+
});
|
|
64
95
|
});
|
|
65
96
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
97
|
+
describe('hasModel', function () {
|
|
98
|
+
it('should check the model registration by its name', function () {
|
|
99
|
+
const model = {name: 'model'};
|
|
100
|
+
expect(S.hasModel(model.name)).to.be.false;
|
|
101
|
+
S.addModel(model);
|
|
102
|
+
expect(S.hasModel(model.name)).to.be.true;
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('should ignore naming convention of the model name', function () {
|
|
106
|
+
const model = {name: 'UserProfileDetails'};
|
|
107
|
+
const modelNames = [
|
|
108
|
+
'userProfileDetails',
|
|
109
|
+
'UserProfileDetails',
|
|
110
|
+
'user-profile-details',
|
|
111
|
+
'user_profile_details',
|
|
112
|
+
'USER-PROFILE-DETAILS',
|
|
113
|
+
'USER_PROFILE_DETAILS',
|
|
114
|
+
'USERPROFILEDETAILS',
|
|
115
|
+
'userprofiledetails',
|
|
116
|
+
];
|
|
117
|
+
modelNames.forEach(v => expect(S.hasModel(v)).to.be.false);
|
|
118
|
+
S.addModel(model);
|
|
119
|
+
modelNames.forEach(v => expect(S.hasModel(v)).to.be.true);
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it('should respect numbers in the model name', function () {
|
|
123
|
+
const model1 = {name: 'UserProfileDetails1'};
|
|
124
|
+
const modelNames1 = [
|
|
125
|
+
'userProfileDetails1',
|
|
126
|
+
'UserProfileDetails1',
|
|
127
|
+
'user-profile-details-1',
|
|
128
|
+
'user_profile_details_1',
|
|
129
|
+
'USER-PROFILE-DETAILS-1',
|
|
130
|
+
'USER_PROFILE_DETAILS_1',
|
|
131
|
+
'USERPROFILEDETAILS1',
|
|
132
|
+
'userprofiledetails1',
|
|
133
|
+
];
|
|
134
|
+
const modelNames2 = [
|
|
135
|
+
'userProfileDetails2',
|
|
136
|
+
'UserProfileDetails2',
|
|
137
|
+
'user-profile-details-2',
|
|
138
|
+
'user_profile_details_2',
|
|
139
|
+
'USER-PROFILE-DETAILS-2',
|
|
140
|
+
'USER_PROFILE_DETAILS_2',
|
|
141
|
+
'USERPROFILEDETAILS2',
|
|
142
|
+
'userprofiledetails2',
|
|
143
|
+
];
|
|
144
|
+
S.addModel(model1);
|
|
145
|
+
modelNames1.forEach(v => expect(S.hasModel(v)).to.be.true);
|
|
146
|
+
modelNames2.forEach(v => expect(S.hasModel(v)).to.be.false);
|
|
147
|
+
});
|
|
69
148
|
});
|
|
70
149
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
150
|
+
describe('getModel', function () {
|
|
151
|
+
it('returns the model by its name', function () {
|
|
152
|
+
const model = {name: 'model'};
|
|
153
|
+
S.addModel(model);
|
|
154
|
+
const result = S.getModel('model');
|
|
155
|
+
expect(result).to.be.eql(model);
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it('throws an error if the model is not defined', function () {
|
|
159
|
+
const throwable = () => S.getModel('undefined');
|
|
160
|
+
expect(throwable).to.throw('The model "undefined" is not defined.');
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
it('should ignore naming convention of the model name', function () {
|
|
164
|
+
const model = {name: 'userProfileDetails'};
|
|
165
|
+
const modelNames = [
|
|
166
|
+
'userProfileDetails',
|
|
167
|
+
'UserProfileDetails',
|
|
168
|
+
'user-profile-details',
|
|
169
|
+
'user_profile_details',
|
|
170
|
+
'USER-PROFILE-DETAILS',
|
|
171
|
+
'USER_PROFILE_DETAILS',
|
|
172
|
+
'USERPROFILEDETAILS',
|
|
173
|
+
'userprofiledetails',
|
|
174
|
+
];
|
|
175
|
+
S.addModel(model);
|
|
176
|
+
modelNames.forEach(v => expect(S.getModel(v)).to.be.eq(model));
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it('should respect numbers in the model name', function () {
|
|
180
|
+
const model1 = {name: 'userProfileDetails1'};
|
|
181
|
+
const modelNames1 = [
|
|
182
|
+
'userProfileDetails1',
|
|
183
|
+
'UserProfileDetails1',
|
|
184
|
+
'user-profile-details-1',
|
|
185
|
+
'user_profile_details_1',
|
|
186
|
+
'USER-PROFILE-DETAILS-1',
|
|
187
|
+
'USER_PROFILE_DETAILS_1',
|
|
188
|
+
'USERPROFILEDETAILS1',
|
|
189
|
+
'userprofiledetails1',
|
|
190
|
+
];
|
|
191
|
+
const modelNames2 = [
|
|
192
|
+
'userProfileDetails2',
|
|
193
|
+
'UserProfileDetails2',
|
|
194
|
+
'user-profile-details-2',
|
|
195
|
+
'user_profile_details_2',
|
|
196
|
+
'USER-PROFILE-DETAILS-2',
|
|
197
|
+
'USER_PROFILE_DETAILS_2',
|
|
198
|
+
'USERPROFILEDETAILS2',
|
|
199
|
+
'userprofiledetails2',
|
|
200
|
+
];
|
|
201
|
+
S.addModel(model1);
|
|
202
|
+
modelNames1.forEach(v => expect(S.getModel(v)).to.be.eq(model1));
|
|
203
|
+
modelNames2.forEach(v => expect(() => S.getModel(v)).to.throw(Error));
|
|
204
|
+
});
|
|
78
205
|
});
|
|
79
206
|
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {Service} from '@e22m4u/js-service';
|
|
2
2
|
import {Repository} from './repository.js';
|
|
3
|
+
import {modelNameToModelKey} from '../utils/index.js';
|
|
3
4
|
import {InvalidArgumentError} from '../errors/index.js';
|
|
4
5
|
|
|
5
6
|
/**
|
|
@@ -48,10 +49,11 @@ export class RepositoryRegistry extends Service {
|
|
|
48
49
|
* @returns {Repository}
|
|
49
50
|
*/
|
|
50
51
|
getRepository(modelName) {
|
|
51
|
-
|
|
52
|
+
const modelKey = modelNameToModelKey(modelName);
|
|
53
|
+
let repository = this._repositories[modelKey];
|
|
52
54
|
if (repository) return repository;
|
|
53
55
|
repository = new this._repositoryCtor(this.container, modelName);
|
|
54
|
-
this._repositories[
|
|
56
|
+
this._repositories[modelKey] = repository;
|
|
55
57
|
return repository;
|
|
56
58
|
}
|
|
57
59
|
}
|
|
@@ -10,29 +10,59 @@ describe('RepositoryRegistry', function () {
|
|
|
10
10
|
const dbs = new DatabaseSchema();
|
|
11
11
|
dbs.defineDatasource({name: 'datasource', adapter: 'memory'});
|
|
12
12
|
dbs.defineModel({name: 'model', datasource: 'datasource'});
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
const rep =
|
|
13
|
+
const reg = dbs.getService(RepositoryRegistry);
|
|
14
|
+
reg.setRepositoryCtor(MyRepository);
|
|
15
|
+
const rep = reg.getRepository('model');
|
|
16
16
|
expect(rep).to.be.instanceof(Repository);
|
|
17
17
|
expect(rep).to.be.instanceof(MyRepository);
|
|
18
18
|
});
|
|
19
19
|
});
|
|
20
20
|
|
|
21
21
|
describe('getRepository', function () {
|
|
22
|
-
it('
|
|
22
|
+
it('returns an existing repository by the given name or create new one', function () {
|
|
23
23
|
const dbs = new DatabaseSchema();
|
|
24
24
|
dbs.defineDatasource({name: 'datasource', adapter: 'memory'});
|
|
25
25
|
dbs.defineModel({name: 'modelA', datasource: 'datasource'});
|
|
26
26
|
dbs.defineModel({name: 'modelB', datasource: 'datasource'});
|
|
27
|
-
const
|
|
28
|
-
const repA1 =
|
|
29
|
-
const repA2 =
|
|
30
|
-
const repB1 =
|
|
31
|
-
const repB2 =
|
|
27
|
+
const reg = dbs.getService(RepositoryRegistry);
|
|
28
|
+
const repA1 = reg.getRepository('modelA');
|
|
29
|
+
const repA2 = reg.getRepository('modelA');
|
|
30
|
+
const repB1 = reg.getRepository('modelB');
|
|
31
|
+
const repB2 = reg.getRepository('modelB');
|
|
32
32
|
expect(repA1).to.be.eq(repA2);
|
|
33
33
|
expect(repB1).to.be.eq(repB2);
|
|
34
34
|
expect(repA1).to.be.not.eq(repB1);
|
|
35
35
|
expect(repA2).to.be.not.eq(repB2);
|
|
36
36
|
});
|
|
37
|
+
|
|
38
|
+
it('should ignore naming convention of the model name', function () {
|
|
39
|
+
const dbs = new DatabaseSchema();
|
|
40
|
+
const modelName = 'userProfileDetails';
|
|
41
|
+
dbs.defineDatasource({name: 'datasource', adapter: 'memory'});
|
|
42
|
+
dbs.defineModel({name: modelName, datasource: 'datasource'});
|
|
43
|
+
const reg = dbs.getService(RepositoryRegistry);
|
|
44
|
+
const rep = reg.getRepository(modelName);
|
|
45
|
+
const modelNames = [
|
|
46
|
+
'UserProfileDetails',
|
|
47
|
+
'user-profile-details',
|
|
48
|
+
'user_profile_details',
|
|
49
|
+
'USER-PROFILE-DETAILS',
|
|
50
|
+
'USER_PROFILE_DETAILS',
|
|
51
|
+
'USERPROFILEDETAILS',
|
|
52
|
+
'userprofiledetails',
|
|
53
|
+
];
|
|
54
|
+
modelNames.forEach(v => expect(reg.getRepository(v)).to.be.eq(rep));
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('should respect numbers in the model name', function () {
|
|
58
|
+
const dbs = new DatabaseSchema();
|
|
59
|
+
dbs.defineDatasource({name: 'datasource', adapter: 'memory'});
|
|
60
|
+
dbs.defineModel({name: 'model1', datasource: 'datasource'});
|
|
61
|
+
dbs.defineModel({name: 'model2', datasource: 'datasource'});
|
|
62
|
+
const reg = dbs.getService(RepositoryRegistry);
|
|
63
|
+
const rep1 = reg.getRepository('model1');
|
|
64
|
+
const rep2 = reg.getRepository('model2');
|
|
65
|
+
expect(rep1).to.be.not.eq(rep2);
|
|
66
|
+
});
|
|
37
67
|
});
|
|
38
68
|
});
|
package/src/utils/index.d.ts
CHANGED
|
@@ -11,4 +11,5 @@ export * from './get-value-by-path.js';
|
|
|
11
11
|
export * from './transform-promise.js';
|
|
12
12
|
export * from './select-object-keys.js';
|
|
13
13
|
export * from './exclude-object-keys.js';
|
|
14
|
+
export * from './model-name-to-model-key.js';
|
|
14
15
|
export * from './get-decorator-target-type.js';
|
package/src/utils/index.js
CHANGED
|
@@ -11,4 +11,5 @@ export * from './get-value-by-path.js';
|
|
|
11
11
|
export * from './transform-promise.js';
|
|
12
12
|
export * from './select-object-keys.js';
|
|
13
13
|
export * from './exclude-object-keys.js';
|
|
14
|
+
export * from './model-name-to-model-key.js';
|
|
14
15
|
export * from './get-decorator-target-type.js';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import {InvalidArgumentError} from '../errors/index.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Model name to model key.
|
|
5
|
+
*
|
|
6
|
+
* @param {string} modelName
|
|
7
|
+
* @returns {string}
|
|
8
|
+
*/
|
|
9
|
+
export function modelNameToModelKey(modelName) {
|
|
10
|
+
if (!modelName || typeof modelName !== 'string' || /\s/.test(modelName))
|
|
11
|
+
throw new InvalidArgumentError(
|
|
12
|
+
'The model name should be a non-empty String ' +
|
|
13
|
+
'without spaces, but %v given.',
|
|
14
|
+
modelName,
|
|
15
|
+
);
|
|
16
|
+
return modelName.toLowerCase().replace(/[-_]/g, '');
|
|
17
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import {expect} from 'chai';
|
|
2
|
+
import {modelNameToModelKey} from './model-name-to-model-key.js';
|
|
3
|
+
|
|
4
|
+
describe('modelNameToModelKey', function () {
|
|
5
|
+
it('should return a simple lowercase string as is', function () {
|
|
6
|
+
expect(modelNameToModelKey('user')).to.be.eq('user');
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it('should convert to lowercase and remove hyphens and underscores', function () {
|
|
10
|
+
const modelNames = [
|
|
11
|
+
'userProfileDetails',
|
|
12
|
+
'UserProfileDetails',
|
|
13
|
+
'user-profile-details',
|
|
14
|
+
'user_profile_details',
|
|
15
|
+
'USER-PROFILE-DETAILS',
|
|
16
|
+
'USER_PROFILE_DETAILS',
|
|
17
|
+
'USERPROFILEDETAILS',
|
|
18
|
+
'userprofiledetails',
|
|
19
|
+
];
|
|
20
|
+
modelNames.forEach(v =>
|
|
21
|
+
expect(modelNameToModelKey(v)).to.be.eq('userprofiledetails'),
|
|
22
|
+
);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('should handle a mixed string with uppercase, hyphens and underscores', function () {
|
|
26
|
+
const modelName = 'User_Profile-Details';
|
|
27
|
+
const expected = 'userprofiledetails';
|
|
28
|
+
expect(modelNameToModelKey(modelName)).to.be.eq(expected);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('should not remove numbers from the string', function () {
|
|
32
|
+
const modelName = 'Type1-Model_2';
|
|
33
|
+
const expected = 'type1model2';
|
|
34
|
+
expect(modelNameToModelKey(modelName)).to.be.eq(expected);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('should throw an error for an empty string', function () {
|
|
38
|
+
const throwable = () => modelNameToModelKey('');
|
|
39
|
+
expect(throwable).to.throw(
|
|
40
|
+
'The model name should be a non-empty String ' +
|
|
41
|
+
'without spaces, but "" given.',
|
|
42
|
+
);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('should throw an error for a string with spaces', function () {
|
|
46
|
+
const throwable = () => modelNameToModelKey('user profile');
|
|
47
|
+
expect(throwable).to.throw(
|
|
48
|
+
'The model name should be a non-empty String ' +
|
|
49
|
+
'without spaces, but "user profile" given.',
|
|
50
|
+
);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('should throw an error for null', function () {
|
|
54
|
+
const throwable = () => modelNameToModelKey(null);
|
|
55
|
+
expect(throwable).to.throw(
|
|
56
|
+
'The model name should be a non-empty String ' +
|
|
57
|
+
'without spaces, but null given.',
|
|
58
|
+
);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it('should throw an error for undefined', function () {
|
|
62
|
+
const throwable = () => modelNameToModelKey(undefined);
|
|
63
|
+
expect(throwable).to.throw(
|
|
64
|
+
'The model name should be a non-empty String ' +
|
|
65
|
+
'without spaces, but undefined given.',
|
|
66
|
+
);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('should throw an error for a number', function () {
|
|
70
|
+
const throwable = () => modelNameToModelKey(123);
|
|
71
|
+
expect(throwable).to.throw(
|
|
72
|
+
'The model name should be a non-empty String ' +
|
|
73
|
+
'without spaces, but 123 given.',
|
|
74
|
+
);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('should throw an error for an object', function () {
|
|
78
|
+
const throwable = () => modelNameToModelKey({name: 'test'});
|
|
79
|
+
expect(throwable).to.throw(
|
|
80
|
+
'The model name should be a non-empty String ' +
|
|
81
|
+
'without spaces, but Object given.',
|
|
82
|
+
);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('should throw an error for an array', function () {
|
|
86
|
+
const throwable = () => modelNameToModelKey(['test']);
|
|
87
|
+
expect(throwable).to.throw(
|
|
88
|
+
'The model name should be a non-empty String ' +
|
|
89
|
+
'without spaces, but Array given.',
|
|
90
|
+
);
|
|
91
|
+
});
|
|
92
|
+
});
|