@forklaunch/core 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/.prettierignore +2 -0
- package/.prettierrc +6 -0
- package/dist/cache/index.d.ts +3 -0
- package/dist/cache/index.js +20 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/cache/interfaces/ttlCache.interface.d.ts +1 -1
- package/dist/cache/redisTtlCache.d.ts +3 -2
- package/dist/cache/redisTtlCache.js +2 -2
- package/dist/cache/redisTtlCache.js.map +1 -1
- package/dist/cache/types/{ttlCacheRecord.js → ttlCacheRecord.types.js} +1 -1
- package/dist/cache/types/ttlCacheRecord.types.js.map +1 -0
- package/dist/controllers/index.d.ts +1 -0
- package/dist/controllers/index.js +18 -0
- package/dist/controllers/index.js.map +1 -0
- package/dist/database/index.d.ts +1 -0
- package/dist/database/index.js +18 -0
- package/dist/database/index.js.map +1 -0
- package/dist/database/mikro/models/entities/base.entity.js +1 -1
- package/dist/entityMapper/index.d.ts +2 -0
- package/dist/entityMapper/index.js +19 -0
- package/dist/entityMapper/index.js.map +1 -0
- package/dist/entityMapper/interfaces/entityMapper.interface.d.ts +3 -3
- package/dist/entityMapper/models/baseEntityMapper.model.d.ts +23 -23
- package/dist/entityMapper/models/baseEntityMapper.model.js +17 -17
- package/dist/entityMapper/models/baseEntityMapper.model.js.map +1 -1
- package/dist/entityMapper/models/requestEntityMapper.model.d.ts +17 -23
- package/dist/entityMapper/models/requestEntityMapper.model.js +13 -19
- package/dist/entityMapper/models/requestEntityMapper.model.js.map +1 -1
- package/dist/entityMapper/models/responseEntityMapper.model.d.ts +15 -16
- package/dist/entityMapper/models/responseEntityMapper.model.js +8 -8
- package/dist/entityMapper/models/responseEntityMapper.model.js.map +1 -1
- package/dist/entityMapper/types/entityMapper.types.d.ts +3 -22
- package/dist/http/index.d.ts +2 -0
- package/dist/http/index.js +19 -0
- package/dist/http/index.js.map +1 -0
- package/dist/http/middlewares/index.d.ts +2 -0
- package/dist/http/middlewares/index.js +19 -0
- package/dist/http/middlewares/index.js.map +1 -0
- package/dist/http/middlewares/request.middleware.d.ts +11 -11
- package/dist/http/middlewares/request.middleware.js +32 -31
- package/dist/http/middlewares/request.middleware.js.map +1 -1
- package/dist/http/middlewares/response.middleware.d.ts +3 -2
- package/dist/http/middlewares/response.middleware.js +9 -6
- package/dist/http/middlewares/response.middleware.js.map +1 -1
- package/dist/http/types/api.types.d.ts +16 -13
- package/dist/http/types/index.d.ts +2 -0
- package/dist/http/types/index.js +19 -0
- package/dist/http/types/index.js.map +1 -0
- package/dist/http/types/primitive.types.d.ts +14 -13
- package/dist/index.d.ts +6 -1
- package/dist/index.js +20 -5
- package/dist/index.js.map +1 -1
- package/dist/services/index.d.ts +1 -0
- package/dist/services/index.js +18 -0
- package/dist/services/index.js.map +1 -0
- package/dist/services/interfaces/baseService.d.ts +1 -1
- package/dist/tests/{dto.test.js → entityMapper.test.js} +10 -32
- package/dist/tests/entityMapper.test.js.map +1 -0
- package/dist/tests/http.middleware.test.d.ts +1 -0
- package/dist/tests/http.middleware.test.js +79 -0
- package/dist/tests/http.middleware.test.js.map +1 -0
- package/dist/tests/redisTtlCache.test.js +32 -15
- package/dist/tests/redisTtlCache.test.js.map +1 -1
- package/entityMapper/index.ts +2 -0
- package/entityMapper/interfaces/entityMapper.interface.ts +11 -11
- package/entityMapper/models/baseEntityMapper.model.ts +90 -73
- package/entityMapper/models/requestEntityMapper.model.ts +96 -76
- package/entityMapper/models/responseEntityMapper.model.ts +83 -62
- package/entityMapper/types/entityMapper.types.ts +6 -23
- package/http/index.ts +2 -0
- package/http/middlewares/index.ts +2 -0
- package/http/middlewares/request.middleware.ts +118 -62
- package/http/middlewares/response.middleware.ts +56 -30
- package/http/types/api.types.ts +43 -25
- package/http/types/index.ts +2 -0
- package/http/types/primitive.types.ts +65 -44
- package/index.ts +6 -5
- package/jest.config.ts +2 -2
- package/package.json +13 -4
- package/tests/entityMapper.test.ts +219 -0
- package/tests/http.middleware.test.ts +99 -0
- package/tests/redisTtlCache.test.ts +49 -29
- package/dist/cache/types/ttlCacheRecord.js.map +0 -1
- package/dist/tests/dto.test.js.map +0 -1
- package/tests/dto.test.ts +0 -235
- /package/dist/cache/types/{ttlCacheRecord.d.ts → ttlCacheRecord.types.d.ts} +0 -0
- /package/dist/tests/{dto.test.d.ts → entityMapper.test.d.ts} +0 -0
@@ -8,34 +8,11 @@ class TestEntity extends base_entity_1.BaseEntity {
|
|
8
8
|
name;
|
9
9
|
age;
|
10
10
|
}
|
11
|
-
class T extends requestEntityMapper_model_1.RequestEntityMapper {
|
12
|
-
toEntity(...additionalArgs) {
|
13
|
-
const entity = new TestEntity();
|
14
|
-
entity.id = this.dto.id;
|
15
|
-
entity.name = this.dto.name;
|
16
|
-
entity.age = this.dto.age;
|
17
|
-
return entity;
|
18
|
-
}
|
19
|
-
schema = {
|
20
|
-
id: typebox_1.string,
|
21
|
-
name: typebox_1.string,
|
22
|
-
age: typebox_1.number
|
23
|
-
};
|
24
|
-
}
|
25
|
-
const y = new T(new typebox_1.TypeboxSchemaValidator());
|
26
|
-
y.fromJson({ id: '123', name: 'test', age: 1 });
|
27
|
-
var x = { id: '123', name: 'test', age: 1 };
|
28
|
-
T.fromJson(new typebox_1.TypeboxSchemaValidator(), x);
|
29
|
-
T.fromJson(new typebox_1.TypeboxSchemaValidator(), {
|
30
|
-
id: '123',
|
31
|
-
name: 'test',
|
32
|
-
age: 1
|
33
|
-
});
|
34
11
|
class TestRequestEntityMapper extends requestEntityMapper_model_1.RequestEntityMapper {
|
35
12
|
schema = {
|
36
13
|
id: typebox_1.string,
|
37
14
|
name: typebox_1.string,
|
38
|
-
age: typebox_1.number
|
15
|
+
age: typebox_1.number
|
39
16
|
};
|
40
17
|
toEntity(...additionalArgs) {
|
41
18
|
const entity = new TestEntity();
|
@@ -77,14 +54,14 @@ describe('Request Entity Mapper Test', () => {
|
|
77
54
|
const json = {
|
78
55
|
id: '123',
|
79
56
|
name: 'test',
|
80
|
-
age: 1
|
57
|
+
age: 1
|
81
58
|
};
|
82
59
|
const responseEM = TestRequestEM.fromJson(json);
|
83
60
|
const staticEM = TestRequestEntityMapper.fromJson(new typebox_1.TypeboxSchemaValidator(), json);
|
84
61
|
const expectedDto = {
|
85
62
|
id: '123',
|
86
63
|
name: 'test',
|
87
|
-
age: 1
|
64
|
+
age: 1
|
88
65
|
};
|
89
66
|
expect(staticEM.dto).toEqual(expectedDto);
|
90
67
|
expect(responseEM.dto).toEqual(expectedDto);
|
@@ -94,7 +71,7 @@ describe('Request Entity Mapper Test', () => {
|
|
94
71
|
const json = {
|
95
72
|
id: '123',
|
96
73
|
name: 'test',
|
97
|
-
age: 1
|
74
|
+
age: 1
|
98
75
|
};
|
99
76
|
const entity = extractNonTimeBasedEntityFields(TestRequestEM.deserializeJsonToEntity(json));
|
100
77
|
const objectEntity = extractNonTimeBasedEntityFields(TestRequestEM.fromJson(json).toEntity());
|
@@ -115,12 +92,13 @@ describe('Request Entity Mapper Test', () => {
|
|
115
92
|
test('Serialization Failure', async () => {
|
116
93
|
const json = {
|
117
94
|
id: '123',
|
118
|
-
name: 'test'
|
95
|
+
name: 'test'
|
119
96
|
};
|
120
97
|
// @ts-expect-error
|
121
98
|
expect(() => TestRequestEM.fromJson(json)).toThrow();
|
99
|
+
expect(() =>
|
122
100
|
// @ts-expect-error
|
123
|
-
|
101
|
+
TestRequestEntityMapper.fromJson(new typebox_1.TypeboxSchemaValidator(), json)).toThrow();
|
124
102
|
});
|
125
103
|
});
|
126
104
|
describe('Response Entity Mapper Test', () => {
|
@@ -141,7 +119,7 @@ describe('Response Entity Mapper Test', () => {
|
|
141
119
|
const expectedDto = {
|
142
120
|
id: '123',
|
143
121
|
name: 'test',
|
144
|
-
age: 1
|
122
|
+
age: 1
|
145
123
|
};
|
146
124
|
expect(staticEM.dto).toEqual(expectedDto);
|
147
125
|
expect(responseEM.dto).toEqual(expectedDto);
|
@@ -158,7 +136,7 @@ describe('Response Entity Mapper Test', () => {
|
|
158
136
|
const expectedJson = {
|
159
137
|
id: '123',
|
160
138
|
name: 'test',
|
161
|
-
age: 1
|
139
|
+
age: 1
|
162
140
|
};
|
163
141
|
expect(json).toEqual(expectedJson);
|
164
142
|
expect(objectJson).toEqual(expectedJson);
|
@@ -176,4 +154,4 @@ describe('Response Entity Mapper Test', () => {
|
|
176
154
|
expect(() => TestResponseEntityMapper.fromEntity(new typebox_1.TypeboxSchemaValidator(), entity).toJson()).toThrow();
|
177
155
|
});
|
178
156
|
});
|
179
|
-
//# sourceMappingURL=
|
157
|
+
//# sourceMappingURL=entityMapper.test.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"entityMapper.test.js","sourceRoot":"","sources":["../../tests/entityMapper.test.ts"],"names":[],"mappings":"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"}
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
@@ -0,0 +1,79 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
const mockSchemaValidator_1 = require("@forklaunch/validator/tests/mockSchemaValidator");
|
4
|
+
const http_1 = require("../http");
|
5
|
+
describe('Http Middleware Tests', () => {
|
6
|
+
let contractDetails;
|
7
|
+
let req;
|
8
|
+
let resp;
|
9
|
+
const nextFunction = (err) => {
|
10
|
+
expect(err).toBeFalsy();
|
11
|
+
};
|
12
|
+
const testSchema = {
|
13
|
+
test: (0, mockSchemaValidator_1.union)(['a', (0, mockSchemaValidator_1.optional)((0, mockSchemaValidator_1.literal)('test'))])
|
14
|
+
};
|
15
|
+
beforeAll(() => {
|
16
|
+
contractDetails = {
|
17
|
+
name: 'Test Contract',
|
18
|
+
summary: 'Test Contract Summary',
|
19
|
+
body: testSchema,
|
20
|
+
params: testSchema,
|
21
|
+
requestHeaders: testSchema,
|
22
|
+
query: testSchema,
|
23
|
+
responses: {
|
24
|
+
200: testSchema
|
25
|
+
}
|
26
|
+
};
|
27
|
+
req = {
|
28
|
+
context: {},
|
29
|
+
contractDetails: {},
|
30
|
+
schemaValidator: {},
|
31
|
+
params: testSchema,
|
32
|
+
headers: testSchema,
|
33
|
+
body: testSchema,
|
34
|
+
query: testSchema
|
35
|
+
};
|
36
|
+
resp = {
|
37
|
+
bodyData: {},
|
38
|
+
statusCode: 200,
|
39
|
+
corked: false,
|
40
|
+
getHeaders: jest.fn(),
|
41
|
+
setHeader: jest.fn(),
|
42
|
+
status: jest.fn(),
|
43
|
+
send: jest.fn(),
|
44
|
+
json: jest.fn(),
|
45
|
+
jsonp: jest.fn(),
|
46
|
+
};
|
47
|
+
});
|
48
|
+
test('Create Request Context', async () => {
|
49
|
+
req.context = {};
|
50
|
+
req.schemaValidator = {};
|
51
|
+
(0, http_1.createRequestContext)(mockSchemaValidator_1.mockSchemaValidator)(req, resp, nextFunction);
|
52
|
+
expect(req.context.correlationId).not.toBe('123');
|
53
|
+
expect(req.schemaValidator).toBe(mockSchemaValidator_1.mockSchemaValidator);
|
54
|
+
});
|
55
|
+
test('Enrich Request Details', async () => {
|
56
|
+
req.contractDetails = {};
|
57
|
+
(0, http_1.enrichRequestDetails)(contractDetails)(req, resp, nextFunction);
|
58
|
+
expect(req.contractDetails).toEqual(contractDetails);
|
59
|
+
});
|
60
|
+
test('Validate Request Params', async () => {
|
61
|
+
(0, http_1.parseRequestParams)(req, resp, nextFunction);
|
62
|
+
});
|
63
|
+
test('Validate Request Headers', async () => {
|
64
|
+
(0, http_1.parseRequestHeaders)(req, resp, nextFunction);
|
65
|
+
});
|
66
|
+
test('Validate Request Body', async () => {
|
67
|
+
(0, http_1.parseRequestBody)(req, resp, nextFunction);
|
68
|
+
});
|
69
|
+
test('Validate Request Query Params', async () => {
|
70
|
+
(0, http_1.parseRequestQuery)(req, resp, nextFunction);
|
71
|
+
});
|
72
|
+
test('Validate Response', async () => {
|
73
|
+
(0, http_1.parseResponse)(req, resp, nextFunction);
|
74
|
+
});
|
75
|
+
// Not supported yet
|
76
|
+
// test('Validate Auth', async () => {
|
77
|
+
// });
|
78
|
+
});
|
79
|
+
//# sourceMappingURL=http.middleware.test.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"http.middleware.test.js","sourceRoot":"","sources":["../../tests/http.middleware.test.ts"],"names":[],"mappings":"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"}
|
@@ -1,35 +1,52 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
const testcontainers_1 = require("testcontainers");
|
3
4
|
const redisTtlCache_1 = require("../cache/redisTtlCache");
|
4
5
|
describe('RedisTtlCache', () => {
|
6
|
+
let container;
|
5
7
|
let cache;
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
let key;
|
9
|
+
let value;
|
10
|
+
let ttlMilliseconds;
|
11
|
+
beforeAll(async () => {
|
12
|
+
container = await new testcontainers_1.GenericContainer('redis')
|
13
|
+
.withExposedPorts(6379)
|
14
|
+
.start();
|
15
|
+
cache = new redisTtlCache_1.RedisTtlCache(5000, {
|
16
|
+
url: `redis://${container.getHost()}:${container.getMappedPort(6379)}`
|
17
|
+
});
|
18
|
+
key = 'testKey';
|
19
|
+
value = { data: 'testValue' };
|
20
|
+
ttlMilliseconds = 1000;
|
21
|
+
}, 30000);
|
11
22
|
afterAll(async () => {
|
12
|
-
// Ensure the Redis client is disconnected after tests complete
|
13
23
|
await cache.disconnect();
|
24
|
+
await container.stop();
|
14
25
|
});
|
15
|
-
|
16
|
-
const key = 'testKey';
|
17
|
-
const value = { data: 'testValue' };
|
18
|
-
const ttlMilliseconds = 10000; // 10 seconds
|
26
|
+
it('PutRecord', async () => {
|
19
27
|
await cache.putRecord({ key, value, ttlMilliseconds });
|
28
|
+
});
|
29
|
+
test('Read Record', async () => {
|
20
30
|
const storedValue = await cache.readRecord(key);
|
21
|
-
expect(storedValue).toEqual(
|
31
|
+
expect(storedValue).toEqual({
|
32
|
+
key,
|
33
|
+
ttlMilliseconds,
|
34
|
+
value
|
35
|
+
});
|
22
36
|
});
|
23
|
-
test('
|
24
|
-
const key = 'testKey';
|
37
|
+
test('Peek Record', async () => {
|
25
38
|
const exists = await cache.peekRecord(key);
|
26
39
|
expect(exists).toBeTruthy();
|
27
40
|
});
|
28
|
-
test('
|
29
|
-
const key = 'testKey';
|
41
|
+
test('Delete Record', async () => {
|
30
42
|
await cache.deleteRecord(key);
|
31
43
|
const existsAfterDelete = await cache.peekRecord(key);
|
32
44
|
expect(existsAfterDelete).toBeFalsy();
|
33
45
|
});
|
46
|
+
test('Check No Record', async () => {
|
47
|
+
await Promise.resolve(setTimeout(async () => { }, ttlMilliseconds));
|
48
|
+
const existsAfterTtl = await cache.peekRecord(key);
|
49
|
+
expect(existsAfterTtl).toBeFalsy();
|
50
|
+
});
|
34
51
|
});
|
35
52
|
//# sourceMappingURL=redisTtlCache.test.js.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"redisTtlCache.test.js","sourceRoot":"","sources":["../../tests/redisTtlCache.test.ts"],"names":[],"mappings":";;AAAA,0DAAuD;AAEvD,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;
|
1
|
+
{"version":3,"file":"redisTtlCache.test.js","sourceRoot":"","sources":["../../tests/redisTtlCache.test.ts"],"names":[],"mappings":";;AAAA,mDAAwE;AACxE,0DAAuD;AAEvD,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC7B,IAAI,SAA+B,CAAC;IACpC,IAAI,KAAoB,CAAC;IACzB,IAAI,GAAW,CAAC;IAChB,IAAI,KAAc,CAAC;IACnB,IAAI,eAAuB,CAAC;IAE5B,SAAS,CAAC,KAAK,IAAI,EAAE;QACnB,SAAS,GAAG,MAAM,IAAI,iCAAgB,CAAC,OAAO,CAAC;aAC5C,gBAAgB,CAAC,IAAI,CAAC;aACtB,KAAK,EAAE,CAAC;QAEX,KAAK,GAAG,IAAI,6BAAa,CAAC,IAAI,EAAE;YAC9B,GAAG,EAAE,WAAW,SAAS,CAAC,OAAO,EAAE,IAAI,SAAS,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE;SACvE,CAAC,CAAC;QAEH,GAAG,GAAG,SAAS,CAAC;QAChB,KAAK,GAAG,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;QAC9B,eAAe,GAAG,IAAI,CAAC;IACzB,CAAC,EAAE,KAAK,CAAC,CAAC;IAEV,QAAQ,CAAC,KAAK,IAAI,EAAE;QAClB,MAAM,KAAK,CAAC,UAAU,EAAE,CAAC;QACzB,MAAM,SAAS,CAAC,IAAI,EAAE,CAAC;IACzB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,WAAW,EAAE,KAAK,IAAI,EAAE;QACzB,MAAM,KAAK,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,aAAa,EAAE,KAAK,IAAI,EAAE;QAC7B,MAAM,WAAW,GAAG,MAAM,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;QAEhD,MAAM,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC;YAC1B,GAAG;YACH,eAAe;YACf,KAAK;SACN,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,aAAa,EAAE,KAAK,IAAI,EAAE;QAC7B,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;QAE3C,MAAM,CAAC,MAAM,CAAC,CAAC,UAAU,EAAE,CAAC;IAC9B,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,eAAe,EAAE,KAAK,IAAI,EAAE;QAC/B,MAAM,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;QAC9B,MAAM,iBAAiB,GAAG,MAAM,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;QAEtD,MAAM,CAAC,iBAAiB,CAAC,CAAC,SAAS,EAAE,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,iBAAiB,EAAE,KAAK,IAAI,EAAE;QACjC,MAAM,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,IAAI,EAAE,GAAE,CAAC,EAAE,eAAe,CAAC,CAAC,CAAC;QACnE,MAAM,cAAc,GAAG,MAAM,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;QACnD,MAAM,CAAC,cAAc,CAAC,CAAC,SAAS,EAAE,CAAC;IACrC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
@@ -1,17 +1,17 @@
|
|
1
|
-
import {
|
1
|
+
import { AnySchemaValidator } from '@forklaunch/validator';
|
2
2
|
|
3
3
|
/**
|
4
4
|
* Interface representing a constructor for an entity mapper.
|
5
|
-
*
|
5
|
+
*
|
6
6
|
* @template T - The type of the entity mapper.
|
7
7
|
* @interface EntityMapperConstructor
|
8
8
|
*/
|
9
|
-
export interface EntityMapperConstructor<T, SV extends
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
}
|
9
|
+
export interface EntityMapperConstructor<T, SV extends AnySchemaValidator> {
|
10
|
+
/**
|
11
|
+
* Creates a new instance of the entity mapper.
|
12
|
+
*
|
13
|
+
* @param {AnySchemaValidator} schemaValidator - The arguments to pass to the constructor.
|
14
|
+
* @returns {T} - A new instance of the entity mapper.
|
15
|
+
*/
|
16
|
+
new (schemaValidator: SV): T;
|
17
|
+
}
|
@@ -1,17 +1,24 @@
|
|
1
|
-
import {
|
2
|
-
|
3
|
-
|
1
|
+
import {
|
2
|
+
AnySchemaValidator,
|
3
|
+
Schema,
|
4
|
+
SchemaValidator
|
5
|
+
} from '@forklaunch/validator';
|
6
|
+
import { EntityMapperConstructor } from '../interfaces/entityMapper.interface';
|
7
|
+
import { EntityMapperSchemaValidatorObject } from '../types/entityMapper.types';
|
4
8
|
|
5
9
|
/**
|
6
|
-
* Constructs an instance of a
|
10
|
+
* Constructs an instance of a T.
|
7
11
|
*
|
8
|
-
* @template
|
9
|
-
* @param {EntityMapperConstructor<
|
12
|
+
* @template T - A type that extends BaseEntityMapper.
|
13
|
+
* @param {EntityMapperConstructor<T>} self - The constructor of the T.
|
10
14
|
* @param {...any[]} args - The arguments to pass to the constructor.
|
11
|
-
* @returns {
|
15
|
+
* @returns {T} - An instance of the T.
|
12
16
|
*/
|
13
|
-
export function construct<
|
14
|
-
|
17
|
+
export function construct<T, SV extends AnySchemaValidator>(
|
18
|
+
self: EntityMapperConstructor<T, SV>,
|
19
|
+
schemaValidator?: SV
|
20
|
+
): T {
|
21
|
+
return new self(schemaValidator || ({} as SV));
|
15
22
|
}
|
16
23
|
|
17
24
|
/**
|
@@ -19,75 +26,85 @@ export function construct<EntityMapperType, SV extends SchemaValidator>(self: En
|
|
19
26
|
*
|
20
27
|
* @template SV - A type that extends SchemaValidator.
|
21
28
|
*/
|
22
|
-
export abstract class BaseEntityMapper<SV extends
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
+
export abstract class BaseEntityMapper<SV extends AnySchemaValidator> {
|
30
|
+
/**
|
31
|
+
* The schema validator exact type.
|
32
|
+
* @type {SV}
|
33
|
+
* @protected
|
34
|
+
*/
|
35
|
+
_SV!: SV;
|
29
36
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
37
|
+
/**
|
38
|
+
* The schema validator as a general type.
|
39
|
+
* @type {SchemaValidator}
|
40
|
+
* @protected
|
41
|
+
*/
|
42
|
+
protected schemaValidator: SchemaValidator;
|
36
43
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
44
|
+
/**
|
45
|
+
* The schema definition.
|
46
|
+
* @type {EntityMapperSchemaValidatorObject<SV>}
|
47
|
+
* @abstract
|
48
|
+
*/
|
49
|
+
abstract schema: EntityMapperSchemaValidatorObject<SV>;
|
43
50
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
51
|
+
/**
|
52
|
+
* The Data Transfer Object (DTO).
|
53
|
+
* @type {Schema<this['schema'], SV>}
|
54
|
+
*
|
55
|
+
*/
|
56
|
+
_dto: Schema<this['schema'], SV> = {} as unknown as Schema<
|
57
|
+
this['schema'],
|
58
|
+
SV
|
59
|
+
>;
|
50
60
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
61
|
+
/**
|
62
|
+
* Creates an instance of BaseEntityMapper.
|
63
|
+
*
|
64
|
+
* @param {SV} schemaValidator - The schema provider.
|
65
|
+
*/
|
66
|
+
constructor(schemaValidator: SV) {
|
67
|
+
this.schemaValidator = schemaValidator as unknown as SchemaValidator;
|
68
|
+
}
|
59
69
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
70
|
+
/**
|
71
|
+
* Validates and sets the Data Transfer Object (DTO).
|
72
|
+
*
|
73
|
+
* @param {this['_dto']} dto - The Data Transfer Object (DTO).
|
74
|
+
* @throws {Error} - Throws an error if the DTO is invalid.
|
75
|
+
*/
|
76
|
+
set dto(_dto: this['_dto']) {
|
77
|
+
if (
|
78
|
+
!this.schemaValidator.validate(
|
79
|
+
this.schemaValidator.schemify(this.schema),
|
80
|
+
_dto
|
81
|
+
)
|
82
|
+
) {
|
83
|
+
throw new Error('Invalid DTO');
|
71
84
|
}
|
85
|
+
this._dto = _dto as unknown as Schema<this['schema'], SV>;
|
86
|
+
}
|
72
87
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
88
|
+
/**
|
89
|
+
* Validates and gets the Data Transfer Object (DTO).
|
90
|
+
*
|
91
|
+
* @returns {this['_dto']} - The Data Transfer Object (DTO).
|
92
|
+
* @throws {Error} - Throws an error if the DTO is invalid.
|
93
|
+
*/
|
94
|
+
get dto(): this['_dto'] {
|
95
|
+
return this._dto as unknown as this['_dto'];
|
96
|
+
}
|
82
97
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
98
|
+
/**
|
99
|
+
* Gets the schema of a T.
|
100
|
+
*
|
101
|
+
* @template T - A type that extends BaseEntityMapper.
|
102
|
+
* @param {EntityMapperConstructor<T>} this - The constructor of the T.
|
103
|
+
* @returns {T['schema']} - The schema of the T.
|
104
|
+
*/
|
105
|
+
static schema<T extends BaseEntityMapper<SV>, SV extends AnySchemaValidator>(
|
106
|
+
this: EntityMapperConstructor<T, SV>
|
107
|
+
): T['schema'] {
|
108
|
+
return construct(this).schema;
|
109
|
+
}
|
110
|
+
}
|