@e22m4u/js-repository 0.1.0 → 0.1.2
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/.eslintrc.cjs +41 -17
- package/.mocharc.cjs +2 -2
- package/docs/assets/main.js +2 -2
- package/docs/assets/navigation.js +1 -1
- package/docs/assets/search.js +1 -1
- package/docs/assets/style.css +35 -15
- package/docs/classes/Adapter.html +19 -19
- package/docs/classes/AdapterLoader.html +8 -8
- package/docs/classes/AdapterRegistry.html +8 -8
- package/docs/classes/BelongsToResolver.html +9 -9
- package/docs/classes/DatasourceDefinitionValidator.html +8 -8
- package/docs/classes/DefinitionRegistry.html +12 -12
- package/docs/classes/FieldsClauseTool.html +10 -10
- package/docs/classes/HasManyResolver.html +10 -10
- package/docs/classes/HasOneResolver.html +10 -10
- package/docs/classes/IncludeClauseTool.html +12 -12
- package/docs/classes/InvalidArgumentError.html +7 -5
- package/docs/classes/InvalidOperatorValueError.html +7 -5
- package/docs/classes/ModelDataSanitizer.html +8 -8
- package/docs/classes/ModelDataValidator.html +9 -9
- package/docs/classes/ModelDefinitionUtils.html +23 -23
- package/docs/classes/ModelDefinitionValidator.html +8 -8
- package/docs/classes/NotImplementedError.html +7 -5
- package/docs/classes/OperatorClauseTool.html +32 -32
- package/docs/classes/OrderClauseTool.html +10 -10
- package/docs/classes/PrimaryKeysDefinitionValidator.html +8 -8
- package/docs/classes/PropertiesDefinitionValidator.html +8 -8
- package/docs/classes/ReferencesManyResolver.html +8 -8
- package/docs/classes/RelationsDefinitionValidator.html +8 -8
- package/docs/classes/Repository.html +28 -24
- package/docs/classes/RepositoryRegistry.html +9 -9
- package/docs/classes/Schema.html +10 -10
- package/docs/classes/SliceClauseTool.html +10 -10
- package/docs/classes/WhereClauseTool.html +9 -9
- package/docs/enums/DataType.html +2 -2
- package/docs/enums/DecoratorTargetType.html +11 -0
- package/docs/enums/RelationType.html +2 -2
- package/docs/functions/capitalize.html +1 -1
- package/docs/functions/cloneDeep.html +2 -2
- package/docs/functions/excludeObjectKeys.html +2 -2
- package/docs/functions/getCtorName.html +1 -1
- package/docs/functions/getDecoratorTargetType.html +2 -0
- package/docs/functions/getValueByPath.html +1 -1
- package/docs/functions/isCtor.html +3 -2
- package/docs/functions/isPureObject.html +1 -1
- package/docs/functions/selectObjectKeys.html +2 -2
- package/docs/functions/singularize.html +1 -1
- package/docs/functions/stringToRegexp.html +2 -2
- package/docs/index.html +1 -1
- package/docs/interfaces/AndClause.html +2 -2
- package/docs/interfaces/Constructor.html +4 -0
- package/docs/interfaces/OrClause.html +2 -2
- package/docs/modules.html +4 -1
- package/docs/types/AnyObject.html +1 -1
- package/docs/types/BelongsToDefinition.html +1 -1
- package/docs/types/DEFAULT_PRIMARY_KEY_PROPERTY_NAME.html +1 -1
- package/docs/types/DatasourceDefinition.html +1 -1
- package/docs/types/FieldsClause.html +1 -1
- package/docs/types/FilterClause.html +1 -1
- package/docs/types/Flatten.html +1 -1
- package/docs/types/FullPropertyDefinition.html +1 -1
- package/docs/types/HasManyDefinition.html +1 -1
- package/docs/types/HasOneDefinition.html +1 -1
- package/docs/types/Identity.html +2 -2
- package/docs/types/IncludeClause.html +1 -1
- package/docs/types/ItemFilterClause.html +2 -2
- package/docs/types/ModelData.html +1 -1
- package/docs/types/ModelDefinition.html +1 -1
- package/docs/types/ModelId.html +1 -1
- package/docs/types/NestedIncludeClause.html +1 -1
- package/docs/types/NormalizedFieldsClause.html +1 -1
- package/docs/types/NormalizedIncludeClause.html +1 -1
- package/docs/types/OperatorClause.html +3 -3
- package/docs/types/OptionalUnlessRequiredId.html +2 -2
- package/docs/types/OrderClause.html +1 -1
- package/docs/types/PartialBy.html +2 -2
- package/docs/types/PartialWithoutId.html +2 -2
- package/docs/types/PolyBelongsToDefinition.html +1 -1
- package/docs/types/PolyHasManyDefinitionWithTargetKeys.html +1 -1
- package/docs/types/PolyHasManyDefinitionWithTargetRelationName.html +1 -1
- package/docs/types/PolyHasOneDefinitionWithTargetKeys.html +1 -1
- package/docs/types/PolyHasOneDefinitionWithTargetRelationName.html +1 -1
- package/docs/types/PropertiesClause.html +3 -3
- package/docs/types/PropertyDefinition.html +1 -1
- package/docs/types/PropertyDefinitionMap.html +1 -1
- package/docs/types/ReferencesManyDefinition.html +1 -1
- package/docs/types/RelationDefinition.html +1 -1
- package/docs/types/RelationDefinitionMap.html +1 -1
- package/docs/types/WhereClause.html +2 -2
- package/docs/types/WithoutId.html +2 -2
- package/mocha.setup.js +8 -3
- package/package.json +9 -4
- package/src/adapter/builtin/memory-adapter.js +6 -2
- package/src/adapter/builtin/memory-adapter.spec.js +116 -0
- package/src/adapter/decorator/data-sanitizing-decorator.d.ts +2 -1
- package/src/adapter/decorator/data-validation-decorator.d.ts +2 -1
- package/src/adapter/decorator/default-values-decorator.d.ts +2 -1
- package/src/adapter/decorator/fields-filtering-decorator.d.ts +2 -1
- package/src/adapter/decorator/inclusion-decorator.d.ts +2 -1
- package/src/definition/model/index.js +1 -0
- package/src/definition/model/model-definition.js +1 -0
- package/src/definition/model/properties/index.js +1 -0
- package/src/definition/model/properties/property-definition.js +1 -0
- package/src/definition/model/relations/index.js +1 -0
- package/src/definition/model/relations/relation-definition.js +1 -0
- package/src/filter/filter-clause.d.ts +4 -4
- package/src/index.d.ts +1 -1
- package/src/index.js +1 -0
- package/src/repository/repository.d.ts +9 -3
- package/src/repository/repository.js +0 -1
- package/src/schema.d.ts +1 -1
- package/src/schema.spec.ts +71 -0
- package/src/types.d.ts +8 -0
- package/src/types.js +1 -0
- package/src/utils/get-decorator-target-type.d.ts +27 -0
- package/src/utils/get-decorator-target-type.js +63 -0
- package/src/utils/get-decorator-target-type.spec.js +77 -0
- package/src/utils/index.d.ts +1 -0
- package/src/utils/index.js +1 -0
- package/src/utils/is-ctor.d.ts +2 -1
- package/src/utils/is-ctor.js +2 -1
- package/src/utils/is-ctor.spec.js +1 -1
- package/tsconfig.json +3 -1
|
@@ -187,6 +187,64 @@ describe('MemoryAdapter', function () {
|
|
|
187
187
|
expect(tableData).to.be.eql({...input, [DEF_PK]: idValue});
|
|
188
188
|
});
|
|
189
189
|
|
|
190
|
+
it('generates a new identifier when a value of a primary key is an empty string', async function () {
|
|
191
|
+
const schema = new Schema();
|
|
192
|
+
schema.defineDatasource({
|
|
193
|
+
name: 'memory',
|
|
194
|
+
adapter: 'memory',
|
|
195
|
+
});
|
|
196
|
+
schema.defineModel({
|
|
197
|
+
name: 'model',
|
|
198
|
+
datasource: 'memory',
|
|
199
|
+
properties: {
|
|
200
|
+
foo: DataType.STRING,
|
|
201
|
+
bar: DataType.NUMBER,
|
|
202
|
+
},
|
|
203
|
+
});
|
|
204
|
+
const adapter = new MemoryAdapter(schema.container, {});
|
|
205
|
+
const input = {
|
|
206
|
+
[DEF_PK]: '',
|
|
207
|
+
foo: 'string',
|
|
208
|
+
bar: 10,
|
|
209
|
+
};
|
|
210
|
+
const created = await adapter.create('model', input);
|
|
211
|
+
const idValue = created[DEF_PK];
|
|
212
|
+
expect(idValue).to.be.not.eq('');
|
|
213
|
+
expect(created).to.be.eql({...input, [DEF_PK]: idValue});
|
|
214
|
+
const table = adapter._getTableOrCreate('model');
|
|
215
|
+
const tableData = table.get(idValue);
|
|
216
|
+
expect(tableData).to.be.eql({...input, [DEF_PK]: idValue});
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
it('generates a new identifier when a value of a primary key is zero', async function () {
|
|
220
|
+
const schema = new Schema();
|
|
221
|
+
schema.defineDatasource({
|
|
222
|
+
name: 'memory',
|
|
223
|
+
adapter: 'memory',
|
|
224
|
+
});
|
|
225
|
+
schema.defineModel({
|
|
226
|
+
name: 'model',
|
|
227
|
+
datasource: 'memory',
|
|
228
|
+
properties: {
|
|
229
|
+
foo: DataType.STRING,
|
|
230
|
+
bar: DataType.NUMBER,
|
|
231
|
+
},
|
|
232
|
+
});
|
|
233
|
+
const adapter = new MemoryAdapter(schema.container, {});
|
|
234
|
+
const input = {
|
|
235
|
+
[DEF_PK]: 0,
|
|
236
|
+
foo: 'string',
|
|
237
|
+
bar: 10,
|
|
238
|
+
};
|
|
239
|
+
const created = await adapter.create('model', input);
|
|
240
|
+
const idValue = created[DEF_PK];
|
|
241
|
+
expect(idValue).to.be.not.eq(0);
|
|
242
|
+
expect(created).to.be.eql({...input, [DEF_PK]: idValue});
|
|
243
|
+
const table = adapter._getTableOrCreate('model');
|
|
244
|
+
const tableData = table.get(idValue);
|
|
245
|
+
expect(tableData).to.be.eql({...input, [DEF_PK]: idValue});
|
|
246
|
+
});
|
|
247
|
+
|
|
190
248
|
it('generates a new identifier for a primary key of a "number" type', async function () {
|
|
191
249
|
const schema = new Schema();
|
|
192
250
|
schema.defineDatasource({
|
|
@@ -1214,6 +1272,64 @@ describe('MemoryAdapter', function () {
|
|
|
1214
1272
|
expect(tableData).to.be.eql({...input, [DEF_PK]: idValue});
|
|
1215
1273
|
});
|
|
1216
1274
|
|
|
1275
|
+
it('generates a new identifier when a value of a primary key is an empty string', async function () {
|
|
1276
|
+
const schema = new Schema();
|
|
1277
|
+
schema.defineDatasource({
|
|
1278
|
+
name: 'memory',
|
|
1279
|
+
adapter: 'memory',
|
|
1280
|
+
});
|
|
1281
|
+
schema.defineModel({
|
|
1282
|
+
name: 'model',
|
|
1283
|
+
datasource: 'memory',
|
|
1284
|
+
properties: {
|
|
1285
|
+
foo: DataType.STRING,
|
|
1286
|
+
bar: DataType.NUMBER,
|
|
1287
|
+
},
|
|
1288
|
+
});
|
|
1289
|
+
const adapter = new MemoryAdapter(schema.container, {});
|
|
1290
|
+
const input = {
|
|
1291
|
+
[DEF_PK]: '',
|
|
1292
|
+
foo: 'string',
|
|
1293
|
+
bar: 10,
|
|
1294
|
+
};
|
|
1295
|
+
const created = await adapter.replaceOrCreate('model', input);
|
|
1296
|
+
const idValue = created[DEF_PK];
|
|
1297
|
+
expect(idValue).to.be.not.eq('');
|
|
1298
|
+
expect(created).to.be.eql({...input, [DEF_PK]: idValue});
|
|
1299
|
+
const table = adapter._getTableOrCreate('model');
|
|
1300
|
+
const tableData = table.get(idValue);
|
|
1301
|
+
expect(tableData).to.be.eql({...input, [DEF_PK]: idValue});
|
|
1302
|
+
});
|
|
1303
|
+
|
|
1304
|
+
it('generates a new identifier when a value of a primary key is zero', async function () {
|
|
1305
|
+
const schema = new Schema();
|
|
1306
|
+
schema.defineDatasource({
|
|
1307
|
+
name: 'memory',
|
|
1308
|
+
adapter: 'memory',
|
|
1309
|
+
});
|
|
1310
|
+
schema.defineModel({
|
|
1311
|
+
name: 'model',
|
|
1312
|
+
datasource: 'memory',
|
|
1313
|
+
properties: {
|
|
1314
|
+
foo: DataType.STRING,
|
|
1315
|
+
bar: DataType.NUMBER,
|
|
1316
|
+
},
|
|
1317
|
+
});
|
|
1318
|
+
const adapter = new MemoryAdapter(schema.container, {});
|
|
1319
|
+
const input = {
|
|
1320
|
+
[DEF_PK]: 0,
|
|
1321
|
+
foo: 'string',
|
|
1322
|
+
bar: 10,
|
|
1323
|
+
};
|
|
1324
|
+
const created = await adapter.replaceOrCreate('model', input);
|
|
1325
|
+
const idValue = created[DEF_PK];
|
|
1326
|
+
expect(idValue).to.be.not.eq(0);
|
|
1327
|
+
expect(created).to.be.eql({...input, [DEF_PK]: idValue});
|
|
1328
|
+
const table = adapter._getTableOrCreate('model');
|
|
1329
|
+
const tableData = table.get(idValue);
|
|
1330
|
+
expect(tableData).to.be.eql({...input, [DEF_PK]: idValue});
|
|
1331
|
+
});
|
|
1332
|
+
|
|
1217
1333
|
it('generates a new identifier for a primary key of a "number" type', async function () {
|
|
1218
1334
|
const schema = new Schema();
|
|
1219
1335
|
schema.defineDatasource({
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import {Adapter} from '../adapter.js';
|
|
1
2
|
import {Service} from '@e22m4u/js-service';
|
|
2
3
|
|
|
3
4
|
/**
|
|
@@ -9,5 +10,5 @@ export declare class DataSanitizingDecorator extends Service {
|
|
|
9
10
|
*
|
|
10
11
|
* @param adapter
|
|
11
12
|
*/
|
|
12
|
-
decorate(adapter): void;
|
|
13
|
+
decorate(adapter: Adapter): void;
|
|
13
14
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {Service} from '@e22m4u/js-service';
|
|
2
|
+
import {Adapter} from '../adapter.js';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Data validation decorator.
|
|
@@ -9,5 +10,5 @@ export declare class DataValidationDecorator extends Service {
|
|
|
9
10
|
*
|
|
10
11
|
* @param adapter
|
|
11
12
|
*/
|
|
12
|
-
decorate(adapter): void;
|
|
13
|
+
decorate(adapter: Adapter): void;
|
|
13
14
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {Service} from '@e22m4u/js-service';
|
|
2
|
+
import {Adapter} from '../adapter.js';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Default values decorator.
|
|
@@ -9,5 +10,5 @@ export declare class DefaultValuesDecorator extends Service {
|
|
|
9
10
|
*
|
|
10
11
|
* @param adapter
|
|
11
12
|
*/
|
|
12
|
-
decorate(adapter): void;
|
|
13
|
+
decorate(adapter: Adapter): void;
|
|
13
14
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {Service} from '@e22m4u/js-service';
|
|
2
|
+
import {Adapter} from '../adapter.js';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Fields filtering decorator.
|
|
@@ -9,5 +10,5 @@ export declare class FieldsFilteringDecorator extends Service {
|
|
|
9
10
|
*
|
|
10
11
|
* @param adapter
|
|
11
12
|
*/
|
|
12
|
-
decorate(adapter): void;
|
|
13
|
+
decorate(adapter: Adapter): void;
|
|
13
14
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {Service} from '@e22m4u/js-service';
|
|
2
|
+
import {Adapter} from '../adapter.js';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Inclusion decorator.
|
|
@@ -9,5 +10,5 @@ export declare class InclusionDecorator extends Service {
|
|
|
9
10
|
*
|
|
10
11
|
* @param adapter
|
|
11
12
|
*/
|
|
12
|
-
decorate(adapter): void;
|
|
13
|
+
decorate(adapter: Adapter): void;
|
|
13
14
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -43,8 +43,8 @@ export declare type ItemFilterClause = Pick<FilterClause, 'fields' | 'include'>;
|
|
|
43
43
|
* ```
|
|
44
44
|
*/
|
|
45
45
|
export declare type WhereClause =
|
|
46
|
-
& AndClause
|
|
47
|
-
& OrClause
|
|
46
|
+
& Partial<AndClause>
|
|
47
|
+
& Partial<OrClause>
|
|
48
48
|
& PropertiesClause;
|
|
49
49
|
|
|
50
50
|
/**
|
|
@@ -124,7 +124,7 @@ export declare type OperatorClause = {
|
|
|
124
124
|
* ```
|
|
125
125
|
*/
|
|
126
126
|
export interface AndClause {
|
|
127
|
-
and
|
|
127
|
+
and: WhereClause[];
|
|
128
128
|
}
|
|
129
129
|
|
|
130
130
|
/**
|
|
@@ -138,7 +138,7 @@ export interface AndClause {
|
|
|
138
138
|
* ```
|
|
139
139
|
*/
|
|
140
140
|
export interface OrClause {
|
|
141
|
-
or
|
|
141
|
+
or: WhereClause[];
|
|
142
142
|
}
|
|
143
143
|
|
|
144
144
|
/**
|
package/src/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export * from './types.js';
|
|
2
2
|
export * from './schema.js';
|
|
3
3
|
export * from './utils/index.js';
|
|
4
|
-
export * from './filter/index.js';
|
|
5
4
|
export * from './errors/index.js';
|
|
5
|
+
export * from './filter/index.js';
|
|
6
6
|
export * from './adapter/index.js';
|
|
7
7
|
export * from './relations/index.js';
|
|
8
8
|
export * from './definition/index.js';
|
package/src/index.js
CHANGED
|
@@ -14,11 +14,17 @@ import {DEFAULT_PRIMARY_KEY_PROPERTY_NAME} from '../definition/index.js';
|
|
|
14
14
|
* Repository.
|
|
15
15
|
*/
|
|
16
16
|
export declare class Repository<
|
|
17
|
-
Data extends
|
|
17
|
+
Data extends object = ModelData,
|
|
18
18
|
IdType extends ModelId = ModelId,
|
|
19
19
|
IdName extends string = DEFAULT_PRIMARY_KEY_PROPERTY_NAME,
|
|
20
20
|
FlatData extends ModelData = Flatten<Data>,
|
|
21
21
|
> extends Service {
|
|
22
|
+
// it fixes unused generic bug
|
|
23
|
+
private _Data?: Data;
|
|
24
|
+
private _IdType?: IdType;
|
|
25
|
+
private _IdName?: IdName;
|
|
26
|
+
private _FlatData?: FlatData;
|
|
27
|
+
|
|
22
28
|
/**
|
|
23
29
|
* Model name.
|
|
24
30
|
*/
|
|
@@ -162,7 +168,7 @@ type WithoutId<IdName extends string, Data extends ModelData> = Flatten<
|
|
|
162
168
|
/**
|
|
163
169
|
* Makes fields as optional and remove id field.
|
|
164
170
|
*/
|
|
165
|
-
type PartialWithoutId<IdName extends string, Data extends
|
|
171
|
+
type PartialWithoutId<IdName extends string, Data extends object> = Flatten<
|
|
166
172
|
Partial<Omit<Data, IdName>>
|
|
167
173
|
>;
|
|
168
174
|
|
|
@@ -171,5 +177,5 @@ type PartialWithoutId<IdName extends string, Data extends ModelData> = Flatten<
|
|
|
171
177
|
*/
|
|
172
178
|
type OptionalUnlessRequiredId<
|
|
173
179
|
IdName extends string,
|
|
174
|
-
Data extends
|
|
180
|
+
Data extends object,
|
|
175
181
|
> = Flatten<Data extends {[K in IdName]: any} ? PartialBy<Data, IdName> : Data>;
|
|
@@ -3,7 +3,6 @@ import {Adapter} from '../adapter/index.js';
|
|
|
3
3
|
import {AdapterRegistry} from '../adapter/index.js';
|
|
4
4
|
import {InvalidArgumentError} from '../errors/index.js';
|
|
5
5
|
import {DefinitionRegistry} from '../definition/index.js';
|
|
6
|
-
import {ModelDefinitionUtils} from '../definition/index.js';
|
|
7
6
|
|
|
8
7
|
/**
|
|
9
8
|
* Repository.
|
package/src/schema.d.ts
CHANGED
|
@@ -30,7 +30,7 @@ export declare class Schema extends Service {
|
|
|
30
30
|
* @param modelName
|
|
31
31
|
*/
|
|
32
32
|
getRepository<
|
|
33
|
-
Data extends
|
|
33
|
+
Data extends object = ModelData,
|
|
34
34
|
IdType extends ModelId = ModelId,
|
|
35
35
|
IdName extends string = DEFAULT_PRIMARY_KEY_PROPERTY_NAME,
|
|
36
36
|
>(modelName: string): Repository<Data, IdType, IdName>;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import {expect} from 'chai';
|
|
2
|
+
import {Schema} from './schema.js';
|
|
3
|
+
import {Repository} from './repository/index.js';
|
|
4
|
+
import {DefinitionRegistry} from './definition/index.js';
|
|
5
|
+
|
|
6
|
+
describe('Schema', function () {
|
|
7
|
+
describe('defineDatasource', function () {
|
|
8
|
+
it('sets the datasource definition', function () {
|
|
9
|
+
const schema = new Schema();
|
|
10
|
+
schema.defineDatasource({name: 'datasource', adapter: 'memory'});
|
|
11
|
+
const res =
|
|
12
|
+
schema.getService(DefinitionRegistry).getDatasource('datasource');
|
|
13
|
+
expect(res).to.be.eql({name: 'datasource', adapter: 'memory'});
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it('throws an error if the datasource name already defined', function () {
|
|
17
|
+
const schema = new Schema();
|
|
18
|
+
schema.defineDatasource({name: 'datasource', adapter: 'memory'});
|
|
19
|
+
const throwable =
|
|
20
|
+
() => schema.defineDatasource({name: 'datasource', adapter: 'memory'});
|
|
21
|
+
expect(throwable).to.throw(
|
|
22
|
+
'The datasource "datasource" is already defined.',
|
|
23
|
+
);
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
describe('defineModel', function () {
|
|
28
|
+
it('sets the model definition', function () {
|
|
29
|
+
const schema = new Schema();
|
|
30
|
+
schema.defineModel({name: 'model'});
|
|
31
|
+
const res = schema.getService(DefinitionRegistry).getModel('model');
|
|
32
|
+
expect(res).to.be.eql({name: 'model'});
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('throws an error if the model name already defined', function () {
|
|
36
|
+
const schema = new Schema();
|
|
37
|
+
schema.defineModel({name: 'model'});
|
|
38
|
+
const throwable = () => schema.defineModel({name: 'model'});
|
|
39
|
+
expect(throwable).to.throw('The model "model" is already defined.');
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
describe('getRepository', function () {
|
|
44
|
+
it('returns a repository by the model name', function () {
|
|
45
|
+
const schema = new Schema();
|
|
46
|
+
schema.defineDatasource({name: 'datasource', adapter: 'memory'});
|
|
47
|
+
schema.defineModel({name: 'model', datasource: 'datasource'});
|
|
48
|
+
const res = schema.getRepository('model');
|
|
49
|
+
expect(res).to.be.instanceof(Repository);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('throws an error if the model is not defined', function () {
|
|
53
|
+
const schema = new Schema();
|
|
54
|
+
const throwable = () => schema.getRepository('model');
|
|
55
|
+
expect(throwable).to.throw('The model "model" is not defined.');
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('uses generic types to define the repository type', function () {
|
|
59
|
+
const schema = new Schema();
|
|
60
|
+
schema.defineDatasource({name: 'datasource', adapter: 'memory'});
|
|
61
|
+
schema.defineModel({name: 'model', datasource: 'datasource'});
|
|
62
|
+
interface MyModel {
|
|
63
|
+
myId: number;
|
|
64
|
+
}
|
|
65
|
+
const res1: Repository = schema.getRepository('model');
|
|
66
|
+
const res2: Repository<MyModel, number, 'myId'> =
|
|
67
|
+
schema.getRepository<MyModel, number, 'myId'>('model');
|
|
68
|
+
expect(res1).to.be.eq(res2);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
});
|
package/src/types.d.ts
CHANGED
|
@@ -28,3 +28,11 @@ export declare type ModelId = unknown;
|
|
|
28
28
|
*/
|
|
29
29
|
type Identity<T> = T;
|
|
30
30
|
export declare type Flatten<T> = Identity<{[k in keyof T]: T[k]}>;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* A callable type with the "new" operator
|
|
34
|
+
* allows class and constructor.
|
|
35
|
+
*/
|
|
36
|
+
export interface Constructor<T = unknown> {
|
|
37
|
+
new (...args: any[]): T;
|
|
38
|
+
}
|
package/src/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decorator target type.
|
|
3
|
+
*/
|
|
4
|
+
export declare enum DecoratorTargetType {
|
|
5
|
+
CONSTRUCTOR = 'constructor',
|
|
6
|
+
INSTANCE = 'instance',
|
|
7
|
+
STATIC_METHOD = 'staticMethod',
|
|
8
|
+
INSTANCE_METHOD = 'instanceMethod',
|
|
9
|
+
STATIC_PROPERTY = 'staticProperty',
|
|
10
|
+
INSTANCE_PROPERTY = 'instanceProperty',
|
|
11
|
+
CONSTRUCTOR_PARAMETER = 'constructorParameter',
|
|
12
|
+
STATIC_METHOD_PARAMETER = 'staticMethodParameter',
|
|
13
|
+
INSTANCE_METHOD_PARAMETER = 'instanceMethodParameter',
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Get decorator target type.
|
|
18
|
+
*
|
|
19
|
+
* @param target
|
|
20
|
+
* @param propertyKey
|
|
21
|
+
* @param descriptorOrIndex
|
|
22
|
+
*/
|
|
23
|
+
export declare function getDecoratorTargetType(
|
|
24
|
+
target: object,
|
|
25
|
+
propertyKey?: string,
|
|
26
|
+
descriptorOrIndex?: PropertyDescriptor | number,
|
|
27
|
+
): DecoratorTargetType;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {object} PropertyDescriptor
|
|
3
|
+
* @property {boolean|undefined} configurable
|
|
4
|
+
* @property {boolean|undefined} enumerable
|
|
5
|
+
* @property {*} value
|
|
6
|
+
* @property {boolean|undefined} writable
|
|
7
|
+
* @property {Function} get
|
|
8
|
+
* @property {Function} set
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Decorator target type.
|
|
13
|
+
*
|
|
14
|
+
* @enum {string}
|
|
15
|
+
* @property {string} CONSTRUCTOR
|
|
16
|
+
* @property {string} INSTANCE
|
|
17
|
+
* @property {string} STATIC_METHOD
|
|
18
|
+
* @property {string} INSTANCE_METHOD
|
|
19
|
+
* @property {string} STATIC_PROPERTY
|
|
20
|
+
* @property {string} INSTANCE_PROPERTY
|
|
21
|
+
* @property {string} CONSTRUCTOR_PARAMETER
|
|
22
|
+
* @property {string} STATIC_METHOD_PARAMETER
|
|
23
|
+
* @property {string} INSTANCE_METHOD_PARAMETER
|
|
24
|
+
*/
|
|
25
|
+
export const DecoratorTargetType = {
|
|
26
|
+
CONSTRUCTOR: 'constructor',
|
|
27
|
+
INSTANCE: 'instance',
|
|
28
|
+
STATIC_METHOD: 'staticMethod',
|
|
29
|
+
INSTANCE_METHOD: 'instanceMethod',
|
|
30
|
+
STATIC_PROPERTY: 'staticProperty',
|
|
31
|
+
INSTANCE_PROPERTY: 'instanceProperty',
|
|
32
|
+
CONSTRUCTOR_PARAMETER: 'constructorParameter',
|
|
33
|
+
STATIC_METHOD_PARAMETER: 'staticMethodParameter',
|
|
34
|
+
INSTANCE_METHOD_PARAMETER: 'instanceMethodParameter',
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Get decorator target type.
|
|
39
|
+
*
|
|
40
|
+
* @param {object} target
|
|
41
|
+
* @param {string|undefined} propertyKey
|
|
42
|
+
* @param {PropertyDescriptor|number|undefined} descriptorOrIndex
|
|
43
|
+
* @returns {DecoratorTargetType}
|
|
44
|
+
*/
|
|
45
|
+
export function getDecoratorTargetType(target, propertyKey, descriptorOrIndex) {
|
|
46
|
+
const isCtor = typeof target === 'function';
|
|
47
|
+
const isParameter = typeof descriptorOrIndex === 'number';
|
|
48
|
+
const isProperty = propertyKey != null && descriptorOrIndex == null;
|
|
49
|
+
const isMethod = propertyKey != null && descriptorOrIndex != null;
|
|
50
|
+
const D = DecoratorTargetType;
|
|
51
|
+
if (isCtor) {
|
|
52
|
+
if (isParameter)
|
|
53
|
+
return propertyKey ? D.STATIC_METHOD_PARAMETER : D.CONSTRUCTOR_PARAMETER;
|
|
54
|
+
if (isProperty) return D.STATIC_PROPERTY;
|
|
55
|
+
if (isMethod) return D.STATIC_METHOD;
|
|
56
|
+
return D.CONSTRUCTOR;
|
|
57
|
+
} else {
|
|
58
|
+
if (isParameter) return D.INSTANCE_METHOD_PARAMETER;
|
|
59
|
+
if (isProperty) return D.INSTANCE_PROPERTY;
|
|
60
|
+
if (isMethod) return D.INSTANCE_METHOD;
|
|
61
|
+
return D.INSTANCE;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import {expect} from 'chai';
|
|
2
|
+
import {getDecoratorTargetType} from './get-decorator-target-type.js';
|
|
3
|
+
import {DecoratorTargetType as DTT} from './get-decorator-target-type.js';
|
|
4
|
+
|
|
5
|
+
describe('getDecoratorTargetType', function () {
|
|
6
|
+
const validate = function (value) {
|
|
7
|
+
return function (target, propertyKey, descriptorOrIndex) {
|
|
8
|
+
const type = getDecoratorTargetType(
|
|
9
|
+
target,
|
|
10
|
+
propertyKey,
|
|
11
|
+
descriptorOrIndex,
|
|
12
|
+
);
|
|
13
|
+
expect(value).to.be.eq(type);
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
it('returns CONSTRUCTOR', function () {
|
|
18
|
+
class Target {}
|
|
19
|
+
validate(DTT.CONSTRUCTOR)(Target);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('returns INSTANCE', function () {
|
|
23
|
+
class Target {}
|
|
24
|
+
validate(DTT.INSTANCE)(Target.prototype);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('returns STATIC_METHOD', function () {
|
|
28
|
+
class Target {
|
|
29
|
+
static method() {}
|
|
30
|
+
}
|
|
31
|
+
const desc = Object.getOwnPropertyDescriptor(Target, 'method');
|
|
32
|
+
validate(DTT.STATIC_METHOD)(Target, 'method', desc);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('returns INSTANCE_METHOD', function () {
|
|
36
|
+
class Target {
|
|
37
|
+
method() {}
|
|
38
|
+
}
|
|
39
|
+
const desc = Object.getOwnPropertyDescriptor(Target.prototype, 'method');
|
|
40
|
+
validate(DTT.INSTANCE_METHOD)(Target.prototype, 'method', desc);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('returns STATIC_PROPERTY', function () {
|
|
44
|
+
class Target {
|
|
45
|
+
static prop;
|
|
46
|
+
}
|
|
47
|
+
validate(DTT.STATIC_PROPERTY)(Target, 'prop');
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('returns INSTANCE_PROPERTY', function () {
|
|
51
|
+
class Target {
|
|
52
|
+
prop;
|
|
53
|
+
}
|
|
54
|
+
validate(DTT.INSTANCE_PROPERTY)(Target.prototype, 'prop');
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('returns CONSTRUCTOR_PARAMETER', function () {
|
|
58
|
+
class Target {
|
|
59
|
+
constructor(param) {}
|
|
60
|
+
}
|
|
61
|
+
validate(DTT.CONSTRUCTOR_PARAMETER)(Target, undefined, 0);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('returns STATIC_METHOD_PARAMETER', function () {
|
|
65
|
+
class Target {
|
|
66
|
+
static method(param) {}
|
|
67
|
+
}
|
|
68
|
+
validate(DTT.STATIC_METHOD_PARAMETER)(Target, 'method', 0);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it('returns INSTANCE_METHOD_PARAMETER', function () {
|
|
72
|
+
class Target {
|
|
73
|
+
method(param) {}
|
|
74
|
+
}
|
|
75
|
+
validate(DTT.INSTANCE_METHOD_PARAMETER)(Target.prototype, 'method', 0);
|
|
76
|
+
});
|
|
77
|
+
});
|
package/src/utils/index.d.ts
CHANGED
package/src/utils/index.js
CHANGED
package/src/utils/is-ctor.d.ts
CHANGED
package/src/utils/is-ctor.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {expect} from 'chai';
|
|
2
2
|
import {isCtor} from './is-ctor.js';
|
|
3
3
|
|
|
4
|
-
describe('
|
|
4
|
+
describe('isCtor', function () {
|
|
5
5
|
it('returns true if a given value is a constructor', function () {
|
|
6
6
|
expect(isCtor(Date)).to.be.true;
|
|
7
7
|
expect(isCtor(Number)).to.be.true;
|
package/tsconfig.json
CHANGED