Skip to content

Commit 2caa2d8

Browse files
committed
fix(json-api-nestjs): Fix validate for patch method
Allow set empty attributes with relation Closes: #83
1 parent 5dbbd41 commit 2caa2d8

File tree

6 files changed

+98
-9
lines changed

6 files changed

+98
-9
lines changed

apps/json-api-server-e2e/src/json-api/json-api-sdk/patch-methode.spec.ts

+39
Original file line numberDiff line numberDiff line change
@@ -102,4 +102,43 @@ describe('PATCH method:', () => {
102102

103103
await jsonSdk.jonApiSdkService.deleteOne(newCommentsAfterSave);
104104
});
105+
106+
it('Should be update empty attributes with relations', async () => {
107+
const newAddress = new Addresses();
108+
newAddress.city = faker.location.city();
109+
newAddress.state = faker.location.state();
110+
newAddress.country = faker.location.country();
111+
112+
const newComments = new Comments();
113+
newComments.text = faker.string.alpha();
114+
newComments.kind = CommentKind.Comment;
115+
116+
const newAddressAfterSave = await jsonSdk.jonApiSdkService.postOne(
117+
newAddress
118+
);
119+
120+
const newCommentsAfterSave = await jsonSdk.jonApiSdkService.postOne(
121+
newComments
122+
);
123+
124+
userAfterSave.addresses = newAddressAfterSave;
125+
userAfterSave.comments = [newCommentsAfterSave];
126+
127+
const userWithEmptyAttr = new Users();
128+
userWithEmptyAttr.id = userAfterSave.id;
129+
userWithEmptyAttr.addresses = newAddressAfterSave;
130+
userWithEmptyAttr.comments = [newCommentsAfterSave];
131+
132+
await jsonSdk.jonApiSdkService.patchOne(userWithEmptyAttr);
133+
const userAfterUpdate = await jsonSdk.jonApiSdkService.getOne(
134+
Users,
135+
userWithEmptyAttr.id,
136+
{ include: ['addresses', 'comments'] }
137+
);
138+
expect(userAfterUpdate.addresses).toEqual(newAddressAfterSave);
139+
newCommentsAfterSave.updatedAt = userAfterUpdate.comments[0].updatedAt;
140+
expect(userAfterUpdate.comments[0]).toEqual(newCommentsAfterSave);
141+
142+
await jsonSdk.jonApiSdkService.deleteOne(newCommentsAfterSave);
143+
});
105144
});

libs/json-api/json-api-nestjs-sdk/src/lib/service/json-api-sdk.service.ts

-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import {
1111
QueryParamsForOneItem,
1212
RelationBodyData,
1313
ResourceObject,
14-
ResourceObjectRelationships,
1514
ReturnIfArray,
1615
} from '../types';
1716
import { EntityArray, getTypeForReq } from '../utils';

libs/json-api/json-api-nestjs-sdk/src/lib/types/index.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,9 @@ type MainData<E> = {
4545
export type PostData<E> = {
4646
data: MainData<E>;
4747
};
48-
4948
export type PatchData<E> = {
50-
data: { id: string } & MainData<E>;
49+
data: { id: string } & Omit<MainData<E>, 'attributes'> &
50+
Partial<Pick<MainData<E>, 'attributes'>>;
5151
};
5252
export type RelationData = { id: string; type: string };
5353
export type RelationBodyData = {

libs/json-api/json-api-nestjs/src/lib/helper/zod/zod-helper.spec.ts

+22-1
Original file line numberDiff line numberDiff line change
@@ -573,9 +573,24 @@ describe('zod-helper', () => {
573573
attributes,
574574
},
575575
};
576+
const check3 = {
577+
data: {
578+
id: '1',
579+
type: 'users',
580+
relationships,
581+
},
582+
};
576583

577584
expect(zodInputPatchSchemaTest.parse(check)).toEqual(check);
578585
expect(zodInputPatchSchemaTest.parse(check2)).toEqual(check2);
586+
expect(zodInputPatchSchemaTest.parse(check3)).toEqual({
587+
data: {
588+
id: '1',
589+
type: 'users',
590+
relationships,
591+
attributes: {},
592+
},
593+
});
579594
});
580595

581596
it('should be not ok', () => {
@@ -608,7 +623,13 @@ describe('zod-helper', () => {
608623
},
609624
},
610625
};
611-
const arrayCheck = [check1, check2, check3];
626+
const check4 = {
627+
data: {
628+
id: '1',
629+
type: 'users',
630+
},
631+
};
632+
const arrayCheck = [check1, check2, check3, check4];
612633
expect.assertions(arrayCheck.length);
613634
for (const item of arrayCheck) {
614635
try {

libs/json-api/json-api-nestjs/src/lib/helper/zod/zod-helper.ts

+27-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Repository } from 'typeorm';
2-
import { z, ZodObject } from 'zod';
2+
import { z, ZodObject, ZodUnion } from 'zod';
33
import { QueryField } from 'json-shared-type';
44

55
import {
@@ -45,6 +45,7 @@ import {
4545

4646
import {
4747
PatchShape,
48+
PatchShapeDefault,
4849
zodPatchRelationshipsSchema,
4950
} from './zod-input-patch-schema';
5051

@@ -93,7 +94,12 @@ export type PostData<E extends Entity> = z.infer<ZodInputPostSchema<E>>['data'];
9394

9495
export type ZodInputPatchSchema<E extends Entity> = ZodObject<
9596
{
96-
data: ZodObject<PatchShape<E>, 'strict'>;
97+
data: ZodUnion<
98+
[
99+
ZodObject<PatchShapeDefault<E>, 'strict'>,
100+
ZodObject<PatchShape<E>, 'strict'>
101+
]
102+
>;
97103
},
98104
'strict'
99105
>;
@@ -236,7 +242,8 @@ export const zodInputPatchSchema = <E extends Entity>(
236242
{} as FieldWithType<E>
237243
);
238244
const typeName = camelToKebab(getEntityName(repository.target));
239-
const postShape: PatchShape<E> = {
245+
246+
const patchShapeDefault: PatchShapeDefault<E> = {
240247
id: zodIdSchema(primaryType),
241248
type: zodTypeSchema(typeName),
242249
attributes: zodAttributesSchema(fieldWithType),
@@ -247,9 +254,25 @@ export const zodInputPatchSchema = <E extends Entity>(
247254
).optional(),
248255
};
249256

257+
const patchShape: PatchShape<E> = {
258+
id: zodIdSchema(primaryType),
259+
type: zodTypeSchema(typeName),
260+
attributes: zodAttributesSchema(fieldWithType)
261+
.optional()
262+
.default({} as any),
263+
relationships: zodPatchRelationshipsSchema(
264+
relationArrayProps,
265+
relationPopsName,
266+
primaryColumnType
267+
),
268+
};
269+
250270
return z
251271
.object({
252-
data: z.object(postShape).strict(),
272+
data: z.union([
273+
z.object(patchShapeDefault).strict(),
274+
z.object(patchShape).strict(),
275+
]),
253276
})
254277
.strict();
255278
};

libs/json-api/json-api-nestjs/src/lib/helper/zod/zod-input-patch-schema/index.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,20 @@ import { ZodAttributesSchema } from '../zod-input-post-schema/attributes';
33
import { ZodTypeSchema } from '../zod-input-post-schema/type';
44
import { ZodIdSchema } from '../zod-input-post-schema/id';
55

6-
import { ZodObject, ZodOptional } from 'zod';
6+
import { ZodDefault, ZodObject, ZodOptional } from 'zod';
77
import {
88
ZodPatchRelationshipsSchema,
99
zodPatchRelationshipsSchema,
1010
} from './relationships';
1111

1212
export type PatchShape<E extends Entity> = {
13+
id: ZodIdSchema;
14+
type: ZodTypeSchema<string>;
15+
attributes: ZodDefault<ZodOptional<ZodAttributesSchema<E>>>;
16+
relationships: ZodPatchRelationshipsSchema<E>;
17+
};
18+
19+
export type PatchShapeDefault<E extends Entity> = {
1320
id: ZodIdSchema;
1421
type: ZodTypeSchema<string>;
1522
attributes: ZodAttributesSchema<E>;

0 commit comments

Comments
 (0)