Skip to content

Commit 98f459c

Browse files
authored
Merge pull request #36 from Mites-G/unique-relations
Only return unique values in relationship object response
2 parents 02b0479 + 92be59d commit 98f459c

File tree

7 files changed

+177
-7
lines changed

7 files changed

+177
-7
lines changed

libs/json-api-nestjs/src/lib/mixin/service/transform/transform.mixin.ts

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -186,10 +186,21 @@ export class TransformMixinService<T> {
186186
const propsData = data[field];
187187
const typeName = getEntityName(this.relationTarget.get(field));
188188
if (Array.isArray(propsData)) {
189-
builtData.data = propsData.map((i) => ({
190-
type: camelToKebab(typeName),
191-
id: i[this.relationPrimaryField.get(field)].toString(),
192-
}));
189+
const tmp = propsData.reduce((acum, item) => {
190+
const key = `${camelToKebab(typeName)}:${item[
191+
this.relationPrimaryField.get(field)
192+
].toString()}`;
193+
194+
if (!acum.has(key)) {
195+
acum.set(key, {
196+
type: camelToKebab(typeName),
197+
id: item[this.relationPrimaryField.get(field)].toString(),
198+
});
199+
}
200+
201+
return acum;
202+
}, new Map());
203+
builtData.data = [...tmp.values()];
193204
}
194205

195206
if (!Array.isArray(data[field]) && typeof data[field] !== 'undefined') {

libs/json-api-nestjs/src/lib/mixin/service/typeorm/methods/get-one/get-one.spec.ts

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,14 @@ import { getDataSourceToken, getRepositoryToken } from '@nestjs/typeorm';
33
import { BadRequestException, NotFoundException } from '@nestjs/common';
44

55
import { TypeormMixinService } from '../../typeorm.mixin';
6-
import { mockDBTestModule, Users, Addresses } from '../../../../../mock-utils';
6+
import {
7+
mockDBTestModule,
8+
Users,
9+
Addresses,
10+
Notes,
11+
Comments,
12+
Roles,
13+
} from '../../../../../mock-utils';
714
import { ConfigParam, QueryField, QueryParams } from '../../../../../types';
815
import { DataSource, Repository } from 'typeorm';
916
import {
@@ -84,11 +91,42 @@ describe('GetOne methode test', () => {
8491
})
8592
);
8693

94+
await repository.manager.getRepository(Roles).save(
95+
Object.assign(new Roles(), {
96+
name: 'user',
97+
key: 'USER',
98+
isDefault: true,
99+
})
100+
);
101+
102+
const comments = await repository.manager.getRepository(Comments).save([
103+
Object.assign(new Comments(), {
104+
kind: 'COMMENT',
105+
text: 'text',
106+
}),
107+
Object.assign(new Comments(), {
108+
kind: 'COMMENT',
109+
text: 'text',
110+
}),
111+
Object.assign(new Comments(), {
112+
kind: 'COMMENT',
113+
text: 'text',
114+
}),
115+
]);
116+
117+
const notes = await repository.manager.getRepository(Notes).save([
118+
Object.assign(new Notes(), {
119+
text: 'text',
120+
}),
121+
]);
122+
87123
const user = {
88124
login: 'login',
89125
lastName: 'lastName',
90126
isActive: true,
91127
addresses: addresses,
128+
comments,
129+
notes,
92130
};
93131
await repository.save(Object.assign(new Users(), user));
94132
});
@@ -188,6 +226,17 @@ describe('GetOne methode test', () => {
188226
expect(selectSpy).toBeCalledWith([...defaultField['include'], aliasString]);
189227
});
190228

229+
it('included relationships should only return unique values', async () => {
230+
defaultField['include'] = ['comments', 'notes'];
231+
const res = await typeormService.getOne({
232+
query: defaultField,
233+
route: { id: params },
234+
});
235+
236+
expect(res.data['relationships'].comments.data.length).toBe(3);
237+
expect(res.data['relationships'].notes.data.length).toBe(1);
238+
});
239+
191240
it('Should be correct query with params', async () => {
192241
let joinSpy;
193242
let selectSpy;

libs/json-api-nestjs/src/lib/mock-utils/db-for-test

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,39 @@ CREATE SEQUENCE public.comments_id_seq
9898
ALTER SEQUENCE public.comments_id_seq OWNED BY public.comments.id;
9999

100100

101+
--
102+
-- Name: notes; Type: TABLE; Schema: public; Owner: -
103+
--
104+
105+
CREATE TABLE public.notes (
106+
id integer NOT NULL,
107+
text text NOT NULL,
108+
created_by integer,
109+
created_at timestamp without time zone DEFAULT CURRENT_TIMESTAMP,
110+
updated_at timestamp without time zone DEFAULT CURRENT_TIMESTAMP
111+
);
112+
113+
114+
--
115+
-- Name: notes_id_seq; Type: SEQUENCE; Schema: public; Owner: -
116+
--
117+
118+
CREATE SEQUENCE public.notes_id_seq
119+
AS integer
120+
START WITH 1
121+
INCREMENT BY 1
122+
NO MINVALUE
123+
NO MAXVALUE
124+
CACHE 1;
125+
126+
127+
--
128+
-- Name: notes_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
129+
--
130+
131+
ALTER SEQUENCE public.notes_id_seq OWNED BY public.notes.id;
132+
133+
101134
--
102135
-- Name: migrations; Type: TABLE; Schema: public; Owner: -
103136
--
@@ -388,6 +421,13 @@ ALTER TABLE ONLY public.addresses ALTER COLUMN id SET DEFAULT nextval('public.ad
388421
ALTER TABLE ONLY public.comments ALTER COLUMN id SET DEFAULT nextval('public.comments_id_seq'::regclass);
389422

390423

424+
--
425+
-- Name: notes id; Type: DEFAULT; Schema: public; Owner: -
426+
--
427+
428+
ALTER TABLE ONLY public.notes ALTER COLUMN id SET DEFAULT nextval('public.notes_id_seq'::regclass);
429+
430+
391431
--
392432
-- Name: migrations id; Type: DEFAULT; Schema: public; Owner: -
393433
--
@@ -468,6 +508,13 @@ ALTER TABLE ONLY public.comments
468508
ADD CONSTRAINT "PK_8bf68bc960f2b69e818bdb90dcb" PRIMARY KEY (id);
469509

470510

511+
--
512+
-- Name: notes PK_notes; Type: CONSTRAINT; Schema: public; Owner: -
513+
--
514+
515+
ALTER TABLE ONLY public.notes
516+
ADD CONSTRAINT "PK_notes" PRIMARY KEY (id);
517+
471518
--
472519
-- Name: migrations PK_8c82d7f526340ab734260ea46be; Type: CONSTRAINT; Schema: public; Owner: -
473520
--
@@ -584,6 +631,14 @@ ALTER TABLE ONLY public.comments
584631
ADD CONSTRAINT "FK_980bfefe00ed11685f325d0bd4c" FOREIGN KEY (created_by) REFERENCES public.users(id);
585632

586633

634+
--
635+
-- Name: notes FK_980bfefe00ed11685f325d0bd4c; Type: FK CONSTRAINT; Schema: public; Owner: -
636+
--
637+
638+
ALTER TABLE ONLY public.notes
639+
ADD CONSTRAINT "FK_notes" FOREIGN KEY (created_by) REFERENCES public.users(id);
640+
641+
587642
--
588643
-- Name: requests_have_pod_locks FK_c7531fe6bbb926bba3f69fcbb55; Type: FK CONSTRAINT; Schema: public; Owner: -
589644
--

libs/json-api-nestjs/src/lib/mock-utils/entities/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ export * from './pods';
66
export * from './comments';
77
export * from './addresses';
88
export * from './user-groups';
9+
export * from './notes';
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import {
2+
PrimaryGeneratedColumn,
3+
Column,
4+
Entity,
5+
JoinColumn,
6+
ManyToOne,
7+
UpdateDateColumn,
8+
} from 'typeorm';
9+
import { IsEmpty, IsNotEmpty } from 'class-validator';
10+
11+
import { Users, IUsers } from '.';
12+
13+
@Entity('notes')
14+
export class Notes {
15+
@PrimaryGeneratedColumn()
16+
public id: number;
17+
18+
@IsNotEmpty()
19+
@Column({
20+
type: 'text',
21+
nullable: false,
22+
})
23+
public text: string;
24+
25+
@IsEmpty()
26+
@Column({
27+
name: 'created_at',
28+
type: 'timestamp',
29+
nullable: true,
30+
default: 'CURRENT_TIMESTAMP',
31+
})
32+
public createdAt: Date;
33+
34+
@IsEmpty()
35+
@UpdateDateColumn({
36+
name: 'updated_at',
37+
type: 'timestamp',
38+
nullable: true,
39+
default: 'CURRENT_TIMESTAMP',
40+
})
41+
public updatedAt: Date;
42+
43+
@ManyToOne(() => Users, (item) => item.notes)
44+
@IsNotEmpty()
45+
@JoinColumn({
46+
name: 'created_by',
47+
})
48+
public createdBy: IUsers;
49+
}

libs/json-api-nestjs/src/lib/mock-utils/entities/users.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@ import {
2020

2121
import { Exclude } from 'class-transformer';
2222

23-
import { Addresses, Roles, Comments } from '.';
24-
import { UserGroups } from './user-groups';
23+
import { Addresses, Roles, Comments, Notes, UserGroups } from '.';
2524

2625
export type IUsers = Users;
2726

@@ -131,6 +130,9 @@ export class Users {
131130
@OneToMany(() => Comments, (item) => item.createdBy)
132131
public comments: Comments[];
133132

133+
@OneToMany(() => Notes, (item) => item.createdBy)
134+
public notes: Notes[];
135+
134136
@ManyToOne(() => UserGroups, (userGroup) => userGroup.id)
135137
@IsNotEmpty()
136138
@JoinColumn({ name: 'user_groups_id' })

libs/json-api-nestjs/src/lib/mock-utils/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
Comments,
1414
Addresses,
1515
UserGroups,
16+
Notes,
1617
} from './entities';
1718
import { DataSource } from 'typeorm';
1819

@@ -27,6 +28,7 @@ export const entities = [
2728
Pods,
2829
Comments,
2930
Addresses,
31+
Notes,
3032
];
3133

3234
const dump = readFileSync(join(__dirname, 'db-for-test'), { encoding: 'utf8' });
@@ -61,6 +63,7 @@ export function mockDBTestModule(): DynamicModule {
6163
Pods,
6264
Comments,
6365
Addresses,
66+
Notes,
6467
],
6568
};
6669
},

0 commit comments

Comments
 (0)