diff --git a/apps/json-api-server-e2e/src/json-api/json-api-sdk/patch-methode.spec.ts b/apps/json-api-server-e2e/src/json-api/json-api-sdk/patch-methode.spec.ts index b2bf2263..62deb265 100644 --- a/apps/json-api-server-e2e/src/json-api/json-api-sdk/patch-methode.spec.ts +++ b/apps/json-api-server-e2e/src/json-api/json-api-sdk/patch-methode.spec.ts @@ -102,4 +102,43 @@ describe('PATCH method:', () => { await jsonSdk.jonApiSdkService.deleteOne(newCommentsAfterSave); }); + + it('Should be update empty attributes with relations', async () => { + const newAddress = new Addresses(); + newAddress.city = faker.location.city(); + newAddress.state = faker.location.state(); + newAddress.country = faker.location.country(); + + const newComments = new Comments(); + newComments.text = faker.string.alpha(); + newComments.kind = CommentKind.Comment; + + const newAddressAfterSave = await jsonSdk.jonApiSdkService.postOne( + newAddress + ); + + const newCommentsAfterSave = await jsonSdk.jonApiSdkService.postOne( + newComments + ); + + userAfterSave.addresses = newAddressAfterSave; + userAfterSave.comments = [newCommentsAfterSave]; + + const userWithEmptyAttr = new Users(); + userWithEmptyAttr.id = userAfterSave.id; + userWithEmptyAttr.addresses = newAddressAfterSave; + userWithEmptyAttr.comments = [newCommentsAfterSave]; + + await jsonSdk.jonApiSdkService.patchOne(userWithEmptyAttr); + const userAfterUpdate = await jsonSdk.jonApiSdkService.getOne( + Users, + userWithEmptyAttr.id, + { include: ['addresses', 'comments'] } + ); + expect(userAfterUpdate.addresses).toEqual(newAddressAfterSave); + newCommentsAfterSave.updatedAt = userAfterUpdate.comments[0].updatedAt; + expect(userAfterUpdate.comments[0]).toEqual(newCommentsAfterSave); + + await jsonSdk.jonApiSdkService.deleteOne(newCommentsAfterSave); + }); }); diff --git a/libs/json-api/json-api-nestjs-sdk/src/lib/service/json-api-sdk.service.ts b/libs/json-api/json-api-nestjs-sdk/src/lib/service/json-api-sdk.service.ts index 7ceb9d7f..a1f4aca6 100644 --- a/libs/json-api/json-api-nestjs-sdk/src/lib/service/json-api-sdk.service.ts +++ b/libs/json-api/json-api-nestjs-sdk/src/lib/service/json-api-sdk.service.ts @@ -11,7 +11,6 @@ import { QueryParamsForOneItem, RelationBodyData, ResourceObject, - ResourceObjectRelationships, ReturnIfArray, } from '../types'; import { EntityArray, getTypeForReq } from '../utils'; @@ -172,7 +171,7 @@ export class JsonApiSdkService { data: { id: entity[this.jsonApiSdkConfig.idKey].toString(), type: getTypeForReq(entity.constructor.name), - attributes, + ...(Object.keys(attributes).length > 0 ? { attributes } : {}), ...(Object.keys(relationships).length > 0 ? { relationships } : {}), }, }; diff --git a/libs/json-api/json-api-nestjs-sdk/src/lib/types/index.ts b/libs/json-api/json-api-nestjs-sdk/src/lib/types/index.ts index 712d3d73..5269fa70 100644 --- a/libs/json-api/json-api-nestjs-sdk/src/lib/types/index.ts +++ b/libs/json-api/json-api-nestjs-sdk/src/lib/types/index.ts @@ -45,9 +45,9 @@ type MainData = { export type PostData = { data: MainData; }; - export type PatchData = { - data: { id: string } & MainData; + data: { id: string } & Omit, 'attributes'> & + Partial, 'attributes'>>; }; export type RelationData = { id: string; type: string }; export type RelationBodyData = { diff --git a/libs/json-api/json-api-nestjs/src/lib/helper/zod/zod-helper.spec.ts b/libs/json-api/json-api-nestjs/src/lib/helper/zod/zod-helper.spec.ts index 388ae761..c950c222 100644 --- a/libs/json-api/json-api-nestjs/src/lib/helper/zod/zod-helper.spec.ts +++ b/libs/json-api/json-api-nestjs/src/lib/helper/zod/zod-helper.spec.ts @@ -573,9 +573,24 @@ describe('zod-helper', () => { attributes, }, }; + const check3 = { + data: { + id: '1', + type: 'users', + relationships, + }, + }; expect(zodInputPatchSchemaTest.parse(check)).toEqual(check); expect(zodInputPatchSchemaTest.parse(check2)).toEqual(check2); + expect(zodInputPatchSchemaTest.parse(check3)).toEqual({ + data: { + id: '1', + type: 'users', + relationships, + attributes: {}, + }, + }); }); it('should be not ok', () => { @@ -608,7 +623,13 @@ describe('zod-helper', () => { }, }, }; - const arrayCheck = [check1, check2, check3]; + const check4 = { + data: { + id: '1', + type: 'users', + }, + }; + const arrayCheck = [check1, check2, check3, check4]; expect.assertions(arrayCheck.length); for (const item of arrayCheck) { try { diff --git a/libs/json-api/json-api-nestjs/src/lib/helper/zod/zod-helper.ts b/libs/json-api/json-api-nestjs/src/lib/helper/zod/zod-helper.ts index 8feb0c54..81f25c3f 100644 --- a/libs/json-api/json-api-nestjs/src/lib/helper/zod/zod-helper.ts +++ b/libs/json-api/json-api-nestjs/src/lib/helper/zod/zod-helper.ts @@ -1,5 +1,5 @@ import { Repository } from 'typeorm'; -import { z, ZodObject } from 'zod'; +import { z, ZodObject, ZodUnion } from 'zod'; import { QueryField } from 'json-shared-type'; import { @@ -45,6 +45,7 @@ import { import { PatchShape, + PatchShapeDefault, zodPatchRelationshipsSchema, } from './zod-input-patch-schema'; @@ -93,7 +94,12 @@ export type PostData = z.infer>['data']; export type ZodInputPatchSchema = ZodObject< { - data: ZodObject, 'strict'>; + data: ZodUnion< + [ + ZodObject, 'strict'>, + ZodObject, 'strict'> + ] + >; }, 'strict' >; @@ -236,7 +242,8 @@ export const zodInputPatchSchema = ( {} as FieldWithType ); const typeName = camelToKebab(getEntityName(repository.target)); - const postShape: PatchShape = { + + const patchShapeDefault: PatchShapeDefault = { id: zodIdSchema(primaryType), type: zodTypeSchema(typeName), attributes: zodAttributesSchema(fieldWithType), @@ -247,9 +254,25 @@ export const zodInputPatchSchema = ( ).optional(), }; + const patchShape: PatchShape = { + id: zodIdSchema(primaryType), + type: zodTypeSchema(typeName), + attributes: zodAttributesSchema(fieldWithType) + .optional() + .default({} as any), + relationships: zodPatchRelationshipsSchema( + relationArrayProps, + relationPopsName, + primaryColumnType + ), + }; + return z .object({ - data: z.object(postShape).strict(), + data: z.union([ + z.object(patchShapeDefault).strict(), + z.object(patchShape).strict(), + ]), }) .strict(); }; diff --git a/libs/json-api/json-api-nestjs/src/lib/helper/zod/zod-input-patch-schema/index.ts b/libs/json-api/json-api-nestjs/src/lib/helper/zod/zod-input-patch-schema/index.ts index e3c5af57..6ce1600b 100644 --- a/libs/json-api/json-api-nestjs/src/lib/helper/zod/zod-input-patch-schema/index.ts +++ b/libs/json-api/json-api-nestjs/src/lib/helper/zod/zod-input-patch-schema/index.ts @@ -3,13 +3,20 @@ import { ZodAttributesSchema } from '../zod-input-post-schema/attributes'; import { ZodTypeSchema } from '../zod-input-post-schema/type'; import { ZodIdSchema } from '../zod-input-post-schema/id'; -import { ZodObject, ZodOptional } from 'zod'; +import { ZodDefault, ZodObject, ZodOptional } from 'zod'; import { ZodPatchRelationshipsSchema, zodPatchRelationshipsSchema, } from './relationships'; export type PatchShape = { + id: ZodIdSchema; + type: ZodTypeSchema; + attributes: ZodDefault>>; + relationships: ZodPatchRelationshipsSchema; +}; + +export type PatchShapeDefault = { id: ZodIdSchema; type: ZodTypeSchema; attributes: ZodAttributesSchema;