Skip to content

Commit 1a1c859

Browse files
committed
feat(json-api-nestjs-shared): Use shared type from separate package
1 parent cd56636 commit 1a1c859

15 files changed

+492
-175
lines changed

libs/json-api/json-api-nestjs-shared/package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,5 @@
55
"tslib": "^2.3.0"
66
},
77
"type": "commonjs",
8-
"main": "./src/index.js",
9-
"typings": "./src/index.d.ts"
8+
"main": "./src/index.js"
109
}

libs/json-api/json-api-nestjs-shared/project.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,16 @@
2424
"assets": ["libs/json-api/json-api-nestjs-shared/*.md"]
2525
}
2626
},
27+
"ts-test": {
28+
"executor": "nx:run-commands",
29+
"options": {
30+
"commands": [
31+
"tsd --files \"src/**/*.test-d.ts\" -t src/lib/types/index.ts"
32+
],
33+
"cwd": "{workspaceRoot}/{projectRoot}",
34+
"parallel": false
35+
}
36+
},
2737
"nx-release-publish": {
2838
"options": {
2939
"packageRoot": "dist/{projectRoot}"
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import { expectType } from 'tsd';
2+
import { Any } from 'ts-toolbelt';
3+
4+
import { Users } from '../utils/___test___/test-classes.helper';
5+
6+
import { RelationKeys, PropertyKeys, IsIterator } from './entity-type';
7+
import { Collection } from '@mikro-orm/core';
8+
9+
type RelationId = 'addresses' | 'manager' | 'roles' | 'comments' | 'userGroup';
10+
type RelationName = 'roles';
11+
type PropertyId =
12+
| 'id'
13+
| 'login'
14+
| 'firstName'
15+
| 'testReal'
16+
| 'testArrayNull'
17+
| 'lastName'
18+
| 'isActive'
19+
| 'testDate'
20+
| 'createdAt'
21+
| 'updatedAt';
22+
type PropertyName =
23+
| 'id'
24+
| 'login'
25+
| 'firstName'
26+
| 'testReal'
27+
| 'testArrayNull'
28+
| 'lastName'
29+
| 'isActive'
30+
| 'testDate'
31+
| 'createdAt'
32+
| 'updatedAt'
33+
| 'addresses'
34+
| 'manager'
35+
| 'comments'
36+
| 'userGroup';
37+
38+
type IsEqualsRelationId = Any.Equals<RelationKeys<Users>, RelationId>;
39+
type IsEqualsRelationName = Any.Equals<
40+
RelationKeys<Users, 'name'>,
41+
RelationName
42+
>;
43+
type IsNoEqualsRelationName = Any.Equals<
44+
RelationKeys<Users, 'name'>,
45+
'comments'
46+
>;
47+
48+
type IsEqualsPropertyId = Any.Equals<PropertyKeys<Users>, PropertyId>;
49+
type IsEqualsPropertyName = Any.Equals<
50+
PropertyKeys<Users, 'name'>,
51+
PropertyName
52+
>;
53+
type IsNoEqualsPropertyName = Any.Equals<PropertyKeys<Users, 'name'>, 'roles'>;
54+
55+
expectType<IsEqualsRelationId>(1);
56+
expectType<IsEqualsRelationName>(1);
57+
expectType<IsNoEqualsRelationName>(0);
58+
59+
expectType<IsEqualsPropertyId>(1);
60+
expectType<IsEqualsPropertyName>(1);
61+
expectType<IsNoEqualsPropertyName>(0);
62+
63+
type ArrayUsers = Users[];
64+
type CollectionUsers = Collection<Users>;
65+
66+
expectType<IsIterator<ArrayUsers>>(1);
67+
expectType<IsIterator<CollectionUsers>>(1);
68+
expectType<IsIterator<Users>>(0);
Lines changed: 40 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,40 @@
1-
export type EntityField =
2-
| string
3-
| number
4-
| bigint
5-
| boolean
6-
| string[]
7-
| number[]
8-
| null
9-
| Date;
10-
11-
export type EntityProps<T> = {
12-
[P in keyof T]: T[P] extends EntityField ? P : never;
13-
}[keyof T];
14-
15-
export type EntityRelation<T> = {
16-
[P in keyof T]: T[P] extends EntityField ? never : P;
17-
}[keyof T];
1+
import { Any } from 'ts-toolbelt';
2+
3+
export type HasId<T, IdKey extends string> = Any.At<T, IdKey> extends undefined
4+
? 0
5+
: 1;
6+
7+
export type CastIteratorType<T> = T extends {
8+
[Symbol.iterator](): Iterator<infer U>;
9+
}
10+
? U
11+
: T;
12+
13+
type RelationCheck<T, IdKey extends string> = T extends never
14+
? 0
15+
: T extends Promise<infer U>
16+
? HasId<U, IdKey>
17+
: HasId<CastIteratorType<T>, IdKey>;
18+
19+
export type RelationKeys<E, IdKey extends string = 'id'> = {
20+
[K in keyof E]: Exclude<E[K], null> extends never
21+
? never
22+
: RelationCheck<Exclude<E[K], null>, IdKey> extends 1
23+
? K
24+
: never;
25+
}[keyof E];
26+
27+
export type PropertyKeys<E, IdKey extends string = 'id'> = keyof Omit<
28+
E,
29+
RelationKeys<E, IdKey>
30+
>;
31+
32+
export type IsIterator<T> = T extends {
33+
[Symbol.iterator](): Iterator<any>;
34+
}
35+
? 1
36+
: 0;
37+
38+
export type TypeOfArray<T> = T extends (infer U)[] ? U : T;
39+
40+
export type ValueOf<T> = T[keyof T];
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
export * from './utils-string.type';
21
export * from './query-type';
32
export * from './entity-type';
43
export * from './response-body';
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
import { expectAssignable } from 'tsd';
2+
3+
import {
4+
Attributes,
5+
ResourceObject,
6+
BaseMeta,
7+
Include,
8+
ResourceObjectRelationships,
9+
} from './response-body';
10+
import { Users } from '../utils/___test___/test-classes.helper';
11+
12+
const CheckBaseMeta = {
13+
meta: { time: 1 },
14+
} satisfies BaseMeta;
15+
16+
const CheckBaseMetaExtend = {
17+
meta: { time: 1, someData: '' },
18+
} satisfies BaseMeta<'object', { someData: string }>;
19+
20+
const CheckBaseMetaForArray = {
21+
meta: { time: 1, pageSize: 0, pageNumber: 0, totalItems: 0 },
22+
} satisfies BaseMeta<'array'>;
23+
24+
expectAssignable<BaseMeta>(CheckBaseMeta);
25+
expectAssignable<BaseMeta<'object', { someData: string }>>(CheckBaseMetaExtend);
26+
expectAssignable<BaseMeta<'array'>>(CheckBaseMetaForArray);
27+
28+
const CheckAttributes = {
29+
firstName: '',
30+
lastName: '',
31+
login: '',
32+
isActive: null,
33+
testDate: new Date(),
34+
testArrayNull: null,
35+
testReal: [1],
36+
createdAt: new Date(),
37+
updatedAt: new Date(),
38+
} satisfies Attributes<Users>;
39+
40+
expectAssignable<Attributes<Users>>(CheckAttributes);
41+
42+
const CheckInclude = {
43+
id: '1',
44+
type: 'users',
45+
attributes: CheckAttributes,
46+
relationships: {
47+
addresses: {
48+
links: {
49+
self: 'selflinks',
50+
},
51+
},
52+
manager: {
53+
links: {
54+
self: 'selflinks',
55+
},
56+
data: {
57+
type: 'users',
58+
id: 'dssd',
59+
},
60+
},
61+
comments: {
62+
links: {
63+
self: 'selfLinks',
64+
},
65+
data: [{ id: '1', type: 'comments' }],
66+
},
67+
roles: {
68+
links: {
69+
self: 'selfLinks',
70+
},
71+
data: [{ id: '1', type: 'roles' }],
72+
},
73+
userGroup: {
74+
links: { self: 'selfLinks' },
75+
data: null,
76+
},
77+
},
78+
links: { self: 'selfLinks' },
79+
} satisfies Include<Users, 'id'>;
80+
81+
expectAssignable<Include<Users, 'id'>>(CheckInclude);
82+
83+
const CheckResourceObject = {
84+
meta: CheckBaseMeta.meta,
85+
data: {
86+
id: '1',
87+
type: 'users',
88+
attributes: CheckAttributes,
89+
links: { self: 'selfLinks' },
90+
},
91+
} satisfies ResourceObject<Users>;
92+
93+
const CheckResourceObjectArray = {
94+
meta: CheckBaseMetaForArray.meta,
95+
data: [
96+
{
97+
id: '1',
98+
type: 'users',
99+
attributes: CheckAttributes,
100+
relationships: {
101+
addresses: {
102+
links: {
103+
self: 'selflinks',
104+
},
105+
},
106+
manager: {
107+
links: {
108+
self: 'selflinks',
109+
},
110+
data: {
111+
type: 'users',
112+
id: 'dssd',
113+
},
114+
},
115+
comments: {
116+
links: {
117+
self: 'selfLinks',
118+
},
119+
data: [{ id: '1', type: 'comments' }],
120+
},
121+
roles: {
122+
links: {
123+
self: 'selfLinks',
124+
},
125+
data: [{ id: '1', type: 'roles' }],
126+
},
127+
userGroup: {
128+
links: { self: 'selfLinks' },
129+
data: null,
130+
},
131+
},
132+
links: { self: 'selfLinks' },
133+
},
134+
],
135+
} satisfies ResourceObject<Users, 'array'>;
136+
137+
expectAssignable<ResourceObject<Users>>(CheckResourceObject);
138+
expectAssignable<ResourceObject<Users, 'array'>>(CheckResourceObjectArray);
139+
140+
const CheckResourceObjectRelationships = {
141+
meta: {
142+
time: 1,
143+
},
144+
data: {
145+
id: '1',
146+
type: 'users-groups',
147+
},
148+
} satisfies ResourceObjectRelationships<Users, 'id', 'userGroup'>;
149+
150+
const CheckResourceObjectRelationshipsArray = {
151+
meta: {
152+
time: 1,
153+
},
154+
data: [
155+
{
156+
id: '1',
157+
type: 'users-groups',
158+
},
159+
],
160+
} satisfies ResourceObjectRelationships<Users, 'id', 'roles'>;
161+
162+
expectAssignable<ResourceObjectRelationships<Users, 'id', 'userGroup'>>(
163+
CheckResourceObjectRelationships
164+
);
165+
expectAssignable<ResourceObjectRelationships<Users, 'id', 'roles'>>(
166+
CheckResourceObjectRelationshipsArray
167+
);

0 commit comments

Comments
 (0)