@nmxjs/types 1.0.21 → 1.1.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.
@@ -0,0 +1 @@
1
+ export const paginationLimit = 25;
@@ -0,0 +1,19 @@
1
+ const fieldMetadata = new Map<string, Map<string, any>>();
2
+
3
+ export const getFieldMetadata = (target: string, property: string) => {
4
+ return fieldMetadata.get(target)?.get(property);
5
+ };
6
+
7
+ export const getAllFieldMetadata = (target: string) => {
8
+ return fieldMetadata.get(target);
9
+ };
10
+
11
+ export const Field = (options: any): PropertyDecorator => {
12
+ return (target: any, propertyKey: string | symbol) => {
13
+ const className = target.constructor.name;
14
+ if (!fieldMetadata.has(className)) {
15
+ fieldMetadata.set(className, new Map());
16
+ }
17
+ fieldMetadata.get(className)!.set(String(propertyKey), options);
18
+ };
19
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nmxjs/types",
3
- "version": "1.0.21",
3
+ "version": "1.1.0",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -22,6 +22,9 @@
22
22
  },
23
23
  "homepage": "https://github.com/n1ghtm6r9/nm-types#readme",
24
24
  "devDependencies": {
25
+ "@types/jest": "^30.0.0",
26
+ "jest": "^30.2.0",
27
+ "ts-jest": "^29.4.6",
25
28
  "typescript": "^5.1.6"
26
29
  },
27
30
  "dependencies": {
@@ -0,0 +1,28 @@
1
+ import { getAllFieldMetadata } from '../../__mocks__/@nmxjs/validation';
2
+ import { EntityDto } from '../../src/dto/EntityDto';
3
+
4
+ describe('EntityDto', () => {
5
+ beforeAll(() => {
6
+ new (EntityDto as any)();
7
+ });
8
+
9
+ it('id should have type String', () => {
10
+ const meta = getAllFieldMetadata('EntityDto');
11
+ expect(meta?.get('id')).toEqual({ type: String });
12
+ });
13
+
14
+ it('createdAt should have type Number', () => {
15
+ const meta = getAllFieldMetadata('EntityDto');
16
+ expect(meta?.get('createdAt')).toEqual({ type: Number });
17
+ });
18
+
19
+ it('updatedAt should have type Number', () => {
20
+ const meta = getAllFieldMetadata('EntityDto');
21
+ expect(meta?.get('updatedAt')).toEqual({ type: Number });
22
+ });
23
+
24
+ it('should have exactly 3 fields', () => {
25
+ const meta = getAllFieldMetadata('EntityDto');
26
+ expect(meta?.size).toBe(3);
27
+ });
28
+ });
@@ -0,0 +1,34 @@
1
+ import { getAllFieldMetadata } from '../../__mocks__/@nmxjs/validation';
2
+ import { GetOneRequestDto } from '../../src/dto/GetOneRequestDto';
3
+
4
+ describe('GetOneRequestDto', () => {
5
+ beforeAll(() => {
6
+ new (GetOneRequestDto as any)();
7
+ });
8
+
9
+ it('id should have type String', () => {
10
+ const meta = getAllFieldMetadata('GetOneRequestDto');
11
+ expect(meta?.get('id')).toEqual({
12
+ type: String,
13
+ });
14
+ });
15
+
16
+ it('select should be nullable array of String without GraphQL', () => {
17
+ const meta = getAllFieldMetadata('GetOneRequestDto');
18
+ expect(meta?.get('select')).toEqual({
19
+ type: String,
20
+ array: true,
21
+ nullable: true,
22
+ withoutGraphQl: true,
23
+ });
24
+ });
25
+
26
+ it('reject should be nullable Boolean without GraphQL', () => {
27
+ const meta = getAllFieldMetadata('GetOneRequestDto');
28
+ expect(meta?.get('reject')).toEqual({
29
+ type: Boolean,
30
+ nullable: true,
31
+ withoutGraphQl: true,
32
+ });
33
+ });
34
+ });
@@ -0,0 +1,19 @@
1
+ import { GetOneResponseDto } from '../../src/dto/GetOneResponseDto';
2
+
3
+ describe('GetOneResponseDto', () => {
4
+ it('should be abstract class with field item', () => {
5
+ class TestResponse extends GetOneResponseDto<{ name: string }> {
6
+ item? = { name: 'test' };
7
+ }
8
+ const instance = new TestResponse();
9
+ expect(instance.item).toEqual({ name: 'test' });
10
+ });
11
+
12
+ it('item can be undefined', () => {
13
+ class TestResponse extends GetOneResponseDto<{ name: string }> {
14
+ item? = undefined;
15
+ }
16
+ const instance = new TestResponse();
17
+ expect(instance.item).toBeUndefined();
18
+ });
19
+ });
@@ -0,0 +1,47 @@
1
+ import { getAllFieldMetadata } from '../../__mocks__/@nmxjs/validation';
2
+ import { ListRequestDto } from '../../src/dto/ListRequestDto';
3
+ import { ListRequestFilterDto } from '../../src/dto/ListRequestFilterDto';
4
+ import { ListRequestSortDto } from '../../src/dto/ListRequestSortDto';
5
+ import { ListRequestPaginationDto } from '../../src/dto/ListRequestPaginationDto';
6
+
7
+ describe('ListRequestDto', () => {
8
+ beforeAll(() => {
9
+ new (ListRequestDto as any)();
10
+ });
11
+
12
+ it('filters should be nullable array of ListRequestFilterDto', () => {
13
+ const meta = getAllFieldMetadata('ListRequestDto');
14
+ expect(meta?.get('filters')).toEqual({
15
+ type: ListRequestFilterDto,
16
+ array: true,
17
+ nullable: true,
18
+ });
19
+ });
20
+
21
+ it('sorts should be nullable array of ListRequestSortDto', () => {
22
+ const meta = getAllFieldMetadata('ListRequestDto');
23
+ expect(meta?.get('sorts')).toEqual({
24
+ type: ListRequestSortDto,
25
+ array: true,
26
+ nullable: true,
27
+ });
28
+ });
29
+
30
+ it('pagination should be nullable ListRequestPaginationDto', () => {
31
+ const meta = getAllFieldMetadata('ListRequestDto');
32
+ expect(meta?.get('pagination')).toEqual({
33
+ type: ListRequestPaginationDto,
34
+ nullable: true,
35
+ });
36
+ });
37
+
38
+ it('select should be nullable array of String without GraphQL', () => {
39
+ const meta = getAllFieldMetadata('ListRequestDto');
40
+ expect(meta?.get('select')).toEqual({
41
+ type: String,
42
+ array: true,
43
+ nullable: true,
44
+ withoutGraphQl: true,
45
+ });
46
+ });
47
+ });
@@ -0,0 +1,101 @@
1
+ import { getAllFieldMetadata } from '../../__mocks__/@nmxjs/validation';
2
+ import { FilterOperatorEnum } from '../../src/interfaces';
3
+ import { ListRequestFilterDto } from '../../src/dto/ListRequestFilterDto';
4
+
5
+ describe('ListRequestFilterDto', () => {
6
+ beforeAll(() => {
7
+ new (ListRequestFilterDto as any)();
8
+ });
9
+
10
+ it('field should have type String', () => {
11
+ const meta = getAllFieldMetadata('ListRequestFilterDto');
12
+ expect(meta?.get('field')).toEqual({ type: String });
13
+ });
14
+
15
+ it('value should have type JSON (not String)', () => {
16
+ const meta = getAllFieldMetadata('ListRequestFilterDto');
17
+ expect(meta?.get('value')).toEqual({ type: JSON });
18
+ });
19
+
20
+ it('value should NOT have type String', () => {
21
+ const meta = getAllFieldMetadata('ListRequestFilterDto');
22
+ expect(meta?.get('value')?.type).not.toBe(String);
23
+ });
24
+
25
+ it('operator should be enum FilterOperatorEnum', () => {
26
+ const meta = getAllFieldMetadata('ListRequestFilterDto');
27
+ expect(meta?.get('operator')).toEqual({
28
+ type: { FilterOperatorEnum },
29
+ enum: true,
30
+ });
31
+ });
32
+
33
+ it('not should be nullable Boolean', () => {
34
+ const meta = getAllFieldMetadata('ListRequestFilterDto');
35
+ expect(meta?.get('not')).toEqual({
36
+ type: Boolean,
37
+ nullable: true,
38
+ });
39
+ });
40
+
41
+ describe('value accepts different data types', () => {
42
+ it('string "test"', () => {
43
+ class TestFilter extends ListRequestFilterDto {
44
+ field = 'name';
45
+ value: any = 'test';
46
+ operator = FilterOperatorEnum.EQ;
47
+ }
48
+ const instance = new TestFilter();
49
+ expect(instance.value).toBe('test');
50
+ expect(typeof instance.value).toBe('string');
51
+ });
52
+
53
+ it('array ["a", "b"]', () => {
54
+ class TestFilter extends ListRequestFilterDto {
55
+ field = 'id';
56
+ value: any = ['a', 'b'];
57
+ operator = FilterOperatorEnum.IN;
58
+ }
59
+ const instance = new TestFilter();
60
+ expect(instance.value).toEqual(['a', 'b']);
61
+ expect(Array.isArray(instance.value)).toBe(true);
62
+ });
63
+
64
+ it('number 123', () => {
65
+ class TestFilter extends ListRequestFilterDto {
66
+ field = 'age';
67
+ value: any = 123;
68
+ operator = FilterOperatorEnum.EQ;
69
+ }
70
+ const instance = new TestFilter();
71
+ expect(instance.value).toBe(123);
72
+ expect(typeof instance.value).toBe('number');
73
+ });
74
+
75
+ it('object { key: "val" }', () => {
76
+ class TestFilter extends ListRequestFilterDto {
77
+ field = 'data';
78
+ value: any = { key: 'val' };
79
+ operator = FilterOperatorEnum.EQ;
80
+ }
81
+ const instance = new TestFilter();
82
+ expect(instance.value).toEqual({ key: 'val' });
83
+ expect(typeof instance.value).toBe('object');
84
+ expect(Array.isArray(instance.value)).toBe(false);
85
+ });
86
+
87
+ it('UUID array for IN operator', () => {
88
+ const uuids = ['550e8400-e29b-41d4-a716-446655440000', '6ba7b810-9dad-11d1-80b4-00c04fd430c8'];
89
+
90
+ class TestFilter extends ListRequestFilterDto {
91
+ field = 'id';
92
+ value: any = uuids;
93
+ operator = FilterOperatorEnum.IN;
94
+ }
95
+ const instance = new TestFilter();
96
+ expect(instance.value).toEqual(uuids);
97
+ expect(Array.isArray(instance.value)).toBe(true);
98
+ expect(instance.value).not.toBe(uuids.join(','));
99
+ });
100
+ });
101
+ });
@@ -0,0 +1,35 @@
1
+ import { getAllFieldMetadata } from '../../__mocks__/@nmxjs/validation';
2
+ import { paginationLimit } from '../../__mocks__/@nmxjs/constants';
3
+ import { ListRequestPaginationDto } from '../../src/dto/ListRequestPaginationDto';
4
+
5
+ describe('ListRequestPaginationDto', () => {
6
+ let instance: any;
7
+
8
+ beforeAll(() => {
9
+ instance = new (ListRequestPaginationDto as any)();
10
+ });
11
+
12
+ it('page should have type Number with default 1', () => {
13
+ const meta = getAllFieldMetadata('ListRequestPaginationDto');
14
+ expect(meta?.get('page')).toEqual({
15
+ type: Number,
16
+ default: 1,
17
+ });
18
+ });
19
+
20
+ it('limit should have type Number with default paginationLimit', () => {
21
+ const meta = getAllFieldMetadata('ListRequestPaginationDto');
22
+ expect(meta?.get('limit')).toEqual({
23
+ type: Number,
24
+ default: paginationLimit,
25
+ });
26
+ });
27
+
28
+ it('page defaults to 1', () => {
29
+ expect(instance.page).toBe(1);
30
+ });
31
+
32
+ it('limit defaults to paginationLimit', () => {
33
+ expect(instance.limit).toBe(paginationLimit);
34
+ });
35
+ });
@@ -0,0 +1,22 @@
1
+ import { getAllFieldMetadata } from '../../__mocks__/@nmxjs/validation';
2
+ import { SortOrderByEnum } from '../../src/interfaces';
3
+ import { ListRequestSortDto } from '../../src/dto/ListRequestSortDto';
4
+
5
+ describe('ListRequestSortDto', () => {
6
+ beforeAll(() => {
7
+ new (ListRequestSortDto as any)();
8
+ });
9
+
10
+ it('field should have type String', () => {
11
+ const meta = getAllFieldMetadata('ListRequestSortDto');
12
+ expect(meta?.get('field')).toEqual({ type: String });
13
+ });
14
+
15
+ it('type should be enum SortOrderByEnum', () => {
16
+ const meta = getAllFieldMetadata('ListRequestSortDto');
17
+ expect(meta?.get('type')).toEqual({
18
+ type: { SortOrderByEnum },
19
+ enum: true,
20
+ });
21
+ });
22
+ });
@@ -0,0 +1,26 @@
1
+ import { getAllFieldMetadata } from '../../__mocks__/@nmxjs/validation';
2
+ import { ListResponseCursorDto } from '../../src/dto/ListResponseCursorDto';
3
+
4
+ describe('ListResponseCursorDto', () => {
5
+ beforeAll(() => {
6
+ new (ListResponseCursorDto as any)();
7
+ });
8
+
9
+ it('totalCount should have type Number', () => {
10
+ const meta = getAllFieldMetadata('ListResponseCursorDto');
11
+ expect(meta?.get('totalCount')).toEqual({ type: Number });
12
+ });
13
+
14
+ it('totalPages should have type Number', () => {
15
+ const meta = getAllFieldMetadata('ListResponseCursorDto');
16
+ expect(meta?.get('totalPages')).toEqual({ type: Number });
17
+ });
18
+
19
+ it('nextPage should be nullable Number', () => {
20
+ const meta = getAllFieldMetadata('ListResponseCursorDto');
21
+ expect(meta?.get('nextPage')).toEqual({
22
+ type: Number,
23
+ nullable: true,
24
+ });
25
+ });
26
+ });
@@ -0,0 +1,24 @@
1
+ import { getAllFieldMetadata } from '../../__mocks__/@nmxjs/validation';
2
+ import { ListResponseDto } from '../../src/dto/ListResponseDto';
3
+ import { ListResponseCursorDto } from '../../src/dto/ListResponseCursorDto';
4
+
5
+ describe('ListResponseDto', () => {
6
+ beforeAll(() => {
7
+ new (ListResponseDto as any)();
8
+ });
9
+
10
+ it('cursor should have type ListResponseCursorDto', () => {
11
+ const meta = getAllFieldMetadata('ListResponseDto');
12
+ expect(meta?.get('cursor')).toEqual({
13
+ type: ListResponseCursorDto,
14
+ });
15
+ });
16
+
17
+ it('should support abstract field items', () => {
18
+ class TestListResponse extends ListResponseDto<{ id: string }> {
19
+ items = [{ id: '1' }];
20
+ }
21
+ const instance = new TestListResponse();
22
+ expect(instance.items).toEqual([{ id: '1' }]);
23
+ });
24
+ });
@@ -0,0 +1,43 @@
1
+ import { getAllFieldMetadata } from '../../__mocks__/@nmxjs/validation';
2
+ import { ProxyTypeEnum } from '../../src/interfaces';
3
+ import { ProxyDto } from '../../src/dto/ProxyDto';
4
+
5
+ describe('ProxyDto', () => {
6
+ beforeAll(() => {
7
+ new ProxyDto();
8
+ });
9
+
10
+ it('ip should have type String', () => {
11
+ const meta = getAllFieldMetadata('ProxyDto');
12
+ expect(meta?.get('ip')).toEqual({ type: String });
13
+ });
14
+
15
+ it('port should have type Number', () => {
16
+ const meta = getAllFieldMetadata('ProxyDto');
17
+ expect(meta?.get('port')).toEqual({ type: Number });
18
+ });
19
+
20
+ it('type should be enum ProxyTypeEnum', () => {
21
+ const meta = getAllFieldMetadata('ProxyDto');
22
+ expect(meta?.get('type')).toEqual({
23
+ type: { ProxyTypeEnum },
24
+ enum: true,
25
+ });
26
+ });
27
+
28
+ it('username should be nullable String', () => {
29
+ const meta = getAllFieldMetadata('ProxyDto');
30
+ expect(meta?.get('username')).toEqual({
31
+ type: String,
32
+ nullable: true,
33
+ });
34
+ });
35
+
36
+ it('password should be nullable String', () => {
37
+ const meta = getAllFieldMetadata('ProxyDto');
38
+ expect(meta?.get('password')).toEqual({
39
+ type: String,
40
+ nullable: true,
41
+ });
42
+ });
43
+ });
@@ -0,0 +1,21 @@
1
+ import { getAllFieldMetadata } from '../../__mocks__/@nmxjs/validation';
2
+ import { UpdateRequestDto } from '../../src/dto/UpdateRequestDto';
3
+
4
+ describe('UpdateRequestDto', () => {
5
+ beforeAll(() => {
6
+ new (UpdateRequestDto as any)();
7
+ });
8
+
9
+ it('id should have type String', () => {
10
+ const meta = getAllFieldMetadata('UpdateRequestDto');
11
+ expect(meta?.get('id')).toEqual({ type: String });
12
+ });
13
+
14
+ it('should support abstract field payload', () => {
15
+ class TestUpdate extends UpdateRequestDto<{ name: string }> {
16
+ payload = { name: 'test' };
17
+ }
18
+ const instance = new TestUpdate();
19
+ expect(instance.payload).toEqual({ name: 'test' });
20
+ });
21
+ });
@@ -0,0 +1,20 @@
1
+ import { EnvironmentEnum } from '../../src/interfaces/EnvironmentEnum';
2
+
3
+ describe('EnvironmentEnum', () => {
4
+ it('should contain DEVELOPMENT', () => {
5
+ expect(EnvironmentEnum.DEVELOPMENT).toBe('development');
6
+ });
7
+
8
+ it('should contain PRODUCTION', () => {
9
+ expect(EnvironmentEnum.PRODUCTION).toBe('production');
10
+ });
11
+
12
+ it('should contain TEST', () => {
13
+ expect(EnvironmentEnum.TEST).toBe('test');
14
+ });
15
+
16
+ it('should contain exactly 3 values', () => {
17
+ const values = Object.values(EnvironmentEnum);
18
+ expect(values).toHaveLength(3);
19
+ });
20
+ });
@@ -0,0 +1,36 @@
1
+ import { FilterOperatorEnum } from '../../src/interfaces/FilterOperatorEnum';
2
+
3
+ describe('FilterOperatorEnum', () => {
4
+ it('should contain EQ', () => {
5
+ expect(FilterOperatorEnum.EQ).toBe('EQ');
6
+ });
7
+
8
+ it('should contain IN', () => {
9
+ expect(FilterOperatorEnum.IN).toBe('IN');
10
+ });
11
+
12
+ it('should contain SEARCH', () => {
13
+ expect(FilterOperatorEnum.SEARCH).toBe('SEARCH');
14
+ });
15
+
16
+ it('should contain LESS', () => {
17
+ expect(FilterOperatorEnum.LESS).toBe('LESS');
18
+ });
19
+
20
+ it('should contain LESS_OR_EQ', () => {
21
+ expect(FilterOperatorEnum.LESS_OR_EQ).toBe('LESS_OR_EQ');
22
+ });
23
+
24
+ it('should contain MORE', () => {
25
+ expect(FilterOperatorEnum.MORE).toBe('MORE');
26
+ });
27
+
28
+ it('should contain MORE_OR_EQ', () => {
29
+ expect(FilterOperatorEnum.MORE_OR_EQ).toBe('MORE_OR_EQ');
30
+ });
31
+
32
+ it('should contain exactly 7 values', () => {
33
+ const values = Object.values(FilterOperatorEnum);
34
+ expect(values).toHaveLength(7);
35
+ });
36
+ });
@@ -0,0 +1,24 @@
1
+ import { ProxyTypeEnum } from '../../src/interfaces/ProxyTypeEnum';
2
+
3
+ describe('ProxyTypeEnum', () => {
4
+ it('should contain HTTP', () => {
5
+ expect(ProxyTypeEnum.HTTP).toBe('HTTP');
6
+ });
7
+
8
+ it('should contain HTTPS', () => {
9
+ expect(ProxyTypeEnum.HTTPS).toBe('HTTPS');
10
+ });
11
+
12
+ it('should contain SOCKS4', () => {
13
+ expect(ProxyTypeEnum.SOCKS4).toBe('SOCKS4');
14
+ });
15
+
16
+ it('should contain SOCKS5', () => {
17
+ expect(ProxyTypeEnum.SOCKS5).toBe('SOCKS5');
18
+ });
19
+
20
+ it('should contain exactly 4 values', () => {
21
+ const values = Object.values(ProxyTypeEnum);
22
+ expect(values).toHaveLength(4);
23
+ });
24
+ });
@@ -0,0 +1,16 @@
1
+ import { SortOrderByEnum } from '../../src/interfaces/SortOrderByEnum';
2
+
3
+ describe('SortOrderByEnum', () => {
4
+ it('should contain ASC', () => {
5
+ expect(SortOrderByEnum.ASC).toBe('ASC');
6
+ });
7
+
8
+ it('should contain DESC', () => {
9
+ expect(SortOrderByEnum.DESC).toBe('DESC');
10
+ });
11
+
12
+ it('should contain exactly 2 values', () => {
13
+ const values = Object.values(SortOrderByEnum);
14
+ expect(values).toHaveLength(2);
15
+ });
16
+ });
@@ -0,0 +1,20 @@
1
+ import { StartModeEnum } from '../../src/interfaces/StartModeEnum';
2
+
3
+ describe('StartModeEnum', () => {
4
+ it('should contain DEV', () => {
5
+ expect(StartModeEnum.DEV).toBe('DEV');
6
+ });
7
+
8
+ it('should contain NATIVE', () => {
9
+ expect(StartModeEnum.NATIVE).toBe('NATIVE');
10
+ });
11
+
12
+ it('should contain WATCH', () => {
13
+ expect(StartModeEnum.WATCH).toBe('WATCH');
14
+ });
15
+
16
+ it('should contain exactly 3 values', () => {
17
+ const values = Object.values(StartModeEnum);
18
+ expect(values).toHaveLength(3);
19
+ });
20
+ });